[{"data":1,"prerenderedAt":720},["ShallowReactive",2],{"cycle-doc-bob-wire-c21-technical-plan.md":3},{"cycle":4,"project":7,"path":10,"title":11,"toc":12,"ast":19},{"id":5,"title":6},"c21","Inventory + Users \u002F Devices",{"id":8,"label":9},"bob-wire","Bob-Wire","technical-plan.md","c21 Technical Plan — Inventory + Users \u002F Devices",[13,14,15,16,17,18],"Scope","Pages","Data","Conventions checklist","Execution phases","Product-side notes (not bob-wire work — for the humans)",{"type":20,"children":21},"root",[22,52,145,151,164,169,174,187,320,325,358,363,376,434,439,444,575,580,677,682,687],{"type":23,"tag":24,"props":25,"children":26},"element","p",{},[27,34,36,41,43,50],{"type":23,"tag":28,"props":29,"children":30},"strong",{},[31],{"type":32,"value":33},"text","Audience:",{"type":32,"value":35}," AI agents executing this cycle in bob-wire\n",{"type":23,"tag":28,"props":37,"children":38},{},[39],{"type":32,"value":40},"Source of truth for content:",{"type":32,"value":42}," ",{"type":23,"tag":44,"props":45,"children":47},"a",{"href":46},"\u002Fcycles\u002Fbob-wire\u002Fc21\u002Fdoc\u002Fdesign-brief",[48],{"type":32,"value":49},"design-brief.md",{"type":32,"value":51}," — settled decisions in §2 are constraints; open questions in §6 may be explored but must be annotated on the wireframe, not silently decided.",{"type":23,"tag":53,"props":54,"children":55},"blockquote",{},[56],{"type":23,"tag":24,"props":57,"children":58},{},[59,64,66,73,74,80,82,88,90,96,97,103,105,111,113,119,121,127,129,135,137,143],{"type":23,"tag":28,"props":60,"children":61},{},[62],{"type":32,"value":63},"Venue change (2026-09-01):",{"type":32,"value":65}," execution moved hi-fi-first into ",{"type":23,"tag":67,"props":68,"children":70},"code",{"className":69},[],[71],{"type":32,"value":72},"..\u002Fdesign",{"type":32,"value":42},{"type":23,"tag":67,"props":75,"children":77},{"className":76},[],[78],{"type":32,"value":79},"app\u002Fpages\u002Fpages\u002F",{"type":32,"value":81}," (Mark's call). Three pages — ",{"type":23,"tag":67,"props":83,"children":85},{"className":84},[],[86],{"type":32,"value":87},"inventory-companies-v1",{"type":32,"value":89},", ",{"type":23,"tag":67,"props":91,"children":93},{"className":92},[],[94],{"type":32,"value":95},"users-devices-v1",{"type":32,"value":89},{"type":23,"tag":67,"props":98,"children":100},{"className":99},[],[101],{"type":32,"value":102},"user-detail-v1",{"type":32,"value":104}," — on shared fixtures ",{"type":23,"tag":67,"props":106,"children":108},{"className":107},[],[109],{"type":32,"value":110},"..\u002Fdesign\u002Fapp\u002Fdata\u002Fc21-inventory-fixtures.ts",{"type":32,"value":112},", registered in design's ",{"type":23,"tag":67,"props":114,"children":116},{"className":115},[],[117],{"type":32,"value":118},"app\u002Fdata\u002Fpage-registry.ts",{"type":32,"value":120}," (groups ",{"type":23,"tag":67,"props":122,"children":124},{"className":123},[],[125],{"type":32,"value":126},"inventory",{"type":32,"value":128}," \u002F ",{"type":23,"tag":67,"props":130,"children":132},{"className":131},[],[133],{"type":32,"value":134},"teams",{"type":32,"value":136},"). The Fleet Overview page is dropped: design c78's ",{"type":23,"tag":67,"props":138,"children":140},{"className":139},[],[141],{"type":32,"value":142},"fleet-overview-v3",{"type":32,"value":144}," owns the landing thread; c21 widget ideas feed it. The bob-wire wf1 plan below stands as reference if a lo-fi pass is ever wanted, but is not the active path.",{"type":23,"tag":146,"props":147,"children":149},"h2",{"id":148},"scope",[150],{"type":32,"value":13},{"type":23,"tag":24,"props":152,"children":153},{},[154,156,162],{"type":32,"value":155},"wf1 wireframe iteration: a clickable prototype of the restructured qcontrol inventory area — Fleet Overview entry widgets, the Inventory page (technology view), the Users \u002F Devices page (people view), and one user-detail drill. Lo-fi, Wire* components, ",{"type":23,"tag":67,"props":157,"children":159},{"className":158},[],[160],{"type":32,"value":161},"layout: 'wireframe'",{"type":32,"value":163},".",{"type":23,"tag":24,"props":165,"children":166},{},[167],{"type":32,"value":168},"Out of scope for wf1: enforcement UI (account blocking is shown as visibility + an annotated \"next step\" affordance only), governance\u002Fcompliance pages, the gamified adoption checklist (parked idea — at most a placeholder widget slot on Fleet Overview), mockups (m1 comes after Thursday-call feedback).",{"type":23,"tag":146,"props":170,"children":172},{"id":171},"pages",[173],{"type":32,"value":14},{"type":23,"tag":24,"props":175,"children":176},{},[177,179,185],{"type":32,"value":178},"All under ",{"type":23,"tag":67,"props":180,"children":182},{"className":181},[],[183],{"type":32,"value":184},"app\u002Fpages\u002Fc21\u002Fwireframes\u002Fwf1\u002Finventory-v1\u002F",{"type":32,"value":186},":",{"type":23,"tag":188,"props":189,"children":190},"table",{},[191,215],{"type":23,"tag":192,"props":193,"children":194},"thead",{},[195],{"type":23,"tag":196,"props":197,"children":198},"tr",{},[199,205,210],{"type":23,"tag":200,"props":201,"children":202},"th",{},[203],{"type":32,"value":204},"Page",{"type":23,"tag":200,"props":206,"children":207},{},[208],{"type":32,"value":209},"File",{"type":23,"tag":200,"props":211,"children":212},{},[213],{"type":32,"value":214},"Content",{"type":23,"tag":216,"props":217,"children":218},"tbody",{},[219,242,269,291],{"type":23,"tag":196,"props":220,"children":221},{},[222,228,237],{"type":23,"tag":223,"props":224,"children":225},"td",{},[226],{"type":32,"value":227},"Fleet Overview",{"type":23,"tag":223,"props":229,"children":230},{},[231],{"type":23,"tag":67,"props":232,"children":234},{"className":233},[],[235],{"type":32,"value":236},"fleet-overview.vue",{"type":23,"tag":223,"props":238,"children":239},{},[240],{"type":32,"value":241},"Entry-story widgets: agent visibility (unique agents, monitored %), team deployment status (coverage % vs identity source of truth), token usage per model per period, accounts posture (enterprise vs personal count). Each widget click-navigates to its page.",{"type":23,"tag":196,"props":243,"children":244},{},[245,250,259],{"type":23,"tag":223,"props":246,"children":247},{},[248],{"type":32,"value":249},"Inventory",{"type":23,"tag":223,"props":251,"children":252},{},[253],{"type":23,"tag":67,"props":254,"children":256},{"className":255},[],[257],{"type":32,"value":258},"inventory.vue",{"type":23,"tag":223,"props":260,"children":261},{},[262,264],{"type":32,"value":263},"Company→technology→instance rollup (Anthropic → Claude Code\u002FClaude Desktop → instances), monitored vs detected-only, models directory w\u002F usage trends (tokens\u002F$ toggle), accounts & licensing panel (enterprise\u002Fpersonal\u002Funknown flagged), surface directories (MCP servers, tools, plugins, skills, repos, external services). User filter chip appears when arriving via drill-through. ",{"type":23,"tag":28,"props":265,"children":266},{},[267],{"type":32,"value":268},"No machines, no sessions, no per-user rows, no risk posturing.",{"type":23,"tag":196,"props":270,"children":271},{},[272,277,286],{"type":23,"tag":223,"props":273,"children":274},{},[275],{"type":32,"value":276},"Users \u002F Devices",{"type":23,"tag":223,"props":278,"children":279},{},[280],{"type":23,"tag":67,"props":281,"children":283},{"className":282},[],[284],{"type":32,"value":285},"users-devices.vue",{"type":23,"tag":223,"props":287,"children":288},{},[289],{"type":32,"value":290},"Coverage header: sensor deployment status vs definitive source of truth (identity\u002FMDM integration state shown, e.g. \"Okta connected · Jamf connected · 47 known workstations\"), actionable uncovered list (\"Alexis — no sensor — investigate\"). User\u002Fteam table: agents used, provider mix, account type (corporate\u002Fpersonal), tokens\u002F$ (toggle), intensity, one-line LLM summary. Rows drill to user detail. Agent-attribute filters mirror Inventory's user filter.",{"type":23,"tag":196,"props":292,"children":293},{},[294,299,308],{"type":23,"tag":223,"props":295,"children":296},{},[297],{"type":32,"value":298},"User Detail",{"type":23,"tag":223,"props":300,"children":301},{},[302],{"type":23,"tag":67,"props":303,"children":305},{"className":304},[],[306],{"type":32,"value":307},"user-detail.vue",{"type":23,"tag":223,"props":309,"children":310},{},[311,313,318],{"type":32,"value":312},"One user: devices → agents on each (relationship chain workstation ↔ identity ↔ agent kept visible), account usage incl. any personal accounts, usage trend, LLM-derived work summary + concrete tool-calling surface (MCP servers, repos), and ",{"type":23,"tag":28,"props":314,"children":315},{},[316],{"type":32,"value":317},"sessions list",{"type":32,"value":319}," (sessions live here, not in Inventory). Links back to Inventory pre-filtered (\"View in Inventory\").",{"type":23,"tag":24,"props":321,"children":322},{},[323],{"type":32,"value":324},"Cross-links to implement (the call's drill paths):",{"type":23,"tag":326,"props":327,"children":328},"ul",{},[329,343,348,353],{"type":23,"tag":330,"props":331,"children":332},"li",{},[333,335,341],{"type":32,"value":334},"Users \u002F Devices → user → click an agent (e.g. Claude) → Inventory with ",{"type":23,"tag":67,"props":336,"children":338},{"className":337},[],[339],{"type":32,"value":340},"?user=tyler&agent=claude",{"type":32,"value":342}," filter chips shown.",{"type":23,"tag":330,"props":344,"children":345},{},[346],{"type":32,"value":347},"Inventory → account panel \"used by 3 people\" → Users \u002F Devices filtered.",{"type":23,"tag":330,"props":349,"children":350},{},[351],{"type":32,"value":352},"Fleet Overview widgets → respective pages.",{"type":23,"tag":330,"props":354,"children":355},{},[356],{"type":32,"value":357},"Include an unknown\u002Funattributed identity row somewhere (brief §6, identity attribution edge case).",{"type":23,"tag":146,"props":359,"children":361},{"id":360},"data",[362],{"type":32,"value":15},{"type":23,"tag":24,"props":364,"children":365},{},[366,368,374],{"type":32,"value":367},"Shared sample-data module: ",{"type":23,"tag":67,"props":369,"children":371},{"className":370},[],[372],{"type":32,"value":373},"app\u002Fdata\u002Fc21-inventory.ts",{"type":32,"value":375},". Shapes:",{"type":23,"tag":326,"props":377,"children":378},{},[379,405,414,423],{"type":23,"tag":330,"props":380,"children":381},{},[382,388,390,396,397,403],{"type":23,"tag":67,"props":383,"children":385},{"className":384},[],[386],{"type":32,"value":387},"Company",{"type":32,"value":389}," → ",{"type":23,"tag":67,"props":391,"children":393},{"className":392},[],[394],{"type":32,"value":395},"technologies[]",{"type":32,"value":389},{"type":23,"tag":67,"props":398,"children":400},{"className":399},[],[401],{"type":32,"value":402},"instances[]",{"type":32,"value":404}," (instance: user, device, monitored: boolean, account ref)",{"type":23,"tag":330,"props":406,"children":407},{},[408],{"type":23,"tag":67,"props":409,"children":411},{"className":410},[],[412],{"type":32,"value":413},"Account { provider, accountId, licensing: 'enterprise' | 'personal' | 'unknown', users[] }",{"type":23,"tag":330,"props":415,"children":416},{},[417],{"type":23,"tag":67,"props":418,"children":420},{"className":419},[],[421],{"type":32,"value":422},"Person { name, team, devices[], sensorInstalled per device, source: 'okta' | 'manual', tokens, dollars, intensity, summary, surface: { mcpServers[], repos[] }, sessions[] }",{"type":23,"tag":330,"props":424,"children":425},{},[426,432],{"type":23,"tag":67,"props":427,"children":429},{"className":428},[],[430],{"type":32,"value":431},"UsageTrendPoint { period, model, tokens, dollars }",{"type":32,"value":433}," — enough periods to show the Anthropic→OpenAI→Grok drift story from the call",{"type":23,"tag":24,"props":435,"children":436},{},[437],{"type":32,"value":438},"Realistic names\u002Fnumbers; include at least: one unmonitored-but-detected agent (Hermes — the call's example of a surprise), one personal ChatGPT account on a named user, several people with no sensor installed, one unattributed agent instance.",{"type":23,"tag":146,"props":440,"children":442},{"id":441},"conventions-checklist",[443],{"type":32,"value":16},{"type":23,"tag":445,"props":446,"children":447},"ol",{},[448,477,488,523,543,563],{"type":23,"tag":330,"props":449,"children":450},{},[451,453,459,461,467,469,475],{"type":32,"value":452},"Wire* components only; grey borders, dashed placeholders, no shadows; ",{"type":23,"tag":67,"props":454,"children":456},{"className":455},[],[457],{"type":32,"value":458},".wire-*",{"type":32,"value":460}," classes ok. ",{"type":23,"tag":67,"props":462,"children":464},{"className":463},[],[465],{"type":32,"value":466},"WireViewToggle",{"type":32,"value":468}," for tokens\u002F$ and monitored\u002Fall toggles; ",{"type":23,"tag":67,"props":470,"children":472},{"className":471},[],[473],{"type":32,"value":474},"wire-annotation",{"type":32,"value":476}," for open-question callouts.",{"type":23,"tag":330,"props":478,"children":479},{},[480,486],{"type":23,"tag":67,"props":481,"children":483},{"className":482},[],[484],{"type":32,"value":485},"definePageMeta({ layout: 'wireframe' })",{"type":32,"value":487}," on every page.",{"type":23,"tag":330,"props":489,"children":490},{},[491,493,499,501,507,508,514,516,522],{"type":32,"value":492},"Register all four pages in ",{"type":23,"tag":67,"props":494,"children":496},{"className":495},[],[497],{"type":32,"value":498},"app\u002Fdata\u002Fwireframe-registry.ts",{"type":32,"value":500},": ",{"type":23,"tag":67,"props":502,"children":504},{"className":503},[],[505],{"type":32,"value":506},"type: 'wireframe'",{"type":32,"value":89},{"type":23,"tag":67,"props":509,"children":511},{"className":510},[],[512],{"type":32,"value":513},"iteration: 'wf1'",{"type":32,"value":515},", feature ",{"type":23,"tag":67,"props":517,"children":519},{"className":518},[],[520],{"type":32,"value":521},"inventory-v1",{"type":32,"value":163},{"type":23,"tag":330,"props":524,"children":525},{},[526,528,534,536,542],{"type":32,"value":527},"Create ",{"type":23,"tag":67,"props":529,"children":531},{"className":530},[],[532],{"type":32,"value":533},"app\u002Fpages\u002Fc21\u002Findex.vue",{"type":32,"value":535}," cycle gallery (copy c16\u002Fc20 pattern) and add c21 to the root TOC in ",{"type":23,"tag":67,"props":537,"children":539},{"className":538},[],[540],{"type":32,"value":541},"app\u002Fpages\u002Findex.vue",{"type":32,"value":163},{"type":23,"tag":330,"props":544,"children":545},{},[546,548,553,555,561],{"type":32,"value":547},"Copy ",{"type":23,"tag":67,"props":549,"children":551},{"className":550},[],[552],{"type":32,"value":49},{"type":32,"value":554}," into the feature dir for ",{"type":23,"tag":67,"props":556,"children":558},{"className":557},[],[559],{"type":32,"value":560},"\u002Fapi\u002Fspecs\u002F",{"type":32,"value":562}," colocation (per brief-colocation convention).",{"type":23,"tag":330,"props":564,"children":565},{},[566,568,573],{"type":32,"value":567},"Annotate, don't decide: where the brief lists open questions (agent vs harness label, page name, fleet definition), pick a working label and mark it with a ",{"type":23,"tag":67,"props":569,"children":571},{"className":570},[],[572],{"type":32,"value":474},{"type":32,"value":574}," (e.g. \"label TBD: agents vs harnesses\").",{"type":23,"tag":146,"props":576,"children":578},{"id":577},"execution-phases",[579],{"type":32,"value":17},{"type":23,"tag":326,"props":581,"children":582},{},[583,593,617,634,651],{"type":23,"tag":330,"props":584,"children":585},{},[586,591],{"type":23,"tag":28,"props":587,"children":588},{},[589],{"type":32,"value":590},"Phase 0 (done):",{"type":32,"value":592}," cycle records, design brief, this plan.",{"type":23,"tag":330,"props":594,"children":595},{},[596,601,602,608,610,615],{"type":23,"tag":28,"props":597,"children":598},{},[599],{"type":32,"value":600},"Phase 1 — wf1 build:",{"type":32,"value":42},{"type":23,"tag":67,"props":603,"children":605},{"className":604},[],[606],{"type":32,"value":607},"\u002Fwireframe",{"type":32,"value":609}," (wireframe-builder) against ",{"type":23,"tag":67,"props":611,"children":613},{"className":612},[],[614],{"type":32,"value":49},{"type":32,"value":616},", four pages above. Builders write .vue files; batch registry entries after parallel runs complete (established parallel-run convention).",{"type":23,"tag":330,"props":618,"children":619},{},[620,625,626,632],{"type":23,"tag":28,"props":621,"children":622},{},[623],{"type":32,"value":624},"Phase 2 — flow:",{"type":32,"value":42},{"type":23,"tag":67,"props":627,"children":629},{"className":628},[],[630],{"type":32,"value":631},"\u002Fflow",{"type":32,"value":633}," to wire the drill paths and filter-chip navigation.",{"type":23,"tag":330,"props":635,"children":636},{},[637,642,643,649],{"type":23,"tag":28,"props":638,"children":639},{},[640],{"type":32,"value":641},"Phase 3 — review:",{"type":32,"value":42},{"type":23,"tag":67,"props":644,"children":646},{"className":645},[],[647],{"type":32,"value":648},"\u002Freview inventory-v1",{"type":32,"value":650}," against the brief; fix conformance gaps.",{"type":23,"tag":330,"props":652,"children":653},{},[654,659,661,667,669,675],{"type":23,"tag":28,"props":655,"children":656},{},[657],{"type":32,"value":658},"Phase 4 — feedback loop:",{"type":32,"value":660}," present at the Thursday follow-up (Mark Peterson product-spec session); capture deltas as an update brief via ",{"type":23,"tag":67,"props":662,"children":664},{"className":663},[],[665],{"type":32,"value":666},"\u002Fwrite-brief",{"type":32,"value":668},", then ",{"type":23,"tag":67,"props":670,"children":672},{"className":671},[],[673],{"type":32,"value":674},"\u002Fiterate",{"type":32,"value":676}," → wf2, or promote to m1 mockups if structure holds.",{"type":23,"tag":146,"props":678,"children":680},{"id":679},"product-side-notes-not-bob-wire-work-for-the-humans",[681],{"type":32,"value":18},{"type":23,"tag":24,"props":683,"children":684},{},[685],{"type":32,"value":686},"Captured from the call so they aren't lost; none block the wireframes:",{"type":23,"tag":326,"props":688,"children":689},{},[690,695,700,705,710,715],{"type":23,"tag":330,"props":691,"children":692},{},[693],{"type":32,"value":694},"Windows installer\u002Ftapping (Kamal) blocks Mark Peterson self-testing; macOS-only today.",{"type":23,"tag":330,"props":696,"children":697},{},[698],{"type":32,"value":699},"Centralize the control plane (Docker + Postgres) vs current local-only mode; wireframes assume centralized mode, with local mode noted in brief §2.10.",{"type":23,"tag":330,"props":701,"children":702},{},[703],{"type":32,"value":704},"OpenFlow's provider mapping should be corrected to OpenAI in the real data.",{"type":23,"tag":330,"props":706,"children":707},{},[708],{"type":32,"value":709},"Identity attachment is \"one of the simplest things we do\" per Tyler once an identity integration exists — wireframes can assume identity data is available when integration is connected.",{"type":23,"tag":330,"props":711,"children":712},{},[713],{"type":32,"value":714},"Data model already holds provider; confirm it represents the company→technology→instance hierarchy the UI now needs.",{"type":23,"tag":330,"props":716,"children":717},{},[718],{"type":32,"value":719},"Summarizer model required for per-user work summaries (customer supplies an LLM endpoint).",1794599409002]