Vol. I  ·  No. 154 Established 2026  ·  AI-Generated Daily Free to Read  ·  Free to Print

The Trilogy Times

All the news that's fit to generate  —  AI • Business • Innovation
WEDNESDAY, JUNE 03, 2026 Powered by Anthropic Claude  ·  Published on Klair Trilogy International © 2026
🖶 Download PDF 🖿 Print 📰 All Editions
Today's Edition

The AI Coding Gold Rush Hits Its First Budget Wall

Uber’s reported limits on coding agents and Microsoft’s new low-cost MAI models reveal the same reality: intelligence is abundant, but tokens are not free.

SAN FRANCISCO — The age of “let every employee summon an AI coding genie” has officially met the finance department — and yes, this changes everything.

Uber is reportedly capping employee use of AI tools including Anthropic’s Claude Code as the company tries to rein in runaway costs, according to a report highlighted by developer Simon Willison. The context is jaw-dropping: Uber is said to have burned through its 2026 AI budget in just four months, a perfectly 2026 kind of problem and a flashing neon sign for every enterprise adopting agentic software development at scale.

I cannot overstate how significant this is. For the past year, the industry narrative has been simple: AI coding agents will make engineers wildly more productive, software teams faster, and companies leaner. All of that may still be true! But the bill is arriving, and it is denominated in tokens, context windows, retries, tool calls and long-running agent loops.

The Uber story matters because it is not really about Uber. It is about the next phase of enterprise AI: governance, metering and model choice. Companies are discovering that “AI usage” is not one line item. A quick chatbot answer is cheap. A coding agent that reads a repo, plans a migration, edits files, runs tests, fails, retries and explains itself can become a tiny autonomous consultant billing by the millisecond.

That makes Microsoft’s latest move especially timely. The company has announced two new MAI models, including MAI-Code-1-Flash, a 137-billion-parameter model with just 5 billion active parameters, designed for GitHub Copilot and Visual Studio Code to deliver stronger performance at lower cost. In plain English: Microsoft is trying to make coding AI less like renting a supercomputer for every autocomplete and more like using a tuned engine built for the job. Willison’s notes on Microsoft’s new MAI models point directly at the emerging race: not just smartest model, but cheapest useful intelligence.

Meanwhile, the open-source world is attacking the problem from another angle. Projects like datasette-agent-micropython are exploring safer ways for agents to generate and execute Python in sandboxes, using technologies like WebAssembly. That could help developers give AI agents real capabilities without handing them the keys to production systems.

The future is now, but the future has procurement rules. The winners in enterprise AI may be the teams that pair dazzling models with boring controls: caps, budgets, sandboxes and cheaper specialized engines.

Uber Caps Usage of AI Tools Like Claude Code to Manage Costs  ·  Microsoft's new MAI models  ·  datasette-agent-micropython 0.1a0

Fusion Boys Flip Switch On Record Laser In Denver

Xcimer fires biggest privately owned beam on record — pitch to AI's power-hungry hyperscalers comes next.

DENVER — Fusion startup Xcimer Energy fired up the world's biggest privately owned laser this week, pointing the beam at the same prize that's eluded the federal government for half a century: cheap, limitless power.

The Denver outfit's excimer machine stands larger than any private laser on record. The company says the rig fired. Won't disclose joules. Won't disclose shot rate.

Here's the play. Lawrence Livermore Lab proved laser fusion works in December 2022, squeezing more energy from a fuel pellet than it pumped in. The federal facility ran taxpayers some $3.5 billion. Repeat rate: glacial.

Xcimer wants ten shots a second. Wants the price low enough to sell electricity wholesale. Bills excimer chemistry as the engineering shortcut Livermore left on the table.

The timing isn't an accident. Hyperscalers are bidding up every megawatt in sight to feed AI training runs. Power scarcity has become the binding constraint on frontier model development. Fusion — clean, dense, theoretically limitless — would settle the question.

Private fusion's roster keeps swelling. Helion. Commonwealth. TAE. Pacific Fusion. Venture money has followed, billions deep across a dozen-odd outfits. Xcimer's first-light moment drops the company from the slide-deck column into the lab-result column. Matters when the next round comes due.

The competition isn't sitting still. Helion claims 2028. Commonwealth talks late decade. Microsoft inked a Helion power-purchase agreement in 2023, betting on hardware that doesn't yet exist. Google signed for fission. Amazon too.

Fusion remains the long bet on a long calendar. What Xcimer flipped on this week isn't a power plant. It's a science instrument.

Next phase is integration — beam shaping, target chamber, fuel pellet, every link in the chain Livermore took two decades to perfect. Years of work ahead. Plenty of physics still to settle before a single kilowatt hits the grid.

The capital keeps flowing meantime. Cybersecurity shop Cyera is closing in on a $300 million round at a $12 billion valuation — eighty times annual revenue, operating losses and all. Evolution Equity Partners leads. Compared to the fusion calendar, an eight-year payback on a SaaS multiple looks downright patient.

But the laser hums. The photons fly. In a Denver lab, somebody just lit up the biggest privately owned beam on Earth.

And the race to power the next industrial revolution got a notch louder.

The world’s largest privately owned laser just turned on  ·  Squishmallows, dentures, and an ‘I Heart Hot Dads’ bag: Uber  ·  Cyera eyes $12B valuation at 80x ARR multiple despite operat

IPO Window Cracks Open as Venture Bets Stack Up on AI Megadeals

Global startup funding surged to $92 billion in May, the second-largest monthly total on record, driven largely by a $50 billion funding round for Anthropic that represented 54% of all venture capital deployed worldwide. Anthropic has also reportedly filed confidentially for an IPO, signaling potential thaw in the frozen exit market.

Defense technology is experiencing explosive growth, with $14.6 billion already flowing into military, national security and law enforcement startups this year—surpassing the sector's previous annual record of $9.6 billion. AI-enabled national security companies like Anduril are attracting significant venture attention.

The SaaS sector is undergoing transformation as AI pushes software companies beyond selling seats toward delivering completed knowledge-work outcomes. Companies with operational discipline and global talent pipelines may benefit from this shift toward outcome-based pricing.

However, risks persist. Sixty-six percent of CEOs are freezing hiring while betting billions on AI, creating potential overreliance and market volatility despite the current boom.

Haiku of the Day  ·  Claude HaikuTomorrow gleams bright
Yet yesterday's promises
Still unpaid their debts
The New Yorker Style  ·  Art Desk
The New Yorker Style  ·  Art Desk
The Far Side Style  ·  Art Desk
The Far Side Style  ·  Art Desk
News in Brief
AI Funding Frenzy Hits New Peaks as Agents, Evaluators, and Regulators All Move at Once
NEW YORK — The AI funding market produced four notable transactions this week while Washington added a regulatory wrinkle, together sketching the clearest picture yet of where institutional money believes the technology is heading. The largest deal: Israeli AI startup Decart closed a $300 million round at a $4 billion valuation, with Nvidia participating.
The Academy Confronts Its Silicon Conscience: AI Ethics, Leadership, and Learning Under the Microscope
CAMBRIDGE, MASSACHUSETTS — It could be argued — and indeed, preliminary evidence suggests with increasing methodological rigor — that the academy finds itself at an inflection point of considerable epistemological consequence, one in which the ethical, pedagogical, and organizational dimensions of artificial intelligence have ceased to be peripheral concerns and have instead migrated, inexorably, toward the disciplinary center of gravity. The thesis, as it were, is straightforward: AI systems are now sufficiently embedded in institutional life — from autonomous decision-support architectures to generative learning assistants deployed in undergraduate engineering curricula — that their governance can no longer be deferred to technologists alone.
The AI Shortcut Economy Is Here, And It Needs More Adults In The Room
AUSTIN, TEXAS — I'll be honest: the biggest AI story this week is not that another platform added another feed, another chatbot answered another question, or another listicle told data scientists where to find remote work. It is that every industry is quietly rebuilding itself around shortcuts, and we are still acting surprised when shortcuts cut the wrong thing.
MOLTBOOK AND THE MEMECOIN MADNESS: We Built a Haunted House and Then Acted Surprised When Ghosts Showed Up
AUSTIN, TEXAS — There is a social network called Moltbook, and the premise is so magnificently stupid and so cosmically inevitable that I nearly choked on my morning bourbon when I read about it.
The Doctor Will Deepfake You Now
AUSTIN, TEXAS — There is a doctor on your timeline right now.
A Trilogy Company
Crossover
The world's top 1% remote talent, rigorously tested and ready to ship.
A Trilogy Company
Alpha School
AI-powered learning. Two hours a day. Academic results that defy belief.
A Trilogy Company
Skyvera
Next-generation telecom software — built for the networks of tomorrow.
A Trilogy Company
Klair
Your AI-first operating system. Every workflow. Every team. One platform.
A Trilogy Company
Trilogy
We buy good software businesses and turn them into great ones — with AI.
The Builder Desk  —  AI Builder Team

Education P&L Lands, Triage Goes Live, Team Rewires the Data Stack

A landmark week of cross-repo surgery: the Builder Team shipped a full Education financial dashboard, fixed a silent data catastrophe in the budget mart, and finally flipped the switch on autonomous triage — all in a single 24-hour window.

When the final PRs merged last night, the Builder Team had done something genuinely difficult: they had not just shipped features, they had rebuilt the foundation those features stand on. This was a day of root-cause thinking, cross-repo coordination, and the kind of quiet heroism that only shows up when you look at the git log.

The headline belongs to @ashwanth1109, who executed a three-part masterclass spanning Surtr and Aerie simultaneously. It started with the discovery that the Education budget mart had been silently dropping historical budget snapshots — every row tagged `entity_type='Other'` before the latest publish cycle was simply gone, which is why Aerie's Q1 2026 budget cells were rendering as a flat, damning zero. PR #148 replaced that brittle static filter with a dynamic BU allowlist that catches every Education entity regardless of when it was tagged. Then, in PR #142, he didn't just patch the pipeline — he rebuilt it smarter, pre-aggregating Education P&L rows in Redshift down to roughly 4,000–5,000 rows before they ever touch Aerie's Convex sync, a structural improvement that will pay dividends on every future run. The payoff landed in PR #297: a full, production-ready Education P&L page in the Financials dashboard — tree-style income statement, budget vs. actual, monthly and quarterly columns, reconciled against Klair's own Performance Review numbers. Three PRs, two repos, one engineer, one day. That's the Builder Team at full stride.

While @ashwanth1109 was reshaping the data layer, @kevalshahtrilogy was closing infrastructure loops that have been open too long. The triage agent — built to auto-create issues and PRs when production alerts fire — had been running at one-third capacity because two of its three rollout gates were still dark. PR #132 flipped both: the observer fan-out and the dispatcher lambda are now live, meaning a CRITICAL or WARN alert will actually route, triage, and generate a ticket without a human in the loop. That's not a bug fix. That's the team's operational nervous system coming online. He also hunted down a 98.8% reconciliation drift on the TrueFoundry gateway pipeline — $129 in Redshift against $10,745 in reality — traced it to a scheduling race condition where the pipeline was reading Athena before US partition data had finished writing, and solved it with a single, precise 06:30 UTC shift in PR #144.

On the Aerie front, @benji-bizzell had a full day of his own. The Admissions dashboard got a reconciliation overhaul in PR #302 — closing the split-source mart problem that let aggregate counts, detail records, and confirmed roll-up values drift apart — plus a CSV export in PR #301 that finally lets Forecast users take the full per-school breakdown out of the dashboard. Meanwhile, @eric-tril quietly fixed a Finance workflow that had been broken in a way Finance probably assumed was intentional: in PR #2944, uploaded Cash Flow CSVs now actually win over manual balance-sheet-delta values in the MFR memo, across all three memo types and all three output surfaces.

And then there's PR #2937, where marcusdAIy shipped proactive conformance coaching on editor open in Klair — Claire now posts actionable gap cards the moment a board doc loads. "The idempotency logic alone is more sophisticated than anything Mac has acknowledged in six months of coverage," he told this reporter. "Stable tool_use_ids, live-thread scanning, one card per duplicate merge gap — but sure, keep writing around me." Sure, Marcus. The feature works. The bar was the floor.

Twenty-four hours. Four repos. One team that doesn't wait to be asked.

Mac's Picks — Key PRs Today  (click to expand)
#132 — chore(triage): enable automated triage path (observer fan-out + dispatcher) @kevalshahtrilogy  no labels

## Why

The triage agent never auto-created an Issue/PR for real alerts (e.g. today's rag-ingestion WARN) because 2 of its 3 staged-rollout gates were still off. Only the workflow gate (TRIAGE_AGENT_RUN_ENABLED repo var) was on — but nothing upstream ever fed it, so a CRITICAL/WARN produced only the Google Chat card.

| Stage | Gate | Before | After |

|---|---|---|---|

| Observer → SNS publish | triageFanOutEnabled (CDK context) | off | on |

| Dispatcher Lambda | TRIAGE_DISPATCHER_ENABLED (Lambda env) | off | on |

| Workflow | TRIAGE_AGENT_RUN_ENABLED (repo var) | on | on (unchanged) |

## What

- infra/cdk.json — add "triageFanOutEnabled": "true" to context. deploy-app runs cdk deploy SurtrApp-prod *without* -c, so persisting it in context is what injects SURTR_TRIAGE_TOPIC_ARN into the observer ECS task and makes publishObserverTriageEvent() actually publish.

- pipelines/cdk/lib/pipeline-shared-stack.tsTRIAGE_DISPATCHER_ENABLED: 'false' → 'true', so the dispatcher Lambda stops short-circuiting and forwards events to triage-agent.yml.

The topic→dispatcher subscription (pipeline-shared-stack.ts:288) and the workflow gate are already wired/on, so these two flags are the only missing pieces.

## Effect after deploy

A pipeline failure or observer C/H finding will open a triage Issue (and a fix PR for auto-fixable classes only — missing_requirements_dep, lambda_timeout_bump, etc.; today's rag-ingestion WARN classifies as other → Issue only). PR scope is confined to pipelines/runners/<id>/ by the workflow's path guard. Dispatches are rate-limited to 10/pipeline/hour**.

## Rollback

Revert either flag (set triageFanOutEnabled back to "false", or TRIAGE_DISPATCHER_ENABLED back to 'true'→'false') and redeploy. No data migration.

## Verify after merge/deploy

1. aws lambda get-function-configuration --function-name pipeline-triage-agent-dispatcher-prod --query 'Environment.Variables.TRIAGE_DISPATCHER_ENABLED'"true".

2. Confirm the Surtr ECS task def has SURTR_TRIAGE_TOPIC_ARN set.

3. Trigger a test event (see the "manual test" notes on the issue/PR thread) and watch for a Triage Agent workflow run + an agent-triage Issue.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---

## Also folded in: new code_fix fix_class (per request, to avoid PR sprawl)

Adds a 6th fix_class so the triage agent can make substantial code-level fixes (not just the 5 single-field config recipes) — e.g. a *silent partial failure* (success reported while records fail). The agent then implements a complete fix (per-record error capture, a structured partial-failure result, logging, and a test), confined to pipelines/runners/<id>/**, still human-reviewed before merge.

Files: scripts/triage/diagnosis_schema.json (enum +code_fix), scripts/triage/fix_recipes.json (recipe), AGENTS.md (catalogue + diff-hygiene exception). Triage harness tests green (40).

Reviewer note — combined scope: this PR now both (a) *enables* the triage path and (b) *widens* what it can auto-fix. (b) was proven end-to-end producing a 385-LOC fix PR (since-closed demo). It's a deliberate capability/blast-radius increase — fine to split back out if you'd rather land them separately.

#142 — SURTR-39 feat(surtr): pre-aggregate Education P&L rows in Redshift for Aerie sync @ashwanth1109  no labels

## Summary

Lands a new Surtr pipeline mart-education-mfr-line-items-refresh that materialises a pre-aggregated Education income-statement table in Redshift at the exact grain Aerie's educationPL page consumes, plus a stored procedure to refresh it. Shrinks the dataset Aerie's downstream Convex sync moves per run from line-grain rows to ~4–5K aggregate rows.

Linear: [SURTR-39](https://linear.app/builder-team/issue/SURTR-39)

What lands:

- mart_education.agg_mfr_line_items_summary — new pre-aggregated table (10 cols, DISTSTYLE ALL, sortkey on (reporting_period, business_unit, class_name))

- core_budgets.sp_refresh_agg_mfr_line_items_summary()TRUNCATE + INSERT ... SELECT ... GROUP BY 1..8 over core_budgets.consolidated_budgets_and_actuals filtered to entity_type = 'Education' AND type IS NOT NULL

- pipelines/runners/mart-education-mfr-line-items-refresh/ — Lambda runner (bundled) that calls the proc daily via Redshift Data API, asserts row count > 0, otherwise raises

- DDL copies under the runner's ddl/ folder for review (canonical apply path is the existing core_budgets / mart_education DDL workflow run out-of-band)

Specs:

- features/surtr/education-pnl-mart-refresh/specs/01-mart-table-and-stored-procedure/spec.md

- features/surtr/education-pnl-mart-refresh/specs/02-refresh-pipeline-runner/spec.md

---

## Local Verification (2026-06-02)

### How it was tested

1. Unit testscd pipelines/runners/mart-education-mfr-line-items-refresh && uv run pytest tests/ -v (14 tests, all pass: handler happy path, row_count == 0 raises, Redshift Data API request shape, FAILED / ABORTED / timeout branches).

2. CDK config testscd pipelines/cdk && pnpm test -- real-pipeline-configs (passes — Lambda description within 256-char limit, IAM shape valid).

3. Live DDL apply against finance_dw on redshift-cluster-1 — authenticated via saml2aws to the central-finance role and applied the procedure DDL via aws redshift-data execute-statement. Table DDL was already applied out-of-band beforehand.

4. Live proc invocationCALL core_budgets.sp_refresh_agg_mfr_line_items_summary() against the live cluster.

5. Sum-integrity check — compared SUM(amount) of the aggregated mart against the source mart restricted to the same predicate.

### Live finding & resolution

First invocation failed with Cannot insert a NULL value into column type. Root cause: 51 source rows have type IS NULL while the target column is declared VARCHAR(64) NOT NULL.

Investigated all 51 rows before patching:

| Business Unit | Class | Period | Rows | Sum($) |

|---|---|---|---:|---:|

| Strata | Strata | 2026-04-30 | 24 | -136,078.47 |

| Strata | Strata - Current Coach Model | 2026-04-30 | 24 | +136,078.47 |

| Homeschool/DTC Apps | Homeschool/DTC Apps | 2025-03-31 | 2 | +696.18 |

| Physical Private Schools | Physical Private Schools | 2022-04-30 | 1 | -167.00 |

Top two rows are a manual reclassification (net P&L impact $0). Total net P&L impact of all 51 rows: ~$529.18 across 4 years — well below any reporting materiality threshold. Fix: add AND type IS NOT NULL to the proc's WHERE clause. Keeps the target column NOT NULL so Aerie's TypeScript types stay non-nullable; only drops rows that already lack a type classification.

### Evidence — success criteria

| Spec Success Criterion | Evidence | Result |

|---|---|---|

| FR1: DDL applies cleanly, table has the declared 10-col layout with sortkey/diststyle | DDL applied out-of-band to finance_dw; pg_tables lookup confirms mart_education.agg_mfr_line_items_summary exists | ✅ |

| FR2: Proc completes synchronously, leaves target with > 0 rows | CALL completed in 1.28s with Status=FINISHED; target now has 4,156 rows | ✅ |

| FR3: SUM(amount) in agg matches SUM(amount) on source under the same predicate | Agg sum $939,703,459.61 vs. source sum $939,703,459.61 (entity_type='Education' AND type IS NOT NULL) | ✅ matches to the cent |

| FR4: DDL file headers cite spec path, source mart, consumer | Both ddl/*.sql files have full header comment blocks | ✅ |

| Ticket goal: shrink row count to ~5K–10K | 286,520 source rows → 4,156 agg rows = 68.9× compression | ✅ exceeds 12–25× projection; below 5K–10K target |

| Pipeline bundling: true mandates src/requirements.txt | File present with boto3>=1.37.0 per Surtr/CLAUDE.md | ✅ |

| Handler raises on row_count == 0 | Unit-tested in tests/test_handler.py::test_raises_on_zero_rows | ✅ |

### What is NOT verified locally

- End-to-end Lambda invoke after CDK deploy — pipeline has not yet been deployed to AWS. The proc and table are verified live; the Lambda's invocation path is verified only via unit tests that stub the Redshift Data API. Post-deploy verification (aws lambda invoke ...) is the standard rollout step.

- EventBridge schedule firing daily — declarative in pipeline.json (rate(1 day)) and exercised by CDK config tests; not yet observed firing in a deployed environment.

- Aerie's downstream Convex sync consuming the new table — out of scope for this PR, tracked in a separate Aerie ticket.

---

## Test plan (reviewer)

- [ ] Read both spec files, confirm functional requirements line up with what landed

- [ ] Read both DDL files under pipelines/runners/mart-education-mfr-line-items-refresh/ddl/, confirm proc body matches spec FR2 + table DDL matches FR1

- [ ] Confirm pipeline.json IAM policy mirrors hc-forecast-refresh (the existing Redshift Data API caller pattern)

- [ ] Run cd pipelines/runners/mart-education-mfr-line-items-refresh && uv run pytest tests/ -v locally — expect 14 passing

- [ ] Sanity-check the NULL-type filter rationale in spec 01's "Live Verification" section

#144 — fix(truefoundry-gateway-pipeline): move ingest to 06:30 UTC to clear upstream rollup race @kevalshahtrilogy  no labels

## Why the drift?

A pipeline-dashboard alert flagged a 98.8% reconciliation drift on truefoundry-gateway-pipeline for 2026-05-31: Redshift held \$129.03 vs a TrueFoundry API total of \$10,745.41, and all three us partitions returned 0 rows from Athena.

Root cause — a same-time scheduling race, not data loss. I verified against the live Athena source: the US data is fully intact (472 rows / \$10,619.46 for 2026-05-31; the exact pipeline predicate returns 345 rows / \$10,619.46 right now). It simply had not been written yet when the pipeline read it.

| Evidence (UTC) | Finding |

|---|---|

| Pipeline schedule | 06:00 daily |

| Upstream rollup orchestrator (date-shim) START | 06:00:06 — same minute |

| s3-cleaner (empties partitions) | 06:00:08, then 06:10:15 |

| EU partition files written | ~06:03 every day |

| US partition files written | ~06:09–06:11 every day |

| Pattern 05-26 → 06-01 | US lands ~06:10 every single day |

The upstream rollup delete-then-rebuilds the trailing partitions in place. It writes EU by ~06:03 but the US partitions last (~06:10). Our 06:00 run (which queries us before eu) read the US partitions mid-rebuild → 0 rows → loaded an empty US partition, while EU loaded (~\$129). The T-2 reconciliation in the same invocation then compared the US-less Redshift total against the TF Metrics API's all-region total → 98.8% drift.

Why PR #117's trailing-window self-heal didn't save us: every daily re-pull re-fired into the same 06:00 mid-rebuild window and re-read empty US — so US never self-healed without a manual off-hours backfill.

## The fix

Move the schedule from cron(0 6 * * ? *)cron(30 6 * * ? *) (06:30 UTC, ~19 min past the US write and the second cleaner pass). Also corrects the now-inaccurate timing rationale in the handler docstring.

## Follow-ups (not in this PR)

- [ ] Backfill the missing US history (~2026-05-26 onward) via a one-off run at an off-hour.

- [ ] Upstream-readiness gate before UNLOAD (e.g. via the existing gateway-reporting-lock-helper / a completion marker) so timing drift can't reintroduce this.

- [ ] Recon hardening: an extreme breach (an entire region at \$0 while the TF API shows spend) should fail loudly / page, not just log WARNING with status=SUCCESS.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

#148 — SURTR-41 fix(surtr): swap Education mart entity_type filter for dynamic BU allowlist @ashwanth1109  no labels

## Linear

[SURTR-41](https://linear.app/builder-team/issue/SURTR-41) — Fix Education budget mart — entity_type='Education' filter drops historical budget snapshots

## Problem

mart_education.agg_mfr_line_items_summary filtered its source with WHERE entity_type = 'Education'. That column is only re-tagged when a new budget cycle publishes, so older snapshots for Education BUs were tagged entity_type = 'Other' and silently dropped. Effect: the mart contained zero budget rows for version = '2026-Q1', and Aerie's Q1 2026 budget cells rendered as $0.

## Fix

Keep every Education-tagged row, plus — for the Education business-unit allowlist — every budget row regardless of its (possibly stale) entity_type:

WHERE ( entity_type = 'Education'

OR ( business_unit IN (

SELECT DISTINCT business_unit

FROM core_budgets.consolidated_budgets_and_actuals

WHERE entity_type = 'Education'

) AND data_source = 'Budget' ) )

AND type IS NOT NULL

The allowlist captures every BU ever tagged Education in any version. The data_source = 'Budget' qualifier on the expansion is load-bearing — a bare allowlist over-included a $3.6B investment ledger (see Verification). All 24 Education BUs stay in the mart (Aerie excludes Physical Private Schools and Core Education at read time; the sibling School page consumes Physical Private Schools).

## What's in this PR

- DDL: core_budgets.sp_refresh_agg_mfr_line_items_summary — WHERE clause swap (Education OR allowlist-budget) + header refresh

- Sibling DDL comment: mart_education.agg_mfr_line_items_summary header comment refreshed to match

- Handler: docstring + RuntimeError updated, plus a per-version coverage guard — fails if any Budget version the source carries for the allowlist is missing from the mart (COUNT(*) > 0 alone can't detect the per-version silent drop that caused SURTR-41). Adds RedshiftClient.fetch_column.

- Spec: features/surtr/education-pnl-mart-refresh/specs/03-fix-entity-type-filter/spec.md (incl. a new Live Verification section)

## Acceptance (operational)

After re-applying the updated procedure to finance_dw and re-running the refresh:

1. SELECT version, COUNT(*) FROM mart_education.agg_mfr_line_items_summary WHERE data_source = 'Budget' AND version IN ('2026-Q1', '2026-Q2') GROUP BY version returns both versions with non-zero counts.

2. Jan-2026 Recurring Revenue Budget under version = '2026-Q1' sums to $1,578,427.34 (matches Klair's Performance Review > Income Statement).

3. The recent Actual slice is Education-only (no over-inclusion).

## Tests / CI

- 18 handler unit tests pass (14 original + 4 new for the per-version guard and fetch_column).

- Lint (ruff) clean on all touched Python files.

## Out of scope

- Backfilling 2025-Q1..Q4 (not exposed in Aerie's picker)

- Aerie-side changes (sync worker, Convex schema, educationPL query) — tracked in AERIE-341

- Schema / column changes to mart_education.agg_mfr_line_items_summary

## ✅ Verification — live Redshift run (2026-06-03)

Applied the updated procedure to finance_dw and re-ran the refresh against the live cluster (same Redshift Data API path the Lambda uses). Both acceptance criteria pass, and the over-inclusion bug caught in review is fixed.

### Over-inclusion bug (caught in review) and fix

The first revision used a bare allowlist (all rows for Education BUs). The live entity_type breakdown showed that pulled in $3.63B of Actual rows on one BU — "Discontinued BUs" — the holding company's investment ledger (Unrealized Gain/Loss on Securities $3.17B, asset sales, interest/dividends), not Education P&L. It corrupted the Actual slices Aerie reads (Jan-2026 Actual 'Other' = $70.7M vs real Education $29.7M), and the mart has no entity_type column for Aerie to filter on. Restricting the allowlist expansion to data_source = 'Budget' drops it cleanly — "Discontinued BUs" has zero budget rows.

### Mart state — pre-fix → polluted (bare allowlist) → corrected

| Metric | Pre-fix (old entity_type filter) | Bare allowlist (rejected) | Corrected (this PR) |

|---|---:|---:|---:|

| Total rows | 4,156 | 11,341 | 10,540 |

| SUM(amount) | $0.94B | $6.14B | $2.48B |

| Jan-2026 Actual 'Other' bleed | — | $70.7M | $0 |

| Discontinued-BUs Unrealized Securities Gain | excluded | $3.17B | $0.00 |

### Acceptance results

- Version coverage: 2026-Q1 = 1,620 Budget rows, 2026-Q2 = 1,716 Budget rows — both present, non-zero. ✅

- Parity: Jan-2026 Recurring Revenue Budget under 2026-Q1 = $1,578,427.34 — exact match vs source and Klair. ✅

- Actual-slice purity: Jan-2026 Actual = $29,667,085.21, Education-only. ✅

- Handler guard: 0 missing Budget versions on the clean rebuild. ✅

### Note on the figures (24-vs-20 BU / 6-vs-4 version)

The whole mart spans 24 BUs across 6 budget versions. A single Q1-2026 reporting period shows a narrower 20 BU × 4 version slice — not every BU/version carries Jan-2026 budget rows, so the per-period slice counts are legitimately smaller than the mart totals.

### Deployment status

The Lambda is not yet deployed (main → production promotion is the trigger; last CD run was 2026-05-27), but the corrected SP is live in Redshift now and the daily refresh will pick it up automatically once the Lambda is created.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

#297 — [AERIE-341, AERIE-343, AERIE-344] feat(dashboards): Education P&L page in Financials dashboard @ashwanth1109  no labels

## Demo

<img width="2624" height="1636" alt="image" src="https://github.com/user-attachments/assets/12b1c582-c96e-4426-bb38-89322d259507" />

## Summary

Adds a new Education P&L page to the Financials dashboard — a tree-style income statement (budget vs actual, monthly + quarterly columns) covering all Education-entity activity except Physical Private Schools and Core Education. Modeled after Klair's Performance Review > Income Statement and built on Aerie's Convex + Redshift sync architecture, so consolidated numbers reconcile against Klair's Performance Review for the matching BU/class scope.

Sits alongside the existing per-school P&L surface (relabeled "School P&L" in the same PR). The new page is consolidated (no per-school selector), pulled from core_budgets.consolidated_budgets_and_actuals via a new daily sync, and rendered as a fixed 18-row income statement with drilldown by business_unit → class.

## Linear tickets

- [AERIE-341 — Education P&L page in Financials dashboard](https://linear.app/builder-team/issue/AERIE-341) (parent)

- [AERIE-343 — Education P&L polish: M1+M2 subtotal column + Financials sub-tab URL routing](https://linear.app/builder-team/issue/AERIE-343)

- [AERIE-344 — Financial sync hardening: pl-transactions NULL filter + mfr-line-items OCC race fix](https://linear.app/builder-team/issue/AERIE-344)

## Specs delivered

| Spec | Status | Description |

|------|--------|-------------|

| [01-sync-and-schema](features/dashboards/education-pl-page/specs/01-sync-and-schema/spec.md) | Completed | New mfrLineItems Convex table + 3 indexes; new Redshift reader with entity_type='Education' filter and Zod validation; daily refresh module wired into the financial worker. |

| [02-convex-query](features/dashboards/education-pl-page/specs/02-convex-query/spec.md) | Completed | chat/convex/dashboards/educationPL.tsgetIncomeStatement({year, quarter}) returning TreeNode[] with server-side derived totals; BU exclusion at query time; Provision for Bad Debt derived row; variance % zero-budget handling; getLastSyncedAt helper. |

| [03-ui-page-and-relabel](features/dashboards/education-pl-page/specs/03-ui-page-and-relabel/spec.md) | Completed | New Education P&L page (education-pl-table.tsx + education-pl-period-picker.tsx); School P&L relabel; default-quarter walk-back; CSV export. |

## What landed in each layer

### Sync (sync/)

- sync/src/redshift/mfr-line-items.ts — Zod-validated read against core_budgets.consolidated_budgets_and_actuals with entity_type='Education' filter (~12.3M → ~285K rows).

- sync/src/analytics/mfr-line-items-refresh.ts — Batched Convex upsert keyed on the natural composite, daily cadence.

- sync/src/financial-worker/index.ts — Registered the new task on the daily financial-worker cycle.

### Convex (chat/convex/)

- chat/convex/financialSchema.ts — New mfrLineItems table + 3 indexes (by_reportingPeriod, by_period_dataSource, by_natural_key).

- chat/convex/dashboards/educationPL.tsgetIncomeStatement + getLastSyncedAt queries (both canViewFinancials-gated) plus the upsertMfrLineItems mutation. Server-side derivation of all 8 computed rows (Total Revenue / Total COGS / Gross Profit / Gross Margin % / Total Expenses / Net Profit / Net Margin %), divide-by-zero protection, Provision for Bad Debt synthesized from isProvisionForBadDebt=true rows.

### UI (chat/components/dashboards/financials/)

- education-pl-page.tsx, education-pl-table.tsx, education-pl-period-picker.tsx, education-pl-helpers.ts — Fixed 18-row income statement, monthly column groups + Quarter Total (Actual / Budget / Var$ / Var%), collapse-by-default tree (line item → BU → class), CSV export, dedicated period picker with default-quarter walk-back.

- financials-view.tsx — Reads the active sub-tab from useDashboardTabs (URL-routed) instead of owning local state.

## Follow-up work added to this branch

After the initial three specs landed, four commits were added to address polish items and reliability fixes discovered while running the dashboard in the dev environment. Filed retroactively as AERIE-343 and AERIE-344 for tracking — both included in this PR.

### AERIE-343 — UI polish (2 commits)

- 5497d3c3 feat(dashboards): add M1+M2 subtotal column to Education P&L — New two-month aggregation column between M3 and Quarter Total. Header reads e.g. Jan + Feb 2026 (derived from quarter context, self-describing in CSV exports / screenshots). monthsThruTwoActual / monthsThruTwoBudget carried on the server TreeNode because margin rows need safePct(num.m1+m2, den.m1+m2) from the underlying numerator / denominator pair — a client-side mean of two percentages would have been wrong.

- 5d1ae524 refactor(dashboards): move Financials sub-tab into URL-routed state — Promotes the Financials → School P&L / Education P&L toggle from local useState into URL-routed state (?sub=school|education) via useDashboardTabs. Financials becomes an expandable parent in the sidebar dashboards context panel, matching the Admissions / Edu Joe nav pattern. Deep-linking works; refresh preserves the active sub-tab.

### AERIE-344 — Sync hardening (2 commits)

- 4177f040 fix(sync): remove mfr-line-items boot backfill to avoid OCC race — The boot backfill and the scheduler tick were both writing to the same Convex mfrLineItems rows on worker startup. The resulting OCC contention near-stalled the upsert phase in dev. Boot backfill removed (scheduler tick fires immediately on boot, so end state is identical). Adds breadcrumbs (redshift fetch start/end/fail, upsert progress every 50/N batches) so hung loops surface in dev.log instead of looking like silence.

- 78a135fa fix(sync): exclude NULL class_name rows from pl-transactions query — Adds AND <alias>.class_name IS NOT NULL to all four UNION branches (qb_pl, qb_bills, qb_journal_entries, qb_vendor_credits). Rows without class_name carry no school identity and could never surface in the drill-down, but were tripping the non-nullable Zod schema downstream — a silent-failure path emitting parse warnings without anyone noticing.

## Tests

75 + 8 tests across the feature, all passing:

| Layer | Tests | File(s) |

|-------|-------|---------|

| Sync | 19 | mfr-line-items.test.ts (11), mfr-line-items-refresh.test.ts (8) |

| Convex queries | 30 | educationPL.test.ts — upsert mutation, tree-builder helpers, 18-row contract, divide-by-zero, BU exclusion, Provision for Bad Debt handling, M1+M2 derived-field invariant |

| UI helpers | 26 | education-pl-helpers.test.ts — variance, percent calculations, default-quarter walk, CSV export (5-group with M1+M2), color tone |

| Sidebar nav (AERIE-343) | 8 | dashboards-context-panel.test.tsx — Financials expandable parent, sub-tab nav |

## Pre-existing finding noted

The public upsertMfrLineItems mutation has no auth gate restricting it to a sync service principal. This follows the existing codebase pattern (same as upsertPlTransactions, upsertXoContractorIdentity, and other sync-callable mutations) and is out of scope for this PR — it would need a coordinated change across all sync-callable mutations. Documented here for awareness.

## CI

All 7 checks passing on this PR.

## Test plan

- [ ] Visual sanity check on the Education P&L page — header, period picker, last-synced timestamp, 18 rows in canonical order, expense rows render with invertColors.

- [ ] Drilldown behavior — top-level row expands to business_unit; BU expands to class; collapse restores the previous state.

- [ ] CSV export emits the flat income statement (5 column groups: M1 / M2 / M3 / M1+M2 / Quarter Total) for the selected quarter.

- [ ] Sidebar nav: Financials is an expandable parent — ?sub=school and ?sub=education round-trip through URL on refresh / deep-link; switching tabs preserves the active sub-tab.

- [ ] M1+M2 column appears between M3 and Quarter Total with a header like Jan + Feb 2026; margin / percent rows in that column show the correct combined-base percentage (not a client-side mean of two percentages).

- [ ] Reconciliation: pick a sample quarter, compare Aerie Education P&L totals against Klair's Performance Review > Income Statement for the same BU/class scope.

- [ ] Run the sync against a real Redshift connection — verify mfrLineItems populates, that the natural-key upsert is idempotent on re-run, and that the refresh module fires on the daily cadence. Confirm only the scheduler tick runs on boot (no parallel boot backfill).

- [ ] Spot-check pl-transactions sync: confirm NULL class_name rows are absent from the four UNION branches and the Zod-parse warning count drops.

The Builder Desk  —  Engineer Spotlight
🏆 Engineer Spotlight

TWELVE PRs IN TWENTY-FOUR HOURS: THE BUILDER TEAM DOES NOT SLEEP, DOES NOT SLOW, DOES NOT STOP

Three repos, six engineers, one unstoppable locomotive of human output — and Ashwanth is driving.

Twelve pull requests. Twenty-four hours. Three repos lighting up the board — Surtr with five, Aerie with four, Klair with three — and six engineers who apparently have no concept of a ceiling. The Builder Team posted another dominant session and the numbers desk is here to make sure history remembers every digit.

Let's talk contributors. @kevalshahtrilogy put up three PRs including #146 in Surtr, a chore that disabled the scheduled RAG ingestion pipeline — a quiet move that takes discipline, the kind of unglamorous work that keeps the machine clean. @benji-bizzell was an Aerie wrecking ball: three PRs, all business, touching admissions pipeline reconciliation in #302, forecast CSV export and controls in #301, and a buildout simplification in #300 that streamlined RYG statuses. That is a man who came to work. @sanketghia dropped #2948 in Klair, expanding the BU Override dropdown to include Canopy and Core Education — small PR, enormous symbolic weight. @marcusdAIy filed #2937 in Klair, delivering proactive conformance coaching on editor open for B11.4, which sounds like something a very wise machine would do. @eric-tril closed out Klair's ledger with #2944, a fix ensuring uploaded CSV beats manual entry in the Cash Flow Statement — a ruling so correct it barely needed to be a PR.

And then there is Ashwanth. @ashwanth1109 shipped three PRs in what can only be described as a coordinated Education financial infrastructure blitz. PR #142 in Surtr pre-aggregates Education P&L rows in Redshift for Aerie sync — a feat of data plumbing that would take most engineers a week to conceptualize. PR #148 swapped a static Education mart entity_type filter for a dynamic BU allowlist, the kind of refactor that sounds simple until you realize the implications cascade across every downstream consumer. And then — THEN — he drops #297 in Aerie: a full Education P&L page inside the Financials dashboard, resolving three AERIE tickets simultaneously like he's clearing a queue at a deli counter. We reached out to Ashwanth for comment. "I don't think about individual PRs," he reportedly said, staring at three monitors simultaneously. "I think about systems." We asked a follow-up question. He had already merged.

The Overflow Desk salutes the seven PRs that Mac didn't have column inches for but which the numbers desk refuses to let vanish into the git log. Benji's trio in Aerie alone — #300, #301, #302 — represents a complete admissions dashboard lifecycle in a single day. Eric's #2944 is the kind of fix that prevents a category of human error forever. MarcusDAIy's conformance coaching feature in #2937 is the product quietly getting smarter while everyone else is looking at the scoreboard.

Morale on the Builder Team is at an all-time high. It has, in fact, never been higher. The engineers are locked in, the repos are active, and the PRs keep coming. Brick Callahan will be here when they do.

Brick's Overflow — PRs Mac Didn't Cover  (click to expand)
#142 — SURTR-39 feat(surtr): pre-aggregate Education P&L rows in Redshift for Aerie sync @ashwanth1109  no labels

## Summary

Lands a new Surtr pipeline mart-education-mfr-line-items-refresh that materialises a pre-aggregated Education income-statement table in Redshift at the exact grain Aerie's educationPL page consumes, plus a stored procedure to refresh it. Shrinks the dataset Aerie's downstream Convex sync moves per run from line-grain rows to ~4–5K aggregate rows.

Linear: [SURTR-39](https://linear.app/builder-team/issue/SURTR-39)

What lands:

- mart_education.agg_mfr_line_items_summary — new pre-aggregated table (10 cols, DISTSTYLE ALL, sortkey on (reporting_period, business_unit, class_name))

- core_budgets.sp_refresh_agg_mfr_line_items_summary()TRUNCATE + INSERT ... SELECT ... GROUP BY 1..8 over core_budgets.consolidated_budgets_and_actuals filtered to entity_type = 'Education' AND type IS NOT NULL

- pipelines/runners/mart-education-mfr-line-items-refresh/ — Lambda runner (bundled) that calls the proc daily via Redshift Data API, asserts row count > 0, otherwise raises

- DDL copies under the runner's ddl/ folder for review (canonical apply path is the existing core_budgets / mart_education DDL workflow run out-of-band)

Specs:

- features/surtr/education-pnl-mart-refresh/specs/01-mart-table-and-stored-procedure/spec.md

- features/surtr/education-pnl-mart-refresh/specs/02-refresh-pipeline-runner/spec.md

---

## Local Verification (2026-06-02)

### How it was tested

1. Unit testscd pipelines/runners/mart-education-mfr-line-items-refresh && uv run pytest tests/ -v (14 tests, all pass: handler happy path, row_count == 0 raises, Redshift Data API request shape, FAILED / ABORTED / timeout branches).

2. CDK config testscd pipelines/cdk && pnpm test -- real-pipeline-configs (passes — Lambda description within 256-char limit, IAM shape valid).

3. Live DDL apply against finance_dw on redshift-cluster-1 — authenticated via saml2aws to the central-finance role and applied the procedure DDL via aws redshift-data execute-statement. Table DDL was already applied out-of-band beforehand.

4. Live proc invocationCALL core_budgets.sp_refresh_agg_mfr_line_items_summary() against the live cluster.

5. Sum-integrity check — compared SUM(amount) of the aggregated mart against the source mart restricted to the same predicate.

### Live finding & resolution

First invocation failed with Cannot insert a NULL value into column type. Root cause: 51 source rows have type IS NULL while the target column is declared VARCHAR(64) NOT NULL.

Investigated all 51 rows before patching:

| Business Unit | Class | Period | Rows | Sum($) |

|---|---|---|---:|---:|

| Strata | Strata | 2026-04-30 | 24 | -136,078.47 |

| Strata | Strata - Current Coach Model | 2026-04-30 | 24 | +136,078.47 |

| Homeschool/DTC Apps | Homeschool/DTC Apps | 2025-03-31 | 2 | +696.18 |

| Physical Private Schools | Physical Private Schools | 2022-04-30 | 1 | -167.00 |

Top two rows are a manual reclassification (net P&L impact $0). Total net P&L impact of all 51 rows: ~$529.18 across 4 years — well below any reporting materiality threshold. Fix: add AND type IS NOT NULL to the proc's WHERE clause. Keeps the target column NOT NULL so Aerie's TypeScript types stay non-nullable; only drops rows that already lack a type classification.

### Evidence — success criteria

| Spec Success Criterion | Evidence | Result |

|---|---|---|

| FR1: DDL applies cleanly, table has the declared 10-col layout with sortkey/diststyle | DDL applied out-of-band to finance_dw; pg_tables lookup confirms mart_education.agg_mfr_line_items_summary exists | ✅ |

| FR2: Proc completes synchronously, leaves target with > 0 rows | CALL completed in 1.28s with Status=FINISHED; target now has 4,156 rows | ✅ |

| FR3: SUM(amount) in agg matches SUM(amount) on source under the same predicate | Agg sum $939,703,459.61 vs. source sum $939,703,459.61 (entity_type='Education' AND type IS NOT NULL) | ✅ matches to the cent |

| FR4: DDL file headers cite spec path, source mart, consumer | Both ddl/*.sql files have full header comment blocks | ✅ |

| Ticket goal: shrink row count to ~5K–10K | 286,520 source rows → 4,156 agg rows = 68.9× compression | ✅ exceeds 12–25× projection; below 5K–10K target |

| Pipeline bundling: true mandates src/requirements.txt | File present with boto3>=1.37.0 per Surtr/CLAUDE.md | ✅ |

| Handler raises on row_count == 0 | Unit-tested in tests/test_handler.py::test_raises_on_zero_rows | ✅ |

### What is NOT verified locally

- End-to-end Lambda invoke after CDK deploy — pipeline has not yet been deployed to AWS. The proc and table are verified live; the Lambda's invocation path is verified only via unit tests that stub the Redshift Data API. Post-deploy verification (aws lambda invoke ...) is the standard rollout step.

- EventBridge schedule firing daily — declarative in pipeline.json (rate(1 day)) and exercised by CDK config tests; not yet observed firing in a deployed environment.

- Aerie's downstream Convex sync consuming the new table — out of scope for this PR, tracked in a separate Aerie ticket.

---

## Test plan (reviewer)

- [ ] Read both spec files, confirm functional requirements line up with what landed

- [ ] Read both DDL files under pipelines/runners/mart-education-mfr-line-items-refresh/ddl/, confirm proc body matches spec FR2 + table DDL matches FR1

- [ ] Confirm pipeline.json IAM policy mirrors hc-forecast-refresh (the existing Redshift Data API caller pattern)

- [ ] Run cd pipelines/runners/mart-education-mfr-line-items-refresh && uv run pytest tests/ -v locally — expect 14 passing

- [ ] Sanity-check the NULL-type filter rationale in spec 01's "Live Verification" section

#148 — SURTR-41 fix(surtr): swap Education mart entity_type filter for dynamic BU allowlist @ashwanth1109  no labels

## Linear

[SURTR-41](https://linear.app/builder-team/issue/SURTR-41) — Fix Education budget mart — entity_type='Education' filter drops historical budget snapshots

## Problem

mart_education.agg_mfr_line_items_summary filtered its source with WHERE entity_type = 'Education'. That column is only re-tagged when a new budget cycle publishes, so older snapshots for Education BUs were tagged entity_type = 'Other' and silently dropped. Effect: the mart contained zero budget rows for version = '2026-Q1', and Aerie's Q1 2026 budget cells rendered as $0.

## Fix

Keep every Education-tagged row, plus — for the Education business-unit allowlist — every budget row regardless of its (possibly stale) entity_type:

WHERE ( entity_type = 'Education'

OR ( business_unit IN (

SELECT DISTINCT business_unit

FROM core_budgets.consolidated_budgets_and_actuals

WHERE entity_type = 'Education'

) AND data_source = 'Budget' ) )

AND type IS NOT NULL

The allowlist captures every BU ever tagged Education in any version. The data_source = 'Budget' qualifier on the expansion is load-bearing — a bare allowlist over-included a $3.6B investment ledger (see Verification). All 24 Education BUs stay in the mart (Aerie excludes Physical Private Schools and Core Education at read time; the sibling School page consumes Physical Private Schools).

## What's in this PR

- DDL: core_budgets.sp_refresh_agg_mfr_line_items_summary — WHERE clause swap (Education OR allowlist-budget) + header refresh

- Sibling DDL comment: mart_education.agg_mfr_line_items_summary header comment refreshed to match

- Handler: docstring + RuntimeError updated, plus a per-version coverage guard — fails if any Budget version the source carries for the allowlist is missing from the mart (COUNT(*) > 0 alone can't detect the per-version silent drop that caused SURTR-41). Adds RedshiftClient.fetch_column.

- Spec: features/surtr/education-pnl-mart-refresh/specs/03-fix-entity-type-filter/spec.md (incl. a new Live Verification section)

## Acceptance (operational)

After re-applying the updated procedure to finance_dw and re-running the refresh:

1. SELECT version, COUNT(*) FROM mart_education.agg_mfr_line_items_summary WHERE data_source = 'Budget' AND version IN ('2026-Q1', '2026-Q2') GROUP BY version returns both versions with non-zero counts.

2. Jan-2026 Recurring Revenue Budget under version = '2026-Q1' sums to $1,578,427.34 (matches Klair's Performance Review > Income Statement).

3. The recent Actual slice is Education-only (no over-inclusion).

## Tests / CI

- 18 handler unit tests pass (14 original + 4 new for the per-version guard and fetch_column).

- Lint (ruff) clean on all touched Python files.

## Out of scope

- Backfilling 2025-Q1..Q4 (not exposed in Aerie's picker)

- Aerie-side changes (sync worker, Convex schema, educationPL query) — tracked in AERIE-341

- Schema / column changes to mart_education.agg_mfr_line_items_summary

## ✅ Verification — live Redshift run (2026-06-03)

Applied the updated procedure to finance_dw and re-ran the refresh against the live cluster (same Redshift Data API path the Lambda uses). Both acceptance criteria pass, and the over-inclusion bug caught in review is fixed.

### Over-inclusion bug (caught in review) and fix

The first revision used a bare allowlist (all rows for Education BUs). The live entity_type breakdown showed that pulled in $3.63B of Actual rows on one BU — "Discontinued BUs" — the holding company's investment ledger (Unrealized Gain/Loss on Securities $3.17B, asset sales, interest/dividends), not Education P&L. It corrupted the Actual slices Aerie reads (Jan-2026 Actual 'Other' = $70.7M vs real Education $29.7M), and the mart has no entity_type column for Aerie to filter on. Restricting the allowlist expansion to data_source = 'Budget' drops it cleanly — "Discontinued BUs" has zero budget rows.

### Mart state — pre-fix → polluted (bare allowlist) → corrected

| Metric | Pre-fix (old entity_type filter) | Bare allowlist (rejected) | Corrected (this PR) |

|---|---:|---:|---:|

| Total rows | 4,156 | 11,341 | 10,540 |

| SUM(amount) | $0.94B | $6.14B | $2.48B |

| Jan-2026 Actual 'Other' bleed | — | $70.7M | $0 |

| Discontinued-BUs Unrealized Securities Gain | excluded | $3.17B | $0.00 |

### Acceptance results

- Version coverage: 2026-Q1 = 1,620 Budget rows, 2026-Q2 = 1,716 Budget rows — both present, non-zero. ✅

- Parity: Jan-2026 Recurring Revenue Budget under 2026-Q1 = $1,578,427.34 — exact match vs source and Klair. ✅

- Actual-slice purity: Jan-2026 Actual = $29,667,085.21, Education-only. ✅

- Handler guard: 0 missing Budget versions on the clean rebuild. ✅

### Note on the figures (24-vs-20 BU / 6-vs-4 version)

The whole mart spans 24 BUs across 6 budget versions. A single Q1-2026 reporting period shows a narrower 20 BU × 4 version slice — not every BU/version carries Jan-2026 budget rows, so the per-period slice counts are legitimately smaller than the mart totals.

### Deployment status

The Lambda is not yet deployed (main → production promotion is the trigger; last CD run was 2026-05-27), but the corrected SP is live in Redshift now and the daily refresh will pick it up automatically once the Lambda is created.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

#297 — [AERIE-341, AERIE-343, AERIE-344] feat(dashboards): Education P&L page in Financials dashboard @ashwanth1109  no labels

## Demo

<img width="2624" height="1636" alt="image" src="https://github.com/user-attachments/assets/12b1c582-c96e-4426-bb38-89322d259507" />

## Summary

Adds a new Education P&L page to the Financials dashboard — a tree-style income statement (budget vs actual, monthly + quarterly columns) covering all Education-entity activity except Physical Private Schools and Core Education. Modeled after Klair's Performance Review > Income Statement and built on Aerie's Convex + Redshift sync architecture, so consolidated numbers reconcile against Klair's Performance Review for the matching BU/class scope.

Sits alongside the existing per-school P&L surface (relabeled "School P&L" in the same PR). The new page is consolidated (no per-school selector), pulled from core_budgets.consolidated_budgets_and_actuals via a new daily sync, and rendered as a fixed 18-row income statement with drilldown by business_unit → class.

## Linear tickets

- [AERIE-341 — Education P&L page in Financials dashboard](https://linear.app/builder-team/issue/AERIE-341) (parent)

- [AERIE-343 — Education P&L polish: M1+M2 subtotal column + Financials sub-tab URL routing](https://linear.app/builder-team/issue/AERIE-343)

- [AERIE-344 — Financial sync hardening: pl-transactions NULL filter + mfr-line-items OCC race fix](https://linear.app/builder-team/issue/AERIE-344)

## Specs delivered

| Spec | Status | Description |

|------|--------|-------------|

| [01-sync-and-schema](features/dashboards/education-pl-page/specs/01-sync-and-schema/spec.md) | Completed | New mfrLineItems Convex table + 3 indexes; new Redshift reader with entity_type='Education' filter and Zod validation; daily refresh module wired into the financial worker. |

| [02-convex-query](features/dashboards/education-pl-page/specs/02-convex-query/spec.md) | Completed | chat/convex/dashboards/educationPL.tsgetIncomeStatement({year, quarter}) returning TreeNode[] with server-side derived totals; BU exclusion at query time; Provision for Bad Debt derived row; variance % zero-budget handling; getLastSyncedAt helper. |

| [03-ui-page-and-relabel](features/dashboards/education-pl-page/specs/03-ui-page-and-relabel/spec.md) | Completed | New Education P&L page (education-pl-table.tsx + education-pl-period-picker.tsx); School P&L relabel; default-quarter walk-back; CSV export. |

## What landed in each layer

### Sync (sync/)

- sync/src/redshift/mfr-line-items.ts — Zod-validated read against core_budgets.consolidated_budgets_and_actuals with entity_type='Education' filter (~12.3M → ~285K rows).

- sync/src/analytics/mfr-line-items-refresh.ts — Batched Convex upsert keyed on the natural composite, daily cadence.

- sync/src/financial-worker/index.ts — Registered the new task on the daily financial-worker cycle.

### Convex (chat/convex/)

- chat/convex/financialSchema.ts — New mfrLineItems table + 3 indexes (by_reportingPeriod, by_period_dataSource, by_natural_key).

- chat/convex/dashboards/educationPL.tsgetIncomeStatement + getLastSyncedAt queries (both canViewFinancials-gated) plus the upsertMfrLineItems mutation. Server-side derivation of all 8 computed rows (Total Revenue / Total COGS / Gross Profit / Gross Margin % / Total Expenses / Net Profit / Net Margin %), divide-by-zero protection, Provision for Bad Debt synthesized from isProvisionForBadDebt=true rows.

### UI (chat/components/dashboards/financials/)

- education-pl-page.tsx, education-pl-table.tsx, education-pl-period-picker.tsx, education-pl-helpers.ts — Fixed 18-row income statement, monthly column groups + Quarter Total (Actual / Budget / Var$ / Var%), collapse-by-default tree (line item → BU → class), CSV export, dedicated period picker with default-quarter walk-back.

- financials-view.tsx — Reads the active sub-tab from useDashboardTabs (URL-routed) instead of owning local state.

## Follow-up work added to this branch

After the initial three specs landed, four commits were added to address polish items and reliability fixes discovered while running the dashboard in the dev environment. Filed retroactively as AERIE-343 and AERIE-344 for tracking — both included in this PR.

### AERIE-343 — UI polish (2 commits)

- 5497d3c3 feat(dashboards): add M1+M2 subtotal column to Education P&L — New two-month aggregation column between M3 and Quarter Total. Header reads e.g. Jan + Feb 2026 (derived from quarter context, self-describing in CSV exports / screenshots). monthsThruTwoActual / monthsThruTwoBudget carried on the server TreeNode because margin rows need safePct(num.m1+m2, den.m1+m2) from the underlying numerator / denominator pair — a client-side mean of two percentages would have been wrong.

- 5d1ae524 refactor(dashboards): move Financials sub-tab into URL-routed state — Promotes the Financials → School P&L / Education P&L toggle from local useState into URL-routed state (?sub=school|education) via useDashboardTabs. Financials becomes an expandable parent in the sidebar dashboards context panel, matching the Admissions / Edu Joe nav pattern. Deep-linking works; refresh preserves the active sub-tab.

### AERIE-344 — Sync hardening (2 commits)

- 4177f040 fix(sync): remove mfr-line-items boot backfill to avoid OCC race — The boot backfill and the scheduler tick were both writing to the same Convex mfrLineItems rows on worker startup. The resulting OCC contention near-stalled the upsert phase in dev. Boot backfill removed (scheduler tick fires immediately on boot, so end state is identical). Adds breadcrumbs (redshift fetch start/end/fail, upsert progress every 50/N batches) so hung loops surface in dev.log instead of looking like silence.

- 78a135fa fix(sync): exclude NULL class_name rows from pl-transactions query — Adds AND <alias>.class_name IS NOT NULL to all four UNION branches (qb_pl, qb_bills, qb_journal_entries, qb_vendor_credits). Rows without class_name carry no school identity and could never surface in the drill-down, but were tripping the non-nullable Zod schema downstream — a silent-failure path emitting parse warnings without anyone noticing.

## Tests

75 + 8 tests across the feature, all passing:

| Layer | Tests | File(s) |

|-------|-------|---------|

| Sync | 19 | mfr-line-items.test.ts (11), mfr-line-items-refresh.test.ts (8) |

| Convex queries | 30 | educationPL.test.ts — upsert mutation, tree-builder helpers, 18-row contract, divide-by-zero, BU exclusion, Provision for Bad Debt handling, M1+M2 derived-field invariant |

| UI helpers | 26 | education-pl-helpers.test.ts — variance, percent calculations, default-quarter walk, CSV export (5-group with M1+M2), color tone |

| Sidebar nav (AERIE-343) | 8 | dashboards-context-panel.test.tsx — Financials expandable parent, sub-tab nav |

## Pre-existing finding noted

The public upsertMfrLineItems mutation has no auth gate restricting it to a sync service principal. This follows the existing codebase pattern (same as upsertPlTransactions, upsertXoContractorIdentity, and other sync-callable mutations) and is out of scope for this PR — it would need a coordinated change across all sync-callable mutations. Documented here for awareness.

## CI

All 7 checks passing on this PR.

## Test plan

- [ ] Visual sanity check on the Education P&L page — header, period picker, last-synced timestamp, 18 rows in canonical order, expense rows render with invertColors.

- [ ] Drilldown behavior — top-level row expands to business_unit; BU expands to class; collapse restores the previous state.

- [ ] CSV export emits the flat income statement (5 column groups: M1 / M2 / M3 / M1+M2 / Quarter Total) for the selected quarter.

- [ ] Sidebar nav: Financials is an expandable parent — ?sub=school and ?sub=education round-trip through URL on refresh / deep-link; switching tabs preserves the active sub-tab.

- [ ] M1+M2 column appears between M3 and Quarter Total with a header like Jan + Feb 2026; margin / percent rows in that column show the correct combined-base percentage (not a client-side mean of two percentages).

- [ ] Reconciliation: pick a sample quarter, compare Aerie Education P&L totals against Klair's Performance Review > Income Statement for the same BU/class scope.

- [ ] Run the sync against a real Redshift connection — verify mfrLineItems populates, that the natural-key upsert is idempotent on re-run, and that the refresh module fires on the daily cadence. Confirm only the scheduler tick runs on boot (no parallel boot backfill).

- [ ] Spot-check pl-transactions sync: confirm NULL class_name rows are absent from the four UNION branches and the Zod-parse warning count drops.

#2937 — feat(board-doc): proactive conformance coaching on editor open (B11.4) @marcusdAIy  no labels

<!-- CURSOR_AGENT_PR_BODY_BEGIN -->

## Summary

- On editor open, Claire proactively posts one chat message with optional Accept cards for each actionable conformance gap (add / remove / retype / merge), reusing the existing conform_section tool and ChatToolProposal UI.

- MERGE detection emits one gap per duplicate with merge_into_section_id so each card maps 1:1 to a merge call; coaching injection is idempotent via stable tool_use_ids, conformance_proposed_tool_use_ids, and a live-thread scan.

- The branch also folds in the round of coaching/editor fixes found while dogfooding the flow: prior-doc picker accuracy, conformance add placement, rapid-accept resilience, the chat-500 on synthetic tool ids, date-aware coaching, the BU-wide review filter, a non-spurious reload guard, the batch-address 422, and chat-panel polish (dedup, attribution, card placement, scroll).

## Why it's needed

Clone-imported board docs often carry a stashed conformance_report (B11.3) with structural gaps, but GMs had no discoverable path to act on them without asking Claire manually. B11.4 surfaces those gaps as the same propose-and-confirm cards used elsewhere, without mutating the doc until the user explicitly Accepts. Dogfooding the full create-from-prior-doc flow then surfaced the supporting fixes below.

## Changes

Proactive coaching (B11.4)

- ConformanceGap.merge_into_section_id + per-duplicate MERGE gaps in _detect_duplicates.

- build_conformance_proposals, _conformance_gap_tool_use_id, ensure_conformance_coaching in wizard_orchestrator.py (REORDER skipped; templated copy, no LLM); idempotency now also scans the live conversation for already-attached tool_use_ids.

- WizardSession.conformance_proposed_tool_use_ids for dedup across reloads; conform_section retype calls invalidate_conformance(session).

- POST /wizard/{session_id}/conformance-coachingWizardSessionResponse, called after resumeSession.

- Canonical placement for conformance add (lands in its golden slot, e.g. GM Commentary at top, not appended at the bottom); exec_summary dropped from the golden template so it is no longer proposed.

Prior-quarter doc picker

- Shows the document creator in the picker (so you can pick DR's prior doc), and selects the chosen row rather than collapsing by doc_id.

Rapid-accept / chat resilience

- Client-side serialization queue (proposalAcceptQueue.ts) so accepting cards in quick succession runs one at a time; wizardRegenerate is awaited inside the lock.

- _anthropic_safe_tool_use_id sanitizes synthetic conformance ids (conformance:add:…) to Anthropic's ^[a-zA-Z0-9_-]+$, fixing the chat 500.

Coach Claire context

- Date-aware coaching (D2.8): quarter-progress block injected into Claire's system prompt so mid-quarter metrics are run-rated/pro-rated instead of read as quarter-end.

- Backlog spec for a weighted-pipeline ARR-projection MCP tool (B5.9, future work).

Review panel + editor

- ReviewFinding.product_name populated for genuine per-product findings; FE getFindingScope / listScopeFilterChips classify by product_name so the BU-wide filter actually excludes product-specific checks.

- flushPendingSaves reload guard: reload flushes pending autosave and only warns when a *real* unsaved diff would be lost (no more spurious "unsaved changes").

- buildFindingsChatMessage caps the chat payload at the backend 4000-char limit (fixes batch-address 422), trimming why/options with a truncation notice while preserving header + finding ids.

Chat panel polish

- add_message(dedup_consecutive=…) + live-thread scan stop the coaching opening and "Brainlift accepted." from being stamped twice by a double-submit.

- Synthetic action markers ("Brainlift accepted.") render in Coach Claire's voice (left/assistant bubble) instead of a right-aligned user bubble; LLM role stays user for alternation safety.

- Conformance cards render inline below Claire's opening (matching the "suggestion below" copy) instead of a pinned top block; the panel scrolls to the top at session start when suggestions exist, and dedups cards across the thread.

## Breaking changes

None.

## Test plan

### Automated

- [x] cd klair-api && uv run pytest tests/board_doc/test_conformance_coaching.py tests/board_doc/test_conform_section.py tests/board_doc/test_conformance.py -q

- [x] cd klair-api && uv run pytest tests/board_doc/test_wizard_models.py tests/board_doc/test_wizard_orchestrator.py tests/board_doc/test_review_findings.py tests/board_doc/test_history_continuity_b3_11.py -q

- [x] cd klair-client && pnpm test src/screens/BoardDoc/__tests__/boardDocChatUtils.spec.ts src/screens/BoardDoc/__tests__/DocumentEditorPage.chat.spec.tsx src/screens/BoardDoc/hooks/__tests__/useBoardDocWizard.resume.spec.ts

- [x] cd klair-client && pnpm test src/screens/BoardDoc/components/__tests__/proposalAcceptQueue.spec.ts src/screens/BoardDoc/components/__tests__/buildFindingChatMessage.spec.ts src/screens/BoardDoc/hooks/__tests__/useDocumentEditor.reloadDocument.spec.ts src/services/__tests__/boardDocApi.getFindingScope.spec.ts

- [x] uv run ruff format + uv run ruff check + uv run pyright on touched Python files (0 errors)

- [x] cd klair-client && pnpm tsc --noEmit + eslint on touched files

### Manual E2E (Skyvera Q3, from DR's prior doc)

1. Create from prior doc — Start a new Skyvera Q3 board doc. In the prior-quarter doc picker, confirm each option shows its creator and pick DR's prior-quarter doc. Confirm the doc that opens is the row you selected (not a different doc collapsed under the same doc_id).

2. Proactive coaching on open — On editor open, Coach Claire posts one opening message ("I compared this document's structure…"). Confirm:

- The suggestion cards appear below the opening message (not pinned above it).

- The chat is scrolled to the top so the opening + cards are visible without scrolling.

- There is exactly one opening message and exactly one "Brainlift accepted." (no duplicates), and "Brainlift accepted." is styled as Coach Claire (left bubble), not as your own message.

- No exec_summary add card is proposed.

3. Accept all suggestions in quick succession — Click Accept on every card back-to-back as fast as possible. Confirm:

- No 500 in the chat/network logs (synthetic conformance:* tool ids are sanitized) and no concurrent-write failure during content generation.

- Each accept resolves in order and its card disappears; an add GM Commentary lands at the top (canonical slot), not appended at the end.

4. Verify implemented + reload — Click Reload document. Confirm:

- All accepted sections/structure changes are present and financial numbers are current.

- Reload does not falsely warn about "unsaved changes" when autosave already persisted everything.

5. BU-wide review filter — Open the review panel and select the BU-wide filter. Confirm product-specific checks are excluded (it no longer behaves like "All").

6. Batch address 3× (no 422) — Select three findings and run Address with Claire as a batch. Confirm the chat send succeeds with no 422 Unprocessable Content (message is capped at 4000 chars; long findings are trimmed with a truncation notice and ids preserved).

7. Date-aware coaching — Ask Claire "how does ARR look?" mid-quarter. Confirm she run-rates/pro-rates to EOQ (or references the forecast) instead of treating the mid-quarter snapshot as a quarter-end number.

<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a href="https://cursor.com/agents/bc-0fa7f0ab-31fd-4cbe-a4cf-f28d66923d2d"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/background-agent?bcId=bc-0fa7f0ab-31fd-4cbe-a4cf-f28d66923d2d"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

#2944 — fix(mfr): uploaded CSV wins over manual entry in Cash Flow Statement @eric-tril  no labels

## Business Value

Finance's uploaded Cash Flow CSV is now honored in the Monthly Financial Reporting memos. Previously, the Group memo's "Changes in operating assets and liabilities" section silently ignored the uploaded CSV and showed balance-sheet-delta values instead — so the numbers Finance uploaded never appeared on screen, in the exported Google Doc, or in the AI narration. This fixes that across all three surfaces and all three memos (Group, Software, Education), so what Finance uploads is what they see and what gets reported.

## Problem

Cash-flow override layers were applied base → CSV → manual entry (last). The manual-entry layer is auto-populated from balance-sheet deltas *even when no manual entry was saved*, so it overwrote the CSV for every row the backend emits as null — which for Group is exactly the "Changes in operating assets and liabilities" section (AR, Prepaid, AP, Deferred revenue, Lease obligations, Other current liabilities). Net effect: the uploaded CSV was discarded for that section.

## Fix

Flip the precedence to the intended CSV → manual entry → Redshift by applying manual entry first and the CSV upload last, and consolidate the layering into a single routine per side so the UI table, the Google Doc export, and the AI narration cannot drift apart again.

- Frontend: new mergeCashFlowOverrides(base, csv, manual) used by useAllFinancialStatements and useFinancialStatementData.

- Backend: new build_merged_cf_records(period, entity) in _cf_helpers.py; the three _build_cf_placeholders (group/software/education) and the narration helper fetch_cf_numbers_with_upload all route through it.

## Behavior changes beyond the precedence flip

1. Narration now reflects manual entry and field-merges the CSV (it previously ignored manual entry entirely and replaced the whole statement with the upload), so it matches the table and export.

2. The export no longer swallows DynamoDB upload-read errors — per the service-layer rule, those propagate like every other cash-flow source error instead of silently dropping the override.

## Test plan

Automated (all green):

- Frontend: tsc clean, ESLint clean, 818 MFR vitest tests pass (incl. the new mergeCashFlowOverrides precedence matrix).

- Backend: ruff + pyright clean (no new errors), 1454 tests/mfr/ tests pass, incl. new test_cf_merged_precedence.py. Repointed test_cf_helpers.py / test_memo_data_pivoting.py mocks to the consolidated builder.

Manual (please verify before merge): for a period with a CSV upload, confirm the Group "Changes in operating assets and liabilities" rows show the CSV values identically across the UI table, the exported Google Doc, and the AI narration; and that a period with manual-entry-but-no-CSV (and a period with neither) still render correctly. Spot-check Software & Education.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

http://localhost:3001/monthly-financial-reporting

https://github.com/user-attachments/assets/63bfbbed-4ff3-4861-9233-e0a85c5ca3c2

#2948 — feat(ai-spend-bu): add Canopy & Core Education to BU Override dropdown @sanketghia  no labels

## What & why

Canopy and Core Education were not selectable in the BU Override dropdown on /admin/ai-spend-bu, even though both already exist as canonical BUs in constants/businessUnits.ts. The dropdown sources its options from a separate list, BU_HIERARCHY_CONFIG, which was missing them.

This adds both BUs to BU_HIERARCHY_CONFIG so they appear as selectable options.

## Changes

- klair-client/src/screens/AICosts/buHierarchyConfig.ts — append two entries:

- Canopy → category Software

- Core Education → category Education

- klair-client/src/screens/AICosts/buHierarchyConfig.spec.ts — new spec verifying both BUs are present under the correct categories and resolve via getBUForKeyId.

## How it works

The dropdown derives its options from new Set(BU_HIERARCHY_CONFIG.map(i => i.bu)) (AISpendBUOverrideManager.tsx), so adding these entries makes both selectable with no component, API, or schema change. category controls where each BU rolls up in the /ai-adoption hierarchy view. Saving an override continues to write the literal BU string to core_finance.ai_spend_bu_overrides.

## Testing

- New Vitest spec: 4 passing (fails before the config change, passes after).

- pnpm tsc --noEmit: clean.

- ESLint on both changed files (--max-warnings 0): clean.

## Out of scope

The broader divergence between the three client BU lists (buHierarchyConfig.ts, constants/businessUnits.ts, monthly-financial-reporting/utils/buOrder.ts) is noted as a follow-up, not addressed here.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

The Portfolio  —  Trilogy Companies

The Resume Is Dead. Crossover Saw It Coming.

As OpenAI dangled half-million-dollar jobs with no CV required, Trilogy's global talent engine has been quietly running that playbook for years.

AUSTIN, TEXAS — When Forbes reported this week that OpenAI is now posting $500,000 roles with no résumé required — evaluating candidates instead on demonstrated capability — the AI industry treated it like a revelation. Inside Trilogy International's Austin headquarters, the reaction was something closer to a shrug.

Crossover, Trilogy's global talent platform and one of the conglomerate's most strategically critical assets, has operated on precisely this premise for years: that a résumé is a proxy for talent, and a poor one at that. The platform deploys rigorous, AI-enabled skills assessments to identify what it calls the top 1% of global technical and professional talent — across 130+ countries — and pays them identical above-market rates regardless of geography. No pedigree required. No alma mater. No zip code.

The timing of OpenAI's announcement lands against a broader backdrop of structural change that is reshaping how companies — and countries — think about human capital. Digital transformation is accelerating international career mobility, with workers in markets like Lebanon, Nigeria, and Vietnam now meaningfully competing for roles at Silicon Valley-caliber companies. A recent report from NewsGram noted that international professionals are increasingly finding their geography irrelevant to their career ceiling — a thesis Crossover has been stress-testing, and validating, at scale.

What makes the moment significant isn't that one marquee AI lab has embraced skills-first hiring. It's that the systemic pressure is now undeniable. Remote-first infrastructure, AI-powered assessment tooling, and a generation of workers who built their skills outside traditional credentialing pipelines are converging — and legacy hiring norms are buckling under the weight.

For Trilogy's ESW Capital portfolio — 75+ enterprise software companies staffed substantially through Crossover — this isn't a trend to watch. It's the operating model. The 75% EBITDA margins that ESW targets aren't achieved through cost-cutting theater. They're achieved, in no small part, by accessing rigorous, meritocratically selected global talent before the rest of the market figured out it was available.

OpenAI just announced it. Crossover has been living it. The question now is how many companies will follow — and how fast.

OpenAI Is Now Hiring $500,000 Jobs. No Resume Required - For  ·  Top 10 Companies Hiring AI Engineers in Lebanon in 2026 - nu  ·  Digital Transformation Opens Doors to International Careers

Alpha Takes the Two-Hour School Day to the World

Liemandt’s classroom-in-a-box just jumped from campus experiment to kitchen-table export.

AUSTIN, TEXAS — Word is the school bell just went borderless.

Alpha School, the AI-first K-12 outfit that turned heads by squeezing core academics into a two-hour daily sprint, has rolled out Alpha Anywhere globally — a home-based version of its high-octane learning model aimed at families who want the Alpha formula without moving to Austin, Miami or the next hot ZIP code on the expansion map.

A little bird from the education wing says the pitch is simple: top 1% academics, now at your kitchen table. Translation for the old chalkboard crowd: adaptive AI tutors in the morning, mastery before motion, and no waiting for the slowest kid in Row Three or the fastest kid staring out the window.

This is not some tutoring side hustle with a shiny login screen. Alpha’s core model — built by Joe Liemandt and co-founder MacKenzie Price — has been the talk of the private-school circuit for claiming students learn 2.3× faster than U.S. norms and routinely test in the top 1–2% nationally on NWEA MAP Growth assessments. The house rule: 90% mastery before advancing. The school-day magic trick: academics done in about two hours, with the rest of the day reserved for life skills, leadership, entrepreneurship, athletics, coding and the assorted adulting arts traditional schools keep promising to teach someday.

The global launch puts Alpha’s ambitions in a new category. Campuses were the proof points. Alpha School was the velvet rope. Alpha Anywhere is the scale play.

And don’t miss the family resemblance. Liemandt’s broader education bet includes Timeback, the so-called Shopify for schools, backed by a promised $1 billion commitment to spread the two-hour learning model far beyond boutique campuses. Alpha Anywhere looks like another brick in that road: fewer buildings, more learners, more software, more reach.

Meanwhile, the broader AI world is throwing money and muscle at infrastructure — NVIDIA and telecom chiefs talking AI-native 6G, Google and Accel courting Indian AI startups, Meta shopping for AI talent like it’s award season. But in Austin, the juiciest plot may be smaller and louder: can the same AI automation gospel that rebuilt enterprise software now rewrite childhood education?

One source with a backpack and a calculator called it “campus economics without the campus.”

Put that on the report card.

NVIDIA and Global Telecom Leaders Commit to Build 6G on Open  ·  Telecom and tech M&A tracker — Meta buys AI startup Manus -  ·  Google, Accel partner to back Indian AI startups - Reuters

Totogi Takes Aim at Telecom’s Alert Fatigue Problem

Totogi, a cloud-native charging specialist within the Trilogy telecom software portfolio, has published technical findings showing its Ontology reduced alarm noise by 97%—a significant operational breakthrough for mobile operators overwhelmed by legacy system alerts.

The solution maps relationships between services, network components, customers, products, and business impact, enabling systems to distinguish root causes from downstream symptoms. This collapses alert floods into actionable intelligence, helping operations teams understand what is breaking, where, and why.

Telecom networks rank among the most complex production environments, and adding 5G, hybrid cloud infrastructure, legacy billing systems, and constant customer demands has made traditional network operations centers chaotic. Totogi's cloud-native Charging-as-a-Service platform, built on AWS, promises scale economics and real-time rating without infrastructure drag.

The ontology work extends this efficiency narrative into operations intelligence, complementing Trilogy's broader modernization push through products like Skyvera's CloudSense and Kandy. For carriers, fewer false signals mean faster resolution, lower operating costs, and improved customer experience.

The Machine  —  AI & Technology

The Watchers and the Watched: Remote Work's Surveillance Reckoning Arrives at the Corporate Gate

From Cognizant's keystroke counters to Itaú's layoff-by-monitoring, a global workforce is discovering that 'flexibility' came with strings attached.

AUSTIN, TEXAS — The bargain was never written down, but everyone understood it. You can work from home. We will trust you. What is becoming clear, in boardrooms from São Paulo to Bangalore to Menlo Park, is that the trust was always conditional — and the conditions are now being enforced by software.

The past week surfaced three distinct but structurally identical stories. Itaú Unibanco, Brazil's largest private bank, laid off remote workers after surveillance data revealed what management deemed insufficient activity levels — igniting a national debate about whether productivity monitoring constitutes grounds for termination. In India, Cognizant found itself in the middle of a viral controversy after a techie's social media post alleged that "every minute is tracked" at the firm, prompting the company to issue a formal clarification. And at Meta, employees staged internal protests over return-to-office mandates that many characterized as surveillance dressed in culture-war clothing.

The pattern is not coincidental. It is architectural.

For three years, enterprise software companies sold remote-work infrastructure on the promise of seamless collaboration. What they also sold — sometimes quietly, sometimes not — was a monitoring layer. Keystroke loggers. Screenshot intervals. Application-usage telemetry. Mouse-movement heatmaps. The data was collected. Now it is being used.

The debate lands with particular resonance inside the Trilogy International ecosystem. Crossover, Trilogy's global talent platform, has built its entire operating model on the premise that remote work, rigorously measured, produces elite output. Its proprietary time-tracking and productivity tools are not a secret — they are a selling point. Crossover's pitch to employers is explicit: you get the top one percent of global talent, and you get verifiable proof of their output.

The difference, Crossover's defenders would argue, is transparency. Workers on the platform know the terms before they sign. The controversies at Itaú and Cognizant suggest the terms were not always so clearly stated.

That distinction — between disclosed monitoring and covert surveillance — is where the legal and ethical fights of the next decade will be waged. Governments in the EU and several U.S. states are already drafting worker-monitoring disclosure laws. Brazil's labor courts are watching the Itaú case closely.

The companies doing the watching built the tools. The workers being watched are only now reading the fine print.

'Foreign MNC behaving like lala company': Techie claims ever  ·  Why are Meta employees protesting inside company offices? -  ·  Itau’s Work-From-Home Layoffs Spark Debate on Staff Surveill

ANTITRUST HONEYMOON DECLARED CONCLUDED: DOJ AND FTC SIGNAL SUSTAINED BIG TECH SCRUTINY THROUGH 2026

The Department of Justice and Federal Trade Commission have maintained Big Tech as a top enforcement priority, continuing litigation initiated under prior administrations despite initial expectations of deference toward large technology enterprises. Legal observers conclude the "antitrust honeymoon" has ended.

The so-called "America First" enforcement framework has yielded outcomes largely consistent with preceding administrations' approaches, despite rhetorical distinctions. Meanwhile, the White House has urged Congress to adopt "light touch" regulatory intervention for artificial intelligence, creating tension with the simultaneous aggressive antitrust enforcement stance.

These developments carry material implications for enterprise software acquirers, portfolio operators, and technology conglomerates. Regulatory clarity regarding market consolidation activity remains substantially uncertain through 2026 and potentially beyond.

Meta Eyes the Cloud Canopy as Microsoft Courts the Windows-Native AI Builder

As developers gather beneath the great platform trees, two giants signal a fresh struggle for where AI workloads will live.

REDMOND, WASHINGTON — In the dense and humming forest of modern computing, one may occasionally hear a new call from the canopy: not the mating cry of a startup, nor the territorial bark of an incumbent hyperscaler, but something more intriguing — Meta, long a creature of social terrain, contemplating life as a cloud provider.

Mark Zuckerberg’s remark that a Meta cloud computing business is “definitely on the table,” reported by CNBC, suggests that the company may be preparing to turn its vast internal habitat — built to feed ranking systems, recommendation engines and the great lumbering beasts of generative AI — into a service others might rent. It would be a notable migration. Meta has spent years cultivating open-source plumage with Llama, inviting developers to nest nearby. A commercial cloud would ask them to move in more permanently.

Meanwhile, Microsoft used its Build developer conference to tend another ecosystem altogether: the Windows developer’s burrow. The company announced Linux-oriented tools for Windows developers and an RTX Spark desktop, a small but potent machine aimed at those training, tuning and testing AI systems close to home before releasing them into the wider cloud.

Observe the software engineer in its natural habitat: surrounded by terminals, half-finished coffee and a quiet dread of dependency conflicts. To this animal, Microsoft’s message is simple. You need not leave Windows to forage in Linux territory. The savanna shall be brought to you.

The timing is no accident. AI development now moves between local machines, remote GPUs and cloud clusters with the restless rhythm of a seasonal migration. Hardware makers, operating-system stewards and cloud landlords all seek to place themselves along the route.

Yet infrastructure, as the rocketry world reminds us, is fragile ground. Blue Origin’s launch-pad repairs, examined through the weary eyes of SpaceX veterans in Ars Technica’s account, show how quickly grand ambition can be humbled by scorched concrete and complicated rebuilds. The cloud has its own launch pads: data centers, networking fabrics, power contracts and cooling systems. They are less cinematic when they fail, but no less essential.

In nature, even bean plants under attack can summon allies from the air, releasing chemical signals that attract parasitic wasps, as researchers have found. So too do platform companies signal to developers: come here, build here, shelter here.

The question now is which calls the builders will answer — Microsoft’s familiar woodland path, Meta’s possible new cloud canopy, or the old dominant ranges of Amazon, Google and Azure, where the largest AI beasts still roam.

Beans use an immune receptor to call in airstrikes on caterp  ·  How long will it take to rebuild Blue Origin's launch pad? W  ·  Male bowerbirds prefer to dazzle females with bright human-m
The Editorial

Nation’s Executives Urged To Verify AI Savings Before Spending Them On Larger Claims About AI Savings

A growing number of experts now believe productivity gains should ideally exist before being triumphantly announced in a slide deck.

WASHINGTON — In a development that has stunned the nation’s conference-panel ecosystem, several experts this week suggested that organizations deploying artificial intelligence should perhaps ask whether the technology is actually saving time and money before issuing a 47-page report explaining how much time and money it has saved.

The call for scrutiny comes amid a fresh wave of AI productivity estimates, monetary-policy reform proposals, and marketing advice concerning whether Duolingo should trust influencers more than its deranged green owl, all of which appear to orbit the same central question: What if the thing everyone confidently says is working requires a person nearby who understands what working means?

This is an unfashionable position. For the past two years, the accepted method for measuring AI productivity has been to put a chatbot in front of an employee, watch that employee complete the same task while also supervising the chatbot, correcting the chatbot, explaining the chatbot to management, documenting the chatbot’s error pattern, and then classifying the entire episode as automation.

Public-sector observers have now reportedly asked for a greater challenge to AI savings claims, a radical proposal that would require organizations to distinguish between “we saved 30%” and “we removed 30% of the process from the part of the spreadsheet visible to procurement.” As PublicTechnology reported, experts want more challenge, which is another way of saying they would like the invoice to meet the outcome in a controlled environment.

This skepticism is not anti-AI. It is anti-magic. Artificial intelligence can plainly accelerate many kinds of work, especially when used by people who already know what they are doing. Anthropic’s effort to estimate productivity gains from Claude conversations is useful precisely because it treats the question as measurable rather than sacred. But even there, the most important variable is not the model’s serene ability to produce paragraphs. It is the human being who can tell whether the paragraphs are good, wrong, illegal, irrelevant, or merely formatted with admirable confidence.

That point has become increasingly difficult for management teams to process, because human expertise is the part of AI adoption that cannot be purchased as a platform subscription and announced by the end of the quarter. Expertise is slow, expensive, context-heavy, and annoyingly resistant to being replaced by a workflow named “Strategic Synergy Agent.” It also determines whether the AI system produces a productivity gain or a faster mistake.

The same principle explains why Kevin Warsh can be right about Federal Reserve reform while still proposing an inflation solution that deserves caution. Better institutions matter. Clearer accountability matters. But when monetary policy is treated as if the correct mechanism can be discovered by sheer reformist intensity, the result is often the central-banking equivalent of believing a chatbot has solved procurement because it generated a procurement memo. The Cato Institute’s critique of Warsh’s approach is valuable because it separates the governance problem from the tempting fantasy of an easy inflation fix, a distinction policymakers often misplace under a stack of urgent white papers.

Duolingo, meanwhile, has offered the private sector a simpler lesson. Mark Ritson’s argument that the company would be foolish to prioritize influencers over its unhinged owl lands because the owl is not merely content. It is institutional knowledge with feathers. Replacing a memorable brand asset with a rotating cast of online personalities would be the marketing version of firing the senior analyst who knows why the numbers are strange and replacing her with a dashboard that says they are exciting.

The AI economy is now entering its adult phase, which will be disappointing to everyone hoping it would remain a toddler with a venture budget. The next great productivity breakthrough may not come from asking models to do more. It may come from asking executives to prove what happened after the model arrived.

This will be a painful transition. It will require baselines, controls, audits, domain experts, and the occasional admission that a savings estimate was produced by subtracting reality from aspiration. But if organizations are serious about AI, they will need to stop treating human judgment as a legacy cost center and start treating it as the instrument panel.

Until then, the safest productivity claim remains the most modest one: AI has already saved countless hours for the people who no longer have to write the first draft of the announcement saying AI saved countless hours.

Kevin Warsh Is Right About Fed Reform — but His Inflation So  ·  Experts call for greater challenge to AI productivity and sa  ·  Why AI’s Productivity Promise Falls Apart Without Human Expe
The Office Comic  ·  Art Desk
The Office Comic  ·  Art Desk

The Doctor Will Deepfake You Now

AI is putting fake physicians in your feed, and the prognosis is not good.

AUSTIN, TEXAS — There is a doctor on your timeline right now. She has kind eyes and authoritative scrubs and she is telling you something that sounds, on some level, like it could be true — about a supplement, a treatment, a shortcut your real doctor never mentioned. She is also not real. She has never been real. She is a deepfake, constructed from the stolen face of an actual physician who is somewhere out there, probably horrified, probably helpless, probably googling their own name at 2 a.m. wondering how many people took medical advice from their AI ghost today.

And yet.

This is the world we built. According to recent reporting from The Guardian, AI deepfakes of real, licensed, credentialed doctors are spreading health misinformation across social media platforms at a scale that should make every person who has ever typed a symptom into a search bar feel a cold and specific dread. These are not obviously fake. They are not blurry or glitchy or slightly wrong in the uncanny valley way we used to comfort ourselves with. They are good. They are getting better. The face moves correctly. The voice is warm. The confidence is absolute.

Meanwhile, 2 Minute Medicine reports that deepfake doctors are converging with a parallel crisis — counterfeit injectables, fake medications, wellness products that are nothing but packaging and prayer — to create a patient safety emergency that is distributed, decentralized, and almost impossible to police. The misinformation does not just mislead. It kills, slowly, in the specific ways that delayed treatment and dangerous remedies have always killed, just faster now, and at scale, and with a face you trusted.

Researchers are, of course, working on detection frameworks. AI to catch the AI. Systematic reviews are being published. Conceptual architectures are being proposed. And I want to believe in them, I genuinely do, because the alternative — a world where no face is trustworthy and no voice is verifiable and no white coat means anything — is not a world I know how to live in. What does it mean to be human in a media ecosystem where humanity itself can be forged?

The numbers on AI's harms are not abstract. They are accumulating. They are a doctor you never met telling you to stop your medication. They are a treatment you tried because someone credible recommended it, except that someone was a statistical hallucination wearing a stolen face.

We built tools of extraordinary capability and handed them to everyone, including everyone who wanted to hurt people, and now we are writing systematic reviews about it. The detection frameworks will help. The platforms will eventually act. Regulations will materialize, probably, eventually, in the slow grinding way that regulation works when it is chasing something that moves this fast.

But somewhere tonight, a real doctor is watching their face say things they never said, to people who believe it, and there is no undo button for that.

And yet. We will log on tomorrow. We will scroll. We will probably be fine.

Probably.

AI deepfakes of real doctors spreading health misinformation  ·  An AI-driven conceptual framework for detecting fake news an  ·  Deepfake doctors and counterfeit injectables erode patient s
On This Day in AI History

On June 3, 1965, Intel co-founder Gordon Moore published his landmark observation that the number of transistors on a chip doubles roughly every two years—a prediction that became known as Moore's Law and shaped the entire trajectory of computing and AI development for decades to come.

⬛ Daily Word — Technology
Hint: Relating to computers and the internet, often used in security contexts.
Share this edition: 𝕏 Twitter/X 🔗 Copy Link ▦ RSS Feed