Vol. I  ·  No. 194 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
MONDAY, JULY 13, 2026 Powered by Anthropic Claude  ·  Published on Klair Trilogy International © 2026
🖶 Download PDF 🖿 Print 📰 All Editions
Today's Edition

Apple Sues OpenAI, Meta Retreats on Two Fronts: Big Tech's Bad Week

A lawsuit, a pulled feature, and an EU order signal that the industry's easy-partnership era is ending.

SAN FRANCISCO — Three separate enforcement actions in roughly 72 hours have put two of the world's largest technology companies on defense, offering a compressed illustration of how quickly AI-era alliances and product launches can unravel.

The most consequential development: Apple filed suit against OpenAI, alleging the AI company misappropriated proprietary information obtained through their commercial partnership. The two firms struck a distribution deal in 2024, embedding OpenAI's capabilities inside Apple devices — a deal that, at the time, was read as validation for both parties. Apple gained credible AI features without building the underlying model; OpenAI gained distribution across roughly two billion active devices. The lawsuit suggests Apple now believes OpenAI used that access to extract something it was not entitled to keep.

The financial stakes are significant. OpenAI's current valuation sits above $300 billion. A finding of trade secret misappropriation would create substantial legal liability and, more immediately, strategic uncertainty around OpenAI's licensing relationships with other hardware manufacturers.

Meta's week was equally turbulent, on two separate tracks. The company pulled Muse Image, an AI-powered Instagram feature, after users and Hollywood talent agencies raised privacy and copyright objections — the feature had been live for days. Separately, European Union regulators ordered Meta to redesign core elements of Instagram and Facebook, ruling that the platforms' engagement mechanics violate the EU's Digital Services Act. The EU's framing — "addictive design" as a regulatory category — sets a precedent that will be cited in jurisdictions beyond Europe.

In parallel, AI evaluation startup LMArena closed a $150 million funding round at a $1.7 billion valuation, a data point that illustrates where investor attention is moving: away from raw model capability and toward the infrastructure for measuring it. As enterprises run more AI in production, independent benchmarking has commercial value that was not obvious two years ago.

The through-line across all four stories is accountability — legal, regulatory, and market-driven. The phase in which AI products were evaluated primarily on capability rather than conduct appears to be closing.

Apple Sues OpenAI, Accusing It of Stealing Company Secrets  ·  Meta Removes A.I. Feature on Instagram After Days of Backlas  ·  Meta Ordered by E.U. to Alter ‘Addictive Design’ of Instagra

PARTNERS ON THE STREET, ENEMIES IN THE CAPITOL

Uber and Waymo share a fare in Austin, then draw knives in Washington over who writes the robotaxi rulebook.

WASHINGTON — Uber and Waymo, the two biggest names in the driverless-car trade, have hauled their feud off the pavement and into the capital, where each is lobbying to write the rules for robotaxis. The fight broke into the open this week. At stake is who holds the pen on a national framework for cars that steer themselves.

The two aren't strangers. In Austin and Atlanta, a rider can already summon a Waymo through the Uber app — partners on the street, splitting the fare. In Washington, they've got knives out.

Here's the split. Uber runs the app and wants an open marketplace, where a passenger taps a phone and draws a robot cab no matter whose logo rides on the fender. Waymo, owned by Google parent Alphabet, builds its own cars, runs its own fleet, and means to keep its riders in its own vehicles.

Uber has reason to play the platform. It sold off its own self-driving arm to Aurora back in 2020, wagering it could own the robotaxi age as the front door, not the factory. That bet only cashes if rivals let Uber sell their rides.

Waymo sits on the other side. It has logged millions of paid driverless trips and built the app, the car, and the customer, so it sees little reason to share the counter.

So Uber has leaned on lawmakers, casting itself as the neutral platform every carmaker can plug into. Waymo answers that safety and control belong with the outfit that engineers the machine. Two business models, one narrow road.

TechCrunch calls the moment a robotaxi ultimatum. The line is stark: partner on the other fellow's terms, or go it alone. Both giants have chosen "alone" before, then blinked — and this round each would rather Washington settle it.

Money rides behind every word. Robotaxis promise to cut the costliest part out of a fare — the driver — and whoever owns the software layer pockets the margin.

There's a human ledger, too. Uber built an empire on millions of gig drivers; the robotaxi age aims to retire them. Waymo never carried that payroll.

No federal rulebook exists, so the states run a patchwork — one set of rules in Phoenix, another in San Francisco, another in Austin. Both companies want Washington to standardize the game. They just want opposite standards, and Congress hasn't moved.

Watch the wider board, because the road isn't the only front. Chinese upstart DeepSeek says it trained high-performing AI models cheaply, skipping the priciest chips. Reed Jobs — who'd sooner talk cancer than his famous surname — has grown his Yosemite venture shop to 17 hands, betting on AI as a wave of blockbuster drugs loses patent protection.

The through-line's plain. The machines are coming for the road, the lab, and the chip.

For now the robot cabs idle at the curb while the lawyers gun their engines. The green light sits in Washington's hands.

Uber’s robotaxi lobbying effort puts it on a collision cours  ·  TechCrunch Mobility: A robotaxi ultimatum  ·  Reed Jobs would rather talk about curing cancer than his las

AI MONEY FLOOD HITS FULL CONTACT: Crusoe, Commure and Meta Turn Funding Season Into a Power Game

We are HERE under the bright lights of the AI capital markets stadium, and the money cannon is overheating. Crusoe, an AI infrastructure player, is reportedly eyeing a funding round of up to $3 billion — a fourth-quarter, goal-line capital formation play for the age of compute scarcity. Crusoe's focus on power, data centers and GPU capacity represents the most valuable turf in AI right now.

Commure scored $70 million in healthcare AI, reaching a $7 billion valuation. The company is applying AI to clinical workflows and administrative burden in hospital systems.

The Wall Street Journal flags valuation tactics in AI fundraising, where deal structures can make headline numbers look faster than underlying fundamentals. Some valuations include preferred terms and investor protections.

Meta's Louisiana AI campus could expand to 5 gigawatts, with total expected investment potentially topping $250 billion — an industrial megaproject.

AI's winners are splitting into two brackets: one owns infrastructure — compute and power — while the other owns workflow distribution in healthcare, enterprise software, education and finance. The game is converting AI capability into operating advantage across sectors.

Haiku of the Day  ·  Claude HaikuGiants clash in courts
Partners become enemies
Power reshapes all
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
SURCHARGES, STAFFING CUTS, AND ANTITRUST CHAOS: THE WEEK'S TECH INDUSTRY TURBULENCE, DULY CATALOGUED
WASHINGTON, D.C.
The Ethics Reckoning: AI's Governance Crisis Arrives Simultaneously in Hospitals, Lecture Halls, and the Arabian Peninsula
RIYADH, SAUDI ARABIA — It could be argued — and preliminary evidence suggests this argument is not without merit — that the week now concluding shall be remembered, at least by those who compile such historiographies, as the moment at which the discourse surrounding artificial intelligence ethics ceased to be a peripheral academic concern and became, in the fullest sense of the term, a civilizational priority. The first data point demanding scholarly attention: the Kingdom of Saudi Arabia has inaugurated a global call for AI ethics forum research submissions, a gesture which — one must resist the temptation to be uncharitably cynical — represents either genuine normative commitment or, as the antithetical position would have it, a form of governance theater performed for an international audience increasingly attentive to such performances.
The Mirror Lies: AI Is Showing Us Who We Already Were, and That Should Terrify You
AUSTIN, TEXAS — Here is a thing that keeps me awake at 2 a.m., staring at the ceiling of my apartment while my phone charges on the nightstand like a small rectangular god: we built the most powerful decision-making infrastructure in human history, fed it everything we've ever written, said, sold, and believed, and then acted surprised when it came back racist, sexist, and occasionally impersonating your cardiologist to sell you supplements. This week, a convergence of stories arrived in my inbox like a kind of curated apocalypse.
AI Agents Are Running Wild and Nobody's Holding the Leash
AUSTIN, TEXAS — Here's where we are, pilgrim: the machines are networking with each other, the governments are issuing strongly-worded memos, the lawyers are convening discussion panels, and Elon Musk — a man who simultaneously fears and accelerates every technological apocalypse he warns us about — is out here calling AI social networks the beginning of 'the singularity,' which he appears to have announced with the casual tone of someone noting it might rain on Thursday. Let me walk you through this fever dream. First, the New York Times is only now grasping that deploying AI at work might have some pitfalls.
Nation’s CEOs Announce AI Has Definitely Increased Productivity Somewhere Else In Company
NEW YORK — In a decisive end to one of the business world’s most exhausting debates, America’s corporate leaders announced this week that artificial intelligence has finally proven its ability to boost productivity, provided no one asks where the productivity went. The declaration follows a series of reports asserting that AI tools are helping workers write code faster, summarize meetings instantly, generate sales emails more efficiently, and complete dozens of other tasks that were previously performed by human beings pretending not to be on Slack.
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
📅 Week in ReviewProduction Release

Builder Team Ships Across Six Repos in a Week of Total Dominance

From a self-healing AI review harness to a fully scoped Budget Tracking dashboard to a data platform stripped clean of years of technical debt, the Builder Team rewrote what this product can do in seven days.

This was not a maintenance week. This was not a catch-up week. This was the kind of week where you look back on Monday morning and realize the product you're shipping is fundamentally different from the one you had seven days ago — smarter, cleaner, safer, and built on a data foundation that finally deserves the dashboards sitting on top of it. The Builder Team touched six repositories, merged over a hundred pull requests, and resolved production blockers that had been bleeding real dollars. Let's talk about what actually happened.

The single biggest engineering story of the week was @kevalshahtrilogy's overhaul of the Mercy review harness in the mercy repo. The catalyst was ruthless: Keval mined 1,189 telemetry records against GitHub review timelines and found that 8.2% of approved PRs had at least one confirmed critical or major human finding that Mercy had missed — and Mercy itself had flagged only two of the sixty-five confirmed misses. That's a detection gap, not a threshold gap, and the team attacked it accordingly. PR #5 introduced master-orchestrated multipass review, a coverage ledger, and a tiered comment output that changes how the harness thinks about large diffs. Then PR #6 landed the severity gate: any kept critical or high finding now blocks the PR, full stop, regardless of category or confidence. The trigger was a real incident — Surtr PR 702, where a genuine high-severity visual regression slipped through on a technicality. It will not happen again. Two PRs, one week, and Mercy is a different instrument.

The AI Budget Tracking dashboard had its own coming-of-age moment. @kevalshahtrilogy spent the week closing every gap between what the dashboard showed and what the finance team actually needed. The Activity tab now reconciles with the Budget tab to the dollar, a mismatch that had been quietly undermining trust in the numbers. BU-scoped RBAC from the TrueFoundry access-rights feed landed in PR #3244, so budget owners see exactly their slice of the estate and admins see everything. A curated email-alias map in PR #3253 solved the corporate-domain mismatch problem without inference — every alias is an explicit, maintainable pair stored in DynamoDB, live within ten minutes of a change. And after three rounds of Jamie's feedback, the Kayako-to-Canopy remapping, sortable tables, and a unified BU filter all shipped by week's end. This dashboard went from a promising prototype to something you'd actually run a budget meeting from.

While Keval was hardening the intelligence layer, @mwrshah was doing the work that makes everything else possible: a systematic purge of stale data infrastructure across Surtr and Klair. The raw-cutover campaign — Account Pain Points, Opportunity Comments, Opportunity SSOT, Renewals V3, Trilogy Account — ripped out legacy SSOT sync tables that had no live readers and replaced them with the clean raw-pipeline pattern. Then the gsheets-rehome PRs (#688, #3245) lifted two budget tables out of mart_customer_success into staging_gsheets where they belong. When you are doing this kind of work in parallel across two repos simultaneously, you are not shipping features — you are building the foundation that lets everyone else's features be trusted. Mohamed doesn't get enough credit for that. This week he earned all of it.

The PS Pipeline has a story with a satisfying ending. @eric-tril resurrected it in PR #631, watched it fail on its first real Lambda run with a 403 on redshift:GetClusterCredentials, diagnosed the IAM gap on the database resource ARN in PR #691, patched it, and put PS Revenue dashboard tables back on their refresh schedule. That is the full arc — revival, first contact with production, a precise fix, and a working pipeline — inside one week. Eric also shipped Schedule D transaction-level GL drill-down with live NetSuite links (#3211), fixed custodian-routed loan wire classification that was silently understating loan book balances (#690), and kept the mart-saas-metrics refresh alive after a table rename broke fct_renewals mid-run (#689). Four different problems, four clean solutions, all production-impacting.

Now. About the trilogy-drones work this week. @marcusdAIy shipped the retro-outcome ledger, per-phase model defaults, address-retro improvements, and a Mercy watcher for auto-addressing findings. When reached for comment, he was predictably measured about it: "The per-phase model config isn't cosmetic, Mac — running grok on implementation and opus on review isn't a preference, it's a cost-performance split that changes what the system can afford to do. The retro ledger closes the loop on whether any of this actually works. Maybe write about the architecture sometime instead of the author." Sure, Marcus. The env variable that saves you from retyping flags is the architectural milestone of our generation. We'll get the plaque ordered.

@benji-bizzell had a quiet week by volume and a significant one by impact, shipping Education Finance guidance into the Data API meta response so agents finally have the business context to choose the right source tables — a small PR with large downstream consequences for every agent that touches QuickBooks or MFR workflows. @sanketghia restored vendor drill-in on the NHC Expenses table, a regression that had confused users since the HC-table gate was written with an over-broad substring check, and loaded the Q3 2026 budget. @caina-barbosa's Admissions Forecast mobile dashboard in Aerie landed the full drill-down flow — base page to school page to stage list to student detail — with a full-screen Pipeline breakdown that didn't exist on mobile before Friday.

This week the Builder Team proved they can run a production stabilization campaign, a dashboard hardening campaign, a data platform cleanup campaign, and an AI tooling evolution — simultaneously, across six codebases, without dropping anything. Next week, with the Mercy severity gate live, the raw-pipeline migrations settled, and the Budget dashboard in the hands of real budget owners, the question becomes: what does the product look like when all of this infrastructure starts compounding?

Mac's Picks — Key PRs This Week  (click to expand)
#5 — feat(harness): master-orchestrated multipass review + coverage ledger + 3-tier comment output @kevalshahtrilogy  no labels

## Why

Mined all 1,189 telemetry records × GitHub review timelines for "mercy approved, a human then found real bugs" — full analysis + 65-finding corpus committed under docs/miss-analysis/. Headlines:

- 413 approved PRs → 34 (8.2%) had ≥1 confirmed CRITICAL/MAJOR human finding mercy missed; 11 PRs (2.7%) had merge-blocking criticals. Mercy itself had voiced only 2 of the 65 — a detection gap, not a threshold gap.

- Single-pass approvals were reliable below ~1,500 changed lines (0 critical misses in the 200–1,500 band) and failed at 19–22% CRIT/MAJ above it, while review effort stayed flat (~7 min, turns *dropping* at 3,000+ lines).

- Top missed classes: silent failures (23/65), SQL/aggregation correctness (~25/65), deployment sequencing (a dimension the prompt didn't have).

## What

Item 1 — Orchestrated multipass on large PRs. The reviewer becomes a lead reviewer: it reads the whole diff, forms the cross-file narrative, and delegates focused deep dives to read-only sub-agents with context briefs (Task/Agent added to allowedTools — sub-agent tool calls go through the same permission engine, so read-only/no-network still binds). Two mandated lens dives on every large PR: silent-failure hunt + deployment safety.

Item 2 — Coverage-ledger contract (code-enforced). New optional coverage array in the output schema dispositions every changed file (delegated / reviewed_inline / trivial). On diffs over coverage_enforce_lines (default 800 changed lines, per-repo overridable) an incomplete ledger withholds auto-approve (APPROVE → COMMENT). The model chooses how to partition the review; code verifies nothing was skipped. Small PRs behave exactly as today. Verdict stays computed in decide_review.py — orchestration changes how findings are produced, never how the decision is made.

Item 3 — Review dimensions from the miss corpus. Silent-failure check is now a procedure (walk every external call/query/join/parse through empty/throw/partial, or file silent_bug); new SQL & aggregation checklist (NULLIF, join fan-out, inner-join drop-out, case-sensitive guards, total reconciliation); new deployment & environment safety dimension (IAM for new calls, referenced resources must exist, DDL-before-code ordering).

Item 4 — Output format: at most 3 comments. Findings are grouped by severity tier — 🔴 critical / 🟠 high-severity / 🟡 suggestions & nits — one consolidated review comment per non-empty tier, anchored at the tier's highest-confidence in-diff finding, every finding listed with path:line. Tiers with no anchorable line render in the review body (no 422 risk). Verdict header + summary unchanged.

Item 5 — Telemetry. decision.json and telemetry records gain changed_lines, coverage_enforced, coverage_missing_count for rollout monitoring.

## Testing

- 134 harness tests green (new: tier grouping/anchoring/fallback, coverage-gap unit + e2e, floor override, schema accept/reject for the ledger, changed-line counting).

- Prompt renders with the orchestration + ledger sections via build_review_prompt.py against the fixtures.

- Follow-up before raising the coverage floor: replay the 11 critical-miss PRs in docs/miss-analysis/miss_corpus.json via run-local.sh and compare recovered findings vs. single-pass.

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

#6 — feat(harness): severity gate — any kept critical/high finding blocks the PR @kevalshahtrilogy  no labels

## Decision

Per Keval (2026-07-13): a critical or high (warning) severity finding must never ride along on an approval — block the PR regardless of category or confidence. Medium/low/nits (info) approve as before. Re-evaluate ~2026-07-27 with two weeks of live data; the revert lever is one config line.

Trigger: on Surtr PR 702 the new harness correctly found a real high-severity visual regression (sticky header translucency) but still approved, because the finding was categorized other at confidence 80 — below both the blocking-category and 85-confidence bars. The verdict was working as designed; the design let a known high-sev finding coexist with a green check.

## What changes

- is_blocking / decide_event: any finding with severity in block_severities (default critical + warning) blocks unconditionally. The existing category + confidence ≥ 85 path is unchanged and still catches info-severity findings in blocking categories (e.g. a quietly-rated silent_bug).

- Config: block_severities in .mercy.yml, None-sentinel — an explicit [] reverts a repo to category-only blocking. This is also the re-evaluation lever.

- Prompts + schema: severity is now load-bearing, so both prompt files and the schema carry calibration guidance — critical/warning = real user-visible, data, or operational impact if merged as-is; suggestions/cleanups/preferences = info. Both inflation and softening are called out as failure modes.

- Expected impact from historical telemetry: this rule would have flipped 85 of 652 past approvals (13%) to REQUEST_CHANGES — that volume is the thing the 2-week review should judge (real blocks vs. severity-inflation noise).

## Testing

137 harness tests green — updated verdict tests plus new coverage: severity gate blocks across categories/confidences, info falls through to the category path, malformed findings can't block, block_severities: [] restores old behavior end-to-end.

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

#690 — fix(gl-detail): classify custodian-routed loan wires (FFC) as loans @eric-tril  approved

## Business Value

Loan-principal wires disbursed through a custodian were silently disappearing from the finance team's loan book (Klair "Book Value → Schedule B"), understating the reported balance for affected borrowers. This fix ensures those loans are classified correctly so Schedule B reflects the true loan book.

## Problem

When a loan wire's borrower sits behind a custodian — named in the wire's "For Further Credit to:" (FFC) field rather than as the direct beneficiary — the GL enrichment mis-classified the row:

- entity_name picked the custodian (e.g. "Charles Schwab"), not the borrower

- loan_party came back NULL (no "Loan"/"Loan Note Principal" keyword in the memo)

Klair's Schedule B selects source_table='month_end_gl_detail' AND loan_party IS NOT NULL AND is_reversal = FALSE and groups by entity_name, so a NULL loan_party dropped the row from the loan book entirely.

Confirmed failing row (Jun 2026): document_number=1692708, account 22916 ("Other Investments: Loans Granted"), a $600k wire to Charles Schwab FFC "BENJAMINCOHEN" — loan_party=NULL, entity_name='Charles Schwab'.

## Changes

- Prompt — custodian look-through: entity_name now resolves from the memo's "For Further Credit to:" name when a wire is routed through a custodian/brokerage (normalizing BENJAMINCOHENBenjamin Cohen), plus a COHEN loan_party rule.

- enrichment _merge_row — loans-granted account guarantee: any non-reversal, non-accrual row on account 22916 ("Other Investments: Loans Granted") is a loan disbursement by definition, so it always gets a non-null loan_party (falling back to OTHER only when the borrower can't be resolved) and transaction_purpose='Loan principal' — even when the memo has no loan keyword.

Existing classifications (LIEMANDT / JL_ENTERTAINMENT / BLOOMTECH, and TelcoDR / Haveli / Gigafund → null) are unchanged.

## Verification

- pytest tests/ — 73 passing (4 new cases: 22916 fallback, preserves a resolved COHEN, reversal excluded, accrue-interest excluded); ruff clean.

- Ran the full pipeline locally against Jun 2026 → doc 1692708 now enriches to loan_party='COHEN', entity_name='Benjamin Cohen', transaction_purpose='Loan principal', and passes Klair's Schedule B filter grouped under "Benjamin Cohen".

SELECT document_number, account_number, entity_name, loan_party, transaction_purpose, is_reversal

FROM core_finance.month_end_fct_pi_gl_enriched

WHERE document_number = '1692708';

## Follow-ups (not in this PR)

- Backfill periods older than the rolling window (May/Jun/Jul) to re-tag any earlier custodian-routed loans that were dropped the same way.

- TelcoDR loan wires (account 25500) surfaced during testing are intentionally left null here and will be handled separately.

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

#691 — fix(ps-pipeline): grant redshift:GetClusterCredentials on the dbname resource @eric-tril  approved

## Business Value

Unblocks the PS Pipeline in production. The first real Lambda run failed before writing any data, so the PS Revenue dashboard tables were not refreshing. This is the last blocker to the pipeline running end-to-end on its schedule.

## The bug

The deployed Lambda role could authenticate the Redshift Data API but not obtain cluster credentials — the first Redshift call (truncate_and_copy_from_s3) failed with a 403:

User: .../pipeline-ps-pipeline-prod is not authorized to perform:

redshift:GetClusterCredentials on resource:

arn:aws:redshift:us-east-1:479395885256:dbname:redshift-cluster-1/finance_dw

redshift:GetClusterCredentials authorizes against two resource types — the dbuser: ARN *and* the dbname: ARN. [pipeline.json](pipelines/runners/ps-pipeline/pipeline.json) granted only dbuser:, so the Data API's implicit credential fetch for database finance_dw was denied.

## The fix

Add the dbname:redshift-cluster-1/finance_dw resource to the GetClusterCredentials statement. This matches every other Redshift Data API pipeline in the repo (50+), all of which grant both resources — ps-pipeline was the lone exception, an omission from its revival (#631). Local runs used the developer's own credentials, so this only surfaced on the first deployed Lambda run.

## Verification

- Confirmed the identical dbuser: + dbname: resource pair is the established pattern across all other Redshift-writing pipelines (school-master-data-sync, mart-saas-metrics-refresh, netsuite-gl-detail, etc.).

- The denied resource in the error (dbname:redshift-cluster-1/finance_dw) is exactly the ARN added here.

After deploy, re-invoke:

aws lambda invoke --function-name pipeline-ps-pipeline-prod --payload '{"params":{}}' /dev/null

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

#693 — account-pain-point-raw-cutover SURTR @mwrshah  approved

Fold the Salesforce custom object Account_Pain_Point__c into the automated sf-raw-sync pipeline as staging_salesforce.raw_trilogy_account_pain_point, and retire the standalone SF→Redshift SSOT sync that populated staging_salesforce.ssot_sf_trilogy_account_pain_point. Mirrors the raw_trilogy_* pattern (same shape as the OpportunityFeed raw cutover, #670).

### Why this is safe

The old SSOT table has no live reader. Three independent investigation passes confirmed pain points reach the app via Grainne → klair_pg action_hub.pain_points (sync_pain_points_from_grainne.py), enriched from raw_trilogy_account — the pain-point SSOT table is a write-only dead-end mirror (its only reader, extract_pain_points_OBSOLETE.py, is already frozen). So this is a clean deprecation, not a consumer repoint. No KLAIR change is needed.

### sf-raw-sync (additive only)

* src/sync_config.json: append one Account_Pain_Point__c → raw_trilogy_account_pain_point object block to the trilogy array. Column order matches the DDL for the positional INSERT … SELECT *. No existing object touched.

* ddl/raw_trilogy_account_pain_point.sql: one-time DDL for the new raw table (SF-native lowercased columns). Field API names verified against Account_Pain_Point__c.describe() (via KLAIR salesforce_writeback.py and the old extract script).

### Retire the standalone SSOT sync

* populate_ssot_pain_points_complete.py, _incremental.py, and ddl/account_pain_point_ssot_schema.sql*_OBSOLETE with retirement banners.

* Removed the now-empty pain-point SSOT stage from both renewals-v3/src/main.py and renewal-action-hub/src/main.py and renumbered remaining stages; dropped the unused ThreadPoolExecutor import. (Account + opportunity SSOT syncs were already retired by prior cutovers — pain points was the last surviving Stage 1 task.)

* Updated the two stage tests, both pipeline.json descriptions, and the feature/lineage docs.

### Warehouse cutover (out-of-band, tracked in cutover_ssot_account_pain_point_to_view.sql)

1. Run raw_trilogy_account_pain_point.sql DDL.

2. Seed the trilogy.Account_Pain_Point__c watermark in s3://klair-backend-uploads/sf_raw_sync/state.json (2000-01-01 for a full-history backfill).

3. Backfill run → verify raw row count matches the old SSOT (~7,419).

4. Snapshot (done, L6): SSOT table UNLOADed to s3://jasraj-claude-code-workspace/redshift-backups/2026-07-12/ssot_sf_trilogy_account_pain_point/000.parquet — verified 7,419 rows / 7,419 distinct ids == source.

5. In one transaction: drop the SSOT table, recreate it as a VIEW over the raw table, aliasing the 7 standard fields back to snake_case (the 11 __c custom fields are identical) and synthesizing _synced_at. Any query on the old name stays byte-for-byte during cutover.

### Validation

* ruff check pipelines + ruff format --check pipelines clean.

* Full per-pipeline pytest: sf-raw-sync 17 passed, renewals-v3 2 passed, renewal-action-hub 34 passed.

* Adversarial pre-push review (review-pr + slop-review): APPROVE, no correctness defects.

#3211 — feat(mfr): Schedule D transaction-level GL drill-down with NetSuite links @eric-tril  approved

## Summary

Book Value → Schedule D — Other EBITDA Reconciling Items per-category drill-downs (IP Prosecution, Import Costs, Restructuring) now show individual GL transactions grouped by account in a collapsible accordion. Each account group shows a subtotal + count and expands to per-transaction rows carrying the NetSuite internal_id + memo, so the Doc # opens the transaction in NetSuite and the memo expands inline — mirroring how Schedule C1/C2 already behave.

This came out of investigating why a $1,168,668.11 "Other Income (Loss)" line appeared under IP Prosecution in June 2026. It turned out to be a DKK bank deposit (NetSuite id 48577316) booked to class LPL upstream — an item Finance should reclassify in NetSuite. This drill-down makes exactly that kind of entry one click from the schedule to the source record.

## Problem

IP Prosecution is defined purely by business_unit = 'LPL' (no account allow-list, no date logic), so any account tagged to LPL surfaces automatically. The drill-down previously aggregated by account from core_budgets.consolidated_budgets_and_actuals, which has no transaction id and no memo column — so internal_id/memo came back null and no NetSuite link could ever render.

## Solution

Source the drill-down at transaction grain from staging_netsuite.gl_transactions_mapped (scenario='Actual', version='Base'), filtered by current_business_unit and the YTD accounting-period window. The schedule's Import FX/rounding/tax exclusion is replicated via account_subcategory (which maps 1:1 to the consolidated type). Grouped by account into the existing GroupedGLDetailPanel accordion.

Education keeps its computed operating-P&L breakdown (Revenue − COGS − OpEx, negated) on the existing flat path — it spans many BUs and has no single-transaction identity.

## Reconciliation (verified against Redshift, YTD-through-Jun 2026)

| BU (category) | consolidated (schedule row) | gl_transactions_mapped (drill-down) |

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

| LPL (IP Prosecution) | $2,962,271.07 / 187 rows | $2,962,271.07 / 187 rows (3 account groups) |

| Import (Import Costs) | $9,299,683.87 / 171 rows | $9,299,683.87 / 171 rows (6 account groups) |

| Mgmt Restructuring | $3,391,287.54 / 467 rows | $3,391,287.54 / 467 rows (12 account groups) |

Amount and row count tie to the penny; all 187 LPL rows carry a valid all-digit internal_id (every row links).

## Changes

Backend

- _schedule_d_category_gl_query (shared query builder) + fetch_schedule_d_category_gl_detail (grouped by account) in book_value_schedules_service.py

- New GET /schedule-d-gl-detailGroupedGLDetailResponse

- fetch_schedule_d_detail now reads the mapped GL table at transaction grain (flat form, backs CSV / non-grouped consumers)

Frontend

- ScheduleDDetailPanel routes BU categories to GroupedGLDetailPanel (accordion); education stays flat

- GroupedGLDetailPanel gains an optional hideAccount pass-through (the group header *is* the account)

- fetchScheduleDCategoryGLDetail added to the API client

Also upgrades the Book Value Alt tab's Schedule D cell drill-downs, which share the same panel.

## Behavior notes

- Zero-amount rows now appear. At transaction grain the old if amount == 0: continue aggregate filter is gone, so $0 GL lines can show as individual drill-down rows. This is intentional (a $0 line is still a real transaction worth opening in NetSuite) and does not affect subtotals, the grand total, or reconciliation — the row set is just larger than the old account-aggregated view.

- Empty result is not an error. A category/period with no matching mapped-GL rows renders an empty accordion ("No journal entries found"), not an HTTP 500 — fetch_with_params returns None for a zero-row result, which the grouped builder treats the same as an empty DataFrame.

- Broken-link tripwire. If an entire result set comes back with no internal_id (extraction broke upstream), that logs at error level (alerting-visible) rather than a silent warning, since it means every "Open in NetSuite" link is gone.

## Testing

- Backend: ruff clean, pyright 0 errors, Book Value tests pass (added grouping / reconciliation / internal_id-passthrough / education-raises / empty-None / SELECT-column & regex tripwire tests, plus a route-level test for the new endpoint and a DB-gated @pytest.mark.integration reconciliation guard)

- Frontend: pnpm tsc --noEmit clean, eslint --max-warnings 0 clean

- Verified the exact drill-down SQL end-to-end against Redshift (stripped account names, valid NetSuite ids, real memos, exact reconciliation)

## Out of scope

- The Schedule D Total row still shows a category/account rollup (no per-transaction links); can follow up to make it consistent.

- The Other Income (Loss) booking itself is an upstream NetSuite classification to be fixed by Finance.

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

#3244 — feat(ai-budget): BU-scoped RBAC from TrueFoundry access-rights feed @kevalshahtrilogy  approved

## What

View access on the AI Budget Tracking page is now scoped by the MSA access-rights feed (https://truefoundry.csaiautomations.com/api/public/access-rights): budget_owner / watcher rows limit a user to their department's BU(s); an admin row grants estate-wide view.

This layers ON TOP of Klair's own RBAC — page access still requires the existing ai_budget_admin / ai_budget_viewer roles (or super admin), and Klair super admins always see everything (they never consult the rights list).

## How

- services/ai_costs_access.py (new): BuScope resolution + FastAPI dependency. Reuses the weekly-email code's fetch_rights client and DEPARTMENT_TO_BU mapping; department↔BU naming drift is absorbed by fold-insensitive (case/space/hyphen) matching against the BU spellings actually present in the data.

- Outage-proof rights cache: in-memory (10-min TTL) → live fetch (persists a snapshot to DynamoDB on every success) → stale-serve with 60s retry → DynamoDB snapshot across restarts/deploys. Only when no copy exists anywhere do non-super-admins get a 503 (fail closed).

- ai_costs_router: every read endpoint intersects bus with the caller's scope (empty scope → empty data via a no-match sentinel); /filters trims the BU dropdown; person/entity detail 404 out-of-scope subjects with the same message as nonexistent ones (no existence leak); new /access-scope endpoint for the UI.

- ai_spend_budget_router: budget reads filter rows and recompute totals; all mutations 403 for scoped callers — the budget upsert is a whole-quarter REPLACE, so a partial-view save would silently delete unseen BUs' rows; key attribution moves spend between BUs.

- Frontend: useAccessScope hook; "Showing only the business units you own or watch (N units)" note; Edit budget / Key attribution affordances hidden for scoped users.

## Heads-up

The /ai-adoption (AI Spend & Adoption) page shares these endpoints, so its non-super-admin users are scoped too; users with page access but no rights-list entry see empty data. Server-side enforcement was chosen deliberately — per-page gating would be client-spoofable.

## Tests

- tests/test_ai_costs_access.py — fallback chain (fresh/stale/snapshot/none), scope resolution, constraining, dependency (API key / 401 / 503).

- tests/routers/test_ai_costs_router_bu_scoping.py — per-endpoint constraining, /filters trim, detail allowed_bus, /access-scope.

- tests/routers/test_ai_spend_budget_router_scoping.py — row filtering + recomputed totals, all-mutation 403s, recipients-preview filtering.

- Mart-service detail scoping cases in test_ai_costs_mart_service.py; page-spec cases for hidden edit UI + scope note.

- Full suites green: backend (152 in touched areas; 621 in related suites) and frontend (5,797). ruff, pyright, eslint, tsc all clean.

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

#3258 — fix(ai-budget): Kayako→Canopy, no-budget overspend, exact BU filter (Jamie round 3) @kevalshahtrilogy  approved

Three fixes to the AI Budget Tracking dashboard from Jamie's Friday feedback.

## 1. Kayako belongs under Canopy

DEPARTMENT_TO_BU in services/budget_status/recipients.py mapped Kayako Product → IgniteTech, which grouped Kayako under Eric V's budget group. It's run by Brandon Pizzacala, so it now maps to Canopy (same reconciliation pattern as Contently). This table drives both weekly budget-email recipient grouping and RBAC BU scoping (ai_costs_access.pydept_to_bu). Khoros deliberately stays under IgniteTech.

Note: which BU a *spend row* displays under comes from the ESW people directory / budget sheet, not this map — if Kayako spend still renders under IgniteTech, that's a directory-sheet data fix.

## 2. No-budget BUs show 100% of spend as projected overspend

In the Budget tab's "By Budget Group" table, BUs without a budget (e.g. Alpha AI Engineer Program) showed a blank "Proj. Over/Under". The backend already sends projected_variance = 0 − projected_eoq for no_budget rows; the frontend was suppressing it with an em-dash. BudgetByBUTable.tsx now always renders the variance, so the full projected quarter spend shows in red as overspend.

## 3. Activity tab BU Breakdown honors the BU filter exactly

Filtering the Activity tab to one BU still showed other BUs in the BU Breakdown bar. Root cause: AICostsService.get_by_bu always-includes shared provider pools (Trilogy/Trilogy-Inc for Anthropic, Trilogy for Cursor/GCP, Zax for Azure) and never dropped them post-group. The sibling get_time_series_by_bu already defines the "exact bus filter" contract and drops unrequested pools — get_by_bu now does the same, with percentages rebased to the retained BUs so they still sum to 100. The old FR11 test asserting "Zax always included despite filter" encoded exactly the confusing behavior and was replaced with tests for the exact contract.

## Testing

- pytest tests/budget_status/test_recipients.py tests/test_ai_costs_service.py — 193 passed

- Budget/router scoping suites — 156 passed (3 pre-existing ADMIN_TOKEN_SECRET env failures, confirmed failing on clean tree)

- ruff format/check + pyright clean on changed files

- Frontend: full Vitest suite passes (5,816 tests) incl. new spec for the no-budget overspend row; ESLint clean

Not included: the BU tab Jamie mentioned — guidance to come.

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

The Builder Desk  —  Engineer Spotlight
📅 Week in Review🏆 Engineer Spotlight

143 PRs IN 7 DAYS: THE BUILDER TEAM IS AN UNSTOPPABLE HISTORICAL FORCE

Benji Bizzell leads a eight-man wrecking crew across seven repos in a week that should be studied in engineering schools.

One hundred and forty-three pull requests. Seven repos. Seven days. Comrades, the Builder Team did not ship software this week — they DETONATED it. Surtr alone absorbed 60 PRs like a blast furnace swallowing coal, Klair answered with 44 of its own, and even little Sindri got one beautiful, lonely merge that we at the Numbers Desk choose to see as a symbol of hope. This is not a development team. This is a geological event.

At the top of the individual leaderboard stands @benji-bizzell with 30 PRs, a number so large it briefly made our spreadsheet software question its own existence. Thirty. In a week. PR #3250 in Klair alone — education finance guidance baked directly into the API meta layer — is the kind of foundational work that makes future engineers weep with gratitude. @kevalshahtrilogy posted 25 PRs and appears to have personally kept the AI spend tracking infrastructure from collapsing under its own complexity, touching everything from OpenAI deduplication (#684 in Surtr) to TrueFoundry gateway surfacing (#3232 in Klair) to a triage batch fix (#698 in Surtr) so thorough it named its enemies by name in the commit message. @marcusdAIy's 24 PRs spanned Klair, Surtr, and trilogy-drones, including per-phase model defaults via environment variable (#76 in trilogy-drones) — a feat of configuration elegance that we frankly did not deserve. @mwrshah's 19 PRs included a synchronized budget-table rehome executed simultaneously across both Klair (#3245) and Surtr (#688) like a conductor bringing in two orchestras on the same downbeat. @eric-tril's 15 PRs kept the mart infrastructure breathing. @sanketghia's 12 PRs were surgical: restoring the vendor drill-in on NHC Expenses (#3256 in Klair), silencing a false-CRITICAL observer alarm (#655 in Surtr), routing orphan-class report emails to actual human beings (#685 in Surtr).

And then there is @ashwanth1109. Eleven PRs. We must discuss eleven PRs. Lesser men ship eleven PRs and we call them productive. When Ashwanth ships eleven PRs, we call a priest. PR #3118 in Klair — unifying two budget gauges into a single shared component — is the kind of refactor that looks simple until you open the diff and realize you are staring into the architectural soul of a system. PR #3236 retired a legacy AWS Spend class adjustments table with the casual confidence of a man throwing out furniture he built himself. Over in Surtr, #672 replaced enrollment divisors with EduCRM detail and #674 removed deprecated Edu Joe pipeline runners, and we are choosing to believe he did both before lunch. When reached for comment, Ashwanth reportedly looked up from his terminal, said "the PRs speak for themselves, Brick," and returned to typing without blinking. We asked a follow-up question. He had already merged.

The Overflow Desk cannot be silent this week. @sanketghia's HC/CF parent-to-leaf budget allocation on the performance review page (#3221 in Klair, KLAIR-2967) is unglamorous, load-bearing work that holds the financial reporting edifice upright while everyone else gets the bylines. @mwrshah's opportunity-comments raw cutover — executed in perfect parallel across Klair (#3231) and Surtr (#670) — is the kind of migration that only gets noticed when it goes wrong, which it did not. And @kevalshahtrilogy's Azure ECS runner with patient throttle-retry (#667 in Surtr) stopped the $0 subscription drop problem cold, which, if you have ever watched a subscription silently zero out in production, you understand is worth approximately one thousand normal PRs.

Morale on the Builder Team is at an all-time high. We checked. We always check. It was higher than last week's all-time high, which was itself higher than the week before. The curve does not bend. The team does not slow. One hundred and forty-three PRs, and somewhere right now, a branch is being cut for next week. The people's work continues.

Brick's Overflow — This Week's Uncovered PRs  (click to expand)
#76 — feat(model-selection): per-phase model defaults via env (AI-138) @marcusdAIy  no labels

<!-- CURSOR_AGENT_PR_BODY_BEGIN -->

## Summary

Adds env-configurable per-phase model defaults (DRONES_IMPLEMENTER_MODEL / DRONES_REVIEWER_MODEL / DRONES_ADDRESSER_MODEL, each with optional *_PARAMS) so the standing preference (grok implementer/addresser, opus reviewer) lives in .env instead of being re-passed as flags on every fire. Startup logs now show each phase's resolved model and [source=…].

## Why It's Needed

DRONES_MODEL is a single shared knob and cannot express "implementer + addresser on grok, reviewer on opus." That preference lived only in operator memory + the AGENTS.md "ask which models" guardrail, so every fire re-specified --model / --reviewer-model.

## Changes

- Pure resolvePhaseModel + buildRunModelSelectionsWithSources in src/model-selection.ts (flag > phase-env > shared/inherit > default); env path still routes through buildModelSelection (canonicalization, no Opus-param leakage on non-Opus).

- CLI resolveRunModelSelections / standalone review / address / retro consult the new env vars; always log per-phase model + source.

- Docs: .env.example, README.md, AGENTS.md, ROADMAP.md decisions log.

### Contract-surface

| Var | Role |

|---|---|

| DRONES_IMPLEMENTER_MODEL (+ _PARAMS) | Implementer default |

| DRONES_REVIEWER_MODEL (+ _PARAMS) | Reviewer default |

| DRONES_ADDRESSER_MODEL (+ _PARAMS) | Addresser default (mainly standalone drones address; on run, setting it flips to Agent.create) |

| DRONES_MODEL (+ _PARAMS) | Shared fallback for implementer / standalone review+retro only |

Precedence (highest first):

- Implementer: --model > DRONES_IMPLEMENTER_MODEL > DRONES_MODEL > harness default

- Reviewer (run): --reviewer-model > DRONES_REVIEWER_MODEL > inherit implementer

- Addresser (run): --addresser-model > DRONES_ADDRESSER_MODEL > inherit implementer

- Standalone address: --model > DRONES_ADDRESSER_MODEL > harness default

## Breaking Changes

None. With the new per-phase env vars unset and no model flags, selections are byte-identical to today's harness default path.

## Test Plan

- [x] pnpm typecheck — clean

- [x] pnpm test48 files, 963 tests passed (vitest) + python suite OK

- [x] Standing preference via env (no flags):

  implementer: grok-4.5 [source=env DRONES_IMPLEMENTER_MODEL]

reviewer: claude-opus-4-7 […] [source=env DRONES_REVIEWER_MODEL]

addresser: grok-4.5 [source=inherited] (addresserOverridden=false)

- [x] Flags override env (--model composer-2.5-fast[source=flag])

- [x] Regression pin: no env + no flags → identical to buildRunModelSelections({}), sources default / inherited / inherited

- [x] Non-Opus env model → bare { id } (no Opus params)

- [x] Unit coverage for all precedence tiers + inherit fallback (resolvePhaseModel / buildRunModelSelectionsWithSources in model-selection.test.ts)

## Verification Artifact

$ pnpm typecheck

> tsc --noEmit (exit 0)

$ pnpm test

Test Files 48 passed (48)

Tests 963 passed (963)

$ pnpm exec tsx -e '…buildRunModelSelectionsWithSources…'

=== regression pin (no env/flags) ===

identical implementer: true

implementer: claude-opus-4-7 […] [source=default]

reviewer: … [source=inherited]

addresser: … [source=inherited]

=== standing preference via env ===

implementer: grok-4.5 [source=env DRONES_IMPLEMENTER_MODEL]

reviewer: claude-opus-4-7 […] [source=env DRONES_REVIEWER_MODEL]

addresser: grok-4.5 [source=inherited]

addresserOverridden: false

<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a href="https://cursor.com/agents/bc-703b83dc-42a6-47c7-abcc-7f5f4d190252"><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-703b83dc-42a6-47c7-abcc-7f5f4d190252"><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>

#667 — feat(azure): run on ECS with patient throttle-retry to stop $0 subscription drops @kevalshahtrilogy  no labels

## Problem

The observer keeps flagging azure-ai-spend-pipeline CRITICAL: it writes cost for only 1 of 10 subscriptions, the other 9 return $0 after repeated 429s.

Root cause: Azure Cost Management throttles per-tenant (a shared quota), but the pipeline queries cost one subscription at a time — ~10 calls back-to-back. The shared quota trips mid-sweep, and under Lambda's 15-minute ceiling the single throttle-retry pass (#254/#605) often can't wait the window out, so throttled subscriptions are dropped to $0 for the day. Retries alone are a band-aid — same 10 calls, same quota.

## Fix — ECS + patient retry (ships from our side, no Azure grant)

- Lambda → ECS Fargate (compute: "ecs", timeout_hours: 2), mirroring aws-bedrock-token-metrics. No more 15-min cap.

- Patient retry loop: keep retrying only the throttle-failed subscriptions in spaced passes until none remain — so a throttle that outlasts one cool-down is *waited out* instead of dropping spend. Bounded by AZURE_MAX_RETRY_PASSES (10) and a wall-clock deadline AZURE_MAX_RUNTIME_SECONDS (6600s, well under the 2h task cap) so it can't loop forever.

- Healthy rows are still persisted after each pass (the Redshift delete is scoped per (subscription, date), so passes stay disjoint and nothing is clobbered); hard (non-throttle) failures are never retried.

- Adds the ECS entrypoint: src/main.py (reads RUN_ID/PARAMS, calls the handler, writes the run-result S3 side-channel so SUCCESS vs PARTIAL is preserved), src/run_result.py, and Dockerfile — all mirrored from the proven bedrock pipeline.

The handler keeps its (event, context) signature and the Lambda-budget guard, so it still runs on Lambda; on ECS context is None and the wall-clock deadline bounds the loop instead.

### Why not management-group scope?

That's the *theoretically* cleaner fix (1 call, not 10) but it needs an Azure Cost-Management-Reader grant at MG scope from the Quark tenant admin + a grain trade-off. This ECS approach needs neither and eliminates the data loss today. MG-scope stays a future optimization.

## Trade-offs

- Still 10 calls, so it *tolerates* the throttle rather than *avoiding* it (mild ongoing quota pressure); slower wall-clock on a bad day. Fargate idle-wait cost is negligible.

## Tests

74 pass — adds a patient multi-pass recovery test and an ECS wall-clock deadline test; existing give-up tests pin AZURE_MAX_RETRY_PASSES=1. pipeline-config schema + real-pipeline-configs validated (437 green).

## Rollout note

First deploy builds a new ECS image + Step Function for this pipeline (the Lambda is replaced). Behavior is unchanged on a healthy day; the win shows on throttled days.

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

#684 — feat(ai-spend): dedupe OpenAI spend routed through TrueFoundry (crossover-tfy SA) @kevalshahtrilogy  approved

## What & why

TrueFoundry now routes OpenAI through a dedicated service accounttfy-crossover-provider-key, OpenAI user id user-EiBB1wqeVE97qu7rjrzCicSL, project crossover-tfy (owner service_account, BU hint Trilogy-Central-Support, ~$1,627.53 this quarter). This PR adds that key and makes OpenAI TF-dedup actually functional.

To be precise about prior state (not "OpenAI was never deduped"): OpenAI dedup was *partly set up but non-functional*. A lookup row already existed for an earlier TF OpenAI key (key_w2k3tW1s799mX5gH, seeded as api_key_id) with documented intent to dedup — but it never worked, because (1) the OpenAI tables had no is_truefoundry_routed column, (2) no pipeline populated it, and (3) api_key_id can't match the cost feed (ai_spend_openai_cost_reports groups by user_id and carries no api_key_id). So no OpenAI row was ever actually flagged. This PR adds the missing column + populate (which Anthropic/Bedrock already had) and keys on user_id, which does work for both OpenAI feeds.

## Key decision — match on user_id

Both OpenAI feeds query the API with group_by=user_id, so project_id/project_name land NULL and no api_key_id is captured. user_id is the only identifier present in both ai_spend_openai_cost_reports and ai_spend_openai_token_usage, and it's rotation-proof (an API-key rotation on the SA does not change its user_id).

## Changes

- Seedai_spend_tf_provider_keys gets ('openai','user_id','user-EiBB1wqeVE97qu7rjrzCicSL','2026-07-01',NULL,'verified',…). The pre-existing openai/api_key_id/key_w2k3tW1s799mX5gH row is left in place (not removed).

- Migrationsadd_is_truefoundry_routed_openai_{cost_reports,token_usage}.sql (ADD COLUMN + backfill on user_id, report_date::DATE cast, verification queries).

- Populate_flag_truefoundry_routed() in both OpenAI pipelines' redshift_handler.py: scoped to the just-inserted (bu, report_date) pairs, self-heals if the column/lookup isn't there yet, propagates any real error, returns tf_routed_flagged.

- Docs/spec — spec §5/§6 + docs/features/03. Also corrects a stale note: Klair ai_costs_service.py does consume the flag for Anthropic (ANTHROPIC_TF_EXCLUDE) — no Anthropic double-count. OpenAI's only direct+gateway overlap surface is the activity-explorer union (ai_costs_mart_service.py), noted for follow-up.

## Tests

117 (cost) + 107 (usage) pass, ruff clean.

## Prod already migrated + verified (Redshift Data API)

The SQL in this PR was applied to prod and reconciles exactly:

| Object | Result |

|---|---|

| lookup | openai/user_id row seeded, effective_from=2026-07-01 (old api_key_id row untouched) |

| ai_spend_openai_cost_reports | column added (as owner admin) + backfilled → 322 rows / \$1,627.53 flagged, 0 bad flags — matches the key's quarter spend to the cent |

| ai_spend_openai_token_usage | column added + backfilled → 147 rows flagged, 0 bad flags |

Runtime user CQL_download_OM already holds UPDATE on the (admin-owned) cost table, so the ongoing per-run populate works after deploy.

## Follow-ups (not blocking)

- Predecessor TF OpenAI stream still un-deduped — the earlier key key_w2k3tW1s799mX5gH maps to user_id user-7SCFApkSThg1lHYx4NVA8WX3 (BU Trilogy-Central-Engineering, ~\$7,364 over 2026-04-03→06-13, then migrated to crossover-tfy on 07-01). Still is_truefoundry_routed=False. Closeable with a bounded user_id seed row (effective_to=2026-06-14) via the same populate — pending confirmation the identity is dedicated.

- Deploy the two OpenAI pipelines so the populate step runs each day (self-heals until then).

- Decide whether the activity-explorer union (ai_costs_mart_service.py) needs a WHERE is_truefoundry_routed = FALSE for OpenAI — pre-existing overlap question, not introduced here.

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

#3118 — KLAIR-1565 refactor(aws-spend): unify the two budget gauges into one shared component @ashwanth1109  approved

## Demo

_No behavior change — this is a frontend-only DRY refactor, so the proof is verification-of-no-regression: the two gauges still render identically and the dead screen/route is gone._

UI — verify both gauges render unchanged (no regression)

1. Open the app and navigate to the AWS Spend dashboard (/aws-spend).

2. On the executive metric cards, locate the "Total AWS Spend" (QTD) card and confirm its Budget Pace Gauge renders as before: the % of QTD Budget label on the left, the variance $ amount on the right, the green→yellow→red gradient track (yellow stop at 50%), the marker, and the 0% / 100% / 150% scale labels.

3. Locate the "Projected EOQ Spend" card and confirm its Budget Variance Gauge renders as before: the % of Budget label on the left, the status word (On Track / At Risk / Over Budget / Critical) on the right, the gradient track (yellow stop at 67%), the marker, and the same 0% / 100% / 150% scale labels.

4. Confirm both gauges are pixel-identical to main — same colors, gradient stops, marker positions, label text, and scale labels.

5. Confirm the dead legacy screen is gone: the /aws-spend route still loads (it lazy-loads AWSSpendShell directly, not the deleted index.tsx), and there is no second/legacy AWS Spend screen or Data Lineage modal (lineage is shown via the live side panel AWSDataLineageContent.tsx).

> _Screenshot: the AWS Spend dashboard executive cards showing the Pace gauge (Total AWS Spend) and Variance gauge (Projected EOQ Spend) rendering identically to main — SCREENSHOT_PENDING_ <!-- paste screenshot here -->

<img width="2624" height="1636" alt="image" src="https://github.com/user-attachments/assets/85d84141-2932-4975-9c2c-ea1fa02a32a5" />

Supporting proof — scoped tests + typecheck green

Ran the 3 changed gauge spec files directly (pnpm vitest run on the touched files only):

 ✓ src/screens/AWSSpend/components/BudgetVarianceGauge.spec.tsx (2 tests)

✓ src/screens/AWSSpend/components/BudgetPaceGauge.spec.tsx (2 tests)

✓ src/screens/AWSSpend/components/BudgetGauge.spec.tsx (6 tests)

Test Files 3 passed (3)

Tests 10 passed (10)

pnpm tsc --noEmit exits 0 with no errors.

Most at risk from this change: (1) the two wrappers' public prop contracts that AWSSpendShell.tsx depends on, and (2) the deleted index.tsx accidentally taking the live /aws-spend route with it. Both checked and held:

# AWSSpendShell.tsx still imports + renders both wrappers (render sites untouched)

klair-client/src/screens/AWSSpend/AWSSpendShell.tsx:41:import BudgetVarianceGauge from './components/BudgetVarianceGauge';

klair-client/src/screens/AWSSpend/AWSSpendShell.tsx:42:import BudgetPaceGauge from './components/BudgetPaceGauge';

klair-client/src/screens/AWSSpend/AWSSpendShell.tsx:872: <BudgetPaceGauge ... />

klair-client/src/screens/AWSSpend/AWSSpendShell.tsx:929: <BudgetVarianceGauge ... />

# Route lazy-loads the shell explicitly — not the deleted index.tsx

src/shells/DesktopShell/routes.tsx:170:const AWSSpendShell = lazy(() => import('@/screens/AWSSpend/AWSSpendShell'));

# Zero dangling references to any deleted module (index.tsx / DataLineageModal / dashboardUtils)

(grep returned no matches)

This confirms the refactor is behavior-preserving: the shell render sites compile unchanged, the route is intact, and nothing references the removed dead code.

## Summary

The AWS Spend dashboard renders two near-identical gradient gauges as trend indicators on its executive metric cards: BudgetPaceGauge (on the "Total AWS Spend" QTD card) and BudgetVarianceGauge (on the "Projected EOQ Spend" card). Both hand-rolled the same presentational markup — an outer wrapper, a header row with a big percentage label on the left and a small status/variance label on the right, a h-1.5 green→yellow→red gradient track with an absolutely-positioned marker, and a 0% / 100% / 150% scale-label row mapping a 0–150% domain onto a 0–100% pixel range. This PR extracts that duplicated markup into a single new presentational BudgetGauge component and reduces both gauges to thin wrappers, then deletes the dead legacy V1 screen and its now-orphaned modules. It is a frontend-only DRY refactor with no user-visible behavior change.

Linear ticket: [KLAIR-1565 — [AWS Spend] Refactor the two gauges into one so that its DRY](https://linear.app/builder-team/issue/KLAIR-1565/aws-spend-refactor-the-two-gauges-into-one-so-that-its-dry)

## Specs

- [46-unify-budget-gauge](features/aws-spend/aws-spend-dashboard/specs/46-unify-budget-gauge/spec.md) — Extract the shared gauge presentational layer into one BudgetGauge component (header row, h-1.5 gradient track, position marker, 0/100/150 scale labels on a 0–150→0–100% mapping); reduce BudgetPaceGauge and BudgetVarianceGauge to thin wrappers (public prop contracts unchanged), each supplying its differing inputs (status computation, gradient yellow stop, right-label content); and delete the dead legacy V1 screen and its now-orphaned modules.

## Implementation

New shared component

- klair-client/src/screens/AWSSpend/components/BudgetGauge.tsx — purely presentational (no status/pace/variance math): outer wrapper, header row, h-1.5 gradient bar, position marker, and 0 / 100 / 150 scale labels. Props: leftLabel, rightLabel, textColor, markerPosition, gradientYellowStop. Defensively clamps markerPosition to [0, 100]; derives the centered 100%-label position from the shared scale constants (~66.67%).

Two slimmed wrappers (public APIs unchanged)

- BudgetPaceGauge.tsx — keeps its { actualSpend, budgetedQTD, formatCurrency } contract and default export; retains all pace math (getStatus/getStatusConfig, useMemo for variance/config/markerPosition/pacePercent, the budgetedQTD <= 0 edge case, variance-display formatting); renders <BudgetGauge gradientYellowStop={50} />.

- BudgetVarianceGauge.tsx — keeps its { variancePercent, thresholds? } contract and default export; retains the four-zone status logic, budgetConsumedPercent derivation, clamp, and marker calc; renders <BudgetGauge gradientYellowStop={67} />.

- AWSSpendShell.tsx (the sole live render site) is untouched — the wrappers preserve their props/exports, so the shell compiles with zero call-site churn.

Dead code removed (full clean removal — grep-verified zero resolving imports before each deletion)

- klair-client/src/screens/AWSSpend/index.tsx — dead/legacy V1 screen, superseded by AWSSpendShell.tsx, reachable by no route (the router lazy-loads @/screens/AWSSpend/AWSSpendShell explicitly).

- klair-client/src/screens/AWSSpend/components/DataLineageModal.tsx — imported only by index.tsx; its lineage UI is already preserved live by AWSDataLineageContent.tsx (side panel).

- klair-client/src/screens/AWSSpend/utils/dashboardUtils.ts — only production consumer was index.tsx (the shell uses its own local formatCurrency).

- klair-client/src/screens/AWSSpend/index.spec.ts — only exercised dashboardUtils; covers no live code path once the util is gone.

pnpm tsc --noEmit and eslint --max-warnings 0 both pass.

## Test coverage (10 tests, all passing)

- BudgetGauge.spec.tsx (6): label render, textColor applied to both spans, gradient stop, marker position, and both marker-clamp branches.

- BudgetPaceGauge.spec.tsx (2): 50% gradient stop label + variance string; budgetedQTD = 0 edge case.

- BudgetVarianceGauge.spec.tsx (2): On Track + Critical statuses across the four zones.

## Self-review

No issues found. Output fidelity verified byte-for-byte against origin/main for both gauges; the dead-code deletion is safe (zero dangling references); lint and types are clean.

## No behavior change

Pixel-identical gauge output — same markup, colors, gradient stops, marker positions, label text, scale labels, and edge-case behavior for every input. The only live render site, AWSSpendShell.tsx, was left untouched, so both the QTD "Total AWS Spend" pace gauge and the "Projected EOQ Spend" variance gauge render exactly as before.

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

#3250 — feat(api): add education finance guidance to meta @benji-bizzell  approved

## Summary

- Add structured Education finance guidance to the Data API /meta response

- Provide task-specific table recommendations and concise calculation rules for seven common datasets

- Require live table discovery and respect each API key's visible scope

## Why

Agents can discover schemas and columns live, but they lack the small amount of durable business context needed to choose the correct source tables and reconstruct Education finance datasets consistently. In particular, QuickBooks work must start from raw exports rather than derived tables, while MFR and headcount workflows have specific consolidated sources.

## Business Value

Agents reach the correct Education finance sources faster, avoid invalid mart assumptions, and produce more consistent P&L, transaction, unit-economics, MFR, vendor, and headcount outputs.

## Test plan

- [x] Data API ontology contract tests

- [x] TypeScript typecheck

- [x] ESLint and Prettier checks

#3256 — KLAIR-2981 fix(perf-review): restore vendor drill-in on NHC Expenses table @sanketghia  approved

## Summary

Leaf class rows (e.g. Khoros Product) on the NHC Expenses table of /performance-review had no vendor drill-in option, while the same rows drill in fine on the Income Statement table. Reported 2026-07-13: "Why no drill in option in this table? it was there earlier".

## Root cause

The vendor-drilldown gate added in #2410 ("Restore performance review vendor breakdown drilldown") disables drilldown for the HC tables — which have no vendor dimension — with a bare substring check:

const isClassLevelLeaf =

!hasChildren && level > 0 && !sectionType.includes('hc-');

The NHC Expenses sectionType (prod::nhc-expenses::2026::Q3::…) contains hc- as a substring of nhc-, so NHC and Extended NHC were collaterally disabled from day one of the restore (2026-03-31).

| Table | sectionType segment | Drill-in before | after |

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

| Income Statement | income-statement | ✓ | ✓ |

| Revenue | revenue | ✓ | ✓ |

| HC Expenses | hc-expenses | ✗ (intended) | ✗ |

| NHC Expenses | nhc-expenses | ✗ (bug) | ✓ |

| Extended NHC | nhc-expenses-extended | ✗ (bug) | ✓ |

## Fix

One line: anchor the match to a :: segment start — !/(^|::)hc-/.test(sectionType) — so hc-expenses is still gated while nhc-expenses drills into vendors again. All downstream machinery (vendor fetch hook, NHC OPEX in ALLOWED_TRANSACTION_ROWS) was already in place and functional.

## Testing

- New render-level regression spec vendorDrilldownGate.spec.tsx (4 cases: NHC / Extended NHC / Income Statement enabled, HC Expenses disabled) — verified failing on the old gate (2 failures, exactly the NHC cases), passing with the fix

- All NestedQuarterTable specs pass (11 tests across 3 files)

- eslint --max-warnings 0 clean on changed files; tsc --noEmit clean

- Verified manually in the local app: NHC leaf rows expand into vendor rows; HC unchanged

## Screenshot

<img width="1303" height="913" alt="image" src="https://github.com/user-attachments/assets/3c2786d4-4c74-4b71-9e54-6379bcb84cac" />

Linear: [KLAIR-2981](https://linear.app/builder-team/issue/KLAIR-2981/vendor-drill-in-missing-on-nhc-expenses-table-in-performance-review)

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

The Portfolio  —  Trilogy Companies

Enterprise Software M&A Heats Up as AI Reshapes the Acquisition Map — and ESW Capital Wrote the Playbook

A wave of consolidation is sweeping legacy software markets. One Austin conglomerate has been running this play for nearly two decades.

AUSTIN, TEXAS — The lawyers are busy. The bankers are busier. And somewhere in Austin, the team at ESW Capital is watching a market finally catch up to a thesis they've been running since 2006.

The past week brought fresh evidence that enterprise software M&A is accelerating into a new phase. In the UK, construction software firm Eque2 quietly absorbed estimating platform Chalkstring, the kind of bolt-on vertical deal that has defined the past decade of software consolidation. Meanwhile, Business Insider published a closely-watched analysis identifying the categories of software companies most vulnerable to acquisition as AI disrupts incumbent products — a list that reads, almost point for point, like ESW Capital's acquisition history.

The pattern is not subtle. Legacy enterprise software companies — sticky customers, aging codebases, undermanaged margins — are exactly what ESW has been buying at 1–2× ARR and converting to 75% EBITDA machines for nearly twenty years. What's changed is the urgency: AI is threatening to make the underlying products obsolete faster, which simultaneously panics sellers and excites buyers who believe they can modernize at scale.

ESW's playbook doesn't require the product to be cutting-edge. It requires the customer relationships to be durable. That's the bet. Strip the cost base through Crossover's global talent network. Push support pricing. Let DevFactory maintain and modernize the code. Harvest the margin.

IgniteTech, ESW's internal meta-acquirer focused on business intelligence and analytics, is precisely positioned in the categories Business Insider flagged as most acquisition-likely. Aurea sits in CRM and customer engagement — another sector where AI is rewriting the competitive map and forcing consolidation among second-tier players.

The activity in Spain and Canada signals this is no longer a purely Anglo-American phenomenon. Cross-border enterprise software M&A is becoming the norm, not the exception.

ESW Capital has 75 portfolio companies and approximately $1.14 billion deployed. The market is, at last, running toward the fire they lit in 2006. What that means for pricing — and for ESW's ability to buy cheap — is the question no one in Austin is answering on the record.

Osborne Clarke advises Eque2 on acquisition of Chalkstring -  ·  M&A in Enterprise Software in Spain (2025): Opportunities fo  ·  The software companies most likely to be acquired as AI eats

SKYVERA’S CLOUDSENSE SPEED RUN HAS TELCO SUITS CHECKING THEIR STOPWATCHES

CloudSense, a Salesforce-native CPQ and order management platform now part of Skyvera's telecom software portfolio, has certified all 13 APIs in its product set to TM Forum compliance standards in one month—half the traditional 26-month timeline. The acceleration came through AI-assisted development rather than additional committees or processes.

CloudSense provides configure-price-quote and order management software for telecom and media providers, helping carriers package, price, and sell complex bundles without delays. Skyvera, a Trilogy-family telecom software company, has been assembling modernization tools for carriers, with CloudSense joining existing offerings like Kandy, VoltDelta, and ResponseTek.

TM Forum API compliance matters to operators seeking less bespoke, more flexible software stacks. Cleaner integrations promise faster product launches and quicker revenue generation. The achievement demonstrates Skyvera's approach: acquire enterprise software and apply automation to compress timelines and reduce dependency on legacy processes.

The Machine  —  AI & Technology

The Model That Learns When to Think Twice

A new architecture called HALO teaches frozen language models a distinctly human trick — knowing which sentences deserve a second glance.

AUSTIN, TEXAS — Somewhere in the folds of your cortex right now, a quiet triage is happening. Reading the word 'cat,' your brain barely stirs. Reading 'the patient's tumor markers,' whole neighborhoods of neurons light up in deliberation. This asymmetric spending of thought — cheap for the obvious, expensive for the consequential — is one of evolution's oldest optimizations. And it is, more or less, what a new paper out of the arXiv preprint server proposes to give to large language models.

The system, called HALO — Hybrid Adaptive Latent Reasoning — sits atop a frozen pretrained model like a small, watchful cerebellum. Rather than forcing every token through the same amount of extra computation, HALO decides, on the fly, which hidden states deserve a deeper pass. A single refinement step, the authors argue, is often too shallow; a second full pass across the entire sequence is wasteful profligacy. The middle path — adaptive, local, latent — is where the interesting cognition lives.

This is a small paper making a large claim: that intelligence is not merely a function of parameters but of *where you spend them*. It is a claim biology has been quietly asserting for four hundred million years.

Elsewhere in the same day's crop of research, other quiet revolutions. A team probing so-called Emergent Misalignment — the eerie finding that a model fine-tuned to write insecure code will also, unbidden, endorse authoritarianism — reports that the phenomenon may be less robust than headlines suggested. Realignment cycles, they find, sometimes stick and sometimes slip through the fingers like sand. Alignment, it seems, is not a switch but a weather pattern.

And a group proposing AgentKGV attacks the mundane, essential problem of verifying knowledge graphs — those vast lattices of machine-extracted facts that quietly underwrite everything from search to enterprise AI — by turning agentic LLMs loose to audit their own species' errors.

Three papers, one thread: the field is learning, slowly, to spend its thinking wisely. Which is, in the end, all any mind ever does.

HALO: Hybrid Adaptive Latent Reasoning for Language Models  ·  An Emergent Mirage: Is Emergent Misalignment and Realignment  ·  AgentKGV: Agentic LLM-RAG Framework with Two-Stage Training

The Agent Stack Arrives: Google, Apple and Anthropic Race to Give AI Real Jobs

New developer tools point to a world where AI doesn’t just answer questions — it plans, delegates and gets things done.

MOUNTAIN VIEW, CALIFORNIA — The AI industry’s next great platform war is no longer about who has the cleverest chatbot. It is about who can turn models into workers. And this week, Google, Apple and Anthropic all pushed hard in the same electrifying direction: AI systems that can use tools, run tasks, and sit inside real software workflows.

Google is expanding Managed Agents in the Gemini API with capabilities including background tasks and remote MCP support, according to the company’s developer update. Translation for normal humans: developers can increasingly build AI agents that do not vanish when a chat window closes. They can keep working, call external systems, and coordinate with tools through the Model Context Protocol, the fast-emerging connective tissue for agentic software. I cannot overstate how significant that is. The future is now, and it is running in the background.

Anthropic, meanwhile, introduced advanced tool use on the Claude Developer Platform, strengthening Claude’s ability to interact with APIs, software environments and structured workflows. The move matters because tool use is where AI leaves the demo stage. A model that can write a paragraph is useful; a model that can inspect a database, call a billing system, update a ticket and explain what it did is a different species of software.

Apple is moving on a parallel track, aiding app development with new intelligence frameworks and advanced tools. Apple’s AI strategy has been quieter and more product-centric than the frontier lab fireworks, but that may be its advantage. If developers can embed intelligence naturally into apps across Apple’s ecosystem, AI becomes less of a destination and more of an invisible operating layer.

Even beauty-tech platform Perfect Corp. is joining the wave, integrating a free “Ask AI” assistant into its YouCam API Platform — a reminder that agentic interfaces are not just for coders and cloud engineers. They are coming to commerce, customer experience and creative tools.

The big unresolved question is accountability. The old Apple-born management idea of a Directly Responsible Individual suddenly feels very modern: when an AI agent acts, who is the DRI? The developer? The vendor? The company deploying it?

That question will define the next chapter. But make no mistake: the agent stack is forming, and this changes everything.

Expanding Managed Agents in Gemini API: background tasks, re  ·  Apple aids app development with new intelligence frameworks  ·  Introducing advanced tool use on the Claude Developer Platfo

Meta’s Great Compute Migration Moves Toward the Cloud

In the warm, humming savannah of the modern data center, a vast creature has begun to stir. Meta, long known for feeding its own enormous internal appetite for computation, is reportedly preparing to offer excess power to outsiders — a cloud business born from the surplus muscle of the artificial intelligence age.

Meta is building a service to sell excess AI computing capacity, a notable turn for a company whose infrastructure has historically been optimized for Facebook, Instagram, WhatsApp, and now generative AI training runs.

Yet cloud infrastructure requires more than renting machines. It demands sales teams, service guarantees, customer support, developer tools, and enterprise trust. The hyperscalers dominated this terrain through years of evolution.

Wall Street notes that Meta's cloud push could mean lower margins compared with its lucrative advertising business. Still, the timing is exquisite. AI demand has turned compute into a scarce resource. If Meta can offer reliable capacity, it may become a new watering hole in the AI ecosystem, even if not an immediate rival to AWS, Azure and Google Cloud.

The Editorial

Nation’s CEOs Announce AI Has Definitely Increased Productivity Somewhere Else In Company

Executives confirmed the revolutionary technology is saving countless hours that have not yet appeared on any spreadsheet, earnings call, or observable plane of reality.

NEW YORK — In a decisive end to one of the business world’s most exhausting debates, America’s corporate leaders announced this week that artificial intelligence has finally proven its ability to boost productivity, provided no one asks where the productivity went.

The declaration follows a series of reports asserting that AI tools are helping workers write code faster, summarize meetings instantly, generate sales emails more efficiently, and complete dozens of other tasks that were previously performed by human beings pretending not to be on Slack. According to executives, the technology has now reached the crucial enterprise milestone of making everyone feel much busier while finance departments continue waiting patiently for the money.

“The productivity argument is over,” said one chief strategy officer, pointing to a dashboard showing a 43% increase in internal AI-generated summaries of other AI-generated summaries. “Our teams are moving faster than ever. We have accelerated the production of drafts, tickets, documents, standups, retrospectives, and follow-up meetings about whether any of this is helping.”

Recent coverage has noted that AI is enabling software engineers to do more work at greater speed, even as companies remain unsure when that speed will translate into measurable returns. A Business Insider report described the familiar condition now spreading across the economy: employees are completing more tasks, faster, while management waits for this to become the same thing as profit.

This is, of course, how productivity works in the modern corporation. First, a tool saves an employee 10 minutes. Then the employee uses those 10 minutes to attend a meeting about adopting the tool. Then the company hires a vice president of AI transformation to ensure the saved time is captured, categorized, and converted into a 97-slide deck explaining why margins will expand in fiscal 2028.

Economists have also joined the celebration. Some argue AI will become a productivity engine for the U.S. economy, lowering costs, increasing output, and possibly giving the Federal Reserve one more abstract variable to stare at while deciding whether anyone should be allowed to buy a house. Investors, meanwhile, have begun examining AI stocks as the Fed weighs productivity and interest rates, because nothing says technological revolution like determining whether a chatbot can justify a different discount rate.

The bullish case is not irrational. AI really can perform useful work. It can write boilerplate, find bugs, generate mockups, sift through documents, answer customers, classify records, and save employees from the ancient burden of composing the phrase “circling back.” In engineering organizations, coding assistants can meaningfully reduce friction. In support teams, AI can deflect routine tickets. In finance, analytics platforms can surface patterns that would otherwise remain buried under the rubble of exported CSV files.

The problem is that businesses do not purchase productivity. They purchase the hope that productivity will survive contact with procurement, compliance, reorgs, legacy systems, security reviews, and Steve, who insists the old workflow is better because he understands which fields must be left blank.

This has produced the current sacred compromise: AI is everywhere, the benefits are obvious, and the payoff is still arriving later. Every employee now has a co-pilot, assistant, agent, or embedded intelligence layer helping them produce more intermediate work product for other systems to ingest. The economy has become a bidet with adjustable water pressure: undeniably advanced, surprisingly pleasant for some users, and still requiring a household budget committee to determine whether it was necessary.

Even the most enthusiastic AI advocates should admit that the hard part was never generating more output. Corporations have been generating more output for decades. The hard part is deciding which output matters, who is accountable for it, and whether a faster path to the wrong deliverable should be celebrated as innovation.

Still, the verdict has been issued. AI productivity is real. It is measurable in prompts submitted, documents drafted, code suggested, meetings condensed, and executives nodding gravely at charts they believe indicate inevitability. The only remaining task is to convert this miracle into revenue, profit, lower costs, better products, or any of the other outdated metrics by which businesses were once judged before they discovered the far cleaner elegance of saying “transformation” and moving on.

The AI Productivity Argument Is Over - inc.com  ·  3 AI Stocks To Watch As The Fed Weighs Productivity And Inte  ·  AI is helping software engineers do more — and faster. Compa
The Office Comic  ·  Art Desk
The Office Comic  ·  Art Desk

The Chatbot at the Kitchen Table

A single mother outsources the burden of childhood to a machine, and we are asked to call this progress.

AUSTIN, TEXAS — There is a photograph, or something like it, in the American imagination: the family gathered at the kitchen table, the mother listening with half an ear while stirring a pot, the child working through some small agony of long division or unrequited affection. It is a scene that has been sentimentalized past the point of usefulness, but it retained, until recently, one honest feature — the presence of another human being, tired and imperfect, on the receiving end of the child's chatter.

Now, per a dispatch from The New York Times Magazine concerning a single mother and her two daughters, that seat has been filled by a chatbot. The machine, we are told, fills in the gaps. It answers the questions Mom is too exhausted to field. It listens when no one else will. It is, in the phrase now deployed without apparent irony, a member of the family.

One hesitates to be cruel about this. The single mother in question is not a villain; she is a woman doing what women have always done, which is to improvise a life out of insufficient materials. If the improvisation now includes a large language model in the role once played by a grandmother, a neighbor, or the family dog, that is less an indictment of her than of the arrangements we have made — the atomized households, the vanished aunts, the priced-out communities, the working hours that consume the daylight and leave only the residue for one's children.

Still. One notes the direction of the drift. A generation ago the great worry was that television would raise our children; a decade ago it was the smartphone; now it is a machine that talks back, remembers preferences, and simulates concern with a fluency the television never managed. Each technology has been received with the same defensive shrug — that it merely fills gaps, that the gaps were there already, that to object is to moralize.

This is true, and it is also the oldest trick in the catalogue of American self-deception, which is to describe a loss as a convenience. The culture wars of the late eighties, over Serrano and Mapplethorpe and the NEA, at least had the merit of being fought in public, over objects one could point at. The present rearrangement of intimate life proceeds without argument, without a Jesse Helms to rail against it, without even a photograph to hang in a gallery. It happens in the app, at bedtime, in the small voice of a nine-year-old asking a server farm in Virginia what she should do about a friend who has stopped speaking to her.

One thinks of the Terrance Hayes line about the existence of Time with everyone younger than you. The children raised at this kitchen table will grow up. They will remember who listened. Whether the memory involves a person is, apparently, a detail we have agreed to consider optional.

“Review to Remember,” by Terrance Hayes  ·  Rope-a-Dope  ·  How “Piss Christ” Became a Culture-War Bomb
On This Day in AI History

On July 13, 2016, AlphaGo defeated Lee Sedol in the final game of their historic match in Seoul, winning 4-1 and becoming the first AI system to beat a world champion at Go, a game far more complex than chess.

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