diff --git a/prolog-sessions/kb.pl b/prolog-sessions/kb.pl index 43782468..08f36b91 100644 --- a/prolog-sessions/kb.pl +++ b/prolog-sessions/kb.pl @@ -250,6 +250,8 @@ doctrine(a_script_with_two_modes_has_two_gates,'scripts/check-comment-runs.py ru doctrine(an_injecting_reviewer_needs_its_own_tree,'An adversarial reviewer given leave to inject faults RACES THE AUTHOR if they share a worktree: on wave F the reviewer subagent injections landed in the author tree mid-gate and the author own run reported a failure for a fault it had not written. Everything was restored cleanly, but the diagnosis cost real time and could have been read as a genuine regression. A reviewer that injects gets its own worktree or a scratch copy, always. Related and separately costly: the session SCRATCHPAD IS SHARED across wave agents, and one agent overwrote another pr-body.md mid-task -- unique filenames, or a per-agent subdirectory.'). doctrine(who_may_connect_is_two_questions,'Ask of any access control whether it constrains the CLIENT or what may DRIVE the client. A websocket handshake is exempt from the same-origin policy, so an address allow-list, a private network and loopback binding all answer \"may this client reach the endpoint\" and answer YES to a cross-site hijack: the request genuinely comes from an allowed client, driven by a page the user never intended to trust. Only Origin separates them. Loopback is the LEAST protected case, having no proxy in front of it at all -- the intuition that it is the safe default is exactly backwards (improvise-kc7n).'). doctrine(a_line_count_in_a_document_is_a_dated_snapshot,'repo-map File Inventory line counts were audited 2026-09-21: 26 of 61 resolvable entries had drifted past 10 percent, several by a third. They are useful as \"is this file big\" and useless as a figure to cite, which is how false precision enters a document that is otherwise carefully checked. Refreshed and labelled with the date and the method. Two traps found while doing it: a naive path-walking refresh resolves a bare name like lib.rs or render.rs against the FIRST matching crate and silently rewrites the wrong number (it reported lib.rs 561 -> 8), and the ws-server/ and improvise-worker-server/ entries use a shorthand prefix no such walk resolves at all, so they drift silently and must be checked by hand.'). +doctrine(measure_the_obvious_fix_before_reporting_it_as_the_fix,'On improvise-mcq4 the obvious narrowing -- fingerprint only the active view rather than every view -- was the ticket own first option AND the orchestrator suggestion AND the author plan, and implementing it moved 12.41ms to 12.56ms: NOTHING. The per-view multiplier was never the cost; two EXPENSIVE builds were, and the bench second view was a fresh one with everything on Axis::None, costing nothing to build. It would have been reported as the fix if the author had not re-measured after implementing. The real fix was unrelated: at batch start self.layout ALREADY IS the active view pruned layout, so hash it instead of building a second (4.1x to 1.9x). A fix that three people agree is obvious has had its plausibility checked and not its effect.'). +doctrine(a_clean_merge_of_two_mechanisms_leaves_both,'When two branches replace one mechanism with two different ones, the dangerous file is the one that does NOT conflict. On PR #78 app.rs conflicted loudly (two hunks, resolved by hand) while effect.rs AUTO-MERGED CLEAN and left #76 new per-effect SetPageSelection reset standing beside #78 whole-grid observation: two complete live cursor-invalidation mechanisms, 1435 tests green, nothing failing. A conflict marker is a request for attention; its absence is not a statement that none is needed. After any merge where both sides touched the same SUBJECT, ask what each side did rather than whether git could combine the texts -- git merge-tree reporting no conflict answers \"can these texts be combined\", never \"does the combination do what both sides meant\".'). work_done('improvise-8tk',bug_fix,'ZZ/:wq quit even when the save failed, silently discarding the model. Save now aborts the effect batch on failure; save_to_current_path/1 returns Result; three tests in ui/effect.rs.'). work_done('improvise-907',bug_fix,'Import wizard step machine redesign: validation_error() gate at ReviewProposals (no-category and over-limit), history-stack previous() bound to Left on every step, and Done made a real confirmation step holding the built workbook. Superseded improvise-gfq, improvise-o1c, improvise-c6j.'). work_done('improvise-6sq',wont_do,'Merging EditOrDrill and EnterEditAtCursorCmd into one EnterEdit{mode} is not safe: they differ in WHEN the cell value is read, not in a mode parameter. Added ui/app.rs::tests::i_and_o_diverge_on_an_empty_records_grid as executable evidence.').