kb: five facts from PR #82, and the negative arm's own anti-vacuity guard
CI / Build all bundles (push) Has been cancelled
CI / Test and lint (host) (push) Has been cancelled
CI / wasm32 check (browser bundle crates) (push) Has been cancelled
CI / Browser JS unit tests (node --test) (push) Has been cancelled
CI / Knowledge base consistency (push) Has been cancelled
CI / Lint the harness crate (push) Has been cancelled
CI / Browser harness (OPFS contract + shell) (push) Has been cancelled
CI / Deploy to GitHub Pages (push) Has been cancelled
CI / Build all bundles (push) Has been cancelled
CI / Test and lint (host) (push) Has been cancelled
CI / wasm32 check (browser bundle crates) (push) Has been cancelled
CI / Browser JS unit tests (node --test) (push) Has been cancelled
CI / Knowledge base consistency (push) Has been cancelled
CI / Lint the harness crate (push) Has been cancelled
CI / Browser harness (OPFS contract + shell) (push) Has been cancelled
CI / Deploy to GitHub Pages (push) Has been cancelled
PR #82 disproved the replacement claim this orchestrator had handed its author, not only the original: of the four prepare steps documented as "the reason the test is not vacuous", only DeleteView and ShowItem are. ToggleGroup::apply toggles collapse unconditionally — the membership check gates only reset_cursor — and TransposeAxes' step restates a precondition View::on_category_added already establishes. Verified against the source before recording. Also records the detector half of the N-1-guarded-edits shape, named by the PR #79 reviewer: a comment explaining why something is correct is weak evidence that anything checks it, and the more carefully argued the comment, the more likely it is standing in for a test. Five instances across two independent reviews. The two new keys are dated slugs rather than improvise- ids, because bd issued none. An ID-shaped non-ID is worse than a dead id: the diagnosis is identical and the repair is not. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
This commit is contained in:
@@ -236,6 +236,10 @@ doctrine(name_the_test_that_fails_when_only_this_edit_is_reverted,'A repair is u
|
||||
doctrine(a_stale_list_of_what_is_missing_is_worse_than_no_list,'repo-map gotcha 24 named TransposeAxes and CycleAxis as the only effects calling reset_cursor, and named SetAxis, HideItem, ShowItem, ToggleGroup, TogglePruneEmpty, AddCategory, RemoveCategory, AddItem and RemoveItem as renumbering the grid WITHOUT resetting. improvise-9mo9 had closed that the day before: all of them reset, thirteen in total. So the paragraph named as ABSENT the exact set that was by then PRESENT, and read as a survey of outstanding work rather than as history -- strictly worse than saying nothing, because it invites an agent to re-fix what is fixed. A list of what is missing decays in the one direction that looks like a to-do. Where the set is derivable, publish the DERIVATION beside it: awk over impl Effect blocks for reset_cursor, brace-matched rather than grepped.').
|
||||
doctrine(two_counts_from_two_derivations_are_not_one_fact,'Thirteen effects call reset_cursor and thirteen declare Model(LayoutGeometry). The counts are equal and the SETS ARE NOT: CreateView, DeleteView and SetNumberFormat declare the kind and never reset; SetPageSelection resets only conditionally. Equal length invites reconciling one list to the other, which silently changes what one of them means. Same shape as the wasm bundle being seven crates while its CI gate covers eight -- neither number is the other one typo.').
|
||||
doctrine(verify_the_claim_you_are_about_to_publish_as_the_correction,'While correcting repo-map gotcha 24 for being stale, the orchestrator asserted from a reviewer report that CreateView, DeleteView and SetNumberFormat declare LayoutGeometry and never reset the cursor. Measuring it before merging found the claim TRUE but UNDERSTATED: the sets differ in BOTH directions, three each way -- AddItem, AddItemInGroup and RemoveItem reset while declaring CellData. And the orchestrator naive awk reported fourteen LayoutGeometry effects, picking up HelpPageSet, which is the exact artefact the same document already warns about two paragraphs away. A correction is a claim like any other and decays the same way; the person writing the fix is the one least likely to check it, because they have just read the evidence and feel current.').
|
||||
doctrine(a_careful_comment_is_weak_evidence_that_anything_checks_it,'The companion to name_the_test_that_fails_when_only_this_edit_is_reverted, and the half that tells you WHERE TO LOOK: a comment explaining why something is correct is weak evidence that anything checks it, and the more carefully argued the comment, the more likely it is standing in for a test. Five instances in one wave, found by two reviewers independently. improvise-0x9u drawn-vs-seed: a two-line comment explaining that restoring seed would leave 1200 where 1,200 was -- and reverting the line left the whole suite green while the shipped demo showed 18400. UNCALLED in wasm_surface.test.js: a doc comment justifying every exemption, silent on the fact that callsOn is a source scan and cannot see a call inside a function nothing calls. The improvise-cl7y size table: prose that reads as measurement throughout while one column is a gzip -9 proxy for brotli. declined() view-back: a uniform user-facing sentence that erased a real distinction between not-built and cannot-be-built-without-addressed-commands. improvise-o31u: an evidence entry naming two faults, neither of which makes the test fail. The comment reads as evidence because it is the most thoughtful thing on the screen, which is exactly the illusion.').
|
||||
doctrine(a_prepare_step_is_not_evidence_until_deleted,'A test-fixture prepare step is claimed load-bearing far more often than it is. Measured 2026-09-20 on every_layout_geometry_effect_is_visible_to_the_narrow_fingerprint: of four prepare steps documented as \"the reason the test is not vacuous\", only DeleteView and ShowItem are. ToggleGroup passes without one because ToggleGroup::apply calls toggle_group_collapse UNCONDITIONALLY -- the membership check gates only reset_cursor -- and TransposeAxes step is literally a no-op, because View::on_category_added already assigns the first regular category Row and the second Column. The check is cheap and nobody runs it: delete each prepare in turn and require the case to fail. A prepare documenting realistic input is fine; a prepare DESCRIBED as carrying the test and not carrying it is an entry that will be cited. Note the orchestrator brief asserting the replacement claim was itself wrong on two of the four, so this is not a failure of the original author alone.').
|
||||
doctrine(a_precondition_asserted_after_the_act_asserts_nothing,'An assertion naming a fixture precondition must run BEFORE the code under test, or the code under test establishes it. Proven 2026-09-20 on selecting_the_page_already_selected_invalidates_no_cursor: \"the fixture was not on Q1\" ran after a SetPageSelection to Q1, so it could never see a fixture that started elsewhere. The property was still guarded -- a Q2 fixture failed -- but at a DIFFERENT assertion, under a message about renumbering. That split is the failure mode: the guard survives, the explanation drifts, and the next reader trusts the sentence rather than the assertion.').
|
||||
doctrine(an_evidence_entry_that_measurement_contradicts_is_worse_than_none,'context/test-evidence records WHY a test can fail, so a mechanism stated there is load-bearing prose and will be cited. Proven 2026-09-20: the entry for every_layout_geometry_effect_is_visible_to_the_narrow_fingerprint claimed a dirty=false clear stopped the preparation satisfying the assertion. Removing the clear AND blinding document_config to 0 left all THIRTEEN cases reading false -- dirty is raised only inside App::apply_effects and no prepare runs an effect, so no preparation can set it. Nothing checks an evidence claim against the code: check-comment-runs.py --check-evidence verifies only that each heading names a test that exists. Re-run an evidence entry injection when you touch the test it describes. Probing this particular test needs the assert replaced by a print, because the loop aborts at case 1 under any injection blinding document_config -- which is probably how the wrong claim survived.').
|
||||
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<String,String>; 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.').
|
||||
@@ -265,6 +269,7 @@ work_done('improvise-lyyc',bug_fix,'--check-evidence gained its second direction
|
||||
work_done('improvise-x4wv',bug_fix,'web/assemble.sh\'s stamped guard exited on the FIRST missing cache-bust stamp, so breaking two substitutions named one and cost a wasm-pack rebuild to find the next. stamped now records and a gate after the four calls fails the build. Both the fix and the gate\'s own absence were proved by injection; the comment says the gate is the whole guard.').
|
||||
work_done('improvise-2f97',feature,'kb_error(dangling_citation/3): a name cited inside another clause\'s text must resolve as a doctrine/2, invariant/2 or decision/3. The token rule is narrow on purpose -- only a name-shaped token (lowercase, digits, underscores, at least one underscore) directly inside doctrine(, invariant( or decision( -- so prose cannot false-positive. Retiring doctrine(an_advisory_gate_is_not_a_gate) is now refused by name rather than silently dangling its citers. kb_text/2 is hand-maintained, like gate_predicate/1.').
|
||||
work_done('improvise-dj1l',bug_fix,'scripts/kb-merge.pl matched clause keys by unification, which lost and corrupted clauses: two variant-headed rules in one delta went two in, one out (536 before, 2 in delta, 537 after), and a non-ground rule over a predicate holding facts deleted one AND was written with its variable bound. See invariant(key_matching_is_variant_equality_never_unification). Five regression cases added to scripts/kb-test.sh, including one that injects a dropping fold to prove check_total fires; scripts/kb gained a KB_MERGE seam so a broken merge can be injected.').
|
||||
work_done('pr82-fingerprint-guards-2026-09-20',test,'PR #82, follow-up to #76. Added assert!(app.view().prune_empty) to selecting_the_page_already_selected_invalidates_no_cursor (paged_model(false) plus deleted moved-conjunct had left it GREEN); moved its page-selection precondition ahead of the effect and onto App::view(); corrected the test-evidence entry for every_layout_geometry_effect_is_visible_to_the_narrow_fingerprint, whose stated mechanism measurement contradicts, and recorded which two of its four prepare steps are load-bearing. 1425 passing, unchanged. Key is a dated slug and not an improvise- id, because bd issued none: an ID-shaped non-ID is worse than a dead id, the diagnosis being identical and the repair not.').
|
||||
work_followup('improvise-8tk','improvise-lae','no-file-path UX: prompt for a path rather than only erroring. ExportPrompt is CSV-only, so a new SavePrompt TextEntry mode committing to SaveAs is the likely shape.').
|
||||
work_followup('improvise-6sq','improvise-ct5','i on an empty records grid reports \'cannot drill\', leaking a pivot-mode concept into records mode').
|
||||
work_followup('improvise-h0b','improvise-a2x','ViewState field types (AppMode, MinibufferConfig, ViewFrame, KeyCode, KeyModifiers) still derive no Serialize, and improvise-command depends only on serde_json. Deferred: nothing serializes ViewState until improvise-cqi builds a Snapshot, so the derives would have no consumer.').
|
||||
@@ -333,6 +338,7 @@ decision('improvise-djoo',the_nav_disclosure_is_a_checkbox_not_details,'The doc-
|
||||
decision('improvise-864a',skip_a_superseded_pages_deploy,'Three merges within 20s queued three deploys on one Pages environment; only the newest kept its github-pages artifact and the other two runs went red on an empty fetch with a GREEN upload step. Chose to SKIP (compare GITHUB_SHA against the tip of main) rather than cancel: the concurrency block\'s own comment records that a deploy-pages cancelled midway can leave the deployment half-applied. Unresolved and flagged: why GitHub drops the losing runs\' artifacts -- the fix does not depend on the answer.').
|
||||
decision('improvise-9c8c',gate_the_comment_cap_last,'The CI step enforcing the two-line comment cap and the test-evidence keys was held back until every unit of the comment wave had merged, so that the gate\'s first green run was evidence rather than vacuous.').
|
||||
decision('improvise-kh8',landing_page_at_the_root,'USER RULING 2026-09-20: the landing page should be served at the root of the repository and link to the in-browser demo. Supersedes the agent\'s proposed landing_page_beside_the_app, which argued for the app at the root with the landing page at /landing/ on the grounds that the live app is the better front door; that argument is recorded as the reason the alternative was considered, and it was overruled. web/assemble.sh puts docs/index.html at the site root and moves the app bundle (index.html, app.js, style.css, worker.js, demo.improv, pkg/, worker-pkg/) under /app/, moving the two bundle dirs WITH the app so every relative path in the generated glue stays correct. The non-obvious cost: harness/tests/shell.spec.js navigates to /index.html six times, so a path move at the root silently retargets the whole shell spec at a different page. The deployed arrangement IS what the harness serves (improvise-vvl3), which is the property that makes the harness trustworthy and also the property that makes a layout change a test change.').
|
||||
decision('pr82-fingerprint-guards-2026-09-20',a_test_reads_the_view_its_effect_writes,'App::view() resolves ViewState::active_view (this client) and Workbook::active_view() is the DOCUMENT DEFAULT; gotcha 29 makes them deliberately free to differ since improvise-jytm. A test asserting what a geometry effect did must read App::view(), the view the effect writes through view_mut(). They agree in a single-client fixture, so the mismatch is latent and survives review easily -- found only because a sibling guard added beside it used the other accessor, one test reading one view through two accessors.').
|
||||
wire_carries(command,both_directions,'user intent up, projection commands down').
|
||||
wire_carries(snapshot,on_connect_only,'improvise-q08: full ViewState + render cache filled from current viewport').
|
||||
wire_carries(command,both_directions,'user intent client->server, projections server->client').
|
||||
|
||||
Reference in New Issue
Block a user