Commit Graph

153 Commits

Author SHA1 Message Date
Edward Langley f155d12afe chore: more updates 2026-09-25 00:28:55 -07:00
Edward Langley 14141771e4 chore: update issues 2026-09-25 00:08:54 -07:00
Edward Langley cf33a5d78a chore: update issues 2026-09-25 00:07:05 -07:00
Edward Langley f2093dc0c1 bd update 2026-09-23 22:31:05 -07:00
Edward Langley ef16723b90 docs(agents): commit frequently, so the work is safe in git
User ruling. A worktree is not durable storage: an agent finished a whole
ticket with every gate green and lost all of it, uncommitted, when its
worktree was deleted during a disk cleanup. The brief template now requires a
WIP commit after the first green test and after every meaningful step, and
separates "do not merge to main" from pushing the agent's own branch, which is
encouraged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
2026-09-22 20:47:01 -07:00
Edward Langley e9f7327328 docs: the fmt gate every brief prescribed, and the collapse ruling
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
AGENTS.md's brief template now carries the gate list, because the one I had
been handing agents said `cargo fmt --all`, which reaches only one of this
repo's two workspace roots — and `cargo fmt -p opfs-contract` from the root
exits 1 as a usage error indistinguishable from a real verdict
(improvise-b4ks). Both spellings fail in the direction that looks like
success. The gate is `scripts/fmt-workspaces.sh`.

kb: the improvise-6qet ruling (a collapsed group is one aggregate row), and
the CI lane's doctrine on stubs and fixtures.

Also recovers kb.pl from a truncation: the working tree had lost 276 of 801
facts, most likely to a `kb replace` killed mid-write at a session boundary,
and `kb add` had written onto it with kb_consistent passing. Restored from
HEAD; this commit is 6 insertions, 0 deletions. Filed as improvise-usus.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-22 20:21:05 -07:00
Edward Langley 29e41a32e0 docs(kb): what adversarial review found, and four vacuity shapes
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
From PRs #143/#146/#147/#150/#152/#156/#157 and the adversarial review of the
first five.

The finding worth the review's cost: `Repr::Nonfinite(&'a str)` could only be
produced by a deserializer that borrows from its input, so the new wire
spelling round-tripped through `from_str` and `from_slice` and nothing else —
the same JSON document escaped as `inf` was refused, and `to_value` did
not round-trip its own output. Both of the PR's tests used `from_str`, which
is precisely the one path that borrows.

Four vacuity shapes, each confirmed by injection rather than argued:

- A disjunctive assertion can accept the bug it guards — one branch here was
  exactly the error message the defect produces.
- A law asserted over an immutable `CmdContext` is a tautology: a `Cmd` is
  pure over its context by construction, so `execute` twice without applying
  effects asserts `f(x) == f(x)` and no rival can fail it. Applying the
  effects REFUTED this one rather than rescuing it.
- A rival must fail the property, not the setup — `AddFormula` and
  `RemoveItem` are both `CellData`, so the obvious test proved the neighbour.
- Every agent appends to the same evidence file at EOF: four conflicts in ten
  PRs. Loud, but the resolution is the hazard, since `--check-evidence` cannot
  see a dropped entry.

kb_consistent: TRUE, 803 facts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-22 19:49:23 -07:00
Edward Langley b1a989d8cf docs(kb): the command lane's doctrine, and a second vector for the base trap
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
From PRs #144/#148/#151. `AGENTS.md`'s remote note gains the worktree-base
vector: a branch cut from the orchestrator's local `main` inherits whatever
that checkout merged but did not push, and nothing in the branch says so —
which is how #148's diff came to name the three orchestrator-only files and
read as a rule violation rather than a base problem.

Four facts. A fold test must fold the batch the producer really emits — a
`Binding::Sequence` flattens into one vec, and a per-step batching cannot see
intra-batch order at all. A type name is not a field, measured: one 14-site
rival left 14 of 16 assertions passing, while an assertion on a *fieldless*
effect is complete rather than smoke. A registry with two arms demotes the
weaker caller, and neither direction is safe by default. And a clean text
merge can delete an evidence entry that no gate checks.

Two gate traps: `--check-evidence` prints the comment cap FIRST, so reading it
through `tail -1` drops the half that was always there; and a compound command
refused by the worktree shell guard runs NEITHER part.

kb_consistent: TRUE, 798 facts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-22 19:34:07 -07:00
Edward Langley 810398e4a4 docs(kb): the TUI composed-row rule, and a trap in our own remote topology
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
PRs #145/#149. New gotcha 50: `fill_line` takes a `Keeps` because the three
rows sharing a line disagree about which side yields, and the one key table on
screen is the one derived from the keymap — with the import wizard as the
deliberate inverse, since its derived line comes from the mode keymap while
the real keys are per-step.

AGENTS.md gains the remote trap, and it is the orchestrator's fault: briefs
said "merge `main`", and because `origin`/`gitea` take `main` directly while
GitHub gets branches, `origin/main` runs ahead of `gh/main`. An agent doing
the habitual thing pulled four unmerged commits — another PR's whole diff —
into a branch based on `gh/main`. Nothing in CI can see it; the result
compiles and passes. Codex caught it. The window is transient, which makes it
worse: the hazard is absent exactly when you would think to check.

Closes improvise-t14d, improvise-rr8n and improvise-vgp4 — the last
stale-open, fixed by 94a3d17 two days before it was filed.

Measured on main at 78a7bbf: 1700 passed / 0 failed / 7 ignored over 38
binaries, longest single binary 0.69s. kb_consistent: TRUE, 792 facts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-22 19:01:31 -07:00
Edward Langley 755e3477c5 docs(kb): drill decomposition, aggregate scope, and a closed ticket read as open
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
PRs #140/#141. Gotcha 27 gains the one home for what a virtual view must BE
(`view::{records_spine,records_steps,drill_steps}` as data; `cmd/grid.rs::
steps_into_active_view` as the TUI's translation). Gotcha 44 gains the
finding: `RecordHash` is document-scoped and `AggregateHash` is layout-scoped
and cannot be otherwise, so `App::resolve_aggregate` answers only where the
host stands — that, not ADR 001 layer 2, is what blocks browser drill.

Gotcha 29 described improvise-lltt as an open gap. It is CLOSED, and verified
so: every view-scoped `ModelCommand` carries `view: String` and `model_effects`
maps it to `ViewTarget::Named`. A closed ticket cited as an open gap is the
mirror of a dead ID — it reads as a promise that work remains.

improvise-gd28 closed by REMOVING its dependency on improvise-7b8v rather than
forcing past it: the dependency encoded the premise #141 disproved. Files
improvise-t0ma, improvise-obtu, improvise-t219.

kb_consistent: TRUE, 788 facts. Dead-ID audit: 360 ids, all resolve.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-22 18:38:51 -07:00
Edward Langley db6593b1b2 docs(kb): gotcha 40 was stale in three sentences (improvise-ilvl)
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
The replay audit found `layout_version` documented as bumping "per
`ModelChange::LayoutGeometry` effect". It does not: `observe_reshape` diffs
`view_shapes` before and after the batch and bumps only where a view's shape
actually moved, so an idempotent `set-axis` bumps nothing. The source comment
at `apply_effects` has said so since improvise-pdvm; the repo map was the
stale copy, and it said the opposite in three sibling sentences — the
parenthetical, the "both tiers are read off the `EffectKind`" claim, and the
"bumps inside the loop" claim, which is also false (it runs once, after).

The observed form subsumes the gotcha 21 argument rather than restating it:
an aborted batch moved no shape, so there is nothing to not-claim.

Also files improvise-6uva (P1) and improvise-up8g, and records the audit on
improvise-ilvl. kb_consistent: TRUE, 783 facts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-22 18:27:02 -07:00
Edward Langley 3be1653385 docs(kb): the session's rulings, deferrals and doctrine
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
Records the campaign's accumulated facts: the Pages-tracks-main ruling, the
reserve-space-do-not-fit-it rule behind the header stability work, the
decimals-by-default decision and its grammar placement, and the doctrine
learned from this session's failures — a ready ticket may already be fixed,
a prose count is checked by no one, a clean merge is not a tested merge.

kb_consistent: TRUE.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-22 18:23:34 -07:00
Edward Langley c720565372 chore: update issues.jsonl
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
2026-09-21 22:21:03 -07:00
Edward Langley 8eb93628b2 kb: the view/server split exists so clients can differ, and that is a test
User: 'The whole point of the view / server split is that multiple clients can
have different views of the model.'

Recorded as the RATIONALE rather than a fact, because it is the single premise
the day's four rulings follow from -- client-local view stack, ephemeral drill,
client-only view switching, and identical staging. gotcha 29 already said 'the
model is shared and the UI is not'; this says why, and converts the split from a
fact into a test: does the proposal force two clients into the same view?

Plus the two integration doctrines: an autostash instruction is not permission to
pop (the stash stack is shared across six other sessions), and a capability and
its key can land in different tickets.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 21:18:01 -07:00
Edward Langley 0cfbc6f373 kb: browser drill stages identically, because staging and the basis check answer different questions
User ruling. An agent proposed that a browser write through with ordinary
SetCell commands rather than staging, since those are already basis-checked.
The substitution does not hold: the basis check is anti-staleness coordination
between clients and answers whether a picture is CURRENT; staging is an
editing-session abstraction for one user and answers whether they want to KEEP
what they typed. Write-through would silently remove the ability to abandon a
drill -- invisible to any test that asks only whether an edit lands.

The convergence that makes it cheap: clause 4 is delivered, so a staged commit
is a batch of SetCells taking its atomicity from the transaction that already
exists.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 19:50:37 -07:00
Edward Langley e3fc2210b8 kb: the doctrine this wave's four agents earned
Twelve facts across four PRs. The ones that generalise furthest:

a_completeness_check_closed_over_the_omitting_artefact_is_blind -- the parity
guard asked whether every RenderModel field is painted, and its domain was
RenderModel, the very thing that can omit a field. It reported a clean bill for
a whole wave while totals and page_coords were painted by nothing.

an_escape_hatch_is_where_a_new_check_goes_vacuous -- both bugs in a new guard
were in its exemptions, never its check. '&state.grid' is a substring of
'&state.grid.row_frame'.

a_cursor_rule_copies_between_panels_only_if_the_list_is_homogeneous -- the
obvious repair for uej8 is worse than the bug.

a_ticket_can_be_one_level_too_high_and_its_fix_unimplementable -- g3no's stated
fix could not work on the browser side twice over.

deliberate_slack_can_become_load_bearing_with_nobody_editing_it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 19:32:56 -07:00
Edward Langley ebc89b7a57 fix(beads): repair 11 dependency edges stored with the flag as part of the id
`bd dep add X blocked-by:Y` passes "blocked-by:Y" as the POSITIONAL
depends-on-id, and bd stores it without validating that the id exists. So all
11 edges the groom added pointed at non-existent issues, resolved to nothing,
and every bead I had just blocked still reported READY -- bd ready said 100
when it should have said 94.

Correct syntax is `bd dep add X --blocked-by Y` or the bare positional
`bd dep add X Y`, with -t for a non-blocks type.

Caught by verifying the ready list before dispatching a wave against it, which
is the only reason it did not become six agents working on blocked tickets.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 14:32:34 -07:00
Edward Langley 700879de20 chore(beads): groom the backlog
Three duplicates closed, each filed independently by a different reviewer on
the same day, each carrying its unique content over to the survivor rather
than being dropped:
  eiv2 -> jc95  (CSV nonfinite becomes zero; jc95 raised P2 -> P1, since the
                 duplicate's P1 was the better rating and PR #101's
                 reproduction already cites jc95)
  dhw5 -> l1f5  (a blank numeric CSV field types the column as Label)
  16af -> i0v9  (OPFS handle contention; the duplicate's single-tab RELOAD
                 trigger is now recorded on i0v9, which had only driven the
                 two-tab case)

jkxr closed -- fixed on main today, by injection.

New: improvise-1wft. Five beads from three reviewers turned out to be one
failure mode -- the browser's boot fails for several reasons and the page says
nothing specific or nothing at all, because no channel carries a boot failure's
REASON from the worker to the page. i0v9/86nw/9cma/iobc/vep8 now block on it so
they are not fixed five different ways.

improvise-bck read READY -- every dependency closed -- while its own criterion
(1) was failing. Now blocked on 1wft and p7lh, with a note that the criterion
says Chrome AND Firefox while the shell spec is Chromium-only by design.

Two more clusters recorded on their members so they dispatch as single units:
the three `_ =>` wildcard beads (492x/4lgj/vyrx, a straight design-principles
section 2 violation) and the five vacuous-assertion beads (lm5e/gjat/ub4o/
sfwy/a36c), the latter pointed at jkxr as the worked example.

pcje narrowed and retitled: p7lh owns totals and the page bar, which is the
demonstrated half and a bck blocker. lhi4/u6gc paired -- same match block, and
u6gc regresses gd83 whenever prune_empty is on.

h074 reclaimed: an expired lease, heartbeat 17 hours dead.

Audited: all 14 deferred beads carry a recorded reason. A first pass reported
four without one; that was a false positive from reading only `notes` when the
reason was in `description`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 14:28:40 -07:00
Edward Langley 0f0c38b50d chore: update issues.jsonl 2026-09-21 14:24:34 -07:00
Edward Langley 61a3509185 chore: regenerate issues.jsonl from the database
The previous export raced improvise-qjy2's creation. Regenerated so the file
matches the database, which is the truth.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 14:23:24 -07:00
Edward Langley 5f47fecf05 chore(merge): gh/main — PR #100 adversarial review findings
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
# Conflicts:
#	.beads/issues.jsonl
2026-09-21 13:50:16 -07:00
Grok Bot (Ed Langley) 2705c16cab beads: file PR #100 adversarial review findings
24 new beads from cloud adversarial review PR #100 (P1–P3). No application
code changes. Map: F01–F05 P1, consolidated P2/P3 transport and ws-server,
F21 noted as dup of iobc.
2026-09-21 13:49:44 -07:00
Edward Langley d358da46a1 chore(merge): gh/main — Grok Bot adversarial findings (jkxr, df2w)
# Conflicts:
#	.beads/issues.jsonl
2026-09-21 13:47:48 -07:00
Edward Langley 62d3af8f10 chore: various things 2026-09-21 13:46:31 -07:00
Edward Langley f9d4e3bb3e chore(merge): gh/main 2026-09-21 13:44:56 -07:00
Grok Bot (Ed Langley) fdcb9063dc beads: adversarial review findings (jkxr, df2w)
Vacuous parse_duplicate_categories checker; open empty formula panel
invisible via emptiness-as-closed RenderModel encoding.
2026-09-21 13:44:16 -07:00
Edward Langley 856a5f84eb chore: update issues.jsonl 2026-09-21 13:40:08 -07:00
Grok Bot (Ed Langley) bb69a157e0 beads: file web smoke bugs from external Grok Bot hunt
OPFS handshake flake, silent seed/doc failures, narrow-grid clip,
Esc leaving formula panel open, and Create-cell silent decline.
2026-09-21 13:33:27 -07:00
Edward Langley 1f2886873b kb: a derivation protects only what it derives
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
Three facts from the UX audit, which found the product mostly coherent and
the incoherence concentrated in two places.

The help pages are DERIVED from the keymap and a row naming a nonexistent key
is dropped — good architecture, working. The ex-command rows are Literal and
escaped it, and that is exactly where the worst content bug lives: every
documented spelling of :formula fails, on the quick-start page, for the
headline feature, because the parser splits on whitespace and nothing says to
quote. Verified. When a derivation lands, enumerate what it does not cover,
because the covered part now looks trustworthy and the uncovered part looks
identical.

The browser paints the host's hints and help over a smaller capability set:
four advertised keys decline out loud, ten more are silent, and help page 2's
whole Search section is taught to a browser user who cannot use it. A shared
vocabulary still owes a per-surface capability filter.

And the status bar contradicts the wizard overlay on four of eight steps —
on Done it says Esc cancels where Esc goes back. Two writers of one fact,
improvise-edp's disease in the UI layer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 13:30:40 -07:00
Edward Langley 532c7f2405 docs: the gotcha-44 gap list named two closed tickets as open
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
improvise-h0iv and improvise-1wl0 are both fixed — group_runs coalesces by
header identity via ptr::eq, and AxisFrame::first carries no serde(default),
its doc comment saying why. The repo map listed both as 'still open beside
it'. Verified against the code before correcting.

That is the second time this exact paragraph has done it, and
doctrine(a_stale_list_of_what_is_missing_is_worse_than_no_list) was written
about its previous instance — by me, two days ago, after which I committed
the next one. A list of what is missing decays in the one direction that
reads as a to-do.

Also files the bug-hunt findings. Six hunters over six territories produced
five P1s, every one demonstrated rather than reasoned:

  dy3j  a Label category is not persisted, so a document with 12 categories
        plus a label can NEVER BE REOPENED
  o9uq   in records mode edits someone else's record and can rename it
        away — silent data corruption from a documented key
  pv3g  fit-measure panics on large finite values; a hard crash in the TUI
  bd9o  the browser reaches records mode through the tile bar, and everything
        it can do there is silent
  (plus the P2 set: prune_empty never persisted, the browser drawing neither
   page bar nor totals, two prune_axis_items group bugs, an inline-edit
   commit addressing the current cache while the screen is frozen)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 13:26:29 -07:00
Edward Langley 70025e2e33 chore: close PR #98's three tickets
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
improvise-lltt (P1), improvise-e5pf and improvise-ac2z all landed in #98 and
were left open — I closed #96's tickets on merge and not #98's. Each verified
against merged main rather than the PR body: App::view_mut() is gone and
view_mut_of is present; resolve::changed_mode is gone and settled_mode is in
improvise-protocol; grid_in::rederived_for is present.

Second occurrence of this gap. The first was 26 tickets at once, and the cause
is the same: .beads is orchestrator-only, so an agent cannot close what it
fixed, and closing is a separate step I have to remember after every merge.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 13:15:09 -07:00
Edward Langley 26456c698e kb: editing a shell script corrupts the instances already running it
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
bash reads a script incrementally rather than loading it whole, so editing a
file while an instance executes it shifts the byte offsets underneath that
instance. Two background pr-reviews watchers, started ten minutes earlier and
sleeping in their poll loops, both died with 'syntax error near unexpected
token do' the moment I appended a paragraph to the usage text. bash -n
confirmed the file itself was fine.

The failure is in the RUNNING instance, not the file, so it is invisible to
every check you would think to run afterwards. And worse than a crash here:
each watcher exited having printed only the EARLIER review, so the wait it
existed to perform silently did not happen. I re-ran both cleanly before
merging rather than counting them.

Closes improvise-hsoe, improvise-4dpj and improvise-26dm from PR #96.
Backlog: 32 open.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 11:04:36 -07:00
Edward Langley c73df4b5a1 kb: a pipe discards the exit code you meant to read
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
Fourth occurrence in one campaign, and this one was in a tool I wrote TO BE
the reliable answer. scripts/pr-reviews --wait correctly exited 1 on a
timeout, and my invocation ended in '| tail -20; echo', so the harness
reported 0 — a review window that had EXPIRED read as a review that had
ARRIVED, which is the dangerous direction.

The earlier three: pr-watch reading tr's status through a pipe; a probe
reporting EXIT=0 from a checker that had exited 1; and PIPESTATUS in zsh,
where the array is lowercase pipestatus — the two shells differ, which is its
own trap.

The script's usage now says not to pipe it.

Closes improvise-711n (,.2f yielded zero decimals — the spelling our own docs
show) and improvise-x1ns (the preflight undercount ChatGPT Codex found on a
PR I had already merged unread).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 10:56:36 -07:00
Edward Langley ea206bf8de docs: read the reviews before merging; authorship will not identify them
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
I merged twenty PRs this campaign without reading their REVIEWS. CI green plus
a dispatched adversarial agent felt like the whole gate and was not. Two
ChatGPT Codex reviews were sitting on merged PRs; both were correct.

improvise-x1ns (P2, filed, live on main): encoded_width's categorical branch
counts only distinct PRESENT values, while build_categorical maps every
missing cell to MISSING_CAT and emits an additional one-hot. A forced category
with N present values plus one missing coordinate passes the preflight as N
and materializes N+1 — caught only by the later exact check, which is the
allocation the preflight exists to prevent.

The keeper from that review: 'bounded by the later exact check' is not a
defence, because the exact check runs AFTER the allocation. It bounds the
error message, not the cost. Our own review had seen the shape and reasoned it
away on exactly that ground.

The PR #91 review described round 1 and round 2 fixed it — verified with a
probe rather than assumed, both directions. But the regression it asked for
does not exist, so improvise-4dpj now carries it.

Three things make a Codex review easy to miss, all now in AGENTS.md: it
arrives as a review rather than a comment; it posts under the owner's account,
the same one our agents use, so authorship cannot distinguish it — the tell is
the TRAILING '_Automated review by ChatGPT Codex_' where ours OPEN with
'_Posted by Claude_'; and it may target an earlier head, so a finding can be
already fixed or still live and you must check which.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 10:15:30 -07:00
Edward Langley d72d7558d3 kb: a check that returns empty for the wrong reason passes
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
Two doctrines, both about checks that cannot fail, both found this round.

This repo configures diff.external = difftastic, which prints side-by-side
output carrying no unified-diff markers — so 'git diff | grep "^-"' matches
nothing regardless of content. An agent verifying that a merge dropped nothing
read three consecutive empty outputs as three clean bills. I reproduced it: on
a file with one real deletion, git diff | grep -c '^-' gives 0 and
--no-ext-diff gives 1. Use --no-ext-diff, or --numstat/--name-only which are
unaffected.

That is the sharpest form of check_the_checker in the campaign: an empty
result is the one outcome nobody investigates.

And the CI diagnosis, recorded with my own error in it. A pull_request
workflow builds refs/pull/N/merge; a CONFLICTING PR has none, so no run is
created and it looks identical to a dropped webhook. 34 minutes of polling, a
close/reopen and an empty commit produced nothing; one merge produced a run in
seconds. Ask gh pr view --json mergeable first.

Filed improvise-hsoe: --check-evidence cannot see a duplicate heading, and
three exist on main — verified. Both copies pass, because a duplicate names a
running test just as well, and one of them is stale by construction.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 05:41:31 -07:00
Edward Langley 99ec32d6f3 kb: comparing a function against itself tests nothing
Two facts from the adversarial review of PR #92, both about checks that
cannot fail.

improvise-jmjz guarded its width half with col_widths == compute_col_widths,
but compute_col_widths IS grid_body with an empty window — the same function
twice — so windowing degrades both sides identically and the assertion cannot
fail. Injecting the fault left 1476 tests passing. A consolidation is exactly
when such a check gets written, because the second implementation has just
been deleted.

And a negative result is only as good as the setup that produced it: the
none_cats hazard was reported 'argued and unobserved' from a fixture whose
stated condition was absent, because add_category defaults a category to
Column and nothing moved it. Setting the axis explicitly failed the property
on the first run and found improvise-ac2z.

Filed from the same review: improvise-711n (parse_number_format yields zero
decimals for the ,.2f spelling our own docs show, P2) and improvise-swre
(memoise the grid across frames). improvise-jmjz closed on its own criterion;
improvise-6nsd lowered to P4 with the severity note.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 05:11:52 -07:00
Edward Langley fe816c9734 kb: a mitigation that names the wrong file is not a mitigation
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 #91 deferred a wire-level gap because 'keys.rs emits no ChangeMode at
all'. True, and irrelevant: keys.rs holds only BrowserKey, and the live
browser resolver is improvise_protocol::resolve, which emits
ChangeMode(AppMode::Normal) at five sites. The browser front end kept the very
bug the PR fixed for the TUI, and the suite was green over a divergence the PR
created.

I copied that false clause straight into improvise-e5pf when I filed it.
Corrected, and raised to P2: it is live, not latent.

The rule: before writing 'X does not do Y' as the reason a gap may be
deferred, grep for Y rather than for X. The claim that matters is about the
behaviour, and the file you happen to have open is not the only place it lives.

Also records that improvise-sihr's prose defended its staleness with an
example that works for a different reason — toggle-records-mode overwrites
normal_mode()'s answer in both directions, so the staleness is neutralised
there rather than exercised, and the case that would have tested it regressed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 04:15:16 -07:00
Edward Langley 27399b6a28 kb+docs: prose that calls a change free is a claim, and it is checkable
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
Wave K's own prose said improvise-zv8t cost nothing — "no document that
fitted before stops fitting" — reasoning that a tree splitting on a numeric
category was refused as an artefact anyway. False: the refusal is conditioned
on used_features, so a fit that never split on the column SUCCEEDED, and the
wide columns are exactly the ones a fit has least reason to split on. Measured
with a throwaway probe on both sides. The sentence sat one paragraph below the
"permanent refusal" claim the previous wave had just corrected, in the same
section, green on either reading.

So prose_that_calls_something_permanent_forecloses_the_ticket has a sibling. A
cost claim is as checkable as a permanence claim and is checked the same way:
construct the document the claim says does not exist. Filed improvise-e8no for
the cost, with a note not to close it by making the forcing conditional on
cardinality — that is inference by another name.

The branch's own adversarial round found a bug the branch introduced: forcing
by column NAME while budgeting by column INDEX, and a document may legally
name a category and a measure the same thing. Repaired as a data dependency
rather than a moved line, so the injection is a compile error.

GridLayout::new has now caused FOUR bugs. improvise-iot6 was the last
production instance — every remaining call site is test code, which I verified
rather than took on report: two of them sit inside cfg(test) blocks well below
the module head and neither was named in the hand-back.

Suite re-measured here: 1464 over 35 binaries, 1 ignored.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 04:10:12 -07:00
Edward Langley 3e3ebec25a kb+docs: an injection that does not fail names an untested path
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
Five facts from Wave J. The one worth reading is the first: check_the_checker
is written as "inject the fault and watch it fail", and the case where it
PASSES is the more informative result, because it is evidence about the test
rather than about the code. On improvise-sihr, forcing
ReturnToNormalUnlessMoved alone back to Normal left the characterization test
green — which is how the untested path was found. An empty colon line takes
ExecuteCommand's is_empty branch and settles through ChangeMode, so the effect
settling every colon line that actually runs had no test. There are two tests
rather than one because of it.

Also records why ChangeMode could hide the bug at all: it was a simple_effect!,
which declares a one-field newtype writing one place, so there was nowhere for
a rule to live and the exit mode had to be a constant in the keymap and in
each commit command. Gotcha 16 already warns the macro's kind argument must be
mandatory; this is a second cost of the same shape.

And that improvise-9c9o's ticket pre-diagnosed its own fix as a protocol
change, and was wrong — the basis is App's own bookkeeping, so it was achieved
by moving where the re-base happens. A pre-diagnosis is a hypothesis wearing
the authority of a decision.

Inventory: three protocol files were absent entirely — help.rs (925),
client.rs (255) and resolve.rs, which at 2477 lines and 46 tests is the
largest file in the crate.

Filed improvise-e5pf: Command::ChangeMode(Normal) is on the wire and
reduce_view folds it without the records resolution. Latent — keys.rs emits no
ChangeMode and a view-half command never reaches the host's slice, both
verified rather than assumed — and closeable only by enriching the projection.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-21 04:06:44 -07:00
Edward Langley ada16d211a kb+docs: the Pages artifact is reaped by a foreign successful deploy
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
improvise-864a diagnosed over all 100 push-to-main runs rather than the three
the ticket named — and the three-run framing was mine, a sampling artefact
that made a two-day, sixteen-failure pattern look like a concurrency race
between queued deploys. 12/12 artifact-not-found failures had another run's
SUCCESSFUL deploy complete inside their own upload-to-deploy window, against
2/56 successes.

The decisive observation was a negative one already sitting in a log: a run
seeing its own harness-serve and wasm-bundles but not its own github-pages.
Same run, same token, same call, same retention — which kills flakiness,
eventual consistency, retention, token scope and a v3/v4 mismatch together.

One clause of the ticket's own correction is falsified: PR #46's guard aimed
at the right quantity for the wrong reason. It still must not ship, because
the association is not a mechanism and one run survived a foreign deploy in
its own window.

improvise-ijql closed additive. The author argued against the precedent I
pointed it at and was right: a provenance line qualifies an answer the run
gave, a disclaimer qualifies one it did not, and exit 0 is what CI branches
on. The rule is now stated over the exit code.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-20 22:24:32 -07:00
Edward Langley 7df602de18 docs: no effect calls reset_cursor now, and two beads from the #78 review
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
Gotcha 24 rewritten. Since improvise-ni6k the cursor is invalidated by
OBSERVING the grid's frame in apply_effects, inside the loop; no effect calls
reset_cursor at all, where this paragraph said thirteen did two days ago and
two before that. Total over EffectKind::Model(_) by construction rather than
by a maintained list — but totality is conditional on classification, and
nothing makes classification total.

Records the two-arm asymmetry and why it exists: narrowing the CellData arm
to one view measured as free and silently lost a multi-client invalidation.
The absolute is stated beside the ratio.

Two beads filed from the re-review, neither blocking the merge:

improvise-iot6 (P2) — render_csv builds GridLayout::new, so CSV export writes
rows the view prunes. FOURTH instance of that trap and the first in
production a user can see; reachable from :export and the CLI, and none of
export.rs's three tests mentions pruning, which is why it has been shipping.

improvise-9c9o (P2) — a geometry effect immediately after a mid-batch
SwitchView skips the check entirely. Passes on pre-PR main and on round 1,
fails at the merged head. Under-reporting, which gotcha 35 says is the
expensive direction.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-20 22:17:06 -07:00
Edward Langley 862bd0371a kb+docs: a leaf is not an identity, and the CI graph is a gate
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
Facts from PR #83, including two that replace text I had not yet applied —
the earlier phrasing said evidence names are "leaf names", which the merged
work makes wrong.

The finding worth carrying is one the review did not contain and the author
found while fixing it: NEITHER HALF SUFFICES. Refusing an ambiguous leaf does
not survive a rename — rename one of a colliding pair and the leaf is unique
again and resolves silently to the survivor. Qualification is the fix; the
refusal is only what forces someone to write it. Verified here independently:
un-qualifying the cited heading exits 1 naming both candidates, restoring it
exits 0.

improvise-ijql is NOT closed. The docs half is done, but line 1010 still
early-returns on the flag, so --check-evidence still selects rather than adds
and still says nothing about the cap it skipped. Recorded on the ticket with
the two candidate shapes.

Filed improvise-sxsf: `cargo test -- --list` does not name the binary, so two
crates sharing a module path remain indistinguishable. Not reachable today,
not guarded, and "verified latent" ages the moment anyone adds a crate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-20 21:52:02 -07:00
Edward Langley 38a270ac70 docs: the door is Sessions::apply_checked, and close 26 landed tickets
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
improvise-ahdf. Gotchas 36 and 43 named Sessions::apply as the production
door. It is not pub, it delegates to apply_checked after Checked::against,
and its only call sites are tests — Host calls apply_checked. Verified by
reading the signatures rather than the prose: apply at project.rs:878 has no
pub, apply_checked at :887 does. design-principles.md §5 already said
apply_checked, so the repo map was the stale copy of a fact stated twice.

Two of the four remaining mentions were live claims and are corrected; one is
historical ("demonstrated against ... before removal") and stands, and one is
the new sentence saying apply is not pub.

Also closes 26 tickets whose fixes are in merged main, each verified against
the code or against an evidence entry rather than against a PR body. Left
open deliberately: h074 (reported half-done), s17o (a decision in #78's
ground), mcq4 (fixed to 1.9x, residual documented), lltt (P1, detector only).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-20 21:44:32 -07:00
Edward Langley 95839fce43 docs: gotcha 49 for the origin check, and the inventory is a dated snapshot
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
Gotcha 49 records improvise-kc7n: a websocket handshake is exempt from the
same-origin policy, so no network control can see cross-site hijacking — an
IP allow-list, a private network and loopback binding all answer "may this
client reach the endpoint" and the honest answer is yes. Loopback is the
least protected case, not the safest. Records why all three arms are decided
rather than defaulted, and that none of it is authentication.

The File Inventory line counts were audited: 26 of 61 resolvable entries had
drifted past 10%, several by a third. Refreshed, and relabelled as a dated
snapshot with the method, because false precision in a carefully-checked
document is worse than an obvious estimate. Two traps found while doing it,
both recorded: a path-walking refresh resolves a bare name like lib.rs
against the first matching crate and rewrites the wrong number, and the
ws-server/ entries use a shorthand prefix no such walk resolves at all.

The code-review skill's gate list now runs BOTH spellings of
check-comment-runs.py. The flag selects rather than adds, so --check-evidence
never runs the comment cap and does not say so; three separate agents hit it
in one campaign (improvise-ijql).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-20 21:36:29 -07:00
Edward Langley 1351ecc9b8 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
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
2026-09-20 21:23:06 -07:00
Edward Langley 381a2f55d3 docs: the two thirteens differ in both directions, and my own awk proved why
Verifying the correction before merging it found the claim true but
understated. The reset_cursor set and the LayoutGeometry set are both
thirteen and differ THREE EACH WAY: CreateView, DeleteView and
SetNumberFormat declare the kind and never reset; AddItem, AddItemInGroup
and RemoveItem reset while declaring CellData, because adding or removing
an item renumbers the grid even though the change is data.

The naive awk over LayoutGeometry reported fourteen, picking up
HelpPageSet — the exact artefact this document already warns about two
paragraphs away, walked into while writing the correction. That warning
is now attached to the derivation it applies to.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-20 21:17:31 -07:00
Edward Langley 2afbf37b67 docs: correct two stale gotchas, and record the N-1-guarded-edits shape
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
repo-map gotcha 24 named TransposeAxes and CycleAxis as the only effects
calling reset_cursor, and listed nine others as renumbering the grid without
resetting. improvise-9mo9 closed that the day before: all of them reset,
thirteen in total, SetPageSelection conditionally. The paragraph named as
absent the exact set that was by then present, so it read as a survey of
outstanding work. Re-derived by brace-matching impl Effect blocks, and the
derivation is published beside the list so the next reader can re-run it
rather than trust it.

gotcha 44's group_of sentence said "nearest preceding header ... changing
that means changing AxisEntry and is filed, not smuggled in". improvise-gd83
landed that change in PR #77: AxisEntry::GroupEnd exists and group_of answers
membership. Names the two that are still open beside it, h0iv and 1wl0.

Three doctrines added. The one worth the space is
name_the_test_that_fails_when_only_this_edit_is_reverted: three independent
reviews in one wave found the same shape, a repair of N edits where N-1 are
guarded and the last carries a careful comment instead of a test — and the
unguarded edit is reliably the one the author understood best.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-20 21:11:56 -07:00
Edward Langley d2a54ac320 kb: restore six doctrines a hard reset discarded, and record how
Consolidates four doc branches and restores what resyncing lost.

I wrote doctrines to kb.pl on local main, pushed each as a branch, then ran
`git reset --hard gh/main` twice to resync -- discarding six clauses that
existed only in the unmerged local commits. Nothing failed: kb_consistent
passed on the reduced file, the counts simply read lower, and the loss was
found only by grepping for clause names I happened to remember writing.

That is the same shape as everything else this wave found. A count that looks
plausible is not evidence, and the check that would have caught it -- diff the
clause NAMES, not the total -- is the one this repo already applies to tests
after a merge.

doctrine(a_hard_reset_discards_knowledge_written_to_the_working_branch) states
the two rules: write a fact once, on the branch that will carry it to main, not
on a local main that is going to be resynced; and after any reset or force-move
of a branch holding knowledge, re-count and diff clause names.

Restored: every_wave_agent_gets_its_own_worktree,
the_orchestrator_delegates_substantial_work,
a_message_assertion_is_a_uniqueness_claim_about_the_whole_vocabulary,
run_the_gate_ci_runs,
an_observation_correct_about_what_changed_can_be_wrong_about_when_it_is_read,
a_siblings_unmerged_pr_is_invisible_to_bd_search.

Also carries: the wave skill, the Copilot-gate correction to AGENTS.md, the
help evidence rename, and the code-review skill's missing -D warnings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-20 19:40:33 -07:00
Edward Langley debad21556 docs: run the gate CI runs, and bindings.rs is run
Two one-line corrections the wave's last review surfaced, both about a claim
being stated in more than one place.

.claude/skills/code-review/SKILL.md told every reviewer and every wave agent to
run `cargo clippy --workspace --all-targets` with no `-D warnings`. Clippy exits
0 on warnings, so the committed local gate was green on exactly the input CI is
red on. This is not one person's shell mistake, it is the instruction: a
reviewer following the skill as written would report clean and be wrong, which
happened on PR #71. Also adds --no-fail-fast, since fail-fast hides blast radius.

README.md was a sixth copy of "bindings.rs is never run", which PR #70 corrected
in five places -- its grep missed README, and PR #72 then rewrote the sentence
four lines above and carried the wrong half forward. Neither PR is at fault
individually; it is an interaction between two branches, and it is the exact
failure the corrected fact is a monument to.

Plus doctrine(a_weak_check_and_a_strong_one_agree_until_the_defect): five
instances this wave, one mistake -- a check written against the failure you
imagined rather than the outcome the user sees. The weak and strong checks agree
on every input anyone tried and diverge only on the input that is the defect.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-20 17:24:17 -07:00
Edward Langley 7fd57c06b3 docs: say what to do; attribute what agents post
Two user rulings.

Documentation should not spend itself on history -- that is bloat. Prose docs
now lead with the rule and keep only the line that stops it looking arbitrary;
the worked examples and the how-we-found-it move into doctrine/2 text, which is
what that predicate is for and where a reader goes deliberately rather than
while looking for a command. Trimmed: both skills, context/code/kb-tool.md, and
the kb paragraph in AGENTS.md.

Anything an agent posts to GitHub goes out under the owner's account, so every
comment, review and issue body now opens with a line naming the model and that
an agent wrote it. A PR body's generated-with footer already did this; comments
carried nothing, and an unattributed one reads as his own words to every reader
-- including a reviewer deciding how much weight to give it. The reply on PR #68
has been amended in place.

improvise-xfsb files the structural fix: a GitHub App or machine user so agents
post under their own identity. An attribution line is a convention an agent can
forget; a separate identity cannot be.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
2026-09-20 16:04:33 -07:00