SAMPLE · Stack swap test · nail-salon (Frisco TX) on the universal Valet core · industry proof-of-concept demo

The transfer works — config vs core

✓ Swap test PASSED — same engine, only the industry + brand config changed.

The universal GM dashboard, margin engine, efficiency/coaching logic and staff timer all run a nail salon by swapping two config layers — nail-INDUSTRY + Ooo La La-BRAND. Zero universal-core logic was rewritten. "Don't build anything for Ooo La La we're not building for Bark & Purr" holds: it's the same core B&P runs, re-tenanted.

What changed vs what stayed

The line between these two columns IS the IP. Everything on the right lifts unchanged to the next tenant.

● Changed — CONFIG only

  • Industry layer (nail)services, active-time benchmarks, pay models, margins, capacity unit "stations"
  • Brand layer (Ooo La La)name, plum/pink colors, voice, staff (Mimi/Lux/Coco/Bao), Frisco location, IDs, goals
  • Competitive setFrisco salon prices (vs B&P's Allen groomers)
  • Sample dataindustry-average nail numbers (no specific salon's books)

■ Stayed — UNIVERSAL CORE

  • The 3-leg dashboard enginerevenue · profitability · service/reviews layout + render
  • Margin engineactive-minutes → labor cost → margin per service
  • Efficiency + coaching logic% of benchmark, n≥4 / ≥15-pt outlier flagging
  • Honesty system"connect this source" states, watermarked SAMPLE toggle
  • Source plumbingMyTime / booking / POS / reviews / Compass adapters

The dimensions that swapped

DimensionBark & Purr (grooming)Ooo La La (nail)Layer
Subjectthe pet — breed · coat · sizethe guest — a personconfig
Service driverdog size × coat → time/priceservice type + add-ons → time/priceconfig
Capacity unitgroomer-hoursstation-hours (mani + pedi chairs)config
Labor lanescommission groomer + hourly bathernail tech: commission / hourly / booth / hybridconfig
Efficiency modelbath + groom phase minutesper-service active minutesconfig (effModel flag)
Margin mathmin × loaded $/min → marginidenticalcore
Coaching engineflag ≥15 pts slower, n≥4identical — flagged Bao (new)core
3-leg layout + honestyrevenue/profit/serviceidenticalcore

The sample pages

Open with the "Sample data" toggle ON to see them populated (industry averages — clearly watermarked SAMPLE).

What the swap test found (honest)

Per Stack Protocol §"flag the leak" — the swap surfaced refactor debt. Naming it is the point.

The math core transferred cleanly; the grooming COPY did not. The current B&P dashboard (GM_Dashboard_Universal_v2.html) hardcodes grooming wording in display strings — column labels "Bath / Groom", cause text ("matting", "de-shed"), the word "dog/PAWrent". Those are leaks: brand/industry copy sitting in the core.
Fix (already prototyped here): the shared engine core/gm-core.js moves that copy into the industry config (effModel, subject, coachCauses, phase labels). It renders both grooming and nail from config — that's the paid-down version. Recommendation (Tier-2): converge the v2 B&P dashboard onto gm-core.js so there's one core, not an inline grooming monolith + a generalized fork.

The config layer (industry-sourced — verifiable by a skeptical owner)

Every benchmark, pay-model split and margin band is cited. No invented numbers.

Config fileWhat's in itKey sources
active-time-benchmark.jsonactive minutes per service (mani 30 · gel 45 · dip 60 · acrylic set 75 · pedi 55) + add-ons + role-tier modifierPolish Pops, BTArtbox, Bela, Booksy
pay-models.jsonhourly $10–25 · commission 30–60% (entry 40/60) · booth $400–1,200/mo · hybrid (gold standard)GlossGenius, Zenoti, Square, Strategies.com, Booksy
economics.jsonnet margin 15–25% · labor 45–55% · rent 8–10% · supplies 5–10% · seat utilization 75–80% · capacity = stationsBooksy, BusinessDojo, PlanPros, Vagaro
service-catalog.jsonnail menu + add-ons (baseline pricing)known-salon baseline + Frisco menus

Folder: industries/nail-salon/ · brand layer: industries/nail-salon/brands/ooolala/. All figures are industry baselines for the demo; a real salon's menu, pay structure and P&L drop straight into these files and every page recomputes.

One core, not two — the no-double-maintenance proof

Per Linda: improvements go into the universal core; both tenants inherit by config. We do not hand-maintain two dashboards.

The nail instance is expressed in the canonical core's exact config contract (gm/v2-config.nailsalon.ooolala.js) and validated against the core's verbatim margin math in node:

Check (run on the core's own functions)Result
Per-service net margin15–25% — lands in the industry band, no core edit
Slow-tech acrylic (99m vs 75m bench)attributed to TIME over benchmark, not price — the pricing-vs-staffing split works on nails
Frisco competitive verdictscompute (gel/acrylic/pedi "priced right"; classic mani thin → "lower cost")
Margin math change requiredzero — nails = one commission lane with prep-phase 0
Only true leak founddisplay copy — "Bath/Groom" labels & cause text → move to config

Convergence (Tier-2, handed to GM-dashboard seat): lift the canonical core into a shared file + add a laborModel switch + move the grooming display strings to config. Then B&P and Ooo La La are each just a config bundle on one engine. Ref: captains-log/HANDOFF_GMcore_Externalize_for_Nail_Swap_20260612.md

What flips live the moment Kareem grants access

Today: 100% SAMPLE / "connect this source". Each source flips by setting one config key (null → his URL); that source's SAMPLE block is replaced by his real data. No core or page edits.

SourcePowersFlipNeeds from Kareem
MyTime / bookingrevenue, ticket, no-shows, utilization, repeat mixsources.mytime.endpoint null→URLread access + location ID
POS / P&Lnet margin, labor %, true-cost, per-service flagstruecost.isSample true→false + his P&Lbookkeeping read + pay structure
Compassactive time vs benchmark, coachingsources.compass.endpoint null→URLtechs use the timer
Analyticssearch→booking conversionsources.ga4 property + endpointGA property read
Reviewsrating trendsources.reviews.endpoint null→URLGoogle Business Profile

No Kareem needed for: active-time benchmarks, pay-model engine, margin bands, Frisco competitive set, and the swap itself — all ship today. Full detail: industries/nail-salon/brands/ooolala/go-live-manifest.json.

Red-team — pitfalls, ~95% confidence, long-view

Sharpen-the-saw: reverse-engineered failure modes before shipping.

Pitfall a skeptic raisesHow it's handled
"This is just made-up numbers."Every config figure is cited (Booksy, Zenoti, GlossGenius, Square, trade timing guides). SAMPLE is watermarked; demo toggle OFF by default; truecost.isSample shown on-page.
"The ticking timer looks live."Labelled "illustrative sample timer"; source note says SAMPLE captures until Compass launches.
"You forked the dashboard — now you maintain two."Flagged honestly. The nail config is drop-in to the canonical core; convergence handoff filed so it's ONE core, not a fork.
"Grooming logic won't really fit nails."Validated on the core's verbatim math: margins, slow-tech attribution, competitive verdicts all compute. Only display copy leaks.
"Frisco competitor prices aren't his."Labelled SAMPLE public-menu ranges; verdict direction holds across the range; firmed up without needing Kareem.
"What happens when his real numbers differ?"Nothing breaks — they replace the SAMPLE block via config; every page recomputes. That's the design.
Confidence ~95%. The swap is proven config-only and validated on the core's own math. The one open dependency — externalising the core so it's literally one engine — is a coordination step with the GM-dashboard seat, not a rebuild. Long-view test: nothing here gets redone later; the nail config is built to the canonical contract, so when the core externalises, it drops in unchanged.