Skip to content
Changelog, page 4

What shipped, and when.

A day-by-day record of what landed in Underwrite, kept by hand. Page 4 of 23.

Want to verify? The six files the decision depends on are rendered from the live source at /methodology/engine.

Show only

Filter by engine, UI, AI, ops, marketing or fixes.

2026-09-29
6 entries

Underwrite moves to black, and the release carries September's honesty work: the AI prose is checked against the engine before a reader sees it, a quote counts as evidence only when it states the value beside it, the memo carries one verdict, and a parse applies only what the document gave it. The canonical figures do not move: 15.34% IRR, 2.44x and PURSUE at a 6.50% exit cap, 13.51% IRR, 2.19x and PASS at 7.00%.

  1. The IC memo's executive summary and the desk's AI Deal Review print what a model writes about a deal the engine has already computed, and until this release only a sentence in the prompt kept that prose faithful. The server now checks it before answering. A recommendation that differs from the engine's verdict is refused, a hedge included, because the engine has two verdicts and no third; every percentage and multiple the prose states must be a figure the engine produced, at the precision the prose states it. Refused prose is never printed: the panel says it did not match the engine's result, and the figures and the verdict on the page are unaffected.

  2. A parsed field was marked as sourced whenever the model's sentence was found in the document, even when that sentence stated a different figure. A quote now counts as provenance only when it is in the document and states the value beside it. A PDF's text never reaches the server, so no PDF quote is presented as checked: the model's sentence is shown as its report, beside the hand-verify flag. The model's note to the analyst may say what the document stated and did not state; a note carrying a number the document does not contain is withheld, and the reader sees no note rather than one the server rewrote.

  3. The memo printed a composite GO banner, a timing BUY, a LEAN SELL optimizer and a section headed Recommendation beside the engine's own plate. Those sections are gone, and so are the two capital stack recommenders, so the plate's PURSUE or PASS is the one verdict the memo gives. Deal Strength prints its points and the rule behind them with no band word, no tile is labelled Recommended, sell versus refinance is a cash comparison, and the memo asserts no tax rule and recommends no exit cap.

  4. A parse used to spread a document's figures over the worked example, so a memorandum with no retail kept the example's retail income under the document's name. Income the parse did not take from the document is now zero, a rent roll it did not list is removed, and a note above the verdict says which values are still the desk's. A rent roll with rows the parse could not read is not applied, and the panel says why. A lease term the model cannot represent, such as 5.5 years, is carried as the document states it and holds the result until it is corrected, rather than being rounded. A deal shape the model covers only in part says so beside the verdict.

  5. Saving a new deal into a full library deleted the oldest saved deal while the notice said only that the new one was saved; it is now refused, with a note that nothing was removed. A property preset asks before it replaces a parsed deal's figures and names what it replaces. A figure the memo cannot compute is stated as not computable instead of printed as a number. Confidential Mode now governs the memo page as well as the desk, so the memo's AI summary is off with it.

  6. The environmental site screen matched its cues inside longer words: "lab" fired inside "available", "port" inside "support" and "marsh" inside "Marshall", so 725 Marshall Street read as a flood-elevated site. The cues that fired inside unrelated words are now narrowed, each by its own pattern, and the storage-tank acronyms match only as whole words; every other cue still matches inside a longer word, so riverfront and railyard still count. No canonical figure moves.

2026-08-26
5 entries

A real Offering Memorandum reaches the parser, and the upload limit is a number we measured rather than a number we hoped for. Someone tried to upload an OM and was told files under 4MB parse reliably, while the same screen advertised 32MB. Both figures were wrong. This release finds the real constraint, architects around it, and publishes the tested limit.

  1. The panel advertised 32MB while the hosting platform rejected any request body over 4.5MB before the route ever ran, so a normal OM failed with an error blaming the file. Two constraints were hiding behind that copy. The platform caps a request arriving at a function at 4.5MB, which no configuration can raise. The parser service caps a request at 32MB, and a PDF sent inline is base64 encoded, which costs four bytes for every three, so a 32MB PDF was never going to fit inside a 32MB request no matter where it was hosted. PDFs above 4MB now upload straight from the browser into private storage and are read back by the server, whose own outbound fetch has no such cap. The published ceiling is 22MB because that is the largest whole megabyte that still fits the parser service's request limit after encoding, and it was verified end to end at 1MB, 5MB, 12MB, 20MB, and 22MB. Workbooks are unchanged at 32MB: they are read in the browser and only bounded cell text is sent, so neither limit applies to them.

  2. A document staged for parsing goes into private storage that only this server can read, never a public address. The upload token is scoped to one folder, to PDFs, to the size ceiling, and to a few minutes. The server proves the object belongs to this store before reading a byte, and addresses it by pathname so a crafted request cannot point the reader at anything else. The document is deleted the moment the parse settles, on success and on every failure path.

  3. The old message claimed files under 4MB parse reliably, which was not true and told the reader nothing about what had gone wrong. Each failure now says what happened: the upload did not reach the parser, the document was received but exceeds what the parser service accepts in one request, the file was read but extraction ran past the request window, or the document has more pages than the service takes. The upload stage shows its own progress and elapsed time, and cancelling stops the upload as well as the parse.

  4. The freshness indicators on the macro dashboard and the status pill computed staleness in a way that could never report it: one compared the snapshot time against itself, the other was masked by reference figures that are seeded by design. A snapshot served entirely from expired cache could have carried a live badge. Both now read the per-series freshness recorded when the data was fetched, and report live, cached with the age of the data itself, seeded fallback, or unavailable. Treasury, SOFR, CPI, and breakeven values were checked against the provider's own published series for the same observation date and match to the basis point.

  5. Two new gates run with the rest of the suite. The parser gate re-derives the advertised ceiling from the encoding arithmetic and fails if the published number does not survive it, if a staged reference could point outside our own storage, or if the retired copy about 4MB ever returns. The live data gate scans the shipped client bundle for provider endpoints and key material, checks units and freshness semantics, and compares displayed values against the provider's raw response.

2026-08-22
4 entries

The dark world becomes one continuous place, and then every millimeter of the product gets read back. Phase 3 of the luxury pass joins the proof and the module universe into a single computational stretch with one provenance line running through the margin, and phase 4 goes through the shipped surface looking for what a demanding reader would actually hit. The engine is untouched: Phase 3 remains at 143 modules.

  1. The proof section and the module universe now share the obsidian environment with the reverse-trace, so the computational stretch of the page reads as a single place rather than three dark panels. A data attribute remaps the document's own tokens inside that environment, which means existing type and rule utilities flip with the world instead of being rewritten for it. Running down the page margin is one verify-blue provenance line: it appears as the evidence begins, stays through the model, and hands off to the trace's own rail. Both rails derive their position from the same measured page margin, so they align exactly rather than approximately, and neither knows the other exists. Print restores the light document everywhere.

  2. A full adversarial read of the shipped surface, with every finding reproduced before it was applied and fourteen of thirty-four rejected on inspection. The largest defect was invisible: the brand serif was never bound to the utility that six call sites use, so the trace headlines and the hero money figure, the biggest type in the product, had been rendering in the operating system's generic serif.

  3. The platform in front of the AI routes returns HTML, not JSON, when a request is too large or runs past its window, so asking for JSON printed a JavaScript parser string under the Parse button on the marquee feature. Responses are now read once and parsed only when they are JSON, with authored copy for the statuses the platform actually produces. A parse that extracts nothing says so instead of rendering as a success with the sample deal still on screen. A share link that fails to decode announces itself instead of quietly becoming the sample deal. The reading stage, the one stage that waits on the model, gained an elapsed count, a cancel, and a three minute ceiling, so a hung request can no longer leave the button disabled forever.

  4. Every definition tooltip had been hover-only, which on a touch screen and on a keyboard is no way in at all: the glyph is now a real button with a full-size target, reachable by tab and readable on focus, while the mark itself stays the same size and every call site lays out to the pixel it did before. The four widest tables freeze their label column and its header, so a ten-year pro forma scrolled sideways no longer becomes a grid of unlabelled money. The results tab bar was hiding a third of itself at 390 pixels with no affordance, which buried the Monte Carlo explorer and the IC memo behind an invisible gesture. The stress switcher moved above the results it rewrites.

The engine math is on the methodology page, the six files the decision depends on are on the engine viewer, and the Phase 1 simplification list is at /methodology/beyond-phase-1.