- The readout could not answer which version a project had been given, and the data had been there the whole time. One table explodes every turn into a row per section of the instructions it served, and then looks up which version each one got BY THE SECTION'S NAME. The slow brain was filing its record under Mira while the sections it actually served all belong to Atlas, and the version it recorded named a section from a prompt that row did not describe, so twenty one rows came out reading default and the version never became a row at all. On dev right now that is two projects, one on each of the two personalities, and no chart could tell them apart. Two fixes, both about a row telling the truth about itself. The brief-building brain files under its own name, because labelling it Mira put the brief-builder's sections under the name of the brain that writes the reply, in the one table the readout groups by. And the fast lane records its OWN thirty five sections and its own version, which it never did, which is why the experiment had been borrowing a row that could not carry it: the same call that decides which text to use now returns which one it used, so the record cannot drift from the swap. The version is reported on the CONTROL too, not only when it swaps, because nobody was on the experiment and the experiment never ran are different facts and a readout that cannot separate them reads a broken allocation as a null result.
- The experiment was bucketing a PERSON while the report measures a PROJECT, and that is a statistics bug rather than a naming one. One client with five projects contributed five correlated observations to one arm and they were counted as five independent ones, which understates the spread and makes a result that means nothing look like it means something. The assignment now runs on the project, both lanes, and nothing else about it moves: the same pure calculation, drawn from nothing, stored nowhere, and stable forever for a given project. Measured at an even split over two thousand projects it came out 995 to 1,005. Where there is no project there is no arm, deliberately, and NOT a quiet fall back to the person, because falling back would put a conversation's first messages on one voice and its later ones on another, which is the exact thing sticky assignment exists to prevent. What it costs is stated rather than buried: one person's two projects can now sound slightly different from one another, which is a visible inconsistency to a returning client, and it is the first thing to revisit if anybody reports it.
- Twenty five of twenty six named slots did not appear on the page that exists to offer them. Named, described, allocatable, and unreachable. The list is built by SPLITTING the prompts we have registered, and a slot declared at the point a message is SENT has no such prompt to split: the search agent's prompts are parameterised per run, the negotiator has thirteen blocks built per call, the quality readers assemble theirs from a committed file. Their text is built at the moment it is used, which is precisely WHY they were declared this way, and precisely why a walk of the registry could never find them. Only one showed, and only because that section also happens to live inside a registered prompt. They are listed now as their own group per agent rather than invented into the registry, because there is no constant to register and claiming one would put a prompt in the contract that no part of the code owns. They are marked as NOT dialable on purpose: a dial needs the section to be rendered through the builder and these are chosen at the call site, so the dial would move nothing, and a console that showed a slider here would be the exact failure it exists to make visible. Their VERSIONS do work, which is what an experiment actually needs. The slot names also moved onto the runtime labels, finishing the rename from the day before, so an operator reading the console, the debug dashboard and the reporting warehouse sees one word for one brain.
- Every screen of the search journey is now clickable on one page, and an empty lane stopped reading as a stage nobody reached. The whole flow, the live rail, the brief-ready moment, the sign-in gate, the start choice, both waiting screens, the live dashboard, the reveal, the results and the fallback, mounted as the real components against fixtures inside the app's own shell and built to a single self-contained page, so product design and copy can be reviewed end to end without driving a real project to each state one at a time. Alongside it, the talent pipeline's Yours now lane appears only once somebody is actually engaged: every other lane keeps drawing at zero, where the count IS the information, but an empty engagement zone reads as a stage the run reached and failed rather than one it has not got to.
A Saturday of 4 commits, and the through-line is a row that tells the truth about itself. The reporting table could not say which version of the personality a project had been given, because the brief-building brain filed its record under the name of the brain that writes the reply and the reply's own lane recorded nothing at all, so twenty one rows read default and the version never became a row; both lanes now record their own sections and their own arm, and the arm is reported on the control as well, since nobody was on it and it never ran are different facts. The experiment itself was bucketing a person while the report measures a project, so one client with five projects counted as five independent observations; it buckets on the project now, and where there is no project there is no arm rather than a fallback that could change a client's voice mid-conversation. Twenty five of twenty six named slots were missing from the page that exists to offer them, because they are built at the moment they are sent and a walk of the registry can never find them. And the whole search journey became one clickable page for design review, while an empty Yours now lane stopped implying a stage the run had reached.