{"path":"research/catching-a-proposal-made-unnecessary.md","content":"# Catching a proposal that a later ruling made unnecessary\n\n*2026-10-26. The outside reader (`scripts/outside_check.py`) checks each new ledger row against everything\nsettled. It missed the one kind of finding that mattered most on AF1 (a generalization at the scope its\ninference needs): three later rulings had removed the reason for AF1's restriction, and nothing said so.\nThree changes to the reader on 25 and 26 October did not make it say so either\n(`outside-checks/README.md` § A sixth answer). His question that started this note, verbatim:*\n\n> \"Is there no way to more generally aid in its understanding of this type of thing?! Research this\n> extensively online. Ultrathink\"\n\n## 1. What is decided and what is open\n\n- **Ruled:** BD18 (weighed now and when mature): a cost that ends when a pass is built or settled is a cost\n  of now, never counted against the design. AF1's revision (ruled 2026-10-25) is the case that started it.\n- **Built on his word, 25–26 October:** the answer *made unnecessary by*; BD18 quoted into the reader's\n  instructions; a required *view* field (today, as designed, both) on each finding; a required statement\n  of what a proposal's rule needs the graph to hold, and whether today's graph holds it.\n- **Open, and the subject here:** how, in general, a reader comes to see that a proposal's purpose is\n  already met by a settled item, or that its reason is a condition of today that the design removes.\n\n## 2. What the corpus already holds\n\n| Angle | Where it is | What it says for this question |\n|---|---|---|\n| The reader's design and record | `outside-checks/README.md` | Of 280 findings on 110 open rows (24 October), 133 *extends*, 111 *depends on*, 30 *repeats*, 6 *narrows*, 0 *reverses*: the reader reports textual kinship far more than any change to what is settled. |\n| Contradiction detection across documents | `corpus-graph/reading-for-insight/finding-inconsistencies-as-a-helper-read-it.md` (11 October) | Its recommendation 3 already names *a claim superseded by a later decision* as a class; recommendation 6 gives every candidate both dates; recommendation 9 says the best model recovers about 60% of planted errors, so run two passes in different orders, merge by union, and **use the ledger to measure the miss rate per class**. Graphiti compares a new fact only with related old ones (finding 10). Not built. |\n| A question asked two ways flips | ledger AD14, open | On thirty links one model refused 4 under one question and 20 under another; a reader can agree with itself and still be answering the wording. |\n| Trigger from a graph condition, not a door | `machine-work-as-a-standing-property.md` § 7, R8 ruled | Work that is owed is read from the state of the record, and a changed version makes earlier readings outdated. The outside check runs only when a row is new (the door), never when a ruling lands. |\n| Now and mature | BD18, BD19 ruled | The rule is in the reader's instructions since 25 October. |\n| Rows absorbed or superseded by others | the ledger's state cells | P13 (absorbed by *confident housekeeping is the machine's job*), S2 (superseded by T1), I13 (by I14), AF1 (revised after AG12, AT1, BC1, AY1): the ground truth for § 5. |\n\nNot in the corpus before this note: truth maintenance, design rationale and assumption management,\nthe legal doctrines of a law whose reason has ceased, sunset reviews, and the LLM work on redundancy and\non a reader's run-to-run spread (§ 4).\n\n## 3. What first principles settle\n\n**Being made unnecessary is a relation between a proposal's reason and a settled item, not between two\ntexts.** AF1 said a generalization *starts no wider than its links*. Its reason was unstated: a rule\ndrawn from few links should not claim more than they show. AG12 (a machine's sentence is a claim from the\nmoment it is written), BC1 (a claim's prior comes from its reference class) and AY1 (every case moves a\nstatistical generalization) remove that reason, since a wide rule is then simply a claim with a low\nposterior that its cases correct. None of the three shares a phrase with AF1. A reader that must quote\nboth sides finds overlap of words, which is why its findings run to *extends* and *depends on*.\n\n**So the reason has to be on the page before anything can see it gone.** A system that keeps beliefs with\ntheir justifications marks a belief unsupported when its justification fails; a system that keeps only\nthe beliefs cannot. A ledger row holds the proposal and, often, a recommendation and a counter; it rarely\nholds the one sentence *we propose this because C*. The reader must then rebuild C and judge C in one\ncall, two inferences, and either can drift.\n\n**Two directions can carry the check.** At proposal time the reader holds one proposal and every ruling\n(about 62,000 words), and must find the one ruling that removes a reason it was never told. At ruling\ntime the question is narrow: *this new ruling, against each open row's stated reason: does it remove\nit?* The second is how a justification-keeping system propagates a change, and it is the trigger the\nstanding-work ruling (R8) asks for. AF1's absorbers were ruled while AF1 stood open, and nothing asked.\n\n**A single reading of a long recall task is a sample.** Three readings of AF1 named three different sets\nof rows. Recall over a union of readings rises; precision is then the judge's job, which the second look\nalready does.\n\n## 4. What outside work adds\n\nTwo reports, saved verbatim beside this note: `report-llm-methods.md` (what helps a model read for this) and\n`report-formal-methods.md` (truth maintenance, design rationale, assumption management, requirements, law,\npolicy, software). Their read-status tags travel with every figure there; none is measured on a ledger of\ndesign rulings, so all of it is analogy.\n\n**Every field that handles this records the reason, and none discovers it.**\n\n- **Truth maintenance** (Doyle's justification-based system, de Kleer's assumption-based one). A belief is\n  held while one of its recorded justifications holds; a justification can carry an *unless* list, and a\n  belief goes out when an *unless* item comes in. The coherence school (AGM) keeps a belief as long as nothing\n  contradicts it, so it would keep AF1: **\"no contradiction found\" is the wrong test for this case by\n  construction.** A belief with two recorded reasons survives losing one, so a row's reasons must be listed\n  apart.\n- **Design rationale.** SEURAT stores assumptions as objects; disabling one lists the decisions to look at\n  again. Architecture decision records carry a *superseded by* link. No study measured whether recorded\n  rationale lets maintainers notice an obsolete decision.\n- **Assumption management** (Lago and van Vliet; Yang, Liang and Avgeriou). Most damage comes from\n  assumptions left implicit; of 112 practitioners, 49 identified assumptions and 22 recorded them. Tools find\n  assumption sentences well (F1 0.96) and judge none still valid.\n- **Requirements.** Obsolete requirements are found by tracing a change forward, not by rereading: an LLM\n  check of impact reached 85.7% recall with engineers reading 3.0% of requirements, 95.8% with domain\n  retrieval. LLMs find literal redundancy (565 of 582) far better than redundancy of meaning.\n- **Law.** A law whose reason has ceased (*cessante ratione*) is rarely held dead by a court; repeal by\n  implication is disfavoured, and a later act repeals an earlier one only when it covers the whole subject\n  and is clearly meant as a substitute (Posadas, 1936). Courts asked to find an overruling in a whole opinion\n  scored 42% to 75%. **The law's answer is a stated supersession, which turns discovery into checking.**\n- **Policy.** Sunset clauses mostly renew by inertia; reviews that work are planned when the rule is made,\n  with their trigger and default written then.\n- **Software.** Stale feature flags are found from the flag registry's state, not by reading code; an\n  expiring comment names its condition (`// TODO [engine:node@>=8]`), and a lint rule reports it when the\n  condition is met.\n- **What helps a model read.** With a long context and little word overlap between question and answer, 11\n  of 13 models fell below half their short-context score at 32,000 tokens (NoLiMa). Checking a step with its\n  premises shown raised error-finding by 6 to 16 points (PARC). Repeated runs raise what any one finds and\n  lower precision (union recall 1.000 at precision 0.275 in one review-screening study), so a strict judge\n  follows. Naming the class with worked examples raised recall about 3 points and cost about 5 of precision.\n\n## 5. The tests\n\n**The set** (`catching-a-proposal-made-unnecessary/cases/`): four rows the ledger records as absorbed by\nsettled items, and two open rows as controls, each given to the reader as its body only, with its own row\nleft out of what is settled. Ground truth is the ledger's own state cells, which recommendation 9 of the\n11 October inconsistency report already proposed using.\n\n| Row | Absorbed by, as the ledger records it | Shares words with it? |\n|---|---|---|\n| AF1, as worded before its revision | AG12, AT1, BC1, AY1 together | no |\n| P13 (spend attention where it creates understanding) | the principle *confident housekeeping is the machine's job* | yes |\n| S2 (a machine may not build on machine output until a person engages) | T1 (review need not keep pace with a proven pass) | T1 names S2 |\n| I13 (cross-cutting exposure lowers participation) | I14 (the Matthes meta-analysis: no overall relationship) | yes |\n| AX10, AU8 | nothing: controls | |\n\n**Three readers, one call per row or per ruling, Claude Sonnet at low effort:**\n\n| Reader | AF1 | P13 | S2 | I13 | Controls flagged as unnecessary |\n|---|---|---|---|---|---|\n| Today's outside reader, run 1 | no | yes (*repeats*) | no | yes (*reverses*) | 0 |\n| Today's outside reader, run 2 | no | yes (*repeats*) | yes (*reverses*) | yes (*made unnecessary by*) | 0 |\n| Reasons first (`trial.py reasons`): the proposal's reasons as *because* sentences, then what removes each | no (named AD23, AD25, AT3) | yes | yes | yes | AX10 by four rows, AU8 by two |\n| From the ruling's side (`trial.py forward`): one ruling against 30 open proposals | no, from each of the four | yes (*meets its purpose*) | yes (*reverses it*) | yes (*narrows it*) | 0 of 203 checks |\n\nWhat the three runs show, read case by case (`runs/`):\n\n- **Every reader catches the absorptions that share words or name each other, and none catches AF1.**\n  From the ruling's side, AT1 and AY1 each saw the bearing (*\"Both deal with a generalization's scope\n  narrowing by counterexamples\"*) and judged AF1's purpose distinct. They were right one at a time: no\n  single one of the four makes AF1 unnecessary. What made it unnecessary is what the four say together,\n  that a generalization's reach is carried by its posterior, its prior and its cases, and that sentence\n  existed nowhere until his revision of AF1 wrote it.\n- **Reasons first raises recall and loses precision**, as the literature predicts of a permissive\n  finder: it found S2's absorber on its one run, where today's reader found it on one of two, and it\n  called both controls unnecessary. Read by hand, AU8 against AL7 is an application of AL7, not a\n  redundancy; AX10 against AX8 is closer, and a person would have to judge it.\n- **Reasons first named AD25 against AF1** (*\"AD25 already settles, by a different route ... how wide a\n  rule is licensed to be\"*), as the second trial of 26 October did. AD25 was ruled before AF1 was written,\n  so the ledger's own record of what absorbed AF1 may be incomplete. The test set's ground truth is a\n  record, and a record can miss something.\n- **The ruling's side made no false flag** in 203 checks and found three of three single-ruling cases.\n  It is also small: one ruling and thirty proposals is a few thousand words, against 62,000.\n\nOne run of each trial reader; the spread found on 26 October means one run is a sample, not a rate.\n\n## 6. Recommendations\n\nIn order of dependency. Each governs **how we work** (the ledger and the checks run on it), not the claim\ngraph. None is ruled; the three that change the ledger's practice are Arc BE in the ledger.\n\n1. **Check at ruling time, from the ruling's side (BE1).** When a row is ruled, one call puts that ruling to\n   every open row and asks whether it removes a row's reason or meets its purpose. Evidence: 3 of 3\n   single-ruling absorptions found, 0 false flags in 203 checks (§ 5); the forward direction is what\n   requirements tracing and truth maintenance use (§ 4). It is the trigger R8 already asks for. Built only as\n   a trial (`trial.py forward`).\n2. **Every new proposal row states what it is for and why (BE2).** One *For:* line and one or more *Because:*\n   lines, each marked *today* or *as designed*, the first naming what it waits on (a pass, a count). Then\n   recommendation 1 reads a stated reason instead of rebuilding one, and BD18's split is on the row. The\n   reasons-first trial could write these (§ 5), so existing open rows can be given them by machine, marked as\n   machine-written.\n3. **When rulings together say what none says alone, write that sentence as a settled line (BE3).** AF1 was\n   made unnecessary by four rulings jointly, and no check of one ruling at a time can find that; the canon\n   review's cluster lines already are such sentences (cluster 1, how a claim's posterior is computed). Then\n   the check in recommendation 1 is one line against one row.\n4. **Keep the outside reader as it is, and add a permissive finder only behind its second look.** The\n   reasons-first reader found more and flagged both controls (§ 5); a union of runs followed by the strict\n   second look is the shape the literature supports. Waits on 1 to 3; no new rule.\n5. **An absorbed row names what absorbed it.** A **Meets:** clause beginning *made unnecessary by* already\n   draws a link on the ledger map (`deliberus/ledger_map.py`, since 2026-10-25), so writing it on the row\n   when a check finds the absorption needs no new rule.\n\nNot worth trying first, from the reports: persona wording, temperature alone, majority votes over whole\nreadings.\n\n## 7. A joint absorption can be found: derive the proposal again (2026-10-26)\n\nHis question, after § 5 said no check of one ruling at a time can find AF1, verbatim:\n\n> \"No ingenious way this can be detected? Ultrathink\"\n\n**Recognition fails and generation works.** Asked to *recognise* that several rulings together make a row\nunnecessary, a reader holds a row and the rulings and must see a combination nobody wrote down. Asked to\n*write* the rule it would propose today for the same problem, from everything settled, a writer composes\nthose rulings, since composing is what writing a rule is. The difference between the old row and the fresh\none is then read clause by clause, and a clause the fresh rule drops points at what dropped it. The writer is\ngiven only the problem, never the old answer, or it anchors on it.\n\n| Trial (`trial.py`, Claude Sonnet, low effort, one run each) | AF1 | Rows nothing absorbed |\n|---|---|---|\n| Joint question: the four rulings together, *does this set make AF1 unnecessary?* | narrows, then no bearing with the order reversed | a close-in-topic set read as *meets its purpose* |\n| Derive again: problem only, then compare clause by clause | the restriction dropped in 2 of 2 runs, with a sentence for what the rulings settle together | rows ruled the same day still came back *narrows* (2) or *meets its purpose* (2) |\n\nWhat the trials showed:\n\n- **The derive-again reading found AF1's restriction gone both times**, and both times wrote the sentence\n  the settled items settle together (run 1: *AT1, AT12, AY3 and BD20 settle that a rule's width …*; run 2:\n  *AD22, AD25, AT1, AT12, AY2 and AY3 settle that the general sentence under a link is a generalization whose\n  kind, width and number are read from pooled filed cases*). Neither named the four rows the ledger records;\n  AF1 is absorbed several ways over, and the record names one.\n- **Its overall verdict cannot be trusted alone**: every fresh rule differs from an old one in detail, so\n  rows he ruled that day also came back *narrows*. Two of the four negatives came back *meets its purpose*\n  because the row's own copy sits in the canon (BD27, BD29), which the check now leaves out.\n- **So what reaches him is a clause, filtered three ways**: dropped or changed in the fresh rule, its cited\n  ruling's words found in that ruling, and that ruling made after the row was written. The date is the\n  discriminator a trial cannot show and the ledger can: a ruling made before the row is a tension he wrote\n  alongside, not an absorption.\n- **The joint question is not used**: one set, two orders, two verdicts.\n- **The derive-again reading is costly (three calls a row), so it runs only where it is owed**: when two or\n  more rulings each come back from the ruling's side as bearing on part of a row. A *bears on part of it*\n  verdict is added to that check for this; in § 5's trial the readers had written exactly that in their\n  reasons (*\"Both deal with a generalization's scope narrowing\"*) and could only answer *no bearing*.\n\nBuilt the same evening on his rulings of BE1, BE2 and BE3 (`deliberus/ruling_check.py`,\n`scripts/ruling_ripples.py --meaning | --rederive ROW | --together`, `scripts/row_reasons.py`,\n`tests/test_ruling_check.py`, `tests/test_ledger_for_because.py`). The machine-written For: and Because: lines\nfor older rows are kept beside the ledger, keyed by each row's wording, so no row he wrote is edited and the\noutside check does not count it unread again. Trial runs: `catching-a-proposal-made-unnecessary/runs/joint-1.json`,\n`rederive-1.json`, `rederive-2.json`.\n\n## 8. The first runs on the live ledger, and what they taught (2026-10-26)\n\nHis words for the runs, verbatim: *\"Yes: build BE1, widening ruling_ripples.py to read every open row by meaning\nwhen a row is ruled, its owed work kept in the outside check's records.\"* · *\"Ah, ruled, build them too\"* (BE2,\nBE3) · on the machine-written lines for the older rows: *\"Yes please\"*.\n\n- **The check at ruling time, from the ruling's side**: AX4 (a long leap folds) and AX9 (any claims that fit may\n  share a card) were each put to every open row, 856 readings in all. Two came back *bears in part*, none whole,\n  so no row was derived again from those two alone.\n- **AX10 (one zoom moves both folds, in five levels) was derived again** and came back with a joint sentence: AX8\n  (split to the floor, join for display), B2, Q38 and Q49 settle *\"no fixed five-level zoom ladder at all, only a\n  continuously computed fold/join over one floor-stored representation\"*. Read against AX10 and AX8 whole, the\n  reason mixes up storage with display: AX10's levels are display settings over the one floor, which AX8 permits.\n  Two points survive it: AX8 names two motions where AX10 drives both with one zoom, and his requirement of\n  2026-10-24 has code decide, live and per view, what a vertical fold shows. It is a high-priority to-do beside Q50\n  (what relevance means), on his word: *\"Lemme come back to this, set it as a high priority todo so it surfaces\n  along with this other item\"*.\n- **A joint sentence can outrun its evidence.** The clause it rested on most, *five levels*, cited a quote from AX8\n  that AX8 does not contain, and the sentence still reached `--together` unmarked, because the quote and date filter\n  of § 7 governed the clauses and not the sentence. Since the same evening each sentence says how many of its\n  dropped or changed clauses passed that filter (AX10's: 2 of 5; `together_support` in `deliberus/ruling_check.py`,\n  tested). A sentence is still shown when few pass, since what it proposes may be right for other reasons; the\n  count tells him how much of it the rulings' own words carry.\n- **Every open row now states its problem and reasons**: 428 rows carry marked For: and Because: lines beside the\n  ledger (`docs/research/outside-checks/row-reasons.jsonl`), written in 43 calls, none failed. `row_reasons.py\n  --owed` names any row added later without them, which is how Q50 got its lines the hour it was added.\n"}