appnqjDpqDniH3IRllocalStorage key _dlr_patlocalStorage key _dlr_dashcache_v1The Leadership Dashboard is a client-side HTML/JavaScript application. It runs entirely in the browser, connecting directly to Airtable via its REST API and to Gmail via a deployed Google Apps Script web app. There is no back-end server.
On load, the dashboard fetches 9 Airtable tables in parallel: Accounts, Fixed Costs, Tenancies, Transactions, Rental Units, Tenants, Categories, Sub-Categories, and Businesses. It also fires non-blocking fetches for invoices, Gmail sync, and Fintable status.
Those nine are not the whole list. The same load also reads Strategic Projects (tblHrpTMd5LNYn8v1, js/dashboard.js:185), Tasks and Prospects for the KPI compute (:487, :458), Team Members and AI Agents for the agent cards, and AI Recon Audit for the accuracy score. Opening the page also writes to Airtable, in two places: the Strategic KPI automation below, and the recon audit log in section 6.
Some Strategic Projects carry their own KPI compute code. It is written by hand and stored in the KPI Compute Code field on the project record in Airtable. Opening the dashboard runs that code in your browser and saves the answer back to Airtable. The page is not read-only.
loadDashboard() calls loadStrategicKpis() as its first action (js/dashboard.js:929), which reads the Strategic Projects table (:110, :185).runAutomatedKpis() (:514). Projects with a close date are skipped, so a closed quarter cannot drift away from its snapshot (:519).new Function() (:429). A safety check blocks obvious dangerous wording first (:410), and the note beside it in the code is honest that this is a speed bump rather than a wall. Only put compute code in that field if you wrote it yourself.:611-617): KPI Current, KPI Last Updated, KPI Last Updated By, and a KPI Detail JSON blob holding the workings, capped at about 95KB.loadDashboard() again, so the write repeats all day while the tab is open. The save is fire-and-forget: if Airtable rejects it, the only sign is a line in the browser console (:618), and nothing on screen tells you it failed. If the compute itself fails, the project row shows a red Compute failed badge (:709) with the reason on hover.localStorage (key _dlr_pat) and persists across browser sessions until you log out or clear storage.localStorage (not sessionStorage), so you stay logged in even after closing the browser. To log out, use the logout button or clear your browser’s local storage.api.airtable.com. No third-party server is involved.The dashboard uses a stale-while-revalidate caching strategy to provide instant page loads. On every successful data load, the full dataset is saved to localStorage under the key _dlr_dashcache_v1.
| Behaviour | What Happens |
|---|---|
| Cache hit (under 24 hours old) | The dashboard renders immediately from cached data. A blue Refreshing… badge appears (with the cache age, e.g. “showing data from 3h ago”). A fresh fetch runs in the background; when complete, the display silently updates and the badge disappears. |
| Cache miss or older than 24 hours | The loading overlay is shown while data fetches from scratch. No stale data is displayed. |
| Background refresh fails | The badge turns red with “Couldn’t refresh — showing saved data”. The cached data remains visible. |
| Auth failure | Cache is cleared and the login screen is shown. |
formatAge function rounds minutes, hours, and days. Cache is managed by loadDashCache, saveDashCache, and clearDashCache in js/dashboard.js.The Operations Hub uses a fixed left sidebar for navigation. Each page also has a standalone URL for deep-linking and sharing.
| Page | Purpose | Standalone URL |
|---|---|---|
| Leadership Dashboard | Financial overview, portfolio, cash flow, AI commentary | index.html#overview |
| CFVs | Cash flow void detection, chase tracking, comments | index.html#cfv |
| Accounts Payable Variable | Gmail invoices, AI matching, mark-as-paid, business assignment | index.html#invoices |
| Profit & Loss | Transaction-based P&L reporting | index.html#pnl |
| Inbound Comms | Email triage, AI labels, follow-up management | follow-up.html |
| Property Compliance | GSC, EICR, insurance status tracking | compliance.html |
| Site Map & Links | Page registry, version tracking, SOP sync status | index.html#sitemap |
switchTab(), which updates the URL hash and fires a data refresh for that page.The financial overview section shows five KPI cards. All figures are calculated from live Airtable data.
| Card | How It’s Calculated | Notes |
|---|---|---|
| Opening Balance | Sum of accGBP from Santander record (rec3LiEiifomEHlvy) + TNT Mgt Zempler record (recsR9QhRKYwgV8oP) |
Shown as a single £ total with per-account breakdown in subtitle |
| Monthly Income | Two figures shown as a range: amber = In Payment only; green = In Payment + CFV Actioned. Only tenancies where tenant status is active are included. | Click to expand — shows per-tenancy breakdown sorted by due day |
| Monthly Costs | Sum of costExpected for all active fixed costs (where costInactive is not set) |
Click to expand — shows per-cost breakdown sorted by due day |
| Monthly Operating Cushion | Monthly income minus monthly property fixed costs (active costs whose Business is Real Estate). Personal and Operations Director costs are not subtracted; they stay on the Monthly Costs card. Two figures: amber = In Payment income minus property costs; green = (In Payment + CFV Actioned) minus property costs | Range reflects uncertainty from CFV Actioned tenancies. Distinct from gross profit (revenue − COGS) and operating profit (revenue − fixed − variable costs). |
| Operating Cushion Margin | Operating Cushion ÷ Monthly Income × 100, shown as a % range (amber to green) | Calculated independently for low and high operating cushion figures |
expandableCard() helper from js/shared.js. The chevron (▶) rotates when open.js/config.js)| Constant | Value | Purpose |
|---|---|---|
WAGES_TARGET_GBP | £650/month | Wages spend budget |
MAINT_TARGET_GBP | £1,700/month | Maintenance spend budget |
UTILITIES_TARGET_GBP | £200/month | Utilities budget |
COMPLIANCE_TARGET_GBP | £1,000/month (£250 from 1 January 2027) | Compliance certificates budget |
CFV_TARGET_GBP | £750/month | Non-payment allowance |
CLEAR_PROFIT_TARGET | £10,000/month | The income floor: your income from property after all variable costs |
variableCostReserve | £4,300/month | The property variable budget: RE_VARIABLE_BUDGET_GBP, the sum of the five lines above |
requiredOperatingCushion | £14,300/month | The cushion the income floor needs: the floor + the variable budget (calculated). A floor, not the Q4 target |
Eight cards, worked out on every load. Nobody types a number. The rules are in js/re-kpis.js (tests: tests/re-kpis.test.js); the named units, tenants and targets are RE_Q4 in js/config.js.
| Card | How it is worked out |
|---|---|
| Income from property (plan) | Property cushion (plan) less the £4,300 variable budget. |
| Income from property (cash) | Property cushion (cash) less every other property payment in the same month (payments tagged Real Estate with no cost record: wages, maintenance, utilities, compliance, other). |
| Property cushion (plan) | Rent of tenancies that read In Payment, less active costs whose Business is Real Estate. |
| Property cushion (cash) | Rental Income received, less payments tagged Real Estate that are linked to a cost record. The last full calendar month, with the rolling 31 days and the Q3 average beside it. A rolling 31 days can take in two of a monthly payment that lands at both ends (on 14 Oct 2026, two mortgages paid on 14 Sep and again on 12 and 13 Oct, £1,411), so the headline is the last full month (Kevin, 14 Oct 2026). Both cash cards are held to the same 31 December marker as their plan card: the gap between plan and cash is the leak. |
| Named units with a signed tenant in | Each named unit counts when a tenancy that has started and not ended is linked to it. One unit is set to count only once someone other than the tenant moving out of it lives there. |
| New rent in payment from the named tenants | Rent of the named tenants and units, counted only while the tenancy reads In Payment. A replacement tenant anywhere else is never counted. |
| Personal net cash flow | The Wealth page's own figure (buildMonthlyCashflow) for the last full month, with the 3-month average beside it. |
| Self-managed properties fully compliant | A property counts when gas (or the No Gas tick box on the property), the electrical inspection and the insurance are each in date and have a file attached. |
When a card stops updating. A card shows a red Not updating badge and the reason when its data did not load, the bank feed is more than 4 days old, no rent is in the window, or a named unit or tenant is missing. An amber Check badge means the figure will move (payments not yet filed) or needs a look; the reason is written beside the badge. The bar on a card always measures progress to the committed target, and the card says so. The health bar check Q4 real estate KPIs updating turns red with it. The three project KPIs are also saved to their projects; the daily data check q4-real-estate-kpis-are-current fails if any of them has not been saved for 2 days.
Above the financial KPI cards, the reconBar section displays two cards side by side:
txReconciled is false and txAccountAlias matches one of the monitored accounts (Santander or TNT Mgt Zempler). Each row shows date, label, and amount.triggerReconciliation(this), which runs the AI matching engine from js/reconciliation.js. A status span (id="reconStatus") shows progress.TABLES.reconAudit), one row per approved transaction where the AI made a suggestion. getReconAccuracyStats() returns a cached copy for an instant paint; refreshReconAccuracyStats() runs in the background on every dashboard load and pulls rows from the last 31 days only (server-side filterByFormula, so the payload stays small). Each write calls pruneStaleAudit() which deletes rows older than 35 days — this keeps the table ~1 month of data so reads never slow down. On first load after this change ships, migrateLocalReconLog() copies any historical entries from the legacy _recon_accuracy_log localStorage key into Airtable and then clears it.From the Rental Units table (tblM3mZCR5kiEdWMj):
unitPropName lookup field).unitStatus does NOT contain “void”.unitStatus contains “void” (case-insensitive). Expandable: shows unit display name.From the Tenancies table, filtered to active tenant status (tenStatus + isTenancyActive):
tenPayStatus = In Payment. Sorted by tenDueDay asc. Expandable with surname, ref, rent, due day.tenPayStatus = CFV. Amber text.tenPayStatus = CFV Actioned. Amber text.After the tenancy cards, the dashboard checks for potential CFVs not yet flagged in Airtable. The logic:
tenPayStatus = “In Payment” and active tenant status and rent > 0:daysOver = days since the current month’s due day (0 if not yet due).daysOver ≥ CFV_TOLERANCE_DAYS (= 2 days) AND tenPaidThisMonth is falsy AND no cfv_dismissed_[tenancyId] key in localStorage…If any potential CFVs are detected, an amber banner is inserted below the tenancy cards: “N potential CFVs detected — click to review”. Clicking the banner calls switchTab('cfv') to navigate directly to the CFV tab.
cfv_dismissed_[id] key set in localStorage) is excluded from the banner count. The CFV tab itself has separate dismiss logic. To clear a dismissal, remove the key from localStorage or wait for it to be cleared on “In Payment” status reload.This section compares actual spending over the last 31 days against monthly budget targets. Transactions are filtered to the 31-day window using txDate and matched to sub-categories by sub-category record IDs in the REC constants.
| KPI Card | Data Source | Budget | Traffic Light |
|---|---|---|---|
| Rental Income (31d) | Transactions with sub-category = REC.subRentalInc (recI8yCstyDP1Nd4b) |
No budget target (shown as actual) | Green (income) |
| Maintenance Spend (31d) | Transactions with sub-category = REC.subMaint (recWomXYQ3XTgMdrr). Absolute value of txReportAmount. |
£1,700 (MAINT_TARGET_GBP) |
Green < budget, amber ≤ budget × 1.1, red > budget × 1.1 |
| Wages Spend (31d) | Transactions with sub-category in REC.subOpexLabour or REC.subCOGSLabour. Absolute value. |
£650 (WAGES_TARGET_GBP) |
Same traffic light logic as maintenance |
| CFV Exposure | Sum of tenRent for all tenancies with status CFV or CFV Actioned (active tenants only) |
£750 (CFV_TARGET_GBP) |
Same traffic light logic |
| Cushion for the £10,000 income floor | Property cushion from In Payment tenancies (their rent less property fixed costs) vs the £14,300 the income floor needs. Rent from CFV Actioned tenancies is not counted: it is not being paid. This is a floor, not the Q4 target, which sits on the Property cushion (plan) card. | £14,300 (requiredOperatingCushion: the £10,000 floor + the £4,300 variable budget) |
Green if at or above the floor, amber if below |
Built by buildCashFlow() in js/cashflow.js. Projects daily inflows and outflows for 31 days from today’s opening balance.
tenRent, tenDueDay, and tenPayFreq.tenantPayType contains “Universal Credit” are flagged as UC via the tenancyIsUC map.tblx5kvhzNEI5TFlS) are loaded with costDueDay, costFrequency, and costDueDateNext.The table has seven columns. There is no Net column (js/cashflow.js:719-726).
| Column | Description |
|---|---|
| Date | Calendar date for the row |
| Opening | Balance at the start of the day, with any earlier recommended withdrawals already taken off |
| In | Money in for the day, leaving out anything already reconciled or unticked |
| Out | Money out for the day, including the weekly commitments described below |
| Closing | Opening + In − Out − Withdraw. Carries forward as the next day’s Opening |
| Withdraw | Cash the withdrawal advisor says is safe to take that day |
| Account | Which accounts the day’s items sit on |
All the money columns are read from the same worked-through series (waProjected, js/cashflow.js:712-714), not from the raw Airtable rows, so each row reconciles exactly: Opening + In − Out − Withdraw = Closing. The table prints that same line under its totals row (:770).
The forecast is not a plain projection of Airtable data. Two things are applied on top of it before the table is drawn.
waDefaultCommitments()). It is not held in Airtable. It lives in this browser only, under the localStorage key _wa_settings (:1192). Edit the amounts and days in the controls above the table. A different browser, or a cleared cache, falls back to those defaults.:517-552). It only takes what still leaves the safety floor intact on that day and on every day after it, after holding back the rest of the variable budget: £3,650 a month for maintenance, compliance, utilities and the non-payment allowance, spread evenly over the 31 days (wages are already in the weekly commitments). That money stays in the Closing column; only the withdrawals are smaller (Kevin, 14 Oct 2026: it read £23,950 when £20,300 left the budget covered). Once marked, the withdrawal is subtracted from every later Opening and Closing (:546-549), so the Closing balance you are reading already assumes you took that cash. The green Safe to withdraw (31-day cycle) figure above the table is the total of them (:629).Where the safety floor comes from: the largest single expected payment in, times 30%, scaled by how late payments have actually been running (analysePaymentLag(), :502-508), rounded up to the nearest £50 and never below £500. You can type over it in the floor box, which is also stored in _wa_settings.
:429), split between Santander and TNT Zempler when the two parts genuinely add up to the total (:519-524). Row 1 of the table shows the balance box above the table, which you can type over (:456). Once edited, your figure drives the whole forecast. A mismatch warning only appears when the two are more than £200 apart (:579), so a smaller gap passes with nothing said.The AI commentary section (id="aiCommentary") is generated in renderDashboard() using live KPI data. It covers six titled sections:
Below the AI commentary the dashboard works out how to split one payment across the cards. It is a single-payment allocator, not a weekly schedule. There is no Friday timetable and no £750 buffer any more. The card list is built inline in renderDashboard() (js/dashboard.js:1950-1990) and the split is redrawn by recalcCCStrategy() (:2046).
| Card | What counts as owed | Payment due day |
|---|---|---|
| American Express | The balance if it is positive, otherwise nothing (:1958) | 28th |
| Santander Credit Card | The balance if it is positive, otherwise nothing (:1959). The old £5,500 limit-minus-available sum is gone. | 14th |
| Lloyds Credit Card | The size of the balance ignoring the minus sign (:1957) | 21st |
Any card with nothing owed drops out of the list entirely (:1966).
:2049). This is the avalanche method: pay the minimum on everything, then put all the rest against the dearest card.:2054). If your figure is below the total of the minimums, the total of the minimums is used instead (:2052).:2055-2059).:2077-2085).:1978-1988). It averages those, divides by the balance and multiplies by twelve. If it finds none, the card shows 0% (no interest detected) and sorts last, even if it is really the dearest card you hold. The minimum payment follows the same fork: 1% of the balance plus the average interest where interest was found, otherwise a flat 2.5% of the balance, and never less than £25 (:1989).ReKpis.debtPaydown, drawn by renderCreditCardSummary()). Until 14 Oct 2026 it divided by the property surplus before the variable budget and your living costs, and said £24,165 of cards would clear in about 2 months. If the Wealth figures or the Debt pot share cannot be read, the panel says so and gives no time.The standalone Balance Calculator has gone, along with its own opening balance box and its Select All, Deselect All, Inflows Only and Outflows Only buttons. The what-if tool now sits inside the cash flow forecast itself: open any day in the table and every expected item has a tick box beside it (js/cashflow.js:670-673 for money in, :681-684 for money out).
toggleCFExclusion(), :1148).buildWhatIfLine(), :1159-1179). It only appears once something is unticked.localStorage under the key _cf_exclusions (:1131, :1155), not in sessionStorage, so a reload does not clear them. An untick is only dropped once its date has passed (:1137-1140). Anything you untick today keeps real income or real costs out of the forecast, quietly, for as long as its date is still in the future. If the forecast looks too good or too bad, open the days and look for unticked rows, or clear the _cf_exclusions key.| Parameter | Value | Purpose |
|---|---|---|
| Look-back | 5 days before expected date | Catches early payments |
| Look-ahead | 5 days after expected date | Catches late payments |
If the transaction’s Tenancy link points at this tenancy, that settles it and nothing else is checked. A transaction linked to a different tenancy is barred from clearing this one (js/cashflow.js:132-142, :155).
Two or more keywords from the tenant name or reference appear in the transaction description. Highest confidence.
One keyword plus an amount within 5p of the expected rent.
One keyword plus an amount within 30% of expected rent, which covers letting agent deductions.
There is no amount-only match any more. Every path needs at least one word in common (:161-174). A matching amount on its own is not evidence the same tenant paid: several tenancies share the same rent figure, and matching on amount was clearing the wrong tenancy’s forecast (:128-131, :175).
| Parameter | Value | Description |
|---|---|---|
| Refresh Interval | REFRESH_INTERVAL = 15 minutes | Timer set after each successful data load via setInterval(smartRefresh, REFRESH_INTERVAL) |
| Idle Threshold | IDLE_THRESHOLD = 15 minutes | User must be idle for 15 minutes before an auto-refresh fires |
| Activity Tracking | click, keydown, input events | Each event updates lastUserActivity timestamp |
| Deferred Refresh | If user is active | Sets refreshPending = true and schedules an idle check; fires as soon as user has been idle 15 min |
loadDashboard().script.google.com and open the existing project (or create new).markPaid actions.GMAIL_SCRIPT_URL in js/config.js.js/config.js. Only update it if you re-deploy the script to a new URL.tenPayStatus = “In Payment” or “CFV Actioned”, and that their linked Tenants record has an active status. Both conditions must be met for a tenancy to appear in income calculations.CLEAR_PROFIT_TARGET + RE_VARIABLE_BUDGET_GBP = £10,000 + £4,300 = £14,300. If the displayed value differs, check js/config.js for the budget constants.js/cashflow.js:161-174). Links: if the transaction is linked to a different tenancy in Airtable, it is barred from clearing this one (:155). Check the date, the description and the Tenancy link on the transaction.tenPaidThisMonth (a formula field in Airtable) and the 2-day tolerance. If the formula is not updating, refresh Airtable or check the formula definition. The banner disappears as soon as tenPaidThisMonth is truthy or the payment status moves off “In Payment”.markUserActive().Since 9 Oct 2026 every AI card sits in its own AI Team section, below the 31-Day Operational Metrics. Since 15 Oct 2026 it opens with one panel that replaced the Agent Work, Defects, Bottleneck and Fix of a Fix cards. The same day it was made simpler, so you can see at a glance whether the AI team works and whether it improves week on week. The Mac works all of it out (scripts/ai_team_health.py, the Estate Status row ai-team-verdict, every 10 minutes); the page only draws it.
| Part | What it shows |
|---|---|
| The answer (top right) | Green "Working well", amber "Getting better", amber "Not getting better", red "Getting worse" or grey "Can't tell", with one line saying why. |
| Things needing a fix | One number: the real problems right now, against last week's number. "At least" when a check could not be read, and the check is named. |
| Weekly bars | One bar a week (Monday to Sunday), oldest on the left, up to 8 weeks. Shorter is better. Until there are two weeks it says when the bars start (15 Oct 2026). |
| Three lights | Work is flowing, Something is broken (or Nothing is broken), It can keep going. A red or amber light names what is wrong in a few words. Tap a light to open its checks. |
The checks behind each light (tap a check to see its rule, the tasks or jobs behind it, and where the number came from):
| Light | Checks |
|---|---|
| Work is flowing | Emails are getting cleared · Responses are getting written · Everything's moving · No bottlenecks · Approved work gets carried out |
| Something is broken | Every agent is working · No job is broken · No bugs or errors · The data is accurate · Nothing's getting missed |
| It can keep going | Agents are on top of their work · Your queue is under control · Drafts are right first time · Enough allowance to finish the week |
What counts as a thing needing a fix: tasks stuck with nothing blocking them, every blocked task (a stuck task that gets blocked still counts, so the number never falls with nothing fixed), approved work not done in 24 hours, idle agents, failing or blocked jobs, wrong data checks, things missed, emails over 2 days old, email tasks waiting for a draft, approval cards over 2 days old, and 1 for any Claude allowance pause this week. The open code-problem backlog and the two rates (work done against new, drafts right first time) never add to it; they turn their light amber or red instead. A task, job or email that two checks both count is counted once.
The answer, in order: red "Getting worse" when a light is red that was not red at the end of last week (or whose colour last week is not on record), or there are more things to fix than last week; grey "Can't tell" when more than two checks cannot be read or the number is "at least"; green "Working well" when no light is red, no light got worse since last week, every check was read and there are 5 things or fewer; grey "Can't tell" when there is no number from last week yet; amber "Getting better" when there are fewer things than last week and no light got worse; amber "Not getting better" otherwise. A red light always shows red and is named under the answer, even when the number falls.
Trust guards: a check whose source cannot be read, is missing or is out of date is grey, "Can't tell"; it is never shown green, and the number becomes "at least". A check that read red and cannot be read now keeps its light red. "Everything's moving" leaves out blocked tasks, which "No bottlenecks" counts, so one task is never counted twice. An answer the Mac worked out more than two hours ago turns the answer, the lights and the bars grey, "Not updated since …", and a row the Mac could not build shows its reason instead of its last answer. The health bar's "AI team verdict read from the Mac" check says the same. The old cards' numbers (the agent work split, the defect split, blocks by kind and the fix-of-a-fix rate) sit inside the checks they explain.
Below the panel, under the heading North star: how much work AI does, two cards measure progress to getting up to 90% of repeatable operational work done by AI agents. The two agent cards follow under The agents and your approvals.
| Card | What it shows |
|---|---|
| AI Agents | How many agents are live and testing, and how much of their work is waiting for an approval. |
| Agent Approvals | Work waiting for a yes right now, plus each agent's accuracy record per type of work. |
| Work Done by AI | The share of completed work (measured in time, not task count) done by AI over the last 30 days. Target: 90% of repeatable operational work. |
| AI Time & Money Saved | The same work expressed as hours handed to AI and the labour cost that saved, over the last 30 days and since AI go-live (1 Jun 2026). Includes a "doing the work of X of a full-time person" line and a trend against the 30 days before. |
What counts as AI work (both cards use the same rules): a task completed with an AI agent on the Team Member field, or work an agent prepared that was approved first time. Work that was sent back for changes never counts as AI work, whatever the links say, because a human had to redo it.
How the money figure is worked out: every completed task carries a time estimate (how long a person would need). AI hours are those estimates summed for AI work, then valued at £17.50 per hour: the UK office admin wage plus employer National Insurance and pension. The rate and the go-live date live in js/config.js (AI_LABOUR_RATE_GBP_PER_HOUR, AI_WORK_EPOCH), so changing them is one edit. Figures are whole pounds; pence on an estimate would be false precision.
Trust guards: both cards publish the share of completed tasks carrying a time estimate and warn below 80% (a task without an estimate is invisible to the sums). An empty query shows "no data", never a fake 0% or £0. The health bar's "AI Time & Money Saved card computed" check confirms the card loaded on every sync.
| Version | Date | Changes |
|---|---|---|
| 2.151 | 15 Oct 2026 | The AI Team panel made simpler: one answer, one number ("Things needing a fix") against last week, weekly bars and three lights (Work is flowing, Something is broken, It can keep going). The fourteen checks open from the lights, unchanged. A red light always shows, even when the number falls. |
| 2.150 | 15 Oct 2026 | The AI Team section opens with one "Is the AI team healthy?" panel: fourteen questions in three groups, each with a colour, a short answer and last week's number, under one verdict. It replaced the Agent Work, Defects, Bottleneck and Fix of a Fix cards; their numbers moved inside the lines. A line that cannot be read is grey and named. |
| 2.147 | 14 Oct 2026 | Money figures audit against Airtable. Four figures corrected: the operating cushion card now measures In Payment tenancies against the £14,300 income floor (it counted CFV Actioned rent and called the floor a target); the cash cushion and cash income cards headline the last full month (a rolling 31 days counted two mortgages twice); Safe to withdraw holds back the £3,650 of the variable budget not already in wages; credit card “months to clear” runs on personal net cash flow times the Debt pot share. Stale wages, budget and allowance figures in this guide corrected. |
| 2.140 | 9 Oct 2026 | New AI Team section: Agent Work, Defects, Bottleneck and Fix of a Fix cards, with the four existing AI cards moved into it from the 31-Day Operational Metrics. |
| 2.94 | 3 Sep 2026 | Documentation-drift corrections. Added Strategic KPI Automation (the dashboard runs compute code held in Airtable and writes KPI values back on every load and every refresh) and corrected the list of tables touched. Rewrote the credit card section against the live avalanche allocator, including the estimated APR and the best-case “months to clear”. Replaced the forecast column table with the seven real columns and added the Withdrawal Advisor and weekly commitments. Replaced the retired Balance Calculator with the in-row what-if tick boxes and corrected the storage claim (localStorage, not sessionStorage). Removed the retired amount-only inflow match and added the linked-tenancy priority. |
| 2.93 | 28 Aug 2026 | Added AI Workforce & Labour Saved section covering the four agent cards, including the new AI Time & Money Saved card (hours + £ saved, 30-day and since go-live, FTE framing, trend). |
| 2.9 | 16 Apr 2026 | Updated budget values (wages £1,500 not £3,000; required GP £16,000 not £17,500). Added: stale-while-revalidate cache, income/profit range display, AI Reconciliation Accuracy card, Run Reconciliation button, 31-Day Operational Metrics section, CFV alert banner, budget progress bars with target markers, credit card repayment plan detail, 9 Airtable tables fetched. Corrected: auth stored in localStorage (not sessionStorage). |
| 2.3 | 12 Apr 2026 | Added Platform Navigation, Balance Calculator, Smart Refresh, mobile responsive, Google Apps Script setup sections. |
| 2.0 | Mar 2026 | Restructured into modular JS files. Sidebar navigation replaces horizontal tabs. |