[{"data":1,"prerenderedAt":833},["ShallowReactive",2],{"$f3fIjTcpMoimQf6C9GGhxf7Vp30qKWzpEgsf-Vm19Ua0":3},{"newThing":4,"project":5,"cycle":9,"sections":25,"threads":811,"otherDocs":812,"documents":814,"images":816,"archiveItems":830,"links":831},"DataMachine — the base-component + curated-preset pattern qmap arrived at, now a named layer idea",{"id":6,"label":7,"liveBase":8},"design","Design",null,{"id":10,"num":11,"dir":12,"name":13,"title":14,"focus":15,"status":16,"statusNote":8,"created":17,"completed":8,"mode":18,"report":8,"recordless":19,"thumbnail":20,"imageCount":21,"artifactCount":22,"lastActivity":23,"hasPickup":19,"hasInitialPrompt":24},"c91",91,"c91.data-machine","data-machine","DataMachine","Build the `DataMachine` composition component and document the base-component + curated-preset pattern it embodies","archived","2026-09-17","assemblage — every piece is composed from existing primitives (`DataMetricValue`, `DataMetricTrend`, `DataMetricSpark`, `DataDonutChart`); the work is composition, not invention",false,"\u002Fcycles\u002Fdesign\u002Fc91-data-machine.png",2,1,"2026-09-18",true,[26,101,134,327,780],{"key":27,"title":28,"empty":19,"ast":29},"why","Why",{"type":30,"children":31},"root",[32,96],{"type":33,"tag":34,"props":35,"children":36},"element","p",{},[37,40,46,48,55,57,63,65,71,73,79,81,87,88,94],{"type":38,"value":39},"text","Looking at the emerging DataMachine design (split out of c90's qcontrol page-chrome work), the same shape qmap and qflow arrived at independently became visible: a base component made maximally expressive — many props, deep visual range — specifically so the ",{"type":33,"tag":41,"props":42,"children":43},"em",{},[44],{"type":38,"value":45},"library maintainers",{"type":38,"value":47},", not end consumers, can curate a handful of copyable, pre-configured examples for real use cases. qmap's realization is explicit and documented: ",{"type":33,"tag":49,"props":50,"children":52},"code",{"className":51},[],[53],{"type":38,"value":54},"QMap",{"type":38,"value":56}," (42 props) + preset wrapper components ",{"type":33,"tag":49,"props":58,"children":60},{"className":59},[],[61],{"type":38,"value":62},"QMapDataflow",{"type":38,"value":64},"\u002F",{"type":33,"tag":49,"props":66,"children":68},{"className":67},[],[69],{"type":38,"value":70},"QMapPolicyViolation",{"type":38,"value":72},", with the workflow spelled out in qmap's own CLAUDE.md glossary (\"Config Lab → tune → export → paste into a wrapper\"). qflow hasn't grown this yet — ",{"type":33,"tag":49,"props":74,"children":76},{"className":75},[],[77],{"type":38,"value":78},"TrafficViz",{"type":38,"value":80}," is still simple (5 props) — but the same instinct is visible in its ",{"type":33,"tag":49,"props":82,"children":84},{"className":83},[],[85],{"type":38,"value":86},"clientConfig",{"type":38,"value":64},{"type":33,"tag":49,"props":89,"children":91},{"className":90},[],[92],{"type":38,"value":93},"mode",{"type":38,"value":95}," props.",{"type":33,"tag":34,"props":97,"children":98},{},[99],{"type":38,"value":100},"This is a scope departure from c90 (qcontrol page-chrome assembly), so it becomes its own cycle rather than a thread inside c90.",{"key":102,"title":103,"empty":19,"ast":104},"objective","Objective",{"type":30,"children":105},[106],{"type":33,"tag":34,"props":107,"children":108},{},[109,111,116,118,124,126,132],{"type":38,"value":110},"Ship ",{"type":33,"tag":49,"props":112,"children":114},{"className":113},[],[115],{"type":38,"value":14},{"type":38,"value":117}," as a new q-nuxt-layer composition component, document it on the design site with the two reference mockups as copyable presets, and write the base+preset pattern into ",{"type":33,"tag":49,"props":119,"children":121},{"className":120},[],[122],{"type":38,"value":123},"component_philosophy.md",{"type":38,"value":125}," and ",{"type":33,"tag":49,"props":127,"children":129},{"className":128},[],[130],{"type":38,"value":131},"design_methodology.md",{"type":38,"value":133}," as a named, reusable idea.",{"key":135,"title":136,"empty":19,"ast":137},"scope","Scope",{"type":30,"children":138},[139,279,296],{"type":33,"tag":140,"props":141,"children":142},"ol",{},[143,237,255],{"type":33,"tag":144,"props":145,"children":146},"li",{},[147,157,159,165,167,173,175,181,183,189,191,197,199,205,206,212,214,220,221,227,229,235],{"type":33,"tag":148,"props":149,"children":150},"strong",{},[151],{"type":33,"tag":49,"props":152,"children":154},{"className":153},[],[155],{"type":38,"value":156},"q-nuxt-layer\u002Fcomponents\u002Fdata\u002Fmachine\u002Findex.vue",{"type":38,"value":158}," — new composition component. Composes ",{"type":33,"tag":49,"props":160,"children":162},{"className":161},[],[163],{"type":38,"value":164},"DataMetricValue",{"type":38,"value":166},", ",{"type":33,"tag":49,"props":168,"children":170},{"className":169},[],[171],{"type":38,"value":172},"DataMetricTrend",{"type":38,"value":174},", and ",{"type":33,"tag":49,"props":176,"children":178},{"className":177},[],[179],{"type":38,"value":180},"DataMetricSpark",{"type":38,"value":182}," as-is; adds new inline markup (title, full-width hairline, description, provenance row) that has no reuse case outside DataMachine, so it stays flat (",{"type":33,"tag":49,"props":184,"children":186},{"className":185},[],[187],{"type":38,"value":188},"index.vue",{"type":38,"value":190}," + no sub-files) rather than following the ",{"type":33,"tag":49,"props":192,"children":194},{"className":193},[],[195],{"type":38,"value":196},"_\u002F",{"type":38,"value":198}," primitive-vs-layout split used by ",{"type":33,"tag":49,"props":200,"children":202},{"className":201},[],[203],{"type":38,"value":204},"components\u002Fdata\u002Fmetric\u002F",{"type":38,"value":125},{"type":33,"tag":49,"props":207,"children":209},{"className":208},[],[210],{"type":38,"value":211},"components\u002Fdata\u002Fhistory-graph\u002F",{"type":38,"value":213},". ",{"type":33,"tag":49,"props":215,"children":217},{"className":216},[],[218],{"type":38,"value":219},"#left",{"type":38,"value":64},{"type":33,"tag":49,"props":222,"children":224},{"className":223},[],[225],{"type":38,"value":226},"#right",{"type":38,"value":228}," slots for consumer-composed content (icon grids, ",{"type":33,"tag":49,"props":230,"children":232},{"className":231},[],[233],{"type":38,"value":234},"DataDonutChart",{"type":38,"value":236},") — no new primitives built for these.",{"type":33,"tag":144,"props":238,"children":239},{},[240,245,247,253],{"type":33,"tag":148,"props":241,"children":242},{},[243],{"type":38,"value":244},"Design-site documentation",{"type":38,"value":246}," — registry entry (new group, since DataMachine composes data-metric primitives rather than being one), ",{"type":33,"tag":49,"props":248,"children":250},{"className":249},[],[251],{"type":38,"value":252},"_demos\u002FDataMachine.vue",{"type":38,"value":254}," with the two reference mockups (\"User Coverage\", \"Devices Sensored\") as primary copyable presets plus empty\u002Fminimal\u002Ftypical\u002Foverflow\u002Ferror scenario coverage, visual index placement.",{"type":33,"tag":144,"props":256,"children":257},{},[258,263,265,270,272,277],{"type":33,"tag":148,"props":259,"children":260},{},[261],{"type":38,"value":262},"Philosophy docs",{"type":38,"value":264}," — extend Principle 4 (Progressive enhancement) and its Design Lineage paragraph in ",{"type":33,"tag":49,"props":266,"children":268},{"className":267},[],[269],{"type":38,"value":123},{"type":38,"value":271},"; extend \"Decomposition and Modularity\" in ",{"type":33,"tag":49,"props":273,"children":275},{"className":274},[],[276],{"type":38,"value":131},{"type":38,"value":278},". Both cite qmap → DataMachine as the cross-project instance of the pattern.",{"type":33,"tag":34,"props":280,"children":281},{},[282,287,289,294],{"type":33,"tag":148,"props":283,"children":284},{},[285],{"type":38,"value":286},"Preset scope:",{"type":38,"value":288}," design-site demo presets only for now, not named layer-level wrapper components like ",{"type":33,"tag":49,"props":290,"children":292},{"className":291},[],[293],{"type":38,"value":62},{"type":38,"value":295},". The two reference images become copyable example configs in DataMachine's own demo file — proving the pattern without committing to named wrapper components before real qcontrol usage validates which configs are worth freezing.",{"type":33,"tag":34,"props":297,"children":298},{},[299,304,306,311,313,318,320,325],{"type":33,"tag":148,"props":300,"children":301},{},[302],{"type":38,"value":303},"Explicitly out of scope:",{"type":38,"value":305}," refactoring the existing ",{"type":33,"tag":49,"props":307,"children":309},{"className":308},[],[310],{"type":38,"value":196},{"type":38,"value":312}," convention in ",{"type":33,"tag":49,"props":314,"children":316},{"className":315},[],[317],{"type":38,"value":204},{"type":38,"value":319}," or ",{"type":33,"tag":49,"props":321,"children":323},{"className":322},[],[324],{"type":38,"value":211},{"type":38,"value":326}," — those families have primitives genuinely reused outside their own layouts and keep their existing structure.",{"key":328,"title":329,"empty":19,"ast":330},"key-changes","Key Changes",{"type":30,"children":331},[332],{"type":33,"tag":333,"props":334,"children":335},"ul",{},[336,435,495,544,577,594,689,734],{"type":33,"tag":144,"props":337,"children":338},{},[339,343,345,350,352,357,359,364,365,370,371,376,378,383,384,389,391,396,398,404,406,412,413,419,420,426,427,433],{"type":33,"tag":148,"props":340,"children":341},{},[342],{"type":38,"value":17},{"type":38,"value":344}," — Built ",{"type":33,"tag":49,"props":346,"children":348},{"className":347},[],[349],{"type":38,"value":156},{"type":38,"value":351}," (",{"type":33,"tag":49,"props":353,"children":355},{"className":354},[],[356],{"type":38,"value":14},{"type":38,"value":358},"): title, full-width hairline, optional description, and provenance row wrapped around ",{"type":33,"tag":49,"props":360,"children":362},{"className":361},[],[363],{"type":38,"value":164},{"type":38,"value":64},{"type":33,"tag":49,"props":366,"children":368},{"className":367},[],[369],{"type":38,"value":172},{"type":38,"value":64},{"type":33,"tag":49,"props":372,"children":374},{"className":373},[],[375],{"type":38,"value":180},{"type":38,"value":377},", with ",{"type":33,"tag":49,"props":379,"children":381},{"className":380},[],[382],{"type":38,"value":219},{"type":38,"value":64},{"type":33,"tag":49,"props":385,"children":387},{"className":386},[],[388],{"type":38,"value":226},{"type":38,"value":390}," slots for consumer-composed content. No changes needed to the reused primitives — ",{"type":33,"tag":49,"props":392,"children":394},{"className":393},[],[395],{"type":38,"value":164},{"type":38,"value":397},"'s existing ",{"type":33,"tag":49,"props":399,"children":401},{"className":400},[],[402],{"type":38,"value":403},"unit",{"type":38,"value":405}," handling already covers ",{"type":33,"tag":49,"props":407,"children":409},{"className":408},[],[410],{"type":38,"value":411},"bytes",{"type":38,"value":64},{"type":33,"tag":49,"props":414,"children":416},{"className":415},[],[417],{"type":38,"value":418},"duration",{"type":38,"value":64},{"type":33,"tag":49,"props":421,"children":423},{"className":422},[],[424],{"type":38,"value":425},"ms",{"type":38,"value":64},{"type":33,"tag":49,"props":428,"children":430},{"className":429},[],[431],{"type":38,"value":432},"%",{"type":38,"value":434},"\u002Fcustom passthrough cleanly.",{"type":33,"tag":144,"props":436,"children":437},{},[438,442,444,449,451,456,458,463,465,471,473,479,481,486,488,493],{"type":33,"tag":148,"props":439,"children":440},{},[441],{"type":38,"value":17},{"type":38,"value":443}," — Documented on the design site: new ",{"type":33,"tag":49,"props":445,"children":447},{"className":446},[],[448],{"type":38,"value":13},{"type":38,"value":450}," registry group + ",{"type":33,"tag":49,"props":452,"children":454},{"className":453},[],[455],{"type":38,"value":14},{"type":38,"value":457}," entry, ",{"type":33,"tag":49,"props":459,"children":461},{"className":460},[],[462],{"type":38,"value":252},{"type":38,"value":464}," with the two reference presets (\"User Coverage\", \"Devices Sensored\") plus empty\u002Fminimal\u002Ftypical\u002Foverflow\u002Ferror scenarios and a unit-passthrough spot-check, visual-index placement on ",{"type":33,"tag":49,"props":466,"children":468},{"className":467},[],[469],{"type":38,"value":470},"\u002Fcomponents",{"type":38,"value":472},". Also fixed a stale leftover from the c28 data-metric rename: the ",{"type":33,"tag":49,"props":474,"children":476},{"className":475},[],[477],{"type":38,"value":478},"data-metric",{"type":38,"value":480}," group's registry label and ",{"type":33,"tag":49,"props":482,"children":484},{"className":483},[],[485],{"type":38,"value":470},{"type":38,"value":487}," section header both still read \"Data Machine\" — renamed to \"Data Metric\" so the new real ",{"type":33,"tag":49,"props":489,"children":491},{"className":490},[],[492],{"type":38,"value":14},{"type":38,"value":494}," component doesn't collide with it.",{"type":33,"tag":144,"props":496,"children":497},{},[498,502,504,509,511,516,518,523,524,529,530,535,537,542],{"type":33,"tag":148,"props":499,"children":500},{},[501],{"type":38,"value":17},{"type":38,"value":503}," — Wrote the base + curated-presets pattern into ",{"type":33,"tag":49,"props":505,"children":507},{"className":506},[],[508],{"type":38,"value":123},{"type":38,"value":510}," (Principle 4 + Design Lineage) and ",{"type":33,"tag":49,"props":512,"children":514},{"className":513},[],[515],{"type":38,"value":131},{"type":38,"value":517}," (Decomposition and Modularity), citing qmap's ",{"type":33,"tag":49,"props":519,"children":521},{"className":520},[],[522],{"type":38,"value":54},{"type":38,"value":64},{"type":33,"tag":49,"props":525,"children":527},{"className":526},[],[528],{"type":38,"value":62},{"type":38,"value":64},{"type":33,"tag":49,"props":531,"children":533},{"className":532},[],[534],{"type":38,"value":70},{"type":38,"value":536}," as the precedent and ",{"type":33,"tag":49,"props":538,"children":540},{"className":539},[],[541],{"type":38,"value":14},{"type":38,"value":543}," as the new cross-project instance.",{"type":33,"tag":144,"props":545,"children":546},{},[547,551,553,559,561,567,569,575],{"type":33,"tag":148,"props":548,"children":549},{},[550],{"type":38,"value":17},{"type":38,"value":552}," — Swapped the demo's hand-rolled, too-smooth sparkline arrays for the existing ",{"type":33,"tag":49,"props":554,"children":556},{"className":555},[],[557],{"type":38,"value":558},"app\u002Fdata\u002Fsparklines.ts",{"type":38,"value":560}," fixtures (",{"type":33,"tag":49,"props":562,"children":564},{"className":563},[],[565],{"type":38,"value":566},"sparkNoise",{"type":38,"value":568}," for generic examples, ",{"type":33,"tag":49,"props":570,"children":572},{"className":571},[],[573],{"type":38,"value":574},"sparkUp",{"type":38,"value":576}," for the positive-delta \"Devices Sensored\" preset) — real telemetry is jagged, not a clean ramp.",{"type":33,"tag":144,"props":578,"children":579},{},[580,584,586,592],{"type":33,"tag":148,"props":581,"children":582},{},[583],{"type":38,"value":17},{"type":38,"value":585}," — Added a ",{"type":33,"tag":49,"props":587,"children":589},{"className":588},[],[590],{"type":38,"value":591},"UxCopyBtn",{"type":38,"value":593}," (icon-only, top-right corner) to each preset card in the demo, copying a self-contained Vue template snippet of that exact preset — makes the \"copy this, don't hand-assemble\" pattern literal instead of just stated.",{"type":33,"tag":144,"props":595,"children":596},{},[597,601,603,608,610,616,618,624,626,632,634,640,642,648,650,656,658,663,665,671,673,679,681,687],{"type":33,"tag":148,"props":598,"children":599},{},[600],{"type":38,"value":17},{"type":38,"value":602}," — Fixed a real bug in ",{"type":33,"tag":49,"props":604,"children":606},{"className":605},[],[607],{"type":38,"value":180},{"type":38,"value":609}," surfaced by using it unfilled: ",{"type":33,"tag":49,"props":611,"children":613},{"className":612},[],[614],{"type":38,"value":615},"svgMachine.sparkChart",{"type":38,"value":617}," always injected baseline anchor points (",{"type":33,"tag":49,"props":619,"children":621},{"className":620},[],[622],{"type":38,"value":623},"(0,-10)",{"type":38,"value":625}," \u002F ",{"type":33,"tag":49,"props":627,"children":629},{"className":628},[],[630],{"type":38,"value":631},"(width+10,-1)",{"type":38,"value":633},") meant to close a filled polygon; with ",{"type":33,"tag":49,"props":635,"children":637},{"className":636},[],[638],{"type":38,"value":639},"fillColor=\"none\"",{"type":38,"value":641}," those anchors render as a visible drop at the start\u002Fend of the stroked line. Added a ",{"type":33,"tag":49,"props":643,"children":645},{"className":644},[],[646],{"type":38,"value":647},"closePath",{"type":38,"value":649}," param (",{"type":33,"tag":49,"props":651,"children":653},{"className":652},[],[654],{"type":38,"value":655},"q-nuxt-layer\u002Futils\u002Fsvg.js",{"type":38,"value":657},") and had ",{"type":33,"tag":49,"props":659,"children":661},{"className":660},[],[662],{"type":38,"value":180},{"type":38,"value":664}," pass ",{"type":33,"tag":49,"props":666,"children":668},{"className":667},[],[669],{"type":38,"value":670},"fillColor !== 'none'",{"type":38,"value":672},", so line-only sparklines render clean. Also fixes the same latent artifact in ",{"type":33,"tag":49,"props":674,"children":676},{"className":675},[],[677],{"type":38,"value":678},"SecurityPolicyCard",{"type":38,"value":680},"'s three sparklines (verified, no regression). ",{"type":33,"tag":49,"props":682,"children":684},{"className":683},[],[685],{"type":38,"value":686},"SparkChartOld",{"type":38,"value":688}," untouched — deprecated, out of scope.",{"type":33,"tag":144,"props":690,"children":691},{},[692,696,698,703,704,709,711,717,719,724,726,732],{"type":33,"tag":148,"props":693,"children":694},{},[695],{"type":38,"value":17},{"type":38,"value":697}," — Replaced the static ",{"type":33,"tag":49,"props":699,"children":701},{"className":700},[],[702],{"type":38,"value":566},{"type":38,"value":64},{"type":33,"tag":49,"props":705,"children":707},{"className":706},[],[708],{"type":38,"value":574},{"type":38,"value":710}," fixtures with a new ",{"type":33,"tag":49,"props":712,"children":714},{"className":713},[],[715],{"type":38,"value":716},"generateVelocitySpark()",{"type":38,"value":718}," helper in ",{"type":33,"tag":49,"props":720,"children":722},{"className":721},[],[723],{"type":38,"value":558},{"type":38,"value":725}," — a damped random walk (velocity carries forward instead of each point being independent) so the line moves in short organic runs like real traffic, with an optional ",{"type":33,"tag":49,"props":727,"children":729},{"className":728},[],[730],{"type":38,"value":731},"drift",{"type":38,"value":733}," for a biased trend (used for the positive-delta \"Devices Sensored\" preset).",{"type":33,"tag":144,"props":735,"children":736},{},[737,741,743,749,751,756,757,762,764,770,772,778],{"type":33,"tag":148,"props":738,"children":739},{},[740],{"type":38,"value":17},{"type":38,"value":742}," — Added optional ",{"type":33,"tag":49,"props":744,"children":746},{"className":745},[],[747],{"type":38,"value":748},"slotGap",{"type":38,"value":750}," prop (Number, px) — extra spacing between ",{"type":33,"tag":49,"props":752,"children":754},{"className":753},[],[755],{"type":38,"value":219},{"type":38,"value":64},{"type":33,"tag":49,"props":758,"children":760},{"className":759},[],[761],{"type":38,"value":226},{"type":38,"value":763}," slot content and the main value\u002Fdelta group, on top of the row's default gap. Implemented as conditional margin on ",{"type":33,"tag":49,"props":765,"children":767},{"className":766},[],[768],{"type":38,"value":769},"v-if=\"$slots.left\u002Fright\"",{"type":38,"value":771}," wrappers so it costs nothing when a slot is unused. Demoed with a dedicated \"Slot Gap\" comparison (default vs. ",{"type":33,"tag":49,"props":773,"children":775},{"className":774},[],[776],{"type":38,"value":777},"slotGap=\"24\"",{"type":38,"value":779},") and documented in the registry.",{"key":781,"title":782,"empty":19,"ast":783},"outcome","Outcome",{"type":30,"children":784},[785],{"type":33,"tag":34,"props":786,"children":787},{},[788,790,795,797,802,804,809],{"type":38,"value":789},"Shipped ",{"type":33,"tag":49,"props":791,"children":793},{"className":792},[],[794],{"type":38,"value":14},{"type":38,"value":796}," composing existing DataMetric primitives with no changes required to them, proving the base+presets pattern didn't need new primitive work — just new composition markup (title\u002Fhairline\u002Fdescription\u002Fprovenance) that has no reuse case outside this component, hence the flat ",{"type":33,"tag":49,"props":798,"children":800},{"className":799},[],[801],{"type":38,"value":188},{"type":38,"value":803}," convention rather than the ",{"type":33,"tag":49,"props":805,"children":807},{"className":806},[],[808],{"type":38,"value":196},{"type":38,"value":810}," split. Presets stayed at the design-site-demo level rather than named layer wrappers, deferring that decision until real qcontrol usage validates which configs are worth freezing. The pattern itself is now named and cross-referenced in both philosophy docs, closing the loop qmap\u002Fqflow opened independently.",[],[813],"initial-prompt.md",[815],{"file":813,"title":8},[817,825],{"src":20,"kind":818,"order":819,"caption":820,"capturedAt":821,"subject":822,"route":823,"evolution":824},"hero",4999,"\u002Fcomponents\u002Fdata-machine — adminProps harness above the two copyable presets (User Coverage, Devices Sensored) and the scenario grid","2026-09-18T16:47:18.842Z","component\u002Fdata-machine","\u002Fcomponents\u002Fdata-machine\u002Fdata-machine",{"subject":822,"moments":21},{"src":826,"kind":827,"order":828,"capturedAt":821,"subject":822,"route":823,"evolution":829},"\u002Fcycles\u002Fdesign\u002Fc91-data-machine-full.png","full",9000,{"subject":822,"moments":21},[],[832],{"route":823,"href":823},1794599413389]