RPP Sales Plan: Deep Dive and Landing Plan

Four answers (version control, HOUZN December, fonts, tab-by-tab), what normal hotels do for budgeting, and the plan to land this feature. Compiled from the live Google workbooks, the RPP codebase and database, THM email history, and industry research.
Generated 2026-07-19 by Woz Sources cited inline throughout
TL;DR

The four answers

1 · How do we get version control?
There is none today, in either the sheets or the app. The "(UNLOCKED)" in the filenames is just a name: zero sheet protection exists on any of the 6 workbook files (verified via Sheets API and xlsx export). In RPP, every edit overwrites the single plan row in place; nothing is snapshotted. Fix: a status + lock field this week, then immutable plan versions (Budget locked, Forecast rolling, Reforecast snapshots), which is also the industry-standard model.
2 · Why is December missing for HOUZN?
It is not missing in the 2026 Sales Goal workbook. All 12 months are populated in all three properties' workbooks (cells pulled 2026-07-19), and all HOUZN scenarios in the RPP database carry December too. Two real things hide behind the impression: HOUZN's December RevPAR cells were hand-typed over broken formulas (the only such patch in all 3 files), and the separate file "HOUZN - Sales Team Goals - 2026" is completely blank, every month $0. If you saw an empty December, it was almost certainly that second file.
3 · What's up with the fonts?
It is all one font (Arial), zero exceptions in 4,900+ cells. What reads as a font mess is size and color: the pasted STR "Response" tab renders its dot-plot with 18pt bullet characters next to 10pt data tables, plus hardcoded blacks and grays that ignore the theme. The GM-facing Sales Goals tab is actually clean and identical across all three properties.
4 · What does each tab do, and is it clunky?
The app is a superset of the sheet's math but is missing the sheet's one irreplaceable job: entering the budget. The in-app budget editor was deleted 2026-07-17 as dead code and never replaced, so budgets exist only for the 3 seeded pilots and 3 of the 5 tabs dead-end everywhere else. Full tab-by-tab and a ranked clunk audit below.
Ground truth

The original: where it lives and how it works

The paper ancestor of the RPP Sales Plan is one Google workbook per property, built during Ronald's December 2025 budget cycle (GM deadline 2025-12-20, email 2025-12-12, Spark msg 13967).

PropertyFileCreatedLast editedDrive path
HOURP2026 Sales Goal HOURP - v1 (UNLOCKED)2025-11-252026-02-16Drive (THM) / HOURP - SpringHill Suites Houston Med Center / HOURP - Sales and Marketing / Sales Performance / Sales Goals and Targets
HOUUS2026 Sales Goal HOUUS - v1 (UNLOCKED)2025-11-242026-02-16.../ 01 - Sales Performance / 01B - Sales Goals and Targets
HOUZN2026 Sales Goal HOUZN - v1 (UNLOCKED)2025-11-202026-02-16.../ 01 - Sales Performance / 01B - Sales Goals and Targets
File IDs: HOURP 1fCx4Jwp...wy_4, HOUUS 1C_xQkVl...eUQQ, HOUZN 1hLyourB...27Wg (drive metadata via gog, pulled 2026-07-19). Each folder also holds the frozen 2025 edition. All three 2026 files were last touched within 7 minutes of each other on Feb 16, 2026, and not since: one batch data-entry session, then 5 months of dormancy.

Three tabs per workbook

The mechanism: three orange inputs, everything else cascades

Row 30 Market Growth % (monthly)
Row 33 Occupancy Adj % vs 2025
Row 36 ADR Adj % vs 2025
Projected Occ / ADR = 2025 actual × (1 + adj)
RevPAR & Revenue = RevPAR × days × rooms
Projected RGI = TTM RGI × (1 + own growth − market growth)

The punchline of the design: the GM's plan is forced to declare a market-share position (projected RGI), not just a revenue number. HOURP's 2026 plan landed at $6,534,417 projected on $6,093,340 TTM 2025 (+6.8%), projected RGI 101.2 vs 96.0 actual (Sales Goals rows 9, 28, 40, 41).

Known quirks in the sheet math: the Growth row computes 1 − (2025 ÷ 2026), which understates growth (Feb shows 10.7% where the conventional calc is 12.0%: 523,340 / 467,268 − 1). Revenue is STR-derived (occ × ADR × rooms × days), so it never ties exactly to QBO account 4100. And the whole workbook is static: STR pasted once, no live actuals, frozen since Feb 16.

Downstream: the plan's monthly Growth row is copied into "HOURP - Sales Team Goals - 2026" (same folder), which sets the group-sales team's monthly revenue goals. HOURP's tracker has 2026 actuals through April; HOUUS has no tracker file at all; HOUZN's exists but is empty (see question 2).

Question 1

Version control: what exists, what to build

Current state, sheets

Current state, app

How to get it

OptionWhat it isGets youEffort*Verdict
A. Status + lock Add status (draft / submitted / approved / locked) + approved_by/at to sales_plans; gate writes when approved or locked; status badge in the UI. The plan stops silently changing. A real "this is the committed budget" state. 0.5-1 day Do this week
B. Immutable versions New sales_plan_versions table: on approval, the full plan (scenarios + the three adjustment maps + targets) is frozen as a labeled snapshot ("Original Budget", "Q2 Reforecast"). The live row stays the working draft. Version picker in the top bar; the existing Scenarios tab becomes the compare view. Exactly the industry model: Budget locked, Forecast rolling, Reforecasts as approved snapshots, all comparable side by side. 2-4 days The real answer
C. Full change log Append-only log of every field change (who, when, old, new), point-in-time reconstruction. Forensic audit trail ("who moved June ADR"). 3-5 days Only if lender/partner scrutiny demands it
*Effort figures are engineering estimates from the code dissection (assumption, not measured). Detail: the snapshot payload reuses the JSONB shapes that already exist in sales_plans, so option B is mostly a migration + an approve RPC + a version picker.
Once B ships, the Google workbooks stop being the system of record: the December budget cycle happens in RPP (GM types the same three levers, Ronald approves, the plan locks), and the sheet becomes an export, not a source.
Question 2

HOUZN December: found it

Checked three places: the Google workbook, the sibling files, and the RPP database. December exists in the workbook and the database. The blank December lives in a different file.

WhereDecember stateEvidence
2026 Sales Goal HOUZN workbook Fully populated All 12 months + totals present in both the 2025 actuals and 2026 projection blocks (cells pulled 2026-07-19): Dec 2025 occ 56.23%, Dec 2025 RevPAR $62.72, Dec 2026 projected ADR $113.79, RevPAR $64.63. Comp/Response tabs carry the full December 2025 STR report (created Jan 17, 2026, STR ID 63698, 9-member compset).
RPP database (sales_plans) Fully populated All four HOUZN scenarios (2025 Actual, GM Budget 2026, SMART Forecast 2026, Fair Share 2026) carry months 1-12; GM Budget December: $278,475 revenue, 56.8% occ, $113.79 ADR (live query 2026-07-19).
"HOUZN - Sales Team Goals - 2026" tracker Entirely blank Every row Jan-Dec, all years 2022-2026, is empty; the sheet's own total row computes $0 (cells pulled read-only 2026-07-19 from file 1CiAgtwC...IE4k). Last touched 2026-06-30, the most recently edited file in the whole investigation. HOURP's equivalent tracker has actuals through April 2026 (same-day pull of file 1kPj1UrS...-sfw); HOUUS has no tracker file in its folder.
The forensic detail worth knowing: in the HOUZN workbook, the two December RevPAR cells (Sales Goals O19, O20) are hand-typed constants (62.72 and 53.7) where every other month, and both sibling workbooks, use live formulas (=O15*O11). It is the only formula break in all three files. Someone manually patched HOUZN's December during the Feb 16 batch session; the typed value is 1 cent off what the formula would produce, consistent with copying STR's own rounded number. December needed manual help once, but it is there.

So the answer: if you saw a missing December for HOUZN, you were most likely in the Sales Team Goals tracker (which is 100% empty and was touched as recently as June 30), not the Sales Goal workbook. If you did see it blank in the workbook itself, that state no longer exists and predates nothing we can reconstruct: revision history is not readable through our tooling, so pre-Feb-16 states are unverifiable. Flagging that honestly rather than inventing a cause.

Question 3

Fonts: one family, chaotic sizes

All three workbooks were exported to xlsx and every populated cell's font inventoried (4,900+ cells total, ~1,600-1,800 per workbook).

Practical takeaway: nothing to fix by hand. The mess is an artifact of pasting STR report renders into Sheets, and it disappears entirely once RPP is the surface, because RPP already ingests the same STR data into compset_metrics and renders it natively (the Compset Intel tab). The pasted Comp/Response tabs are exactly the part of the workbook RPP has already made obsolete.
Question 4

The app, tab by tab

Route /app/sales-plan, five tabs. Property picker defaults to the most recently updated property that has a plan; properties are tagged "plan" / "no plan".

TabWhat it does (plain English)Data sourceYou can editState
Forecast The heart, and the direct descendant of the Google sheet. Auto-pulls last year's STR actuals for you and your compset, gives the GM the same three levers (Market Growth, Occ Adjustment, ADR Adjustment), instantly projects occ/ADR/RevPAR/revenue and projected RGI per month. Closed months show real actuals. A rank-goal bar lets you set a target compset rank, and "Wynn" auto-suggests the lever values needed to hit a target RGI. STR via compset_metrics (auto), room counts via budget_assumptions, math in salesPlanCalc.ts 3 adjustment rows, target rank Works, best-in-class core
Pace "Will this month make budget?" Budget vs month-to-date actuals vs on-the-books, plus the pickup still needed and the ADR that implies. night_audit_current + booking_pace + the GM Budget scenario Nothing (read-only) Blank without a pace feed + budget
Actuals vs Plan Monthly report card for closed months: actual vs GM Budget, green/amber/red variance, YTD summary, STR RGI column where it exists (never fabricated). night_audit_current + GM Budget scenario + compset_metrics Nothing (read-only) Dead-ends without a budget
Scenarios Side-by-side comparison of stored scenarios (GM Budget, SMART Forecast, prior-year actual): weighted annual cards + a 12-month revenue matrix. scenarios JSONB on the plan row Nothing (read-only) Redundant today; becomes the version-compare view
Compset Intel 18-month STR trend table (occ/ADR/RevPAR with MPI/ARI/RGI and ranks) plus the compset member roster. compset_metrics + compset member tables Nothing (read-only) Duplicates the Compsets page

The clunk audit, ranked by user pain

ProblemWhy it hurtsWhere
1You cannot create or edit a budget in the app. The budget editor (BudgetBuilderTab, 467 lines) was deleted 2026-07-17 as already-dead V1 code and never replaced.Budgets exist only for the 3 seeded pilots (HOURP, HOUUS, HOUZN, verified by live DB query). For any other property, "Create Sales Plan" makes an empty shell and Pace, Actuals vs Plan, and the Forecast's budget rows all dead-end. The single biggest blocker to landing the feature.commit f57e8a0; SalesPlan.tsx:71
2Two "plans" with an unexplained relationship. Editing the Forecast levers changes the SMART Forecast scenario, but Pace and Actuals vs Plan always grade against the GM Budget.A GM will assume the numbers they edit are "the plan." Nothing on screen says otherwise except a footnote.ForecastTab.tsx:349
3Projected revenue silently shows $0 when budget_assumptions is missing for the property/year.RevPAR rows populate while the revenue KPI reads $0. Looks broken, no warning shown.ForecastTab.tsx:73-81
4RGI is averaged three different ways on one screen (revenue-weighted KPI, arithmetic-mean grid total, arithmetic TTM in the rank bar).The numbers visibly disagree with each other, eroding trust in all of them.salesPlanCalc.ts:264; ForecastGrid.tsx:38
5Occ adjustment is points in the app, was % in the sheet.A GM trained on the sheet typing "+3" gets +3 occupancy points, not +3%.salesPlanCalc.ts:165
6The brand forecast is stored with no provenance. The SMART forecast is Marriott's own number (Ace, 2026-07-19), but the app stores it as an anonymous scenario, indistinguishable from something we computed.Who produced a forecast, when, and via what feed is the whole ballgame for a multi-brand operator. Fixed by the forecast-lane model below.Spark msg 179768; sales_plans.scenarios JSONB
7Wynn's goal-seek is a black box (magic weighting constant, hard caps, unexplained per-month suggestions).GMs will blindly accept or entirely ignore it.salesPlanCalc.ts:352-453
8No role scoping. RLS is tenant-only; every role that sees the nav, including front desk, can edit any property's plan.Fine for internal pilot, untenable the day GMs get logins.migration 259:15; nav-config.ts:131
9Half the data model is dead (target_revpar_rank, rgi_goal, fair_share_formula, market_context, actuals_through: no UI reads them), plus dead V1 hooks including the orphaned GL-4100 budget sync.Cruft, and the market-events overlay everyone wants is already modeled but invisible.useSalesPlan.ts:129-292
10Five tabs where three carry the load; invisible save state; heavy horizontal scroll on mobile.Feels bigger and clunkier than it is.SalesPlan.tsx:118
Research

What normal hotels do for budgeting

Web research across industry guides, tool vendors, and asset-management sources. Full source list in the footer note; key claims linked inline.

The standard process

The version model everyone converges on

"The budget is a commitment made once a year, the forecast is the truth updated monthly, and when they diverge, the forecast wins with the variance log explaining why" (Model Reef). One model, three views: Budget (locked at the assumption layer), Forecast (rolling, updated monthly), Reforecast (approved snapshot when the plan is no longer the plan). Monthly cadence, every variance over 5% gets a one-line written explanation, forecast accuracy targets of ±5% at 30 days out.

Brands do ask for the numbers

Correction to the initial research (Ace, 2026-07-19, confirmed in the inbox): franchise revenue management requests budgets. Marriott's SMART program runs on HOUZN (Amy Wickliff's SMART Recaps to Sam Xie and ownership, Spark msg 179768) with One Yield as the yield system (registration approval msg 63402), and IHG's equivalent covers HOUUS. So the module needs a brand-RM-ready output: monthly occupancy / ADR / RevPAR in the shape the revenue manager loads into One Yield or Concerto, on the brand's calendar. What it does not need is franchise-compliance workflow beyond that.

Tools reality check

TierToolsCost signalWho uses it
Enterprise budgeting suitesActabl ProfitSword, Otelier TruePlan, Aptech Targetvue, Fairmas"Contact us" pricing20-30+ property groups, PE/asset-manager mandates
RMS forecastingIDeaS G3, Duetto~$1,200-3,500 / mo / hotel*Full-service and better-performing select-service
Accounting-platform budget modulesM3, Inn-FlowBundled with accountingThe select-service mainstream
The actual defaultExcel / Google Sheets + STR STAR$0Most 10-30 property operators, including THM today
*Directional third-party figures (exploretech for IDeaS, Duetto from vendor marketing), not quoted price sheets. The gap in the market: nothing self-serve and affordable does STR-anchored budgeting for a 15-hotel select-service operator. That gap is RPP's wedge at $299/mo.
Adversarial review, 2026-07-19

The review board

Seven independent reviews of this plan: the four W5 lenses, two cross-vendor advisors on non-Claude models, and the Hormozi offer lens. All seven returned REVISE. The plan below already incorporates their accepted findings and Ace's round-2 decisions.

ReviewerLensSharpest finding
WynnRevenue scienceCompute projected RGI per month as an exact ratio (not the flat TTM approximation); grade the budget on attainment but prediction lanes on accuracy at matched snapshot horizons, or GMs learn to sandbag.
WarrenMoney mathMeasure THM's actual STR-to-GL revenue gap and calibrate the 4100 sync with it; store integer rooms-sold as the budget primitive; a reforecast approval must never silently re-baseline the locked budget.
WaltonOperationsBrand-recap feeds need expected-cadence freshness alerting like every other ingestion pipeline; the monthly ritual needs the same reminder machinery as the annual season or it decays like the trackers did.
Woz (fresh eyes)EngineeringThe "SMART Forecast" scenario in code is the GM's own computed projection, not Marriott's number (two-lane split required); snapshots must freeze computed outputs, not input levers; the orphaned 4100 function is broken as written.
Andrej (GPT-5.4)Systems rigorNo cutover acceptance bar: freeze a golden corpus from the pilot workbooks and assert month-level parity before the sheet loses system-of-record status; approval needs atomicity and a read-back reconciliation assertion.
ChaseAI (Gemini)Scope disciplineShip P0 completely before any P1; the auto-suggest black box must be fixed or removed, not shipped as-is; gate the GL sync.
HormoziThe offerFlat $299/mo breaks the pricing model for a portfolio product; the accuracy-grading proof can be built from THM's existing history now; nothing in the plan was designed to make an operator switch.

Adopted from the board (engineering calls)

P0 SHIPPED 2026-07-19. Commits c8a7482 (build) + 354c851 (board hotfix) live in production via deploy 91305df; migrations 274 + 275 applied and verified. A 5-reviewer post-ship board (Wynn, Warren, fresh-eyes Woz, Andrej, ChaseAI) found 12 items; all fixed and shipped same day. Calc test suite: 63 assertions green. Live now: status lifecycle with lock trigger, promote-to-budget with integer rooms-sold, seed-from-last-year, exact monthly RGI everywhere, raise-only suggestions with per-lever honesty, visible save errors, linear transitions with the implied-RGI approve checkpoint.

Round-3 decisions (Ace, 2026-07-19, post-ship)

DecisionCall
GM accessAfter the P1 roles slice ships. P1 order: versions + backfill first, then roles, then season workflow.
2026 dry runMid-August, Ronald drives the reforecast on the 3 pilots once the versions slice lands; this doubles as Ronald's tool onboarding, with the 2027 season calendar drafted in the late-August debrief.
Non-pilot proofDFWXY (richest non-pilot STR coverage: 2,454 metric rows since Jan 2025, live query). Night-audit feed to be verified before seeding.
Design partnerNo outreach until DFWXY proves. The gate stands; the search starts only after the proof case works.
Case studyGrade everything, internal-only: parse HOUZN's historical Marriott SMART recaps and grade all lanes at matched horizons; the recap archive doubles as the SMART parser's development corpus. Prospect-facing framing decided later.
Group laneHolds P2. A new DOS bridges on a maintained paper goal sheet generated from the plan's Growth row.

Round-2 decisions (Ace, 2026-07-19)

DecisionCall
Occupancy leverREVERSED to points (stored and computed), displayed unmistakably as "+3.0 pts" with a translation tooltip for sheet-trained GMs. No pilot data migration, no suggest-logic rewrite.
4100 sync guardrailCalibrated auto-sync: per-property trailing-12 STR-to-GL ratio applied and shown at approval; residual gap over ~5% flags a data-integrity review instead of posting as a grade (threshold is Warren's convention, tuned after measuring).
PricingPer-property base plus premium tier (accuracy grading, multi-brand aggregation, portfolio rollup are the premium). Warren models the per-door number before the first external conversation.
Proof artifactBuild the accuracy-grading case study on THM's own history during P0/P1, as both the sales proof and the design spec for the live P2 feature.
Design partnerHard gate: when P0 proves on a non-pilot property, one external management company onboards (founder-priced) so P1/P2 are shaped by two operators.
Auto-suggestRebuilt as Ace's manual process: per-month, raise-only against the hotel-set RGI target, each suggestion with its one-line reason, capped, never lowering months already above target. Stays in for the 2027 season.
Compset Intel tabDropped from the module; a link jumps to the Compsets page with the property preselected.
Portfolio rollupBuilt during the 2027 season work; aggregates only approved locked budgets, everything else shows "no plan yet". Ready as the design-partner demo.
The offerFree graded-budget diagnosis ("if we don't show you something you didn't know, you pay nothing") as the opening offer, reusing the case-study machinery.
Support pathRonald is first line for GM data questions with in-app explainers ahead of him; genuine data or bug issues escalate to Woz.
Recommendation

The landing plan

The Forecast tab's core (STR-anchored, three levers, projected RGI, rank goals) is already better than anything in the affordable tier. What is missing is the boring institutional half: a budget you can enter, lock, version, and report against. Three phases.

Locked decisions (Ace, 2026-07-19 Q&A)

DecisionCall
Budget entryPromote forecast to GM Budget (tune the three levers, freeze as budget, inline month tweaks allowed before approval). Plus a one-click "Set budget = last year" seeding option, since the non-pilot properties budget off prior year today.
RolesGM drafts own property, ownership approves and locks; Ronald/Junaid get portfolio-wide staff edit.
Occupancy leverPercent, matching the workbook. Superseded Reversed to points in round 2 after the engineering review (see Review Board section).
First in-app season2027 budget season starting September 2026, lock by early December; dry run = a 2026 mid-year reforecast on the pilots.
Rollout scopeThe 3 pilots stay the real users for now. Wider THM rollout later; last-year seeding covers the rest meanwhile.
IHG feedIHG sends an email recap like Marriott's (Ace), so the IHG parser follows the SMART parser on the same pattern.
Accuracy gradingVisible to ownership and GMs, every lane including the brand RM's.
SegmentsOne group/negotiated lane only in P2, replacing the Sales Team Goals sheets. No full segmentation yet.
P&L scopeRooms revenue only. Approved budget auto-syncs to GL 4100 in the budget/BVA system (revive the orphaned sync); expenses stay in the budget module.
Connector timingAfter P1 lock ships: SMART parser then IHG as the first P2 items.

Brand-agnostic by design (locked with Ace, 2026-07-19)

The SMART forecast comes from Marriott directly; IHG has an equivalent that is not wired in; many management companies use brand revenue management. So the architecture treats forecasts as lanes with provenance and brand programs as connectors:

P0

Make it whole

~1.5-2 weeks (re-estimated after review: the RGI and suggest items are math changes, not display fixes)
  • Rebuild budget entry (decided): a "Promote to GM Budget" action that freezes the current working forecast as the budget scenario, inline month editing for tweaks before approval, and a "Set budget = last year" one-click seed for properties without a modeled plan. Kills clunk #1.
  • Status + lock (version-control option A): draft / submitted / approved / locked with a visible badge.
  • Trust fixes: one RGI definition everywhere (ratio-of-sums, monthly-exact), occ lever stays in points labeled "+3.0 pts" (round-2 reversal), a visible warning instead of silent $0 revenue, a save indicator, the two-lane forecast split ("GM Model Forecast" for the computed lane; "Brand RM Forecast" reserved for the real parsed feed), and the auto-suggest rebuilt per-month raise-only with visible reasons.
P1

Version control + the annual cycle

re-estimated ~3-4 weeks, split into three independently-shipped slices: versions + backfill, roles, season workflow
  • Immutable plan versions (option B): approval freezes a labeled snapshot; reforecasts open a new draft; the Scenarios tab becomes the version-compare view. Matches the industry "one model, three views" standard. The forecast-lane provenance fields ride along in this same migration (source, brand, program, as-of, feed) so nothing brand-specific calcifies.
  • Monthly reforecast ritual in-app: variance over 5% requires a one-line note that persists (institutional memory, the thing Excel never keeps).
  • Role scoping RLS before any GM gets a login (decided): GMs edit their own property's draft, ownership approves and locks, Ronald/Junaid hold portfolio staff edit, locked plans read-only for everyone.
  • Budget-season workflow (decided): the 2027 season runs in-app starting September 2026 with a lock by early December; dry run is a 2026 mid-year reforecast on the 3 pilots. Ronald's email cycle becomes an RPP flow with deadlines and per-property completion status.
  • Revive the 4100 sync (decided): on approval, the locked rooms-revenue budget pushes automatically to GL account 4100 in the budget/BVA system. Sales Plan stays rooms-only; expenses stay in the budget module.
P2

Differentiators

sequenced by demand
  • Brand connectors (decided: start after P1 lock ships): the Marriott SMART recap parser first (built against the real emails in the HOUZN thread history), then the IHG parser, which follows the same pattern since IHG also delivers an email recap (Ace, 2026-07-19). Plus forecast accuracy grading per lane, visible to ownership and GMs, once a few months of actuals accumulate: "your brand RM's forecast has run N% hot" is the feature that sells this to management companies.
  • Brand-RM export: one-click monthly occ / ADR / RevPAR budget sheet in the shape each brand's RM program asks to receive (One Yield for Marriott, IHG's equivalent). One canonical budget, per-brand rendering.
  • Market-events overlay: the schema already stores events (market_context: Rodeo, World Cup, the Apple/Foxconn facility for HOUZN) with zero UI. Surface them on the Forecast grid as month annotations with suggested bumps.
  • Group lane (decided, instead of full segmentation): one group/negotiated revenue lane with monthly goals for the DOS, replacing the half-dead "Sales Team Goals" sheets (one of which is HOUZN's blank file).
  • Portfolio rollup: all 15 properties, revenue / RGI / variance vs plan on one owner screen. This is the screen that sells the product to other operators.
Bottom line: the hard, differentiated part (STR-anchored forecasting with share targets) already exists and works. Landing the feature is mostly plumbing: budget entry, lock, versions, roles, and a clean annual workflow. That set turns the December Google-sheet ritual into the product, and it is the same set that makes it sellable beyond THM.