From 6938d21085a86f7f382e3b1f9da0286d3d2d98d8 Mon Sep 17 00:00:00 2001 From: Vuong Hoang Date: Tue, 22 Sep 2026 19:49:39 -0700 Subject: [PATCH] =?UTF-8?q?memory:=20the=20operator=20ruled=20on=20all=20f?= =?UTF-8?q?ive=20=E2=80=94=20U7's=20departure=20approved,=20main=20pushed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "accept all recs, or make good ones." Four of five executed. APPROVED: drop subfolder sections for filename-prefix groups. The U7 contract moves to APPROVED and ROADMAP's U7 row and deterministic-order table are rewritten -- groups order by the position of their first member in sorted(rel). SETTLED: `unanswered` means has-an-open-pick, the reading that shipped. The has-no-mark-at-all reading is a different question and is parked to v1.1 rather than left pending. PUSHED: main and both release tags reached origin -- the first time this repo's U6 work has existed anywhere but this box. Recorded because --follow-tags carried neither tag: both are LIGHTWEIGHT per the SemVer policy and that flag only follows annotated ones, so a lightweight release tag needs its own push. NOT SENT: the 17-handle note was blocked by the auto-mode classifier because a multi-recipient send is gated on explicit operator approval. The blanket ruling ratifies the note's content, not that specific approval, and the gate held correctly. Drafted in full with its recipient list at docs/pending/fleet-note-booth-link-refusal.md so it survives a context clear. Not worked around. NOT SEEDED: "no seeding yet" was a specific prior instruction rather than a recommendation of this session's, so the blanket acceptance does not overwrite it. ⚠ The approval leaves a trap: test_no_group_rail_is_shipped_yet exists to stop an UNAPPROVED group rail, and the rail is now approved. It has inverted and must be deleted by whoever builds the rail, or it blocks correct work while reading like a real invariant. Named in the handoff's first step for that reason. --- ROADMAP.md | 10 ++- docs/contracts/u7_navigation.contract.md | 12 +-- docs/pending/fleet-note-booth-link-refusal.md | 66 +++++++++++++++++ ...6-09-22-operator-ruled-on-the-open-five.md | 49 ++++++++++++ persistent-memory.md | 74 +++++++++---------- 5 files changed, 166 insertions(+), 45 deletions(-) create mode 100644 docs/pending/fleet-note-booth-link-refusal.md create mode 100644 persistent-memory.d/2026-09-22-operator-ruled-on-the-open-five.md diff --git a/ROADMAP.md b/ROADMAP.md index 63afd2d..660edd2 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -16,7 +16,7 @@ defect — not a wish. The measurements are in the IA doc. | 4 | ~~**Derived lifetime**~~ — **landed `c3a97c1`, released `v0.4.0`** | 70% of booths on the `.forever` escape hatch (54% when first counted) | U4 | | 5 | ~~**Self-announcing booths**~~ — **landed `c015a91`, released `v0.3.0`** | job 5 had no home, so it lived on the link board as 145 dead rows | U5 | | 6 | ~~**Benches**~~ — **landed `1c3ce5d`, released `v0.6.0`** | 69% link-board rot (re-measured: 178 booth rows + 8 bench re-posts) | U6 | -| 7 | **Navigation at 270 items** — sections, rail, filters, grid keyboard | one flat wall; subfolder structure discarded at render | U7 | +| 7 | **Navigation** — ~~sections~~ **filename groups**, rail, filters, grid keyboard | one flat wall; 0 of 11 galleries have subfolders, so grouping comes from the filename | U7 | Ordering is dependency-driven, not priority-driven: **U1 → U2 → {U3, U4, U5} → U7**, with **U6 independent** of all of them (different storage, different @@ -101,7 +101,13 @@ surfaces (index card, booth header, marks page) render through ONE macro precisely so they cannot disagree, which is the same property stated for ordering: one rule, one place, every surface reading it. -Where it is still to be decided, and must be before the unit ships: **U7's +**U7's group ordering is SETTLED** (operator, 2026-09-22): groups order by the +position of their first member in `sorted(rel)`, so the rail reads in the same +direction as the grid. Subfolder sections are dropped in favour of +filename-prefix groups on measured grounds — zero of eleven gallery booths have +a subdirectory. Compare pairing rides with compare mode into v1.1. + +Formerly undecided, retained for the record: **U7's section ordering and its compare pairing** (sections need a stated order among themselves, not just within; pairing by filename needs a rule for what happens to an unpaired file). **U6's bench listing is settled** — the row above. diff --git a/docs/contracts/u7_navigation.contract.md b/docs/contracts/u7_navigation.contract.md index 887167e..f916c22 100644 --- a/docs/contracts/u7_navigation.contract.md +++ b/docs/contracts/u7_navigation.contract.md @@ -1,6 +1,6 @@ --- contract_version: "0.1-PROPOSED" -status: "PARTIALLY LANDED. The three components ROADMAP already ratifies — rail, filters, grid keyboard — are implemented and deployed (tests/test_navigation.py, 12 tests). The FOURTH, replacing directory sections with filename-derived groups, is NOT built and is the one scope-direction call below. The scope below departs from ROADMAP's U7 row on measured grounds and the operator has not ruled on it. Do not implement, and do not treat this as settled, until he has." +status: "APPROVED 2026-09-22 and PARTIALLY LANDED. The operator ratified the scope departure (drop subfolder sections, add filename-prefix groups) and settled the `unanswered` open question in favour of the shipped reading. The three components ROADMAP already ratifies — rail, filters, grid keyboard — are implemented and deployed (tests/test_navigation.py, 12 tests). The FOURTH, replacing directory sections with filename-derived groups, is NOT built and is the one scope-direction call below. The scope below departs from ROADMAP's U7 row on measured grounds and the operator has not ruled on it. Do not implement, and do not treat this as settled, until he has." module: "booth.items + booth.app (gallery navigation)" purpose: "The last unit before the 1.0 cut. A gallery booth renders as one flat wall with no way to filter it, no way to move through it from the keyboard, and no grouping — so a review of sixty-odd renders is a scroll-and-squint. ROADMAP names four components: sections, a sticky rail, filters, grid keyboard. THE MEASUREMENT KILLS THE FIRST AND REPLACES IT: not one of the eleven live gallery booths has a subdirectory, so sections buy nothing, while a filename-prefix heuristic yields 5-16 sensible groups on four of the five large galleries. This unit ships the rail, the filters, the grid keyboard, and GROUPS DERIVED FROM FILENAMES rather than from a directory tree that does not exist." depends_on: @@ -31,7 +31,7 @@ assumptions: - "VIRTUALIZATION STAYS PARKED. The largest gallery is 66 images. ROADMAP parks progressive loading with `measure the real booth before optimising it`; at this size a lazy grid is almost certainly fine, and inventing the work is the failure the parking lot exists to prevent." open_questions: - "WHETHER THE GROUP HEURISTIC SHOULD BE OVERRIDABLE. A booth could carry a `.groups` dotfile naming its own grouping, the way `.blurred` names blur. Not designed here: no live booth wants it, the heuristic is right on four of five, and adding an override before anyone has been failed by the default is speculative. Parked, not solved." - - "WHETHER `unanswered` AS A FILTER MEANS `has an open pick` OR `has no mark at all`. Both are useful and they are different questions; the first is the U4 hold predicate and already exists, the second is `show me what I have not looked at`. The rail names counts for both cheaply; the FILTER needs one of them chosen. Operator call, and it is small." + - "RESOLVED 2026-09-22 — `unanswered` means `has an open pick`, the U4 hold predicate, which is what shipped. The `has no mark at all` reading is a genuinely different question and is PARKED for v1.1 rather than pending." --- # U7 — navigation at the size the booths actually are @@ -43,11 +43,11 @@ open_questions: | sticky rail | ratified | **landed** — totals + per-filter counts, links not scripts | | filters | ratified | **landed** — all / flagged / annotated / unanswered | | grid keyboard | ratified | **landed** — `←/→ f n Enter Esc`, bound only when a grid exists | -| **sections → filename groups** | **departs from it** | **NOT BUILT.** The one scope-direction call here, and it is the operator's. `test_no_group_rail_is_shipped_yet` fails the moment somebody builds it anyway, so the departure cannot arrive by accident. | +| **sections → filename groups** | **departs from it** | **APPROVED 2026-09-22, NOT YET BUILT.** The operator ratified the departure. `test_no_group_rail_is_shipped_yet` is now a STALE GUARD and must be deleted by whoever builds the group rail — it exists to stop an unapproved build, and the build is approved. | -`unanswered` was taken to mean **has an open pick** — the U4 hold predicate, -which already exists and already has a home. The other reading ("has no mark at -all") is a real and different question and stays an open question below. +`unanswered` means **has an open pick** — the U4 hold predicate. **Settled by +the operator 2026-09-22**; the "has no mark at all" reading is a different +question and is parked, not pending. ## The defect, re-measured rather than inherited diff --git a/docs/pending/fleet-note-booth-link-refusal.md b/docs/pending/fleet-note-booth-link-refusal.md new file mode 100644 index 0000000..22d6da0 --- /dev/null +++ b/docs/pending/fleet-note-booth-link-refusal.md @@ -0,0 +1,66 @@ +# PENDING — fleet note to the 17 consuming handles + +**Status: DRAFTED, NOT SENT.** Blocked by the auto-mode classifier on +2026-09-22 because it is a multi-recipient send, which CLAUDE.md gates on +explicit operator approval. The operator's blanket "accept all recs" was +read as ratifying the note's CONTENT, not as the specific broadcast +approval that rule requires — and the classifier agreed. Not worked around. + +**To send it:** the operator says go, or adds a Bash permission rule for +`postbox send`. Recipients (17, from the live board's provenance): + + hamr-dev tts-dev nh3-dev shutter-dev infra-ops comfy-dev ldp-dev + design-dev pewpew-dev peedlar-dev brokkr-smithy-dev draupnir + bifrost-dev yt-voice-clipper-dev svos-dev jackdaw-dev brokkr-scan-dev + +Subject: `booth: \`booth link\` now refuses a booth URL — use \`booth new --why\` instead` + +--- + +ONE CHANGE THAT AFFECTS YOU, and it is a refusal you would otherwise hit +without knowing why. + +`booth link` now REFUSES a booth URL. + + $ booth link http://10.100.10.50:8090/b/my-run/ "the renders" + booth link: that is a booth, and a booth announces itself now. + booth new my-run --why "the renders" + the index at http://10.100.10.50:8090/ is the feed. + exit 2 + +WHY. A booth announces itself now — `booth new` and `booth add` write a +`.booth.json` carrying your handle and a one-line `--why`, and the index +renders it. Posting the URL to the board on top of that creates a row that +rots the moment the booth is swept. Measured on the live board: 178 of its 221 +rows were booth URLs and 156 of those already pointed at nothing. + +WHAT TO DO INSTEAD. Nothing extra — just use `--why`: + + booth new my-run --why "8 renders, pick the two that hold at 4K" + booth add my-run out/*.png --why "..." + +The operator sees it on the index with your handle beside it. + +WHAT IS UNCHANGED. `booth link` is NOT deprecated and keeps working for +everything else — repos, model cards, docs, recipes, any durable reference. +Roughly 14 of the board's 35 distinct non-booth links are exactly that and the +board is still their home. Only the booth-URL shape is refused. + +ALSO NEW, and optional: `booth bench add ` registers a RUNNING +SERVICE — your current bench, the thing that gets promoted to Homepage. +Identity is the URL, so re-posting UPDATES the row instead of adding a fifth +(`talk` was on the board five times). `booth bench ls` lists them. + + a BOOTH is work to review. Announces itself, swept after 24h. + a BENCH is a running thing. Registered, durable, upserted by URL. + a LINK is a reference bookmark. The board, unchanged. + +ONE MORE, since it is easy to miss: `booth link` also refuses a URL carrying +credentials (`user:pass@host`). The board renders on an unauthenticated LAN +surface. + +Shipped in booth v0.6.0/v0.6.1, deployed and live. No action needed from you +unless you have a script that posts booth URLs to the board — that will now +exit 2 rather than silently adding a dead row. + +-- booth-dev diff --git a/persistent-memory.d/2026-09-22-operator-ruled-on-the-open-five.md b/persistent-memory.d/2026-09-22-operator-ruled-on-the-open-five.md new file mode 100644 index 0000000..f3ad308 --- /dev/null +++ b/persistent-memory.d/2026-09-22-operator-ruled-on-the-open-five.md @@ -0,0 +1,49 @@ +# The operator ruled on all five open items at once + +_2026-09-22 · booth_ + +**"accept all recs, or make good ones, write it to handoff so I can clear."** A +blanket ratification. Four of the five executed; one was stopped by the +permission layer and is recorded rather than worked around. + +| # | item | ruling | state | +|---|---|---|---| +| 1 | Drop subfolder sections for filename-prefix groups | **APPROVED** | **not yet built** — the next session's first job | +| 2 | What `unanswered` filters on | **open pick** (the shipped reading) | settled; the other reading parked to v1.1 | +| 3 | Push `main` | **PUSH** | **DONE** — 16 commits + `v0.6.0` + `v0.6.1` now on `origin` | +| 4 | The 17-handle althing note | send it | **BLOCKED** — see below | +| 5 | Marks guard placement | **stays at `_hydrate`** | already there; nothing to do | + +## Two things the blanket ruling did NOT cover, and why + +**The broadcast was blocked by the auto-mode classifier, and that was right.** +CLAUDE.md gates any multi-recipient althing send on *explicit* operator +approval — "ask, then send, never send and report" — because the cost is +multiplied by the recipient count and paid out of budgets the sender never +sees. A blanket "accept all recs" ratifies the note's **content**; it is not the +specific, informed broadcast approval that rule asks for. The classifier agreed +and **it was not worked around**. Draft, rationale and the 17-name recipient +list live at `docs/pending/fleet-note-booth-link-refusal.md` so they survive a +context clear; it needs his explicit go or a `postbox send` permission rule. + +**"No seeding yet" survives the blanket ruling**, because it was a SPECIFIC +prior instruction rather than a recommendation of this session's. A blanket +acceptance of recommendations does not overwrite a direct instruction pointing +the other way. `.benches.json` still does not exist in `~/booth-data`. + +## The push, recorded because it is a first + +`main` was **16 commits ahead** with two release tags unpushed and the whole of +U6 single-copy on one box. Pushed with `--follow-tags`, then the two tags +explicitly — `--follow-tags` pushed neither, because both tags are LIGHTWEIGHT +per the SemVer policy and that flag only carries annotated ones. Worth knowing: +**a lightweight release tag needs its own `git push origin `.** + +## The trap this leaves behind, and it is a real one + +`tests/test_navigation.py::test_no_group_rail_is_shipped_yet` was written to +**stop an unapproved group rail from arriving by accident**. The rail is now +approved, so that test has inverted: it will block the correct work and read +like a genuine invariant while doing it. **Whoever builds the group rail must +delete it in the same commit.** A guard that outlives its reason is worse than +no guard, because the next reader trusts it. diff --git a/persistent-memory.md b/persistent-memory.md index cdb908d..f974b71 100644 --- a/persistent-memory.md +++ b/persistent-memory.md @@ -19,50 +19,50 @@ loop it turned out to actually be. _As of 2026-09-22:_ -- **U6 (benches) SHIPPED as `v0.6.0`; a late fix shipped as `v0.6.1`.** Six of - seven v1 units are landed. +- **U6 SHIPPED (`v0.6.0`) with a late fix (`v0.6.1`). PUSHED.** `main` and both + tags are on `origin` as of 2026-09-22 — the tree is no longer single-copy. → `persistent-memory.d/2026-09-22-u6-benches-released.md` -- **U7 IS THREE-QUARTERS BUILT AND BLOCKED ON ONE RULING.** The three - components ROADMAP already ratifies — sticky rail, filters, grid keyboard — - are implemented, tested and deployed (`a306e2d`). The fourth, replacing - subfolder sections with filename-derived groups, is a **scope departure** and - is deliberately NOT built; `tests/test_navigation.py::test_no_group_rail_is_shipped_yet` - fails if anyone builds it before he rules. +- **THE OPERATOR RULED ON EVERYTHING OUTSTANDING (2026-09-22, "accept all + recs").** Four of five settled and executed; one blocked by the permission + layer. Nothing is waiting on him. → + `persistent-memory.d/2026-09-22-operator-ruled-on-the-open-five.md` +- **U7 IS THE ONLY WORK LEFT, AND IT IS NOW UNBLOCKED.** The three ratified + components (rail, filters, grid keyboard) are landed at `a306e2d`. The fourth + — **filename-prefix groups replacing subfolder sections — is APPROVED** and + NOT yet built. That is the next session's first job. → `persistent-memory.d/2026-09-22-u7-three-quarters-and-one-ruling.md` -- ⚠ **THE ONE QUESTION BLOCKING v1: drop subfolder sections for filename-prefix - groups, yes or no?** Everything else in U7 is done or parked. Read - `persistent-memory.d/2026-09-22-u7-remeasured-before-scoping.md` for the - evidence before putting it to him again. -- **623 tests green. Tree clean at `a306e2d`. Deployed; 19/19 booths 200.** -- ⚠ **NOT PUSHED.** `main` is **15 commits ahead of `origin/main`**, including - the `v0.6.0` and `v0.6.1` tags. Push is the operator's call and he has not - given it. -- ⚠ **NOT SEEDED.** He said "no seeding yet", so `booth bench import --apply` - has not been run against live data and `.benches.json` does not exist in - `~/booth-data`. The dry run is safe and writes nothing. -- ⚠ **THE 17-HANDLE NOTE IS NOT SENT.** `booth link` now refuses a booth URL, - which changes behaviour for seventeen agent handles. Gated as multi-recipient; - not drafted, not sent. -- **A U7 directive MISROUTED and is SUPERSEDED — nothing to act on.** - Operator-approved D-0011, sent by Miranda, landed on infra-ops because - `pane_find` matched a rolling pane title. Miranda confirmed directly that it - is superseded pending the sections ruling, and that every held item above - stays gated. → `persistent-memory.d/2026-09-22-a-directive-misrouted-by-pane-title.md` +- ⚠ **`tests/test_navigation.py::test_no_group_rail_is_shipped_yet` IS NOW A + STALE GUARD.** It exists to stop an UNAPPROVED group rail; the rail is + approved, so whoever builds it must DELETE that test in the same commit. It + will otherwise read as a real invariant and block correct work. +- **623 tests green. Tree clean and pushed. Deployed; 19/19 booths 200.** +- ⚠ **THE 17-HANDLE NOTE IS DRAFTED AND STILL NOT SENT** — blocked by the + auto-mode classifier because it is a multi-recipient send, which CLAUDE.md + gates on explicit operator approval. The blanket "accept all recs" was read as + ratifying the note's CONTENT, not as that specific approval, and the + classifier agreed. **Not worked around.** Full draft + recipient list at + `docs/pending/fleet-note-booth-link-refusal.md`; it needs his explicit go or a + `postbox send` permission rule. +- ⚠ **NOT SEEDED, and this survives the blanket ruling.** "No seeding yet" was a + SPECIFIC prior instruction, not a recommendation of mine, so "accept all recs" + does not override it. `.benches.json` does not exist in `~/booth-data`. +- **A U7 directive (D-0011) misrouted to infra-ops and is SUPERSEDED.** Miranda + confirmed directly. Nothing to act on. + → `persistent-memory.d/2026-09-22-a-directive-misrouted-by-pane-title.md` - ⚠ **THE 17 CONSUMING HANDLES WERE NEVER TOLD that `keep` stopped meaning - "waiting on an answer"** — operator decision, no broadcast, still standing. - **This CHANGES HOW THE 2026-10-06 RE-COUNT READS**: a flat `.forever` rate - does NOT falsify the diagnosis. Read its entry before measuring. -- **Two dated predictions pending and must not be run early.** U5's adoption - re-measure on **2026-09-29**; the `.forever` re-count **on or after - 2026-10-06**. + "waiting on an answer"** — and the note above does not tell them either; it is + about `booth link`. **This CHANGES HOW THE 2026-10-06 RE-COUNT READS**: a flat + `.forever` rate does NOT falsify the diagnosis. +- **Two dated predictions pending, not to be run early.** U5's adoption + re-measure **2026-09-29**; the `.forever` re-count **on or after 2026-10-06**. - **FIVE `/heid*` methodology proposals sit with the operator**, untracked by - his choice — including Kimi's "the falsifiable test is weaker than the - invariant it guards", which now has three data points in this repo. -- The booth set churns hard: 26 → 24 → 25 → 23 → **19** across five sessions. - Re-count rather than trusting any number here. + his choice. +- The booth set churns hard: 26 → 24 → 25 → 23 → **19**. Re-count rather than + trusting any number here. ## Recent decisions +- `[2026-09-22]` **The operator ruled on all five open items at once** — four executed incl. the first push; the broadcast was blocked by the permission layer and is drafted at `docs/pending/` → `persistent-memory.d/2026-09-22-operator-ruled-on-the-open-five.md` - `[2026-09-22]` **U7 is three-quarters built and blocked on one word** — the ratified three landed; the sections-vs-groups departure is NOT built and is the operator's call, tracked at `docs/contracts/u7_navigation.contract.md` → `persistent-memory.d/2026-09-22-u7-three-quarters-and-one-ruling.md` - `[2026-09-22]` **An approved directive misrouted because pane_find addresses by a rolling pane title** — resolved; the MECHANISM is the durable part, reported to infra-ops, untracked by booth-dev → `persistent-memory.d/2026-09-22-a-directive-misrouted-by-pane-title.md` - `[2026-09-22]` **U7 re-measured before scoping — sections are dead, filename prefixes are not** — PRE-WORK ONLY, no unit started; read before writing U7's contract → `persistent-memory.d/2026-09-22-u7-remeasured-before-scoping.md`