BOS v3 — RUN PLAN (money-brain, fixed + staged)
Last updated: 2026-07-01 · code pushed to script
1_cgriwCQtZyQWAiDjeOpfa5T9-kFTkb6sXzLg0kaTKB2eG186O6XoMWo(bound to v1 sheet1L_rxCSOncM6WtqCYaEbooNdxiXbfOi_Sfm7k0IAAsBo) · nested repo commit2719748
Source:HookStreet-Business-OS/sheets/src/v3-obligations.js+src/v3-webapp.js
What was fixed (2026-07-01)
- Sign flip (credits → fake debt). Raw
($500.00)/ negative balances no longer silently absolutized — the balance still stores positive, but the row yellow-flagsCREDIT-SIGN INPUTfor hand-review. - Installment overstatement (runway killer). Legacy col F ("Min Due / Scheduled Pmt / Installment Total") no longer maps uniformly to
min_due. Installment rows (type-category = Installments: Kids / Life Ins / Services, or notes mention "installment") route col F tototal_amount(col D);min_due(col I) becomes a formula =total_amount / inst_countthat reads 0 until you enterinst_count(col S). These rows yellow-flagINSTALLMENT: ... enter inst_count. - Blind zero interest.
monthly_interest(col X) now showsNEEDS DATAwhen APR or balance is blank, instead of a silent 0.
⚠ Cardinal rules (unchanged)
- V3_GO is NOT idempotent. It re-migrates fresh from legacy and overwrites every hand-fix in Obligations_v3. Run it ONCE per build; after that only
V3_REFRESH_DASHBOARD/V3_REFRESH_CASHFLOW. - The legacy "Monthly Obligations" tab is READ-ONLY to v3 — never written.
- No triggers, no emails involved in any of this.
Sacrificial-first run procedure (do it in this order)
- Duplicate the sheet. Drive → right-click "Monthly Obligations" (v1,
1L_rxCSOnc...) → Make a copy. The copy carries the bound script with it. - Open the COPY's script editor (Extensions → Apps Script — verify the title says "Copy of…" so you're not in the live script).
- Run
V3_GOthere. Grant scopes if asked (it's the copy — safe). - Verify on the copy:
-Obligations_v3row count ≈ legacy active rows; yellow rows have 🚨 notes explaining exactly what they need.
- Installment rows (Kids / Life Ins / Services): col F money landed in total_amount (D),min_due(I) shows-(0) untilinst_count(S) is filled — then it auto-derives.
- Any card you know carries a credit balance: flaggedCREDIT-SIGN INPUT, not shown as debt.
-monthly_interest(X) saysNEEDS DATAon blind cards, numbers elsewhere.
-Cashflow_v3columns B–D are sane monthly numbers (no installment totals repeating every month, no#VALUE!).
-Dashboard_v3KPIs render; "Due this month" is no longer inflated by installment totals. - Only after the copy passes → open the LIVE sheet's script editor and run
V3_GOonce. - Hand-fix the yellows on live: enter
inst_count/inst_paid/inst_startfor installments, APRs, pay_from TBDs, confirm any CREDIT-SIGN rows, split any "1, 15" rows into two. - From then on:
V3_REFRESH_CASHFLOW/V3_REFRESH_DASHBOARDonly. Never re-runV3_GO(it wipes step 6). - Trash the sacrificial copy when done (Drive trash, not rm).
The read-only JSON endpoint (STAGED, not deployed)
Code is pushed (src/v3-webapp.js), but this script project has never had a web-app deployment (only @HEAD exists) — creating the first one is a decision Sam makes, not something a session auto-does.
To go live (after v3 has run on the live sheet):
1. In the live script editor, run V3_SETUP_API_TOKEN() once → copy the token from the execution log into the Worker's secret store (never git).
2. cd HookStreet-Business-OS/sheets && npx clasp deploy → record the new deployment ID as the LIVE id (all future updates: npx clasp deploy -i <that id> per feedback_clasp_redeploy_breaks_webapp).
3. Call: https://script.google.com/macros/s/<DEPLOYMENT_ID>/exec?fn=obligations&token=<TOKEN>
Response shape:
{ "ok": true, "asof": "2026-07-01T18:00:00-04:00",
"due_next_7": [{ "name": "...", "amount": 123.45, "due": "2026-07-05", "pay_from": "Chase 5609" }],
"needs_you": [{ "name": "...", "why": "NEEDS APR · status: Urgent" }],
"totals": { "monthly_min": 0, "monthly_interest": 0 } }
Errors: {ok:false, error: 'v3_not_run' | 'unauthorized' | 'token_not_configured' | 'unknown_fn' | 'schema_mismatch: ...'}. Manifest webapp block = USER_DEPLOYING / ANYONE_ANONYMOUS — the token is the only gate, so treat it like a password.
What remains for the Worker wiring
- Decision + first web-app deploy (steps above).
- ops-api: store the token as a Worker secret, add a fetch of the
/execURL, surfacedue_next_7+needs_youin the morning brief / portal money tile. - Note the harvest schema (
docs/COMMAND_CENTER_HARVEST.md) remains the reference for the eventual D1 obligations model — v3 naming (total_amount,min_due,inst_count) keepsminimum_paymentvsmonthly_paymentdistinct per that doc.