This is the public record of changes to how findings are produced. Each version has a quick summary, the main changes, links for context, and the complete change note. Every claim records the version that produced it.
v1.43
Carried two round and sections
Two more kinds of public document can now be carried into the panel package. One is a document that every reviewer's research tools failed to retrieve in two rounds in a row of the same run, even when a quick check later opens it; it can come from outside the City's meeting portal, and the site checks its copy against a fresh download. The other is a document too long for a reviewer's package, carried as whole sections that a published rule picks, with every section left out listed in public with its reason. The label beside such a source says the reviewers' tools failed, not the document, and that the site chose the sections.
What changed
What happened. Two runs stopped on cases v1.41 and v1.42 did not cover. In council-hearing, the claim turns on the Council Procedures Bylaw, a PDF on edmonton.ca. Every quick check of that address, by the site's fetcher and by each reviewer's tool, opened it, yet all three reviewers recorded HTTP 502 from it in their research runs, in two rounds, and read the key section only through search-engine extracts. Under v1.42 a reviewer's refusal counted only from a fresh probe, which passed, so the bylaw never qualified, and only meeting-portal files could be carried at all. In snow-clearing, the proposals the claim is about sit in a 144-page budget attachment whose text runs to 454 KB, more than the 400 KB a reviewer's package may hold, and v1.41 carries a document only whole.
The two-round ground. A document the frozen brief names also qualifies when every reviewer recorded a failure to read it in two consecutive committed rounds of the same run. The evidence is the reviewers' own committed answers, never a probe and never the editor's account of them. A round that was stopped and moved aside still counts, but only if its record names the same story and date, and each reviewer in each round needs its own answer file. Each answer is read mechanically for a sentence that ties a failure to the document: an HTTP status of 400 or more, or words such as "could not read" or "fetch error", where the nearest document named before it is this one, by its exact address (on the meeting portal, the same DocumentId), its file name or a name the frozen brief itself uses. A sentence where another document is the one that failed, or where it cannot be told which, does not count, and neither does a citation of some other source. The manifest records, for each reviewer in each round, the answer file, where in it, the exact sentence, the status or error, the model, the tool and the times. The latest successful quick checks are recorded beside them and do not erase them. Reviewers are still told to read the source directly if they can, and to write "read directly from" and the address when they do; a direct read by any reviewer, in either round or any later one, ends the ground, and in its own round it outweighs any failure the same reviewer recorded. No round is ever run to make a document qualify. At package time the ground is worked out again from the committed answers, which must be unchanged. Nothing on the site says such a source is unavailable: the label says the reviewers' research tools failed to retrieve it, which is all two failed rounds show.
Documents outside the portal. A public document outside the City's meeting portal can now be carried. It has no meeting page to check against, so the manifest records instead the publisher's address, how the archive was obtained and by whom, the archive's hash, and a fresh download by the site with its own hash. The two must be the same bytes. Identical extracted text is accepted only where the publisher serves changing bytes, and only with a written note on why they change and how the version and content were checked; anything else stops the run. Before packaging, a person who is not the editor opens the publisher's address in an ordinary browser, without signing in, and confirms it is the same document and version, within the 72 hours before a launch. If no such person can, the manifest says why, this is allowed only when the site's fresh download matched, and the label beside the source says no one outside the site could confirm the link. Every human check in a manifest names its checker and their role, and the manifest names the editor's own session; a check made by that session, or by anyone in the editor's role, does not count.
Sections of long documents. A document too long to carry whole is carried as whole sections, chosen by a second published, versioned keyword rule fixed before the run. For a budget attachment a section is one whole service package, from its title through its description to its cost tables and their totals, or one part of the document as its table of contents divides it. Every page belongs to exactly one section. A package must be whole, with one title, a description and a last cost table ending in its total; a package that starts partway down a page, contents the splitter cannot read line by line, or any other format it cannot read stops the build. The rule matches a section's title and whole text, ignoring case, and each matched section goes in whole with its page numbers. The manifest, committed before the run, lists every section with its title, pages, size, the terms it matched and whether it was carried, so anyone can see on GitHub what the reviewers did not get; the text stays private. Someone other than the editor reads the entire document, records a reason for every section, and looks in the sections not carried for qualifications, contrary evidence, cross-references and context, not only for keyword misses. Anything they find is fixed by a new rule version and a rerun of every reviewer, never by adding a section by hand and never by cutting one. At package time the document is extracted and split again from its archive; an inventory edited by hand, or a section split or cut, refuses the package. Every build and every package measure the package against the 400 KB budget, and if everything relevant does not fit, the run stops. Nothing is trimmed to fit.
Labels, drafting and corrections. Beside each such source, on phone and desktop and never above the answer, a short label says in plain words what the reviewers saw: for sections, that the site chose them under a published rule and the rest was not given to the reviewers; for the two-round ground, that their tools failed, not that the document is unavailable; and in both, that every reviewer read the same text the site supplied, so their agreement on it is not independent retrieval. It links the full document, the rule and the section inventory. Where a carried budget document is cited, drafting keeps what Administration proposed apart from what Council approved. Before publication the drafter checks the methodology quality ledger's recorded failure modes and records the result, and the first story under each extension gets the cold-reader phone test of v1.41. The committed inventory is public on GitHub before the run, and the corrections route stays open after publication; a material omission raised either way goes through the same rule-and-rerun process.
Who did what. The editor recommended both extensions and the founder chose them on 2026-10-02. The board reviewed them in four memos on GPT-6 Sol, one per role; all four answered ADOPT WITH CHANGES, and every change they asked for is in the rules above. One is adopted in a narrower form: the public trust memo asked for a way for the people being fact-checked to flag missing context before publication. The public inventory and the corrections route are that way; contacting them before publication is not added, because outside contact goes through the founder and none is planned. council-hearing reruns round 1 with the bylaw carried on the two-round ground once this is merged and the bylaw's address has been opened by a person; snow-clearing reruns round 1 with the budget attachment carried by section once the checker passes its section inventory.
Correction, 2026-10-02. As first released, v1.43 also required a person to open every carried meeting page, which v1.42 did not; for a meeting page carried by item, the site fetcher's HTTP 200 on the live page counts again as the check that the page is public, as it did under v1.42, while every other carried document still needs a person.
Correction, 2026-10-02 (D-0049). The 400 KB package budget above was a cautious default chosen when v1.41 was built, not a figure taken from the reviewers. It is replaced by a rule: each reviewer's package may be at most half of the context that reviewer can use, so at least half stays free for its own research, converted from tokens to bytes at the lowest bytes-per-token ratio seen on the site's own past packages. We measured that ratio from the token counts the model providers reported for 63 past attempts in five runs. For the two GPT-6 readers, Codex reports a 272,000-token context of which 95 per cent is usable, 258,400 tokens; the lowest ratio was 4.039 bytes per token, counting only the tokens the provider assigned to the package itself, so the limit is 521,838 bytes. Codex adds about 10,900 tokens of its own instructions and tool definitions to every request; those come out of the half kept for research, which is why the package is measured on its own. For the Claude reader, the context is 1,000,000 tokens; the lowest ratio was 2.407 bytes per token, counting every input token of the request, so the limit is 1,203,500 bytes. Every reviewer gets the same package, so a run is held to the smaller limit, 521,838 bytes. The limit is still hard: a package over it stops the run and nothing is trimmed. If a reviewer runs out of context during its research, the round fails, and that reviewer's limit drops to a third of its context.
Full change note
Two failed rounds show that the reviewers' tools failed, not that the document is closed to anyone; the label says exactly that. Picking sections of a long document is a choice the site makes, so the rule and the full inventory are public before the run, and an independent reader checks every section.
v1.42
Carried minutes items
Council agendas and minutes that the reviewers' own web tools cannot open can now be carried into the panel package, by item. A rule published before any text is extracted picks the items; each goes in whole with the page's header and attendance, and someone other than the editor checks every item of every page for anything the rule missed. The reviewers are told the site chose the items. A claim that needs every recorded vote runs only once those votes are reconciled; otherwise it is parked for the run.
What changed
What happened. The council-pause-vote run stopped in round 1. All three seats read the carried report and Attachment 5, and all three reported that the City's meeting pages, the agendas and minutes the brief makes controlling for every motion and vote, answered their web tools with HTTP 403. The site's own fetcher reads those pages, so v1.41 did not carry them, and the brief stops on an inaccessible essential source. The minutes it relies on come to about 610 KB, more than the 400 KB a seat's package may hold.
Who is refused. A page now also qualifies when a panel seat's own tool is refused there, not only when the site's fetcher is. The evidence is a dated probe through that seat's pinned model and tool, no more than six hours old, in which the tool's own request was for that exact page. Only failure data the tool itself emits counts, and only that is recorded: an HTTP status and the tool's error type or code, never the text the tool returned. Page titles, snippets and the model's words are never read, so a probe whose tool reports neither is unclear and does not count; today that leaves the Claude seat's WebFetch as the only tool that can show a refusal. The ground applies to reports and attachments as well as meeting pages: the City portal's browser check does not answer every request the same way, and the site's fetcher has opened a report on one request that it was refused on the next. A document is therefore carried while either ground holds, and excluded as fetchable only when neither does, which keeps the carried set the same from one build to the next. The manifest says which ground applied to each document, and at package time a seat refusal is checked again against its row in the committed probe file. When any seat qualifies, every seat gets the same text.
The rule. A meeting page is carried as its header, meaning the meeting, date, time, location and attendance with the roll call item, plus every agenda item that names the program's capital profile CM-20-0330, report IS03688, the program by either of its names, its borrowing bylaws 20394 and 21265, or bike or cycling. The match is on each item's number, title and whole text, and ignores case. Each item goes in whole: its title, every motion, mover, seconder, vote and result, and the text under it. The rule is versioned in the public repository and recorded in the manifest with every page's hash and its full item index, carried or not. Names of members of the public in the carried items are replaced with "[member of the public]" by a published mechanical step, and the manifest counts the names withheld in each item. The step covers lists of public speakers and of outside delegations, attachments titled in eScribe's speaker-panel form, and the entries in a procedural Requests to Speak motion, which decides who speaks and nothing about the program; an entry that begins with an agenda item number is kept, as are that motion's operative words, mover, vote and result. Every other motion, mover, seconder, vote and result is never changed, and neither is any office-holder the page names in its attendance or roll call, matched without titles such as Mayor or Councillor, or any member of City staff acting in role.
The guards. Someone other than the editor reads every item of every archived page against a relevance test set by effect, not by keyword: an item holding a motion, amendment or vote that changes or proposes to change the program's funding, authorization, scope or delivery, whether or not it names the program. They record for each item whether it was carried and why. A relevant item the rule missed is fixed by publishing a new rule version and running it again on every page, then checking again; there is no way to add an item by hand. The package is refused while any page lacks a passed check, any item lacks a reason, or a missed item is on the record. At package time each page is read again from its hash-checked archive and its carried text and item index are regenerated; anything that differs from the manifest stops the run. A page whose live copy differs from the archive in its header, including attendance, or in any item's text, motions or votes fails and has to be archived again. The claims that need every recorded vote are listed in a committed file for the run, which must exist, even listing none, whenever meeting pages are carried; each listed claim gets a gate the package cannot pass while it is pending. For such a claim, the full set of relevant votes is reconciled with the City's open voting record before a round, with the brief's rules for absence, abstention and recusal applied, in a file committed and unchanged at launch, listing each vote with its meeting, item, motion, result and every member's vote. A passed gate records that file's hash and the hashes of every carried page it covered; any change to either puts the gate back to pending. If that set cannot be established or does not fit the 400 KB budget, the claim is parked for the run and the seats are told so; nothing is trimmed to fit. The archived pages and the carried text stay private because their rights are unclear, so the label beside such a source says the reviewers read selected items chosen by the site under a published rule, that the rest of each page was not shown to them, and that our copies cannot be published; it links the City's page, the rule and the item index. Anyone can report an omitted item through the corrections route.
Who did what. The founder decided it: carry by item, as the editor recommended, rather than park the voting-bloc claim and carry four whole minutes pages. The board reviewed it in four memos on GPT-6 Sol, one per role, and all four answered ADOPT WITH CHANGES. Each change they required is in the rule above; none was turned down. The council-pause-vote run restarts round 1 once the completeness check and the vote reconciliation pass and the package fits; its stopped answers move to a superseded directory.
Full change note
Carrying selected items puts a choice into the package that carrying a whole document did not. The rule, the item index and a check by someone other than the editor are what keep that choice from being the editor's.
v1.41
Carried documents
When a frozen brief names a City council file that the City portal will not serve to automated tools, and the site holds a copy a person downloaded in a browser, the reviewers now get that file's full text. Every seat gets the same text, marked as source material, and researches everything else itself. The run commits a manifest of hashes and checks; the text is never published. A story that relies on a carried file says so beside the source.
What changed
What happened. The council-pause-vote brief rests on report IS03688 and the three versions of its Attachment 5. The City serves those files at addresses that answer scripts and AI tools with a browser check (HTTP 403), while anyone can open them in a browser. The brief says an inaccessible essential source stops a run, so under the old method the run could not start. The site already held browser-downloaded copies of all four, identified by hash in the evidence registry.
The rule. A document is carried only when the frozen brief names its public URL, the site's fetcher is still refused there by a browser check, and the site holds bytes a person downloaded in a browser. The brief names the URL either exactly, or by the portal's address template on the same host together with the file's number in a sentence that lists it as a DocumentId; a bare number anywhere else does not count, and the manifest records which way it was named. Only an HTTP 403 carrying Cloudflare's challenge header or its challenge page counts as a browser check, and the manifest records which of the two matched; a 401, a 429, a server error or a bare 403 does not count. The manifest is rebuilt before each round, which probes every URL again, and a probe more than six hours old, or dated in the future, refuses the package; in round 2 every carried URL must have been probed after round 1 finished. A document the fetcher can now retrieve is not carried, because the seats can fetch it themselves. The council meeting page must still list the file under the same title and DocumentId, compared against an archived copy of that page whose hash is checked first; a revision or a withdrawal stops the run. The text is extracted with pdftotext, and every seat in a round, and in round 2, gets the identical section, labelled as the text of a City document and not instructions.
The guards. The manifest names who downloaded each file, when, and that it was in a browser, and who confirmed, within the 72 hours before a launch, that a person can still open the public URL. A session that is not the editor reads each original against its extracted text and records whether pages, tables or figures are missing or garbled; the run stops if an essential passage cannot be checked. The bytes are compared with a second browser download by someone other than the first downloader, or the manifest says why none could be made. Each document is screened for personal information beyond office-holders and City staff acting in role. A carry manifest, committed before the run and unchanged at launch, records per document the public URL, the download date, the file size, both hashes, the extraction tool and version, the probe result and time, the reason it is carried, and each check. The runner accepts only the run's own manifest and texts inside the run's private directory. It refuses the package if a check is missing or failed, a text does not match its hash, or the package is over its seat's fixed ceiling, which is checked again before a retry is sent. Every seat's row records the hash of the section it received, and a seat whose section differs from any other row in the run, in either round, is refused before it launches and again before its answer is installed, so a mismatched answer is never filed. The site never calls agreement on a carried document independent retrieval: the seats' independent work on it is their reading of it and their other research, and what a City document says is attributed to the City. A source read this way is labelled beside it, with the City link, the method, a note that all reviewers read the same copy, and the byte hash.
Who did what. The founder decided it, on the editor's recommendation. Four board memos run on GPT-6 Sol, for evidence and methodology, public trust, product and audience, and technology and sustainability, each said ADOPT WITH CHANGES. Every change they asked for was adopted and none was rejected. Sending a public City record to the two panel vendors is the same act as their own web tools fetching it, which the method already relies on; that is the editor's reasoning, not a legal reading. The first story published under this rule gets a cold-reader phone test as part of its rendered critique.
Full change note
A browser check stops a script, not a reader. Carrying the file lets the panel read what any resident can, and the label keeps the site from claiming the reviewers found it on their own.
v1.40
Google seat gone
The last route to the Google seat closes. v1.37 retired it for new runs and let a run frozen before the retirement finish on it; the one such run, lanes-and-congestion, is closed incomplete and restarted on the current three seats instead, and the exception is gone. No stage of any run uses a Google model.
What changed
The founder's words: "close the attempt and restart clean under v1.37, we can't wait for gemini reset, it just eats through tokens too fast, we should drop gemini altogether from all work." v1.37 named a clean restart as the alternative to waiting a week, and this is that choice.
The closed attempt is kept whole beside the run, under closed-2026-09-23/: three counted answers from three vendors, the uncounted Luna answer, the manifest, the merge and the fetch report. None of it is an input to the restart and no answer is carried across. The restarted round 1 runs the three current seats named in v1.37 on the unchanged frozen brief, with the roster fixed before any seat ran. The editor has read the closed answers; the seats have not, and the synthesis rule decides the finding, so the restart changes the roster and nothing else.
The runner now refuses the Google seat with no flag. The launcher keeps the profile only so the tests can exercise the code that produced the answers already published under Gemini; no caller passes it.
Full change note
An exception kept for one run is a door left open for every run. With that run restarted there is nothing left for it to hold open.
v1.39
Wording confirmation
A brief whose third framing report leaves only fixes the checker has already written out word for word can now be applied and confirmed instead of parked. The editor pastes the checker's text and nothing else; a separate reader decides beforehand that every finding qualifies; the same checker then confirms the edit or rejects it. One of the two briefs that asked for this qualifies. The other does not, and stays parked.
What changed
What happened. Two questions many people asked in the first source, whether Edmonton's roads are in poor condition (infrastructure-deficit) and who pays for roads (who-pays-for-roads), have been parked since 2026-09-03 by the three-report cap. v1.35 gave a route for a third report that parks claims; neither brief's report does. infrastructure-deficit's report leaves one finding, with its replacement sentence written out by the checker. who-pays-for-roads leaves four.
The rule. Every standing finding of the third report must carry copy-ready replacement text, or ask for a park the v1.35 way. The editor applies every one of them exactly as written, with no new quotation, calculation, source, lookup or drafting. A finding whose fix needs any of those makes the whole brief ineligible, and no new wording is asked of the checker to make it eligible. Before the confirmation, a reader who is not the editor (a separate read-only model session) reads the third report, this rule and the editor's finding-to-edit table and records ELIGIBLE or INELIGIBLE for each finding. The brief then goes once to the same seat and pinned model as the third report, which reads the whole difference against its own report and the sources the brief already cites, and answers CONFIRMED (the brief freezes) or REJECTED (it parks, reopening only on new intake evidence). There is no dispute route, no cutoff is reopened, and there is no further report.
Applied. infrastructure-deficit qualifies on the editor's reading and goes to the separate eligibility reader, then to confirmation; the result is published in its run record. who-pays-for-roads does not: one replacement names attachment addresses without giving them, one asks for phrases to be replaced throughout with no text supplied, and one depends on what the 2024 provincial manual says, which is a source reading. It stays parked. The editor disputed one of its findings in September and has since conceded it after the 2026-09-09 audit withdrew a related allegation; that history stays in its run record.
Who did what. The founder asked for the two parked briefs to be worked on and decided the rule. The editor proposed it, applies the edits and conceded the findings. The board, four role memos run on GPT-6 Sol, reviewed it and made it stricter: copy-ready text only, and a separate eligibility reader. The confirming seat checks a bounded edit and does not re-verify the claims. This is the third change made to the framing cap after the cap stopped the editor's own briefs, after v1.20 and v1.35, and the site says so rather than leaving it to be found.
Full change note
The cap stops an editor revising until the checker gives up. A report whose every fix is already written by the checker leaves the editor nothing to revise, so the route lets the editor paste and nothing more, and puts the gate in someone else's hands.
v1.38
Capture check binary note
The capture check that admits a Claude seat now permits one thing it used to refuse, and prints a count of it on every run row: the operator's home-directory path when it appears only inside the note Claude Code itself writes after saving a fetched binary to disk. The path is still sent to the vendor; the row says how many requests carried it. Every other occurrence of any protected string still refuses the run.
What changed
What happened. On 2026-09-23 the Claude seat (Opus 5.5, Claude Code 2.1.280) ran the lanes-and-congestion brief to completion and was refused by the capture check: fourteen of forty-two requests carried the home-directory path. The cause was the CLI's own behaviour, not an instruction file on this machine. WebFetch retrieved a 2.6 MB City PDF, the CLI saved it under the operator's home and put "[Binary content (application/pdf, 2.6MB) also saved to <path>]" into the tool result, and that note then sat in every later request. The refused attempt, 09c6859382ba86e9, stays refused and retained; nothing about it is reclassified.
What changes. The check cuts that one fixed note, and only where the CLI writes it, out of a tool result before searching it for the home path: the note must sit inside a tool_result block and name a path under the CLI's own projects directory in the operator's home, in a tool-results folder. The same words in a text block, a system prompt or a tool input, or a note naming any other path, are searched as sent. The check counts the requests where it cut a note and puts the count on the run row as operator_path_notes. The home path anywhere else, the repository path anywhere, and the canary token anywhere refuse the run exactly as before. The proof sentence on a passing row says, when the count is above zero, that the path was sent to the vendor and is recorded rather than refused. This is a disclosed exposure, not a clean capture, and no row calls it clean.
Why this and not the alternatives. Giving the seat its own configuration directory under the temporary path, as the other seats have, loses the login: the CLI keys its Keychain entry to that directory, and making it work would mean a script copying the operator's OAuth token into a per-attempt Keychain item, which nothing on this site will do. A separate account and machine user for the seat is the structural fix and is open in the board record. Until then the exposure is the operator's own home path, which names him, and he is already named on the site as the founder; the account email and id in the captured request have been disclosed on the same footing since v1.29.
What the attempt also showed. The fetch handed the reviewer the PDF's raw bytes, which it could not read, so the document was saved and not read. That is the web-only profile's limit as v1.28 disclosed it: public-web tools may not retrieve PDFs a shell could, and an inaccessible essential source stops a run rather than becoming a finding. The refused attempt's Not established is not a finding of this site.
By whom. The founder, told the three ways out, said "do what you think is best"; the editor chose this one and put it to the full board with the two-vendor change below. Four memos, all REVISE, every required change taken: the exception is prospective, exact, counted and disclosed, and the refused attempt stays refused.
Full change note
A rule that refuses a run for a string the tool itself wrote is a rule that will be turned off the first time it bites. Better to say exactly what is let through, count it, and print the count where a reader will see it.
v1.37
Two vendor panel
The Google seat retires. For every run frozen after 2026-09-23 the panel is three model seats from two vendors, one Anthropic model and two OpenAI models, and every page that describes the panel says so. The two OpenAI seats are not independent of each other, so three agreeing verdicts are not three independent confirmations. Runs frozen before this date had three vendors and keep that label. The matrix, the agreement words and the synthesis rule do not change; what changes is what agreement means.
What changed
Why. The Google route is one command-line tool on a consumer account whose weekly allowance ran out on 2026-09-16, blocking the second intake for a week, and again on 2026-09-23 after one panel seat and three audit attempts. The founder will not buy more: "we should drop gemini completely, I don't have enough usage to continue with it." The site's method has always run on the founder's subscriptions; a seat he cannot afford to run is not a seat.
What the panel is now. Claude Opus 5.5, GPT-6 Sol and GPT-6 Luna, all at high, pinned in the launcher. Two seats, two vendors, would have needed a new synthesis rule for two verdicts and left two rules on the site; two Anthropic seats would have put the editor's vendor in the majority; a paid third vendor is money this method has never spent. Three seats from two vendors keeps the matrix, the vocabulary and every published finding's meaning intact and moves the loss to where it belongs, the independence claim, which is now stated wherever the panel is described: on the methodology page, on every finding, in the glossary, in search descriptions and share text. Panel agreement, Unanimous, Adjacent or Split, describes seats, not vendors.
The vendor split. When the Anthropic seat differs from both OpenAI seats, the finding names the vendor split beside the seat agreement and the drafting addresses it from the sources. It is never presented as a plain two-to-one majority. The quality ledger tracks the Luna seat's catches and misses and any miss the two OpenAI seats share, with a review point after several counted runs; one shadow run is not evidence of quality, and this entry claims none.
Effective date. A run frozen under the three-provider rule finishes under it. Lanes-and-congestion froze on 2026-09-23 before this entry; its round 1 counts the Gemini seat's admitted answer and keeps the Luna shadow answer as shadow, and its round 2 needs the Google seat once more, after the allowance resets about 2026-09-30, unless the founder closes the attempt as incomplete and starts a clean run under this rule. No panel is assembled from answers already seen. The runner starts the retired seat only with --finish-frozen-run; audits refuse it outright.
The other stages. Triage reads on GPT-6 Sol and GPT-6 Luna at high, one vendor, and the register says so; a proposition both decline or park is re-decided by an Anthropic audit reader before the register records it, so one vendor cannot quietly remove a claim. The extraction seats are Haiku 4.5, Sonnet 5 and GPT-6 Luna at low, from two vendors. Faithfulness, plain-speech and gate audits run on OpenAI, off the editor's vendor as before. The shadow-seat experiment of v1.34 ended after one run, superseded by Luna counting; the one comparison stays in that run's record. A preflight step (scripts/panel/preflight.sh: the seat's CLI version, and for Codex its reported login state; Claude's Keychain login is proven by the canary) runs from the runner before a package is assembled, so a dead seat is found before anything is sent; the quota probe is the launcher's canary itself, a one-line model call that every attempt already makes and that fails on an exhausted allowance before the package goes.
By whom, again. The founder decided the retirement on cost; the editor chose the shape and put it to the full board: four memos, all REVISE, every required change taken, one split resolved three to one against counting the shadow answer for the run in progress. The memos ran on GPT-6 Sol, the vendor that gains two seats, so the pass spent the usage the founder has and asked the beneficiary to argue against itself. The board record is private; this entry is the public account of it.
What this entry does not do: it does not change the matrix, the agreement words, the cautious lean or any published finding; it does not claim the two OpenAI seats are independent; and it does not claim Luna reviews as well as the seat it replaces.
Full change note
Three vendors was the method's best argument for independence, and it is gone for as long as the founder pays for two. The honest move is not to find a third seat that looks like a third vendor but to say, on every page, what the panel now is.
v1.36
Register fold
When a new source raises a claim the register already holds, the merge now marks it with that claim's id, and its wordings are added to the existing claim under the new source's name. No near-duplicate claim is registered beside it. The register generator prints this as an addition to the existing claim. On the second source, one claim was folded this way and one was kept apart.
What changed
Decision D-0030 required this, and the second source showed it could not happen. The merge prompt gave the seat the register and did not say what to do with a match, and the generator could only print new claims. The prompt now says: when a merged claim and a register claim would be settled by the same evidence, set `register_id` to the register claim's id and keep the forms, seats, side and commenters as usual. It does not rewrite the existing wording, and when unsure it does not fold. A near-duplicate costs one extra check. A wrong fold puts a person's words under a claim they did not make.
The generator prints a third block beside the new questions and claims. For each existing claim, it lists the wordings to append, the seats to add and how much the claim's people count and its question's count rise. It still prints and does not write. A folded claim is not grouped into a question, because it already has one, and the grouping check accepts it being absent and refuses it being present.
One pseudonym is one person within one source. A wording from another source therefore always adds one person to the count, even if the pseudonym matches one already counted. The site stopped printing people counts under D-0030 for this reason. The register validator already checked each wording against the capture its own source names, so a claim with wordings from two sources passes. Tests now cover that case.
On the second source, the claim that Edmonton's roads are in poor condition although taxes pay for them was folded onto the first source's claim about the poor condition of roads and basic services. The same road-condition records settle both, and that claim already held wordings about roads alone. The question the second source had registered around it held nothing else and was removed. Its address now redirects to the older question. The claim that Edmonton plans to raise taxes substantially over four years was kept apart from the property-taxes question, because past bills and a future budget plan are settled by different records.
Full change note
A register that grows a near-duplicate for each source stops being a register. The second source is the first time this could happen, and the step was missing. It has been added now, before a third source makes the fix a cleanup job.
v1.35
Park confirmation after the third report
A third framing report that says the record cannot carry a claim no longer ends the question. The editor may apply that report unchanged, park the claims it found uncheckable in public with what would reopen them, and send the brief back once for a park confirmation. The same checker either confirms the parks and the brief freezes with what is left, or rejects them and the brief parks as before. One round, and nothing in it reopens an argument.
What changed
What happened. Three of the four questions most people asked in the first source are parked by the three-report cap (methodology v1.12): infrastructure-deficit and who-pays-for-roads since 2026-09-03, lanes-and-congestion since 2026-09-16. On lanes-and-congestion the third report's decisive finding was that the City's published evaluations of its lane conversions are counts and monitoring, not the before-and-after studies that could attribute a travel-time change to a conversion, so three of the four claims cannot be answered at the causal level people assert them, while the fourth, that the City removed traffic lanes, is checkable and its ladder passed. The editor agrees with every word of that. The method already knows what to do with it for a claim, since v1.24 parks a claim the panel could not answer and publishes the reason; the cap forbade doing it for a brief. A rule written to stop a brief being revised until a checker gives in was ending questions on findings the editor agrees with.
The route, and when it exists. After a third REVISE the editor may, instead of parking the brief, apply every standing finding of the third report in the checker's own wording, and remove from the brief each claim that report found uncheckable at the asserted level from the identified record, parking it on the register on the v1.24 ground with the instrument that would reopen it. Every standing finding, not some: an editor who disputes any standing finding of the third report has no route here and the brief parks under v1.12. The only edits allowed are the checker's wording and those removals; no source may be added. Each edit is recorded in the run record against the finding it answers.
The confirmation. The brief goes back once, to the same checker seat, vendor and pinned model, as the third report. That report re-examines no finding. It reads the whole difference between the third-report brief and this one, confirms that each park is what the third report asked for and that every edit traces to a finding, re-applies checks 8 and 9 (stakes, and who asks this) to what remains, and ends `PARKS CONFIRMED`, on which the brief freezes with the remaining claims, or `PARKS REJECTED`, on which the brief is parked as it would have been and reopens only on new intake evidence. An edit the report cannot trace to a finding, or a framing finding against a remaining claim, is a rejection. There is no fifth report. FRAME OK and REVISE are not available in this round, for the reason v1.20 gave: REVISE means another revision, and this round cannot send the brief to one.
What the reader sees, which is the part that matters. A question whose brief freezes this way shows each parked claim beside the finding, with the reason the record cannot answer it at the level people assert it and the instrument that would reopen it, and the story's ten-second layer leads with those parks, not with the finding. The remaining finding is never presented as the answer to the question it came from: that the City removed lanes in some district-plan areas is not an answer to whether the lanes cause congestion, and a page that let a reader take it for one would be the checkable-over-contested failure D-0028 names. A question frozen with parked claims does not count as answered for promotion under D-0028. A claim parked here is recorded as parked at framing, because the register's claim page otherwise says it went to the panel and it did not.
The guards, carried from v1.20 and added to. The checker labels its own findings, so what the editor applied is auditable against the committed report. The confirmation runs on the seat that wrote the third report, so the editor cannot shop for a friendlier checker. Nothing about a cutoff value is reopened. The cap's own purpose, no endless revision against a checker, is untouched: this round exists only for an editor who has conceded everything, and it ends.
Why no dispute route. The board pass split on one point: whether an editor may dispute a standing finding of the third report on a factual premise, with the source passage quoted, and have the confirmation verify that passage. Three roles would allow it narrowly; one would not. It is left out. The stricter rule is simpler to audit and closes the concern by construction, and the case first offered for it does not support it: the editor's earlier account of the roads briefs had two of check 3's findings failing verification, and the 2026-09-09 trace audit found the opposite on the finding that mattered, the editor's allegation that the checker had invented a comment count was false and was withdrawn. If a real case arrives where a third report's decisive finding rests on a misread source, that is its own entry, argued from that case.
Why by whom, again. This is the second time the cap has been amended after it blocked the editor's own brief; v1.20 was the first. Three things are offered. The founder decided the change, on the editor's advice, and the full board reviewed it before it was written, four memos, all REVISE, every required change adopted but the dispute route, on the private record. The checker controls the confirmation and can reject. And the lanes parks cut both ways: the claim that removing lanes causes congestion and the claim that bike lanes reduce it are parked on the same ground, for the same reason. What would show this was wrong is a park confirmation becoming routine, or the parks falling on one side of the questions they come from. Both are visible in the run records and the register.
Full change note
v1.20 opened the cap for arithmetic the checker had already corrected; this opens it for a finding the editor has already conceded. Arithmetic has one answer, and "the record cannot carry this claim" is a judgement, which is why this round belongs to the seat that made that judgement and to nobody else.
v1.34
Reviewer model refresh
Two panel seats move to the models their vendors released on 2026-09-22: the Claude seat from Opus 5 to Opus 5.5, the OpenAI seat from GPT-5.6 Sol to GPT-6 Sol, both at the same pinned effort. The stages that are not pinned in a script take the same two models where they used the old ones. A fourth, uncounted seat on GPT-6 Luna starts running beside the panel so that the question of how cheap a research seat can be is answered by a comparison on the record rather than by a guess. No published finding changes and no run is re-done.
What changed
New review runs pin the Claude seat as claude-opus-5-5 and the OpenAI seat as gpt-6-sol, both at high. Opus 5.5 defaults to medium effort, so the explicit pin is what keeps the seat at the level v1.6 chose. The Google seat stays on gemini-3.8-flash-high. Runs already published under Opus 5, Fable 5.1 or GPT-5.6 Sol keep the model their manifests record. GPT-5.6 Sol also stays on the launcher's pinned list, never as the default: v1.35 has a park confirmation run on the same pinned model as the report it confirms, and every framing check before this version ran on GPT-5.6 Sol. It leaves the list when no brief parked on those checks can still be confirmed.
Both moves are cost decisions, made on the vendors' list prices linked below: Opus 5.5 is a fifth cheaper than Opus 5 and GPT-6 Sol half the price of GPT-5.6 Sol. Both vendors publish accuracy claims for the new models. This site has measured none of them, and the entry does not say either seat reviews better than the one it replaces.
The seats that are not pinned in a script follow. The framing check, the intake merge and grouping, the publication gate audit and the freshness audit use GPT-6 Sol at high where they used GPT-5.6 Sol. Triage reads on GPT-6 Sol and Gemini 3.8 Flash, both at high; when the Google tool's quota fails, on GPT-6 Sol and GPT-6 Luna, with the one-vendor limit stated in the run record as v1.33 stated it. Either pair satisfies the rule that both readers come from a vendor other than the editor's, which v1.33's two Anthropic readers did not. Extraction runs on Haiku 4.5, GPT-6 Luna at low and Gemini 3.8 Flash at high; when Google is down the substitute seat is GPT-6 Luna at high, disclosed as two OpenAI extractors. Drafting stays with Claude, the fixed choice stage 6 discloses.
The shadow seat. For the next two panel runs a fourth seat on GPT-6 Luna at high receives the identical frozen package through the same launcher and profile as the counted OpenAI seat. Its answer is committed under the run in a directory whose name begins with shadow-, with its own manifest, and it is never merged and never synthesised: the runner refuses any other destination and refuses round 2, because the merge reads every file in a round directory, and the run's synthesis scope names no shadow. The run record compares its sources and its findings against the three counted seats. The reason for the test rather than the move is in the record: the intake stages are small and factual and already run on the cheap tier, but a panel round is a search-and-read loop of up to half an hour whose cost is the loop, and a source that every cheap seat misses comes back as Not established by omission, which no later gate can catch. After two runs the editor recommends and the founder decides. Until then no finding rests on the shadow seat and no reader is told one does.
What this entry does not do: it does not claim a quality comparison between any two models, it does not change the three-vendor requirement, the round rules, the effort pin or the vendor exclusions on the checks, and it does not put a cheap-tier model on a counted seat.
Full change note
A model release is not a reason to change a method, and a price cut is not a finding. What a price cut buys is the room to ask, on the record, how cheap a seat can be before it stops finding things, and to answer that with a seat whose answers count for nothing until they have been compared with seats whose answers do.
v1.33
Intake source note
The intake prompts no longer name one source's argument. Each whole-source run now commits a source note, one paragraph saying what the people in that source are arguing about and what "for" and "against" mean in it, and every seat reads the note after the prompt. The second source read under this method, a public-group thread on garbage collection, snow clearing and taxes, ran on two vendors rather than three, and the run record says so and why.
What changed
The extraction and merge prompts defined a claim's side as a position in "the bike-lane spending argument". That was the first source's argument written into the method as if it were part of it, and the second source, which is not about bike lanes, exposed it before a seat ran. The definition now points at a source note the run writes and commits beside its artifacts. The note describes the source and its two positions; it names no claim and chooses none, which is the property the rest of the stage rests on. The examples inside the prompts still come from the first thread, because an example has to come from somewhere.
The Google seat could not run on the second source: the only working Gemini command-line tool on the machine reported its account quota exhausted for about a week, and the vendor's other tool refuses to authenticate at all. The founder chose to run the source on two vendors rather than wait, and the record carries that as a stated limit rather than a footnote: extraction on three seats from two vendors, and triage on two readers from one vendor, which is the vendor the merge did not run on. The first run's argument for three seats, that the weakest seat found a fifth of what the strongest did, applies here with one seat fewer, and a claim only the missing seat would have found is a claim this run did not see.
Full change note
A method that names its first source in its rules will read every later source as if it were the first. The fix is not to generalise the wording but to move the source's description out of the method and into the run, where it is written fresh each time and published with the result.
v1.32
Readable layers
A question page now has a ten-second layer. The standfirst is one sentence a person would say to a friend, the TL;DR is a few plain sentences with one fact each, and the exact figures, years, sources and denominators they used to carry live in the explanation, beside the sentences they support. The plain-speech read now reads those two layers as well as the answers. No finding, figure, hedge or source changed on any page.
What changed
The founder's complaint, for the second time, was that the published stories are hard for normal people to read. The 2026-09-03 pass had answered the first complaint by fixing the vocabulary of every layer, and it worked as far as it went. Measured on 2026-09-16, the seven live standfirsts ran 24 to 78 words with a median of 44, the TL;DR bullets 16 to 78 with a median of 34, and four of the seven explanations opened by describing what the frozen brief asked the reviewers. Every layer was plainer and every layer was still written at the journalist's depth. The charter's ten-second reader had no layer of their own.
docs/DESIGN.md section 12 now says what each layer is for. The standfirst is one sentence carrying the stance and at most one fact. The TL;DR is three to five sentences a person would say, one fact each, numbers rounded, with no source names, survey years, denominators, comparator lists or method words. The explanation is where the exact figure, the year and the source live, beside the sentence they support, and it opens with what happened rather than with how the question was put to the panel. Claim detail is where the brief, the split and what a seat tried belong. A length rule for the two top layers exists only as a validator warning, because a length that failed the build would be the thirty-word cap coming back.
Nothing moves up a layer by being deleted from the one below. A figure that leaves a bullet lands in the explanation, and the plain-speech read's clause accounting now covers the standfirst and every bullet as well as the answers, so a figure that left the top of the page and is nowhere below is a rewrite of the page. prompts/plain-speech-read.md carries the rule and the report shape.
The seven live pages were re-layered under the rule in one batch, each with a changelog entry. A model from another vendor read the standfirst and every bullet before merge and rewrote 34 of 42; 27 were taken in whole or part and 7 refused with reasons. A fresh session then read the rendered pages as a resident and found the three single-claim pages printing the claim's answer and the standfirst ten words apart, two bullets calling counter passes riders, and a bullet handing the reader a number beside one saying the number cannot be calculated; all fixed. The founder then ran two more outside comparisons of the old and new pages in fresh sessions; both found the same three things in the way: the provenance line and the board notices sitting between the answer and the TL;DR, seven claim rows before the page-level answer on the cycling page, and a launch banner that told a reader the site had not found its method. All three are changed. The page now runs title, answer, TL;DR, then the claim strip on a question with several claims, then who checked it and when, in the same words one block lower. They also caught three regressions against recorded corrections (a categorical "not money the City has lost" on a Not established finding, the freedom-of-movement line placed in the plans rather than the District Policy, and "measured" for "published"), all fixed. A third comparison quoted text that exists on no version of any page and was discarded. All four reports sit with the editor's dispositions under reviews/2026-09-16-readable-layers/, and docs/readable-layers-2026-09-16.md lists every string that changed beside its old wording.
Full change note
This is the second pass at the same complaint, and the first one did not fail. It fixed the words and left the depth, which is a different fault with the same symptom. Length is the visible sign and not the rule. The rule is that each layer is written for its own reader, and the only check that can tell is a person reading it aloud.
v1.31
Three seats under stated limits
Two of the three reviewer seats were stopped because nothing recorded what was sent to them. They can run again. Each one now runs under the strictest setup its own tool allows, and the check released this morning searches whatever record that tool produces for the private text on this machine. The Codex seat has its outgoing request recorded, the same way the Claude seat does. The Gemini seat has no way to record a request at all, so the check reads that tool's own record of the run instead, and the run record says so in a word of its own.
What changed
The founder's reason, and the whole of it. Complete isolation is not available on a subscription tool. A fully controlled context needs direct calls to a company's programming interface, and the project does not pay for those. So the choice was between three seats under stated limits and no panel at all, and he chose the three seats with the limits written down. The steward's objection of September 9 stands beside this and was not withdrawn. It held that describing how a tool is run does not on its own earn that tool a seat under the contract this site set itself. Nothing in this release answers it. It states what each seat can and cannot show and lets a reader judge.
The Codex seat, what the check covers. Every request the tool sends to the model is written down before it leaves the machine and searched for the private files this machine holds. Each attempt runs from a fresh settings folder holding nothing but a link to the login and two lines naming the model and the effort level, with the host's skills catalogue, plugins, apps, hooks, memories, multi-agent features and the rest switched off by flag. The run record carries how many requests were captured, how many had a body to search, and which private files the search was built from.
The Codex seat, what the check cannot cover. The tool runs its shell and its web access through one internal host and they cannot be separated. Switching that host off takes web search with it, and when the September 9 probe did exactly that the model reported a web page it had never fetched and finished cleanly. So the seat runs with web access on, which means a shell it can also reach. Its read-only sandbox can read the whole computer, and the test file this project plants for its own check IS read every time. That is recorded as a read the setup allowed, not hidden. What refuses a run that touched something private is the search over the request: a tool's output comes back to the model in the next request, so private text a reviewer read is private text the check sees. The check refuses the run. It cannot prevent the read.
The Gemini seat, what the check covers. This tool ignores every setting this project can use to point it at a local recorder, so there is no request to record and none is claimed. What it does write down is an event stream, a transcript of the run, and the page contents its own fetch tool saves, and the same search runs over those. Each attempt runs from an empty home folder holding links to the login and a settings file that refuses every file, write and command tool at the permission check. The live check on September 16 watched two file reads refused in one run while a live page fetch went through.
The Gemini seat, what the check cannot cover. It sees what the model produced and what its tools returned. It cannot see the standing instructions the tool attached on the way out, because they are in no record on this machine. Keeping the operator's own instructions and extensions out rests on running from an empty home folder, which the probe supports and cannot prove. The tool also writes its logs, caches and built-in skills into the operator's real folder whatever home it is given, which is disclosed rather than fought. And with no request recorded, nothing here shows where the request went.
A fourth word in the run record. Until today a run's context check read pass, fail, or unavailable. It can now read record-only, which means the same search ran over a tool's own record of the run rather than over a request. It is weaker than pass and it is a separate word so that no reader has to know which seat had a recorder in front of it. Only the Gemini seat may be admitted on it. Every row also now says which kind of evidence was searched, so the two are never confused.
How a login reaches a reviewer. Through a link, never a copy. Each attempt builds its own folder, readable only by the operator, holding a link to the login the tool already uses, and nothing in this project ever reads a login file or writes one. A machine that is not signed in is a refusal before anything is sent. Afterwards the links are removed as links, never followed, and only the files and folders this project made are taken away.
Two things the first live runs corrected, on the record because they were found by running rather than by reading. The version written into the run record was the first word of what the tool prints, which for one of them is its product name rather than its version. And the Gemini tool saves the page it fetched into a file under its home folder and then tells the model where that file is, so putting that folder inside the archive handed the reviewer the operator's home folder. The check caught it and refused the run, which was right. The folder moved into the same unnamed scratch space the working folder already uses, and only the parts worth keeping are copied back.
What is unchanged. The Claude seat and its checks. The recording program and the retention terms. The refusal to install anything the launcher did not admit. The requirement that a recorded request was taken against the company's real address. The models and effort levels pinned to each seat. The three-seat rule, and the caps on framing checks. No run published before today is certified by this. A check written this afternoon cannot have judged a run from last week.
Full change note
This admits two seats under limits, not because the limits were solved. The Codex seat can read a local file and is caught afterwards rather than stopped. The Gemini seat has no recorded request at all. Both are running because a panel of one is not a panel, and both say in the run record and on the public page exactly what their check did and did not look at.
v1.30
Capture check simplified
The reviewer's outgoing request is still recorded. What it is checked against is simpler. v1.29 compared every captured request against a pinned description of a clean one, keyed to one version of the tool and one model. That description had to be rebuilt by hand every time the maker shipped a new version, which is several times a week. The founder decided the cost was not worth paying. The check now searches the captured request for the private text that exists on this machine, which needs no rebuilding when the tool changes.
What changed
The founder made this call on cost and on version rot, over the steward's advice to keep v1.29. A pinned description of a request is exact, and it goes stale the moment the maker ships a new build. Between September 15 and September 16 that was already true of the only version the table described. Every new version needed a fresh live capture, a new pinned row and a paid probe run before any reviewer could run at all, and the probe itself sends a request. A check nobody can afford to keep current is a check that gets switched off.
What is removed: the pinned description of a clean request; the table of pinned descriptions keyed to a version of the tool and a model; the pinned copy of the tool's own program file and the private archive of it; the refusal to run any version that has no pinned row; the substitute table that let the tests stand in for it; the record of which standard prompt and which tool descriptions were sent, by fingerprint; and the counts of each kind of side request. Six sanitized fixture files derived from a real capture are deleted with them.
What replaces it: the check reads the private files that exist on this machine at the moment of the check. Those are the instruction files in the operator's home directory and in this repository, every project memory file, the home directory path itself, the repository path, and the synthetic token the attempt plants for its own canary. Each file is split into lines, every line of 24 characters or more becomes something to search for, and every text value at any depth inside the body of every captured request is searched for every one of them. A hit is a leak and the run is refused. A capture that does not carry the declared package word for word at least once is refused too, because a capture that cannot be tied to the package it was meant to carry says nothing about it. What is searched is the request bodies and only the request bodies. The delivery headers, the addresses the requests were sent to and the replies that came back are all recorded and retained beside them, and none of them is searched, so a pass is a statement about the bodies of the requests. The run record carries how many requests were captured and how many of those had a body to search, because the two are not the same number and a reader should not have to assume they are.
A refusal names the source file and the line number and never the line. The private text is read into memory, compared, and dropped. Source names are written as $HOME/... and <repo>/..., because the home directory and the repository path are themselves two of the things the check is defending. The public run record carries those names, whether each file existed, and how many lines of it were used. It carries no line of any of them. The project memory files are reported as one entry with a count of how many were found, because there are 92 of them on this machine and a run record nobody can read is not a public record; they are still searched one file at a time, and a refusal names the one that leaked.
What this catches and what it does not, which is the whole of it. It catches known private text from this machine. It cannot catch text the maker attaches that is not on this machine, and it cannot say what the request contains: it says only what the request does not contain. That is weaker than v1.29, which said what every field of the request was. The capture is still retained in full, so a later reader can ask a stronger question of the same bytes. On the maker's side nothing changes and nothing is observed: the capture shows what the tool attached here and cannot show anything attached to this account after the request leaves.
The objection to a check that rests on convention was made in the September 9 review, under v1.28, and it stands on the record beside this decision. The technology reviewer wrote then that a convention plus disclosure is not enough to admit a reviewer under the new contract, and nothing since has withdrawn that. The September 15 technology memo asked for something looser than v1.29 rather than stricter: it asked for the standard prompt's fingerprint to become a dated observation rather than a condition of running, and v1.29 refused, on the ground that a prompt which started carrying memory paths would pass a structure-only gate. This release goes past what that memo asked for: there is no fingerprint left at all. What the new check would catch in that scenario is the memory text itself, if the memory file is on this machine, and nothing if it is not. The same memo asked for a repinning script and recorded that each upgrade otherwise costs a manual probe; that cost is what this release removes, by removing the pin.
What is unchanged: the recording proxy and the retention terms; the flag set that suppresses host customizations; the checks on the run's own report of itself, which are the tool inventory, the absence of plugins, skills and extension servers, one start event and one result event, a zero exit and a complete final message; the synthetic canary before every research run; the runner's refusal to file anything the launcher did not admit; the requirement that the capture was taken against the production address; the three-seat rule; the model and effort pins. Codex and Gemini have no capture at all and stay blocked, so the three-model panel still cannot run and the Gemini source check commissioned for the consultation question is still blocked.
The version of the tool is now written down rather than gated. The run record carries the version that ran, and the private archive carries the path of the program file and a fingerprint of its bytes, so a reader of a retained capture can still ask which file produced it. Neither the path nor that fingerprint goes into a public record. The field naming the version the machine would otherwise have used is gone, because the launcher no longer overrides that choice.
No historical run is certified by this, and nothing published under v1.29 is re-certified under v1.30. A run checked one way was checked that way.
Full change note
This is a narrowing, not an improvement. v1.29 could say what a request was. v1.30 can say what a request was not, for the private text this machine holds, and it can keep saying it tomorrow without a paid probe run. The founder chose the second. The reasons for preferring the first are in the September 15 record and have not been withdrawn.
v1.29
Context proof admission
v1.28 said the context boundary was undemonstrated because nothing emitted the outgoing request. The reviewer CLI now runs through a local recording proxy, every request it sends to the API is retained and checked against a pinned description, and the Claude seat is admitted for research only when that check passes on a canary run and on the research run.
What changed
Every launch of the Claude reviewer goes through a loopback recording proxy that writes each outgoing request and response to the private archive and forwards them to https://api.anthropic.com unchanged. The proxy never rewrites a request. Authorization, API-key and cookie headers are replaced with a placeholder in the retained copy only. Claude Code 2.1.272 honours the base-URL setting under the candidate profile, which is what makes this possible; no global authentication or configuration was changed and no filesystem restriction was added.
The check classifies every captured request into one of five observed shapes and fails if any request matches none of them. A passing run requires: one session-naming request whose body is the declared package; at least one main turn whose system blocks are the vendor default prompt (pinned by SHA-256, not published), the vendor agent line and a version-stamped billing header; exactly two client tool definitions, WebFetch and WebSearch, pinned by SHA-256; a reasoning effort in the request itself matching the pinned seat, which until this release was a setting nobody could check against what was sent; a first user message of exactly two blocks, the account email reminder and then the package byte for byte; a single system-role message carrying the working directory, the git flag, the platform, the shell, the operating-system version, the model identity and the date, matching a fixed template; and, in later messages, no block other than tool results in a user message, with each tool result's own content required to be text and scanned for the host's reminder markup. That last part is a check on block types and on one marker string. It is not a general test for instruction text.
The description is pinned per reviewer model, not per CLI version alone. The first live run under the pinned Claude seat was refused by this check, because the description had been written from feasibility probes that used a smaller, cheaper model and the same CLI sends a different request for each model: a different standard prompt, different tool definitions, and the host context in a different place. The refusal was correct and the description was wrong. It now names both the CLI build and the reviewer model, and the probe-derived description has been removed rather than kept alongside.
Two further corrections came from the first live research run, and both were defects in the description rather than in the run. The web-search helper's tool definition carries the search scope the model asked for, so a search restricted to two government hosts was refused for not matching a fixed shape; the helper's tool is now checked by kind and name, with the scope recorded rather than required. And the count of how many exchanges took place was read from the order events arrived in, which miscounts when one tool's result comes back before the model has finished asking for the next; it is now read from the identifier the service itself puts on each exchange. Nothing was sent that should not have been in either case: the check stopped the run and said what did not match.
The package reaches the vendor twice per attempt: once as the research request, and once before it in the session-naming request, which carries the whole package and no tools. Both are captured and both are checked.
The request carries host context the declared package does not, and this is the full list of it in the request body: the working directory, whether that directory is a Git repository, the platform, the shell and the operating-system version; the model name and its knowledge cutoff; the current date; the operator's account email address; and, in the request metadata, a device id, an account id and a session id. Under the pinned seat the email address arrives in the first message and everything else in a separate message, except the three identifiers, which travel in the request metadata rather than in any message. All of it comes from the vendor's own text. It is disclosed, not suppressed: the proof report records the two message blocks verbatim with the email address replaced by a placeholder, and records that the three identifiers were sent without recording what they are. The list is enforced, not merely described: the system blocks, the tool definitions, the model, the reasoning effort, the messages, the top-level request fields and the metadata fields are each checked against the pinned list, so a field nobody described is a failure. The HTTP headers are recorded and not compared, so a passing check is a statement about the request body. The working directory is now an opaque temporary path named only by the attempt id, so it no longer tells a blind reviewer which story, round or seat it is working on.
Limits, stated because a capture invites the opposite reading, and there are two sides to them. On this machine: the proxy sees only what the CLI addresses to its configured base URL, nothing else on the machine is monitored, and the vendor prompt is pinned by hash rather than read or published. On the vendor's side: the capture shows what the CLI attached here and cannot show anything the vendor attaches to this account after the request leaves. A passing check is evidence about one attempt under one CLI build. It is not a vendor guarantee and does not cover a different build. Claude Code 2.1.266 and 2.1.267 have no pinned profile and now stop before anything is sent.
Because the check describes one build, the launcher runs that build rather than whatever the machine's path points at. The pinned build is identified by the SHA-256 of the executable, copied once into the private archive and run from there, so a published check still names bytes that can be produced after the installer has moved on. Version 2.1.273 was already installed when this shipped; the public run record carries both the version that ran and the version the path would have used, and a newer version needs its own capture and its own pinned entry before it can run at all.
Admission is narrower than the check. A run is admitted for research only when the canary and the research run each pass both their execution check and their request check, the CLI exited zero, the capture was taken against the production API, and the built-in pinned profile was used. The public run record carries the check result, whether the run was admitted, the reason, the upstream the capture was taken against, which pin table was used, the request and turn counts, and hashes of the capture and the report. It does not carry an archive path or the path of the CLI executable.
No historical run is certified by this. Every finding published before this change predates the capture, and a check that did not exist cannot have passed.
Codex and Google are unchanged and still blocked: neither has a capture-backed profile, so the three-seat panel cannot run and the consultation's commissioned Google source audit remains blocked. The model pins, the reasoning-effort pin and the framing-check caps do not change.
Full change note
What changed is the evidence, not the confidence. v1.28 refused every seat because an empty plugin list shows what was not loaded and cannot show what was sent. The request is now retained, so that question has an answer for the attempts that were captured, and only for those.
v1.28
Reviewer execution and retention
A scratch directory did not keep private instructions out of a reviewer. The roads framing audit found private project memory outside the declared package; the third report read and cited it. New reviewer launches must pass an execution check, and complete responses are retained before a report or JSON extract is made from them.
What changed
Correction to v1.14 and the methodology page: a fresh working directory and an undisclosed repository path are not an isolation boundary. The roads audit observed injected memory, but no repository read; absence of a repository read was not proven. Every finding published before this change predates the new execution check. None is retroactively certified, and this audit does not establish that every historical run received private context.
Admission requires suppression of host customizations, a public-web search/fetch tool limit, and observed request and tool evidence. Before a future research attempt can be admitted, a separate synthetic canary under the same profile must show a working public fetch and an unavailable local fixture. This is evidence about the tested execution, not a guarantee about the vendor or future CLI releases. Unsupported versions and unverified profiles stop before research; candidate diagnostics cannot return an admitted review.
The Claude Code 2.1.266/2.1.267 candidate uses Opus 5 at high effort, but its startup inventory does not expose injected instruction text and its debug log does not contain request bodies. That is insufficient context proof. The tested Codex 0.153.4 profile still received host instructions and lost working web access; that test does not rule out every possible configuration. No Google profile has been demonstrated. No research provider is admitted in this release; new panels and source audits remain blocked. Model pins, the three-seat requirement and framing-check caps do not change.
This revises the shell-access practice recorded in v1.14: shell and local-file tools are no longer available to new reviewers without a separately demonstrated boundary. Public-web tools may not retrieve PDFs or other records a shell could retrieve. Budget, roads and infrastructure checks may be blocked as a result. An inaccessible essential source stops the run; it is not grounds for a Not established finding.
Every launch attempt retains its exact package and execution metadata, even when refused. Diagnostic output, including stdout, stderr, the complete final response and check evidence, is kept privately outside Git worktrees. Future research profiles must retain the same complete record before extraction, including trailing provenance and known exit status. Retries have separate artifacts. Nonzero CLI exits, denied or unexpected tools, missing final responses and failed execution checks cannot become successful reviews merely because JSON can be extracted. Existing successful reports are not overwritten.
New public run records must carry attempt identifiers, status, known exit codes, profile and proof results, and artifact hashes, not private paths or raw traces. Historical run records are not backfilled. Complete artifacts are retained while the associated public record exists, with no automatic deletion. Ildar Abdulin is responsible for the archive; inspection requests go to [email protected]. Hash comparisons and redacted excerpts can be provided after privacy and rights review. A hash is not public access to the underlying file, and this policy cannot recover artifacts previously deleted.
The journal now corrects its claim to have captured the whole 621-comment thread. The browser displayed 669 comments and extraction produced 621 records; the difference remains unresolved. The original entry is preserved below a dated correction. The intake summary and cycling article now also distinguish the capture count from the size of the thread; the article records a correction without changing any finding.
Full change note
The roads reports were made with ad-hoc commands, not the panel wrapper. Their original session traces survived and made the audit possible. The omitted footer and the wrapper's loss of raw output are separate observed defects; the audit did not establish who or what removed the footer.
v1.27
Enforcement
Three of this project's own files described checks that did not exist. Two were fixed in the preceding changes; this one makes the third rule actually run, and adds the first mechanical guard on the rule whose absence put words in a real person's mouth.
What changed
The methodology changelog's own header claimed CI required a version entry for any change under prompts/, scripts/merge*, scripts/synthesize* or methodology/. It did not; the rule was a TODO in the validator. It runs now, in npm run validate:diff, which CI runs against the branch's base commit.
Two paths under methodology/ are exempt and the header says so: methodology/audits/ holds records that report on the method rather than change it, and the changelog is the record itself. Without those, the version number would come to mean something happened rather than the method changed.
The second rule in the same TODO runs too: a change to a claim's finding or panel_agreement now requires a matching entry in the parent story's changelog. Re-wording an existing entry does not satisfy either rule.
A claim is one assertion is a rule the merge prompt has always carried and nothing ever checked. One claim reached the public register joining two people's remarks with the word the rule names, recording someone as asserting a tax rise when their words stated a tax bill. A gate now refuses a merge whose proposition asserts two quantities that no single captured wording carries together.
That gate is a corner of the rule, not the rule, and it says so in every report it writes. Whether a wording asserts a proposition is entailment, and no string test decides entailment. The compound propositions with no numbers in them, and the whole of rule 2, still need a reader.
The gate found one claim on the live register: property-taxes-rising-sharply, the one that started this. v1.25 had already split it, so by the time the gate shipped there was nothing left to exempt. The check runs against the published register with no exemptions, and every flagged claim fails.
Replaying the version rule over the last fourteen merges to main found one that owed an entry and had none, and it was ours from the same evening: the change that added the WITHHELD LEAK fail class to the exposure audit edited methodology/exposure-audit.md, which describes the method, and bumped nothing. The rule did not exist yet to stop it. This entry records that class's arrival, so the method's public record is complete without a retroactive version for a single check.
Full change note
The uncomfortable part is not that a check was missing. It is that the file said the check was there. A gap is something a reader can weigh; a documented check that does not run tells them not to bother weighing it. The fourth finding here is what that costs when it is a rule about attribution: a real person, quoted under a pseudonym, recorded as asserting a sentence they did not say.
v1.26
Reviewer model refresh
The Gemini panel seat moves from Gemini 3.1 Pro to Gemini 3.8 Flash at high reasoning effort, and 3.1 Pro is retired from every seat on this site. Runs already published under 3.1 Pro keep the model their manifests record.
What changed
New review runs pin the Gemini seat as agy --model gemini-3.8-flash-high --effort high. This CLI carries the effort setting inside the model id, so the pinned id and the recorded effort say the same thing twice on purpose: the manifest keeps reading the same way for all three seats.
The founder's call, made on his own use of both models and on the one comparison this site has: in the whole-source intake run under v1.15, a first extraction on Gemini 3.6 Flash at low effort cited comment numbers past the end of the thread, and the same seat moved to 3.8 Flash at high became the cleanest of the three, with nothing thrown out by the quote gate. That is an extraction result, not a panel-round one. No published run has compared 3.1 Pro and 3.8 Flash as reviewers, and this entry does not claim one reviews better.
3.1 Pro also served as a triage reader, a gate auditor and an outside reader on writing briefs. Those seats are not pinned in a script; the rule that they use 3.8 Flash from here on is recorded with this entry, and the next run of each records the model it used.
The pins in v1.5 and v1.15 (the Claude seat), v1.6 (effort) and v1.14 (the Gemini seat's permissions flag) stand as written.
Full change note
Two seat changes in two days, both on cost or on the founder's read of a model rather than on a measured comparison of reviewers. That is honest about how a one-person site chooses models and it is also a gap: the method records what ran, and can re-run it, but has no benchmark that would tell a reader whether a seat change moved findings. The manifests make that benchmark possible later; nothing here provides it.
v1.25
Misattribution and prior triage
A real person was published asserting something they never asserted: their tax bill was written up as a tax rise. The gate that checks quotes never looks at the sentence written on top of them, so it could not have seen it, and the merge rule that would have stopped it was written during this very intake run and enforced by nothing. Alongside it, eleven propositions two readers had already refused were queued for published findings with no trace of the refusal, and three account splits counted a person twice. None of this was caught by the pipeline. It was caught by the first audit to go back over the register's own decisions.
What changed
The claim said Edmonton property taxes had risen sharply, by $1,500 in three years for one resident and $6,000 a year for another. The second resident had written: Glad I am paying $6,000 a year in property tax for this! That is what somebody pays, not what it went up by, and there is no sharply anywhere in it. One person's increase had been stitched to another person's bill and the compound put in both their mouths. On a site whose whole promise is fidelity to what people actually said, this is the worst defect available to us. It is now two claims, each carrying only what its own wording supports, and both quotes were read back against the capture by hand.
No tightening of the checks the quote gate makes would have caught it, and that is the part worth understanding. Both quotes are exact substrings of the comments they came from, which is the entire thing that gate was built to prove. It establishes that the words are in the capture under the commenter the site credits them to. Whether the sentence assembled on top of those words says what the words say is a separate question, and no step in the pipeline was asking it.
The rule that would have stopped it was already written. prompts/intake-merge.md opens its merging rules with: A claim is one assertion. If you are joining two assertions with and, they are two claims. This claim joined two people's remarks with exactly that word. Worse, that rule was written the same day, in the re-merge after an independent critique threw the first merge of this run away for grouping by topic instead of by proposition, having found a compound assertion put into the mouths of commenters who had made neither half of it. It was written in direct response to that failure, the same shape in a different claim, it went into a prompt file, and nothing was ever wired up to check it. The re-run under those rules shipped the tax claim anyway. A rule nobody checks is a wish.
Nothing in the pipeline found any of this. The first triage audit did, the day after v1.15 wrote down that nobody had yet shown a second triage read reaching the same decisions. A third reader went back over work that had already passed every check standing in front of it. Every guard here inspects a claim as it goes past and then stops looking at it. There was never anything behind them. The register these defects sit in reached the main branch at midday on 2026-09-03 and the repairs went in that night.
prior_triage is the schema change, and it is what earns a version. When v1.16 lifted triage from the claim up to the question, the decisions made at the old level went in the bin, and eleven propositions that both triage seats had independently returned NO on became live claims under questions that are going ahead. Three of them are the plainest kind: that cyclists pay property taxes, that Edmontonians pay for services they do not use, and that roads carry goods and emergency vehicles. Both readers turned all three down as things nobody disputes, which is the shape that took four published claims off the findings board earlier the same day, and all three were queued to be written up and given published findings. The field records the outcome, the seats that reached it, and the reason the run's combined triage file gave for it. On all eleven that reason copies one seat's wording word for word, and the field neither names that seat nor keeps the other seat's reason, which is a gap this version names and does not close. It moves no question's disposition and decides nothing. It means a brief author can see the refusal instead of rediscovering it.
Two validator rules hold the shape of that field. One requires an outcome from the same vocabulary, at least two named readers and a reason, and rejects any other key. A refusal with no reason attached tells a brief author the claim was turned down without telling them why, which is worse than keeping nothing. Neither rule checks that those values match the run's combined triage file, which is a check that could be written and has not been, so that comparison is still done by hand. The other refuses the field on a claim declined on the right-of-reply ground, where the decline is live rather than historical, because a claim carrying both would read as having been ruled on twice.
The register header told readers the validator tested the for/against/neither split against the question's total. It did not. It tested the total against the range its claims allow, which is a different check that passes things the promised one refuses. The described check now runs, and on its first pass it caught three splits in the published register overshooting their totals by one, on cycling-volumes, lanes-and-congestion and 83-avenue-lane. No page prints those splits, so no page was wrong; the file was. Each was one person who argued on two sides of a question and got counted on both. The claim-level count is deliberately everyone who argued a claim either way. The question-level split is people, once each, so the sides have to add up to the total. Which side somebody who argued on both ends up on is an editor's judgement the file does not record, and the header now says that as well as describing a check that exists.
Six question reasons go back for rewriting, from the same audit. Four ended by naming the two outcomes without saying which reader chose which: three said "The two readers split GO and PARK" and downtown-business said "The two readers split NO and PARK", which tells a reader there was a disagreement and leaves them unable to see who was on which side of it. GPT-5.6 Sol parked all four of them. Gemini 3.1 Pro sent three ahead and declined the fourth, downtown-business. So Sol is the cautious seat in the three go-against-park splits, and Gemini is the stricter seat in the one no-against-park split. None of that was visible from the register, so all four reasons now name both readers and what each of them wanted. The register header called a reason one public sentence; several of these need two or three, and the header now says that too. infill-luxury opened its decline with "No captured post makes this claim", which v1.15 says is a park and not a decline; the decline now leads on the ground that carries it. And hundred-million-approval told the reader who raised it that their question was dropped, without saying that the live half of it, how long the money covers and how it sits beside road spending, is already published.
What this version does not do is close the hole. There is still no check anywhere that a claim's proposition says what its quotes say, and building one is separate work already under way rather than something shipped here. So the honest account of this version is that it repairs the specific defects that day's audit found, and names the gap that let the worst of them through. That gap is open as this is published.
Full change note
The comfortable story would be that a check failed. No check failed. The check was never built. Somebody watched this failure happen during intake, on a different claim, wrote a rule against it the same day, put the rule in a prompt, and moved on, and an Edmontonian ended up on this site asserting a proposition about tax increases when what they had made was a remark about a bill. Between those two moments every check the pipeline runs ran, and passed. That is the shape of the fault, not an accident of one claim, and it is two holes rather than one. Going forwards, nothing compared the sentence with the quotes, and a check that did would have caught this before it shipped. Going backwards, there was nothing at all: the guards run one item at a time, in the direction the work is moving, and not one of them was ever asked to turn round and read what had already gone out. Nothing had gone back over these decisions until that day. The lesson is not to write better rules. It is that a rule which lives only in a prompt is a statement of intent, and the difference between intent and a guarantee is the whole of what this project claims to be selling.
v1.24
A claim parked out of a run
A run may now publish fewer claims than it asked. Where a reviewer's framing concern is right and no repair is available that does not make the claim weaker, the claim leaves the run: named in the run manifest with its reason, parked in public on the register, its answers left committed where they were written, and the rest of the run synthesised.
What changed
What happened. On cycling-volumes a blind seat raised a material framing concern against the claim that Edmonton's riders are recreational rather than commuters. The brief had fixed the 2015 regional household travel survey, whose fieldwork ran mid-September to mid-December on weekdays only, as the instrument for a claim about cycling with no season or day named. Both restrictions cut the same way, against the recreational side, and the same brief fixed July for another claim on the express ground that a claim is tested at its strongest for the side asserting it. The seat was right, and the inconsistency was the brief's.
Why the existing answer did not fit. Since methodology v1.2 a framing concern is answered by revising the brief and rerunning round 1. Neither available revision was honest here. Qualifying the proposition to autumn weekdays, in those words, makes it weaker than the claim people are actually making, and the standing rule is that a proposition may be made more precise and never weaker. Naming a better instrument means an Edmonton travel survey that records trip purpose across a representative period, which the brief's own source search had already looked for and not found.
What a run does instead. run.yaml carries a synthesis_scope: the claims this run synthesises, and the claims it parks with the reason each was parked. scripts/synthesize.ts reads it, produces findings for the claims in scope, and writes the parked ones into synthesis.json with their reasons and with every framing concern raised against them. A run that says nothing about scope behaves exactly as before.
The guards, because parking must not become a quiet way past a halt. Every claim round 1 asked appears in exactly one of the two lists, so a claim cannot fall out of a run by going unmentioned. A parked claim carries the reason a reader is shown; without one, a claim dropped because the record cannot answer it reads exactly like a claim dropped for the answer it gave. And a framing concern against a claim the run still publishes halts the run as it always did.
Nothing is deleted. The parked claim's round-1 answers, its blind re-run and the cross-review that sent it back all stay committed and readable. A claim the site tried and could not answer is part of the record of trying, and a reader following the run can see that a claim was dropped at the last stage and why.
In public. The claim is parked on the register on a new no-instrument ground, which is a different thing from a question parked at triage: this is what is left after the run has been spent. Its page keeps its wording and its provenance, says the claim went to the panel and came back unanswerable, and gives the reason and the condition on which it reopens.
Full change note
The risk is that parking becomes the exit from an answer somebody did not like. Two things bound it. The seats' answers stay committed beside the reason, so anyone can see what the run would have published: here all three had answered, and the finding it cost the run was Contradicted — a finding against the people making the claim, not for them. And the concern that parked it is copied into the deterministic artifact rather than dropped with the claim. What would show this was wrong is a run that parks the claim whose answer the editor found inconvenient, or a register where parked claims accumulate faster than answered ones.
v1.23
Prior verdict from the committed file
Synthesis read a seat's own account of its earlier verdict in preference to the file that recorded it, so a seat could write a cross-review movement that never happened and the artifact would carry it. The committed round is now the only authority on what a seat said before, and a self-report that contradicts it is written out beside the position rather than dropped.
What changed
What the bug allowed. scripts/synthesize.ts computed a reviewer's prior verdict as the from field of that reviewer's own round-2 verdict_changes entry, falling back to the committed round-1 file only when the seat had claimed nothing. A seat's self-report therefore outranked the record. Any seat could report having moved from a verdict it never held, and synthesis.json would publish changed_from as though the movement were a fact about the panel. Nothing checked the two against each other, so a wrong self-report could not be seen in the output at all.
What it did here. On cycling-volumes the Gemini seat's round 2 reported bike-lanes-look-empty moving from Not established to Contradicted, and gave the brief's revision as the reason. It was describing the halted round on the superseded brief, not the round it was answering: against its own committed round 1 on the re-frozen brief the seat had not moved, and round1/gemini.json says Contradicted. synthesis.json recorded the movement anyway.
The rule now. A seat's account of its own earlier position is not evidence about that position; the committed blind round is. Movement is read file against file. Where the seat's from disagrees with the file, the file decides the movement and the disagreement is recorded on the same position as disputed_self_report, carrying what the seat claimed, what the file says and the reason it gave. A seat misdescribing its own prior verdict is a fact about the seat and is worth seeing, so it is written down rather than silently discarded. changed_why is now emitted only where a movement the files show actually happened, so a reason can no longer stand alone attached to nothing.
How it was found, which is the part worth recording. Not by review and not by a test. A seat wrote an account of itself that was anachronistic — true of a round that had been superseded, false of the round it was in — and the synthesis believed it. The wrong entry was visible in synthesis.json for anyone reading it against round1/gemini.json, and it was caught by that comparison. The pipeline has a general rule here already, stated in the runner: models never attest their own identity or run parameters, because a claim by the thing being described is not evidence about it. This is the same rule, and synthesis was the one place still breaking it.
Pinned by tests/synthesize-self-report.test.ts. A seat claiming a from that contradicts its committed round 1 must record no movement; the contradicted claim must appear as disputed_self_report; a movement the files do show still records its stated reason; and a movement the files show but the seat never reported is still read off the files.
Full change note
The narrow version of this is a precedence bug in one expression. The wider version is that the artifact had no way to disagree with a reviewer about the reviewer's own history, and so could only repeat it. Preferring the self-report was not obviously wrong when it was written — a seat that says it moved usually did, and the seat's own wording is more informative than a diff of two verdict words. What it cost is that the one case where the two disagree is exactly the case worth reading, and the code resolved it in favour of the party with the least standing to be believed. What would show this correction was wrong is a run where a seat's self-report turns out to describe its committed round better than the file does, which would mean the wrong file was committed and is a different failure with a different fix.
v1.22
Claim level blind rerun
Cross-review has always been able to send one claim back for a fresh blind re-run. Until now there was nowhere for that re-run to land, so the rule existed and could not be used. It now has a directory, a manifest and a line in the synthesis saying which blind round each claim's finding came from.
What changed
What was missing. Since methodology v1.3, stage 4 has sent a claim back to three blind seats when cross-review catches something material in it: a citation that does not say what it was cited for, evidence that is wrong, a position taken without the source having been read. Patching the claim inside the run was never the answer. The synthesis script read one directory, round1/, and had no way to be told that one claim's answers had been superseded. The only ways to act on the rule were to overwrite the seats' committed answers or to hand-edit the finding, and both are the thing the rule was written to forbid.
Where a re-run lives. Its three seats write into round1-rerun-<n>/ with their own run.yaml beside them, recording their own package hashes. round1/ is never rewritten. It stays the seats' answers to the package its hash records, and for a re-run claim it is the superseded record, readable next to what replaced it. Nothing is deleted and nothing is edited, which is the same shape round1-superseded/ already uses for a brief that was revised under v1.2.
What the seats are asked. The frozen brief, byte for byte, so its freeze hash still verifies; the round-1 reviewer prompt; the schema; and one added instruction naming the claims to answer. The scoping lives in the package wrapper, never in the brief, because editing a frozen brief is a new brief and a new framing check. The seat is told what to answer and nothing about why, so the re-run is as blind as the round it replaces.
What synthesis does with it. For every claim a re-run answered, the three positions come from the re-run and the superseded ones are not in the multiset at all — averaging them in would be the quiet correction the rule forbids. Every other claim is untouched. Each claim in synthesis.json now names its own basis, round1 or the re-run directory, so a reader never has to work out which round produced which finding.
The guards, because this is the one place a locked verdict can be replaced. A re-run must carry all three seats; all three must have answered the same claims; every claim it answers must already exist in round 1; and no two re-runs may cover the same claim. Any of those failing throws rather than picking a winner. Round 2's recorded movement is still measured against round 1, which is the round it actually answered, not against a re-run that came later.
First use, and what it found. On cycling-volumes, claim 1 synthesised Partially supported on a Split panel because one seat returned Not established in round 1, having read the dataset's update date off a developer-portal page rather than querying the dataset; in round 2, with the other seats' work in front of it, it queried directly and moved to Supported. The suspicion was that the round-1 verdict recorded an omission rather than a judgement, which is a material catch, so the claim went back to three blind seats.
The re-run did not do what anyone expected, and that is the argument for having it. Blind, on the same frozen brief, the same seat reached the same developer-portal page, drew the same conclusion and returned Not established again. Two seats returned Supported on a direct query of 1,291,714 counts. The multiset is unchanged and so is the finding: Partially supported, Split. What was a suspicion about one run is now a reproducible position of that seat on this brief, which is a fact worth having and could not have been got by patching the verdict. A mechanism that can only confirm what the editor already believed would not be worth building.
Full change note
The obvious risk is that a re-run becomes a way to re-roll a verdict somebody did not like, and nothing in the mechanism prevents that on its own. Three things bound it. The trigger is stated in stage 4, and what it names are faults in the record rather than outcomes anyone disliked. The superseded answers stay committed and readable beside the ones that replaced them, so a re-run that produced a more convenient answer is visible as exactly that. And the re-run is blind on the same frozen brief, so the only thing that can move is what the seats find, not what the question asks. What would show this was wrong is a run where the re-run count climbs, or one where the superseded verdicts read as sounder than the ones that replaced them.
v1.21
Cross review output shape
The cross-review prompt asked for round 2's notes in words and left their shape to be read off the schema, and one seat lost six findings to the gap. The prompt now states the three fields and their exact shapes, the way the round-1 prompt already states every value it asks for.
What changed
What happened. On cycling-volumes the Gemini seat produced round-2 content four times and failed schema validation the same way every time: errors_in_other_reviews written as objects where the schema requires strings, and verdict_changes using from_verdict, to_verdict and reason where the schema requires from, to and why. Its round 1 validated on the first attempt. Six cross-review findings about the other seats' citations were written in a shape the pipeline cannot read, and were never put to the seats they concern.
Why this is a prompt defect and not only a seat failure. Round 1's prompt hands over every value the schema constrains, verbatim: the four verdicts, the three confidence levels, all six evidence-basis labels. Round 2's prompt named two fields and specified the shape of neither. Worse, its own prose supplied a different word for one key — record every change with THE REASON, where the schema says why — and asked, for each error, whose review, which claim, which citation and what is wrong with it, which is four attributes, in a field the schema types as one bare string. Both fields the seat got wrong are exactly the two places the prompt underspecified, and one of them it got wrong in the prompt's own noun.
The fix, and what was deliberately not fixed. prompts/cross-review.md now states that round2_notes has three fields and no others, that evidence_i_missed and errors_in_other_reviews are arrays of strings, that the four attributes item 3 asks for go into the one string, and that verdict_changes takes exactly claim, from, to and why. The schema is unchanged. Relaxing it to accept the objects the seat emitted would have made the contract follow the failure, and it would have broken every round 2 already committed under it.
The seat is not exonerated. The runner's one retry appends the exact validation errors to the package, so the seat was told which fields were wrong and returned them wrong again. An underspecified prompt explains the first attempt; it does not explain the fourth. Both facts are on the record, and the seat's reliability is tracked in the open question that already holds its earlier failure.
What the re-run settled. Handed the amended prompt and the same round-2 package, the seat validated on its first attempt. Five cross-review findings came back that nobody had read, four of them the ones lost in the invalid output and one new. That is as close to a controlled result as this pipeline offers: same seat, same CLI, same package, one prompt paragraph different, and the failure did not recur.
Full change note
Worth saying plainly which way the causation runs, because the comfortable version is that a seat misbehaved and the prompt was fine. The prompt was not fine. Round 2 is the only part of the schema round 1 never exercises, so it is the only part a seat meets cold, and it was the part the prompt described loosest. Two seats guessed right and one guessed wrong, and a contract that three careful readers resolve two ways is underspecified whatever the pass rate. The correction is the same one made to briefs on this site: state the shape, do not leave it to be inferred.
v1.20
Framing check defect not framing
A framing check that has run out of rounds can still leave arithmetic behind it. An error inside a verdict ladder is now a defect rather than a framing finding: the editor corrects it in the checker's own words and the brief gets one confirmation round. Everything about what a brief tests is still framing, and still capped at three.
What changed
The distinction, written narrowly so it cannot be stretched. A defect finding is one where the checker states the correction and the correction is verifiable without judgement. Three kinds qualify and nothing else does: verdict bands that overlap or leave a gap, a stated rule whose direction contradicts its own arithmetic, and a coverage or completeness rule that lets an unclassified remainder decide a verdict. Internal consistency and arithmetic. That is the whole list, and a defect finding that does not carry the checker's exact replacement wording is not one, because there would be nothing to verify.
Everything else is a framing finding and stays capped at three reports under v1.12: what the claim tests, whose reading of it, the value of a cutoff, whether a source is adequate, whether a verdict is reachable, whether the brief leaks an expectation. If a finding can be argued about, it is a framing finding, because the test for a defect is that there is nothing left to argue about.
What changes. A defect finding still standing after the third report no longer parks the brief. The editor corrects it using the wording the checker supplied, records each correction in the run record against the finding it answers, and the brief goes back for one defect confirmation. That fourth report may do two things: confirm the corrections, or name further defects. Nothing else.
How the loop ends, because a rule with no ending is not a rule. One defect confirmation is all a brief gets. If that report returns further defects and no framing finding, the editor corrects them in writing in the checker's supplied wording, records each against the finding it answers, and the brief freezes. There is no fifth report. This is not a new pattern: it is the one v1.12 already uses one level up, where the editor resolves the open findings in writing after the second framing report and the brief goes on. The check gets its rounds and then the editor is accountable in the record, rather than the loop running until somebody gives up.
The confirmation round has its own two verdict words, because the first one to run had none. The report on cycling-volumes came back headed `Verdict: REVISE`, which is the framing vocabulary, at the moment that word had stopped describing what happens next: a fourth report that accepts every correction and names one more arithmetic error now ends in the editor correcting it and freezing the brief, which is the opposite of what REVISE has always meant here. The checker had nothing else available to write. prompts/framing-check.md now heads that report `DEFECTS CONFIRMED` or `DEFECTS REMAIN`, and states that neither word parks anything, a framing finding being the only thing in a fourth report that can. The committed report keeps the word it was written with. It is the checker's own text and is not edited after the fact.
Why it ends in a freeze rather than a park. An unbounded defect round is a loophole, and a bounded one that ends in parking is a rule that can never release what it caught, which is the failure this whole entry exists to fix. Parking on arithmetic is always the wrong outcome, because a parked brief with a known ladder bug is unusable to everyone and no new intake evidence can ever release it. So the only real question was how the loop ends, and it ends with the editor's name on the correction and the checker's wording quoted beside it.
The guard, which is the point of the amendment. If the defect confirmation raises a framing finding, whether new or revived, the brief stays parked and no further round is available. Without that, a framing objection could be relabelled a defect to buy a fourth pass and the cap would be worth nothing. The checker, not the editor, labels each finding framing or defect in its own report, so the distinction is auditable in the committed record rather than asserted afterwards by the person it benefits. prompts/framing-check.md now carries the definition, the labelling requirement and the fourth round.
This does not loosen the v1.8 bound the cap descends from. Everything v1.8 settled about thresholds stands untouched, its ban on asking for an alternative to the alternative included. The value of a cutoff is a framing question, capped at three, and not renegotiable in a defect round. What a defect round may fix is whether the bands drawn around that value cover every number once, which is arithmetic and has one right answer.
Why now, and by whom. The rule was amended by the editor it had just blocked, on the brief it had just blocked. That is the least comfortable way for a rule to change and it is stated here for that reason. The site's first register-chosen question, cycling-volumes, went through three framing checks; the third settled the framing and called the contested editorial call defensible. What it left standing was three defects, all arithmetic inside verdict ladders, all introduced by the editor while adopting the checker's own findings, and all with the checker's replacement wording already written down.
The test that justifies it, stated so it can be applied without today's case in front of you. The failure would exist whatever brief hit it. A ladder that assigns two verdicts to the same total is worse if it passes than if it parks, so the cap is protecting nothing by holding it. And v1.12's escape clause, that a parked brief reopens only on new intake evidence, can never be satisfied by an arithmetic typo, because no evidence about the world bears on whether one number falls in two bands. A cap that can never release what it caught is a cap on the wrong thing.
Full change note
The obvious objection is that the editor changed the rule that had just stopped the editor's own brief, and it is the right objection to make. Three things are offered against it and nothing more. The definition names three failures and excludes judgement by construction, so a finding anyone could argue with is not one of them. The checker labels its own findings, so an objection cannot be reclassified after it has been read. And a framing finding in the fourth round parks the brief for good, so the extra round is worth nothing to anyone trying to use it as a second attempt at framing. What would show this was wrong is a defect round that turns into a framing argument, or briefs that start needing a fourth report as a matter of course; both are visible in the run records, and the founder can revert this the way he can revert anything else here. The clause about how the loop ends was written the same day, after first use: the confirmation on cycling-volumes accepted all three corrections, raised no framing finding, and named a fourth arithmetic defect that three framing rounds had walked past, and the rule as first written had nothing to say about that. That the first run of a new rule found a real hole in it, and a real bug in the brief, is the argument for the round existing at all.
v1.19
Claim dispositions
Two new dispositions on a published claim. A finding that stands under a question nobody was arguing about comes off the board with a dated note saying so, and an undisputed premise moves underneath the contested claim it supports. Four of the ten published claims left the board. Nothing was deleted, corrected or merged, and every page is still at its address.
What changed
The founder's complaint is why this version exists: the site had spent panel runs establishing things nobody was arguing about. So all ten published claims went back through the current four tests, as if each had arrived today. Three stand as they are, one stays on the board with its reopening condition recorded, two were already withdrawn under v1.13, and four come off the board here. Three of those four come off for one reason, said plainly: nobody was arguing about them.
board_withdrawn is a finding that stands under a question that was not worth asking. The claim keeps its page, its finding, its evidence and its history, and comes off the findings board, the home page's count, the findings feed and the search index. Its own page and its question's page carry a dated note. That note is written to be read as what it is. The finding was not wrong, nothing was corrected, and what changed is our own judgement about whether the question deserved a panel run. It is a more uncomfortable admission than a correction and the copy does not soften it.
Two of the three are the comparisons on the bike-lane money. at-100m-vs-snow sets four years of capital spending against one year of operating spending, so the ratio does not mean what it appears to mean. at-100m-vs-roads depends on a roads-only category the adopted budget does not itself publish. Both are queued for a re-run on a common, defined basis. Both notes also say the thing the founder said about them: these figures are the arithmetic under an argument the site has not checked, which is whether Edmonton is letting roads, alleys and basic services go while it funds bike lanes. That question is on the register and cleared to check. This version does not answer it and does not re-frame the question the two claims sit under, because re-framing is a fresh brief and a panel run, and doing half of one inside a presentation change would leave the site asserting a framing nobody reviewed.
The third is climate-on-track, and it is the plainest case on the list. The City's own carbon budget states that Edmonton is not on track, so no answer this panel could have reached would have surprised anybody. It was never a contested claim.
context_for is the second disposition and it is not a withdrawal. That Edmonton's Proterra buses substantially failed to deliver what the City contracted for is the undisputed basis of the City's own lawsuit, not something anyone disputes. So it comes off the board like the above, and on the question's page it renders underneath the $82 million claim as established background. This is not a wasted panel run. It is the premise that makes the $82 million question worth asking, and it belongs under that question rather than competing with it.
The two e-bus claims are not merged and will not be. Two assertions under one finding is the compound-claim failure two specialist board reads rejected in v1.16: a single finding over both would state neither, and everybody quoted beneath it would be tagged with a verdict on a claim they did not make. They stay two claims with two findings and only the presentation changes. scripts/validate.ts holds the narrow part of that, checking that a context_for target is a claim on the same question, that no claim carries both dispositions, and that no two claims name each other.
ebus-82m-loss stays on the board, unchanged. Both readers parked it because the bankruptcy has not concluded, and its published answer already says nobody can tell yet, which is the correct answer to give. Its reopening condition goes in the story's changelog, where the schema already has a place for one rather than needing a new field: it reopens when the Proterra estate reports what Edmonton actually recovers.
The two readers agreed on six of the ten, which is published here rather than smoothed over. They were not applying the same test. One asked mostly whether the record can answer the claim, which is test 2 on its own; the other asked the whole set, including whether the comparison is sound and whether anybody disputes it. The founder's own example was caught by one and missed by the other: on the snow comparison one reader named the capital-against-operating mix, and the other read the numbers as sitting in the budget and let it through.
The combining rule inverts for a retro-triage, and that is the editorial call in this version. At intake a claim survives on one GO, because discarding a real claim is the costlier error. On work that is already published the cost runs the other way, because keeping means leaving something live that a reader says should not have been checked, and re-running a claim that turns out to be fine costs one panel run. So on published work a park or a decline from either reader is enough to act. The lean changes direction once the thing being judged is in front of readers.
What this does not touch: no finding changed, no page moved, no evidence was removed, no run was repeated. Every claim that left the board is still reachable from /questions and from its own URL, with the dated note saying why.
Full change note
The uncomfortable part is not that a finding was wrong. None of them was. It is that four panel runs went to questions that did not need one, and three of those had answers nobody would have argued with. A correction is easier to publish than this, because a correction says the method worked and caught something. This says the method answered honestly and the site chose the wrong question, which is the one fault no amount of reviewer independence can catch, since every guard here runs after the question is chosen. That is also why the dispositions are not deletions. The claims stay published, at their addresses, with their evidence and their notes, because a site that quietly removes its weak work is asking to be trusted about what it removed.
v1.18
Plain speech answers
Every claim now carries its own one-sentence answer, in the words a person would use, and a reader from a different vendor has to pass it before it publishes. The thirty-word cap that produced the prose this replaces is gone, and nothing has been put in its place.
What changed
The founder's complaint was that the language on the site is not human, that nobody speaks the way it describes things. The cause turned out to be measurable rather than a matter of taste: five of the six published one-sentence answers were exactly thirty words long, against a thirty-word cap. The limit had become a target. Each answer crammed a whole finding set into one breath with colons and semicolons, because the writer was filling the space rather than answering the question, and the rule meant to keep answers short was producing the densest prose on the site.
So the cap goes and nothing replaces it. What does the work now is punctuation. An answer may not use a colon, a semicolon, an em dash or an en dash, because that punctuation is how a second idea gets into a sentence; hyphens inside ordinary compounds are English and stay. The general rule is written down with it: a limit every instance sits on is generating the failure it was meant to prevent, and if a new limit starts collecting instances at its ceiling it is wrong and it goes.
The answer moves onto the claim, which is the unit of judgement. One sentence used to sit on the story and answer every claim under it, which is exactly why it needed semicolons: three findings in one breath. A claim carries one finding, so it now carries one answer, and it opens with the stance a person would say rather than the finding word. The finding word stays where it was, as the badge beside the answer. The badge does the method's job, the answer does the human one, and both appear on every page that shows either.
The story keeps a standfirst where a question has several claims and may drop it where a question has exactly one, in which case that claim's answer is the sentence. Five of the six published standfirsts broke the punctuation rule and were rewritten. Nothing was deleted. Every fact they carried is still on the page, in the TL;DR or the body, and each story's changelog says so.
docs/DESIGN.md section 12 is the standard: what the question, the claim, the answer and the explanation each have to do, and what a script can check against what a reader has to. The schema checks shape only, which is the punctuation, the stance opener and the absence of a finding word. A method-vocabulary list in scripts/validate.ts prints warnings and never fails the build, because a word list that fails the build is the next rule that deletes true content.
The plain-speech read is a required stage with a named artifact, not a style guide. prompts/plain-speech-read.md goes to a model from a different vendor than the one that drafted, at stage 6 beside the faithfulness check, and asks four things: would a person say this out loud, does it make sense to somebody who has not seen the question, is every fact carried by the key facts, and has anything true been dropped rather than moved down. Its report is committed under the run directory at plain-speech/, in the shape the faithfulness reports use, and every published claim names that file in plain_speech_read. scripts/validate.ts checks the file is on disk, so a claim that cannot name its read does not publish.
The control that makes the read worth running is the clause accounting. Every substantive clause of the draft, and of the wording it replaces, has to be booked as kept, moved to the explanation, split into another claim, or dropped with a written reason. This project has already had a rule delete true content once, when a numbers-in-every-bullet rule gutted a story whose key facts were absences in a bylaw's text, and a standard about brevity is exactly the shape of rule that does it again.
The stage exists because of what happened the first time the read ran. The site's own editor drafted the ten answers under the standard it had just written, and the GPT seat rewrote nine of them. The drafts leaned on the question the reader could not see, said 'the buses' with nothing to attach it to, carried two supporting facts where the rule allows one, and in one case asserted a budget total the key facts did not carry. Nine of ten is the argument for the stage, and it is a poor argument for letting the drafting seat mark its own work.
One rewrite was rejected, in writing, under the reader's own section of the committed report. For at-100m-vs-roads the reader offered the budget's combined 'active pathways and roads' line as the roads figure; that line contains the bike lanes being compared against it, and the claim's own key facts say the adopted budget publishes no roads-only total. The reader's other objection to that answer was right and was applied. The editor may reject a rewrite on evidence and has to say so where a reader can find it. The editor may not publish an answer this read has not seen.
What this has not touched, stated plainly: ten answers and six standfirsts. No story prose has been rewritten under the standard yet. The explanation rules in section 12 are written and unenforced, and the pages under the answers still read the way they read before.
Full change note
Deleting a limit is the move that looks like loosening a rule, and the honest reading is that the limit was doing the damage. Thirty words was a number somebody picked; what it produced, on five answers out of six, was a sentence built to reach it. The replacement is stricter where it matters, because a colon is how a second idea gets in and there is now no way to write one, and it is the reader rather than the counter who decides whether a sentence is one a person would say. The part worth being uncomfortable about is that the editor wrote this standard and then failed it nine times out of ten on the first attempt. That is the case for the read being a stage with an artifact rather than a habit, and it is on the public record for the same reason the rest of the method is.
v1.17
Launch slate dropped
The nine-story slate, fixed in public before the first panel ran, is no longer part of the method and comes off the site. Reading whole sources does the job it was built for, and does it on every source rather than once.
What changed
What the slate was: nine stories and fourteen claims between them, named in the design document before any verdict existed, with the site not to be promoted until all nine had run. It defended against one accusation, that this site would test whatever flattered it, and its entire strength was that the naming came first.
That defence is now made continuously rather than once. Since v1.15 nobody selects: a source is read end to end and what it holds is written down whether convenient or not, and the register prints the fate of each item. The first source handled that way threw up 34 questions, sixteen of which had people on both sides of them. Nine titles chosen back in August do less work than a page showing everything the method has looked at.
The slate had also become impossible to satisfy. Under v1.15 a wording nobody has been shown saying cannot go to a panel, and the slate's wordings were composed, not spoken. Two of them already sit on the register as parked, each with the reason beside it, and they stay: they were considered and declined, which is true whatever becomes of the slate.
Removing a pre-registration is exactly the manoeuvre a pre-registration is meant to make impossible, which is why it is written down here instead of being quietly deleted. Anyone who saw the nine stories can find out what became of them.
No new bar takes its place. The slate also carried the rule for when the site could be promoted, and dropping it leaves that unset. When to promote is an open question in the board record; this entry does not answer it, and nothing on the site should be read as though it had.
Nothing about the panel, the verdict words or the publication gate moves. Published stories keep their findings and their pages, and no run is repeated over this.
Full change note
The founder's line, on being told for the third time that the launch bar needed restating, was that everything had changed since it was written. He was right. The bar was drafted for a site that chose its claims one at a time, and the site does not do that any more. The part worth being uncomfortable about is the shape of the move: a promise made in public, withdrawn by the people who made it, on their own argument that they have something better. That argument happens to be true, and it would sound the same if it were false. So the protection is not our word for it. It is a published list of every claim considered, which a reader can check against the sources it came from, and this entry, sitting in the version history where the promise used to be.
v1.16
Claims grouped into investigations
Propositions from a source are now grouped twice. Claims that one investigation would settle share a brief and a panel run; only claims that are the same assertion share a finding.
What changed
The founder read the register the previous version produced and found what was still wrong with it: several separate claims per argument, each of which would cost its own panel run. Four of them turned on who pays for Edmonton's roads. Checked one at a time that is four briefs, four panels and four near-identical findings, and it had already produced an incoherent result, three of the four cleared for checking and the fourth declined as undisputed inside a thread that is an argument about exactly that.
prompts/intake-group.md groups at two levels because they do different work. An investigation is one question, one brief, one body of evidence, one panel run, and propositions belong in the same one when a reviewer reading the same documents would settle both. A claim gets one finding, so it is one assertion: the same wording again, or a flat denial, is a variation of a claim, while a different predicate, scope, period or quantifier is a different claim in the same investigation.
Opposite claims share an investigation and never share a finding. Whether concrete barriers delay emergency vehicles and whether responders ride down the lanes to pass traffic are one question and two claims. A single finding over the pair would state nothing, and it would label everybody quoted under it with a verdict about the other side's argument.
scripts/intake-groups.ts refuses a grouping that would do that. Every proposition is placed exactly once, a claim whose variations argue different ways fails, and a claim's wording has to be copied verbatim from one of its propositions rather than composed, so a reader comparing a claim with the quotes under it finds the same sentence. Whether a two-sided question is framed so it can be answered either way is a judgement, so the script prints those questions for a person to read instead of guessing at them.
Triage now rules on investigations. On the first source that is 34 decisions rather than 112, and the two readers agreed on 30 of 34 where the same two readers had agreed on 78 of 112 ruling claim by claim.
An accusation against a named person is declined even when the question around it goes ahead. Grouping keyed that decision off the investigation at first, and the readers quite reasonably cleared the question of what city hall pays and what councillors have filed, so the accusation sitting inside it was published in full. The decline belongs to the claim: it carries its own refusal, and the register file may not hold the wording either, since a slug is as public as a sentence.
The register grows a level to match. An investigation carries the question, the outcome and the reason; a claim says which investigation it is checked under and carries no outcome of its own. /considered lists investigations, ordered by how many people discussed each, so a question dozens of people are arguing about sits above one raised by a single commenter and cost is spent in that order. Cost still decides when a question is checked, never whether.
Counts say a question or a claim was discussed by so many people, never that it was agreed with: somebody counted under a claim may have been arguing against it. One pseudonym is one person within one source, so the count is exact there; nothing sums a person across sources.
Two specialist board reads rejected the first version of this, in which the group itself carried one finding, and both were right. What one of them called the hostile reading is the sentence to keep: that this site would harvest real quotes to build a consolidated strawman, knock it down with a single verdict, and make everyone quoted look like they were lying.
Full change note
The previous version stopped the editor choosing which claims to check. It did not stop the same argument arriving as five claims, and five checks of one argument is both a waste and a worse answer than one check would be. So the grouping is the fix, and the care in it is all about where a finding attaches. Group for work and you save panel runs. Group for verdict and you produce a finding that answers none of the claims under it while labelling the people quoted beneath it. Those are different operations on the same list, and the method now does them separately: the investigation is the unit of work, the claim is the unit of judgement, and a question both camps are asking is one investigation with claims pointing in both directions.
v1.15
Whole source intake
The unit of intake is now a whole source rather than a claim someone picked out of it. Three cheap models list every factual claim the source contains, one strong model merges the three lists, and a script proves that nothing they raised was lost on the way to that list.
What changed
Anyone may submit a source: a social post with all of its comments, an article, a discussion. Every materially factual claim in it is extracted and dispositioned. Nothing is passed over for looking uninteresting, because nobody is choosing.
prompts/intake-extract.md: three cheap seats, one per panel vendor, each read the whole source alone and list every claim they find, with the words that carry it copied exactly and the comment those words sit in. prompts/intake-merge.md: one strong seat then folds the three lists into propositions, carrying every captured wording forward as a form. The models, their reasoning settings and the exact commands are recorded in each run's manifest.
scripts/intake-coverage.ts checks the arithmetic rather than trusting it. Every claim raised by every seat has to turn up in the merged list, either under a proposition or on a dropped list with one of three permitted reasons: not a claim, a duplicate of the seat's own quote, or not about Edmonton civic government. A seat that logs two assertions as one claim has it split across two propositions, which the check reports rather than treats as a fault. What this proves is narrow and worth stating narrowly: nothing the seats raised was lost between them and the list. It does not show the seats found everything in the source, and no script can show that.
Quotes are checked by script before the merge sees them. A form whose words are not one unbroken run of the comment it cites, or that cites a comment index the capture does not have, is thrown out and the discard recorded. Seven forms across two seats went out that way on the first source read this way. A wrong quote is a false attribution to a real person, which is worse than a missed claim.
No invented claims. A wording the editor or the founder thought of is still registered, but it does not run: it sits at PARK until a captured form of it turns up in a real source. Only wording somebody actually said reaches a panel.
This touches the pre-registered launch slate (docs/DESIGN.md section 7). The slate's topics stand and none of them is dropped. But a slate claim's registered wording is not itself a captured form, so the bar for launch has to be restated after a retro-triage of the claims already published. That restatement is open, and this entry does not settle it.
prompts/intake-triage-batch.md goes to two readers rather than one, both from a different vendor than the editor, neither shown the other's answer. Each rules on every proposition in the source, GO, PARK or NO, with a reason written for whoever suggested the claim. They combine so that going ahead takes both readers, or one GO and one PARK; a decline takes two NOs; everything else parks, a GO set against a NO included. A claim wrongly discarded is gone from the record and nobody can see what was lost; a claim held too long is only late. The verdict matrix leans the same way on findings, and this applies that lean to selection. Where the readers split, the published reason says so.
A source can carry a claim that accuses a named person of wrongdoing, dishonesty or an improper motive. It is extracted like every other claim, so it is counted rather than hidden, then flagged and declined in triage with a standing public reason: an accusation can only be published fairly once the person accused has been asked and their answer printed, and v1 has no such process. The register keeps the row, its outcome and its reason, and publishes neither the accusation nor the name. The identifier is neutral too, because a slug in a URL is published as surely as a paragraph; the wording and the comments go to a private record so the decision stays auditable. What an office-holder did in office is not in this class and is not withheld: a motion brought, a vote cast, a lane installed are matters council minutes settle, and this site names office-holders when it reports them.
Commenters in a capture are given a stable label of the form adjective, Edmonton animal, first initial, such as Snowy Hare F. The label is chosen from a hash of the name, so re-exporting the same source produces the same label every time. Magpie is excluded, being Stew's bird. Public office-holders keep their names. The mapping from label back to name is held privately and is never published.
The Claude panel seat moves from Fable 5.1 to Opus 5. The reason is money: the founder's Fable allowance on his subscription is nearly used up. It is not a finding that one model reviews better than the other, and nothing here measures that. The pins recorded in v1.5 (the seat) and v1.6 (reasoning effort) stand as written. Runs already published under Fable 5.1 keep the model their manifests record and are not re-run over this.
Prompted by the founder's read of the published stories, 2026-09-02: the site was checking arithmetic inside a councillor's quotation, a capital-against-operating budget comparison, and whether the City is on track for its climate targets, while the arguments people were actually having went unchecked. Every check added since v1.10 asked whether a claim could be tested fairly. None asked whether it was the thing being argued about.
Not proven: the extraction has been run on exactly one source, a thread of 621 comments, and nobody has yet shown that a second triage read of the same proposition list reaches the same dispositions. Reproducibility of the disposition is an open question in the board record, not a settled property of the method.
Full change note
Choosing claims by hand was the fault. An editor reading a thread picks what looks checkable, and what looks checkable is rarely what people are arguing about. Every guard added to this method since v1.10 has been about testing honestly: the claim at its strongest, in the units a reader would actually use, against a threshold set in advance. All of those questions presume the claim was worth the panel's time in the first place, and none of them can catch a claim that should never have been chosen. So the method stops choosing. The whole source comes in, every factual claim in it comes out, a script proves the count survived the merge, and triage disposes of the lot together. What that buys is an answer to "why this claim and not that one": there is none, because there was no selection. What it costs is volume, and a triage step that now rules on many propositions at once instead of one. One source has been through the pipeline. The disposition step is the part nobody has run twice on the same input, so the honest claim for this version is narrow: selection bias is out of intake, not out of the method.
v1.14
Panel seat tooling
The Gemini seat's pinned command now approves its own tool calls inside its sandbox, because in headless mode it returned nothing whenever a brief named PDF sources.
What changed
scripts/panel/run-reviewer.sh: the Gemini seat runs `agy --effort high --sandbox --dangerously-skip-permissions --print-timeout 45m -p`. Headless agy auto-denies any tool that needs a permission prompt; the seat reaches for a shell (curl, wget, python3) whenever a brief names PDF sources its URL tool cannot read, and then returns nothing.
On the active-transportation brief the seat failed four times under the previous command and twice more with the brief's documents pre-fetched as text files and a note that it had no shell. Its earlier failure on the low-density-history rerun (six attempts) was the same fault.
The other two seats already run with a shell (the Claude seat's Bash tool, the Codex seat's read-only sandbox), so this levels the seats rather than loosening one. Blindness still comes from the scratch directory, which holds only the package, and repo paths are never passed to a seat.
Founder decision, recorded in the board record; the pre-fetched packet remains the better long-term fix and stays open.
scripts/panel/extract-review.ts: a `$schema` key echoed at the root of a reviewer's answer is dropped before validation. The Gemini seat's first complete review under the new command failed only on that key; it was extracted by hand with the key removed and recorded in the run manifest and the run's errata.
Full change note
A seat that cannot read the documents a brief names is not an independent reviewer of them. Six empty returns on one brief, four under the pinned command and two with the documents supplied as text, showed the fault was the headless permission model, not the package. The change is to the seat's own command, is recorded in every run manifest from here on, and does not touch the package the three seats receive.
v1.13
Findings board
A checked story whose claims are all Not established, and all parked or declined on a triage read, stops being a finding; it moves to the claims considered and its page stays.
What changed
A story leaves the findings board, the story list, search results and topic counts when every claim on it is Not established and a triage read of those claims (prompts/intake-triage.md) returns PARK or NO for each. Its page stays at its URL with a note at the top, so nothing disappears quietly and corrections still apply.
The story is listed on /considered under Checked, not answered, with a one-sentence reason and the condition on which it reopens. The register entry and the triage read are public.
First application: Infill teardown prices. Both published claims are Not established; the read parked both, one because the price-gap ratio needs a decade-scale lot-by-lot linkage the run did not build, the other because no public record says what the housing that replaced particular demolished homes costs.
Every candidate with an intake record and a triage read gets a page of its own under /considered, rendered from the same files that are kept on GitHub.
Prompted by the founder, who asked whether it is good to publish stories that are meaningless. A Not established verdict is a finding when the question is one people ask and the record could have answered it; when neither holds, a verdict tells the reader nothing and the board should not carry it.
Full change note
Not established was doing two jobs: an answer (the record was checked and does not support the claim) and a shrug (nobody could check). Only the first belongs on a board of findings. The second belongs with the claims considered, where the reader can see why.
v1.12
Intake triage
A one-page triage decides whether a claim is worth checking before any brief is written; the framing check is capped at three reports.
What changed
prompts/intake-triage.md: a model other than the editor answers five questions from the intake record, who asks this in their words, how it circulates and what we captured, whether the public record can answer it at the level people ask, which verdicts are possible and whom each would surprise, and what it costs. It ends GO, PARK or NO with a one-sentence reason that can be shown to whoever suggested the claim.
GO requires a real question, a record that can answer it at a level people care about, and at least two verdicts that would surprise someone. The editor may overrule a NO in writing.
The framing check is capped at three reports: after the second the editor resolves open findings in writing, the third confirms, and a brief still at REVISE after the third is parked and reopens only on new intake evidence.
A public candidate register, intake/register.yaml, lists every claim the site has considered, sent to triage or not, with where its wording came from (captured, supplied, or the editor's own hypothesis) and the outcome. Cost decides when a claim is scheduled, never whether it is worth checking; who is affected and whether a decision turns on it decide that.
An Evidence and Methodology specialist read (GPT) said REVISE before first use and named what is still missing: a harm and neglect test with teeth, an audit of a sample of NO and PARK decisions, intake events in the quality ledger, and a preregistered blind re-triage pilot. The register, the origin labels, the cost rule and the cap resolution are adopted here; the rest is recorded as an open question in the board record.
Prompted by the founder: the first delegated story spent four briefs, twelve framing checks and four panel rounds on claims nobody asks; two of them are now being re-framed. The first case through triage is the re-brief of that story.
Full change note
Every check in this method asks whether a claim is fair, precise or computable. None asked whether it was worth the work, so the loop optimised claims into shapes the record could answer and nobody had asked. Triage puts the reader's question first and the cost beside it, and the cap on framing rounds stops the loop from running past the point where the claim is still the claim.
v1.11
Framing check who asks this
A brief must name the question a resident or reporter would actually ask, and the proposition must answer it, not a measurable cousin of it.
What changed
Check 9 in prompts/framing-check.md: the brief states the question people actually ask; a proposition stated in the units the record happens to publish, when nobody would ask it in those units, fails even if every other check passes.
Where the record cannot answer at the level people ask, the brief says so and tests the nearest level the record does answer, in words a reader would use.
Prompted by the founder's read of the published infill story: its two claims were shaped by what the record could compute (a lot-matched value ratio; a purchase model on separately titled dwellings) and answered questions nobody asks. The story is being re-briefed around the questions people do ask: were the demolished houses more affordable than what replaced them, is new infill luxury housing, and can a median-income household afford infill.
Full change note
v1.10 stopped a claim from being neutralised into a truism. This entry closes the neighbouring gap: a claim can be fair, checkable and precise and still be a question nobody asked, because the framing loop optimises toward what the record can compute. The check now starts from the reader's question and works back to the record, instead of the other way round.
v1.10
Framing check truism test
The framing check must reject a proposition that no informed person disputes. The first published delegated claim was one.
What changed
The price-gap claim in Infill teardown prices asked whether housing built on a teardown lot is worth more than the house demolished for it. Nobody disputes that; the circulating claim is about a modest house replaced by housing priced near a million. Four framing-check reports and an escalation neutralised the magnitude out of the brief in the name of fairness to the claim's holder, and the editor adopted each step.
Check 3 of prompts/framing-check.md now says a truism is as much a framing defect as a weak-man, and that a claim about magnitude or consequence must carry it with a predeclared threshold and one alternative.
A new check 8, stakes: the brief must say what each verdict would mean to a holder and to an opponent; if no verdict would surprise either side, or one verdict is impossible on any evidence, the brief is sent back. Two overriding rules: a claim is tested as its holders assert it, so an example offered for a general pattern is tested as the pattern; and a proposition may be made more precise than the claim as made, never weaker.
The claim is re-briefed as the magnitude proposition and re-run; the published finding stands, with a dated editorial note, until the re-run replaces it. Logged in the quality ledger against the check and the editor.
Full change note
v1.9 fixed the check for asking the record for things it cannot supply. This entry fixes the opposite: the check pushed a claim into a form the record could answer only by draining it of the thing people argue about. The founder saw it on the published page and said so. Fairness to a claim's holder means testing the claim they make, at its strongest, with the magnitude they assert; a threshold is a judgement, so the brief states one and one alternative, and the reader sees both.
v1.9
Framing check checkability and first use
First use of delegated briefs: both panels halted on framing concerns the check had passed. The check now sees the output schema, must name a published source for every threshold, and must verify that every instrument a brief relies on exists.
What changed
Both first briefs passed the framing check, then the research panel halted synthesis on a MATERIAL FRAMING CONCERN. Infill: the brief relied on a mature-neighbourhood instrument in force on the freeze date, and none exists since the overlay was retired on 2024-01-01. Low-density history: a density rule the check itself had demanded could not be computed from the 1926 record, and the brief demanded variant verdicts the schema cannot carry.
The framing checker now receives prompts/review-schema.json and may not ask for outputs it cannot carry; must name the published source a reviewer would compute any threshold from, or drop it; and must verify that every instrument, boundary, dataset or definition exists as described on the as-of date.
The reviewer prompt says to write MATERIAL FRAMING CONCERN only to raise one; the synthesis script ignores a negated mention, since a seat wrote 'no MATERIAL FRAMING CONCERN' and a plain text match would have halted on it.
The panel quality ledger gains a framing stage and a framing-miss event; six events from the two first runs are recorded, four valid catches by seats and two misses by the check.
Both stories are being rerun under revised briefs: infill with the dwelling unit as the verdict unit and a frozen historical overlay boundary, low-density history with classification by each era's own terminology and documented housing form, counts from published neighbourhood records. Evidence from the halted runs stays in the registry.
Date erratum: the first run directories and the v1.7 and v1.8 entries were dated 2026-09-02; the actual date was 2026-09-01. Entry dates are corrected; committed directory names are kept and each run's errata records it. The runner's pinned Gemini command could not run as written and is corrected.
Full change note
The framing check was designed to keep a brief fair; on first use it kept the brief fair and made it unresearchable, because the checker optimised definitions without knowing what the output schema carries or what the historical record can supply. The panel caught both cases in round one, which is the method working as designed, and the cost was two halted runs. Three changes follow: the checker sees the schema, the checker must name the published source behind every threshold it asks for, and the checker must confirm that the instruments a brief relies on exist. The halted runs, their concerns, the revised briefs and every check report are committed beside each other so a reader can see the loop.
v1.8
Framing check escalation and bound
Framing-check disputes now resolve with Stew as editor, on the record; the check no longer asks for alternatives to alternatives.
What changed
A finding still open after two revisions is decided in writing by Stew, the editor responsible for content, with the checker's standing objection kept in the committed record. The founder is not asked to arbitrate; he stays accountable and can revert.
A cutoff justified from an identified standard, or stated with one reasonable alternative and results under both, is sufficient. The checker may not ask for an alternative to the alternative.
First use: both infill briefs reached check 3 still at REVISE; the open findings and the editor's resolution of each are committed beside the briefs.
Full change note
v1.7 sent unresolved framing disputes to the founder. On first use both briefs reached that point, and the founder declined the role: editorial content is the steward's responsibility, he supplies ideas. So the escalation now ends with Stew deciding in writing, and the record shows what the checker still objected to. The founder's accountability is unchanged in kind: a standing power to revert, not a per-item approval. The second change closes a regress the first use exposed: a predeclared threshold was asked for an alternative, and the alternative would then have needed one. One identified standard, or one alternative with results under both, is now enough.
v1.7
Delegated briefs and framing check
Stew, the AI steward, now writes review briefs; a second model from a different vendor checks the framing before a brief is frozen. Applied retroactively, the check would have sent all four published briefs back for revision.
What changed
Briefs are drafted by Stew from an intake record that states where each circulating form came from, or that it was not captured. No founder approval is needed per story; the founder's accountability is unchanged.
Before a brief is frozen, a model from a different vendor runs prompts/framing-check.md; it looks for propositions that test a weaker or wider claim than the post made, verdict-sensitive definitions with no stated alternative, and sentences that tell reviewers where to land. The brief is frozen only on FRAME OK; after two unresolved revisions the disagreement goes to Ildar Abdulin in writing.
Every check report, the author's response and any resolution are committed beside the brief. A framing defect found later by the panel, the gate or a correction is logged against the check in the quality ledger.
Run retroactively on the four published briefs, the check returned REVISE on all four, mainly for site-written paraphrases presented as circulating forms, sentences naming which evidence 'would contradict' the claim, and folded or undefined propositions. The reports are committed beside each brief; the findings stand as published and each story will be re-framed and re-run under this version.
Two specialist board reviews (Evidence and Methodology on GPT, Public Trust on Gemini) reviewed the design before first use; both said revise. Their controls that were adopted are the intake record, the alternative-operationalization requirement, the mandatory re-check, the human circuit-breaker and the ledger entry. Not adopted yet: a public waiting period between freeze and panel, and a blind human-methodologist pilot.
Full change note
Every brief so far was drafted by an AI session and ratified by the founder at the publication gate, which D-0007 then delegated to AI audits. This entry says so plainly and closes the loop: Stew writes the brief, and the safeguard that delegation needs is a framing check by a model from a different vendor, run before the freeze, whose report is public. The check's questions are the ones a fair-minded holder of the claim and a fair-minded opponent would both ask: is this the claim I made, is it the strongest fair reading, would I have accepted these definitions before seeing the result, and does the brief tell the reviewers what to find. Run on the four published briefs, the check said all four would need revision. None of that changes a published finding, because the panel and the gate decided on evidence, but it does mean the frames the panel was given were weaker than this version requires. The reports are committed beside the briefs, and the four stories are scheduled to be re-framed and re-run under v1.7 rather than patched. The two specialist reviews are archived in the board's private record; their two unadopted asks are recorded there as open questions, with the founder's decision pending.
v1.6
Reviewer effort pinning
Pinned the reasoning-effort setting for every panel seat and started recording it in run manifests.
What changed
The Claude command now carries --effort high; the GPT and Gemini commands already pinned it.
Every seat runs at its vendor's "high" setting, the highest level the three CLIs share.
Claude and Codex offer settings above high. They are not used: the founder finds the extra cost and run time unmatched by better results, and nothing here benchmarks that.
The runner writes the effort into each review file and the run manifest, and the site displays it from the manifest.
Runs before v1.6 show "not recorded" for effort; the Claude seat's effort came from an unpublished local default and is not backfilled.
The run manifest now also records each seat's display name, so the site no longer reconstructs it from the provider field.
Tooling correction: the manifest stamper read the wrong end of the changelog and wrote methodology_version 1.0 on runs made under later versions. Fixed and tested; earlier manifests are left as written.
Full change note
Models are released often — Fable 5.1 shipped the day of this entry — and the reasoning-effort setting changes what a model returns as much as the model version does. Leaving it unpinned made the published command incomplete for one seat: prior Claude runs inherited an unpublished local default rather than a setting on the record. Effort is now pinned in the command, stamped onto each review file by the runner, and recorded per run in run.yaml. Every seat is pinned to "high" for two reasons: it is the highest level all three CLIs share (the Gemini CLI stops there), and while Claude and Codex offer settings above it, the founder does not use them for the panel — in his experience they cost significantly more and run longer without a matching gain. That is a judgement call, not a measurement; no benchmark of the trade-off exists here. Two smaller corrections ride along: the manifest now names each seat directly, and the script that stamps the methodology version onto manifests was reading the oldest changelog entry instead of the newest, so runs made under v1.1 through v1.5 are labelled "1.0" in their manifests. The stamper is fixed; the earlier labels stay as written, because a manifest is a record of what ran, including its mistakes.
v1.5
Reviewer model refresh
Updated the Claude panel seat from Fable 5 to Fable 5.1 for new review runs.
What changed
New review runs use Claude Fable 5.1 with the pinned model ID claude-fable-5-1.
Historical review artifacts retain the model identity recorded when they ran.
Full change note
The Claude panel seat moved from Fable 5 to Fable 5.1. The pinned reviewer command now uses claude-fable-5-1. Historical review artifacts remain unchanged.
v1.4
Verdict semantics and freshness
Tightened the rule for "Partially supported" findings and added a freshness check before publication.
What changed
A Partially supported finding must name the part of the normalized proposition that fails. Evidence-quality doubts affect confidence, not the finding.
The e-bus procurement claim was re-run against archived evidence under the tightened rule.
Freshness and completeness are now a third publication-gate audit, including a retroactive pass on the four published stories.
Full change note
Two changes from the external review's P0 findings. (1) "Partially supported" now structurally requires naming which part of the normalized proposition fails; evidence-quality doubts (untested allegations, litigation figures) affect confidence, never the finding. The one published claim decided under the looser reading (e-bus procurement failure) is re-run against its archived evidence under the tightened rule; any change ships as a logged verdict-change. (2) The publication gate gains a third audit: freshness & completeness (prompts/freshness-audit.md) — an independent re-search for newer or stronger sources and material events between evidence gathering and publication, run before every publication and retroactively on the four published stories.
v1.3
Synthesis basis and vocabulary
Moved synthesis to independent round-one verdicts, replaced canonical confidence with panel agreement, and opened a quality record.
What changed
The synthesis matrix now uses locked round-one verdicts; round two remains an error-documentation channel.
Panel agreement (Unanimous, Adjacent, Split) replaces canonical confidence; per-reviewer confidence remains in AI review.
The cautious synthesis rule and its reason are now published, and the panel quality record is open.
Full change note
Four decisions from the 2026-09-01 methodology panel, resolved with written second and third opinions (dispositions in methodology/reviews/2026-09-01-panel/DISPOSITIONS.md). (1) Synthesis now consumes the locked ROUND-1 verdicts. Round 1 is the only round in which the three reviewers are independent; synthesising from round 2, where each has read the other two, treated a deliberative round as the vote. Round 2 keeps its job as an error-documentation channel: every final position is carried into synthesis.json as round2_positions and rendered, and a material catch there (fabricated citation, wrong evidence) triggers a fresh blind re-run of the affected claim rather than a correction inside the run. Verified before adoption and re-verified on switching: the round-1 and round-2 multisets give identical canonical findings on all six published claims, so no published verdict changed. (2) The canonical per-claim "confidence" is replaced by PANEL AGREEMENT — Unanimous, Adjacent or Split, computed from the round-1 multiset. Confidence named something the method never computed and read as a probability that the claim was true; agreement describes the panel and is published with a gloss saying so. Per-reviewer confidence stays visible in the AI review, and the matrix no longer emits a canonical confidence at all. The review.agreement value "Majority" becomes "Adjacent" so there is one vocabulary. (3) The matrix keeps its cautious lean and now publishes the reason: a qualification found by one reviewer does not disappear because two missed it, and for a fact-checking site overclaiming is the costlier error. The veto objection is answered by disclosure — the vote composition is always displayed — not by averaging. (4) A panel quality record opens at methodology/quality-ledger.yaml: adjudicated per-seat events (fabricated citations, false accusations, unsupported figures, self-corrections, catches that held up), each traceable to a committed artifact, seeded retroactively from the four published runs with the per-seat denominator stated. It is an error record, not a calibration; a summary publishes when the nine-story slate completes. Reviewer prompts, the merge, and the 20 matrix rows' findings are unchanged.
v1.2
Artifact hygiene and honesty
Made evidence and review artifacts more explicit, and aligned the public site with the delegated publication gate.
What changed
Evidence items now show fetch status and registry ID, so unverifiable citations are visible.
Panel identity comes from the run manifest; known artifact errors get adjacent errata files.
Reviewers now flag framing problems, and story pages link to the brief and gate reports.
Composite paraphrases are labelled as paraphrases.
Full change note
Changes from the first methodology/trust panel review (three models reviewing the process, not the stories; full reports in methodology/reviews/2026-09-01-panel/). (1) Evidence items in combined-evidence artifacts now carry an explicit fetch status and registry id — unverifiable citations are flagged, never silent. (2) Panel identity is rendered from the run manifest, never from a model's self-report. (3) Raw artifacts known to contain errors get an errata.md beside them; the record is annotated, never edited. (4) Reviewer prompt now instructs reviewers to flag material framing problems in the brief; a material framing flag halts synthesis until the brief is revised and round 1 rerun. (5) Site copy reconciled with the v1.1 delegated gate everywhere; gate audit reports and the frozen brief are linked from each story's AI-review section. (6) "Claims we're seeing" drops social-platform styling; composite paraphrases are visually labeled as paraphrases. Research, merge, cross-review, and synthesis rules are unchanged.
v1.1
Publication gate
Delegated the final publication audit to a separate AI audit pair while keeping founder accountability.
What changed
A source-verification audit checks every published statement against archived source bytes.
A privacy and copyright release check covers raw review artifacts.
Both reports are committed with the run; the founder remains accountable for everything published.
Full change note
Publication gate delegated: the founder's per-story manual review is replaced by a dedicated AI audit pair — source verification of every published statement against archived source bytes, and a privacy/copyright release check of raw review artifacts — with both reports committed alongside the run. The founder holds a standing delegation, remains accountable for everything published, and can revert any publication. Research, merge, cross-review, and synthesis stages are unchanged.
v1.0
Initial
Established the first public methodology: three independent reviewers, deterministic synthesis, and a human publication gate.
What changed
Three reviewers work independently in blind round one.
A deterministic merge and multiset synthesis matrix produce canonical findings.
A cross-review round documents errors, drafting gets a two-model faithfulness check, and a human publication gate closes the process.
Full change note
Initial methodology: three-reviewer panel (Claude Fable 5, GPT-5.6 Sol, Gemini 3.1 Pro via CLI), blind round 1, deterministic merge, cross-review round 2, deterministic multiset synthesis matrix, drafting with two-model faithfulness check, human publication gate. Reviewer verdicts: Supported / Partially supported / Not established / Contradicted. Canonical findings add Mixed (split panel only).