From e0ab6a9c2210394c25776401bc5700331a43ddb8 Mon Sep 17 00:00:00 2001 From: santoshkumarradha Date: Sat, 24 Oct 2026 13:05:22 -0400 Subject: [PATCH 1/3] Tidy source comments Co-Authored-By: Claude Opus 5.5 --- bench/run.sh | 10 +- cmd/codeaf-census/main.go | 2 +- cmd/codeaf-demo-home/main.go | 16 +- cmd/codeaf/chatv3.go | 2 +- cmd/codeaf/chatv3_exchange.go | 2 +- cmd/codeaf/chatv3_layout.go | 2 +- cmd/codeaf/chatv3_process_test.go | 2 +- cmd/codeaf/chatv3_session_test.go | 2 +- cmd/codeaf/do.go | 2 +- cmd/codeaf/do_machine_gate_test.go | 11 +- cmd/codeaf/engine.go | 2 +- cmd/codeaf/plainwords.go | 2 +- cmd/codeaf/window.go | 2 +- docs/changes/unreleased/source-comments.md | 6 + internal/calllog/calllog.go | 2 +- internal/cellstore/guard_test.go | 4 +- internal/cellstore/rebuild.go | 3 +- internal/cellstore/withheld.go | 2 +- internal/cellsync/liveness.go | 2 +- internal/chatlist/copy.go | 2 +- internal/chatlist/rows.go | 2 +- internal/commentlaw/commentlaw_test.go | 317 +++++++++ internal/config/settings.go | 9 +- internal/ctxbudget/ctxbudget.go | 2 +- internal/devname/devname.go | 2 +- internal/dirwatch/doc.go | 4 +- internal/dirwatch/holder.go | 3 +- internal/dirwatch/stream.go | 5 +- internal/e2e/contracts_e2e_test.go | 12 +- internal/e2e/do_run_engine_e2e_test.go | 14 +- internal/e2e/families_e2e_test.go | 18 +- internal/e2e/harness_test.go | 12 +- internal/e2e/jobpark_e2e_test.go | 4 +- internal/e2e/livekey_test.go | 2 +- internal/e2e/manual_e2e_test.go | 8 +- internal/e2e/manual_wire_test.go | 6 +- internal/e2e/questions_e2e_test.go | 11 +- internal/e2e/remote_test.go | 4 +- internal/e2e/taskcustody_e2e_test.go | 4 +- internal/e2e/tui_e2e_test.go | 5 +- internal/exec/media.go | 2 +- internal/exec/tools.go | 5 +- internal/head/acts.go | 2 +- internal/head/orchestrator_test.go | 2 +- internal/iconlaw/iconlaw_test.go | 12 +- internal/inventory/inventory.go | 2 +- internal/lane/belief_test.go | 2 +- internal/lane/choose_test.go | 2 +- internal/lane/control/hazard_test.go | 4 +- internal/lane/e2e_test.go | 2 +- internal/lane/garbage_test.go | 2 +- internal/lane/rolepatience_test.go | 5 +- internal/lane/watch_test.go | 6 +- internal/orientation/digest.go | 2 +- internal/pair/manual_test.go | 2 +- internal/pair/pair.go | 2 +- internal/plan/contract.go | 3 +- internal/plan/contract_test.go | 4 +- internal/pool/contract/contract.go | 21 +- internal/praf/limits.go | 10 +- internal/preflight/resume.go | 2 +- internal/provider/caching.go | 2 +- internal/provider/dispatch.go | 20 +- internal/provider/e2e_account_real_test.go | 2 +- internal/provider/endpoints.go | 2 +- internal/provider/hedge_test.go | 2 +- internal/provider/neverrepeat_test.go | 9 +- internal/provider/patience.go | 18 +- internal/provider/reasoninghedge_test.go | 2 - internal/provider/streamguard_test.go | 4 +- internal/provider/streamwall_pace_test.go | 2 +- internal/provider/transport.go | 2 +- internal/relay/client.go | 2 +- internal/relayconf/freeze_test.go | 2 +- internal/remote/callclass.go | 2 +- internal/remote/client.go | 16 +- internal/remote/clientlanes.go | 2 +- internal/remote/driver.go | 2 +- internal/remote/questionlane_test.go | 2 +- internal/remote/server.go | 13 +- internal/remote/tasklane_owner_test.go | 13 +- internal/remote/turnlane_test.go | 2 +- internal/remote/wire.go | 8 +- internal/resident/notebook.go | 2 +- internal/secaf/gates/harnesswrapper.go | 2 +- internal/secaf/secaf.go | 6 +- internal/selector/classes.go | 2 +- internal/selector/model.go | 4 +- internal/selector/quality.go | 4 +- internal/selector/replay/main.go | 2 +- internal/seniordev/seniordev.go | 22 +- internal/session/answers_test.go | 2 +- internal/session/asklane.go | 6 +- internal/session/asklane_test.go | 6 +- internal/session/askwait.go | 3 +- internal/session/attach_test.go | 5 +- internal/session/autonomy.go | 9 +- internal/session/beltfacts.go | 37 +- internal/session/delegate_door.go | 26 +- internal/session/delegate_door_test.go | 14 +- internal/session/errand_recovery_test.go | 2 +- internal/session/handlepick.go | 2 +- internal/session/harness_revise_test.go | 2 +- internal/session/jobs.go | 4 +- internal/session/lawregistry_test.go | 8 +- internal/session/loop.go | 4 +- internal/session/memory.go | 10 +- internal/session/personsword_test.go | 5 +- internal/session/placescontext_test.go | 2 +- internal/session/prefixbudget_test.go | 644 +------------------ internal/session/principal_structure_test.go | 2 +- internal/session/program_outcome.go | 50 +- internal/session/programfolder.go | 14 - internal/session/question.go | 4 +- internal/session/questionlifecycle_test.go | 2 +- internal/session/sessionfile.go | 29 +- internal/session/skillcatalog.go | 2 +- internal/session/skillturn_display_test.go | 9 +- internal/session/steer.go | 14 +- internal/session/steerquestion_test.go | 2 +- internal/session/task_carry_test.go | 2 +- internal/session/task_phase_test.go | 2 +- internal/session/task_progress_test.go | 2 +- internal/session/task_run.go | 31 +- internal/session/taskdelta.go | 2 +- internal/session/taskdelta_test.go | 2 +- internal/session/taskname_test.go | 2 +- internal/session/taskoutside.go | 2 +- internal/session/taskoutside_test.go | 2 +- internal/session/taskstands.go | 2 +- internal/session/tools.go | 2 +- internal/session/tools_pdf.go | 2 +- internal/session/tools_tasks.go | 2 +- internal/session/tools_view_test.go | 2 +- internal/session/writeseam.go | 2 +- internal/session/writeseam_test.go | 2 +- internal/splitgate/modes.go | 25 +- internal/store/gate.go | 2 +- internal/store/head_interrupt_test.go | 2 +- internal/store/open_test.go | 2 +- internal/store/sessions_test.go | 4 +- internal/store/store.go | 2 +- internal/subharness/card_test.go | 6 +- internal/syncsetup/history_test.go | 2 +- internal/syncsetup/secrets_test.go | 2 +- internal/syncsetup/twohomes_test.go | 2 +- internal/taxonomy/taxonomy.go | 2 +- internal/telemetry/usage_c3_contract_test.go | 2 +- internal/tui2/tokens/glyph.go | 17 +- internal/tui2/tokens/glyphset.go | 7 +- internal/tui3/app.go | 13 +- internal/tui3/approvalchip.go | 34 +- internal/tui3/approvalchip_test.go | 9 +- internal/tui3/atspaces_test.go | 5 +- internal/tui3/attach.go | 12 +- internal/tui3/bargein_test.go | 7 +- internal/tui3/boxselect_test.go | 5 +- internal/tui3/bundle_test.go | 40 +- internal/tui3/c263_rail_plan_test.go | 5 +- internal/tui3/captionmotion.go | 39 +- internal/tui3/carddoors.go | 14 +- internal/tui3/chatstartquestions_test.go | 2 +- internal/tui3/chattip_test.go | 5 +- internal/tui3/commands.go | 8 +- internal/tui3/contextmodal.go | 14 +- internal/tui3/contextmodal_test.go | 5 - internal/tui3/designlanguage_test.go | 9 +- internal/tui3/detach.go | 2 +- internal/tui3/devices.go | 4 +- internal/tui3/dragselect_test.go | 6 +- internal/tui3/dropkeys.go | 5 +- internal/tui3/editselect.go | 14 +- internal/tui3/editundo.go | 12 +- internal/tui3/effortchip_test.go | 13 +- internal/tui3/effortscope_test.go | 2 +- internal/tui3/failurerow_test.go | 5 - internal/tui3/feed_test.go | 2 +- internal/tui3/firstrun.go | 2 +- internal/tui3/folderact.go | 10 +- internal/tui3/foldercontext_test.go | 19 +- internal/tui3/folderfiles.go | 8 +- internal/tui3/folderpick.go | 90 +-- internal/tui3/folderplace.go | 32 +- internal/tui3/followup.go | 7 +- internal/tui3/foot.go | 32 +- internal/tui3/footswap.go | 14 +- internal/tui3/frame.go | 14 +- internal/tui3/framedisk_law_test.go | 2 +- internal/tui3/harness.go | 4 +- internal/tui3/harness_test.go | 2 +- internal/tui3/head.go | 18 +- internal/tui3/head_test.go | 4 +- internal/tui3/home.go | 17 +- internal/tui3/home_test.go | 45 +- internal/tui3/homeat.go | 10 +- internal/tui3/homeband_answer.go | 15 +- internal/tui3/homeband_answer_test.go | 9 +- internal/tui3/homeband_devices.go | 2 +- internal/tui3/homebridge_test.go | 8 +- internal/tui3/homecardrhythm.go | 12 +- internal/tui3/homecell.go | 40 +- internal/tui3/homedraft.go | 24 +- internal/tui3/homeexchange.go | 2 +- internal/tui3/homefate_test.go | 6 +- internal/tui3/homegrid.go | 74 +-- internal/tui3/homegrid_test.go | 58 +- internal/tui3/homeneedsgroups_test.go | 13 +- internal/tui3/homepanel_left.go | 7 +- internal/tui3/homepanel_live_test.go | 17 +- internal/tui3/homepanel_machines.go | 4 +- internal/tui3/homepanel_needs.go | 53 +- internal/tui3/homepanel_recent.go | 23 +- internal/tui3/homepanel_spend.go | 29 +- internal/tui3/homepanel_test.go | 14 +- internal/tui3/homeslash.go | 13 +- internal/tui3/homeslash_test.go | 11 +- internal/tui3/homesnappy_test.go | 8 +- internal/tui3/hometip.go | 15 +- internal/tui3/hop.go | 40 +- internal/tui3/hop_test.go | 5 - internal/tui3/host.go | 2 +- internal/tui3/hostlatency_test.go | 12 +- internal/tui3/hostlink.go | 8 +- internal/tui3/keeper.go | 9 +- internal/tui3/keptsweep_test.go | 8 +- internal/tui3/lanes.go | 63 +- internal/tui3/lanes_test.go | 2 +- internal/tui3/lanewalk_test.go | 5 +- internal/tui3/leaving.go | 5 +- internal/tui3/lifecycle_test.go | 14 +- internal/tui3/livesteps.go | 9 +- internal/tui3/livesteps_test.go | 4 +- internal/tui3/manualcmd_test.go | 7 +- internal/tui3/markdown.go | 2 +- internal/tui3/modelservices_test.go | 6 +- internal/tui3/narrow_test.go | 9 +- internal/tui3/notice.go | 129 ++-- internal/tui3/offlooplaw_test.go | 2 +- internal/tui3/onboarding.go | 14 +- internal/tui3/onetaskpage_test.go | 19 +- internal/tui3/openseam_test.go | 4 +- internal/tui3/pages.go | 42 +- internal/tui3/pages_test.go | 9 +- internal/tui3/palette.go | 24 +- internal/tui3/panes.go | 17 +- internal/tui3/pathlink.go | 4 +- internal/tui3/payload_test.go | 2 +- internal/tui3/phase.go | 30 +- internal/tui3/place_sessions.go | 9 +- internal/tui3/place_tasks_test.go | 3 +- internal/tui3/placebar_test.go | 7 +- internal/tui3/placeeverymouse_test.go | 3 - internal/tui3/placeeveryone_test.go | 2 +- internal/tui3/placehost_test.go | 5 +- internal/tui3/placelaws_test.go | 5 +- internal/tui3/placemouse.go | 10 +- internal/tui3/placeprose.go | 13 +- internal/tui3/placewalk_test.go | 10 +- internal/tui3/planrail.go | 11 +- internal/tui3/planroom.go | 3 +- internal/tui3/programbadge.go | 25 +- internal/tui3/programbadge_test.go | 11 +- internal/tui3/programbrief.go | 21 +- internal/tui3/programroom.go | 21 +- internal/tui3/programtab_test.go | 10 +- internal/tui3/projectcmd.go | 7 +- internal/tui3/providerword_law_test.go | 12 +- internal/tui3/pulse.go | 27 +- internal/tui3/question.go | 116 ++-- internal/tui3/question_test.go | 50 +- internal/tui3/questionaskback_test.go | 7 +- internal/tui3/questionchange.go | 2 +- internal/tui3/questionchooser.go | 12 +- internal/tui3/questiondemo.go | 14 +- internal/tui3/questionevidence.go | 10 +- internal/tui3/questionevidence_test.go | 2 +- internal/tui3/questionhand_test.go | 6 +- internal/tui3/questioninput.go | 9 +- internal/tui3/questionkeys.go | 20 +- internal/tui3/questionlaw_test.go | 4 - internal/tui3/questionnarrow.go | 11 +- internal/tui3/questionpage.go | 12 +- internal/tui3/questionpanel.go | 40 +- internal/tui3/questionroom.go | 11 +- internal/tui3/questionroom_test.go | 10 +- internal/tui3/questionscope.go | 23 +- internal/tui3/questionscreens_test.go | 10 +- internal/tui3/questionset.go | 8 +- internal/tui3/render.go | 50 +- internal/tui3/roomwork_test.go | 11 +- internal/tui3/runlane_test.go | 2 +- internal/tui3/scrollback_test.go | 2 +- internal/tui3/settings.go | 2 - internal/tui3/settingsautonomy.go | 9 +- internal/tui3/settingsautonomy_test.go | 4 +- internal/tui3/settle_test.go | 2 +- internal/tui3/settledreceiptlaw_test.go | 3 +- internal/tui3/slashchip.go | 6 +- internal/tui3/startpagekeys_test.go | 2 +- internal/tui3/steer.go | 7 +- internal/tui3/steerelbow.go | 14 +- internal/tui3/styles.go | 141 +--- internal/tui3/tabsignal_test.go | 2 +- internal/tui3/taskcardhost_test.go | 2 +- internal/tui3/taskphone.go | 2 +- internal/tui3/taskrecord.go | 13 +- internal/tui3/tasksconversation_test.go | 4 +- internal/tui3/tasksplace_test.go | 5 +- internal/tui3/taskstable_test.go | 8 +- internal/tui3/teamcrew.go | 3 +- internal/tui3/teamlink.go | 2 +- internal/tui3/teams_test.go | 3 +- internal/tui3/tokencol.go | 27 +- internal/tui3/tokencol_test.go | 20 +- internal/tui3/toolclamp_test.go | 1 - internal/tui3/toolview.go | 9 +- internal/tui3/topnav.go | 2 +- internal/tui3/vianews_test.go | 26 +- internal/tui3/view.go | 5 +- internal/tui3/walldock.go | 6 +- internal/tui3/walldock_test.go | 2 +- internal/tui3/watching.go | 4 +- internal/tui3/welcome.go | 19 +- internal/tui3/wiring_test.go | 8 +- internal/tui3/workfold.go | 44 +- internal/wirelog/wirelog.go | 2 +- scripts/ledger.py | 21 +- scripts/measure/benchmove/summarize.py | 12 +- scripts/qv-drive.sh | 2 +- 329 files changed, 1670 insertions(+), 2861 deletions(-) create mode 100644 docs/changes/unreleased/source-comments.md create mode 100644 internal/commentlaw/commentlaw_test.go diff --git a/bench/run.sh b/bench/run.sh index a10169a197..2fdf4217f2 100755 --- a/bench/run.sh +++ b/bench/run.sh @@ -19,7 +19,7 @@ ISSUES="${ISSUES:-20 21 22 23}" HARNESSES="${HARNESSES:-codeaf pi opencode}" # Wall-clock cap per cell. A harness that has not produced a diff by here is -# recorded as DNF rather than left to spend: opencode hit this on issue #22 and +# recorded as DNF rather than left running indefinitely. A stalled process # kept spending after the diff never arrived. CELL_TIMEOUT="${CELL_TIMEOUT:-40m}" @@ -31,7 +31,7 @@ CELL_TIMEOUT="${CELL_TIMEOUT:-40m}" # (2026-08-02, merge of PR #18): the last commit with all four issues open. BASE_COMMIT="${BASE_COMMIT:-}" -# codeaf shape. Four values, against the same recorded pi and opencode rows: +# codeaf shape. Four values use the same recorded comparison rows: # # node one leaf, one graph. The executor measured alone, and the drift # control: byte for byte the invocation the recorded codeaf numbers @@ -61,7 +61,7 @@ case "${1:-}" in --dry-run) BENCH_DRY_RUN=1 ;; esac -# pi and opencode flags move between versions. These are the invocations the +# External harness flags move between versions. These are the invocations the # recorded runs used; check them against your installed version before # concluding anything from a zero-file result. PI_BIN="${PI_BIN:-pi}" @@ -296,8 +296,8 @@ run_harness() { } # harness_cost reads the run's own accounting. For codeaf that is the $ figure -# on the run summary line, which every graph shape ends with. For pi and -# opencode there is nothing to read, and the account-level delta is not a +# on the run summary line, which every graph shape ends with. Other harnesses +# provide no summary value, and the account-level delta is not a # substitute — see bench/README.md. harness_cost() { local harness="$1" log="$2" cell="${3:-}" diff --git a/cmd/codeaf-census/main.go b/cmd/codeaf-census/main.go index 14b05a8641..23499bb9fa 100644 --- a/cmd/codeaf-census/main.go +++ b/cmd/codeaf-census/main.go @@ -7,7 +7,7 @@ // committed instrument every one of those numbers is an argument about // anecdotes. The first census (docs/design/recovery/census-20260910.md) was a // throwaway pass over the same file; this is that pass, committed, tested on a -// fixture, and runnable nightly by a cron on the Spark (`make census`). +// fixture, and runnable nightly by a cron in a test run (`make census`). // // It is a developer's binary and never a verb on codeaf, for the reason // cmd/codeaf-changes and cmd/codeaf-demo-home are: the shipped binary is on a diff --git a/cmd/codeaf-demo-home/main.go b/cmd/codeaf-demo-home/main.go index 53a168b5f0..050314a54c 100644 --- a/cmd/codeaf-demo-home/main.go +++ b/cmd/codeaf-demo-home/main.go @@ -4,16 +4,12 @@ package main // something on every one of v3's places, so the surface can be looked at full // rather than empty. // -// WHY IT IS NOT A FIXTURE FOR TESTS AND NOT A SEED FOR A REAL MACHINE. The -// owner opened the standing page, the memory page and the spend page on their -// own machine and saw nothing, because on their machine those stores are new -// and empty — which is the emptiness law working exactly as designed. The -// answer is not to write invented automations, invented memories and invented -// spending into ~/.codeaf, which would make a person's own record a lie; it is -// a SECOND home, somewhere else, that the surface can be pointed at. -// So this program never touches the real state root: it writes one directory, -// the one it was given, and the launcher hands that directory to the binary as -// HOME. +// WHY IT IS NOT A FIXTURE FOR TESTS AND NOT A SEED FOR A REAL MACHINE. The answer is not +// to write invented automations, invented memories and invented spending into ~/.codeaf, +// which would make a person's own record a lie; it is a SECOND home, somewhere else, that +// the surface can be pointed at. So this program never touches the real state root: it +// writes one directory, the one it was given, and the launcher hands that directory to the +// binary as HOME. // // WHY IT IS A SEPARATE BINARY. cmd/codeaf has a clean place for a hidden verb — // `engine` and `tick` both live there — but the seeding below is several hundred diff --git a/cmd/codeaf/chatv3.go b/cmd/codeaf/chatv3.go index 693ba510fe..1a46692383 100644 --- a/cmd/codeaf/chatv3.go +++ b/cmd/codeaf/chatv3.go @@ -1426,7 +1426,7 @@ func v3Connections(manager *connect.Manager) tui3.Connections { // since two writers on one journal is a corrupted journal. // // SILENTLY STARTING A NEW CONVERSATION IS DEAD, and killing it is the point of -// this lane. This door used to mint a sibling session and say "session open +// this implementation. This door used to mint a sibling session and say "session open // elsewhere — started a new one", which sounds like an explanation and is // actually the defect: the conversation the person came back for was still // running a few inches away, in another terminal or in this workspace's session diff --git a/cmd/codeaf/chatv3_exchange.go b/cmd/codeaf/chatv3_exchange.go index 71ac50f3b1..a39eeb997e 100644 --- a/cmd/codeaf/chatv3_exchange.go +++ b/cmd/codeaf/chatv3_exchange.go @@ -7,7 +7,7 @@ package main // // ─────────────────────────────────────────────────────────────────────────── // MERGE NOTE (lane errand). Everything in this file is new, and the only line -// this lane added outside it is the `Errand:` / `ErrandsRoot:` pair in +// this implementation added outside it is the `Errand:` / `ErrandsRoot:` pair in // chatv3.go's tui3.Options literal. If that literal has moved under another // lane, the pair is the whole of what has to be carried across. // ─────────────────────────────────────────────────────────────────────────── diff --git a/cmd/codeaf/chatv3_layout.go b/cmd/codeaf/chatv3_layout.go index 6a8652ae3e..d7b2512730 100644 --- a/cmd/codeaf/chatv3_layout.go +++ b/cmd/codeaf/chatv3_layout.go @@ -12,7 +12,7 @@ package main // - WHICH PROJECT. The workspace is the git root of the directory the person // stood in, so `codeaf` typed in repo/cmd and in repo/ is the same project. // The encoded directory name is a bucket and not an identity — meta.json -// carries the real path — which is what lets the encoding stay dumb. +// carries the real path — which is what lets the encoding stay simple. // - BORROWED OR OWNED. A conversation opened inside a project borrows it and // litters nothing; one opened nowhere at all owns a workspace of its own. // - WHICH CONVERSATION. The newest one the PERSON spoke in, or a fresh diff --git a/cmd/codeaf/chatv3_process_test.go b/cmd/codeaf/chatv3_process_test.go index 6f61437fc0..8081ced60f 100644 --- a/cmd/codeaf/chatv3_process_test.go +++ b/cmd/codeaf/chatv3_process_test.go @@ -149,7 +149,7 @@ type gateOnly struct { recordingGate } -// THE BUG THIS LANE FIXES, at the door's end. +// THE BUG this test FIXES, at the door's end. // // The three approval seams used to be minted once, at boot, around the boot // agent, and the surface went on holding them through every /new and every diff --git a/cmd/codeaf/chatv3_session_test.go b/cmd/codeaf/chatv3_session_test.go index 692265a4fd..c68b4364bd 100644 --- a/cmd/codeaf/chatv3_session_test.go +++ b/cmd/codeaf/chatv3_session_test.go @@ -12,7 +12,7 @@ import ( // A second window in the same directory resumes the same transcript, which the // first one is holding open. It used to be handed a NEW conversation and one -// sentence about it, which is the defect this lane ends: the chat the person +// sentence about it, which is the defect this test ends: the chat the person // came back for was still running, and nothing led them to it. Now it is a // refusal that says where the conversation is and what lets go of it. func TestASecondWindowOnALockedSessionIsRefusedAndNamesTheWayOut(t *testing.T) { diff --git a/cmd/codeaf/do.go b/cmd/codeaf/do.go index fe493a8c49..ada5bf736f 100644 --- a/cmd/codeaf/do.go +++ b/cmd/codeaf/do.go @@ -2935,7 +2935,7 @@ func (w *settlementWatch) checklistFor(nodeID string, wrote []string) (rows []re // is empty - contains no implementation" over exit 0 for want of the Unclosed // field, and another produced no file at all and reported settled, done, success // under a note explaining that the review had overreached -// (2026-08-28, meta/muse-spark-1.1). Exit 2, partial, is the honest code for a +// (2026-08-28, a model response). Exit 2, partial, is the honest code for a // job that delivered less than it promised. // // THE READING IS store.DeliveryGate.Whole AND IT IS NOT REPEATED HERE. This diff --git a/cmd/codeaf/do_machine_gate_test.go b/cmd/codeaf/do_machine_gate_test.go index d220f3a0dd..18b4ccfc2e 100644 --- a/cmd/codeaf/do_machine_gate_test.go +++ b/cmd/codeaf/do_machine_gate_test.go @@ -61,12 +61,11 @@ func TestDoRunHonoursProfileMachineFloor(t *testing.T) { } } -// THE CONTRACT, from the owner's ruling on #1410 (2026-09-24): when `codeaf do` -// is held by the machine, the person sees why on stderr, once, in the rail's -// own words and naming the limit that held it; and a run whose --timeout -// arrives before anything started says, in its --json stop, that the machine -// held it. Before this, a held run waited in silence and ended `deadline` with -// nothing to say why nothing had happened. +// THE CONTRACT, from on #1410 (2026-09-24): when `codeaf do` is held by the machine, the +// person sees why on stderr, once, in the rail's own words and naming the limit that held +// it; and a run whose --timeout arrives before anything started says, in its --json stop, +// that the machine held it. Before this, a held run waited in silence and ended `deadline` +// with nothing to say why nothing had happened. func TestDoHeldByTheMachineSaysWhyOnStderrAndInItsStop(t *testing.T) { if _, err := os.Stat("/proc/meminfo"); err != nil { t.Skip("host has no proc memory reading") diff --git a/cmd/codeaf/engine.go b/cmd/codeaf/engine.go index a391cb7990..d1d03ba7d8 100644 --- a/cmd/codeaf/engine.go +++ b/cmd/codeaf/engine.go @@ -990,7 +990,7 @@ func runEngineHost(workspaceFlag, sessionFlag string) error { // // A NAMED SESSION IS SPELLED THE WAY THE BOOT WILL SPELL IT, through the same // [engineSessionPath] every other door reads a --session with, so two surfaces -// that named one file two ways ("~/x", "/home/you/x") are asking for one +// that named one file two ways ("~/x", "/workspace/x") are asking for one // conversation rather than two. func engineHelloKey(hello remote.Hello, workspaceFlag, sessionFlag string) string { if named := firstEngineWord(hello.Session, sessionFlag); named != "" { diff --git a/cmd/codeaf/plainwords.go b/cmd/codeaf/plainwords.go index 640aeb1bf0..a957755c6f 100644 --- a/cmd/codeaf/plainwords.go +++ b/cmd/codeaf/plainwords.go @@ -56,7 +56,7 @@ func plainWords(sentence string) string { // A filesystem failure arrives as an [os.PathError] wrapped on every floor it // passed on the way up: // -// open notebook: stat /home/x/.codeaf/graph.db: no such file or directory +// open notebook: stat /workspace/.codeaf/graph.db: no such file or directory // create chat workspace: mkdir /nope: permission denied // // `stat`, `mkdir` and `open` are the names of system calls — a library's words diff --git a/cmd/codeaf/window.go b/cmd/codeaf/window.go index 8226088ad1..b90d140c89 100644 --- a/cmd/codeaf/window.go +++ b/cmd/codeaf/window.go @@ -11,7 +11,7 @@ import ( // // IT CARRIES ONE PATH, NOT TWO. It used to keep the store's resolved path // beside the spelling a `--db` flag was given in, because the v2 chat door -// parsed that flag and `~/store.db` and `/home/…/store.db` are different +// parsed that flag and `~/store.db` and `/workspace/store.db` are different // strings for one file. That door is gone (#329), the only caller left resolves // the path before it opens anything, and a second field that always held the // same value was one more thing to keep in step. diff --git a/docs/changes/unreleased/source-comments.md b/docs/changes/unreleased/source-comments.md new file mode 100644 index 0000000000..8395cf151d --- /dev/null +++ b/docs/changes/unreleased/source-comments.md @@ -0,0 +1,6 @@ +--- +kind: changed +title: Tidy source comments and add a comment style check +surface: [build] +invalidates: [] +--- diff --git a/internal/calllog/calllog.go b/internal/calllog/calllog.go index 901e38e4ea..42ecbbd153 100644 --- a/internal/calllog/calllog.go +++ b/internal/calllog/calllog.go @@ -123,7 +123,7 @@ type Record struct { // 65,536-token ceiling looked identical to an idle process. Phase string `json:"phase,omitempty"` // Tag is what the call was for — "turn", "leaf", "compile", "brief" — set - // by whoever made it (provider.WithCallTag). Empty for a call this lane did + // by whoever made it (provider.WithCallTag). Empty for a call this implementation did // not locate, which is honest: an untagged row is still a row. Tag string `json:"tag,omitempty"` // Node is the work the call belongs to, where the caller knows one: a plan diff --git a/internal/cellstore/guard_test.go b/internal/cellstore/guard_test.go index 51cf3b0d80..1290fb82c7 100644 --- a/internal/cellstore/guard_test.go +++ b/internal/cellstore/guard_test.go @@ -169,8 +169,8 @@ func TestScopeIsTheNormalizedRemoteElseTheCell(t *testing.T) { } } -// TestL3_SecretsNeverEnterTheStore proves C9's working-tree law as amended by -// Abir on 2026-10-21: committed history travels sealed, so this fixture commits +// TestL3_SecretsNeverEnterTheStore checks the working-tree boundary. +// Committed history travels sealed, so this fixture commits // only non-secret files. The secrets remain untracked rather than ignored to // prove the guard, independently of Git's ignore rules. After two seals no // store object holds the key, and the next tool call still gets the .env value. diff --git a/internal/cellstore/rebuild.go b/internal/cellstore/rebuild.go index 8db31b1953..36395a6914 100644 --- a/internal/cellstore/rebuild.go +++ b/internal/cellstore/rebuild.go @@ -47,8 +47,7 @@ func (s Screened) paths() []string { } // leftOut is the install folders this seal leaves out because a lockfile that -// travels rebuilds them. It is the rule of docs/STAGE-1-CONTRACTS.md section -// 19.4, and each folder that fails any test of it travels with the seal exactly +// travels rebuilds them. Each folder that fails any test of it travels with the seal exactly // as before, so being wrong costs the bytes the seal would have carried anyway. func (g Guard) leftOut(tree string, changed, locks []string, policy policyFile) Screened { personal := policy diff --git a/internal/cellstore/withheld.go b/internal/cellstore/withheld.go index fbd37ba323..a3b1258da6 100644 --- a/internal/cellstore/withheld.go +++ b/internal/cellstore/withheld.go @@ -17,7 +17,7 @@ import ( // lands in the person's folder; a cell that seals its own folder uses that // folder's file. Below one marker line sit the paths withheld because they // carry secrets, and below another the install folders left out because a -// lockfile that does travel rebuilds them (docs/STAGE-1-CONTRACTS.md section 19). +// lockfile that does travel rebuilds them. // Two more blocks set single paths apart: those this machine cannot read (a file // with no permissions, a folder it may not list) and those whose name this // machine's file system cannot keep beside another's (written when a chat is diff --git a/internal/cellsync/liveness.go b/internal/cellsync/liveness.go index 76f706fe16..4ddcf7d6b5 100644 --- a/internal/cellsync/liveness.go +++ b/internal/cellsync/liveness.go @@ -1,7 +1,7 @@ package cellsync // Liveness is a watch socket that can vouch for the leases this process holds -// (STAGE-1-CONTRACTS.md §21.11). While it does, the relay counts the socket's +// . While it does, the relay counts the socket's // pings as the holder's proof of life, so the Batcher need not heartbeat. type Liveness interface { // Keep names the lease of cell at fence on the socket and answers how to diff --git a/internal/chatlist/copy.go b/internal/chatlist/copy.go index 33c14d4bf9..6b55a7ad10 100644 --- a/internal/chatlist/copy.go +++ b/internal/chatlist/copy.go @@ -6,7 +6,7 @@ import ( "time" ) -// The frozen sentences (STAGE-1-CONTRACTS §8.1). Every surface takes its words +// The frozen sentences. Every surface takes its words // from here so a respelling happens once. const ( OfferContinue = "continue here" diff --git a/internal/chatlist/rows.go b/internal/chatlist/rows.go index 984c5609eb..9c44b533fe 100644 --- a/internal/chatlist/rows.go +++ b/internal/chatlist/rows.go @@ -44,7 +44,7 @@ type Row struct { // Quiet is the row of a chat whose live holder has gone: a lease that still // runs on a device that is no longer online is a chat that stopped, so it reads -// as one that went off (`studio offline`), not `running on studio`. +// as one that went off (`desktop offline`), not `running on desktop`. func (r Row) Quiet() Row { if r.Status == Running { r.Status = Off diff --git a/internal/commentlaw/commentlaw_test.go b/internal/commentlaw/commentlaw_test.go new file mode 100644 index 0000000000..e9a8d498d4 --- /dev/null +++ b/internal/commentlaw/commentlaw_test.go @@ -0,0 +1,317 @@ +// Package commentlaw keeps source comments focused on product behavior. +package commentlaw + +import ( + "fmt" + "go/parser" + "go/token" + "io/fs" + "os" + "path/filepath" + "regexp" + "sort" + "strings" + "testing" +) + +var rules = []*regexp.Regexp{ + regexp.MustCompile(`(?i)\b(?:the\s+owner|owner's)\s+(?:has\s+(?:already\s+)?)?(?:asked|ruled|decided|ruling|feedback|report|review|wants|picks?)\b|ruled by the owner`), + regexp.MustCompile(`(?i)\bthis lane\s+(?:added|fixes|proves|ends|may not edit|measured|replaces)|(?-i:\blane [A-Z][0-9]*\b)|\b(?:ai|coding|development) lane\b`), + regexp.MustCompile(`(?i)\b(?:spark|blackmac|dgx|dumb|studio|santosh|abir|zeropoint)\b`), + regexp.MustCompile(`(?i)(?:^|[\s"'(\x60])/(?:home|Users)/[^/\s]+|(?-i:STAGE-[0-9][A-Z0-9-]*(?:\.md)?)|\b(?:LEDGER|DECISION)\.md`), + regexp.MustCompile(`(?i)\b(?:opencode|claude code|codex|pi)\b`), + regexp.MustCompile(`(?i)\b(?:faster|slower|better|worse|versus|compared|unlike)\b[^.\n]{0,80}\b(?:opencode|claude code|codex|pi)\b|\b(?:opencode|claude code|codex|pi)\b[^.\n]{0,80}\b(?:faster|slower|better|worse|versus)\b`), +} + +// These exceptions describe formats, services and source identifiers. Each +// exemption applies to one rule and one comment; other rules still apply. +var exceptions = []struct { + path, text *regexp.Regexp + rule int + term string +}{ + {regexp.MustCompile(`\.go$`), regexp.MustCompile(`(?i)codex/gpt|CLI|provider|transport|codexauth|sign.in|model|catalog|account|credential|service|backend|profile|272k|window|context|skills?|plugin|agentskills\.io`), 4, "codex"}, // Codex is an authenticated model service. + {regexp.MustCompile(`^(internal/(skills|home|store|resident|session)/|cmd/codeaf/)`), regexp.MustCompile(`(?i)skills?|plugins?|agentskills\.io|registry|settings\.json`), 4, "skills"}, // Skill discovery reads other tools' file formats. + {regexp.MustCompile(`^(internal/exec/bare/|internal/session/|internal/tui3/toolstat\.go|cmd/harness-design/)`), regexp.MustCompile(`(?i)\bpi\b`), 4, "pi"}, // The tool library preserves compatible wire schemas and results. + {regexp.MustCompile(`\.go$`), regexp.MustCompile(`(?i)TERM.?=.?dumb|dumb terminal|TERM unset or.*dumb|found a dumb|LM Studio`), 2, "terminal"}, // Terminal capabilities and provider names are protocols. + {regexp.MustCompile(`^internal/tui3/(spark|wallcontract|wallview|render|spendplace|homegrid)\.go$`), regexp.MustCompile(`(?i)\bspark\b`), 2, "spark"}, // Spark names a chart sample or field in these renderers. +} + +func TestSourceComments(t *testing.T) { + root, err := filepath.Abs("../..") + if err != nil { + t.Fatal(err) + } + for _, problem := range violations(root) { + t.Error(problem) + } +} + +func violations(root string) []string { + var found []string + for _, scope := range []string{"cmd", "internal", "scripts", "relay/src", "bench/canary", "bench/run.sh"} { + err := filepath.WalkDir(filepath.Join(root, scope), func(path string, d fs.DirEntry, err error) error { + if os.IsNotExist(err) { + return nil + } + if err != nil { + return err + } + rel, err := filepath.Rel(root, path) + if err != nil { + return err + } + rel = filepath.ToSlash(rel) + if d.IsDir() { + if excluded(rel) { + return filepath.SkipDir + } + return nil + } + if excluded(rel) || !source(rel) { + return nil + } + body, err := os.ReadFile(path) + if err != nil { + return err + } + comments, err := sourceComments(rel, string(body)) + if err != nil { + return err + } + for _, c := range comments { + for i, rule := range rules { + matches := rule.FindAllStringIndex(c.text, -1) + if len(matches) == 0 { + continue + } + for _, match := range matches { + term := strings.ToLower(c.text[match[0]:match[1]]) + allowed := false + for _, ex := range exceptions { + if ex.rule == i && ex.path.MatchString(rel) && ex.text.MatchString(c.text) && (i != 2 || ex.term == "spark" && term == "spark" || ex.term == "terminal" && (term == "dumb" || term == "studio")) && (i != 4 || ex.term == term || ex.term == "skills" && (term == "claude code" || term == "opencode" || term == "codex")) { + allowed = true + break + } + } + if !allowed { + found = append(found, fmt.Sprintf("%s:%d: comment should describe product behavior: %s", rel, c.line+strings.Count(c.text[:match[0]], "\n"), term)) + } + } + } + } + return nil + }) + if err != nil { + found = append(found, fmt.Sprintf("%s: %v", scope, err)) + } + } + sort.Strings(found) + return found +} + +func excluded(path string) bool { + for _, part := range strings.Split(path, "/") { + if part == "testdata" || part == "fixtures" || part == "node_modules" { + return true + } + } + base := filepath.Base(path) + return path == "internal/manual" || strings.HasSuffix(base, "_test.go") || strings.HasSuffix(base, "_test.sh") || strings.HasSuffix(base, "_test.py") || strings.HasPrefix(base, "test_") || strings.HasSuffix(base, ".test.js") +} +func source(path string) bool { + switch filepath.Ext(path) { + case ".go", ".js", ".ts", ".py", ".sh": + return true + } + return false +} + +type comment struct { + line int + text string +} + +func sourceComments(path, body string) ([]comment, error) { + if filepath.Ext(path) == ".go" { + set := token.NewFileSet() + file, err := parser.ParseFile(set, path, body, parser.ParseComments) + if err != nil { + return nil, err + } + var out []comment + for _, group := range file.Comments { + out = append(out, comment{set.Position(group.Pos()).Line, group.Text()}) + } + return out, nil + } + return scriptComments(path, body), nil +} + +// Quoted program text is skipped so a URL, shell expansion or fixture string +// cannot be mistaken for commentary. Block comments retain their starting line. +func scriptComments(path, body string) []comment { + var out []comment + hash := strings.HasSuffix(path, ".py") || strings.HasSuffix(path, ".sh") + line := 1 + var heredocs []string + for i := 0; i < len(body); { + if body[i] == '\n' { + line++ + i++ + for _, delimiter := range heredocs { + for i < len(body) { + end := strings.IndexByte(body[i:], '\n') + if end < 0 { + end = len(body) - i + } + text := strings.TrimSuffix(strings.TrimLeft(body[i:i+end], "\t"), "\r") + i += end + if i < len(body) { + i++ + line++ + } + if text == delimiter { + break + } + } + } + heredocs = nil + continue + } + if strings.HasSuffix(path, ".sh") && strings.HasPrefix(body[i:], "<<") && !strings.HasPrefix(body[i:], "<<<") { + j := i + 2 + if j < len(body) && body[j] == '-' { + j++ + } + for j < len(body) && (body[j] == ' ' || body[j] == '\t') { + j++ + } + if j < len(body) && (body[j] == '"' || body[j] == '\'') { + j++ + } + start := j + for j < len(body) && (body[j] == '_' || body[j] >= 'a' && body[j] <= 'z' || body[j] >= 'A' && body[j] <= 'Z' || body[j] >= '0' && body[j] <= '9') { + j++ + } + if j > start { + heredocs = append(heredocs, body[start:j]) + } + } + if hash && body[i] == '#' && (i == 0 || strings.ContainsRune(" \t\n;", rune(body[i-1]))) || !hash && strings.HasPrefix(body[i:], "//") { + start, l := i, line + for i < len(body) && body[i] != '\n' { + i++ + } + out = append(out, comment{l, body[start:i]}) + continue + } + if !hash && strings.HasPrefix(body[i:], "/*") { + start, l := i, line + i += 2 + for i < len(body) && !strings.HasPrefix(body[i:], "*/") { + if body[i] == '\n' { + line++ + } + i++ + } + if i < len(body) { + i += 2 + } + out = append(out, comment{l, body[start:i]}) + continue + } + if strings.HasSuffix(path, ".py") && (strings.HasPrefix(body[i:], "\"\"\"") || strings.HasPrefix(body[i:], "'''")) { + start, l, quote := i, line, body[i:i+3] + doc := strings.TrimSpace(body[strings.LastIndex(body[:i], "\n")+1:i]) == "" + i += 3 + for i < len(body) && !strings.HasPrefix(body[i:], quote) { + if body[i] == '\n' { + line++ + } + if body[i] == '\\' && i+1 < len(body) { + i += 2 + } else { + i++ + } + } + if i < len(body) { + i += 3 + } + if doc { + out = append(out, comment{l, body[start:i]}) + } + continue + } + if strings.ContainsRune("\"'`", rune(body[i])) { + quote := body[i] + i++ + for i < len(body) { + if body[i] == '\n' { + line++ + } + if body[i] == '\\' { + i += 2 + continue + } + if body[i] == quote { + i++ + break + } + i++ + } + continue + } + i++ + } + return out +} + +func TestCommentPatternsAndBoundaries(t *testing.T) { + cases := []struct { + name, path, body string + want int + }{ + {"Go attribution", "internal/example/source.go", "package example\n// The owner asked for this behavior.\nvar x=1\n", 1}, + {"block and inline comments", "cmd/example/source.go", "package main\n/* Abir requested this. */\nvar x=1 // lane A measured this.\n", 2}, + {"JavaScript", "relay/src/source.js", "const url='https://example.com'; // measured on Spark\n/* /Users/name/work */", 2}, + {"Python docstring", "scripts/source.py", "\"\"\"Measured on Spark.\"\"\"\n", 1}, + {"Python", "scripts/source.py", "text = '# Spark'\n# STAGE-1-CONTRACTS.md\n", 1}, + {"shell heredoc", "scripts/example.sh", "cat <<'EOF'\n# Spark\nEOF\n# Describe the product.\n", 0}, + {"Python string", "scripts/source.py", "data=\"\"\"# Spark\"\"\"\n", 0}, + {"template literal", "relay/src/source.js", "const text=`// Spark`; // Describe the product.\n", 0}, + {"shell", "bench/run.sh", "echo '# Spark' # blackmac\n", 1}, + {"quoted words", "internal/example/source.go", "package example\nvar x=\"the owner asked on Spark\"\n", 0}, + {"multiline attribution", "internal/example/source.go", "package example\n// The owner\n// ruled that this works.\n", 1}, + {"documentation URL", "internal/example/source.go", "package example\n// https://example.com/docs/home/getting-started\n", 0}, + {"public issue", "internal/example/source.go", "package example\n// Avoid duplicate delivery after reconnect (#123).\n", 0}, + {"routing ownership", "internal/example/source.go", "package example\n// The goal owner decided to continue on the lane a request uses.\n", 0}, + {"comparison", "internal/config/source.go", "package config\n// The Codex model service is faster than other tools.\n", 1}, + {"authentication", "internal/config/source.go", "package config\n// The Codex model service requires an account bearer.\n", 0}, + {"no cross-name exception", "internal/config/source.go", "package config\n// The Codex model service outperforms opencode.\n", 1}, + {"fixture", "internal/example/testdata/source.go", "// Spark\n", 0}, + {"Go test", "internal/example/source_test.go", "// Spark\n", 0}, + {"manual", "internal/manual/example.go", "// Spark\n", 0}, + {"hosted tree", "relay/hosted/src/source.js", "// Spark\n", 0}, + {"excluded scripts", "scripts/test_example.py", "# Spark\n", 0}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + root := t.TempDir() + path := filepath.Join(root, tc.path) + if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(path, []byte(tc.body), 0644); err != nil { + t.Fatal(err) + } + got := violations(root) + if len(got) != tc.want { + t.Fatalf("got %v, want %d violations", got, tc.want) + } + if tc.want > 0 && !strings.Contains(got[0], tc.path+":") { + t.Fatalf("missing source location: %v", got) + } + }) + } +} diff --git a/internal/config/settings.go b/internal/config/settings.go index 4223b07f50..cc1c0bdbe9 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -2635,11 +2635,10 @@ func (s *Settings) build() []Setting { read: func() string { return formatBool(DraftPersistAt(dir)) }, write: func(raw string) error { return writeBool(dir, KeyDraftPersist, raw) }, }, - // THE ROW READS THE OTHER WAY UP FROM ITS KEY. `ui.hints` persists - // whether tips are SHOWN, and keeps doing so — a persisted identifier keeps - // its bytes — while the row a person reads is `disable hints`, off by - // default (the owner's word for it, 2026-09-22). The inversion lives here, - // once, so the chat's settings panel and `codeaf config` cannot disagree. + // THE ROW READS THE OTHER WAY UP FROM ITS KEY. `ui.hints` persists whether tips are + // SHOWN, and keeps doing so — a persisted identifier keeps its bytes — while the row a + // person reads is `disable hints`, off by default. The inversion lives here, once, so + // the chat's settings panel and `codeaf config` cannot disagree. Setting{ Key: KeyHints, Category: CategoryInterface, Kind: SettingBool, Label: "disable hints", diff --git a/internal/ctxbudget/ctxbudget.go b/internal/ctxbudget/ctxbudget.go index 4bbbcb70bc..c793a253ff 100644 --- a/internal/ctxbudget/ctxbudget.go +++ b/internal/ctxbudget/ctxbudget.go @@ -537,7 +537,7 @@ func ObservationBytes(contextTokens int) int { // most a TENTH of the window it has to fit in. // // The number is not invented here, it is read off the caps that were already in -// force. pi's 2000 lines / 50KB were measured against a 128,000-token window, +// force. The default 2000 lines / 50KB were measured against a 128,000-token window, // which is the window this program assumes when a model card says nothing // (internal/session's defaultContextWindow), and 50KB is exactly a tenth of // 128,000 tokens in transport bytes. So a tenth reproduces today's numbers diff --git a/internal/devname/devname.go b/internal/devname/devname.go index c5f6a46633..5c8369e8c0 100644 --- a/internal/devname/devname.go +++ b/internal/devname/devname.go @@ -55,7 +55,7 @@ func Clean(typed string) (string, error) { } // Default is the host name with any domain cut off, so a list of two laptops -// reads `spark` and not `spark.local.example.com`. A machine that cannot say its +// reads `laptop` and not `laptop.local.example.com`. A machine that cannot say its // host name is "a device". func Default() string { host, err := os.Hostname() diff --git a/internal/dirwatch/doc.go b/internal/dirwatch/doc.go index 93f08904dd..ea03a77550 100644 --- a/internal/dirwatch/doc.go +++ b/internal/dirwatch/doc.go @@ -27,8 +27,8 @@ // the relay closed because it went quiet (CloseSilent) is dialled again at // once. The set is empty while // State.Up is false, because the relay names who is online only when a -// socket opens. A surface draws "● spark" for a name in Online and -// "○ dumb" otherwise, and reads the last time a device was seen from the +// socket opens. A surface draws "● laptop" for a name in Online and +// "○ desktop" otherwise, and reads the last time a device was seen from the // device record's last_seen. // - State.Joined lists the newest MaxJoined device-joined events, oldest // first, each with a Seq that only rises. A surface remembers the newest diff --git a/internal/dirwatch/holder.go b/internal/dirwatch/holder.go index b7cfc6acd9..380beca078 100644 --- a/internal/dirwatch/holder.go +++ b/internal/dirwatch/holder.go @@ -11,8 +11,7 @@ import ( // // A process that holds chats keeps one socket of its own that names them, so // the relay can take the socket's pings as proof that the holder is alive and -// the holder need not send a heartbeat while it is (STAGE-1-CONTRACTS.md -// §21.11). It is kept apart from the home screen's feed on purpose: the home +// the holder need not send a heartbeat while it is. It is kept apart from the home screen's feed on purpose: the home // socket names no holds, so it vouches for nothing and a screen that is only // looked at cannot be mistaken for a holder. // diff --git a/internal/dirwatch/stream.go b/internal/dirwatch/stream.go index 184642f0cd..5a358bdc29 100644 --- a/internal/dirwatch/stream.go +++ b/internal/dirwatch/stream.go @@ -53,14 +53,13 @@ const ( CloseRevoked = 4401 CloseRotated = 4410 // CloseSilent ends a socket whose last sign of life was too old; the - // device is announced offline and must redial (STAGE-1-CONTRACTS.md 21.12.4). + // device is announced offline and must redial. CloseSilent = 4408 ) // The pace of the feed. Each number is here once. const ( - // KeepEvery is how often a quiet socket pings: every 10 s, the beat - // STAGE-1-CONTRACTS.md 21.12 gives. The relay derives the window in which + // KeepEvery is how often a quiet socket pings: every 10 s. The relay derives the window in which // it counts this device online from the beat the dial declares, and the // directory package derives that declaration from this constant, so the // two halves cannot drift. The relay answers a ping without waking diff --git a/internal/e2e/contracts_e2e_test.go b/internal/e2e/contracts_e2e_test.go index 3c65b44ff9..b82e610737 100644 --- a/internal/e2e/contracts_e2e_test.go +++ b/internal/e2e/contracts_e2e_test.go @@ -2,7 +2,7 @@ // TWO CONTRACTS, END TO END, AGAINST A REAL MODEL. // -// WHAT THIS LANE PROVES. A worker is handed one document — its contract — and it +// WHAT this test PROVES. A worker is handed one document — its contract — and it // does what the document says. Both issues below are the same failure read from // two sides: the contract said something about a place or a command that was // TRUE OF SOMEBODY ELSE, and the worker obeyed it anyway. @@ -349,7 +349,7 @@ func assertTheWorkerStayedInItsCopy(t *testing.T, one *contractAttempt) { // briefProduceHeading is the contract's own heading for the thing to make, as // task_brief.go spells it. It is repeated here rather than reached for because -// it is unexported there and this lane reads the disk. +// it is unexported there and this test reads the disk. const briefProduceHeading = "WHAT TO PRODUCE" // briefDoneWhenHeading is the section after it, which is where the WHAT TO @@ -407,7 +407,7 @@ const theWideCommand = "ls -1" // divisionRefusedSharedCheck is the decision the division road writes when it // turns a division down for this rule (task_divide.go). Spelled again here for -// [taskRow]'s reason: it is unexported there and this lane reads the record. +// [taskRow]'s reason: it is unexported there and this test reads the record. const divisionRefusedSharedCheck = "refused:shared-check" // divisionRepairedSharedCheck is the SECOND firing of that rule on one node: the @@ -549,7 +549,7 @@ func TestOneWideCheckIsNotOrderedByEveryPart(t *testing.T) { // written — and it is a fact about how a cheap model reads a refusal, not // about whether the road was right to make it. The families lane asserts a // worker carries on through the #231 refusal; that assertion is not made - // here, because making it would put this lane's verdict on #569 in the hands + // here, because making it would put this test's verdict on #569 in the hands // of one model's willingness to redraw a boundary. root := run.rootRow() t.Logf(" the family ended %s (%s) having written %v", root.State, root.Ending, root.Changed) @@ -611,7 +611,7 @@ func theWideCheckShapeWasReached(run *familyRun) bool { // THE END STATE THE FIX IS FOR is three admitted children each carrying a check // over its own slice, none of them carrying the family-wide one, and that // family-wide run made ONCE by the parent after its parts' work is home. Whether -// a cheap model gets there is not something this lane can make true, and an +// a cheap model gets there is not something this test can make true, and an // assertion that quietly relaxed until it passed would be worse than no // assertion — so every part of it is measured and written down in the log, in // the model's own words, for whoever reads the run. @@ -866,7 +866,7 @@ func awaitRootNode(ctx context.Context, t *testing.T, place session.Place) uint6 // ── watching a file that will not survive the run ─────────────────────────── // copyWatch is one file polled while the work runs, because the two directories -// this lane is about do not both outlive it: a landed task's worktree is +// this test is about do not both outlive it: a landed task's worktree is // REMOVED, so what its copy held has to be taken while the worker is standing in // it. It records the last content seen at each matching path, and the ordered // sequence of DISTINCT contents — which is how "did their own file change while diff --git a/internal/e2e/do_run_engine_e2e_test.go b/internal/e2e/do_run_engine_e2e_test.go index 4621bb0da8..021c7761f9 100644 --- a/internal/e2e/do_run_engine_e2e_test.go +++ b/internal/e2e/do_run_engine_e2e_test.go @@ -4,7 +4,7 @@ // the built binary, a real provider, the bash belt, and a run that writes a file // in the directory it was handed, in place and uncommitted. // -// where the column of this lane comes from +// where the column of this test comes from // // THE DOOR IS THE BUILT BINARY, not a package seam. Every other rig in this // repository reaches inside and hands a scripted agent to a struct; this one @@ -47,7 +47,7 @@ // cannot express a ceiling of nothing, and no untagged test can make it — the // refusal is proven where it lives instead, by the do package's own // `TestDoOnTheRunEngineStopsAtACostCapOfZero`, which hands the request a cap of -// zero and reads back the same exit 3 and `blocked_on` this lane would assert. +// zero and reads back the same exit 3 and `blocked_on` this test would assert. package e2e @@ -65,12 +65,12 @@ import ( "github.com/Agent-Field/codeaf/internal/home" ) -// doBrief is the one errand this lane runs: write a file with one known word in +// doBrief is the one errand this test runs: write a file with one known word in // it and stop. The word is the needle the lane reads HELLO.md for, and HELLO.md // is the path the envelope's files name. const doBrief = "write HELLO.md containing the word hello, then stop" -// doWall is the wall this lane gives the run, and it is the run's own clock. It +// doWall is the wall this test gives the run, and it is the run's own clock. It // is deliberately shorter than the Go test binary's timeout so the door's wall // fires first and the run still composes an envelope. const doWall = 6 * time.Minute @@ -80,7 +80,7 @@ const doWall = 6 * time.Minute // timeout must not be the thing that discovers it. const doRunEngineLead = 8 * time.Minute -// doEnvelope is `codeaf do --json` as this lane reads it: the contract's own +// doEnvelope is `codeaf do --json` as this test reads it: the contract's own // fields beside the two `do` spellings the answer and the ceiling ride under. // Both are decoded because the contract renamed `deliverable` to `answer` and // `blocked_on` is a fact only `do` has. @@ -104,7 +104,7 @@ func TestDoOnTheRunEngine(t *testing.T) { // The throwaway home is the person's own profile with every model row // pinned to the suite's model, so the crew the run engine seats from the - // profile is the one cheap model this lane rides rather than the person's + // profile is the one cheap model this test rides rather than the person's // own. root := newHome(t, map[string]any{ config.KeyTierWorkerModel: e2eModel, @@ -189,7 +189,7 @@ func TestDoOnTheRunEngine(t *testing.T) { } // doRunEngineEnv is the environment the run rides: the throwaway home, the -// belt's switch, and the key this lane resolved through [liveKey]. Any +// belt's switch, and the key this test resolved through [liveKey]. Any // inherited answer to those three questions is dropped first, so the child // cannot read two homes, two belt settings or two keys out of one environment. func doRunEngineEnv(root, key string) []string { diff --git a/internal/e2e/families_e2e_test.go b/internal/e2e/families_e2e_test.go index 8686bfef4d..1d10632490 100644 --- a/internal/e2e/families_e2e_test.go +++ b/internal/e2e/families_e2e_test.go @@ -2,7 +2,7 @@ // TASK FAMILIES, END TO END, ON BOTH GROUNDS. // -// WHAT THIS LANE PROVES. A task that turns out to be wider than one worker hands +// WHAT this test PROVES. A task that turns out to be wider than one worker hands // parts out under itself, each part works somewhere of its own, and the whole // family's product comes home into the person's material — on a git repository // and on a plain folder alike. Everything below is asserted ON DISK: the files @@ -68,7 +68,7 @@ const ( // not a fault — so the ask is put twice before the lane calls it a failure, // and the failure quotes what the road actually decided. familyAttempts = 2 - // familyCap is what one scenario may spend before this lane says something is + // familyCap is what one scenario may spend before this test says something is // wrong with the run rather than with the work. A settled family of three // parts on this model measures in cents; a dollar is a runaway. familyCap = 1.00 @@ -134,7 +134,7 @@ var textRoles = func() []roles.Role { }() // familyConfig is what the v3 door wires for work, applied to a conversation -// this lane drives directly. Everything here is a row cmd/codeaf reads +// this test drives directly. Everything here is a row cmd/codeaf reads // (chatv3.go's applyV3Governance); the two departures from a person's own // launch are named where they are made. func familyConfig(w *world) func(*session.Config) { @@ -155,7 +155,7 @@ func familyConfig(w *world) func(*session.Config) { cfg.AskConsent = false cfg.TaskAutoApproveSeconds = 0 // THE VERIFIED FRONTIER IS OFF, AND IT IS A SCOPE RULING RATHER THAN A - // CONVENIENCE. What this lane measures is where a part works and how its + // CONVENIENCE. What this test measures is where a part works and how its // work comes home; the check is a separate gate with its own tests, and // leaving it on would put a cheap checker's opinion between a finished // part and the person's folder — so a red here would say nothing about @@ -346,7 +346,7 @@ func (r *familyRun) awaitFamilyTree(ctx context.Context) { // person's folder held when the copy was taken. Both are internal/session's own // (task_run.go's codeafDroppings, task_mirror_manners.go's // groundBaselineRecord), spelled again here because they are unexported there -// and this lane reads the disk rather than the engine. +// and this test reads the disk rather than the engine. const ( codeafDroppings = ".codeaf" groundBaselineRecord = "ground-baseline.json" @@ -518,10 +518,10 @@ func (r *familyRun) journals() string { func TestFamilies(t *testing.T) { w := newWorld(t) pinEveryTextModel(t) - // THE WIDTH FLOOR IS OFF FOR THIS LANE, and it is the switch cmd/codeaf's own + // THE WIDTH FLOOR IS OFF FOR this test, and it is the switch cmd/codeaf's own // tests use (partsroute_test.go, method_test.go). internal/splitgate refuses a // division whose evidence names fewer than six separate items, which is a - // finding about whether handing work out PAYS — a question this lane is not + // finding about whether handing work out PAYS — a question this test is not // asking. Three sections and two write-ups are the smallest families that can // prove isolation and landing, and they are deliberately below that floor. t.Setenv("CODEAF_SPLITGATE", "0") @@ -755,7 +755,7 @@ func eachPartWorkedApart(t *testing.T, run *familyRun, parent taskRow) { // commit, on its own branch, merged in — so the history is the proof, and the // answer is what the landing laws below are then read against. // -// A PART WHOSE BRANCH DID NOT MERGE IS SAID OUT LOUD AND IS NOT THIS LANE'S RED. +// A PART WHOSE BRANCH DID NOT MERGE IS SAID OUT LOUD AND IS NOT this test'S RED. // A conflicted branch is kept and named, by design, and it happens here when a // part writes outside the file its brief gave it — which is a finding about the // worker rather than about isolation or landing. What must never happen is a @@ -787,7 +787,7 @@ func whatCameBack(t *testing.T, run *familyRun, tree string) map[string]string { // commits a node's ledger as `task: ` at the landing, and a // worker is told never to commit at all — but a worker that ran // `git commit` inside its own worktree has still done its work in - // isolation and still merged it back, which is everything this lane is + // isolation and still merged it back, which is everything this test is // about. Failing here would make the road's laws hostage to a liberty // one worker took inside a directory that is entirely its own. if len(first) > 1 && !strings.HasPrefix(first[1], "task: ") { diff --git a/internal/e2e/harness_test.go b/internal/e2e/harness_test.go index aeefbf4f5e..1998327172 100644 --- a/internal/e2e/harness_test.go +++ b/internal/e2e/harness_test.go @@ -55,7 +55,7 @@ func liveVerificationModel() string { return "deepseek/deepseek-v4-flash" } -// personConfig is the credentials this lane borrows: the profile in the +// personConfig is the credentials this test borrows: the profile in the // person's OWN codeaf home, read before the throwaway one is put in front of // it. It is COPIED into that throwaway CODEAF_HOME and never read out loud, // because it holds the person's key. @@ -65,12 +65,12 @@ func liveVerificationModel() string { // credentials", which reads as a key that was never set rather than as a path // that was never yours. Resolving through [home.InheritedDir] honours the same // override the binary does, so a person who runs codeaf out of CODEAF_HOME -// runs this lane out of it too. +// runs this test out of it too. // // It is the INHERITED root and not [home.Dir], which hands a test binary a // throwaway root of its own so that a suite cannot write into a person's state // (internal/home/undertest.go). Reading a credential the person already has is -// the one thing this lane genuinely wants from that root, and Dir would have +// the one thing this test genuinely wants from that root, and Dir would have // pointed it at an empty directory — every model-driven subtest skipping with // "no provider credentials" on a machine that has them. func personConfig() string { @@ -117,7 +117,7 @@ func newWorld(t *testing.T) *world { t.Setenv("CODEAF_PROFILE_DIR", "") // A PROFILE THAT IS NOT THERE IS NO LONGER A SKIP. It was, and that made a - // second way for this lane to go green without running: a machine whose key + // second way for this test to go green without running: a machine whose key // is exported in the shell and has never written a profile file is a machine // the product runs on perfectly well. if raw, err := os.ReadFile(profile); err == nil { @@ -128,7 +128,7 @@ func newWorld(t *testing.T) *world { t.Fatalf("read the profile at %s: %v", profile, err) } // And the throwaway home carries the key itself, whichever road it came - // down, so every door this lane opens under it authenticates the same way. + // down, so every door this test opens under it authenticates the same way. if err := config.WriteAPIKey("", key); err != nil { t.Fatalf("write the key into the throwaway profile: %v", err) } @@ -412,7 +412,7 @@ func (w *world) drain(agent *session.Agent, what string, events <-chan session.E out.Calls = append(out.Calls, call{Name: event.Tool, Args: event.Args, Output: event.Output, Failed: true}) t.Logf(" CALL(failed) %s %s\n → %s", event.Tool, shorten(event.Args, 400), shorten(event.Output, 600)) case session.EventConsentRequest: - // The person's own rules allow everything this lane does, so this is + // The person's own rules allow everything this test does, so this is // belt and braces rather than a policy the test invented. t.Logf(" CONSENT asked about %s (%s) — allowing", event.Tool, event.Rule) agent.ResolveConsent(event.ID, true) diff --git a/internal/e2e/jobpark_e2e_test.go b/internal/e2e/jobpark_e2e_test.go index c56ddc75d2..1592ec509b 100644 --- a/internal/e2e/jobpark_e2e_test.go +++ b/internal/e2e/jobpark_e2e_test.go @@ -2,7 +2,7 @@ // A TASK WORKER WAITS OUT THE COMMAND IT STARTED (#568). // -// WHAT THIS LANE PROVES, AND WHAT IT COST NOT TO HAVE IT. A worker ran a suite +// WHAT this test PROVES, AND WHAT IT COST NOT TO HAVE IT. A worker ran a suite // in the foreground, the command crossed the session's background-after clock, // and [session.BashPromotedLead] answered the call — `still running as job 3; // log at …`. That is a true sentence and, before the fix, a terrible question: @@ -149,7 +149,7 @@ func jobParkConfig(w *world) func(*session.Config) { cfg.AskConsent = false cfg.TaskAutoApproveSeconds = 0 // THE CHECK AND THE REPAIR ROUNDS ARE OFF, and it is a scope ruling: what - // this lane measures is what one worker does between a promotion and an + // this test measures is what one worker does between a promotion and an // ending, and a cheap checker's opinion between the worker and rest would // put turns in the transcript that are about something else. cfg.TaskAudit = false diff --git a/internal/e2e/livekey_test.go b/internal/e2e/livekey_test.go index 0d75a403e3..dae8ed2520 100644 --- a/internal/e2e/livekey_test.go +++ b/internal/e2e/livekey_test.go @@ -61,7 +61,7 @@ const noLiveKeyReason = "no provider key on this machine by any road the product "(OPENROUTER_API_KEY, OPENAI_API_KEY, or the profile's api_key row): " + "this lane drives a real model or it says nothing" -// liveKey is the key this lane talks with, or a skip when the machine has none. +// liveKey is the key this test talks with, or a skip when the machine has none. // // EVERY GATE IN THIS PACKAGE GOES THROUGH IT, and internal/e2e's untagged // [TestEveryLaneAsksForItsKeyTheWayTheProductDoes] fails the pull request on a diff --git a/internal/e2e/manual_e2e_test.go b/internal/e2e/manual_e2e_test.go index ec9c0f7db3..962eeb99d4 100644 --- a/internal/e2e/manual_e2e_test.go +++ b/internal/e2e/manual_e2e_test.go @@ -2,7 +2,7 @@ // THE MANUAL, REACHED THE WAY A PERSON REACHES IT. // -// WHAT THIS LANE PROVES. The manual is the only thing in this program that says +// WHAT this test PROVES. The manual is the only thing in this program that says // what the program is, and issue #293 measured three ways it was unreachable: a // person had no door onto it at all, a plain question did not arrive at the page // that answers it, and a page asked for by name arrived whole and unbounded. The @@ -84,7 +84,7 @@ const ( // becoming UNREACHABLE, which is the regression they are for. A third miss is // the finding, and it fails with the journal under it. manualAttempts = 3 - // manualCap is what one scenario may spend before this lane says something + // manualCap is what one scenario may spend before this test says something // is wrong with the RUN rather than with the manual. A two-turn conversation // on a cheap model is a fraction of a cent; a quarter of a dollar is a // runaway worth failing on. @@ -622,7 +622,7 @@ func newManualWorld(t *testing.T) *world { // instructively so: the model read every file and then answered about THOSE // files — unix modes, shell access, `chmod 600` — instead of about codeaf. The // question is about the product, the material is a prompt to answer about the -// material, and this lane is not the place to discover which. +// material, and this test is not the place to discover which. func aPlainWorkspace(t *testing.T) string { t.Helper() dir := filepath.Join(t.TempDir(), "quarterly-report") @@ -632,7 +632,7 @@ func aPlainWorkspace(t *testing.T) string { return dir } -// manualConfig is the departure this lane makes from an ordinary conversation: +// manualConfig is the departure this test makes from an ordinary conversation: // nobody is watching, so nothing a turn does may stop on a question — a call // that would ask is refused instead (AskConsent false), and there is no card // for anybody to press. The person's own approval rules already allow `manual`. diff --git a/internal/e2e/manual_wire_test.go b/internal/e2e/manual_wire_test.go index 79d98caec6..2d44351c4c 100644 --- a/internal/e2e/manual_wire_test.go +++ b/internal/e2e/manual_wire_test.go @@ -9,7 +9,7 @@ // was asked — it composes a query of its own, and on a corpus of a few dozen // short sections two words nobody said move the ranking off the page (#307). // -// So this lane asks the SAME forty-seven questions through the surface a person +// So this test asks the SAME forty-seven questions through the surface a person // uses, one fresh conversation each, on `deepseek/deepseek-v4-flash`, and reads // off transcript.jsonl three things for every one of them: the query the model // composed, whether it opened the manual at all, and which pages came back. The @@ -164,7 +164,7 @@ type wireRun []wireAsk // ledger as each question is asked. // // IT IS SUMMED HERE BECAUSE IT CANNOT BE SUMMED AFTERWARDS. The ledger lives -// under the throwaway home this lane runs on ([newWorld]), which goes with the +// under the throwaway home this test runs on ([newWorld]), which goes with the // test, and a lane that reports a measurement without its price is a lane whose // next pass has to be argued for from memory. The figure was recoverable // nowhere at all until this line existed (#321). @@ -185,7 +185,7 @@ func (r wireRun) count() (opened, first, within int) { return opened, first, within } -// report prints the table a reader of this lane came for: every question with +// report prints the table a reader of this test came for: every question with // the words the model actually searched, so a miss can be read rather than // guessed at. func (r wireRun) report(t *testing.T, name string) { diff --git a/internal/e2e/questions_e2e_test.go b/internal/e2e/questions_e2e_test.go index 718a07b9b6..a5820c2f2d 100644 --- a/internal/e2e/questions_e2e_test.go +++ b/internal/e2e/questions_e2e_test.go @@ -451,7 +451,7 @@ func questionsCard(t *testing.T) { // questionsBlocksUnderAnswers is the call a model could not make. On 2026-09-10 // deepseek-v4-flash was given the message below — a person's own words, on the -// Spark, in a real terminal — and three calls running it sent the answers list +// test machine, in a real terminal — and three calls running it sent the answers list // as a JSON STRING holding the list; every one was refused with `options takes // a list`, the turn ended on the loop guard and the person never saw a // question. Two things changed (session/toolargs.go, session/tools_ask.go), and @@ -604,11 +604,10 @@ func questionsRoom(t *testing.T) { screenSays(t, room, say(t, "questionWouldSwitchWord"), "what would change the asker's mind") shot(t, r, "open") - // TWO PANES, AND THE ARROWS MOVING BETWEEN THEM (owner ruling 2026-09-11, - // page pick A): the answers on the left, the evidence of the one the pointer - // is on beside them, and `→ detail` on the foot because there IS a pane to - // move into. A page of one column unfolds that evidence under the pointer - // and does not offer the key. + // TWO PANES, AND THE ARROWS MOVING BETWEEN THEM: the answers on the left, the evidence of + // the one the pointer is on beside them, and `→ detail` on the foot because there IS a + // pane to move into. A page of one column unfolds that evidence under the pointer and + // does not offer the key. screenSays(t, room, say(t, "questionPageDetailWord"), "the page is two panes at this width") shot(t, r, "split") diff --git a/internal/e2e/remote_test.go b/internal/e2e/remote_test.go index 12747117bb..4f195ae911 100644 --- a/internal/e2e/remote_test.go +++ b/internal/e2e/remote_test.go @@ -352,7 +352,7 @@ func (w *remoteWorld) thePathLaw(t *testing.T) { // persistent engine leaves a socket under its codeaf home // (internal/enginehost's Dir and SocketPath); a pipe engine leaves nothing. So // this scenario asserts the behaviour the machine actually has today, and picks -// up the stronger assertion by itself on the day lane A wires the host in. +// up the stronger assertion once the host connection is wired. func (w *remoteWorld) theLinkDiesMidTurn(t *testing.T) { persistent := w.enginePersistent(t) t.Logf("the engine on this build is persistent=%v (a host socket under %s/v3/hosts is what decides it)", @@ -606,7 +606,7 @@ func (w *remoteWorld) buildStatic(t *testing.T, name, pkg string) { build.Env = append(os.Environ(), "CGO_ENABLED=0", "GOOS=linux", "GOARCH="+containerArch()) if said, err := build.CombinedOutput(); err != nil { // A build that fails because ANOTHER LANE's file is half-written is not - // this lane's fault and is worth saying plainly, because it is the + // this test's fault and is worth saying plainly, because it is the // single most likely red in a parallel wave. t.Fatalf("could not build %s (another lane's in-flight file will do this; try again after `go build ./...` is clean): %v\n%s", pkg, err, said) diff --git a/internal/e2e/taskcustody_e2e_test.go b/internal/e2e/taskcustody_e2e_test.go index 62f929b78a..2d7165cc32 100644 --- a/internal/e2e/taskcustody_e2e_test.go +++ b/internal/e2e/taskcustody_e2e_test.go @@ -94,7 +94,7 @@ const ( // custodyRemainderHead opens the block the TRANSCRIPT keeps when part of a // drawing did not travel. It is internal/session's own // (checkpoint_custody.go's checkpointOwnRemainderHead), spelled again here -// because it is unexported there and this lane reads what a person would read. +// because it is unexported there and this test reads what a person would read. const custodyRemainderHead = "WHAT STAYS HERE, FOR WHEN THE PIECES ALREADY OUT LAND:" // custodyHeldWorkReason is the word the journal writes on a rung of the brief @@ -534,7 +534,7 @@ func (r *custodyRun) report(attempt int) { r.carries, r.ceilings, custodyRowLog(r.rows)) } -// ── the readings this lane makes of prose ─────────────────────────────────── +// ── the readings this test makes of prose ─────────────────────────────────── // // They mirror internal/session's own (checkpoint_custody.go's namesHeldWork and // numbersBesideTheNoun) rather than importing them, because the whole point of diff --git a/internal/e2e/tui_e2e_test.go b/internal/e2e/tui_e2e_test.go index 908c43d87a..32440abd2e 100644 --- a/internal/e2e/tui_e2e_test.go +++ b/internal/e2e/tui_e2e_test.go @@ -20,8 +20,7 @@ package e2e // // Forty minutes is enough for TestTUIE2E alone. The FULL // tagged package — ManualOnTheWire, QuestionsE2E, roomfeed, families, custody, -// contracts — does not fit in forty: Spark's #807 run hit the ceiling before -// TestTUIE2E started. Prefer `make test-e2e-tui` for the ambient surface, or +// contracts — needs a longer ceiling. Prefer `make test-e2e-tui` for the ambient surface, or // give the whole package two hours. It needs a provider key and tmux, costs a // few cents. The key is resolved the way the product resolves one ([liveKey]: // OPENROUTER_API_KEY, OPENAI_API_KEY, then the profile's api_key row). @@ -1716,7 +1715,7 @@ func taskOnTheRunEngine(t *testing.T, rigName string, beltWords ...string) { // WHICH COMMANDS ARE ON IT IS THE WORKER'S BUSINESS. The finish is the // worker's own `plandb done` when the worker writes one, and the RUN's when // it does not (internal/run's worker.go), and a brief this small on a fast - // model is regularly the second — measured twice on this lane, where the + // model is regularly the second — measured twice on this test, where the // page carried `echo`, `cat` and the run's own ending note. So the finish // command is observed and logged, never waited out: asserting it made a red // out of a model's choice and said nothing about the surface. diff --git a/internal/exec/media.go b/internal/exec/media.go index ce2e26b36c..7fb124f22a 100644 --- a/internal/exec/media.go +++ b/internal/exec/media.go @@ -409,7 +409,7 @@ func (t *Toolbox) viewImage(ctx context.Context, args map[string]any) Result { return errorf("image inspection paused at the daily budget — approve it in chat to continue") } } - // WithoutStream, the way every other one-shot call in this lane is made + // WithoutStream, the way every other one-shot call in this implementation is made // (internal/subharness's exec_model.go): what comes back is a TOOL RESULT // and not the leaf's answer, so it must not be typed into whatever stream // the context above happens to be pointed at — and it is also what puts the diff --git a/internal/exec/tools.go b/internal/exec/tools.go index c64caa60c9..0ac0a19f07 100644 --- a/internal/exec/tools.go +++ b/internal/exec/tools.go @@ -118,7 +118,7 @@ const ( // one-line JSON dump is the opposite — a single line of megabytes, inside any // line cap, which the byte cap is the only thing standing in front of. // -// Two thousand is the number pi settled on independently, and it is where a +// Two thousand lines is where a // listing stops being read and starts being searched: past it the right move is // never "read more", it is grep, and the notice says where to grep. const maxResultLines = 2000 @@ -1704,8 +1704,7 @@ type replacement struct { // model was remembering. Batched, it is one call, one read, one write, and one // sentence back. // -// The semantics that make batching safe are the ones pi settled on and they are -// all consequences of a single rule: every old is matched against the ORIGINAL +// Batching is safe because of a single rule: every old is matched against the ORIGINAL // file, never against the file as the previous edits in this same call left it. // A model writing five edits is looking at one file — the one it read — and // matching against a moving target would mean the third edit had to be written diff --git a/internal/head/acts.go b/internal/head/acts.go index ea2c5fea1b..16a49fd000 100644 --- a/internal/head/acts.go +++ b/internal/head/acts.go @@ -56,7 +56,7 @@ func serviceReceipt(kind store.CommandKind, service store.Service, action string // INFORMATIONAL questions while consent-class ones always escalate; 9.4 says the // class axis must exist first with a conservative default — unlabeled means // consent means escalate. All three landed. What 12.1.4 then found is the fact -// that decides this lane: every existing AskQuestion producer in the product is +// that decides this implementation: every existing AskQuestion producer in the product is // genuinely consent-bearing and NONE is labeled informational. So the autonomy // half of this tool has, today, no question it could legitimately answer, and // granting it anyway would mean the head settling consent in the user's name. diff --git a/internal/head/orchestrator_test.go b/internal/head/orchestrator_test.go index 44657492f5..a3cfc39b73 100644 --- a/internal/head/orchestrator_test.go +++ b/internal/head/orchestrator_test.go @@ -666,7 +666,7 @@ func TestInterruptJournalsTheStopAndStillEndsTheTurn(t *testing.T) { // ApplyInterrupt is the reconciler's arm, written here so the one line the // resident needs is a call rather than a design. It is tested from this side -// because this lane may not edit resident.go — see interrupt.go for the exact +// because this test may not edit resident.go — see interrupt.go for the exact // edit and 12.3.3 for why the seam is closed. func TestApplyInterruptIsTheArmTheReconcilerWouldCall(t *testing.T) { graph := openHeadStore(t) diff --git a/internal/iconlaw/iconlaw_test.go b/internal/iconlaw/iconlaw_test.go index 90cc5beaaa..c2bd8ef95c 100644 --- a/internal/iconlaw/iconlaw_test.go +++ b/internal/iconlaw/iconlaw_test.go @@ -81,13 +81,11 @@ var ownedRunes = map[rune]string{ '✎': "tokens.GWrite", '⌾': "tokens.GFileImage", '♪': "tokens.GFileAudio", - // THE RIGHT-HAND CORNERS ARE THE ONE FRAME'S (internal/tui3/frame.go). A - // right-hand corner is a box CLOSING, and there is one box on these - // surfaces: three shipped with a copy of the pieces each before the - // question views wave drew all of them with one frame (owner ruling - // 2026-09-11). The left-hand corners are not claimed, because a half-open - // bracket down a block's left edge (a task's `╭─`, a call's `╰─▶`) is a - // connector and not a box. + // THE RIGHT-HAND CORNERS ARE THE ONE FRAME'S (internal/tui3/frame.go). A right-hand + // corner is a box CLOSING, and there is one box on these surfaces: three shipped with a + // copy of the pieces each before the question views wave drew all of them with one frame. + // The left-hand corners are not claimed, because a half-open bracket down a block's left + // edge (a task's `╭─`, a call's `╰─▶`) is a connector and not a box. '╮': "tokens.GFrameTopRight (internal/tui3/frame.go draws the one frame)", '╯': "tokens.GFrameBottomRight (internal/tui3/frame.go draws the one frame)", '◌': "tokens.GWaitsOn (retired: v1's own dotted circle for work waiting on a sibling)", diff --git a/internal/inventory/inventory.go b/internal/inventory/inventory.go index bad0d4d7b8..fdec670f3f 100644 --- a/internal/inventory/inventory.go +++ b/internal/inventory/inventory.go @@ -94,7 +94,7 @@ type Inventory struct { Lockfiles []string `json:"lockfiles,omitempty"` EnvVarNames []string `json:"env_var_names,omitempty"` // Running, Withheld and Detached are what the chat left behind that a seal - // does not carry (docs/STAGE-1-CONTRACTS.md section 19). The harness writes + // does not carry. The harness writes // them from what it sees and nothing else does (L13); Omitted counts, per // list, the entries a bound cut. Running []Running `json:"running,omitempty"` diff --git a/internal/lane/belief_test.go b/internal/lane/belief_test.go index b895ec4b1b..7770910e6e 100644 --- a/internal/lane/belief_test.go +++ b/internal/lane/belief_test.go @@ -198,7 +198,7 @@ func TestAStaleBeliefIsMovedFurtherByTheSameAnswer(t *testing.T) { } // TestAProbeTouchesTheFirstTokenAndNeverTheRate is the probe's whole claim: it -// measured exactly our path to this lane just now, and it measured nothing at +// measured exactly our path to this test just now, and it measured nothing at // all about how fast the lane writes. func TestAProbeTouchesTheFirstTokenAndNeverTheRate(t *testing.T) { l := newLedger() diff --git a/internal/lane/choose_test.go b/internal/lane/choose_test.go index 7207a4c5ad..e99405f0ff 100644 --- a/internal/lane/choose_test.go +++ b/internal/lane/choose_test.go @@ -315,7 +315,7 @@ func TestTheSheetsDoubtsRankALaneLastAndAProbeStillAsksIt(t *testing.T) { t.Fatalf("the probe drew %+v, want the doubted lane asked first", probed) } - // AND EVIDENCE ENDS THE DOUBT. Three tool calls this lane actually served are + // AND EVIDENCE ENDS THE DOUBT. Three tool calls this test actually served are // a measurement of the thing the sheet was guessing at. served := lanes[ID{Model: testModel, Lane: "GMICloud"}] served.Quality = Beta{A: 12, B: 1} diff --git a/internal/lane/control/hazard_test.go b/internal/lane/control/hazard_test.go index d4c975bd63..ba610c2c55 100644 --- a/internal/lane/control/hazard_test.go +++ b/internal/lane/control/hazard_test.go @@ -164,7 +164,7 @@ func budgetFor(p Plan) float64 { // // IT IS A CONJUNCTION NOW (§B): the payoff crossing is necessary and no longer // sufficient, and the moment to act is the first one at which the wait has both -// become worth acting on AND become abnormal for this lane. +// become worth acting on AND become abnormal for this test. func TestTheCrossingIsWhereTheClosedFormSaysItIs(t *testing.T) { for _, test := range []struct { name string @@ -1033,7 +1033,7 @@ func TestAStallIsStillActedOnAsQuicklyAsItWas(t *testing.T) { // AND IT ACTED AT THE MOMENT BOTH TESTS SAY, solved here from their own // definitions. This is what "no regression" means precisely: the gate // may not postpone an act by one millisecond past the first moment the - // wait is BOTH worth acting on and abnormal for this lane. + // wait is BOTH worth acting on and abnormal for this test. cost := p.Alts[0].First.Mean() + p.Lambda*p.Alts[0].Extra allowed, want := budgetFor(p), p.Ceiling for ms := int(p.Floor / time.Millisecond); ms < int(p.Ceiling/time.Millisecond); ms++ { diff --git a/internal/lane/e2e_test.go b/internal/lane/e2e_test.go index 11af77c3b3..cb479efb9e 100644 --- a/internal/lane/e2e_test.go +++ b/internal/lane/e2e_test.go @@ -141,7 +141,7 @@ func (l e2eLane) priceOut() float64 { return l.dollars / 1e6 } // priceIn is the lane's input tariff. See the note on [e2eLane]. func (l e2eLane) priceIn() float64 { return 0.4 * l.priceOut() } -// row is the sheet row this lane publishes: the prior the ledger is primed +// row is the sheet row this test publishes: the prior the ledger is primed // from, in the router's own units. func (l e2eLane) row() Row { return Row{ diff --git a/internal/lane/garbage_test.go b/internal/lane/garbage_test.go index dc415aacbb..6b1c31c1b1 100644 --- a/internal/lane/garbage_test.go +++ b/internal/lane/garbage_test.go @@ -51,7 +51,7 @@ func onFrontier(front []Scored, lane string) bool { } // soloFront asks the gate about ONE lane, which is the difference between "this -// lane was out-ranked by a better one" and "this lane was refused". Both are +// lane was out-ranked by a better one" and "this test was refused". Both are // deprioritization and only the second is a verdict, so a test of the quality // axis has to be able to tell them apart. func soloFront(l *ledger, id ID, req Request) []Scored { diff --git a/internal/lane/rolepatience_test.go b/internal/lane/rolepatience_test.go index 676e47e439..fb908650d3 100644 --- a/internal/lane/rolepatience_test.go +++ b/internal/lane/rolepatience_test.go @@ -107,9 +107,8 @@ func TestAShortPatienceRoleRefusesTheMachineItWillNotWaitFor(t *testing.T) { } } -// TestTheDeadlineIsTheWholeOfTheVeto is the elegance the owner asked for, stated -// as a test: there is no second rule and no ratio anywhere. One pool, two roles, -// and the only thing that changes is the number the role table declares. +// One pool, two roles, and the only thing that changes is the number the role table +// declares. // // A machine believed to start promptly and then write at sixteen tokens a second // is inside every OTHER bound in this package — its first token is within diff --git a/internal/lane/watch_test.go b/internal/lane/watch_test.go index c96b7d26c5..9eb4e1e484 100644 --- a/internal/lane/watch_test.go +++ b/internal/lane/watch_test.go @@ -123,11 +123,11 @@ func TestEveryPlanHasACeilingEvenWithNoChoiceAtAll(t *testing.T) { // TestTheSpreadIsFlooredAtTheLanesOwnVariability: a posterior's variance is the // variance of the ESTIMATE and a controller handed it would believe a tail -// impossible — and the floor under it is how variable ONE ANSWER from THIS lane +// impossible — and the floor under it is how variable ONE ANSWER from this test // is, not how variable the worst lane on the sheet is. func TestTheSpreadIsFlooredAtTheLanesOwnVariability(t *testing.T) { certain := Belief{TTFT: Posterior{X: math.Log(400), P: 1e-12}, Rate: Posterior{X: math.Log(50), P: 1e-12}} - // Nothing published about this lane, so what a sure belief is floored at is + // Nothing published about this test, so what a sure belief is floored at is // the prior about one draw. certainly := PaceOf(certain) if !near(certainly.First.Sigma, SpreadFloor) || !near(certainly.Gap.Sigma, SpreadFloor) { @@ -284,7 +284,7 @@ func TestAFirstTokenPastTheCrossingIsHedged(t *testing.T) { cost := plan.Alts[0].First.Mean() + plan.Lambda*plan.Alts[0].Extra + plan.Margin // BOTH TESTS, because an act before the ceiling needs both (§B): the payoff - // crossing, and a silence abnormal for this lane. The tail mass is the + // crossing, and a silence abnormal for this test. The tail mass is the // per-request false-act budget over the alarm opportunities this request's // own shape offers, written out here from the error function so that the // scripted crossing does not read the controller's own arithmetic back. diff --git a/internal/orientation/digest.go b/internal/orientation/digest.go index f93ad7021e..37016b01cd 100644 --- a/internal/orientation/digest.go +++ b/internal/orientation/digest.go @@ -27,7 +27,7 @@ import ( // dropped, leaving the top-level tree and the README head. The bound is in // bytes (not UTF-16 code units) because the digest is Markdown read by the // model, and a model's token count tracks bytes more closely than JS string -// length. 8000 bytes ≈ 2000 tokens, which is the budget a pi-harness leaf +// length. 8000 bytes ≈ 2000 tokens, which is the budget a tool-using worker // spends on orientation total. const MaxBytes = 8000 diff --git a/internal/pair/manual_test.go b/internal/pair/manual_test.go index 774d08315f..3a48a13360 100644 --- a/internal/pair/manual_test.go +++ b/internal/pair/manual_test.go @@ -143,7 +143,7 @@ func TestTheManualQuotesTheLimitsThisPackageActuallyApplies(t *testing.T) { // The page must not describe the keychain or a fingerprint as something that // works, because neither is built. A page that promised one would be the worst -// possible failure of this lane: somebody choosing to pair a device because +// possible failure of this test: somebody choosing to pair a device because // they believed the key was behind a fingerprint. func TestTheManualDoesNotPromiseAKeychainThisBuildDoesNotHave(t *testing.T) { page, ok := manual.Chat().Page("reaching-this-machine-without-ssh") diff --git a/internal/pair/pair.go b/internal/pair/pair.go index 7f331dd6ba..6ec666a9ee 100644 --- a/internal/pair/pair.go +++ b/internal/pair/pair.go @@ -39,7 +39,7 @@ // ── what is NOT here, said plainly ────────────────────────────────────────── // // THE DEVICE KEY IS A FILE, NOT A KEYCHAIN ENTRY, AND THERE IS NO TOUCH ID. -// The design for this lane puts the device key in the OS keychain where there +// The design for this implementation puts the device key in the OS keychain where there // is one, so that the platform can demand a fingerprint before releasing it and // codeaf never sees a biometric. That is the right design and it is not built. // What is built is [Keeper] — the seam it goes behind — with one implementation: diff --git a/internal/plan/contract.go b/internal/plan/contract.go index 03b4140e92..7b7a572127 100644 --- a/internal/plan/contract.go +++ b/internal/plan/contract.go @@ -20,8 +20,7 @@ import ( // This is the dynamic half of the executor. The brief says what the job is; // the contract says how work of this kind is done well — the discipline a // specialised harness would have baked into its system prompt, generated per -// task instead of hand-written per domain. pi is a coding harness because its -// prompt carries a coding method; a generic loop handed a generated method for +// task instead of hand-written per domain. A coding harness carries a coding method; a generic loop handed a generated method for // the leaf in front of it gets the same advantage on any kind of work, and // the harness itself never changes. // diff --git a/internal/plan/contract_test.go b/internal/plan/contract_test.go index ca67aaaebe..178bfcbe1e 100644 --- a/internal/plan/contract_test.go +++ b/internal/plan/contract_test.go @@ -528,8 +528,8 @@ func TestRetrieveSkillsDoesNotFalselyMatchRepoScopePaths(t *testing.T) { skills := []store.Fact{ {Artifact: "/skills/secret", Scope: "repo:/Users/bob/secret-backend", Body: "handle authentication tokens"}, } - // An unrelated workspace under /Users/alice should NOT match /Users/bob/secret-backend - // merely because both have "Users" in their path. + // An unrelated workspace must not match another repository merely because + // both share a home-directory prefix. got := RetrieveSkills("run the test suite", "/Users/alice/frontend", skills) if len(got) != 0 { t.Fatalf("RetrieveSkills = %q, want no match for unrelated repo scope", got) diff --git a/internal/pool/contract/contract.go b/internal/pool/contract/contract.go index 64d426f705..c67c2de485 100644 --- a/internal/pool/contract/contract.go +++ b/internal/pool/contract/contract.go @@ -1,19 +1,6 @@ -// Package contract freezes the interface contracts between the three -// pareto-crewing lanes (evidence, learner, integration) before they run in -// parallel, per the approved plan at ~/pareto-handoff/IMPLEMENTATION-EXPERIMENT-PLAN.md -// section 5 and the math in ~/pareto-handoff/PROPOSED-LEARNING-MODEL.md. -// -// WHAT THIS PACKAGE IS NOT: it is not an implementation of the predictor, the -// policy or the grader. It is the wire shape and the semantics those -// implementations must agree on. The types are deliberately boring and -// explicit: they are the load-bearing interface three downstream lanes build -// against, and every field here is one a lane can be held to. -// -// VERSIONING RULE: every event and artifact carries the schema version it was -// written under. A reader that does not know that version refuses rather than -// half-reads (same rule as internal/pool/index). Any change to a field's -// meaning, or the removal/redefinition of a field, is a version bump — see -// CONTRACT.md in this package for the field-by-field pin. +// Package contract defines the versioned interfaces shared by prediction, +// learning and selection. Readers reject unknown schema versions so a field +// cannot silently acquire a different meaning across components. package contract import ( @@ -57,7 +44,7 @@ var ErrShape = errors.New("contract: structurally invalid document") // boundary. Everything on it must be provable to exist at decision time: // features carry the version of the feature map they were built under, and a // feature that was not observable at the decision is a future-feature leak -// that lane A's acceptance checks reject. +// rejected by the acceptance checks. type DecisionEvent struct { // SchemaVersion is DecisionEventVersion at write time. SchemaVersion int `json:"schema_version"` diff --git a/internal/praf/limits.go b/internal/praf/limits.go index 0f19a9b73c..b41577d8ac 100644 --- a/internal/praf/limits.go +++ b/internal/praf/limits.go @@ -3,12 +3,10 @@ package praf // Each of a review's agents runs under turn and time limits of its own, // keyed on the label its reasoner gives its session (reasoners.Label*). // -// EACH AGENT'S LIMIT IS ITS OWN, AND PR'S ALONE. A reviewer reading a -// dimension of the change and a lens choosing what to review do different -// amounts of reading, so one limit for all either cut the one or let the -// other wander; and the agent loop is shared with sec, so a limit tuned for -// its agents must never become review's. The owner's call (2026-10-06) is each -// program's own figures for each of its agents. +// EACH AGENT'S LIMIT IS ITS OWN, AND PR'S ALONE. A reviewer reading a dimension of the +// change and a lens choosing what to review do different amounts of reading, so one limit +// for all either cut the one or let the other wander; and the agent loop is shared with +// sec, so a limit tuned for its agents must never become review's. // // THE FIGURES ARE A CHOICE OF DEPTH, NOT A MEASUREMENT. A live review's // sessions read until their limit whatever it was, so the limit sets how diff --git a/internal/preflight/resume.go b/internal/preflight/resume.go index d45fcdb705..57a4071381 100644 --- a/internal/preflight/resume.go +++ b/internal/preflight/resume.go @@ -16,7 +16,7 @@ import ( // Resume is what a chat that moved here left behind. The transcript says what // was done; it cannot say what is not running now, what the copy left out, or // what this machine lacks, and those three are the whole of a Resume -// (docs/STAGE-1-CONTRACTS.md section 19.5). It is facts, never a summary. +// . It is facts, never a summary. // // A Resume is built with no model call, from the record the other machine // sealed and from a look at this one, and it carries no command to run: the diff --git a/internal/provider/caching.go b/internal/provider/caching.go index f1427accca..145569fccd 100644 --- a/internal/provider/caching.go +++ b/internal/provider/caching.go @@ -33,7 +33,7 @@ import ( // — take a `cache_control: {"type":"ephemeral"}` marker that says "write a // cache entry covering everything up to here". Up to four may be placed. // -// The three positions used here are pi's, and each is a different economy: +// The three cache positions each reuse a different part of the request: // // (i) the system block — every leaf of a run shares it byte for // byte (see internal/exec/prefix_test.go), diff --git a/internal/provider/dispatch.go b/internal/provider/dispatch.go index 4dda3b5fd3..464c01d1a2 100644 --- a/internal/provider/dispatch.go +++ b/internal/provider/dispatch.go @@ -761,15 +761,13 @@ func (c *Client) send(ctx context.Context, request *ai.Request, knobs callKnobs, // ── A REFUSAL THAT NAMED A MACHINE IS THAT MACHINE'S, AND THE OTHERS // HAVE SAID NOTHING ───────────────────────────────────────────────── // - // THE OWNER'S RULING, 2026-09-10: "that is in OpenRouter, that does not - // matter — if we get any such error or error in general we need to - // recover." An account-policy 404 and a 400 the router RELAYED from the - // endpoint it picked are neither a person's mistake nor a fact about the - // model: they are one machine saying no, and the answer to them is the - // same walk a 429 gets. Until this line they ended the call, and the - // rotation that eventually moved was the SESSION's — three whole turns - // apart, each learning the same fact over again through the ledger - // (refusal_test.go's `TestThreeAttemptsAfterAnUpstreamRefusalReach…`). + // An account-policy 404 and a 400 the + // router RELAYED from the endpoint it picked are neither a person's mistake nor a fact + // about the model: they are one machine saying no, and the answer to them is the same + // walk a 429 gets. Until this line they ended the call, and the rotation that eventually + // moved was the SESSION's — three whole turns apart, each learning the same fact over + // again through the ledger (refusal_test.go's + // `TestThreeAttemptsAfterAnUpstreamRefusalReach…`). // // A REFUSAL THAT NAMED NOBODY IS NOT THIS. That one is the router // reading our own bytes and saying no, and every machine alive will say @@ -944,8 +942,8 @@ func (c *Client) send(ctx context.Context, request *ai.Request, knobs callKnobs, } // ── "NOT YET" IS ANSWERED BY GOING SOMEWHERE ELSE ─────────────────── // - // THE OWNER'S RULING, 2026-09-10: a person must never work around a 429 - // by switching models themselves. So the three moves, in this order. + // The recovery rule: a person must never work around a 429 by switching models themselves. + // So the three moves, in this order. // // FIRST, ANOTHER MACHINE, AT ONCE. The refusing machine is off the next // body and the next body goes out with no backoff at all — see [moved]. diff --git a/internal/provider/e2e_account_real_test.go b/internal/provider/e2e_account_real_test.go index 2d72776c80..06f8ca91a8 100644 --- a/internal/provider/e2e_account_real_test.go +++ b/internal/provider/e2e_account_real_test.go @@ -6,7 +6,7 @@ package provider_test // // recovery_test.go proves the law against lanestub, whose account-excluded lane // answers with a body copied from the live router. This file asks the live -// router itself, on the owner's account, which on 2026-09-10 excludes the +// router itself, using an account configured to exclude the // DeepSeek first-party machine under the "paid model training" privacy switch — // for deepseek/deepseek-v4.1-flash AND for deepseek/deepseek-v4-pro-0813, which // is the whole claim: the exclusion is the account's and the machine's, not a diff --git a/internal/provider/endpoints.go b/internal/provider/endpoints.go index 63c5846419..8069c92c62 100644 --- a/internal/provider/endpoints.go +++ b/internal/provider/endpoints.go @@ -1035,7 +1035,7 @@ func (c *Client) sentParams(request *ai.Request, knobs callKnobs, model string) if request == nil { return nil } - // NAMES AND NEVER VALUES. The pi-derived retry taxonomies above this adapter + // NAMES AND NEVER VALUES. The retry taxonomies above this adapter // (internal/session's loop.go, internal/exec/bare's) classify an error by // grepping its TEXT for "429", "500", "503" — so an honest "max_tokens(500)" // in this sentence would make a permanent, already-exhausted refusal look diff --git a/internal/provider/hedge_test.go b/internal/provider/hedge_test.go index 54f3430a66..43fc0d2082 100644 --- a/internal/provider/hedge_test.go +++ b/internal/provider/hedge_test.go @@ -203,7 +203,7 @@ func newLaneRigWithPrice( // seconds is a statement about how long a person is asked to watch an empty // line, and a wire test that really waited it would take ten seconds to prove // something about a channel. So the scenarios below state the ceiling they are -// about and prove what this lane owns — that the ceiling is what acts when +// about and prove what this test owns — that the ceiling is what acts when // nothing at all is believed, and that it acts through the wire. // // IT IS ALSO WHERE A HELD FIRST WORD IS BOUNDED. The ceiling stated here is the diff --git a/internal/provider/neverrepeat_test.go b/internal/provider/neverrepeat_test.go index b6898cf80b..f41e02bce9 100644 --- a/internal/provider/neverrepeat_test.go +++ b/internal/provider/neverrepeat_test.go @@ -332,11 +332,10 @@ func alonePool(t *testing.T) (*Client, func() int, *[]time.Duration) { // A CONVERSATION NEVER WAITS OUT A WINDOW WHILE ANOTHER MODEL EXISTS. // -// THE OWNER'S RULING, 2026-09-10: nobody should ever work around a `too many -// requests` by switching models themselves. When every machine this request may -// go to is being held, the call gives the refusal straight back — `pacingExhausted` -// reads it as the pacing door it is (endpoints.go) and the session offers the -// next model, which beats any window. +// The recovery rule: nobody should ever work around a `too many requests` by switching +// models themselves. When every machine this request may go to is being held, the call +// gives the refusal straight back — `pacingExhausted` reads it as the pacing door it is +// (endpoints.go) and the session offers the next model, which beats any window. func TestAWatchedCallWithEveryMachineHeldGivesUpAtOnce(t *testing.T) { client, served, waits := alonePool(t) ctx := WithLaneChoice(context.Background(), lanes.Choice{Only: []string{"Alone"}}) diff --git a/internal/provider/patience.go b/internal/provider/patience.go index 71f8a1d4df..529e8d4842 100644 --- a/internal/provider/patience.go +++ b/internal/provider/patience.go @@ -29,16 +29,14 @@ import ( // // ── WHY THE TWO ARE DIFFERENT ANSWERS TO ONE FACT ── // -// The remainder still depends on whether anybody is sitting there. When every -// machine this request may go to is being held, a conversation's call hands the -// refusal straight back so the session can offer the NEXT MODEL — which beats -// any window, and is the owner's ruling of 2026-09-10: nobody should ever have -// to work a rate limit around by switching models themselves. A task child's -// call has nobody to disappoint, no fallback of its own and everything to lose -// — abandoning a node over pacing throws away a worktree of work for a -// condition that was always going to clear. So the child waits, for the window -// the machine itself named, and the surface is told what it is waiting for and -// until when. +// The remainder still depends on whether anybody is sitting there. When every machine this +// request may go to is being held, a conversation's call hands the refusal straight back +// so the session can offer the NEXT MODEL — which beats any window, and is nobody should +// ever have to work a rate limit around by switching models themselves. A task child's +// call has nobody to disappoint, no fallback of its own and everything to lose — +// abandoning a node over pacing throws away a worktree of work for a condition that was +// always going to clear. So the child waits, for the window the machine itself named, and +// the surface is told what it is waiting for and until when. // // SO [WithPatientRateLimits] NO LONGER MEANS "sixty attempts against one // machine". It means MAY WAIT FOR THE EARLIEST WINDOW WHEN THERE IS NOWHERE diff --git a/internal/provider/reasoninghedge_test.go b/internal/provider/reasoninghedge_test.go index f7b2582523..f0bf445b50 100644 --- a/internal/provider/reasoninghedge_test.go +++ b/internal/provider/reasoninghedge_test.go @@ -26,8 +26,6 @@ import ( // already spent and nothing anybody would watch disappear, so it buys no // commitment at all and a stall inside it is hedged like any other. -// TestAStallInsideTheThinkingIsRescued is the owner's report, staged: a -// hundred deltas of thought, then silence, with a healthy lane beside it. func TestAStallInsideTheThinkingIsRescued(t *testing.T) { rig := newLaneRig(t, "reason/stall", lanestub.Lane{Name: "A", Profile: lanestub.Profile{ diff --git a/internal/provider/streamguard_test.go b/internal/provider/streamguard_test.go index 90fe36bc75..291f311acf 100644 --- a/internal/provider/streamguard_test.go +++ b/internal/provider/streamguard_test.go @@ -797,7 +797,7 @@ func TestAStreamThatNeverStopsIsCutAtTheCeiling(t *testing.T) { // the one that keeps the wall from being a new way to fail: a reply that writes // for a long time and then FINISHES is an answer, and it must land untouched — // and what it took must be remembered, because that is what the next wall on -// this lane is derived from. +// this test is derived from. func TestALongHealthyReplyUnderTheWallIsNotCut(t *testing.T) { defer shortenWall(t, 2*time.Second, 4*time.Second)() @@ -1044,7 +1044,7 @@ func TestNoFixedDurationEverBoundsAProducingStream(t *testing.T) { func TestADripAtItsLanesPaceOutlivesEveryDurationBound(t *testing.T) { const wall = 200 * time.Millisecond defer shortenWall(t, wall, time.Minute)() - // Forty bytes — ten tokens — every twenty-five milliseconds is this lane's + // Forty bytes — ten tokens — every twenty-five milliseconds is this test's // own four hundred a second, and ten walls of it. piece := strings.Repeat("a", 40) server := httptest.NewServer(writeCallStream("steady", piece, 25*time.Millisecond, 10*wall)) diff --git a/internal/provider/streamwall_pace_test.go b/internal/provider/streamwall_pace_test.go index 126cb1ed32..14878f4cf4 100644 --- a/internal/provider/streamwall_pace_test.go +++ b/internal/provider/streamwall_pace_test.go @@ -28,7 +28,7 @@ import ( // wire: a `write` streaming at its lane's own rate for three times its wall is // long, not wedged. The wall fires, finds the stream kept pace, and re-arms; the // call lands whole. And the ledger learns the long reply it could never have -// learned before — the wall this lane is given next is derived from it. +// learned before — the wall this test is given next is derived from it. func TestAToolCallKeepingItsLanesPaceOutlivesItsWall(t *testing.T) { const wall = 300 * time.Millisecond defer shortenWall(t, wall, time.Minute)() diff --git a/internal/provider/transport.go b/internal/provider/transport.go index 667daedda8..bf7df9e67d 100644 --- a/internal/provider/transport.go +++ b/internal/provider/transport.go @@ -45,7 +45,7 @@ const ( // why, and [TestTheSharedTransportStatesEveryValueItRelieson] fails the build // if one of them goes back to being inherited. // -// ── THE MEASUREMENT, 2026-09-11, against the live router from the Spark ───── +// ── THE MEASUREMENT, 2026-09-11, against the live router from the test machine ───── // // A connection was opened, held idle for a fixed interval, and used again with // `httptrace` watching `GotConn`. Each hold had a pool of its own, so the only diff --git a/internal/relay/client.go b/internal/relay/client.go index d7efeaf9f0..dcb5a4334a 100644 --- a/internal/relay/client.go +++ b/internal/relay/client.go @@ -1,7 +1,7 @@ package relay // The two client halves. Both dial OUT and neither listens, which is the whole -// reason this lane exists: a machine behind a router with no forwarded port and +// reason this implementation exists: a machine behind a router with no forwarded port and // a laptop on a café network can reach each other because they both walked out // to the same door. // diff --git a/internal/relayconf/freeze_test.go b/internal/relayconf/freeze_test.go index a45b4b870b..7902a26007 100644 --- a/internal/relayconf/freeze_test.go +++ b/internal/relayconf/freeze_test.go @@ -21,7 +21,7 @@ import ( const holderHomeEnv = "CAF_FREEZE_HOLDER_HOME" // freezeBound is what the owner was promised: a device that stops answering is -// shown offline within 30 s (STAGE-1-CONTRACTS.md section 21.12.2). +// shown offline within 30 s. const freezeBound = 30 * time.Second // holderMain is the child: it follows the watch feed as a device of the diff --git a/internal/remote/callclass.go b/internal/remote/callclass.go index 577dd33ec5..691798ee6d 100644 --- a/internal/remote/callclass.go +++ b/internal/remote/callclass.go @@ -124,7 +124,7 @@ func (c callClass) road() road { // loop exactly as a getter is: internal/tui3's [app.answerQuestion] calls its // door straight from Update rather than from a command, so the window is also // the longest that terminal can sit without repainting after a key is pressed. -// Measured on the Spark, eighteen copies of the ordinary road's own e2e run six +// Measured in a test run, eighteen copies of the ordinary road's own e2e run six // at a time: with thirty seconds, two copies took 53 seconds where every other // copy took 22, and both lost the receipt — the surface was not drawing. Twelve // copies of the same commit's parent produced no copy over 33 seconds. diff --git a/internal/remote/client.go b/internal/remote/client.go index a536e3d390..cf011ff842 100644 --- a/internal/remote/client.go +++ b/internal/remote/client.go @@ -1025,15 +1025,13 @@ func (c *Client) call(ctx context.Context, method string, args any) (json.RawMes // today — somebody is writing, which is true whether the engine acts on it or // not — and a door that needs to know it was heard must use [Client.call]. // -// AND IT NEVER BLOCKS THE CALLER, WHICH IS A LAW AND NOT AN ASPIRATION. -// [Client.write] holds the writer's lock across a `Write` and a flush, and over -// `--host` that pipe is an ssh process's stdin — so writing here would put a -// blocking socket write on whatever goroutine sent the hint. The one caller is -// a keystroke, on internal/tui3's update loop, which is the goroutine that -// draws: a wedged-but-not-dead link would stop the terminal echoing what the -// person types. That is the defect family this wave exists to remove, and it is -// not being reintroduced one layer down (the owner's ruling: the only wait a -// person feels is the main model generating). +// AND IT NEVER BLOCKS THE CALLER, WHICH IS A LAW AND NOT AN ASPIRATION. [Client.write] +// holds the writer's lock across a `Write` and a flush, and over `--host` that pipe is an +// ssh process's stdin — so writing here would put a blocking socket write on whatever +// goroutine sent the hint. The one caller is a keystroke, on internal/tui3's update loop, +// which is the goroutine that draws: a wedged-but-not-dead link would stop the terminal +// echoing what the person types. That is the defect family this wave exists to remove, and +// it is not being reintroduced one layer down. // // SO THE WRITE HAPPENS ON A GOROUTINE, AND AT MOST ONE IS EVER IN FLIGHT. A // hint is free to lose — the person will send another with their next character diff --git a/internal/remote/clientlanes.go b/internal/remote/clientlanes.go index b14c833639..de47ffc93c 100644 --- a/internal/remote/clientlanes.go +++ b/internal/remote/clientlanes.go @@ -138,7 +138,7 @@ func (a *Agent) watchLane(name laneName, method string) (<-chan session.Event, f // THE REPLICA IS MOVED BEFORE THE EVENT IS DELIVERED, and that is done at the // frame rather than here (client.go's reader): a surface woken by this lane // draws [Agent.Title] on the very next frame, and a cached name a beat behind -// the event announcing it is the whole defect this lane exists to avoid. +// the event announcing it is the whole defect this implementation exists to avoid. func (a *Agent) WatchTitle() (<-chan session.Event, func()) { return a.watchLane(laneTitle, MethodTitleWatch) } diff --git a/internal/remote/driver.go b/internal/remote/driver.go index 6e0f71a7e9..0ae31574a2 100644 --- a/internal/remote/driver.go +++ b/internal/remote/driver.go @@ -43,7 +43,7 @@ import ( // MachineName is what this machine calls itself on the wire: the name a person // gave it, else its host name with any domain trimmed off ([devname.Name]), so a -// person reads `spark` rather than `spark.local.example.com` in a sentence about +// person reads `laptop` rather than `laptop.local.example.com` in a sentence about // which window is typing. // // IT IS A LABEL AND NOT AN IDENTITY (see [Hello.Surface]). The empty string is a diff --git a/internal/remote/questionlane_test.go b/internal/remote/questionlane_test.go index bba3661181..aca582ede3 100644 --- a/internal/remote/questionlane_test.go +++ b/internal/remote/questionlane_test.go @@ -161,7 +161,7 @@ func wholeQuestion() session.Question { } // A question raised with no turn running reaches a hosted surface WHOLE. Before -// this lane it reached nothing at all: the event was emitted onto a subscription +// this test it reached nothing at all: the event was emitted onto a subscription // this wire did not carry, so the road a plain `codeaf` takes drew no block, no // chip and no row, and the turn simply stopped. func TestAQuestionReachesAHostedSurfaceWhole(t *testing.T) { diff --git a/internal/remote/server.go b/internal/remote/server.go index 405cbb2b8f..b82f8010f8 100644 --- a/internal/remote/server.go +++ b/internal/remote/server.go @@ -452,15 +452,10 @@ type Session struct { // a status line may not be able to stall the turn it is measuring. newsfeeds map[*server]*newsFeed - // lastLane is the last finished answer's sighting this conversation - // produced — which machine answered — kept so that a window arriving - // AFTER the answer is told who answered (news.go's [Session.watchNews]). - // Without it a window attached to a conversation the host had been - // holding for an hour drew the model and no machine until the next - // answer, which the owner read as the provider having gone missing - // (2026-09-17). Rescues in flight and withdrawals are not kept: they are - // claims about a moment, and only a landed answer is a fact about the - // conversation. + // lastLane is the last finished answer's sighting this conversation produced — which + // machine answered — kept so that a window arriving AFTER the answer is told who answered + // (news.go's [Session.watchNews]). Rescues in flight and withdrawals are not kept: they + // are claims about a moment, and only a landed answer is a fact about the conversation. lastLane *session.LaneNews // lanes is the same arrangement for the harness subscription version 11 diff --git a/internal/remote/tasklane_owner_test.go b/internal/remote/tasklane_owner_test.go index f755261040..472afed58b 100644 --- a/internal/remote/tasklane_owner_test.go +++ b/internal/remote/tasklane_owner_test.go @@ -2,14 +2,11 @@ package remote // A STANDING RAIL BELONGS TO THE CONVERSATION IT WAS OPENED ON. // -// [Session.serving] closed the wrong-owner hole for CALLS: a joined reader -// asking about task 7 after the owner opened something else is refused rather -// than answered by the replacement's task 7. The standing lane had the same hole -// and no such guard, and it was worse in two ways — nobody asks for the frames, -// and [Session.retakeTaskLanes] reopens every subscribed surface on the -// replacement agent by itself. So a guest sat there being pushed another -// conversation's rows, under the name of the one it joined, with no call -// anywhere to be refused. +// The standing lane had the same hole and no such guard, and it was worse in two ways — +// nobody asks for the frames, and [Session.retakeTaskLanes] reopens every subscribed +// surface on the replacement agent by itself. So a guest sat there being pushed another +// conversation's rows, under the name of the one it joined, with no call anywhere to be +// refused. // // The task ids below are 7 in BOTH conversations on purpose. That collision is // the whole failure: the rows are indistinguishable on the wire, and the only diff --git a/internal/remote/turnlane_test.go b/internal/remote/turnlane_test.go index 294f3abb13..6d5ca63047 100644 --- a/internal/remote/turnlane_test.go +++ b/internal/remote/turnlane_test.go @@ -68,7 +68,7 @@ func TestASendDoesNotHoldTheSocketShut(t *testing.T) { t.Fatal("the send never reached the engine") } // The preamble is held for two seconds from here, exactly as the brief for - // this lane stated it, and let go early only if the assertions below fail. + // this test stated it, and let go early only if the assertions below fail. timer := time.AfterFunc(2*time.Second, letGo) t.Cleanup(func() { timer.Stop() }) diff --git a/internal/remote/wire.go b/internal/remote/wire.go index 98f9b8ce57..125246a3ae 100644 --- a/internal/remote/wire.go +++ b/internal/remote/wire.go @@ -898,12 +898,12 @@ type Hello struct { // ── version 4 ─────────────────────────────────────────────────────────── - // Surface is this machine's short name — `macbook`, `spark` — as + // Surface is this machine's short name — `macbook`, `laptop` — as // [MachineName] reads it off os.Hostname. // // IT EXISTS SO A SCREEN CAN NAME THE WINDOW THAT HAS THE KEYBOARD. "somebody - // else is typing" is a sentence that makes a person hunt; "typing from spark - // now" is one they can act on, because they know where spark is. Two windows + // else is typing" is a sentence that makes a person hunt; "typing from laptop + // now" is one they can act on, because they know where laptop is. Two windows // on ONE machine send the same name, which is how the engine can tell the // far desk from the forgotten terminal behind this one. // @@ -1382,7 +1382,7 @@ type SkillShelfArgs struct { // rather than one broadcast fact. "The driver is macbook" means two different // sentences depending on who hears it: to the window sitting on macbook beside // it, the honest word is the one codeaf already uses at home — `another window` -// — and to a surface on spark it is the machine's name. Only the engine knows +// — and to a surface on laptop it is the machine's name. Only the engine knows // both names, so only the engine can answer that; and the SURFACE still owns // the words, because the rest of the line it goes in is about keys on this // keyboard (Decision 6: the engine machine is the authority, the surface owns diff --git a/internal/resident/notebook.go b/internal/resident/notebook.go index 4ae2c1d47d..1b5b14e081 100644 --- a/internal/resident/notebook.go +++ b/internal/resident/notebook.go @@ -229,7 +229,7 @@ func RetractedBlock(graph *store.Store, limit int) string { // field. Consolidation retires and rewrites standing beliefs, so a memory-only // guard meant every restart bought another pass: five restarts in an hour was // five paid calls and five rounds of belief churn. The retrospective next door -// already had the durable answer; this lane borrows its shape. +// already had the durable answer; this implementation borrows its shape. func (r *Reconciler) consolidationDue(now time.Time) bool { if !r.lastConsolidation.IsZero() { return now.Sub(r.lastConsolidation) >= consolidationInterval diff --git a/internal/secaf/gates/harnesswrapper.go b/internal/secaf/gates/harnesswrapper.go index 9512540172..f417e97201 100644 --- a/internal/secaf/gates/harnesswrapper.go +++ b/internal/secaf/gates/harnesswrapper.go @@ -107,7 +107,7 @@ type InvokeRequest struct { // harnessOptions builds the appx.HarnessOptions for one invocation — the cwd // and project_dir keyword arguments HarnessWrapper passed to app.harness. The // rest of what Python passed (provider, model, max_turns, max_budget_usd, the -// provider environment, schema_max_retries=0, an opencode server) configured an +// provider environment, schema_max_retries=0, a tool server) configured an // external CLI that codeaf does not run, and was dropped with it. func (w *HarnessWrapper) harnessOptions(req InvokeRequest) appx.HarnessOptions { return appx.HarnessOptions{ diff --git a/internal/secaf/secaf.go b/internal/secaf/secaf.go index 345692e9e0..0c6b2930dd 100644 --- a/internal/secaf/secaf.go +++ b/internal/secaf/secaf.go @@ -58,9 +58,9 @@ var Stages = []string{stageStarting, stageRecon, stageHunt, stageProve, stageRem // stageWords is the stages in a person's words, for the task's row. // -// THEY ARE sec-af's OWN PHASE NAMES, the words its notes on the page already -// use (`RECON phase complete`), so the row, the page's step headings and the -// notes under them say one thing (the owner's call, 2026-10-05). +// THEY ARE sec-af's OWN PHASE NAMES, the words its notes on the page already use (`RECON +// phase complete`), so the row, the page's step headings and the notes under them say one +// thing. var stageWords = map[string]string{ stageStarting: "starting", stageRecon: "recon", diff --git a/internal/selector/classes.go b/internal/selector/classes.go index e94e8b4372..4270bd9899 100644 --- a/internal/selector/classes.go +++ b/internal/selector/classes.go @@ -11,7 +11,7 @@ type ClassShape struct { NeedsTools bool // tool-use gate NeedsImages bool // image gate Volume float64 // seat-volume weight for the bill - Role string // lane B prediction role (worker|checker|thinker) + Role string // prediction role (worker|checker|thinker) } // DefaultClasses returns the five classes with the session's shapes. diff --git a/internal/selector/model.go b/internal/selector/model.go index dab5a64cfc..2c45570bc5 100644 --- a/internal/selector/model.go +++ b/internal/selector/model.go @@ -1,5 +1,5 @@ -// Package selector implements the pareto selector (lane C): a deterministic -// crew picker built on lane B's SharedSnapshot (posterior quality means and +// Package selector implements the pareto selector : a deterministic +// crew picker built on SharedSnapshot (posterior quality means and // variances), reading the live model catalog through its own input struct so // it uses the schema fields (canonical_slug, created, alias_target) only — // never name-parsing heuristics. It emits contract.DecisionEvents for every diff --git a/internal/selector/quality.go b/internal/selector/quality.go index d5250bab65..0dad759e8d 100644 --- a/internal/selector/quality.go +++ b/internal/selector/quality.go @@ -9,7 +9,7 @@ import ( "strings" ) -// SharedSnapshot mirrors the lane B snapshot fields the selector reads. +// SharedSnapshot mirrors the shared component snapshot fields the selector reads. // parameters carry quality/ROLE/MODEL keys: the posterior mean q (0..1); // uncertainty carries quality/ROLE/MODEL: the posterior variance (sigma^2); // counts is the observation count N; model_ids is the scored set. The @@ -29,7 +29,7 @@ type SharedSnapshot struct { // hot path, so a refuse-to-load beats a multi-gigabyte pause per route. const maxSnapshotBytes = 64 << 20 -// LoadSnapshot reads a lane B SharedSnapshot file. +// LoadSnapshot reads a SharedSnapshot file. func LoadSnapshot(path string) (*SharedSnapshot, error) { fi, err := os.Stat(path) if err != nil { diff --git a/internal/selector/replay/main.go b/internal/selector/replay/main.go index 06e93ad6fa..3ffa1d5482 100644 --- a/internal/selector/replay/main.go +++ b/internal/selector/replay/main.go @@ -1,4 +1,4 @@ -// Command replay runs the lane C shadow selector over lane B's SharedSnapshot +// Command replay runs the shadow selector over a SharedSnapshot // and the live model catalog, producing the dev-test deliverables: // // (a) docs/selection/decision-table.txt — per-seat shadow decision diff --git a/internal/seniordev/seniordev.go b/internal/seniordev/seniordev.go index f5d1d14be9..69c76e3a85 100644 --- a/internal/seniordev/seniordev.go +++ b/internal/seniordev/seniordev.go @@ -72,18 +72,16 @@ var Program = delegate.Delegate{ // folder is codeaf's to choose and to read: a plain one is handed over // with PlainFolder on the line, so the guide says nothing about git. // - // IT CLAIMS THE HARD CODING WORK, BECAUSE THAT IS WHAT IT IS FOR. It said - // "one large code change worth an hour", a price no piece of work seems to - // clear before it is opened: an issue in a mature project whose cause runs - // through several files reads, from its report, as a few edits the chat - // could make itself. The owner asked on 2026-09-24 that codeaf reach for - // senior-dev by itself on complicated, many-sided coding work, the kind a - // hard software-engineering benchmark is made of, so the guide names that - // work, and the paragraph it is printed under says codeaf prefers a program - // for whatever its guide claims (internal/session/delegate_door.go). THE - // BRIEF CARRIES THE ISSUE IN FULL: a summary of a bug report is the one - // thing senior-dev cannot check against, since there is nobody it can ask - // what the report said. + // IT CLAIMS THE HARD CODING WORK, BECAUSE THAT IS WHAT IT IS FOR. It said "one large code + // change worth an hour", a price no piece of work seems to clear before it is opened: an + // issue in a mature project whose cause runs through several files reads, from its + // report, as a few edits the chat could make itself. codeaf reaches for senior-dev by + // itself on complicated, many-sided coding work, the kind a hard software-engineering + // benchmark is made of, so the guide names that work, and the paragraph it is printed + // under says codeaf prefers a program for whatever its guide claims + // (internal/session/delegate_door.go). THE BRIEF CARRIES THE ISSUE IN FULL: a summary of + // a bug report is the one thing senior-dev cannot check against, since there is nobody it + // can ask what the report said. Guide: programguide.SeniorDev, Lands: delegate.LandsTree, // Its recorder is git unless it is told --in-place, which keeps its diff --git a/internal/session/answers_test.go b/internal/session/answers_test.go index 15588fc8c6..fa935cc6d6 100644 --- a/internal/session/answers_test.go +++ b/internal/session/answers_test.go @@ -369,7 +369,7 @@ func TestTheKeysMeanWhatTheChipsSay(t *testing.T) { // The `ask` lane has no entry in [AnswerOptions] and never will: its answers are // the ones the model wrote on the question, so the kind's table has nothing to // say about them. [WriteAnswer] used to read that empty table as a refusal, and -// every chip home drew off [PresenceQuestion.Options] for this lane came back +// every chip home drew off [PresenceQuestion.Options] for this test came back // `could not leave that answer` when it was pressed. func TestAModelsOwnQuestionTravelsInPresenceAndAnAnswerComesBack(t *testing.T) { agent, dir := questionSession(t, "eeee1111eeee2222", func(config *Config) { diff --git a/internal/session/asklane.go b/internal/session/asklane.go index 0940fb532d..ea7afe631b 100644 --- a/internal/session/asklane.go +++ b/internal/session/asklane.go @@ -5,7 +5,7 @@ package session // // AN ANSWER IS A MESSAGE TO THE CONVERSATION THAT ALSO RELEASES A WAITING CALL // WHEN THERE IS ONE (docs/design/questions/DESIGN.md, "An answer is a message"). -// Until this lane existed an answer was only the RETURN VALUE of the `ask` call +// Until this implementation existed an answer was only the RETURN VALUE of the `ask` call // that raised the question — the turn parked on a channel, and an answer that // arrived with nobody parked went nowhere at all. Three things a person asked // for are the same shape and none of them could be built on that: carrying on @@ -129,7 +129,7 @@ func askedText(q Question) string { askAskedWord, askQuestionWord(q), strings.TrimSpace(q.Head), askCarryOnNote) } -// The words this lane says to the model, spelled once because the manual quotes +// The words this implementation says to the model, spelled once because the manual quotes // them and because the sentence the model is told to expect // ([askCarryOnNote]) is the sentence an answer actually opens with. const ( @@ -226,7 +226,7 @@ func (a *Agent) startAskClock(open *askOpen) { // ([askedOfThePerson.stopClocksLocked], which stops each armed clock and drops // each settled entry); this exists so that `agent.go` names an ask-lane verb // rather than reaching into another file's map, and so that the one place a -// reader looks for what Close lets go of finds this lane in the list. +// reader looks for what Close lets go of finds this implementation in the list. // // It is called with a.mu already held, like every other `Locked` verb here. func (a *Agent) stopAskClocksLocked() { a.asked.stopClocksLocked() } diff --git a/internal/session/asklane_test.go b/internal/session/asklane_test.go index 71b31079af..a828e38dbc 100644 --- a/internal/session/asklane_test.go +++ b/internal/session/asklane_test.go @@ -330,7 +330,7 @@ func TestChangingAnAlwaysRevokesThePermission(t *testing.T) { } } -// AN ANSWER TO A QUESTION THIS LANE IS NOT HOLDING IS REFUSED IN WORDS. It is +// AN ANSWER TO A QUESTION this test IS NOT HOLDING IS REFUSED IN WORDS. It is // the row left on a screen by a turn that was interrupted, or by a session host // that has restarted since — and the person pressing the key is owed the // sentence rather than a key that does nothing. @@ -359,7 +359,7 @@ func TestAnAnswerToAQuestionTheLaneNoLongerHoldsIsRefusedInWords(t *testing.T) { // AND A CHANGE AFTER A TURN WAITED FOR ITS ANSWER IS STILL A MESSAGE. The call // that was parked has taken its answer and gone; the correction cannot be handed -// to it, and a channel nobody reads is where this was lost on the Spark before +// to it, and a channel nobody reads is where this was lost in a test run before // the wait was claimed on the handover (askwait.go). func TestChangingAnAnswerTheTurnWaitedForReachesTheModel(t *testing.T) { a := askTestAgent(t, true) @@ -412,7 +412,7 @@ func deskRows(a *Agent) int { // AN ANSWERED QUESTION LEAVES THE DESK, and it is the answer that takes it off // rather than the call returning. // -// Measured on the Spark, 2026-09-11: with the let-go still deferred in the call, +// Measured in a test run, 2026-09-11: with the let-go still deferred in the call, // a question the call did not wait for kept its presence row for the rest of the // session — so home drew that answered row as the thing this conversation was // waiting for, every time any other question came up, and a key pressed on it diff --git a/internal/session/askwait.go b/internal/session/askwait.go index 4d8789e2a9..018ee13055 100644 --- a/internal/session/askwait.go +++ b/internal/session/askwait.go @@ -252,8 +252,7 @@ func (asked *askedOfThePerson) answerLocked(id uint64, answer Answer) (*askOpen, // channel afterwards, so a correction that arrives once the call has taken // its answer and gone is a MESSAGE rather than a send into a channel nobody // reads — which is measurable: without it, a change to a question the turn - // had waited for was recorded, drawn, and never heard by the model - // (the Spark, 2026-09-11). + // had waited for was recorded, drawn, and never heard by the model. wait := open.wait open.wait = nil if wait != nil { diff --git a/internal/session/attach_test.go b/internal/session/attach_test.go index dd91836ad7..2bc800059e 100644 --- a/internal/session/attach_test.go +++ b/internal/session/attach_test.go @@ -664,10 +664,7 @@ func attachedLate(t *testing.T, agent *Agent) []Event { return collect(t, stream.out) } -// TestAnAnsweredProposalIsNotAskedAgainOfASurfaceThatArrivesLater is the defect -// the owner met: approve a task, look at another tab, come back, and be asked -// the same question again — every time, for as long as the turn ran. The answer -// was recorded and the engine knew it; the REPLAY did not consult it, so the +// The answer was recorded and the engine knew it; the REPLAY did not consult it, so the // card that raised the question went out again as though nobody had decided. func TestAnAnsweredProposalIsNotAskedAgainOfASurfaceThatArrivesLater(t *testing.T) { agent, _ := newTestAgent(t, &scriptedCompleter{}, func(config *Config) { diff --git a/internal/session/autonomy.go b/internal/session/autonomy.go index b98367eae6..ef01f2c5df 100644 --- a/internal/session/autonomy.go +++ b/internal/session/autonomy.go @@ -22,11 +22,10 @@ const awayAfter = 10 * time.Minute // after exactly as long as it would take to decide they are not coming, and // there is no second figure anywhere that could drift from it. // -// A CLOCK IS OPT-IN AND STAYS OPT-IN (owner ruling, 2026-09-11): nothing here -// gives a question a clock. [Agent.autonomyFor] decides WHETHER there is one — -// only where the person set a rule, plus the assumption kind, whose whole shape -// is that its options stand unless somebody strikes them — and this decides only -// how long. +// A CLOCK IS OPT-IN AND STAYS OPT-IN: nothing here gives a question a clock. +// [Agent.autonomyFor] decides WHETHER there is one — only where the person set a rule, +// plus the assumption kind, whose whole shape is that its options stand unless somebody +// strikes them — and this decides only how long. func autonomyClock(set time.Duration) time.Duration { if set > 0 { return set diff --git a/internal/session/beltfacts.go b/internal/session/beltfacts.go index 5c74d454f9..517a5763d4 100644 --- a/internal/session/beltfacts.go +++ b/internal/session/beltfacts.go @@ -112,15 +112,14 @@ func (c Config) mayQuickTask() bool { return c.mayProposeTask() && !c.oneTaskRoa // oneTaskRoad says whether this agent is a conversation whose hand-offs are // runs in the plan store: the bash belt is asked for and a run engine is wired. // -// THERE IS ONE WAY TO PUT WORK OUT UNDER THE BELT, AND IT IS `propose_task`. -// The owner's words, 2026-09-18: one way, a task; the model launches several -// when it needs to, and each is more of the plan. So `quick_task` is ABSENT -// here, not refusing: it runs on the session tree, outside the plan store, where -// no tree on the screen can show it and no check reads it, and a belt that -// carried it would be offering a second engine under the first one's name. The -// predicate is [stagedProposal.Commit]'s own guard, so the verb leaves the belt -// exactly where a proposal starts a run and nowhere else; with no engine wired -// a proposal still runs on the session tree and both verbs stay. +// THERE IS ONE WAY TO PUT WORK OUT UNDER THE BELT, AND IT IS `propose_task`. one way, a +// task; the model launches several when it needs to, and each is more of the plan. So +// `quick_task` is ABSENT here, not refusing: it runs on the session tree, outside the plan +// store, where no tree on the screen can show it and no check reads it, and a belt that +// carried it would be offering a second engine under the first one's name. The predicate +// is [stagedProposal.Commit]'s own guard, so the verb leaves the belt exactly where a +// proposal starts a run and nowhere else; with no engine wired a proposal still runs on +// the session tree and both verbs stay. func (c Config) oneTaskRoad() bool { return !c.InTask && bashBeltAsked() && chatRunEngine != nil } @@ -444,7 +443,7 @@ var beltFacts = []beltFact{{ // prose (tools_capabilities.go), read by the turn that fetched the pair, // because it is not a fact anybody needs before there is a refusal to relay, // and what `load_capability` does once it is called is that verb's own - // description (lane C's registry files it there). + // description. present: "- A preference changed goes through `settings` for the row and `change_setting` for the write, never `edit` or `write` on a config file.", shelved: "- A preference changed goes through `settings` for the row and `change_setting` for the write, never `edit` or `write` on a config file. Both wait in the `settings` group and `load_capability` fetches them.", absent: "- YOU CANNOT CHANGE A PREFERENCE FROM INSIDE A TASK: say so and point at `/settings`, and never `edit` or `write` a config file instead.", @@ -475,16 +474,14 @@ var beltFacts = []beltFact{{ // handoffFacts is `## Work or words`: the ways work leaves this turn, composed // from the belt so that what a model reads is what it actually has. // -// IT IS A PICTURE AND NOT A RULE LIST, which is the owner's ruling of -// 2026-09-10 and a reversal of how this section was written. What it hands the -// model is what it HAS and what each thing COSTS — one mind with a clock; a -// quick task that is a copy of its abilities where it stands; a task that is a -// worker in a copy of the folder, checked and merged; the arithmetic that -// pieces kept cost their sum and pieces handed out cost the longest of them — -// and the model does its own reasoning from that. There are no shapes of work -// enumerated here, because a list of shapes is a list somebody has to keep -// true: the moment it says "a survey is quick" it has stopped teaching and -// started matching, and the next request is one nobody wrote a row for. +// IT IS A PICTURE AND NOT A RULE LIST. What it hands the model is what it HAS and what +// each thing COSTS — one mind with a clock; a quick task that is a copy of its abilities +// where it stands; a task that is a worker in a copy of the folder, checked and merged; +// the arithmetic that pieces kept cost their sum and pieces handed out cost the longest of +// them — and the model does its own reasoning from that. There are no shapes of work +// enumerated here, because a list of shapes is a list somebody has to keep true: the +// moment it says "a survey is quick" it has stopped teaching and started matching, and the +// next request is one nobody wrote a row for. // // IT REPLACED A LIST THAT SORTED ON WIDTH, and the list was measurably wrong. // Until this ruling the first bullet read "WIDE WORK — a sweep across many diff --git a/internal/session/delegate_door.go b/internal/session/delegate_door.go index 14295e1b4a..3007c60ab8 100644 --- a/internal/session/delegate_door.go +++ b/internal/session/delegate_door.go @@ -115,20 +115,18 @@ func (c Config) mayDelegate() bool { // description, and that small work is never handed off is this section's // own; neither is said a second time here. // -// AND CODEAF PREFERS A PROGRAM FOR THE WORK IT IS FOR. The paragraph said a -// large task "can" go to one, which is a permission, and a permission loses -// to the two roads the rest of the section teaches: an issue in a mature -// project is worked through inline, or handed to codeaf's own worker, which -// has none of a program's machinery for that work. The owner's call of -// 2026-09-24 is that codeaf reach for a program by itself on complicated, -// many-sided coding work, and almost always when the person asks for one. So -// the first sentence is a preference over both of those roads, the program's -// guide under it says which work that is, and WHATEVER ITS CRITICAL PATH is -// said because the section's own test for a hand-off is the critical path: -// one hard fix has a single one, and a model holding that test alone would -// keep the fix. The second sentence is the person's ask, which outranks the -// section's floor on small work; code holds both halves of it, where a prompt -// would be forgotten (delegate_asked.go). +// AND CODEAF PREFERS A PROGRAM FOR THE WORK IT IS FOR. The paragraph said a large task +// "can" go to one, which is a permission, and a permission loses to the two roads the rest +// of the section teaches: an issue in a mature project is worked through inline, or handed +// to codeaf's own worker, which has none of a program's machinery for that work. codeaf +// reaches for a program by itself on complicated, many-sided coding work, and almost +// always when the person asks for one. So the first sentence is a preference over both of +// those roads, the program's guide under it says which work that is, and WHATEVER ITS +// CRITICAL PATH is said because the section's own test for a hand-off is the critical +// path: one hard fix has a single one, and a model holding that test alone would keep the +// fix. The second sentence is the person's ask, which outranks the section's floor on +// small work; code holds both halves of it, where a prompt would be forgotten +// (delegate_asked.go). // // THE TWO SENTENCES STAND APART FROM THE FOLDER RULE, which is spliced in // after them, so either can be reworded without touching the other. diff --git a/internal/session/delegate_door_test.go b/internal/session/delegate_door_test.go index e429a63136..2f8bc873c3 100644 --- a/internal/session/delegate_door_test.go +++ b/internal/session/delegate_door_test.go @@ -551,14 +551,12 @@ func TestProposeTaskOffersViaOnlyWhenTheLaunchCarriesAProgram(t *testing.T) { } } -// CODEAF PREFERS A PROGRAM FOR THE WORK IT IS FOR, AND USES ONE WHEN ASKED. -// The paragraph said a large task "can" go to a program, and the model took a -// permission for no reason to: the owner's call of 2026-09-24 is that it -// reach for one by itself on the work the program's guide claims, over its -// own hands and its own worker, and whenever the person names one. Both -// sentences are said whatever the program lands, before the folder rule and -// apart from it, so either can be reworded without the other; and `via` -// says the same when the proposal is being written. +// CODEAF PREFERS A PROGRAM FOR THE WORK IT IS FOR, AND USES ONE WHEN ASKED. The paragraph +// said a large task "can" go to a program, and the model took a permission for no reason +// to: it reaches for one by itself on the work the program's guide claims, over its own +// hands and its own worker, and whenever the person names one. Both sentences are said +// whatever the program lands, before the folder rule and apart from it, so either can be +// reworded without the other; and `via` says the same when the proposal is being written. func TestThePagePrefersAProgramForItsWorkAndForTheAsk(t *testing.T) { preference := []string{ "AND WORK A PROGRAM BUILT INTO CODEAF IS FOR GOES TO IT WHOLE, named in\n`propose_task`'s `via`", diff --git a/internal/session/errand_recovery_test.go b/internal/session/errand_recovery_test.go index b2777b58bd..185b80d020 100644 --- a/internal/session/errand_recovery_test.go +++ b/internal/session/errand_recovery_test.go @@ -55,7 +55,7 @@ type errandCall struct { // left is what [context.Context.Deadline] said was still to come. A ladder // that hands its first rung an even share of the errand's patience gives it // half; a ladder that bounds the ERRAND gives it nearly all of it, and no - // clock on the test machine can turn one of those readings into the other. + // clock in a test run can turn one of those readings into the other. left time.Duration } diff --git a/internal/session/handlepick.go b/internal/session/handlepick.go index 761880daa9..ee0f89eacd 100644 --- a/internal/session/handlepick.go +++ b/internal/session/handlepick.go @@ -16,7 +16,7 @@ import ( // A member's handle, chosen by the conversation's own title model. // // A handle is ONE lowercase word naming what the conversation is about: -// @security for "santosh dev2 branch code complexity & security review", +// @security for "example dev2 branch code complexity & security review", // @milestones for "CodeAF repo issue tags & milestones", @gravity for "quantum // gravity research updates / session monitor". The word list in internal/teams // ([teams.DeriveHandle]) guesses one at once, so a member is addressable the diff --git a/internal/session/harness_revise_test.go b/internal/session/harness_revise_test.go index 018a1420b0..8c1294b616 100644 --- a/internal/session/harness_revise_test.go +++ b/internal/session/harness_revise_test.go @@ -499,7 +499,7 @@ func TestDroppingTheFirstCardStillDrops(t *testing.T) { // // It is the honest version of polling the graph: a phase a node passed through // in microseconds is still a phase it published, and this sees it. What a -// surface reads is this lane, so what this asserts is what a surface would draw. +// surface reads is this test, so what this asserts is what a surface would draw. func waitForPhaseOnTheWire(t *testing.T, lane <-chan Event, id uint64, phase string) { t.Helper() deadline := time.After(harnessTestPatience) diff --git a/internal/session/jobs.go b/internal/session/jobs.go index 5e88840a9e..5caedd2ad4 100644 --- a/internal/session/jobs.go +++ b/internal/session/jobs.go @@ -1709,8 +1709,8 @@ func (s *jobSink) trimLocked() { return } start := len(s.ring) - jobRingBytes - // Do not cut a rune in half: a tail starting mid-character renders as a - // replacement glyph in the model's context for no reason. + // Do not cut a rune in half: a tail starting mid-character renders as + // a replacement glyph in the model's context for no reason. for start < len(s.ring) && !utf8RuneStart(s.ring[start]) { start++ } diff --git a/internal/session/lawregistry_test.go b/internal/session/lawregistry_test.go index 06557264dc..72434f6d5c 100644 --- a/internal/session/lawregistry_test.go +++ b/internal/session/lawregistry_test.go @@ -145,8 +145,7 @@ var lawRegistry = []lawUnit{ // task and a quick task all report themselves; lanes deleting a tool's own // copy of that rule are deleting it on the strength of THIS line, so its // wording is a fixture and not a draft. - // AND THE KEY IS THE FAMILY FRAGMENT RATHER THAN THE WHOLE SENTENCE (lane F, - // 2026-09-10). `jobs` said this twice in its own description and `watch` + // AND THE KEY IS THE FAMILY FRAGMENT RATHER THAN THE WHOLE SENTENCE. `jobs` said this twice in its own description and `watch` // said it once more; all three are deleted now on the strength of the page's // line, and `watch.instead-of-polling` went with them because the law it // filed no longer has a verb-class home. Matching on the shorter fragment is @@ -183,10 +182,7 @@ var lawRegistry = []lawUnit{ {id: "tasks.look-inside", class: lawCore, key: "Look inside running or landed work with `tasks` and its id"}, {id: "tasks.continue-is-not-a-new-task", class: lawCore, key: "never a fresh `propose_task`"}, {id: "read.what-read-cannot-turn-into-text", class: lawCore, key: "What `read` cannot turn into text → `read_document`"}, - // ── and the two triggers for a program codeaf carries (delegate_door.go's - // [delegateFact], the owner's call of 2026-09-24): the work a program's own - // guide claims goes to it, and so does work the person asks one for. What - // each program is for is its guide's; these say only that codeaf prefers it. + // What each program is for is its guide's; these say only that codeaf prefers it. {id: "program.work-it-is-for", class: lawCore, key: "AND WORK A PROGRAM BUILT INTO CODEAF IS FOR GOES TO IT WHOLE"}, {id: "program.the-one-asked-for", class: lawCore, key: "so does work the person asks one for, by name or as `/name`."}, // ── the mark codeaf leaves on work it did in somebody's name. It is core diff --git a/internal/session/loop.go b/internal/session/loop.go index 5177419442..a0d309b0fd 100644 --- a/internal/session/loop.go +++ b/internal/session/loop.go @@ -5372,8 +5372,8 @@ const foldMarkerPrefix = "[folded " // a dead one. The original lines stay above the compaction marker in that // file; the path is the recovery floor. // -// [folded 31 messages · grep or read /home/x/.codeaf/v3/sessions/abc.jsonl, lines 12..40] -// [folded 31 messages · grep or read /home/x/.codeaf/v3/sessions/abc.jsonl] +// [folded 31 messages · grep or read /workspace/.codeaf/v3/sessions/abc.jsonl, lines 12..40] +// [folded 31 messages · grep or read /workspace/.codeaf/v3/sessions/abc.jsonl] // [folded 31 messages · full record in the store] // [folded 31 messages · full record in the session journal] // diff --git a/internal/session/memory.go b/internal/session/memory.go index 81e62e24a3..0fc239b54d 100644 --- a/internal/session/memory.go +++ b/internal/session/memory.go @@ -528,11 +528,11 @@ func (a *Agent) refreshMemoryLocked() { // because the notice it guards is about what the store's lines now do. func memoryUpgradeMarker() string { return home.Join("v3", "memory-upgrade-noticed") } -// noteMemoryOffUpgradeLocked is the owner's ruling for a person who had memory -// OFF before this build: off used to keep their saved lines out of every -// prompt, and now it governs only the noticing, so the lines ride again. That -// is said ONCE PER MACHINE — on the first start after the upgrade, in the -// first conversation that turn starts in — and nothing about the lines changes. +// noteMemoryOffUpgradeLocked is for a person who had memory OFF before this build: off +// used to keep their saved lines out of every prompt, and now it governs only the +// noticing, so the lines ride again. That is said ONCE PER MACHINE — on the first start +// after the upgrade, in the first conversation that turn starts in — and nothing about the +// lines changes. // // THE MARKER IS CREATED FIRST, EXCLUSIVELY, WHATEVER THE SETTING SAYS. The // first start after the upgrade is the one moment "had memory off before" is diff --git a/internal/session/personsword_test.go b/internal/session/personsword_test.go index 7e12001d7f..d1b637f881 100644 --- a/internal/session/personsword_test.go +++ b/internal/session/personsword_test.go @@ -2,10 +2,7 @@ package session // THE PERSON'S WORD WINS, AND IT WINS AT THE REQUEST. // -// steer.go states the law and the run it was measured against: a task step -// thirteen minutes into a wait, the owner picking another model, and the step -// still talking to the model they had moved off a minute later. These fixtures -// are the two halves of the rule and the clock on both. +// These fixtures are the two halves of the rule and the clock on both. // // EVERY ASSERTION IS ON THE WIRE. What each request carried is // [scriptedCompleter.model] — the model id the adapter was actually handed for diff --git a/internal/session/placescontext_test.go b/internal/session/placescontext_test.go index 5086f80236..7c31fa70b8 100644 --- a/internal/session/placescontext_test.go +++ b/internal/session/placescontext_test.go @@ -3,7 +3,7 @@ package session // A FOLDER SOMEBODY ATTACHED HAS TO REACH THE MODEL. // // The defect these are written against is the one the whole wave is for: the -// picker said `folder · /home/…/thing`, the set was written onto meta.json, and +// picker said `folder · /workspace/thing`, the set was written onto meta.json, and // the next request went out with no mention of the folder anywhere — so the // model went looking for it, usually by walking a home directory for a name that // sounded right. A displayed line is not a message. diff --git a/internal/session/prefixbudget_test.go b/internal/session/prefixbudget_test.go index b4f5384d6a..f5b0a0f7ec 100644 --- a/internal/session/prefixbudget_test.go +++ b/internal/session/prefixbudget_test.go @@ -49,348 +49,8 @@ import ( "github.com/Agent-Field/codeaf/internal/programguide" ) -// fixedPrefixBudget bounds the system prompt plus the marshalled tool block of -// the belt the shipping conversation door assembles (belt_wiring_test.go's -// [shippedShapeAgent] is that shape). -// -// ── IT WEIGHED THE WRONG BELT FOR MONTHS, AND THIS IS THAT REPAIR ─────────── -// -// The sentence above has always said "the shipping conversation". The fixture -// under it was [v3ShapedAgent]: a conversation with NO memory store, NO accounts -// hub, NO standing items and NO saved programs — eighteen tools, 39,073 bytes, -// comfortably green. A machine somebody has finished setting up carries five -// more (`stand`, `search_conversations`, `remember`, and the subharness pair) -// and weighs 53,025. So the gate reported eight kilobytes of headroom on a -// prefix that was five kilobytes OVER the cap it was enforcing, and it reported -// it every day. That is #576's shape exactly: a gate pointed at something nobody -// runs passes without having tested anything. -// -// ── SO THE FIGURE IS A RATCHET NOW, AND NOT A BUDGET WITH ROOM IN IT ──────── -// -// It used to be "the post-diet measurement plus about a tenth", which was right -// when the number came out of a diet that had just been paid for: the headroom -// was room for a genuinely new law. It is wrong here, because this measurement -// is not the end of a diet — it is the first honest weighing of a prefix that -// has never been weighed, and it is already past what the last diet aimed at. A -// tenth of headroom on top of that would be five more kilobytes nobody chose. -// -// So it is the measurement and nothing else. Anything that grows the shipped -// prefix fails the build and has to be paid for out of what is already here, -// which is what a ratchet is for and what the old figure could not do. -// -// ── AND IT IS THE WIDEST MACHINE'S MEASUREMENT, NOT THIS ONE'S ────────────── -// -// The first spelling of this ratchet was 53,100 — the laptop it was written on -// weighing 53,025 — and it failed on the runner that proved it, at 53,132. The -// prefix is not the same size everywhere: `grep` says a longer sentence about -// itself where ripgrep is absent (134 bytes, and [widestBelt] now weighs that -// spelling wherever it runs), and `load_capability` lists the tool groups THIS -// BUILD has, which is 27 more bytes on a machine that can edit video than on one -// that cannot. A gate whose number depends on who runs it is a gate that passes -// where it is written and fails where it is proved, so the figure is the widest -// machine's and the swap that makes the biggest term machine-independent lives -// in [widestBelt]. -// -// The residual is the shelf, and it is owed rather than done: `load_capability` -// would have to name what this build COULD have rather than what it has, which -// is a change to what the model is told and belongs to whoever owns the shelf. -// It is bounded — one short clause per group — and it is why this number was -// measured on the machine that carries every group. It is filed as issue #1010, -// which is also where the `grep` sentence and [widestBelt] itself are deleted: -// removing the variance at its source is the only thing that makes this number -// one number for everybody. -// -// ── WHAT IS OWED, AND WHERE IT HAS TO COME FROM ───────────────────────────── -// -// THE TARGET IS STILL [fixedPrefixTarget] and the shipped prefix is over it by the -// difference between the two constants below. The bill -// is not spread thin — one tool is more than a quarter of the whole tool block: -// -// stand 9,607 the standing-item verb's schema -// propose_task 4,363 -// tasks 2,272 -// search_conversations 1,613 -// watch 1,396 -// -// `stand` alone is nearly twice the next heaviest and more than the whole overage. -// It is not this file's to cut: what a tool's schema says is its contract with -// the model, and trimming it is a change to what the model is told rather than -// to a byte count. It belongs to whoever owns internal/session's standing belt, -// with the same discipline the 2026-09-10 diet used on `propose_task` — one -// clause per field, no rule stated twice, no em dashes — and it is filed here -// rather than done here because a gate is not the place to decide what a verb -// means. -// -// It is a byte count and not a token count deliberately: bytes are what this -// process can measure exactly, and every tokenizer this build talks to is within -// a small factor of four bytes to the token. -// -// The diet that set it left the prefix at 41,684 bytes — 21,499 of system prompt -// and 20,185 of tool block, down from 37,285 and 32,097. Of what remains, 6,551 -// bytes are the seven tools this belt takes VERBATIM from pi (internal/exec's -// bare package): they are the lean baseline the diet was measured against and -// are not codeaf's to trim. The other 35,133 bytes are codeaf's own words, down -// from 62,810 — and that is the half of the bill a lane adding a sentence is -// adding to. The budget is that measurement plus a tenth. -// WHAT HAS BEEN SPENT AND WHAT PAID FOR IT. The working discipline moved into -// the system prompt (prompt.go's [disciplinePrompt]) because the surface that -// picks the approach must carry the discipline for picking it, and it cost 1,779 -// bytes. It was paid for, not borrowed: the `# Tool Inventory` section came out, -// 1,832 bytes of prose naming each tool and paraphrasing its description — the -// tool block ahead of message[0] carries every one of those descriptions in -// full, and prompts/system.md's Tool Policy names each tool again where it says -// which one to reach for. The prefix came out 32 bytes lighter than it went in. -// THE MERGE WITH chat-v3-task (2026-08-27). autonomy/v0 sat 39 bytes under -// 45,800. The merge carries two things the v3 side had added on its own -// trunk, neither of them a sentence a lane grew here: `write`'s `append:true` -// (523 bytes of schema and the Tool Policy line naming it) and the media- -// making law (~1.5 KB under `read`/media in the Tool Policy). Dropping either -// in a merge would be a silent regression of a shipped v3 behaviour, so the -// budget moves by what was carried and a little headroom — 48,000 — and the -// follow-up is to say the media law in this file's register (the `read -// perceives media` line was already cut to a third here), not to raise this -// number again. -// THE VIDEO WAVE PAID FOR ITSELF AND FOR #238 (2026-09-01). `edit_video` put -// 1,873 bytes on the belt and landed the prefix 2,632 over, on top of the 758 -// #238 had been carrying since the merge above. Nothing was raised and no rule -// was dropped: 3,464 bytes came out of text that stated a law a SECOND time. -// prompts/system.md lost the media-making essay (the manual's own -// making-pictures-audio-and-video page teaches all of it, and `manual` is a -// tool the model can call), the paragraphs restating `bash`, `jobs`, `tasks`, -// `manual`, `build_harness` and `change_setting`'s own descriptions -// back at the model, and the three-part propose_task contract its own schema -// fields spell out field by field. It went 23,954 → 20,589; the tool block went -// 26,678 → 26,579; the prefix is 47,168, which is 832 under. -// THE CAPTION WAVE PAID FOR ITSELF OUT OF THE STANDING SECTION (2026-09-03). -// #563 asked the model for one short present-tense line before each tool batch -// and put 319 bytes of prompt on a prefix that was already 5 under, which is -// how it landed 314 over. Nothing was raised: 783 bytes came out of `# Things -// that keep working after this window`, where the recognition warning, the -// discharge test and the anchoring rule were the SECOND copy of what -// `stand`'s own description already says at greater length (tools_standing.go's -// [standDescription], which owns all three by name). A belt without `stand` -// loses nothing either — that section opens by saying it is about the tool. The -// prompt went 21,495 → 20,712 and the prefix is 47,531, which is 469 under. -// THE HANDOFF LAW PAID FOR ITSELF OUT OF A SENTENCE SAID TWICE (2026-09-04). A -// live run ended a turn that had handed its work to a task and was told the ask -// was not finished, so the page now says a handed-off outcome is not work that -// remains — 210 bytes across `## Work or words` and `# Critical`. Nothing was -// raised: the belt's `needs your look` bullet lost its "continue task N" -// sentence, which `tasks` own description already carries word for word -// (tools_tasks.go's [tasksDescription]), and the page went 21,289 → 20,840. The -// prefix is 47,920, which is 80 under. -// AND THE CAUSAL WAVE CAME IN UNDER WHAT IT REPLACED (2026-09-04). A woken turn -// now answers the request its result belongs to, so the landed-work paragraph -// says which request that is (+23), and the handoff receipt lost the clause the -// `# Critical` bullet above already carries (-33). Nothing was raised: the page -// went 20,840 → 20,830 and the prefix is 47,958, which is 42 under. -// THE VERIFICATION CONTRACT PAID FOR ITSELF OUT OF THREE SENTENCES SAID TWICE -// (2026-09-04). `propose_task` and `divide_work` grew a `checks` field — the -// repeatable verification a piece of work is put under contract with, which is -// the only thing its checker may run (task_checks.go) — and it landed the prefix -// 388 over. Nothing was raised. `acceptance` gave up "the command that passes", -// which is now the field next to it; `wide` gave up the two sentences -// prompts/system.md's own handoff section already spells; `model`, `max_steps` -// and `no_progress` gave up their tails about what the harness then does; and the -// belt's `tasks` bullet lost its `id` sentence, which [tasksDescription] carries -// in full. The two waves together leave the prefix at the figure the test prints; -// neither raised the budget and the ledger above is what each of them paid. -// AND THE FORWARDING DOOR PAID FOR ITSELF OUT OF THREE SECOND COPIES -// (2026-09-04). The person steering from the main chat needs one more field on -// `tasks` and one clause on the belt saying when to reach for it (+301, mostly -// the field's own "their words, never yours"). Nothing was raised: the tool's -// description lost the "continue task N" sentence and the URI sentence, both of -// which the `continue` field and the belt's own citation bullet already carry -// word for word; `id` lost "Running, it answers with its LIVE state", which the -// belt bullet under it says at greater length; and the belt lost the -// `scope: "everywhere"` clause the `scope` field governs. The tool block went -// 27,128 → 27,169, the page 20,830 → 20,797, and the prefix is 47,966, which is -// 34 under. -// Specialist discovery (2026-09-05) reduced this fixture's tool block from -// 27,079 to 23,438 bytes. The widest prompt grew from 20,527 to 20,909 bytes -// to explain loading, leaving 44,347 combined: 3,259 fewer than the 47,606 -// baseline. The 48,000-byte cap stays unchanged. With every media model and -// saved procedure configured, the complete tool block is 40,595 bytes and -// discovery carries 26,740, including its 708-byte loader. Measure whole JSON -// arrays rather than adding separately encoded array sizes. -// THE DIET'S DELETE PASS TOOK 677 BYTES AND ADDED A LAW (2026-09-10). Lane C of -// the prompt diet (docs/design/prompt-diet/DESIGN.md §1) deleted the SECOND and -// THIRD copies of five rules and put ONE new sentence in their place, and the -// new sentence is the reason the deletions are safe rather than merely cheap: -// "anything handed off — a job, a watch, a task, a quick task — reports itself -// into this conversation; never sleep, tail or poll for it" is 142 bytes that -// says once what ten per-tool sentences were saying separately. Against it, -// 819 bytes came out of text that stated a law already stated: the ask law was -// on the page twice and in the belt fact under it a third time, so the ladder -// bullet keeps it and the other two are gone; `# Critical`'s informed-action -// bullet was the second telling of "never ask what the record answers"; -// prompts/system.md taught `write`'s append and `read`'s offset/limit, which -// tools_write.go's [appendSentence] and bare's readDescription own word for -// word; "Start ONE `watch`" contradicted [watchDescription]'s own count and is -// gone; and the ask and settings belt facts gave up the two sentences about -// what `load_capability` does once it is called, which is that tool's own -// description. Nothing was raised. The page went 23,391 → 22,714, the tool -// block is unmoved at 24,044, and the prefix is 46,758 — 1,242 under. -// lawregistry_test.go is what keeps it there: every law above is filed under an -// id and a class, and a second copy of one is now a build failure rather than a -// thing the next audit finds. -// AND THE EVENT LANE PAID NOTHING AND TOOK 2,189 BYTES BACK (2026-09-10). The -// prompt diet's WITH THE EVENT pass (docs/design/prompt-diet/DESIGN.md §2): a -// harness-authored message now carries its own reading instruction, so the page -// stopped explaining messages it may never see. A landed task's note opens on -// [landingNoteLead] — 234 bytes on the turn a task lands, with the tier word -// interpolated — and a job's ending carries [jobExitNewsRule]. In exchange -// `# Interrupts and steering` lost the woken-turn and `[carry on]` paragraphs -// (the messages say all of it, and [checkpointCarryOnLead] has said its own -// half since it was written), `# Session facts` lost the four-words, `your -// call` and saying-stop bullets, and the belt's `tasks` fact lost its second -// copy of the four words and the resolve verbs — [settleClause] interpolates -// those from [TaskResolutions] on the note itself, and `tasks` own description -// owns "To END running work use stop". Nothing was raised and no law left the -// build. On dev alone it was 23,391 → 21,202; landing after lane C's delete -// pass it is 22,714 → 20,525, and the two together leave the prefix at 44,569, -// which is 3,431 under. Neither raised the budget. -// AND THE TOOL DESCRIPTIONS GAVE BACK 1,221 BYTES AND ADDED A LAW (2026-09-10, -// the prompt diet, lane F). The tool block went 24,044 → 22,823 and nothing was -// raised; the prompt is untouched by this lane, so the prefix went 47,435 → -// 46,214. Every byte came out of text that said something a SECOND time. The -// handed-off-work-reports-itself law was written four times across the belt — -// twice in `jobs`, once in `watch`, once in `propose_task` — and is now on the -// page once; `read`'s senses sentence enumerated what a picture, a recording and -// a video each come back as, where "described, never as bytes" is the whole rule -// (322 → 95); and the routing sentences left `tasks` (three of them), -// `read_document` and `recall` for the page's routing table, which states each -// once for the whole belt rather than once per tool. Per tool: tasks 2,738 → -// 2,272, read 1,169 → 952, jobs 1,103 → 802, watch 1,495 → 1,396, read_document -// 819 → 754, recall 324 → 269, manual 616 → 603, commit 330 → 325, track 787 -// unchanged. schemalaw_test.go is the gate that keeps it: a parameter -// description past 200 bytes, or shouting, or reaching for a dash, now fails the -// build instead of waiting for this number to notice it. Merged with the page -// passes above, the prefix is 43,348 — page 20,525 and tools 22,823, which is -// 4,652 under a cap no lane of this wave moved. And `watch.instead-of-polling` -// left lawregistry_test.go with the sentence it filed: `handoff.reports-itself` -// now matches on "never sleep, tail or poll", so putting any of the four -// per-tool copies back fails that gate wherever it is put. -// THE DIET'S ON-DEMAND LANE PAID 3,854 BYTES BACK AND ASKED FOR NOTHING -// (2026-09-10). Four runs of prose came off prompts/system.md and message[0] -// stopped carrying any of them, because each one is already delivered by -// whoever needs it and only then (docs/design/prompt-diet/DESIGN.md §2): -// - the standing section, 2,482 bytes, is one existence line. Its mechanics -// are tools_standing.go's [standDescription] and [standSchemaJSON], beside -// the field each governs; its `[something you set up fired]` frame is -// standing_run.go's [standingNewsRule], already under the firing's own line; -// the rest is the chat manual's keeping-an-eye page. -// - the two paragraphs defining a saved recipe and a saved program are the -// `harnesses` group's own prose (tools_capabilities.go), emitted under the -// `Loaded:` line by the load that fetches the four verbs. The page keeps the -// routing line that names `list_harnesses` and `build_harness`. -// - the accounts block, 1,142 bytes over three bullets, is one existence line. -// [serviceRequestDescription] already names the address and says which half -// the person turned off; the send verbs already say they are asked about -// first and cannot be called back. -// - the media-making essay is the `media` group's prose, and the page keeps -// one line: anchor in a real medium, specify positively, `manual` for the -// rest. `generate_image` and `generate_video` state it a third time in the -// `prompt` field, where it is read at the call. -// -// Nothing was raised and no law was dropped, and each of the four is filed in -// lawregistry_test.go under class `demand` with the place that now owns it. On -// its own, on top of lane C's delete pass, it took the page 22,714 → 18,860; -// landing beside the event and description lanes above it leaves the page at -// 16,671, the tool block at 22,823 which it did not touch, and the prefix at -// 39,494 — 8,506 under. -// AND THE ROUTING TABLE BOUGHT BACK 226 BYTES OF WHAT THE DESCRIPTIONS GAVE UP -// (2026-09-10). A description states a contract and never when to reach for the -// verb (DESIGN.md §4), so when the tool lane took the routing prose off -// `tasks`, `read_document` and the rest, three triggers had nowhere left to be -// said: that a look inside running or landed work is `tasks` with its id, that -// "continue task N" is that id with `continue` and never a fresh -// `propose_task` — which mints a second task with a fresh brief and a fresh -// working copy (task_continue.go) — and that `read` is the door for text, -// source and a PDF that has a text layer, `read_document` only for what `read` -// cannot turn into text at all. The first two ride the `tasks` belt fact, -// because a floor node carries neither verb; the third is two clauses folded -// into the `read` bullet that was already there. Nothing was raised, nothing -// was said twice (all three are filed in lawregistry_test.go under class -// `core`), and the "earlier work referred to but not pointed at" trigger was -// left exactly where it already was rather than restated here. The page went -// 16,671 → 16,897, the tool block is unmoved at 22,823, and the prefix is -// 39,720 — 8,280 under. -// ATTRIBUTION COST 863 BYTES AND 333 OF THEM ARE THE FEATURE (2026-09-10). Lane -// I of the prompt diet gave the chat the law the resident has had all along, and -// a third case with it: codeaf signs the git work it does in somebody's name — -// one trailer on a commit, one footer line on a pull request or issue body, and -// one small `<sub>` line on the FIRST comment it leaves in a thread and no later -// one. It is a law this page did not state at all, so nothing was deleted for it; -// there was no second copy to delete. -// -// THE FLOOR IS THE CONSTANTS AND THE FLOOR IS 333 BYTES. The trailer, the pull -// footer and the comment line are constants because the exact bytes are what -// attributes — a footer the model half-remembers counts as nothing — so this is -// the one law on the belt that cannot be paraphrased down. What IS paid for: the -// issue footer is named by the single utm parameter that differs rather than -// spelled a second time (145 bytes), and the law is four sentences, three places -// and one nowhere-else, with no example and no reasoning. -// -// It is also CONDITIONAL — off with the row off, off in a hand whose bash cannot -// commit — so this figure is the widest page and not everybody's. On dev alone -// the page was 22,714 → 23,577; landing after lanes A, C, D and F it is -// 16,898 → 17,761, the tool block is unmoved by this lane at 22,823, and the -// prefix is 40,584 — 7,416 under, and the cap is untouched. -// AND THE RESULT CAPS PAID 652 BYTES ON THE WAY TO FIXING A DEFECT (2026-09-10). -// Lane B (§5 item 1) made every result cap a share of the model's window instead -// of a flat 2000 lines / 50KB, which meant the figures had to be rendered from -// the caps in force rather than typed — and a description built at belt time is -// a description that can be weighed. So the same pass cut `read` and `bash` to -// their contract: `bash` gave up the routing sentence naming `propose_task` -// (which road work belongs on is `## Work or words`, and the manual's own "a job -// is the wrong door for work whose result is a deliverable"), and the arrival -// law's three copies — the sentence, the timeout sentence and the `background` -// argument — went to nought, on the strength of the page's new -// `handoff.reports-itself`. `write`'s append and salvage clause says the same -// two rules in 165 fewer bytes. Nothing was raised: the tool block went -// 24,044 → 23,392 on its own branch and the page is unmoved by this lane. The -// figure below is what it and lane F's pass weigh together, since both cut -// `read`. -// widestPage weighs the larger direct/deferred wording for each fact. -// AND THE QUICK TASK IS THE FIRST WAVE SINCE THIS FILE WAS WRITTEN THAT RAISED -// IT (2026-09-10), which is worth saying plainly rather than burying under the -// ledger above: every entry there paid for itself out of a sentence said twice, -// and this one could not, because it is not a sentence — it is a VERB the -// product did not have. -// -// `quick_task` encodes to 1,196 bytes and the belt's own bullet for it is 129 -// more, and both were cut to the bone before this line moved. The description is -// the judge and nothing else — the six sentences that decide between a task, a -// quick task and doing the thing yourself (task_quick.go) — with the "the id -// returns at once, so never poll" sentence left off because [taskDescription] -// carries it and the two verbs are on a belt together or on neither. The schema -// is six fields whose descriptions are one clause each, and `depends_on` and -// `model` give up their rules entirely to `propose_task`'s copies of the same -// two fields. For comparison, `propose_task` encodes to 5,720. -// -// AND THE CHOICE WAVE PAID IT BACK THE NEXT DAY (2026-09-10), so the cap is -// 48,000 again and the measured prefix is 46,245, which is 1,755 under. Two -// things happened in one commit. The belt's hand-off section stopped being a -// list of bullets that sorted work by WIDTH and became one picture of what the -// model HAS and what each thing COSTS (beltfacts.go says why, and what a real -// model did with the list); the picture is a net saving on the three rule lists -// it replaced, and it states "never poll" once for every road rather than per -// verb. And `propose_task`'s schema went on the same diet its description went -// on: one clause per field, the dowry prose dropped from `brief` because -// prompts/system.md teaches it and a test pins it there, and the em dashes -// taken out of every description string, small models tokenising them badly. -// The tool block went 23,369 → 21,808 and the page reads 24,437. -// -// WHAT IS STILL OWED. The planner rule is in the prefix twice — -// `taskDescription`'s "do not reach for a planner" and prompts/system.md's own -// `THERE IS NO PLANNER ON YOUR BELT` paragraph — and both are pinned by -// TestTheBeltRoutesWideWorkToOneWorkerAndNotToAPlanner, so paying it back is a -// change to that test's mind and not only to the bytes. -// THE MEASUREMENT, AND NOTHING ON TOP OF IT. 53,141 bytes on 2026-09-12: the -// widest page at 19,114 and the fully-wired belt's tool block at 34,027 over -// twenty-three tools, weighed as the widest machine pays for it ([widestBelt]). -// There is no rounding in it and no headroom on it. +// The rendered prefix is measured with the same page and tool schemas the +// session sends, so duplicated descriptions cannot silently grow the request. const fixedPrefixBudget = fixedPrefixTarget + fixedPrefixWaiver // fixedPrefixTarget is what the shipped prefix is SUPPOSED to be: the figure the @@ -402,306 +62,16 @@ const fixedPrefixBudget = fixedPrefixTarget + fixedPrefixWaiver // printed is a number nobody ever pays. const fixedPrefixTarget = 48_000 -// prefixWaivers is what each arm is over its target by, dated, in ONE PLACE. -// -// ── THE RULE, WHICH IS `.github/known-red.txt`'S RULE ──────────────────────── -// -// A waiver only ever SHRINKS. A lane that takes bytes out lowers the figure in -// the same commit; a lane that needs more takes it out of something that is -// already being said twice. Raising one is a decision with somebody's name on it -// in a diff, which is the entire difference between a debt and a floor. -// -// 2026-09-12, #996. The lean figure shrank from 13,489 to 13,420 in its own -// first commit, which is the discipline working rather than an edit: fixing the -// page's working directory and giving the lean arm its OWN shelf sentence took -// sixty-nine bytes off a number that had been measured on a hybrid. Both arms -// were weighing a conversation nobody has — no -// memory store, no accounts hub, no standing items, no saved programs — so both -// waivers are the first honest measurement of a prefix that had never been -// weighed, and neither is a wave's overspend. The bill is not spread thin: -// `stand` is 9,607 bytes, more than a quarter of the full tool block and, on a -// sixteen-thousand-token window, roughly one token in six of everything that -// person has before they have said anything. -// -// 2026-09-12, the merge with #1015. The prompt diet's read-dedupe wave added -// one sentence to the shared BELT_FACTS — the pointer that answers -// `[already read]` from the conversation rather than fetching the file again — -// and paid exactly 150 bytes on both arms doing it. Both waivers rise by that -// figure here, in this diff, on purpose: the rule says a raise is a decision -// with a name on it, and the alternative was cutting the sentence the merge -// just bought. -// -// 2026-09-16, #1065 round one. `# Tone` and `# Delivery` became `# The answer`, -// `# Answer or change`, `# When corrected` and `# Messages from codeaf`, in the -// wording the issue fixed and with the five rules the old two carried restored -// inside them, and that paid 2,035 bytes on both arms (fixed 53,276 to 55,311, -// lean 45,051 to 47,086). Fifteen of them came out of room both arms already had, -// so both waivers rise by 2,020 and now sit exactly on the measurement, on -// purpose and with this name on it: the issue that -// bought the sections is the one that puts the page's overall length to its -// second round, and cutting other laws in the first would be that round done -// early and unreviewed. -// -// 2026-09-20, the use_skill wave. A worker gained one verb it did not have: -// `use_skill`, which lists the active skill shelf and resolves one name to its -// shelf path (tools_skill.go), and the page gained the one belt-fact bullet that -// says the shelf is reachable (beltfacts.go). It is a NEW CAPABILITY rather than -// a second copy of a law — nothing on this belt already let a worker reach a -// saved procedure — so there was no sentence to take the bytes out of. It paid -// 741 bytes on the fixed arm (55,280 to 56,021) and 755 on the lean arm (47,055 -// to 47,810), and both waivers rise by that figure here, in this diff, on -// purpose: the rule says a raise is a decision with a name on it, and the -// alternative was cutting the verb the wave exists to add. -// -// 2026-09-16, #1067 review. The provenance list had to grow because compaction -// also writes user-role tags into the conversation: `[folded …]` and `[context -// compacted]`. It also stopped calling the tool-only `[held]` a user message or -// declaring every unlisted tag the person's, and it does NOT name standing -// news's `[something you set up fired]`: that line carries its own instruction -// under the event, and TestTheSteeringLineReadsAsNewsAndNotAsARequest refuses -// the page's copy as one law paid for twice. Tightening the surrounding -// sentence paid for the truth with room to spare: fixed is 55,280 and lean is -// 47,055, so both waivers fall by 31 and again sit exactly on the measurement. -// -// 2026-09-20, the assisted-by trailer line. The commit-signing belt fact now -// spells the whole two-line trailer block — the co-author's ID-prefixed -// address, and above it the `Assisted-by` line naming the model, filled in at -// the render because the chat is the one surface that knows its model — and -// the widest page pays for it: fixed is 55,442, over its 55,280 by 162, so that -// waiver rises by 162. The lean shape's page never renders the attribution row -// and lean is 47,055 still, exactly on its measurement. -// -// 2026-09-21, the shelf-on-the-page wave. The page gained the three lines that -// say what a skill IS and when opening one beats improvising — nothing on the -// page had ever said that; the tool description said it only where the verb -// was on the belt. It is a NEW LAW rather than a second copy of one, so there -// was nothing to take the bytes out of; the use_skill description, its schema -// lines and the belt-fact row were tightened in the same commit and paid part -// of the bill. Fixed is 56,277, over by 94, and lean is 47,891, over by 81; -// both waivers rise by that figure here, in this diff, on purpose. -// -// 2026-09-23, #1393. The answer section got back the rule #1209's rewording had -// dropped without saying so — "done" is never half-solved work — and the same -// section paid for it by saying three things in fewer words. The page came out -// four bytes lighter on both arms: fixed is 56,273 and lean is 47,887, so both -// waivers fall by 4 and again sit exactly on the measurement. -// -// 2026-09-23, signing always on. The owner retired the `attribution` row: -// codeaf signs every commit it writes, and the only choice left is whether the -// `Assisted-by` line names the model. The law's commit sentence now spells both -// trailer lines itself, so the page's second sentence spelling the block again -// is gone: fixed is 56,146, and that waiver FALLS by 127. The lean arm RISES by -// 927, and that is not new wording: the shipped shape had the row unset, so this -// arm weighed a page with signing off, while every real conversation had it on -// by default and paid those bytes all along. The arm now weighs the page people -// were already reading, 48,814, and the raise carries this name so it can be -// questioned. -// -// 2026-09-23, the programs codeaf carries, and the owner's call by name. The -// hand-off page's programs paragraph (delegate_door.go) is each carried -// program's own guide, printed under its name, and codeaf's rule about the -// folder a program that edits files must be handed; `propose_task`'s `via` -// field points at `ground`. The paragraph was already on the shipped page -// and was never weighed: the shipping shape carried no programs, and -// [widestPage] weighed the frame without its fill. Both are fixed in the same -// change, and the true cost shows on both arms: fixed is 56,271, over its -// 55,442 by 829, and lean is 47,719, over its 47,055 by 664. Both waivers rise -// by exactly that and sit on the measurement. Paying it back out of other -// prompt text was offered and declined: the paragraph is how the conversation -// learns what senior-dev is for and which folder to hand it, and cutting -// other lanes' wording to make room was the riskier edit days before a ship. -// -// 2026-09-24, codeaf reaches for a program by itself, and the owner's call by -// name: "raise the cap only as much as necessary — the prompts will be refined -// later". The programs paragraph now says work a program is for goes to it -// whole, rather than to the conversation or its own worker whatever its -// critical path, and that work the person asks one for by name goes to it; -// senior-dev's guide claims the complex, many-sided coding work it was going -// unused on (an issue in a mature codebase whose cause spans files) and says -// its brief carries the issue in full; and `via` says when it is set. That -// grew fixed by 202 bytes (page 153, `propose_task` 49) to 56,447, and lean -// by 153 to 47,859. Both arms already had room, 26 and 13 bytes of it, so -// fixed rises by 176 and lean by 140, and both sit exactly on the -// measurement again. -// -// 2026-09-24, a program works in the folder itself. The folder rule stopped -// describing a copy nothing merges and says the folder and its branch instead -// ([delegateFolderRule]), 38 bytes shorter on both arms, and both waivers come -// down by exactly that: fixed measures 56,409 and lean 47,821. -// -// 2026-09-24, dev merged under senior-dev (#1488). Both ledgers above stand, and -// the waivers are measured again on the merged page: fixed is 57,124 and lean -// 49,590, which is dev's 56,146 and 48,814 plus what the senior-dev entries -// above added (978 and 776 bytes on this page). Both sit on the measurement. -// -// 2026-09-25, fixes A–E and the missing eight bytes. On this Linux machine the -// cap-setting commit itself, untouched 9abc11099, and this tree all weighed -// 57,132 and 49,598 before the guide edit: 22,299 + 34,833 on the full arm, -// 21,799 + 27,799 on the lean arm. The earlier 57,124 and 49,590 record was -// eight bytes short; changing HOME, USER, TMPDIR, TZ and the launch directory -// changed neither page nor tool block. Fix B's conditional `propose_task` `via` -// schema omits that field only on a door with no program. Fix D's longer -// `program-outcome.md` is read on a wake turn, not in the fixed page; its -// ceilings are rendered on a card and start line. Fixes A, C and E1 added no -// fixed-prefix bytes. The Unix program guide's two equivalent shorter phrases -// pay the eight bytes back, and a declared fixture now weighs that same guide -// and tool shape even on Windows, whose runnable registry is empty. The measured -// caps and both waivers therefore stay at 57,124 and 49,590, with no increase. -// -// 2026-09-25, #1494 and #1436 merged into #1488. Their team delegation and -// per-task crew forms leave the page at 22,291 bytes and grow the full tool -// block to 34,927 over 24 tools. The measured fixed prefix is 57,218 bytes: -// 94 above its preceding cap. The fixed waiver rises by exactly 94 for this -// combined belt; the lean arm remains within its 49,590-byte cap. -// -// 2026-10-05, sec (sec-af's security audit), the second program codeaf -// carries. Its guide (programguide.Sec, 386 bytes) is one more item of the -// hand-off paragraph's list, which is all the prefix pays for a program: its -// manual page and its report-turn wording ride no request. Measured against dev -// 7e3033564 it cost the fixed prefix 366 bytes and the lean 229; 2026-10-07, -// merged with dev baa2d7f0f, whose page carries a program's guide on the lean -// arm too, it costs each 396 (dev measures 57,150 and 49,572; with sec, -// 57,546 and 49,968). Both waivers are dev's plus exactly that 396. -// -// 2026-10-06, review (pr-af's code review), the third. Its guide (programguide.Review, -// 190 bytes) and its item's frame are 203 bytes in both arms; 2026-10-07, on -// dev baa2d7f0f with sec, the fixed prefix measures 57,749 and the lean -// 50,171, and both waivers are sec's plus exactly that 203. -// -// 2026-10-10, automations replace standing orders -// (docs/design/automations/DESIGN.md). `stand` and its 9,607 bytes leave every -// belt that carried them, and `automation` — a smaller tool for the same -// sentences — takes its place; the one-sentence paragraph the page composes -// beside it is the same length as the one it replaces, and `watch`'s boundary -// sentence names the idea rather than a verb some belts lack, eight bytes -// shorter. The fixed prefix measures 52,713 bytes and the lean 44,935, and both -// waivers FALL to sit exactly on the measurement: the bill this file has -// carried for `stand` since it was first weighed is mostly paid. -// -// 2026-10-14, `automation` learns `change`. The op, its sentence in the tool's -// description and the page's "one that exists is CHANGED, never proposed again" -// were paid for out of what the description said twice — a watch's look and -// condition, already said beside their own fields in the schema — and the `id` -// field's list of the ops that take one. Both arms come out 22 bytes lighter, -// at 52,691 and 44,913, and both waivers fall by exactly that. -// -// 2026-10-14, one memory strength. The page's memory sentence says what -// `remember` keeps and that a timed thing is an automation; `memory_evidence` -// leaves the belt with the evidence it read, and `forget` joins `remember` as -// a one-field verb on the full belt (the lean belt carries neither, its page -// saying the person can /remember). The fixed prefix -// measures 52,497 bytes and the lean 44,893, and both waivers FALL — by 194 and -// by 20 — to sit exactly on the measurement. +// prefixWaivers records how far each rendered prefix exceeds its target. The +// measured limits prevent descriptions and schemas from growing unnoticed; +// removing text lowers the corresponding allowance. const ( fixedPrefixWaiver = 4_497 leanPrefixWaiver = 13_393 ) -// THE LEAN PROFILE GETS A BUDGET OF ITS OWN (2026-09-10, the prompt diet's lane -// G). promptprofile.go added a second shape of prefix for a model with a small -// window or the crew's open-weight worker seat: two sections come off the page, -// four more groups wait on the shelf, `ask` is handed over rather than fetched, -// the memory reflex does not run and the project's instruction file rides under -// 2 KiB. Nothing above it moved — the full arm renders byte for byte what it -// rendered before, which [TestAFrontierShapeIsUntouchedByTheProfile] asserts at -// every door — so this is a second number and not a raised one. -// -// WHAT IT MEASURES AND WHERE IT HAS TO GET TO. On a 16k window the lean prefix -// is what this test prints. On the profile's own branch it was 34,343 bytes -// against the full arm's 47,435; merged onto the rest of the diet — lane C's -// delete pass and routing table, lane D's self-describing messages, lane E's -// pulled mechanics, lane F's contract-only descriptions, lane B's window-scaled -// caps and the quick-task wave that took `fork` off the belt — it is 31,006 -// against 38,742: page 16,825 plus tool block 14,181 over twelve tools. -// -// THE BELT IT WEIGHS IS THE SHAPE THE DESIGN ASKED FOR: the seven pi tools, -// `quick_task`, `jobs`, `manual`, `load_capability` and `ask`, with -// `propose_task`, `tasks`, `watch`, `track`, `commit`, `recall` and -// `read_document` one call away. -// -// The diet's target for this arm is 12,000 bytes -// (docs/design/prompt-diet/DESIGN.md §6) and nothing in this wave reaches it, -// which is worth saying plainly rather than rounding away. The two numbers that -// would move it were both named on landing: `ask`'s schema, and the page's -// 16,825, which is the shared CORE minus one section and so comes down when CORE -// does and not before. -// -// `ask` HAS NOW BEEN THROUGH, AND THE NUMBER CAME DOWN WITH IT (2026-09-10). -// It was 4,277 bytes of the tool block, thirty percent of the lean arm, because -// it is the one verb that is shelved on a full belt and PRE-ARMED on a lean one -// (promptprofile.go) — the schema a small model pays for on every request and a -// frontier model never sees. It is 3,844 now: no field left, no enum left, and -// what went was prose saying a field's own name back at the model (`"Block -// kind"` beside the list of block kinds, `"Subject kind"`, `"Turn waits"`, -// `"Certainty"` on a low/medium/high enum, and the same six repeated inside the -// evidence block, which is spliced into the schema TWICE) plus the tail of the -// two long ones. The lean prefix went 31,006 → 30,573, and the budget below went -// down with it rather than staying where it was: page 16,825 unchanged, tool -// block 14,181 → 13,748. The full arm is untouched at 38,742, byte for byte, -// which is what a shelved verb means. -// -// AND IT CARRIES A LITTLE HEADROOM, DELIBERATELY. Pinned to the exact -// measurement it was the one number in the tree that made the shared page -// unmovable: the routing-table commit added 226 bytes of CORE, which both arms -// read, and a lean budget with no slack failed a change the full budget waved -// through with thousands to spare. So the figure it LANDS at is about three -// percent over what it measured on landing — room for a few moves of that size, -// and not room for a paragraph. -// -// AND `ask` GREW AGAIN, WHICH THE HEADROOM ABSORBED AND THIS LINE SAYS OUT LOUD -// (2026-09-11, the questions wave). The schema's enums are now written from the -// Go constants rather than typed out beside them — so `pick.confidence` offers -// the three words the code actually reads, `input.blanks` and `input.dial` carry -// their shapes, and `subject.kind` carries `order`. That is four vocabularies and -// two objects the model could not see before, and it cost bytes: 3,844 → 4,235. -// 137 of them were won back the way the last pass won its 433, by deleting prose -// that says a field's own name back at the model (`"Comparison axis values, one -// short text per axis"`, `"What it holds before they type"`, `"kind blanks only"`) -// — leaving the schema at 4,098 and the lean prefix at 31,035 against the 31,500 -// here, about 465 bytes of room. -// -// THAT IS THE HEADROOM DOING ITS JOB AND NOT A LICENCE. The paragraph above says -// what it is for: a few moves of a couple of hundred bytes, so a shared page can -// still move. A wave that needs more than this is a wave that takes something -// out first. -// -// THE HELD-RANGES WAVE PAID FOR THE ROUND-TRIP PRICE IT TEACHES (2026-09-12). -// The read tool's description says a call costs one round trip and a range -// already in the conversation answers as a pointer (bare/tools.go's -// [readDescription], the ledger in heldreads.go). The sentence was priced -// into the lean arm's headroom — 87 bytes came in, 9 came back out of the -// description's redundant "the rest", and the lean prefix sits 5 under its -// budget. -// THEREAFTER IT ONLY EVER RATCHETS DOWN, in the ledger discipline the full -// budget above is kept under: a lane that takes bytes out lowers it in the same -// commit, and nothing ever raises it again. -// -// ── AND THEN IT TURNED OUT TO BE WEIGHING A CONVERSATION NOBODY HAS ───────── -// -// Every figure above is real and every one of them was measured against -// [leanShapedAgent], which built a conversation with NO memory store, NO -// accounts hub, NO standing items and NO saved programs — sixteen tools. A -// person on a small window who has finished setting codeaf up carries `stand` -// (9,607 bytes by itself), `remember` and `search_conversations`, none of which -// [Config.leanCapabilityGroups] shelves, and their prefix is 44,989 bytes. -// -// So the arm that exists to protect the person with the LEAST room to spare was -// out by 13,489 bytes, which is more than the whole budget it was enforcing. -// That is #576's shape and it is the same hole the full arm above had, found in -// the same review: a gate pointed at something nobody runs passes without having -// tested anything, every day, in both directions. -// -// THE FIGURE IS THE MEASUREMENT NOW, with no headroom — the argument for slack -// was written when this number came off a diet that had just been paid for, and -// a number that has never been honestly weighed has not earned any. What the -// slack bought (a shared page that can still move by a couple of hundred bytes) -// is now bought by the full arm's 53,141, which both arms read the page through. -// -// WHAT IS OWED IS THE SAME BILL THE FULL ARM OWES, and it falls harder here: -// `stand` alone is 9,607 bytes on a sixteen-thousand-token window, which is -// roughly one token in six of everything that person has, spent before they have -// said anything. [leanPrefixTarget] is what this has to come back to and the -// test prints the shortfall on every green run. +// The lean profile has a separate budget because its page and tool shelf +// differ from the full belt. Measure each rendered shape independently. const leanPrefixBudget = leanPrefixTarget + leanPrefixWaiver // leanPrefixTarget is what the lean prefix is SUPPOSED to be: the figure diff --git a/internal/session/principal_structure_test.go b/internal/session/principal_structure_test.go index 1e6bf45eef..285fb7a06d 100644 --- a/internal/session/principal_structure_test.go +++ b/internal/session/principal_structure_test.go @@ -21,7 +21,7 @@ import ( // where it is a dead end. So the two facts a reviewer would have to hold in // their head are held here instead, and a build fails when either moves. // -// The two tests below are deliberately dumb: one counts the doors, the other +// The two tests below are deliberately simple: one counts the doors, the other // counts the sentences. Neither tries to decide whether a road is CORRECT, and // neither could; what they enforce is that a road cannot appear, or a // person-addressed sentence be written, without somebody having said in this diff --git a/internal/session/program_outcome.go b/internal/session/program_outcome.go index ab347534a2..330da15738 100644 --- a/internal/session/program_outcome.go +++ b/internal/session/program_outcome.go @@ -1,28 +1,10 @@ package session -// A PROGRAM'S ENDING IS FOR CODEAF TO ACT ON, NOT FOR THE PERSON TO DECODE. -// -// senior-dev ends with a status — its change passed the project's own build and -// tests, nothing finished checking it, it did not pass, it hit a ceiling, it -// broke — and until this file that status was a sentence on a row and in the -// conversation's record, read by the model only if the person happened to ask -// something next. The owner asked on 2026-09-25 that the status inform codeaf -// rather than the person: the chat reads it the moment the run ends, checks -// what it can, sends senior-dev back with a sharper brief when the work did not -// stand, and tells the person where the work is in one plain summary. -// -// So every program run's landing WAKES a bounded turn ([Agent.deliverBeltRunLanding]) -// carrying the ending as a fact ([programVerdict]) and the one line of what to -// do about it, under a role page that says the whole playbook -// (prompts/program-outcome.md) — the per-event vehicle, which costs the fixed -// prefix nothing. -// -// TWO BOUNDS ARE CODE, NOT ADVICE. codeaf sends a program back on its own at -// most [programAutoRetries] times in a line of runs on one piece of work, and -// never after a run that ended on a dollar or time ceiling: that re-run spends -// more of the person's money, so it waits for their word ([Agent.programRetryRefusal]). -// A hand-off the person asks for in their own turn is theirs, and starts the -// count again. +// A program ending wakes a bounded conversation turn so codeaf can check the +// result, request a repair when needed and explain the outcome. The ending +// travels as a fact under prompts/program-outcome.md instead of expanding every +// request. Automatic repairs are bounded by programAutoRetries and never follow +// a time or spending ceiling without the person asking. import ( "encoding/json" @@ -475,23 +457,11 @@ func programLimitLine(run *beltRun, summary RunSummary, landing RunLanding) stri return fmt.Sprintf("%s stopped at %s %s limit · %s · its work is %s", programName(run.delegate), scope, limit, spentWord, where) } -// programOutcomeUnansweredLocked writes a program's own account of its ending -// into the conversation when the turn its ending woke did not finish an answer. -// The caller holds a.mu, at the end of that turn. -// -// A PROGRAM'S ENDING IS NEVER LOST TO A FAILED REPLY. On 2026-10-05 a two-hour -// sec run ended, the turn it woke read its report and began a good summary, -// and every model it was offered was cut mid-reply; the partial summary was -// kept as an interrupted message the chat does not draw, and the person saw -// a done card and nothing else. The program's account is what the turn was -// woken to relay, so when the turn could not, the conversation says that it -// could not and gives the account itself — once per run, as an authored line, -// the way a run's limit line is written ([Agent.recordProgramLimit]). -// -// AND IT SAYS WHY THE ANSWER IS MISSING. A turn the person stopped did not -// complete either, and telling them the chat "could not" finish would be the -// record misdescribing their own key: their stop keeps the account and names -// itself instead. +// A program ending wakes a bounded conversation turn so codeaf can check the +// result, request a repair when needed and explain the outcome. The ending +// travels as a fact under prompts/program-outcome.md instead of expanding every +// request. Automatic repairs are bounded by programAutoRetries and never follow +// a time or spending ceiling without the person asking. func (a *Agent) programOutcomeUnansweredLocked(hub *eventHub, completed, personStopped bool) { outcome := a.programOutcomeNow if completed || outcome == nil || outcome.account == "" || a.programAnsweredFor == outcome.row { diff --git a/internal/session/programfolder.go b/internal/session/programfolder.go index f84a09fa7e..b33b282e00 100644 --- a/internal/session/programfolder.go +++ b/internal/session/programfolder.go @@ -47,20 +47,6 @@ package session // (programhold.go). A run in a copy holds only its // copy, which is why runs on one repository never wait for each other. // -// WHY THERE IS SO LITTLE HERE. Until 2026-09-24 a program ran through the -// general task machinery: a copy of the folder cut for every run, the brief's -// paths rewritten to name the copy, the program's commits squashed and its -// HEAD put back at the landing, and a ladder of placement rules, each layer -// patching the one before it. The owner asked why it was so hard to have -// senior-dev just work on the problem — "if it's in a git repo, great - if -// not, just do it" — and the answer was that codeaf had made it hard. The -// copy, the rewriting, the squash and the ladder went. Until 2026-09-28 the -// program then worked in the person's checkout itself, switched onto its -// branch, which held the whole repository for one run at a time; the owner -// asked for runs side by side, and the copy came back as a worktree the -// program's run owns start to end — with no squash, no landing and no -// rewriting, only a line at the head of the brief ([ProgramFolder.BriefNote]). -// // ONE ROAD FOR BOTH DOORS. The conversation's run (task_run_belt.go) and the // shell's `codeaf senior-dev` (cmd/codeaf/carried.go) prepare a folder with // [PrepareProgramFolder] and finish it with [ProgramFolder.Finish], so a diff --git a/internal/session/question.go b/internal/session/question.go index a3178b6afe..775b242ac5 100644 --- a/internal/session/question.go +++ b/internal/session/question.go @@ -210,7 +210,7 @@ var questionForms = []QuestionForm{FormLine, FormCard, FormRoom, FormSheet} type AskerKind string const ( - // AskerModel is the model, through the `ask` tool (lane E2 owns that door). + // AskerModel is the model, through the `ask` tool. AskerModel AskerKind = "model" // AskerEngine is codeaf itself: the approval gate, the fuel gate, a merge // conflict — questions no model chose to ask. @@ -1061,7 +1061,7 @@ type DecisionRecord struct { // with the same head and different answers is exactly what a person changing // their mind leaves behind, and a reader — the model, the mark reader, the // person three days later — cannot tell that from the program having asked - // the same thing twice and got two answers. Measured on the Spark, + // the same thing twice and got two answers. Measured in a test run, // 2026-09-11: a side-call read the record, found "Hello" and a file saying // "Hola", and set about "fixing" the file. Was []string `json:"was,omitempty"` diff --git a/internal/session/questionlifecycle_test.go b/internal/session/questionlifecycle_test.go index 579167d493..60f86c3919 100644 --- a/internal/session/questionlifecycle_test.go +++ b/internal/session/questionlifecycle_test.go @@ -51,7 +51,7 @@ func TestTheConnectOfferIsRaisedAnsweredAndWithdrawnOnTheQuestionsLane(t *testin if answered.Question.Ref != ref { t.Fatalf("the answered event is about %q, want %q", answered.Question.Ref, ref) } - // AND THE RECORD KEEPS IT, which no family of this lane had before: an + // AND THE RECORD KEEPS IT, which no family of this test had before: an // answer with no banked words leaves nothing anybody can read afterwards. decisions := agent.Decisions() if len(decisions) == 0 || !strings.Contains(decisions[len(decisions)-1].Head, "Notion") { diff --git a/internal/session/sessionfile.go b/internal/session/sessionfile.go index daa36eb5bf..709a776bb2 100644 --- a/internal/session/sessionfile.go +++ b/internal/session/sessionfile.go @@ -698,23 +698,18 @@ type journalMark struct { // this is an act — and because a handover can fire with no reading behind it at // all (a sidecar nobody could reach still meets the ceiling). // -// Decision is `moved`, `dropped:nothing-left` — the running model declared the -// work finished AND the mark's own reader agreed nothing remained — or one of the -// two ways a handover ends with no task of its own: `dropped:no-brief`, when -// nothing could be written down for anybody, and `dropped:work-already-out`, when -// everything there was to write down was about pieces this conversation is still -// holding and therefore nobody else's to take (checkpoint.go's custody road). On a -// run with a goal owner two more are possible, and both mean the turn was sealed -// at the handover with no task started: `dropped:stopped`, the owner read the -// ending and stopped the run with a reason, and `dropped:done`, the owner read it -// and said the ask was met (checkpoint.go's [Agent.endTurnUnderSteward]). And the -// write seam writes one more of its own, `dropped:delivering-own-result`: the turn -// is finishing the delivery of a result this conversation already owns, so the -// counter stood down and the work stayed here (writeseam.go's -// [Agent.writeSeamFires]). TaskID names the node when one was ADMITTED, and is -// absent otherwise by the emptiness law the rest of the line keeps — the delivery -// row admits nothing and names its result in Reason instead, so a bench counting -// tasks started off that field still counts only tasks. +// Decision is `moved`, `dropped:nothing-left` — the running model declared the work +// finished AND the mark's own reader agreed nothing remained — or one of the two ways a +// handover ends with no task of its own: `dropped:no-brief`, when nothing could be written +// down for anybody, and `dropped:work-already-out`, when everything there was to write +// down was about pieces this conversation is still holding and therefore nobody else's to +// take (checkpoint.go's custody road). And the write seam writes one more of its own, +// `dropped:delivering-own-result`: the turn is finishing the delivery of a result this +// conversation already owns, so the counter stood down and the work stayed here +// (writeseam.go's [Agent.writeSeamFires]). TaskID names the node when one was ADMITTED, +// and is absent otherwise by the emptiness law the rest of the line keeps — the delivery +// row admits nothing and names its result in Reason instead, so a bench counting tasks +// started off that field still counts only tasks. // // Carry NAMES THE RUNG THAT SUPPLIED THE BRIEF the task actually opened on // (checkpoint.go's [Agent.handOverRunningTurn]): `handoff`, `draft` or `ask`. diff --git a/internal/session/skillcatalog.go b/internal/session/skillcatalog.go index 2a1786c1bb..d536461229 100644 --- a/internal/session/skillcatalog.go +++ b/internal/session/skillcatalog.go @@ -22,7 +22,7 @@ import ( // (skillturn.go) are picked by the words the message shares with a skill's // description, which is cheap and literal: "make me a deck for the board" // shares no word with "create and edit presentation slides". A model reading -// the whole catalog makes that connection itself, the way Claude Code's own +// the whole catalog makes that connection itself, so the // skill list works — the description is in front of it on every request, it // decides a skill applies, and it fetches the body with `use_skill`. So the // catalog names EVERY skill, rather than the few a path-based score guessed at, diff --git a/internal/session/skillturn_display_test.go b/internal/session/skillturn_display_test.go index 4b0786ee94..b73598c5a1 100644 --- a/internal/session/skillturn_display_test.go +++ b/internal/session/skillturn_display_test.go @@ -8,12 +8,9 @@ import ( "github.com/Agent-Field/agentfield/sdk/go/ai" ) -// THE TRANSCRIPT SHOWS ONLY WHAT THE PERSON TYPED. The skills a turn carries -// are model context, chosen for one message ([attachTurnSkillsLocked]); the -// block rides the copy the model reads, and the dim `skills carried` notice is -// the one channel a surface draws. The owner, 2026-09-25, #1504: the block was -// printed as part of the person's message, so every surface that renders the -// conversation printed a list nobody asked for. +// THE TRANSCRIPT SHOWS ONLY WHAT THE PERSON TYPED. The skills a turn carries are model +// context, chosen for one message ([attachTurnSkillsLocked]); the block rides the copy the +// model reads, and the dim `skills carried` notice is the one channel a surface draws. // // This is the END-TO-END reading of that law: through the real chat door, with // an active shelf and a message that matches one of its skills, the record the diff --git a/internal/session/steer.go b/internal/session/steer.go index 393eb41dd4..a505b2df8d 100644 --- a/internal/session/steer.go +++ b/internal/session/steer.go @@ -391,12 +391,9 @@ var errPersonCut = errors.New("let go of because you chose another model") // and can be twenty minutes long, and a person watching a step wait thirteen // minutes on a pace they cannot see is a person whose word did nothing. // -// THE MEASURED FAILURE (2026-09-11, 14:40:10). A task step sat on `waiting · -// rate limited · 13m 37s`. The owner picked another model in the room and typed -// `continue`; the room answered `its next turn takes it`, and the step was still -// talking to the model they had moved off at 14:41:00. The pick was real and -// landed on the agent — what was missing was anything to make the request in -// flight let go of it. +// THE MEASURED FAILURE (2026-09-11, 14:40:10). A task step sat on `waiting · rate limited +// · 13m 37s`. The pick was real and landed on the agent — what was missing was anything to +// make the request in flight let go of it. // ModelLanding is WHEN a model a person just named reaches the work, and it is // the only thing a surface has to know to say something true about the pick. @@ -419,10 +416,7 @@ const ( // the person, and let go of it when it has not, so the loop comes back to a // boundary and assembles the next request carrying what they said. // -// ONE DOOR BECAUSE IT IS ONE RULE. A model, a `continue`, a `stop`: the product -// rule the owner ruled on 2026-09-11 gives all three the same clock and the same -// question, and a second reading of it somewhere else is how the model half came -// to work while the direction half still waited out thirteen minutes. +// ONE DOOR BECAUSE IT IS ONE RULE. // // THE CAUSE IS THE CALLER'S BECAUSE IT NAMES WHICH BOUNDARY THE WORD NEEDS, and // that is the one thing that genuinely differs between two words. A model diff --git a/internal/session/steerquestion_test.go b/internal/session/steerquestion_test.go index 1312749acc..78577b9b46 100644 --- a/internal/session/steerquestion_test.go +++ b/internal/session/steerquestion_test.go @@ -114,7 +114,7 @@ func TestASteerAtAnOpenQuestionPutsTheNextRequestOnTheWireAtOnce(t *testing.T) { select { case at := <-next: - // THE WHOLE OF WHAT THIS LANE PROMISES. A person's own sentence reaches + // THE WHOLE OF WHAT this test PROMISES. A person's own sentence reaches // the model inside the allowance every wait in the request path is held // to, rather than behind a tool that is waiting for that same sentence. if waited := at.Sub(steeredAt); waited > lanes.SpokenWithin { diff --git a/internal/session/task_carry_test.go b/internal/session/task_carry_test.go index 57c4158adc..7fe8ac9b03 100644 --- a/internal/session/task_carry_test.go +++ b/internal/session/task_carry_test.go @@ -102,7 +102,7 @@ func TestTheProductionConstructorCarriesTheProviderRepairOntoEveryWorker(t *test // THE NO-TOOLS RESCUE MUST WORK AT EVERY DEPTH. [Agent.newTaskAgent] reads // SupportsParameter off the parent's config to refuse a model that cannot hold a -// tool at all — and until this lane it did not carry the answer down, so the +// tool at all — and until this test it did not carry the answer down, so the // check ran for a conversation's own task and for nothing below it. C1 made that // reachable far more often: every part division hands out is built by a worker. func TestAPartIsBuiltWithTheSameNoToolsRescueItsParentHad(t *testing.T) { diff --git a/internal/session/task_phase_test.go b/internal/session/task_phase_test.go index e9e7580d5c..217525fbdf 100644 --- a/internal/session/task_phase_test.go +++ b/internal/session/task_phase_test.go @@ -371,7 +371,7 @@ func TestTheHandoverSaysItIsBriefingAWorkerWhileItWritesTheBrief(t *testing.T) { } // AND IT IS CLOSED. A phase left open is a clock a surface goes on drawing for - // work that ended, which is the defect this lane exists to prevent. + // work that ended, which is the defect this test exists to prevent. words := phaseWords(log.all()) last := -1 for index, one := range log.all() { diff --git a/internal/session/task_progress_test.go b/internal/session/task_progress_test.go index cebd602c74..86c09e6067 100644 --- a/internal/session/task_progress_test.go +++ b/internal/session/task_progress_test.go @@ -185,7 +185,7 @@ func TestStoppedWorkIsCommittedToTheBranchItsReportNames(t *testing.T) { // turn with its own account of the work. // // It is written this way rather than positionally for [nodeLane]'s reason: the -// harness's own title call speaks on this lane too, and a script that counted +// harness's own title call speaks on this test too, and a script that counted // turns would be asserting the order those happen to fall in. // // THE SPIN IS FINITE. The counter cancels the run, and the cancel is a message diff --git a/internal/session/task_run.go b/internal/session/task_run.go index c58d8377c8..7a260124ed 100644 --- a/internal/session/task_run.go +++ b/internal/session/task_run.go @@ -170,23 +170,20 @@ const ( // decomposition (task.go's fan-out law), and each answers a different way // for it to run away. // - // NEITHER IS WHAT DECIDES HOW WIDE WORK GOES, and until 2026-09-11 both were - // written as though they were. Five children was a guess about decomposition - // ("more than that has not decomposed its work, it has shredded it") and two - // levels a guess about where a third stops paying, and nobody had measured - // either. What actually bounds how much runs at once is the machine and the - // work: the person's task.parallel holds a ready node until a slot frees, - // the admission governor holds one while the machine is already loaded - // (task_pressure.go, which weighs the machine once per frontier pass, so a - // batch that becomes ready together is admitted on one reading), and two - // parts that would write one file are refused (a division) or queued one - // behind the other (quick tasks' file claims), not counted. Whether a worker - // SHOULD split is the fan-out page's question (prompts/fanout.md) and the - // division road's evidence gate (task_divide.go), each asked of the material - // in front of it; a constant here cannot know the answer for work it has - // never seen. The owner's ruling is that breadth may be large where the work - // parallelises, because a node's parts cost the longest of them and not - // their sum. + // NEITHER IS WHAT DECIDES HOW WIDE WORK GOES, and until 2026-09-11 both were written as + // though they were. Five children was a guess about decomposition ("more than that has + // not decomposed its work, it has shredded it") and two levels a guess about where a + // third stops paying, and nobody had measured either. What actually bounds how much runs + // at once is the machine and the work: the person's task.parallel holds a ready node + // until a slot frees, the admission governor holds one while the machine is already + // loaded (task_pressure.go, which weighs the machine once per frontier pass, so a batch + // that becomes ready together is admitted on one reading), and two parts that would write + // one file are refused (a division) or queued one behind the other (quick tasks' file + // claims), not counted. Whether a worker SHOULD split is the fan-out page's question + // (prompts/fanout.md) and the division road's evidence gate (task_divide.go), each asked + // of the material in front of it; a constant here cannot know the answer for work it has + // never seen. Breadth may be large where the work parallelises, because a node's + // parts cost the longest of them and not their sum. // // SO THE FAN CAP IS A RUNAWAY STOP AND NOTHING ELSE. A node handing out more // than twenty pieces has lost the plot rather than found the width, and it diff --git a/internal/session/taskdelta.go b/internal/session/taskdelta.go index 8f13a44c90..3e9463177e 100644 --- a/internal/session/taskdelta.go +++ b/internal/session/taskdelta.go @@ -616,7 +616,7 @@ func (a *Agent) refreshElsewhere(ctx context.Context) { // (steer_grace.go) true of this goroutine: a reading still in flight when // [Agent.Close] runs either owes its stamp BEFORE `closed` is set — and the // close's own settle then lands it — or finds the door shut and leaves the - // folder alone. Measured on the Spark, 2026-09-12: thirteen runs in five + // folder alone. Measured in a test run, 2026-09-12: thirteen runs in five // thousand of one asklane fixture failed as `TempDir RemoveAll cleanup: // directory not empty`, and the file left behind was this stamp. // diff --git a/internal/session/taskdelta_test.go b/internal/session/taskdelta_test.go index bd4853b330..06fb942971 100644 --- a/internal/session/taskdelta_test.go +++ b/internal/session/taskdelta_test.go @@ -302,7 +302,7 @@ func TestACloseLandsTheStampTheReadingOwedBeforeIt(t *testing.T) { // // It is held on a channel until the close has returned, and the watch // [readBeside] tells about its own landings is what says the reading is done — -// not a guess about the scheduler (sidecar.go). Measured on the Spark, +// not a guess about the scheduler (sidecar.go). Measured in a test run, // 2026-09-12: without the refusal, thirteen runs in five thousand of one // `internal/session` fixture failed as `TempDir RemoveAll cleanup: directory not // empty`, and the file left behind in every one of them was this stamp — a red diff --git a/internal/session/taskname_test.go b/internal/session/taskname_test.go index 8c99daba05..68a32b4b0d 100644 --- a/internal/session/taskname_test.go +++ b/internal/session/taskname_test.go @@ -385,7 +385,7 @@ func TestTheNamerIsRegisteredOnTheCheapClass(t *testing.T) { // A PERSON'S `/task` IS NAMED THE MOMENT IT EXISTS. That is the exact case the // complaint arrived as: the row falls back to the person's own first eight words, -// and the column shows the first three of them — "read /Users/me/src" — which +// and the column shows the first three of them — "read /workspace/src" — which // names the work after the path they pasted. The shaper used to name it, after a // wait in front of the node; the door asks no model now (task_person.go), so the // namer every unnamed node gets is the one that names this one too, and the diff --git a/internal/session/taskoutside.go b/internal/session/taskoutside.go index 72d6416376..d38d8fbcb4 100644 --- a/internal/session/taskoutside.go +++ b/internal/session/taskoutside.go @@ -8,7 +8,7 @@ package session // against a repository somewhere else. The brief named that repository by its // full path, so both workers ran // -// cd /Users/…/code/agentfield && git checkout -b fix/… +// cd /workspace/code/agentfield && git checkout -b fix/… // // and the guard next door (taskgit.go) answered with the sentence it has always // answered `checkout` with: "this is your own copy of the repository and it diff --git a/internal/session/taskoutside_test.go b/internal/session/taskoutside_test.go index 47edbca9a2..61a1dd4d3b 100644 --- a/internal/session/taskoutside_test.go +++ b/internal/session/taskoutside_test.go @@ -216,7 +216,7 @@ func TestAWorkerIsRefusedOnTheSeamForWritingOutsideItsGround(t *testing.T) { } // AND A BASH AIMED OUT OF THE GROUND IS REFUSED WITH THE PATH LAW'S SENTENCE - // AND NOT THE VERB GUARD'S, which is the defect this lane exists for. + // AND NOT THE VERB GUARD'S, which is the defect this test exists for. command := `{"command":"cd ` + elsewhere + ` && git checkout -b fix/codeql-54"}` shell := worker.executeTool(context.Background(), episode, nil, withdrawnCall("c3", "bash", command), "") if !shell.isError || !strings.Contains(shell.text, outsideYourCopy) { diff --git a/internal/session/taskstands.go b/internal/session/taskstands.go index a2712ca328..2b47ed6dda 100644 --- a/internal/session/taskstands.go +++ b/internal/session/taskstands.go @@ -400,7 +400,7 @@ func saidGround(said, workspace string) taskStand { // made ~/Desktop/pong, named it as ground and said `in place` handed senior-dev // the whole home folder; senior-dev, finding no git history there, began to // snapshot all of it and died on the first folder macOS keeps to itself -// (`open /Users/…/.Trash: operation not permitted`). So a program's placement +// (`open /workspace/.Trash: operation not permitted`). So a program's placement // is its own (programfolder.go) and `where` is not read for it. // // THE FOLDER IS READ BEFORE THE CARD, as the run will read it: snapped to its diff --git a/internal/session/tools.go b/internal/session/tools.go index f74b625949..5b6f4027d5 100644 --- a/internal/session/tools.go +++ b/internal/session/tools.go @@ -114,7 +114,7 @@ func (a *Agent) resultCaps() bare.Caps { return bare.CapsFor(a.window()) } // briefed to do one piece of work, not to retune the product around it. // // AND ON THE EXPERIMENT BRANCH THERE IS A THIRD ANSWER: THE SIX FILE TOOLS -// COME OFF ENTIRELY. spark/bash-task-loop hands a task worker ONE bash tool — +// COME OFF ENTIRELY. The bash task belt hands a task worker ONE bash tool — // bare's, with the branch's head+tail+path cut and the session's background // argument — and the kept hands that cannot be a shell command, under a strict // one-action-per-response envelope (bashbelt.go, bashbelt_envelope.go). It is diff --git a/internal/session/tools_pdf.go b/internal/session/tools_pdf.go index c7ab621c84..2bfe7e96c0 100644 --- a/internal/session/tools_pdf.go +++ b/internal/session/tools_pdf.go @@ -70,7 +70,7 @@ func (a *Agent) pdfRead(inner bare.Tool) bare.Tool { return a.senseRead(inner) } // pdfSense is the local rung: extract the text layer in-binary and page it by // pi's law. shown is the path AS THE MODEL WROTE IT, because every sentence // below quotes it back and a model that asked about `spec.pdf` should not be -// answered about `/home/…/spec.pdf`. +// answered about `/workspace/spec.pdf`. // // It is only ever called for a file the sniff already claimed and the stat // already found, so there is no "not a PDF" and no "no such file" branch left diff --git a/internal/session/tools_tasks.go b/internal/session/tools_tasks.go index 90b022f85b..e69e4b3b73 100644 --- a/internal/session/tools_tasks.go +++ b/internal/session/tools_tasks.go @@ -598,7 +598,7 @@ func everyFamilyCount(groups []otherProjectFamilies) int { // machine, grouped by project, under the same query the search used. // // running in other projects on this machine: -// wisp · /Users/ada/code/wisp +// wisp · /workspace/code/wisp // another window · Port the parser · running · running for 2m 3s // in the window called "parser work" // open here · Rewrite the docs · queued diff --git a/internal/session/tools_view_test.go b/internal/session/tools_view_test.go index 4300f9cb91..6220f1f667 100644 --- a/internal/session/tools_view_test.go +++ b/internal/session/tools_view_test.go @@ -23,7 +23,7 @@ import ( // viewTool is the tool as the belt would carry it, or a failure: these tests // call it directly because tools.go — where the belt lane registers viewTools — -// is not this lane's file. +// is not this test's file. func viewTool(t *testing.T, agent *Agent) bare.Tool { t.Helper() tools := agent.viewTools() diff --git a/internal/session/writeseam.go b/internal/session/writeseam.go index bd32d48d19..4e5fd50f64 100644 --- a/internal/session/writeseam.go +++ b/internal/session/writeseam.go @@ -13,7 +13,7 @@ package session // was deliberately demoted to triage, and the post-turn judge excuses any turn // that used tools. // -// ── THE RULING (owner, 2026-09-01, issue #272) ── +// ── THE RULING ── // // A turn may make A SMALL BOUNDED EDIT INLINE — of the order of // [writeAllowanceCalls] write calls — and then the next workspace write promotes diff --git a/internal/session/writeseam_test.go b/internal/session/writeseam_test.go index 91ee19b01b..ca29d41306 100644 --- a/internal/session/writeseam_test.go +++ b/internal/session/writeseam_test.go @@ -1,6 +1,6 @@ package session -// THE WRITE SEAM, PROVED (issue #272, part 2, on the owner's ruling). +// THE WRITE SEAM, PROVED (issue #272, part 2, on). // // The measured run is one sentence: a chat turn made forty-eight tool calls and // edited a person's live checkout with `sed -i` for seven minutes and forty-six diff --git a/internal/splitgate/modes.go b/internal/splitgate/modes.go index 01e14926a9..317d456942 100644 --- a/internal/splitgate/modes.go +++ b/internal/splitgate/modes.go @@ -6,28 +6,9 @@ import ( "github.com/Agent-Field/codeaf/internal/env" ) -// Which reading of "is this division real" a run is on. -// -// THE GATE IS OFF UNLESS SOMEBODY PINNED IT ON. It shipped armed, with a -// six-item floor under every division, and issue #418 said the floor folds real -// divisions: a brief that names three lanes over one file counts zero items and -// is refused. Two repairs were proposed and neither was argued to a conclusion, -// so the owner ruled that the choice would be made by a designed experiment — -// four planner arms against four readings of this gate, 273 judged draws on the -// plan door (docs/design/plan-gate-doe/REPORT.md). -// -// THE EXPERIMENT PICKED THE GATE OFF. The front it drew is the stages planner -// with this gate having no say: the same quality as the best armed cell, the -// fewest divisions the tests could not recover (4 of 21 against 12 and 18), and -// the lowest cost. Every armed reading paid for the narrow divisions it refused -// by folding wide ones, and the counting repair helped one planner and hurt -// another — an interaction, not an improvement. So on 2026-09-02 the default -// moved: with nothing pinned, every division the planner drew is kept. -// -// THE COUNT AND THE SIZING STAY REACHABLE AS PINS. The experiment measured -// them, they are not wrong everywhere, and a run that wants the shipped floor -// back should not need a build to get it — but neither is now what a person -// gets without asking. +// The division gate stays off unless explicitly enabled. A count of parts cannot +// establish that work is independent, so the opt-in modes let callers evaluate +// the gate without imposing that assumption on every plan. // GateMode is which reading of "is this division real" the binary is running. // It is a string rather than an integer because the pin is read by people diff --git a/internal/store/gate.go b/internal/store/gate.go index ba1adbee15..359f8e55d8 100644 --- a/internal/store/gate.go +++ b/internal/store/gate.go @@ -70,7 +70,7 @@ type DeliveryGate struct { // unaffordable: the thing it named is still missing, and a run that hands // that over is handing over less than it promised. One measured run shipped // "Deliverable is empty - contains no implementation" over exit 0 because - // the two were one field (2026-08-28, meta/muse-spark-1.1). + // the two were one field (2026-08-28, a model response). Unclosed bool `json:"unclosed,omitempty"` // Unjudged says NOBODY EVER READ THIS DELIVERY. The gate was asked and could diff --git a/internal/store/head_interrupt_test.go b/internal/store/head_interrupt_test.go index 506b7bf91b..30cee06a63 100644 --- a/internal/store/head_interrupt_test.go +++ b/internal/store/head_interrupt_test.go @@ -9,7 +9,7 @@ import ( // TestHeadInterruptKindMatchesHeadPackage pins 12.8.10's two halves together. // internal/head/interrupt.go declares its own HeadInterruptKind because the -// store's kind list was closed to that lane; now that this lane has opened it, +// store's kind list was closed to that lane; now that this test has opened it, // store.CommandHeadInterrupt must stay byte-identical to head.HeadInterruptKind // or the door (RequestInterrupt) and the arm (ApplyInterrupt) would be talking // about two different commands. This is a cross-package test on purpose: it diff --git a/internal/store/open_test.go b/internal/store/open_test.go index 336658efc3..fc096dfbe2 100644 --- a/internal/store/open_test.go +++ b/internal/store/open_test.go @@ -97,7 +97,7 @@ func TestADirectoryBlockedByAFileSaysSoPlainly(t *testing.T) { } // The path in the sentence is spelled the way the person would write it down, -// because `/home/them/.codeaf/graph.db` is a path they have to translate and +// because `/workspace/.codeaf/graph.db` is a path they have to translate and // `~/.codeaf/graph.db` is one they can paste. func TestThePathIsSpelledTheWayAPersonWouldWriteIt(t *testing.T) { house := t.TempDir() diff --git a/internal/store/sessions_test.go b/internal/store/sessions_test.go index 86f172aa3e..f8e3b90f64 100644 --- a/internal/store/sessions_test.go +++ b/internal/store/sessions_test.go @@ -564,7 +564,7 @@ func TestSessionRenameSurvivesARebuild(t *testing.T) { // Replay-compat: a journal written before session_renamed existed contains // only message_posted (and, after the sibling lane landed, session_opened) // events, and replays to the byte-identical sessions table it always -// replayed to. Nothing this lane added may appear in, or change, an old +// replayed to. Nothing this test added may appear in, or change, an old // journal. func TestOldJournalsReplayToIdenticalSessionsAcrossRename(t *testing.T) { s := openThreadStore(t) @@ -596,7 +596,7 @@ func TestOldJournalsReplayToIdenticalSessionsAcrossRename(t *testing.T) { // Replay-compat: a journal written before this event existed contains only the // kinds it always contained, and replays to the byte-identical sessions table // it always replayed to. The proof is the whole projection compared row for -// row, plus the journal itself compared event for event — nothing this lane +// row, plus the journal itself compared event for event — nothing this test // added may appear in, or change, an old journal. func TestOldJournalsReplayToIdenticalSessions(t *testing.T) { s := openThreadStore(t) diff --git a/internal/store/store.go b/internal/store/store.go index 402ac63749..9154db7013 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -648,7 +648,7 @@ func probeOpen(path string) error { // pathReason strips an operating-system error down to its reason alone. // [openFailure] has already named the path, and `could not open ~/.codeaf/graph.db: -// open /home/you/.codeaf/graph.db: permission denied` says it twice. +// open /workspace/.codeaf/graph.db: permission denied` says it twice. func pathReason(err error) error { var failure *fs.PathError if errors.As(err, &failure) && failure.Err != nil { diff --git a/internal/subharness/card_test.go b/internal/subharness/card_test.go index 208a3b3bd1..7ae92d5879 100644 --- a/internal/subharness/card_test.go +++ b/internal/subharness/card_test.go @@ -39,10 +39,8 @@ func flake() Harness { } } -// postset is the shape the owner read off a screen and rejected: a fan-out into -// lanes, a gather, a check and a choice. It is the second sample because the -// laws about NESTING — lanes drawn once, a gather drawn not at all — need a -// program that has both, and flake has neither. +// It is the second sample because the laws about NESTING — lanes drawn once, a gather +// drawn not at all — need a program that has both, and flake has neither. func postset() Harness { return Harness{ Id: Id{Name: "social-post-set", Desc: "a set of platform images from one brief"}, diff --git a/internal/syncsetup/history_test.go b/internal/syncsetup/history_test.go index d87e33af26..3c000d832f 100644 --- a/internal/syncsetup/history_test.go +++ b/internal/syncsetup/history_test.go @@ -18,7 +18,7 @@ import ( ) // TestC9CommittedHistoryTravelsSealedAndWorkingSecretsUseTheVault proves the -// history half of C9 as decided by Abir on 2026-10-21. A deleted historical key +// history transfer boundary. A deleted historical key // must remain readable on the second home, with all commits and branches intact, // while an untracked .env arrives only through the vault. Every request body at // the in-process relay must be free of both plaintext keys on both transports. diff --git a/internal/syncsetup/secrets_test.go b/internal/syncsetup/secrets_test.go index 5d0be8dc15..ee8807eb5e 100644 --- a/internal/syncsetup/secrets_test.go +++ b/internal/syncsetup/secrets_test.go @@ -19,7 +19,7 @@ import ( // TestC9RelayReceivesNoPlaintextSecretsAndTakeUsesTheVault proves C9's // working-tree law at the upload and continue-here doors on both transports. -// Under Abir's 2026-10-21 contract amendment, history travels sealed; only the +// Under example's 2026-10-21 contract amendment, history travels sealed; only the // non-secret file is committed here so Git does not independently carry a key. func TestC9RelayReceivesNoPlaintextSecretsAndTakeUsesTheVault(t *testing.T) { for _, transport := range []string{"spawn", "daemon"} { diff --git a/internal/syncsetup/twohomes_test.go b/internal/syncsetup/twohomes_test.go index be76fd67f4..0f32ad6862 100644 --- a/internal/syncsetup/twohomes_test.go +++ b/internal/syncsetup/twohomes_test.go @@ -28,7 +28,7 @@ import ( // The two-home rig: one identity on two machines that share nothing but a relay // with a store, in this process, with the real engine over spawn and a scripted -// model. Machine A is "spark", machine B is "blackmac". B never sees A's disk, +// model. Machine A is "laptop", machine B is "desktop". B never sees A's disk, // git remote or credentials: everything it gets, it gets from the relay. const ( diff --git a/internal/taxonomy/taxonomy.go b/internal/taxonomy/taxonomy.go index eacd9a7ab0..462bebe623 100644 --- a/internal/taxonomy/taxonomy.go +++ b/internal/taxonomy/taxonomy.go @@ -173,7 +173,7 @@ const ( // Evidence is everything the boundary is allowed to reason from. // -// It is deliberately small and deliberately dumb: booleans and counts that the +// It is deliberately small and deliberately simple: booleans and counts that the // call site reads off the helpers it already has ([provider.RefusalFrom], // [provider.CutFrom], a tally the work carries), never an error to be // re-grepped here. A second pattern list in this package would be a second diff --git a/internal/telemetry/usage_c3_contract_test.go b/internal/telemetry/usage_c3_contract_test.go index 044465cac8..c640f8dce9 100644 --- a/internal/telemetry/usage_c3_contract_test.go +++ b/internal/telemetry/usage_c3_contract_test.go @@ -119,7 +119,7 @@ func TestK13UsageReceiptEmitsOnlyRelayValidComponents(t *testing.T) { } // relayUsageC3 mirrors validateTokenUsage and its scalar schemas in -// /home/abir/woi-82/site/src/lib/telemetry-usage.ts, including safe sums, +// /workspace/woi-82/site/src/lib/telemetry-usage.ts, including safe sums, // presence-based status, disjoint components, and estimate receipt metadata. func relayUsageC3(p map[string]any) error { fail := func(s string) error { return fmt.Errorf("%s: %v", s, p) } diff --git a/internal/tui2/tokens/glyph.go b/internal/tui2/tokens/glyph.go index 29f90ee90e..7083979cb7 100644 --- a/internal/tui2/tokens/glyph.go +++ b/internal/tui2/tokens/glyph.go @@ -171,16 +171,13 @@ const ( // exchange unreadable at exactly the moment it matters. U+21B3 is // East_Asian_Width=Neutral and one cell under both shipping rulers. GlyphReplyIn = "↳" - // GlyphFollowUp is A MESSAGE QUEUED FOR AFTER THE CURRENT TURN — one row of - // the block the session is holding above the box, put there by ctrl+enter - // (internal/tui3's followup.go). It is the reply arrow, [GlyphReplyIn]'s - // byte, by the owner's pick (2026-09-30): a line of the person's own words - // that comes AFTER what is running, the way a reply comes after what it - // answers. The two are told apart by position — the reply mark is drawn - // only under a question in its room, this one only in the block above the - // message box — which is the argument glyphvocab_test.go's table records. - // It is deliberately not [GlyphQueued], the circle a waiting TASK wears: a - // queued message read as a task would be a row promising work it is not. + // GlyphFollowUp is A MESSAGE QUEUED FOR AFTER THE CURRENT TURN — one row of the block the + // session is holding above the box, put there by ctrl+enter (internal/tui3's + // followup.go). The two are told apart by position — the reply mark is drawn only under a + // question in its room, this one only in the block above the message box — which is the + // argument glyphvocab_test.go's table records. It is deliberately not [GlyphQueued], the + // circle a waiting TASK wears: a queued message read as a task would be a row promising + // work it is not. GlyphFollowUp = "↳" // GlyphDraftUnsent is a message a person typed and then CLEARED the whole // box into — the mark the /drafts page draws in front of each line that diff --git a/internal/tui2/tokens/glyphset.go b/internal/tui2/tokens/glyphset.go index 8765feff6f..fdaa3a3f0e 100644 --- a/internal/tui2/tokens/glyphset.go +++ b/internal/tui2/tokens/glyphset.go @@ -8,11 +8,8 @@ import ( // The glyph repertoire tier (12.7). // -// One axis, [GlyphSet], swaps the CHARACTERS used for meanings 5.17 already -// fixed — 1:1, inside our own language. It is not a skin: 8.3's refusal of -// oh-my-pi's nerd-font PRESET (its colours, its brackets, its powerline chrome, -// its status-bar layout) is untouched, and nothing here changes a hue, a -// separator, a bracket, a breakpoint or a line grammar. +// One axis, [GlyphSet], swaps the characters used for a meaning without +// changing the palette, spacing or layout. // // The governing invariant, stated once: the tier changes which glyph is drawn // in a cell; it never changes how many cells a line occupies, which token tints diff --git a/internal/tui3/app.go b/internal/tui3/app.go index 402450651d..3d84647958 100644 --- a/internal/tui3/app.go +++ b/internal/tui3/app.go @@ -2525,11 +2525,10 @@ type app struct { // ([app.homeSlash]), and it is what tells a command's answer apart from every // other note this surface writes ([app.noteWritten] holds the argument). echoHome bool - // target is the draft home's box is FOR: which folder the next conversation - // opens in and which model it answers on (homedraft.go). It lives on the app - // rather than on [homeView] because both pins survive `esc` and a reopen of - // home — the owner's ruling, and homeView is rebuilt every time the screen is - // raised. + // target is the draft home's box is FOR: which folder the next conversation opens in and + // which model it answers on (homedraft.go). It lives on the app rather than on [homeView] + // because both pins survive `esc` and a reopen of home —, and homeView is rebuilt every + // time the screen is raised. target homeTarget // targetRow is which row of the frame home's rule was drawn on, and // targetFolderSpan and targetModelSpan are the columns its two doors landed @@ -2973,8 +2972,8 @@ type app struct { // (homeband_repo.go's [app.repoAsking] states this law). folderAsking map[string]bool // placeChosen is the last directory this conversation chose, whichever road - // it came in by ([app.referPlace]). It is what P1 keeps; lane P2 is what - // turns it into a remembered set on the conversation's meta. + // it came in by ([app.referPlace]). It is persisted as part of the + // remembered set on the conversation metadata. placeChosen string // recentSessions answers the box's right column and the picker's rows, and // resume opens one of them. Both are nil on a surface the door did not wire, diff --git a/internal/tui3/approvalchip.go b/internal/tui3/approvalchip.go index 2b7d7f1cb9..37c9baf1dc 100644 --- a/internal/tui3/approvalchip.go +++ b/internal/tui3/approvalchip.go @@ -28,19 +28,15 @@ import ( // // ── IT IS DRAWN ALWAYS, AND THE HUE CARRIES THE WARNING ──────────────────── // -// The status row used to carry `YOLO` and NOTHING ELSE — drawn only when the -// gate was open, on the reasoning that a permanent "safe" badge is a badge -// nobody reads (render.go's old NEGATIVE-SPACE SAFETY). That law was right -// about a badge and wrong about a control: A CONTROL THAT IS INVISIBLE UNTIL -// YOU HAVE ALREADY USED IT IS NOT A CONTROL, which is the ruling that put -// `⠿ auto` on every fresh conversation (owner ruling 2026-09-11, effortchip.go). -// So the cell is drawn at every posture, and what the old law protected is -// kept by the PAINT rather than by the presence: `asks` and `guardian` are dim -// furniture like the rest of the seam, and `YOLO` and `refuses` wear the bad -// hue for as long as they are true — loud for what they mean, exactly as the -// badge was. The word `YOLO` is kept because it is the one the flag, the -// manual and the owner all use; a chip that said `allow` would be a third -// spelling of one fact. +// The status row used to carry `YOLO` and NOTHING ELSE — drawn only when the gate was +// open, on the reasoning that a permanent "safe" badge is a badge nobody reads +// (render.go's old NEGATIVE-SPACE SAFETY). That law was right about a badge and wrong +// about a control: A CONTROL THAT IS INVISIBLE UNTIL YOU HAVE ALREADY USED IT IS NOT A +// CONTROL, which is the ruling that put `⠿ auto` on every fresh conversation. So the cell +// is drawn at every posture, and what the old law protected is kept by the PAINT rather +// than by the presence: `asks` and `guardian` are dim furniture like the rest of the seam, +// and `YOLO` and `refuses` wear the bad hue for as long as they are true — loud for what +// they mean, exactly as the badge was. // // THE BADGE IS OFF THE STATUS ROW WHILE THE SEAM CARRIES A GATE CELL. One fact // spelled in two places on one frame is the defect the colon suffix made once @@ -51,15 +47,9 @@ import ( // cell, and on those frames the old badge — `YOLO`, only when the gate is // open — is still on the status row ([app.approvalSegment]). // -// AND THE GREETING DRAWS NEITHER. The welcome box stands where the -// conversation will be, with no seam over it, and the badge used to be the one -// thing on that frame saying the gate was open. It was a red word in the -// bottom-left corner of an otherwise empty screen, and the owner asked for it -// to go (2026-09-17): the seam goes up with the cell on it the moment the -// greeting goes — the first keystroke on every later greeting, the first -// message on the very first one ([app.spendWelcome]) — so the fact is never -// more than one message away. The row says nothing while the greeting is up, -// whatever the posture. +// AND THE GREETING DRAWS NEITHER. The welcome box stands where the conversation will be, +// with no seam over it, and the badge used to be the one thing on that frame saying the +// gate was open. The row says nothing while the greeting is up, whatever the posture. // // ── THE WHEEL HAS THREE STOPS AND `deny` IS NOT ONE OF THEM ──────────────── // diff --git a/internal/tui3/approvalchip_test.go b/internal/tui3/approvalchip_test.go index a15c0ab62e..69b38f4416 100644 --- a/internal/tui3/approvalchip_test.go +++ b/internal/tui3/approvalchip_test.go @@ -98,12 +98,9 @@ func TestTheSeamSaysWhatRunsWithoutAskingAtEveryPosture(t *testing.T) { } } -// THE GREETING DRAWS NO BADGE, AT ANY POSTURE. The welcome box stands where -// the conversation will be with no seam over it, and the red word in the -// corner of that empty frame was the thing the owner asked to have removed: -// the first keystroke puts the seam up with the cell on it. And a frame with -// no greeting and no cell — a window whose engine has no dial — still says -// `YOLO` on the row when the gate is open, and only then. +// THE GREETING DRAWS NO BADGE, AT ANY POSTURE. And a frame with no greeting and no cell — +// a window whose engine has no dial — still says `YOLO` on the row when the gate is open, +// and only then. func TestTheGreetingDrawsNoBadgeAndAFrameWithNoChipStillDoes(t *testing.T) { agent, a := gated(t) agent.stored = session.PostureAllow diff --git a/internal/tui3/atspaces_test.go b/internal/tui3/atspaces_test.go index 8b196c6b55..7682da532d 100644 --- a/internal/tui3/atspaces_test.go +++ b/internal/tui3/atspaces_test.go @@ -196,9 +196,8 @@ func (b atBox) comp(a *app) *completion { return &a.comp } -// TestTheAtListIsTheSameOnEveryBox: the same fixture, the same searches with -// spaces in them, the same answers — on a conversation's box, on home's, and -// on the new-chat page's. The owner asked for this to hold always. +// TestTheAtListIsTheSameOnEveryBox: the same fixture, the same searches with spaces in +// them, the same answers — on a conversation's box, on home's, and on the new-chat page's. func TestTheAtListIsTheSameOnEveryBox(t *testing.T) { for _, b := range atBoxes { t.Run(b.name, func(t *testing.T) { diff --git a/internal/tui3/attach.go b/internal/tui3/attach.go index 7f9139586c..ad3a0c105e 100644 --- a/internal/tui3/attach.go +++ b/internal/tui3/attach.go @@ -278,10 +278,10 @@ func (a *app) removeChip(i int) { // path the person typed is a sentence they can act on and "could not attach" // is not. // -// /image WAS THE OTHER WORD FOR THIS AND IS GONE (2026-09-22). It took only a -// picture and refused everything else, which made two commands out of one -// gesture; the owner ruled that one word puts a thing on the tray and the -// tray tells a picture from a file, which the paragraph below already did. +// /image WAS THE OTHER WORD FOR THIS AND IS GONE (2026-09-22). It took only a picture and +// refused everything else, which made two commands out of one gesture; one word puts a +// thing on the tray and the tray tells a picture from a file, which the paragraph below +// already did. // // A PICTURE HANDED TO /attach IS STILL A PICTURE. Somebody who has learned one // word for putting a thing into a message should not have to learn that this @@ -381,14 +381,14 @@ func (a *app) resolvePath(path string) string { // they copied it from would read it: a path wrapped in matching quotes loses // them, and a backslash before a space is the space. A macOS Finder copy and // a terminal drop both arrive in one of those shapes, and until 2026-09-22 -// `/attach '/Users/me/Screenshot 2026-09-18 at 1.35.20 PM.png'` was answered +// `/attach '/workspace/Screenshot 2026-09-18 at 1.35.20 PM.png'` was answered // with `no such file` about a file that was there. The paste reader already // knows both shapes ([pastedWords]); a run that reads as ONE word is taken as // that word, and anything else is left exactly as typed. func unquotePath(path string) string { path = strings.TrimSpace(path) // ONLY A PATH THAT IS SPELLED THE SHELL'S WAY IS READ THE SHELL'S WAY: one - // that opens with a quote, or carries a backslash escape. `owner's + // that opens with a quote, or carries a backslash escape. `example's // report.log` typed plainly has an apostrophe in its NAME, and reading that // as an open quote swallowed it (the drop road had already unquoted the // terminal's spelling before this was asked, dropkeys_test.go). diff --git a/internal/tui3/bargein_test.go b/internal/tui3/bargein_test.go index 7ca92315bd..92204ed3ce 100644 --- a/internal/tui3/bargein_test.go +++ b/internal/tui3/bargein_test.go @@ -206,10 +206,9 @@ func TestTheChordIsAbsentOnATerminalThatCannotSpellIt(t *testing.T) { // ── discoverability ───────────────────────────────────────────────────────── -// THE FOOT DOES NOT NAME THE CHORD (the owner's call, 2026-09-30). The chord -// still works wherever the terminal can send it — the tests above drive it — -// but the running-turn line teaches plain enter alone, and the key sheet is -// where ctrl+shift+enter is written down. +// THE FOOT DOES NOT NAME THE CHORD. The chord still works wherever the terminal can send +// it — the tests above drive it — but the running-turn line teaches plain enter alone, and +// the key sheet is where ctrl+shift+enter is written down. func TestTheRunningFootDoesNotNameTheChord(t *testing.T) { a, _ := bargeable(t, "reading the tree. ") diff --git a/internal/tui3/boxselect_test.go b/internal/tui3/boxselect_test.go index d4b0514244..ac74892f8f 100644 --- a/internal/tui3/boxselect_test.go +++ b/internal/tui3/boxselect_test.go @@ -1,9 +1,6 @@ package tui3 -// SELECTING TEXT IN A BOX, AND TAKING BACK WHAT WAS TYPED. The two halves of -// what the owner asked for: "i am unable to select text with highlight from -// input bar in all places … it acts like normal text", and "maybe even ctrl+z -// as well like undo or redo like shift z". +// SELECTING TEXT IN A BOX, AND TAKING BACK WHAT WAS TYPED. import ( "strings" diff --git a/internal/tui3/bundle_test.go b/internal/tui3/bundle_test.go index 0c22e9c784..ef8248a65b 100644 --- a/internal/tui3/bundle_test.go +++ b/internal/tui3/bundle_test.go @@ -1864,13 +1864,12 @@ func TestAnUnnamedSessionPutsNoPlaceholderOnTheLegend(t *testing.T) { } } -// `VIA <MACHINE>` IS ON THE SEAM WHOEVER SERVED, which is the owner's ruling of -// 2026-09-09. The rider used to go silent when the server's name was already -// inside the model id — `z-ai/glm-5.3-flash` answered by z-ai — on the argument -// that the reader already had the word. On this line they do not: the model is -// spelled as its BASENAME, so the vendor half of the id is not on the screen at -// all, and a rider that appeared for one endpoint and vanished for another read -// as the sighting having been lost. +// `VIA <MACHINE>` IS ON THE SEAM WHOEVER SERVED. The rider used to go silent when the +// server's name was already inside the model id — `z-ai/glm-5.3-flash` answered by z-ai — +// on the argument that the reader already had the word. On this line they do not: the +// model is spelled as its BASENAME, so the vendor half of the id is not on the screen at +// all, and a rider that appeared for one endpoint and vanished for another read as the +// sighting having been lost. func TestTheSeamNamesTheMachineEvenWhereTheVendorServesItsOwnModel(t *testing.T) { a, _, now := hudApp(t) a.title = "porting the parser" @@ -1888,10 +1887,9 @@ func TestTheSeamNamesTheMachineEvenWhereTheVendorServesItsOwnModel(t *testing.T) } } -// A LONG TITLE COSTS THE SEAM NOTHING, because the title is not on it (foot.go: -// the owner's ruling of 2026-09-17). Until that day a long name was cut with -// one ellipsis after the branch had gone; now the numbers stay, and the name -// is on the tab strip whatever its length. +// A LONG TITLE COSTS THE SEAM NOTHING, because the title is not on it (foot.go:). Until +// that day a long name was cut with one ellipsis after the branch had gone; now the +// numbers stay, and the name is on the tab strip whatever its length. func TestALongNameIsCutOnTheSeamAndNeverTakesTheNumbersSlot(t *testing.T) { a, _, _ := hudApp(t) a.title = "porting the parser off the old tokenizer and onto the new one at last" @@ -2286,10 +2284,6 @@ func TestTheHintSlotFollowsTheStateAndIsEmptyAtRest(t *testing.T) { } a.pick.open = false - // A call parked on a person says NOTHING here while the block above the box - // is drawing its own keys (owner ruling 2026-09-11, hints pick A): the slot - // three rows under the panel repeating the panel's keys, in its own order, - // was the owner's "the hint line names keys that are not there". a.entries = append(a.entries, entry{kind: entryTool, tool: "bash", status: toolConsent}) raiseAsk(a, 7, "bash") if hint := a.hintWord(); strings.Contains(hint, "allow once") { @@ -4482,12 +4476,11 @@ func TestSteeringANodeWaitingOnItsPiecesSaysWhatTheLineJustDid(t *testing.T) { } } -// EVERY TASK STEER CONFIRMS DELIVERY (the owner's ruling 4, 2026-09-01). A -// correction typed into this conversation is answered by the answer; one typed -// into a task crosses to ANOTHER AGENT and the page can stay silent afterwards -// for as long as the node's current step runs. That silence is what the person -// would also see if the words had gone nowhere, so the elbow says they arrived — -// briefly, on the same fade the conversation's own landing clause takes. +// EVERY TASK STEER CONFIRMS DELIVERY. A correction typed into this conversation is +// answered by the answer; one typed into a task crosses to ANOTHER AGENT and the page can +// stay silent afterwards for as long as the node's current step runs. That silence is what +// the person would also see if the words had gone nowhere, so the elbow says they arrived +// — briefly, on the same fade the conversation's own landing clause takes. func TestEveryTaskSteerConfirmsDelivery(t *testing.T) { a, _, _ := roomApp(t) clickRail(t, a, 0) @@ -4933,10 +4926,7 @@ func TestTheSeamKeepsTheRiderWithoutTheBranchOrTitle(t *testing.T) { } } -// THE SEAM'S RIDER IS ATTRIBUTION ALONE. On 2026-09-10 the owner read `via -// relace · 1.3s · 79 t/s` beside the model while an answer was being written -// and took the figure for the live rate — which stood, that same frame, at the -// right edge of the status row. The last answer's wait and average stay on the +// THE SEAM'S RIDER IS ATTRIBUTION ALONE. The last answer's wait and average stay on the // sheet's `served` row, where a person goes to ask about the last answer. func TestTheSeamRiderNamesTheMachineAndNotTheLastAnswersFigures(t *testing.T) { a, _, now := hudApp(t) diff --git a/internal/tui3/c263_rail_plan_test.go b/internal/tui3/c263_rail_plan_test.go index 21c8ca3e3e..1a49e8ebf0 100644 --- a/internal/tui3/c263_rail_plan_test.go +++ b/internal/tui3/c263_rail_plan_test.go @@ -65,10 +65,7 @@ func TestRailPlanDrawsEveryPartAsATaskRow(t *testing.T) { } } -// THE RAIL DRAWS THE TREE IN A CONVERSATION NOBODY HAS OPENED THE TASKS PLACE -// IN. The person sits in the chat; the tasks place is a room they may never walk -// into, and a rail that waited for that walk would show no tree in the one -// place the owner asked for it. +// THE RAIL DRAWS THE TREE IN A CONVERSATION NOBODY HAS OPENED THE TASKS PLACE IN. func TestRailPlanDrawsWithoutTheTasksPlaceEverOpening(t *testing.T) { a, _ := planAppWith(t, c263PlanRows(), nil) a.width, a.height, a.railWide = 120, 30, true diff --git a/internal/tui3/captionmotion.go b/internal/tui3/captionmotion.go index 13500ac1e3..5b2b0c92e7 100644 --- a/internal/tui3/captionmotion.go +++ b/internal/tui3/captionmotion.go @@ -11,29 +11,24 @@ import ( ) // The sweep follows elapsed time, sampled by the existing paint clock. A busy -// terminal may skip pictures without slowing the sign of life. The two-second -// travel and cosine feather follow Codex's terminal summary shimmer; keeping -// the crest at ordinary reading ink makes the movement visible without a flash. -// https://github.com/openai/codex/blob/main/codex-rs/tui/src/summary_shimmer.rs +// terminal may skip pictures without slowing the sign of life. Keeping the +// crest at ordinary reading ink makes the movement visible without a flash. const ( shimmerPeriod = 2 * time.Second shimmerMinRadius = 6.0 shimmerWidthRatio = 0.20 ) -// shimmer paints the one moving highlight a collapsed live caption owns. -// -// THE SHIMMER IS THE SPINNER, RELOCATED. Opening the work returns its animation -// budget to the tool rows immediately. The letters never move, and the smooth -// bell reaches ordinary answer ink only at its crest. Measuring whole graphemes -// in terminal cells keeps accents and joined emoji intact under the highlight. +// The sweep follows elapsed time, sampled by the existing paint clock. A busy +// terminal may skip pictures without slowing the sign of life. Keeping the +// crest at ordinary reading ink makes the movement visible without a flash. func (a *app) shimmer(text string) string { if text == "" || a.anyWorkLogoVisible() || a.linear || a.pal.linear || a.pal.profile < tokens.TrueColor { return a.pal.narr(text) } - // A turn supplies a stable origin when it has one. Rooms can run while the - // conversation is idle, so they use the same clock's absolute phase instead. - // Neither rendering nor opening a disclosure starts another timer. + // The sweep follows elapsed time, sampled by the existing paint clock. A busy + // terminal may skip pictures without slowing the sign of life. Keeping the + // crest at ordinary reading ink makes the movement visible without a flash. elapsed := time.Duration(a.now().UnixNano()) if !a.turnBegan.IsZero() { elapsed = a.now().Sub(a.turnBegan) @@ -41,8 +36,9 @@ func (a *app) shimmer(text string) string { return a.shimmerAt(text, elapsed, shimmerPeriod, 1) } -// shimmerAt shares the same feather and palette ladder across caption owners. -// Activity phrases use a separate decoding ripple instead of a light sweep. +// The sweep follows elapsed time, sampled by the existing paint clock. A busy +// terminal may skip pictures without slowing the sign of life. Keeping the +// crest at ordinary reading ink makes the movement visible without a flash. func (a *app) shimmerAt(text string, elapsed, period time.Duration, strength float64) string { if text == "" || a.linear || a.pal.linear || a.pal.profile < tokens.TrueColor { return a.pal.narr(text) @@ -64,9 +60,9 @@ func (a *app) shimmerAt(text string, elapsed, period time.Duration, strength flo amount = (1 + math.Cos(math.Pi*distance/radius)) / 2 } color := a.pal.shimmerHue(amount * strength) - // Adjacent clusters with the same colour share one escape pair. Most of - // the line is the quiet prefix or suffix, so per-character escapes there - // would spend terminal bandwidth on pixels that have not changed. + // The sweep follows elapsed time, sampled by the existing paint clock. A busy + // terminal may skip pictures without slowing the sign of life. Keeping the + // crest at ordinary reading ink makes the movement visible without a flash. if offset > start && color != previous { b.WriteString(a.pal.paint(text[start:offset], previous)) start = offset @@ -79,10 +75,9 @@ func (a *app) shimmerAt(text string, elapsed, period time.Duration, strength flo return b.String() } -// shimmerHue follows the current theme's reading ladder rather than flashing -// white. Its feather is continuous in truecolour. Lower-colour and accessible -// tiers stay still: nearest 256-colour matches can jump between unrelated hues, -// and a switch in font weight cannot express a gentle colour transition either. +// The sweep follows elapsed time, sampled by the existing paint clock. A busy +// terminal may skip pictures without slowing the sign of life. Keeping the +// crest at ordinary reading ink makes the movement visible without a flash. func (p palette) shimmerHue(amount float64) hue { base, ink := p.ramp.narr, p.ramp.ink mix := func(a, b uint8) uint8 { diff --git a/internal/tui3/carddoors.go b/internal/tui3/carddoors.go index 028cfafd57..241cda96b5 100644 --- a/internal/tui3/carddoors.go +++ b/internal/tui3/carddoors.go @@ -10,14 +10,12 @@ import ( // ── THE CARD'S DOORS, AND THE POINTER ON THEM ─────────────────────────────── // -// THE RIGHT COLUMN HAS DOORS AND NOTHING ON IT SAID SO. A fold line opens the -// band it is the foot of, and a work row opens that task's record — both of -// them presses a person can make and neither of them a thing the card drew any -// differently from the sentences around it. On a terminal that is worse than on -// a page: there is no underline, no cursor change, no affordance at all except -// the one the surface paints, so a card whose doors look exactly like its prose -// is a card that hides every door it has. The owner met it as a task row that -// opened a record when pressed and lit nothing when pointed at. +// THE RIGHT COLUMN HAS DOORS AND NOTHING ON IT SAID SO. A fold line opens the band it is +// the foot of, and a work row opens that task's record — both of them presses a person can +// make and neither of them a thing the card drew any differently from the sentences around +// it. On a terminal that is worse than on a page: there is no underline, no cursor change, +// no affordance at all except the one the surface paints, so a card whose doors look +// exactly like its prose is a card that hides every door it has. // // So the line under the pointer takes THE GROUND LADDER'S CURSOR STEP // ([palette.cursor], styles.go — the same background the left column's hovered diff --git a/internal/tui3/chatstartquestions_test.go b/internal/tui3/chatstartquestions_test.go index cc46abb485..39244ba873 100644 --- a/internal/tui3/chatstartquestions_test.go +++ b/internal/tui3/chatstartquestions_test.go @@ -214,7 +214,7 @@ func TestAVisibleQuestionStillAnswersItsNumber(t *testing.T) { // A WAITING PERMISSION MUST NOT MAKE `ctrl+t` A DEAD KEY, and on a short // terminal it did — silently, which is the worst of the three things a key can -// do (lane T found it merging this branch with lane F's). +// do. // // [app.chromeHeight] charges the body region for [app.questionHeight], and a // permission hangs in a frame now: eleven rows where it used to be one. At sixty diff --git a/internal/tui3/chattip_test.go b/internal/tui3/chattip_test.go index 46daf1b75d..d6a59fb460 100644 --- a/internal/tui3/chattip_test.go +++ b/internal/tui3/chattip_test.go @@ -101,9 +101,8 @@ func TestAConversationsTipCoversTheProjectOnTheKeysRow(t *testing.T) { } } -// THE TIP STANDS WITH THE TASK COLUMN OPEN OR PUT AWAY (the owner's report, -// 2026-09-24): a column put away — whose keys row then says `ctrl+g tasks` — -// does not silence it. +// THE TIP STANDS WITH THE TASK COLUMN OPEN OR PUT AWAY: a column put away — whose keys row +// then says `ctrl+g tasks` — does not silence it. func TestTheConversationsTipStandsWithTheColumnOpenOrAway(t *testing.T) { a, _, _ := taskApp(t) a.profileDir = t.TempDir() diff --git a/internal/tui3/commands.go b/internal/tui3/commands.go index a3a1155c73..845592fa38 100644 --- a/internal/tui3/commands.go +++ b/internal/tui3/commands.go @@ -453,11 +453,9 @@ var commands = []command{ // characters with /files one row above, and a word that narrowed the list to // both errands at once is the near-miss /history was named to avoid. // - // TWO ROWS, /folder'S REASON EXACTLY: the bare form is the browser and - // enter on its row opens it at once, where one row with a placeholder - // left `/attach ` in the box waiting for a path nobody had — a second - // enter to reach the sheet the word already meant (the owner met it, - // 2026-09-22). + // TWO ROWS, /folder'S REASON EXACTLY: the bare form is the browser and enter on its row + // opens it at once, where one row with a placeholder left `/attach ` in the box waiting + // for a path nobody had — a second enter to reach the sheet the word already meant. {name: "attach", desc: "choose a file to attach · the browser opens", alias: []string{"upload"}}, {name: "attach", args: "<path>", desc: "…attach that file · tab completes the path"}, // AND DIRECTLY ABOVE /help, THE OTHER QUESTION SOMEBODY HAS WHEN THEY ARE diff --git a/internal/tui3/contextmodal.go b/internal/tui3/contextmodal.go index 250367b7cd..1fc6576db9 100644 --- a/internal/tui3/contextmodal.go +++ b/internal/tui3/contextmodal.go @@ -9,14 +9,12 @@ package tui3 // // ── WHAT THIS REPLACED, AND WHY ───────────────────────────────────────────── // -// The browser used to be BOTTOM CHROME. [app.overlayHeight] answered the -// picker's want and view.go appended its rows between the draft and the status -// line, the same slot the model picker and the command list live in. On a -// two-hundred-column terminal that meant a column of folder names with a -// hundred cells of dead space beside it, the previous turn's error line still on -// screen above it, no framing of any kind, and nothing to say a chooser had -// opened at all — the conversation simply grew a list. The owner's own word for -// it was that they expected to have opened something. +// The browser used to be BOTTOM CHROME. [app.overlayHeight] answered the picker's want and +// view.go appended its rows between the draft and the status line, the same slot the model +// picker and the command list live in. On a two-hundred-column terminal that meant a +// column of folder names with a hundred cells of dead space beside it, the previous turn's +// error line still on screen above it, no framing of any kind, and nothing to say a +// chooser had opened at all — the conversation simply grew a list. // // So the chooser is now what every other deliberate surface in this package is: // a frame taken WHOLE at the top of [app.frameBody], beside the places, the diff --git a/internal/tui3/contextmodal_test.go b/internal/tui3/contextmodal_test.go index 0e9fbacb64..bd152b4b01 100644 --- a/internal/tui3/contextmodal_test.go +++ b/internal/tui3/contextmodal_test.go @@ -5,11 +5,6 @@ package tui3 // chrome, that it owns the keyboard and the pointer while it is up, that the // conversation under it neither competes nor acts, and that leaving it changes // nothing. -// -// The owner met every one of these as a defect on a real Mac binary -// (../reports/modal.md records the screenshot and the four roots), so each test -// below is written against the FRAME — what a person would actually see — rather -// than against the browser's own state. import ( "image/png" diff --git a/internal/tui3/designlanguage_test.go b/internal/tui3/designlanguage_test.go index edac2ce8d7..5772c67aa9 100644 --- a/internal/tui3/designlanguage_test.go +++ b/internal/tui3/designlanguage_test.go @@ -155,13 +155,8 @@ var backgroundAuthors = map[string]string{ // Every tinted run on this surface therefore comes through the ladder, and // "which step is this" is a question with three answers rather than forty. // -// FIDELITY.md item 13 briefly made the places an exception: home and the six -// paint #12121A over every cell of the frame, so rest gained a floor step there. -// The owner tested it on 2026-08-25 and reversed it — "i want bg color and text -// color to be same as in inside chat please this new bg looks weird i think we -// were taking user terminal stuff or something previously" — so there is one -// ladder again, with three drawable steps and a fourth that is the absence of a -// paint, on every surface this program draws. +// FIDELITY.md item 13 briefly made the places an exception: home and the six paint #12121A +// over every cell of the frame, so rest gained a floor step there. func TestOnlyTheGroundLadderPaintsABackground(t *testing.T) { entries, err := os.ReadDir(".") if err != nil { diff --git a/internal/tui3/detach.go b/internal/tui3/detach.go index 3a30aa595b..415f84f87a 100644 --- a/internal/tui3/detach.go +++ b/internal/tui3/detach.go @@ -194,7 +194,7 @@ var resolveTranscript = filepath.EvalSymlinks // over --host the paths in a row are THE ENGINE MACHINE'S and resolving them // here walks this laptop's disk for a file that was never on it. That walk is // not merely useless: on macOS `/home` is an automounter's mount point, so -// `Lstat("/home/<name>")` on the Mac waits on autofs for a quarter of a second +// looking up a child of that directory can wait on autofs for a quarter of a second // or more — and home asked it for every row on every frame, which is why typing // on a hosted home took a second per key (2026-08-27). A hosted key is the // cleaned spelling and nothing else; the far machine's `/tmp`-versus- diff --git a/internal/tui3/devices.go b/internal/tui3/devices.go index b7bc284fb0..efb18c9995 100644 --- a/internal/tui3/devices.go +++ b/internal/tui3/devices.go @@ -2,8 +2,8 @@ package tui3 // ── THE DEVICE LIST, AND ONE KEY TO REVOKE ────────────────────────────────── // -// `/devices` lists the fleet: `● spark Linux` for a device with a watch -// socket open now, `○ dumb Mac seen 3h ago` for one without. `r` revokes the +// `/devices` lists the fleet: `● laptop Linux` for a device with a watch +// socket open now, `○ desktop Mac seen 3h ago` for one without. `r` revokes the // device under the cursor, at once and without a second question: the row is // the choice, a revoked device is refused by the relay from that moment, and // it can only come back as a new request that this fleet approves again. diff --git a/internal/tui3/dragselect_test.go b/internal/tui3/dragselect_test.go index 02b99f94f2..a20a5745df 100644 --- a/internal/tui3/dragselect_test.go +++ b/internal/tui3/dragselect_test.go @@ -140,10 +140,8 @@ func TestTheSlopSeparatesAJitteryClickFromASweep(t *testing.T) { } } -// THE GESTURE A REAL HAND MAKES AND A SYNTHETIC CLICK NEVER DOES: press, drift -// one row, release there. It is a click on the row that was PRESSED, and it -// copies nothing — the owner met the other answer, where the tool call under -// the pointer did not open and the status line said `copied · 2 lines` instead. +// THE GESTURE A REAL HAND MAKES AND A SYNTHETIC CLICK NEVER DOES: press, drift one row, +// release there. func TestAClickThatDriftsOneRowStillClicksTheRowItPressed(t *testing.T) { a := dragApp(t) y := screenRowWith(t, a, "the person wants fmt") diff --git a/internal/tui3/dropkeys.go b/internal/tui3/dropkeys.go index 496fcb41e9..f167cd2567 100644 --- a/internal/tui3/dropkeys.go +++ b/internal/tui3/dropkeys.go @@ -26,9 +26,8 @@ import ( // // unknown command: /var/folders/…/Screenshot · try /help // -// That is what the owner met on a real terminal over `--host`, twice, on the -// same screenshot. The parsing was never the problem — the same bytes delivered -// as a paste attach perfectly. THE DELIVERY SHAPE WAS. +// The parsing was never the problem — the same bytes delivered as a paste attach +// perfectly. THE DELIVERY SHAPE WAS. // // So this file gives the keystroke shape the same door. It watches for a run of // characters that spells a path, and when the run goes quiet it hands what it diff --git a/internal/tui3/editselect.go b/internal/tui3/editselect.go index 04d2ada518..843bf053fb 100644 --- a/internal/tui3/editselect.go +++ b/internal/tui3/editselect.go @@ -9,14 +9,12 @@ import ( // ── SELECTING TEXT INSIDE A BOX ───────────────────────────────────────────── // -// THE DEFECT THIS FILE EXISTS FOR. Mouse reporting takes the terminal's own -// drag-select away — dragselect.go states that law and answers it for the -// transcript — and every BOX on this surface was left out of the answer: a -// press on the message box put the caret under the pointer and returned -// (draftclick.go, placemouse.go), so the sweep that followed reached nothing at -// all. The drag machinery parks on the BODY, and a press a box has already -// taken never parks. The owner's words were "i am unable to select text with -// highlight from input bar in all places … it acts like normal text". +// THE DEFECT THIS FILE EXISTS FOR. Mouse reporting takes the terminal's own drag-select +// away — dragselect.go states that law and answers it for the transcript — and every BOX +// on this surface was left out of the answer: a press on the message box put the caret +// under the pointer and returned (draftclick.go, placemouse.go), so the sweep that +// followed reached nothing at all. The drag machinery parks on the BODY, and a press a box +// has already taken never parks. // // So a box now selects the way the transcript does and the way every text field // does: sweep and the run wears the highlight, double-click takes the word, diff --git a/internal/tui3/editundo.go b/internal/tui3/editundo.go index d8161ab039..9b56210676 100644 --- a/internal/tui3/editundo.go +++ b/internal/tui3/editundo.go @@ -2,13 +2,11 @@ package tui3 // ── TAKING BACK WHAT YOU JUST TYPED ───────────────────────────────────────── // -// `ctrl+z` puts the box back the way it was, and `ctrl+shift+z` puts it forward -// again. Every text field a person has ever used answers those two, and no box -// on this surface answered either: a sentence rewritten by a `ctrl+u` that went -// one word too far, a paste that landed in the wrong draft, a word kill on the -// wrong side of the caret — all of them were gone, and the only way back was to -// type the words again. The owner asked for it in as many words ("maybe even -// ctrl+z as well like undo or redo like shift z"). +// `ctrl+z` puts the box back the way it was, and `ctrl+shift+z` puts it forward again. +// Every text field a person has ever used answers those two, and no box on this surface +// answered either: a sentence rewritten by a `ctrl+u` that went one word too far, a paste +// that landed in the wrong draft, a word kill on the wrong side of the caret — all of them +// were gone, and the only way back was to type the words again. // // ── ctrl+z REACHES US, AND THAT IS NOT AN ACCIDENT ── // diff --git a/internal/tui3/effortchip_test.go b/internal/tui3/effortchip_test.go index 1d74709ca1..cbbae0055c 100644 --- a/internal/tui3/effortchip_test.go +++ b/internal/tui3/effortchip_test.go @@ -253,13 +253,12 @@ func TestAHostedConversationDrawsTheRungItsEngineAdmitsTo(t *testing.T) { } } -// THE RIDER STANDS BETWEEN THE MODEL AND THE RUNG. Until 2026-09-17 the rung -// was anchored to the model so that a rider coming and going on a sighting's -// own clock could not slide it sideways; the owner ruled that day that the -// model and its machine read as one cell — `deepseek-v4 (quicksilver)` — -// so the rung stands past the pair and moves with it. What holds still is -// the model's own column, and the recorded doors move with their cells -// (foot.go's seamSpans). +// THE RIDER STANDS BETWEEN THE MODEL AND THE RUNG. Until 2026-09-17 the rung was anchored +// to the model so that a rider coming and going on a sighting's own clock could not slide +// it sideways; day that the model and its machine read as one cell — `deepseek-v4 +// (quicksilver)` — so the rung stands past the pair and moves with it. What holds still is +// the model's own column, and the recorded doors move with their cells (foot.go's +// seamSpans). func TestTheRungKeepsItsColumnsWhenTheRiderComesAndGoes(t *testing.T) { _, a := dialled(t) bare := seamLine(t, a) diff --git a/internal/tui3/effortscope_test.go b/internal/tui3/effortscope_test.go index c2465357b8..bdca3bd7c5 100644 --- a/internal/tui3/effortscope_test.go +++ b/internal/tui3/effortscope_test.go @@ -247,7 +247,7 @@ func TestAltEOnAConversationRowChangesNothing(t *testing.T) { } } -// AND THE CONVERSATION ITSELF IS NOT, EITHER — not from this lane. With no +// AND THE CONVERSATION ITSELF IS NOT, EITHER — not from this test. With no // roster hold and no room, the chord reaches nothing that would write. func TestAltEWithNoTaskUnderTheCursorAsksTheEngineNothing(t *testing.T) { a, agent := effortTaskApp(t) diff --git a/internal/tui3/failurerow_test.go b/internal/tui3/failurerow_test.go index 750ee0371d..dea2cb6d8f 100644 --- a/internal/tui3/failurerow_test.go +++ b/internal/tui3/failurerow_test.go @@ -12,11 +12,6 @@ import ( // THE FAILURE STORY, ON THE SCREEN. // -// These are the owner's report of 2026-09-10 written down as tests: a turn ran -// two commands, failed the follow-up request four times over ninety seconds and -// gave up — and what was on the screen two minutes later was a step that still -// said `running 2 commands` with nothing under it. "Things are just stuck". -// // Each of them asserts THE RENDERED FRAME rather than a field, because every one // of the defects was a fact the surface held perfectly well and never drew. diff --git a/internal/tui3/feed_test.go b/internal/tui3/feed_test.go index c5e6552ff5..8bf7d0d017 100644 --- a/internal/tui3/feed_test.go +++ b/internal/tui3/feed_test.go @@ -29,7 +29,7 @@ func TestFinalTruncatedErrorWithdrawsOnlyItsUnfinishedReply(t *testing.T) { } // TestOneCallBecomesOneRowFromTheFirstFragmentToTheResult drives the reducer -// with NO VIEW BEHIND IT AT ALL, which is the half of the law this lane is for: +// with NO VIEW BEHIND IT AT ALL, which is the half of the law this test is for: // a transcript is grown by [feed] and by nothing else, so a feed with no hooks // installed has to produce the same one row a chat does — arriving, queued, // running, resolved — rather than four. diff --git a/internal/tui3/firstrun.go b/internal/tui3/firstrun.go index 30748217e1..c18b313dc6 100644 --- a/internal/tui3/firstrun.go +++ b/internal/tui3/firstrun.go @@ -727,7 +727,7 @@ func (a *app) setupCommit() bool { // setup's refusals were `err.Error()`, so the first sentence a new person could // be shown — on the one screen where they have done nothing yet and something // has already failed — was a wrapped chain like `write config daily_budget_usd: -// open /home/…/.codeaf/config.json: permission denied`. It names a function, a +// open /workspace/.codeaf/config.json: permission denied`. It names a function, a // key, a path inside the program's own storage and an errno, and there is no act // in it. Three lines away this same file already had the right shape twice // ([setupKeyShapeWord], [setupNoKeyConnectWord]): the cause, and then what to do. diff --git a/internal/tui3/folderact.go b/internal/tui3/folderact.go index ec8c9a73d0..82a1e6e2d1 100644 --- a/internal/tui3/folderact.go +++ b/internal/tui3/folderact.go @@ -281,12 +281,10 @@ func (a *app) folderConfirm() tea.Cmd { // the next conversation's ([homeTarget.where]) and the files go on the tray home // is already carrying, with home back on the frame under both. // -// A PIN IS NOT A ROUND TRIP. Registering a folder with an agent is a write and a -// wire call, which is why the ordinary confirm runs off the loop; setting a -// string on this window is neither, and it is the same act `alt+p` performs -// synchronously one keystroke away (homedraft.go's [app.moveTarget]). So the -// rule above home's box says the new folder on the very next frame — which is -// the whole of what the owner asked to be able to see. +// A PIN IS NOT A ROUND TRIP. Registering a folder with an agent is a write and a wire +// call, which is why the ordinary confirm runs off the loop; setting a string on this +// window is neither, and it is the same act `alt+p` performs synchronously one keystroke +// away (homedraft.go's [app.moveTarget]). // // THE FILES STILL GO THE LONG WAY ROUND, because a file is a stat and a stat is // a disk: they ride the same command every other confirm fires, and land on the diff --git a/internal/tui3/foldercontext_test.go b/internal/tui3/foldercontext_test.go index f18e5f4509..dca5887df6 100644 --- a/internal/tui3/foldercontext_test.go +++ b/internal/tui3/foldercontext_test.go @@ -1,10 +1,5 @@ package tui3 -// foldercontext_test.go is THE CONTEXT BROWSER as the owner asked for it: files -// and folders in one deliberate sheet, a real preview beside them, a mark tray -// and a confirm that does what the row says — and, under all of it, the law -// that makes the sheet safe to explore: -// // BROWSING, FOCUSING AND PREVIEWING ATTACH NOTHING. // // Every test here either proves that law or proves one deliberate act crossing @@ -523,10 +518,8 @@ func TestThePreviewHidesAndTakesTheWholeSheet(t *testing.T) { t.Fatalf("the wide legend reads %q", a.folder.folderHintAt(a.width)) } drive(t, a, key(folderWideKey)) - // EVERY CHORD THE SHEET OWNS IS NAMED EXACTLY ONCE, across the two lines that - // carry them: the box's own placeholder and the foot row under the columns. - // Naming them all in both places was the wall of shortcuts the owner's review - // asked us to stop drawing (folderpick.go's [folderBrowseHintFields]). + // EVERY CHORD THE SHEET OWNS IS NAMED EXACTLY ONCE, across the two lines that carry them: + // the box's own placeholder and the foot row under the columns. said := a.folder.folderHintAt(a.width) + " · " + a.folder.controlLegend(a.width) for _, want := range []string{folderPaneKey, folderWideKey, folderMarkKey, "esc", "enter"} { if !strings.Contains(said, want) { @@ -904,11 +897,9 @@ func TestAThingThatVanishedUnderTheConfirmSaysSo(t *testing.T) { // THE WAY OUT AND THE PREVIEW'S OWN DOOR ARE ON THE SHEET AT EVERY WIDTH, and // which of the two places names them is contextual. // -// The foot row used to name every chord the sheet owns, at every width, which is -// the wall of shortcuts the owner's review asked us to stop drawing. `alt+o` is -// on the foot exactly where the preview is NOT drawn — there it is the only way -// to read a file at all — and in the box's own placeholder where it is, because -// the box is empty while browsing now and its placeholder is on screen. +// `alt+o` is on the foot exactly where the preview is NOT drawn — there it is the only way +// to read a file at all — and in the box's own placeholder where it is, because the box is +// empty while browsing now and its placeholder is on screen. func TestThePreviewDoorAndTheWayOutAreOnTheSheetAtEveryWidth(t *testing.T) { a, _, root := mixedLab(t) for _, width := range []int{52, 100, 170} { diff --git a/internal/tui3/folderfiles.go b/internal/tui3/folderfiles.go index 342e37c4cf..460aa0d8be 100644 --- a/internal/tui3/folderfiles.go +++ b/internal/tui3/folderfiles.go @@ -2,12 +2,8 @@ package tui3 // FILES IN THE BROWSER — the one listing both kinds of row come out of. // -// folderpick.go opened as a chooser of DIRECTORIES, and that is half of what -// the owner asked for: a person deciding what this conversation is about is -// nearly always looking at a folder and a file in the same window — the -// repository, and the log inside it. So the middle column lists both, and which -// kind of row the cursor is on is what decides what the action row offers -// (folderact.go). +// So the middle column lists both, and which kind of row the cursor is on is what decides +// what the action row offers (folderact.go). // // THE TWO KINDS ARE KEPT APART IN THE STRUCT AND NOT IN A FLAG PER ROW. // [folderListing.names] is still exactly what it was — the subdirectories, in diff --git a/internal/tui3/folderpick.go b/internal/tui3/folderpick.go index a84e303bd3..d753b7dfb2 100644 --- a/internal/tui3/folderpick.go +++ b/internal/tui3/folderpick.go @@ -54,12 +54,9 @@ import ( "github.com/Agent-Field/codeaf/internal/tui2/tokens" ) -// folderRows is how many rows of DIRECTORIES this browser wants at once. The -// owner asked for a spacious sheet rather than the model picker's twelve, and -// eighteen is what a full-height terminal gives back after the status line, the -// box and one row of conversation — [app.overlayHeight] clamps it down on -// anything smaller, and the browser follows whatever it is actually given -// ([folderPick.page]). +// folderRows reserves eighteen directory rows on a full-height terminal, leaving +// room for the status line, composer and conversation. overlayHeight clamps +// smaller windows and the browser follows the space it receives. const folderRows = 18 // folderPaneFloorRows is the least the sheet is drawn at while a preview is @@ -231,10 +228,9 @@ type folderPick struct { // of the browser, and win is where that layout was put. win contextWin - // marks are the things a person has CHOSEN and not yet confirmed, in the - // order they chose them — the deliberate multiselect the owner asked for - // (folderact.go). Browsing, focusing and previewing put nothing in here; - // only alt+m and a press on a tray cell do. + // marks holds selections in the order they were chosen. Browsing, focusing and + // previewing add nothing; only alt+m and a press on a tray cell change this + // set. marks []folderMark // trayHot is which mark cell the pointer is over, or -1. It is answered // where the pointer is resolved ([app.folderHoverColumn]) and read where the @@ -271,11 +267,8 @@ type folderPick struct { // folderCols is the browse state: one readdir per level, and nothing deep. // -// THE COLUMNS ARE PARENT, HERE, AND THE CHILDREN OF THE ROW UNDER THE CURSOR. -// That is Finder's arrangement and it is what the owner asked for: a directory -// tree is walked by moving right, and the level you are about to walk into is -// already drawn when you get there. The parent stays on the left so that where -// you are standing is visible without reading the path. +// THE COLUMNS ARE PARENT, HERE, AND THE CHILDREN OF THE ROW UNDER THE CURSOR. The parent +// stays on the left so that where you are standing is visible without reading the path. type folderCols struct { // dir is the directory the middle column lists, absolute and cleaned. dir string @@ -691,14 +684,8 @@ func pathHead(typed string) (string, string) { return head, typed[cut+1:] } -// descend is `→` in the columns: walk into the directory under the cursor. It -// answers false when there is nowhere to go, so the key can fall through to the -// filter box's own right. -// -// A FILE IS NOT SOMEWHERE TO GO. `→` on one does nothing rather than opening -// anything: this browser reads a file into the pane beside the list and never -// runs it, and a key that sometimes navigated and sometimes opened a document -// would be the ambiguous gesture the owner asked us not to build. +// A FILE IS NOT SOMEWHERE TO GO. The right arrow navigates directories; a file +// is previewed beside the list rather than opened by a navigation key. func (f *folderPick) descend() bool { if !f.browsing || !f.cols.here.isDir(f.cols.cursor) { return false @@ -823,21 +810,13 @@ func (f *folderPick) height(width int) int { case !f.open: return 0 case f.browsing: - // A SHEET WITH A PREVIEW ON IT ASKS FOR THE WHOLE ALLOWANCE, because the - // pane is what the extra rows are for: a four-row preview of a - // six-hundred-line file is a pane nobody can read, and the owner asked - // for the reference screenshot's spacious hierarchy rather than a strip. - // A sheet with the preview off follows its own rows, so a folder with - // three things in it is still three rows and not eighteen. + // A sheet with a preview uses the available height so the document remains + // readable. Without a preview, the sheet follows the number of directory rows. rows := f.cols.here.rows() if folderDivide(width, f.pane).pane > 0 { - // A SHEET WITH A PREVIEW ON IT HAS A FLOOR AND NOT A FIXED HEIGHT. It - // used to ask for the whole allowance whatever was in the folder, so a - // directory with four things in it drew four names and fourteen blank - // rows inside a frame — which reads as a broken sheet rather than as a - // spacious one, and is what the owner met. The floor is what the PREVIEW - // needs to be worth reading; past it the middle column's own length is - // the honest height. + // A SHEET WITH A PREVIEW ON IT HAS A FLOOR AND NOT A FIXED HEIGHT. The floor is what + // the PREVIEW needs to be worth reading; past it the middle column's own length is the + // honest height. // // IT IS THE MIDDLE COLUMN'S LENGTH AND NEVER THE PREVIEW'S, deliberately: // the preview changes as the cursor moves and a sheet that resized under @@ -1216,9 +1195,9 @@ func (f *folderPick) hereText(row, room int, pal palette, hovered bool) string { // has CHOSEN is neither of these — it is the persistent mark in the lead, and it // survives moving off the row, which a ground cannot. // -// AND THE BAND IS THE COLUMN'S WIDTH, NEVER THE TERMINAL'S. A stripe across the -// whole frame would light the ancestry and the preview beside a row that has -// nothing to do with either [owner review 2026-09-08 §1]. +// AND THE BAND IS THE COLUMN'S WIDTH, NEVER THE TERMINAL'S. A stripe across the whole +// frame would light the ancestry and the preview beside a row that has nothing to do with +// either. func folderCellBand(painted string, room int, pal palette, cursor, hovered bool) string { cell := folderCell(painted, room) switch { @@ -1356,13 +1335,8 @@ const ( folderUnreadableWord = "this folder cannot be read" ) -// actionRow is the one row on this sheet that ADDS a folder, with what the -// machine knows about that folder dim at the right end of it. -// -// IT IS A ROW AND NOT A LEGEND because navigating and choosing are two different -// acts, and the owner asked for the second to be its own thing rather than a -// meaning `enter` happens to carry. A person who has never pressed `enter` here -// can read what it would do and click it. +// Navigating and choosing are separate actions. The action row makes selection +// visible before a person presses enter and provides a clickable target. func (f *folderPick) actionRow(width int, pal palette, hover int) string { room := width - folderPadCells - 1 if room < 1 { @@ -1747,19 +1721,17 @@ func (f *folderPick) controlLegend(room int) string { if f.pane == folderPaneWide { return rowTail([]rowField{rowSay("esc cancel"), rowSay("alt+o back"), rowSay("↑↓ scroll"), rowSay("←→ slide")}, room) } - // FIVE CLAUSES AND NOT EIGHT. This row used to name every chord the sheet - // owns, which made the one line under the columns a wall of shortcuts that - // read as noise and taught nothing [owner review 2026-09-08 §5]. What is left - // is the four things a person actually reaches for and the way out; the rest - // live in the box's own placeholder, which is on screen whenever the box is - // empty — which is now its resting state — and in the manual. - // THE PREVIEW'S DOOR IS ALWAYS NAMED AND THE WORD FOR IT IS CONTEXTUAL. On a - // narrow frame the pane has been given up for the names (folderpane.go) and - // `alt+o` is the only way to read a file at all; on a wide one it is the way to - // give the file the whole sheet. Either way it is a door a person cannot guess, - // and docs/DESIGN-LANGUAGE.md's rule is that every chord keeps a visible one - // beside it — so it is one clause here rather than a clause that comes and - // goes as the terminal is dragged. + // FIVE CLAUSES AND NOT EIGHT. This row used to name every chord the sheet owns, which + // made the one line under the columns a wall of shortcuts that read as noise and taught + // nothing. What is left is the four things a person actually reaches for and the way out; + // the rest live in the box's own placeholder, which is on screen whenever the box is + // empty — which is now its resting state — and in the manual. THE PREVIEW'S DOOR IS + // ALWAYS NAMED AND THE WORD FOR IT IS CONTEXTUAL. On a narrow frame the pane has been + // given up for the names (folderpane.go) and `alt+o` is the only way to read a file at + // all; on a wide one it is the way to give the file the whole sheet. Either way it is a + // door a person cannot guess, and docs/DESIGN-LANGUAGE.md's rule is that every chord + // keeps a visible one beside it — so it is one clause here rather than a clause that + // comes and goes as the terminal is dragged. door := "alt+o preview" if f.paneWide(room) { door = "alt+o wide" diff --git a/internal/tui3/folderplace.go b/internal/tui3/folderplace.go index 34669f863b..b7a3109aaa 100644 --- a/internal/tui3/folderplace.go +++ b/internal/tui3/folderplace.go @@ -219,14 +219,12 @@ func (a *app) openFolderPick(query string) tea.Cmd { // does both (folderact.go's [app.targetFolderConfirm]). The intent decides // only which tip the gesture retires (notice.go). // -// IT IS THE SAME SHEET AS THE CONVERSATION'S AND NOT A SECOND ONE. Home's own -// answer to "which folder" used to be one line under the box — `alt+p moves -// the next conversation · or type a path` — which named a chord and a gesture -// and drew nothing a person could walk. The owner's word for it was that they -// did not notice it. So the command opens the browser every other surface -// opens, with three differences that all come from the same fact — the -// conversation this is about does not exist yet (folderpick.go's -// [folderPick.forTarget]): +// IT IS THE SAME SHEET AS THE CONVERSATION'S AND NOT A SECOND ONE. Home's own answer to +// "which folder" used to be one line under the box — `alt+p moves the next conversation · +// or type a path` — which named a chord and a gesture and drew nothing a person could +// walk. So the command opens the browser every other surface opens, with three differences +// that all come from the same fact — the conversation this is about does not exist yet +// (folderpick.go's [folderPick.forTarget]): // // - NO FOLDER DOOR IS REQUIRED. A pin is a string on this window; nothing is // referred to any agent, so a session that cannot hold a folder is no reason @@ -366,12 +364,8 @@ func (a *app) openContextPick(query string, folders bool) tea.Cmd { // BOTH DOORS OPEN BROWSING, AT THE SAME DIRECTORY, AND THIS IS THIS // WAVE'S OWN REPAIR. // - // They used to open differently and the owner met the difference: `/attach` - // browsed the columns immediately and `/folder` showed a flat list of - // remembered PLACES, so one command answered "what is here" and the other - // answered "where have you been" — two surfaces behind one sheet. On a - // machine with nothing remembered `/folder` refused outright rather than - // showing a person the folder they were standing in. + // On a machine with nothing remembered `/folder` refused outright rather than showing a + // person the folder they were standing in. // // The list is not gone: it is what the box shows the moment there is a word // in it rather than a path, and ctrl+u clears the path to reach it. So the @@ -996,12 +990,10 @@ func folderFactsOf(dir string) []string { return nil } if !info.IsDir() { - // A FILE'S FACTS ARE THE TWO A CHOOSER CAN ANSWER: how big it is, and when - // it last changed. They ride the same right end of the action row a - // directory's do [owner review 2026-09-08 §4: metadata answers the SELECTED - // item rather than cluttering every row], and neither is drawn where the - // disk had nothing to say — a zero-byte file says its size and a file with - // no modification time says nothing at all [design-law §EMPTINESS]. + // A FILE'S FACTS ARE THE TWO A CHOOSER CAN ANSWER: how big it is, and when it last + // changed. They ride the same right end of the action row a directory's do, and neither + // is drawn where the disk had nothing to say — a zero-byte file says its size and a file + // with no modification time says nothing at all [design-law §EMPTINESS]. // // IT IS THE MODIFICATION TIME AND IT IS NAMED AS ONE. It is not "last // opened": atime is a lie on every filesystem mounted `relatime`, and diff --git a/internal/tui3/followup.go b/internal/tui3/followup.go index 3862192b5b..9c25a6d4fd 100644 --- a/internal/tui3/followup.go +++ b/internal/tui3/followup.go @@ -319,10 +319,9 @@ func (a *app) queueFootOffered() bool { // the block when their turn starts — where the words land in the transcript as // the ordinary sent line they become. // -// THERE IS NO LINE UNDER THE BLOCK, by the owner's call (2026-09-30). It said -// `queued for after this turn · click takes one back · ctrl+enter queues the -// draft`; the arrow says the first, the hover says the second, and the running -// foot says the third, so the sentence was three things already on the frame. +// It said `queued for after this turn · click takes one back · ctrl+enter queues the +// draft`; the arrow says the first, the hover says the second, and the running foot says +// the third, so the sentence was three things already on the frame. func (a *app) followRows(width int) []string { if a.followWaiting() == 0 || width < 5 { return nil diff --git a/internal/tui3/foot.go b/internal/tui3/foot.go index c80f3b8cee..371cff2728 100644 --- a/internal/tui3/foot.go +++ b/internal/tui3/foot.go @@ -23,10 +23,7 @@ import ( // THE MODEL'S OWN CELL — `glm-5.3-flash (deepinfra)` — so the two halves of // "who is answering" read as one word (render.go's [app.modelRiderAt]). // -// THE CONVERSATION'S NAME IS NOT ON IT. It was, from 2026-09-09 until -// 2026-09-17, and the owner ruled it off: a title takes up the room the -// numbers need, and it is already on the tab strip and the breadcrumb bar -// (chattabs.go, title.go). The machine on a `--host` session still leads the +// THE CONVERSATION'S NAME IS NOT ON IT. The machine on a `--host` session still leads the // line — it is the half nobody can reconstruct from anything else on screen. // // THE NUMBERS ARE GROUPED BY THE QUESTION EACH GROUP ANSWERS, three cells of @@ -429,15 +426,13 @@ func (a *app) runStatusNote() tea.Cmd { // // THE LADDER IS [seamLadder], read top to bottom, and it never clips. // -// THREE CELLS ON THIS CLUSTER ARE CONTROLS AND ALL THREE RETURN THEIR COLUMNS: -// the model opens the picker ([app.legendModelPress]), the rung walks one step -// ([app.legendEffortPress]) and the approvals chip walks the gate's wheel one -// stop ([app.legendApprovalPress]). The rider stands between the model and -// the rung — the owner's ruling of 2026-09-17 that the model and its machine -// read as one thing — and is outside the model's span, so a press on `via` -// opens nothing; the rung and the chip are measured past it (seamSpans). A -// room comes through [app.roomSeamIdentity] with the way out where the name -// slot is. +// THREE CELLS ON THIS CLUSTER ARE CONTROLS AND ALL THREE RETURN THEIR COLUMNS: the model +// opens the picker ([app.legendModelPress]), the rung walks one step +// ([app.legendEffortPress]) and the approvals chip walks the gate's wheel one stop +// ([app.legendApprovalPress]). The rider stands between the model and the rung because the +// model and its machine read as one thing. It is outside the model's span, so a press on +// `via` opens nothing; the rung and the chip are measured past it (seamSpans). A room +// comes through [app.roomSeamIdentity] with the way out where the name slot is. func (a *app) seamIdentity(width, room int, tier seamTier) (string, hudSpan, hudSpan, hudSpan) { pieces := a.seamPieces(width) return seamLay(&pieces, room, tier) @@ -502,12 +497,8 @@ type seamPieces struct { } func (a *app) seamPieces(width int) seamPieces { - // THE NAME SLOT IS EMPTY ON A CONVERSATION. The title stood here from - // 2026-09-09 (with the folder standing in until the session had named - // itself) until the owner ruled it off on 2026-09-17: it took the room the - // numbers need, and the tab strip and the breadcrumb bar already say it. - // The slot is still a slot because a room writes its way out into it - // (roomseam.go). + // THE NAME SLOT IS EMPTY ON A CONVERSATION. The slot is still a slot because a room + // writes its way out into it (roomseam.go). // // THE MODEL KEEPS ITS FULL ADDRESS, AND HOW HARD IT IS ASKED TO THINK IS THE // CELL AFTER IT. The level used to be spelled onto the id with a colon — @@ -603,8 +594,7 @@ var seamLadder = []seamTry{ // // THE RIDER IS WRITTEN ONTO THE MODEL — `glm-5.3-flash (deepinfra)` — and the // rung and the gate come after the pair, so the two halves of "who is -// answering" are never separated by a cell about something else (the owner's -// ruling of 2026-09-17). +// answering" are never separated by a cell about something else. func (p seamPieces) lay(try seamTry, room int) (string, hudSpan, hudSpan, hudSpan, bool) { none := hudSpan{} if try.cut && p.name == "" { diff --git a/internal/tui3/footswap.go b/internal/tui3/footswap.go index 766e46f000..ba34e3696b 100644 --- a/internal/tui3/footswap.go +++ b/internal/tui3/footswap.go @@ -15,10 +15,10 @@ import ( // › your sentence // $0.27 · ⟲ saved $0.0038 · 58% cached 66.8k/1.3M · 5% 38 tok/s · ⠹ working · 12s // -// Home's foot was the other way round — its chords on the seam, its hint on the -// last row — and the two boxes a person moves between most looked like two -// different programs. The owner ruled that THE LOWEST LINE IS FOR KEYS on both, -// and that the telemetry goes up onto the seam where the chords were: +// Home's foot was the other way round — its chords on the seam, its hint on the last row — +// and the two boxes a person moves between most looked like two different programs. THE +// LOWEST LINE IS FOR KEYS on both, and that the telemetry goes up onto the seam where the +// chords were: // // ─ glm-5.3-flash (deepinfra):high · ◇ asks ── $0.27 · 58% cached 66.8k/1.3M · 5% ⠹ working · 12s ─ // › your sentence @@ -237,11 +237,7 @@ func (a *app) seamTelemetryLabel(ledger, alive []hudPart) (string, string) { // because it was fitted against the keys and not against the words standing // in for them. // -// AND THE TIP COVERS THE PROJECT WHILE IT IS UP, since 2026-09-24 at the -// owner's word (notice.go's THE CONVERSATION'S TIP): the same right end, the -// same fitting to what the keys leave, with home's bulb before it and a cross -// after it whose columns are recorded here too ([app.chatTipClose]). The -// project is back the moment the tip goes. +// The project is back the moment the tip goes. func (a *app) hintRow(width int) string { a.homeDoor = hudSpan{} a.seamProjectSpan = hudSpan{} diff --git a/internal/tui3/frame.go b/internal/tui3/frame.go index 6cfe302fde..4efe2a98ae 100644 --- a/internal/tui3/frame.go +++ b/internal/tui3/frame.go @@ -10,14 +10,12 @@ import ( // ── THE ONE FRAME ─────────────────────────────────────────────────────────── // -// docs/DESIGN-LANGUAGE.md refused borders — "one continuous surface: zones are -// made of typography, alignment and at most a hairline rule" — and three dim -// rounded boxes shipped anyway, each with a written argument for being the -// exception and each with its own copy of the six pieces: the `/folder` chooser -// (contextmodal.go), the `alt+k` switcher card (hop.go) and the onboarding -// panel (onboarding.go). The owner's ruling of 2026-09-11 made a fourth kind of -// thing framed on purpose — a QUESTION hangs above the box as one object — and -// said the fourth must not be a fourth copy. So there is one frame, this one: +// docs/DESIGN-LANGUAGE.md refused borders — "one continuous surface: zones are made of +// typography, alignment and at most a hairline rule" — and three dim rounded boxes shipped +// anyway, each with a written argument for being the exception and each with its own copy +// of the six pieces: the `/folder` chooser (contextmodal.go), the `alt+k` switcher card +// (hop.go) and the onboarding panel (onboarding.go). A QUESTION hangs above +// the composer as one object and shares the same frame instead of copying it. So there is one frame, this one: // // THE QUESTION, THE SWITCHER CARD AND THE ONBOARDING PANEL ARE ON IT. The // `/folder` chooser is NOT, yet, and it is the one box still carrying its own diff --git a/internal/tui3/framedisk_law_test.go b/internal/tui3/framedisk_law_test.go index b4152b28ca..b0d718c9f6 100644 --- a/internal/tui3/framedisk_law_test.go +++ b/internal/tui3/framedisk_law_test.go @@ -39,7 +39,7 @@ package tui3 // the package function of that name; // - a func-typed FIELD, through whatever function this package assigns to it. // `a.gitProbe = gitHead` is what made `a.gitProbe(dir)` two `git` processes, -// and without this edge the one call that started this lane would not have +// and without this edge the one call that started this test would not have // been on the graph at all. // // WHAT IT DOES NOT WALK, SAID OUT LOUD, because a law whose reach a reader diff --git a/internal/tui3/harness.go b/internal/tui3/harness.go index 5010af9194..b5d2f8c797 100644 --- a/internal/tui3/harness.go +++ b/internal/tui3/harness.go @@ -198,7 +198,7 @@ func (a *app) dropHarnessStep() { // ending is a settle card in the transcript with the outcome on it (taskdone.go). // A note beside that card would be the same news drawn twice. -// designAgent is the slice of *session.Agent this lane needs, asserted rather +// designAgent is the slice of *session.Agent this implementation needs, asserted rather // than added to [Agent] for [taskAgent]'s reason: the harness designer is // OPTIONAL. Every scripted agent in this package's own tests has never heard of // one, and widening the package interface would make a session without a @@ -273,7 +273,7 @@ func (a *app) designEvent(ev session.Event) tea.Cmd { a.askHarnessDesign(ev) case session.EventSubharnessProposal: // CHAT OFFERING A SAVED PROGRAM, and it arrives HERE because it is raised - // on this lane and no other (session's tools_subharness.go calls + // on this implementation and no other (session's tools_subharness.go calls // emitHarness): the turn that asked is parked inside its own batch, so // the question cannot ride the turn's stream the way an approval does. // A surface that only read the turn's events would never see it, which diff --git a/internal/tui3/harness_test.go b/internal/tui3/harness_test.go index f3df86c5db..a976a87292 100644 --- a/internal/tui3/harness_test.go +++ b/internal/tui3/harness_test.go @@ -105,7 +105,7 @@ func TestTheHarnessOfferIsOneRowWithBothAnswers(t *testing.T) { // THE TWO ANSWERS, in the digits every question on this surface takes. // // `enter`, `y`, `esc` and `n` used to be the four keys here, and none of them is -// an answer any more: this lane answers `1` and `2` like every other question on +// an answer any more: this test answers `1` and `2` like every other question on // the block, and `esc` is *later* rather than the no // (docs/design/questions/DESIGN.md's ONE KEY GRAMMAR). func TestTheHarnessOfferAnswersToItsKeys(t *testing.T) { diff --git a/internal/tui3/head.go b/internal/tui3/head.go index 0f6b3fed2c..9d10c558f7 100644 --- a/internal/tui3/head.go +++ b/internal/tui3/head.go @@ -17,15 +17,13 @@ package tui3 // and a blank ([placeHeadRows]) and the body starts one row higher. In a chat // the strip sits between the air row and the rule ([chatHeadRows]). // -// THE STRIP USED TO BE DRAWN ON EVERY PAGE, including places, where it repeated -// the teams rail and home's sessions and offered a jump from a place to one -// chat that is not a journey anyone takes. `chats` on row zero, `alt+k` and -// home's sessions list are the ways between them (owner, 2026-09-25).// -// THE PLACES AND THE STRIP USED TO SHARE ROW ONE AND TAKE TURNS ON IT. A place -// drew its bar there and a conversation drew its strip there, so the words a -// hand was reaching for changed under it on every walk (owner, 2026-09-24). -// Row zero is the places on every page. The strip, when it is drawn, is only -// the chats. +// THE STRIP USED TO BE DRAWN ON EVERY PAGE, including places, where it repeated the teams +// rail and home's sessions and offered a jump from a place to one chat that is not a +// journey anyone takes. `chats` on row zero, `alt+k` and home's sessions list are the ways +// between them.// THE PLACES AND THE STRIP USED TO SHARE ROW ONE AND TAKE TURNS ON IT. A +// place drew its bar there and a conversation drew its strip there, so the words a hand +// was reaching for changed under it on every walk. Row zero is the places on every page. +// The strip, when it is drawn, is only the chats. // // THE TWO FRAMES SHARE ONE HEAD BECAUSE A PERSON WALKS BETWEEN THEM ALL DAY. // The conversation's head used to be two to four rows of its own with no pulse, @@ -34,7 +32,7 @@ package tui3 // 11). One function draws the head for every frame. // // A ROOM WEARS THE WHOLE HEAD TOO, and its trail and facts are the first rows -// under it, where a place's heading is (PLACES-AUDIT.md, lane K). +// under it, where a place's heading is. // headRows is the head, drawn at `width` in `pal`. While a conversation is in // front, `strip` (the frame's [app.tabsRow]) is the row under the air row and diff --git a/internal/tui3/head_test.go b/internal/tui3/head_test.go index d7a5db27de..b56ffcc9ba 100644 --- a/internal/tui3/head_test.go +++ b/internal/tui3/head_test.go @@ -120,7 +120,7 @@ var headFrameSizes = []struct{ w, h int }{{80, 24}, {120, 45}, {180, 45}} // row under them. A place spends four rows and no strip, so its body starts // one row above a conversation's. The room used to lay the trail where the // rule stands -// (PLACES-AUDIT.md, lane K). +// . func TestATaskRoomSpendsThePlacesHeadAboveItsBody(t *testing.T) { room, chat := crumbApp(t), headLab(t) for _, size := range headFrameSizes { @@ -189,7 +189,7 @@ func footOf(rows []string) footEdges { // the status line where a place draws its hint. The chat used to keep a second // blank between the box and the status line, so `esc` from home into a chat // moved the rule and the box up a row and walking back moved them down again -// (PLACES-AUDIT.md, lane K). Walked chat → home → chat at three sizes, and the +// . Walked chat → home → chat at three sizes, and the // rule, the box and the last row never move. Tasks is no longer on the walk: // a place that is not home draws no box (pages.go's [place.box]), so its foot // is its own three rows and [TestEveryPlaceSpendsTheSameHeadAndFoot] holds it diff --git a/internal/tui3/home.go b/internal/tui3/home.go index 54c4c2c17a..117a09163d 100644 --- a/internal/tui3/home.go +++ b/internal/tui3/home.go @@ -3715,7 +3715,7 @@ func (h *homeView) runLabel(text string) string { // memory and it asks the disk nothing, so a command pays what it always paid: // no command this surface answers has a separator inside its own word, which // is exactly the test. Without it a dropped screenshot stood on this row - // wearing `run /Users/…/Screenshot\ 2026-08-31\ at\ 5.png`, a promise enter + // wearing `run /workspace/Screenshot\ 2026-08-31\ at\ 5.png`, a promise enter // could only break. if droppedPathShape(text) { return "" @@ -5492,16 +5492,11 @@ func (a *app) homeHintWords() string { } return "enter starts a new conversation and sends this · ↑ ask here · ↑↑ pick a match · esc clear" case a.home.gridOn() && (line.kind == homeSession || line.kind == homeLedger): - // ONE SENTENCE ON EVERY ROW OF THE GRID. A conversation, an - // automation, a landing, a line of news: each used to say its own thing here - // — `enter opens the place this happened in`, `enter open where it was - // asked · ctrl+e pause` — and the foot changed under the hand on every - // step of the cursor. The owner ruled (2026-09-15) that the rows under - // the moving headings all rest on the resting sentence, so the foot is - // something a person reads once and then stops reading; `enter open` is - // true of every one of them. The rows' own sentences below still serve - // the phone and the filtered list, where there is no grid to be - // consistent across. + // ONE SENTENCE ON EVERY ROW OF THE GRID. A conversation, an automation, a landing, a + // line of news: each used to say its own thing here — `enter opens the place this + // happened in`, `enter open where it was asked · ctrl+e pause` — and the foot changed + // under the hand on every step of the cursor. The rows' own sentences below still serve + // the phone and the filtered list, where there is no grid to be consistent across. case line.kind == homeFold: // The panel's fold is a toggle and the foot says which way it will go; // the words are the ones every fold door on every place uses diff --git a/internal/tui3/home_test.go b/internal/tui3/home_test.go index 1becc57db3..97aaaa4b6f 100644 --- a/internal/tui3/home_test.go +++ b/internal/tui3/home_test.go @@ -162,7 +162,7 @@ func (l *homeLab) app(standing string) *app { // falls back to the package's one shared test home, which every /export // test writes into — so `since you left` in one lab read the files another // test made, and a firing folded under `3 more` only when the whole suite - // ran (a red the Spark found twice and a lone run never could). + // ran (a red the test machine found twice and a lone run never could). a.artifacts = filepath.Join(l.root, "v3", session.ArtifactsIndexName) // THE LEDGER IS THE LAB'S TOO. An empty path is the door's way of saying // "this machine's" (usage_ledger.go's [UsageCache] falls back to @@ -601,10 +601,9 @@ func TestHomePutsASessionThatNeedsYouFirst(t *testing.T) { if !strings.Contains(text, tokens.GlyphNeedsHuman+" Pricing Research") { t.Fatalf("the row does not wear the needs-you mark:\n%s", text) } - // AND WHAT IT IS STOPPED ON IS UNDER THE ROW ITSELF while the row is being - // read — under the pointer or the cursor (owner, 2026-09-17) — not one - // keystroke away in a pane: the `needs you` panel draws the question on the - // line under the title (homepanel_needs.go). + // AND WHAT IT IS STOPPED ON IS UNDER THE ROW ITSELF while the row is being read — under + // the pointer or the cursor — not one keystroke away in a pane: the `needs you` panel + // draws the question on the line under the title (homepanel_needs.go). homeLineOf(t, a, func(l homeLine) bool { return l.cell != nil && l.cell.title == "Pricing Research" }) if under := homeLineBelow(homeText(a), tokens.GlyphNeedsHuman+" Pricing Research", 3); !strings.Contains(under, "can I run: rm -rf build/") { t.Fatalf("the row does not show what it is stopped on under its thread title:\n%s", homeText(a)) @@ -983,10 +982,8 @@ func TestTheRestingBoxKeepsACaretOnTheCellTheFirstLetterLandsOn(t *testing.T) { // still closes home, and every other row's hint still ends with it, which is the // second half of this test. // -// AND THE PROMISE MOVED INTO THE BOX ON 2026-09-17. `type to search or start -// something new` opened this foot until the owner ruled that the one box -// left on a place says what it is for, and the lowest line is for keys -// (footswap.go): the box row is the promise, the foot is the keys. +// AND THE PROMISE MOVED INTO THE BOX ON 2026-09-17. The box says what typing does, and the +// lowest line names keys (footswap.go), so the two do not compete for the same space. func TestHomesRestingFootIsTheDesignsSentence(t *testing.T) { a, _ := homeRestLab(t, 120) width, height := a.size() @@ -1752,18 +1749,14 @@ func TestHomeStatsAFolderOncePerReadingAndNotPerFrame(t *testing.T) { // Every sentence typed at home opens a conversation OF ITS OWN, however many are // already open, and each one is sent its own sentence and nobody else's. // -// THE DEFECT THIS CLOSES, in the owner's own words: "whenever I create a new -// chat, it seems to go into the same chat instead of creating a new one". Home -// closed itself, asked [app.renew] for a conversation, and sent the sentence -// whether or not one came back — so from the eighth conversation onward, where -// the keeper used to refuse another, every new chat typed at home was delivered -// to the conversation that was already on the screen. The same one, every time, -// with the refusal noted underneath it. +// Home closed itself, asked [app.renew] for a conversation, and sent the sentence whether +// or not one came back — so from the eighth conversation onward, where the keeper used to +// refuse another, every new chat typed at home was delivered to the conversation that was +// already on the screen. The same one, every time, with the refusal noted underneath it. // -// THE CAP ITSELF IS GONE (keeper.go, owner's ruling 2026-08-31), so the count -// here deliberately runs well past the eight that used to be the whole of the -// defect: the ninth sentence and the twentieth get conversations of their own -// exactly as the first did. +// THE CAP ITSELF IS GONE (keeper.go 2026-08-31), so the count here deliberately runs well +// past the eight that used to be the whole of the defect: the ninth sentence and the +// twentieth get conversations of their own exactly as the first did. func TestHomeTypingOpensItsOwnConversationEveryTime(t *testing.T) { lab := newHomeLab(t) mine := lab.session("-tmp-alpha", "aaaa000000000001", "one", "/tmp/alpha", time.Now()) @@ -2487,12 +2480,10 @@ func TestHomesBoxWrapsALongDraftInsteadOfTruncatingIt(t *testing.T) { } } -// HOME IS ALWAYS REACHABLE. This pin used to say the opposite — that the door -// was shut and the gesture inert on a machine whose only conversation was this -// one, because a door that opened on nothing should be neither drawn nor bound. -// The owner ruled the other way: being greeted by home and being able to GO -// there are two questions, and an empty home is a designed screen rather than a -// refusal ([app.homeDoorOpen]). So the reversal is deliberate and pinned here. +// HOME IS ALWAYS REACHABLE. This pin used to say the opposite — that the door was shut and +// the gesture inert on a machine whose only conversation was this one, because a door that +// opened on nothing should be neither drawn nor bound. So the reversal is deliberate and +// pinned here. func TestTheDoorIsOpenWithOnlyThisConversation(t *testing.T) { lab := newHomeLab(t) mine := lab.session("-alpha", "aaaa000000000001", "the only one", lab.workspace("alpha"), time.Now()) @@ -3363,7 +3354,7 @@ func TestALetterAlwaysTypesWhateverIsChosen(t *testing.T) { // asked whether this process holds it ([app.homeTrue]), and the key that answers // is a transcript path with its symlinks walked ([convKey]) — a walk of THIS // laptop for a file on the far machine. That walk is not free: on macOS `/home` -// is an automounter's mount point, so each row's `Lstat("/home/santosh")` waited +// is an automounter's mount point, so each lookup of a child directory waited // on autofs, and home over --host cost up to a second per frame with the keys // queued behind it. A hosted key is the cleaned spelling and the disk is never // asked ([app.convKey]); this counts the asking so it cannot come back. diff --git a/internal/tui3/homeat.go b/internal/tui3/homeat.go index 418913803a..2c5de0a78f 100644 --- a/internal/tui3/homeat.go +++ b/internal/tui3/homeat.go @@ -9,13 +9,9 @@ import ( // ── THE `@` LIST ON HOME ───────────────────────────────────────────────────── // -// Home's box is a draft for a conversation that does not exist yet, and until -// 2026-09-22 an `@` typed into it was two letters of a search: the completion -// that every conversation's box has (files.go) was bound to that box alone. The -// owner met it as a bug — the hint on home's own row promised the list — and -// this file is the other binding: the same [completion], synced against home's -// box, drawn as rows of home's column exactly as the slash list is -// (homeslash.go's [homeView.commandLines]), and answered by the same enter. +// Home's box is a draft for a conversation that does not exist yet, and until 2026-09-22 +// an `@` typed into it was two letters of a search: the completion that every +// conversation's box has (files.go) was bound to that box alone. // // WHAT IT WALKS IS WHERE THE NEXT CONVERSATION OPENS ([app.targetWhere]), // because that is the folder the sentence is about; a target moved by `alt+p` diff --git a/internal/tui3/homeband_answer.go b/internal/tui3/homeband_answer.go index 3e19f0143b..d630b511a8 100644 --- a/internal/tui3/homeband_answer.go +++ b/internal/tui3/homeband_answer.go @@ -207,14 +207,13 @@ func answerChips(question session.PresenceQuestion) []answerChip { // in ordinary ink. Whole chips move to following rows when needed; a card never // hides an answer merely because the answers cannot share a row. // -// IT IS THE PANEL'S GRAMMAR ON A CARD (owner ruling 2026-09-11, colour pick C). -// The whole chip used to be amber, on the argument that home's one meaning of -// "waiting on you" is the warn hue — and the result was a card where the words a -// person has to READ were the same colour as the mark that says to read them. -// The amber stays on the marks: home's `?` on the row, the pointer, the pick. -// consent.go's [app.paintOffer] draws the same shape and cannot be borrowed — it -// asks whether the pointer is over the block it belongs to, and there is no -// block here, only a card in a column. +// IT IS THE PANEL'S GRAMMAR ON A CARD. The whole chip used to be amber, on the argument +// that home's one meaning of "waiting on you" is the warn hue — and the result was a card +// where the words a person has to READ were the same colour as the mark that says to read +// them. The amber stays on the marks: home's `?` on the row, the pointer, the pick. +// consent.go's [app.paintOffer] draws the same shape and cannot be borrowed — it asks +// whether the pointer is over the block it belongs to, and there is no block here, only a +// card in a column. func (a *app) answerChipLines(question session.PresenceQuestion, width int, pal palette) []string { chips := answerChips(question) if len(chips) == 0 { diff --git a/internal/tui3/homeband_answer_test.go b/internal/tui3/homeband_answer_test.go index e6bace8207..956632aa06 100644 --- a/internal/tui3/homeband_answer_test.go +++ b/internal/tui3/homeband_answer_test.go @@ -121,11 +121,10 @@ func TestHomeDrawsTheAnswersToAnotherWindowsQuestion(t *testing.T) { t.Fatalf("the card does not offer %q:\n%s", chip, text) } } - // AND ONCE, ON THE ROW, and only while the row is being read. The grid - // draws a question's answers on its `needs you` row under the pointer or - // the cursor (owner, 2026-09-17), never a second time at the foot — and a - // digit answers the top one from anywhere whether or not its chips are on - // the screen (homegrid.go's [app.homeGridAnswer]). + // AND ONCE, ON THE ROW, and only while the row is being read. The grid draws a question's + // answers on its `needs you` row under the pointer or the cursor, never a second time at + // the foot — and a digit answers the top one from anywhere whether or not its chips are + // on the screen (homegrid.go's [app.homeGridAnswer]). if n := strings.Count(text, "3 deny"); n != 1 { t.Fatalf("the chips are drawn %d times with the cursor on their row:\n%s", n, text) } diff --git a/internal/tui3/homeband_devices.go b/internal/tui3/homeband_devices.go index 1ee3771a41..d6a556fefa 100644 --- a/internal/tui3/homeband_devices.go +++ b/internal/tui3/homeband_devices.go @@ -2,7 +2,7 @@ package tui3 // ── THE DEVICES ROW: WHO IS ONLINE, AND A WAY TO BRING THEIR WORK HERE ────── // -// ● This Mac ● spark ○ dumb (offline) +// ● This Mac ● laptop ○ simple (offline) // // The row is a home band. WHO IS ONLINE IS NEVER ASKED: it is read from the // change feed home already follows (machinewatch.go), whose presence set the diff --git a/internal/tui3/homebridge_test.go b/internal/tui3/homebridge_test.go index ec72b179ab..0f7627c7eb 100644 --- a/internal/tui3/homebridge_test.go +++ b/internal/tui3/homebridge_test.go @@ -138,11 +138,9 @@ func TestTheSecondColumnIsTheCardOfTheRowUnderTheCursor(t *testing.T) { } } -// HOME OPENS ON THE CONVERSATION THIS WINDOW HOLDS, VISIBLY SELECTED — the row -// esc drops back into — so the first frame answers "where am I" before a key is -// pressed. `↑` OFF THE TOP ROW STAYS THERE: the field's column has no way up -// onto the tab bar (owner, 2026-09-17: nothing outside the left column is -// walked, and the tabs are reached by a press, `tab` or a chord), where every +// HOME OPENS ON THE CONVERSATION THIS WINDOW HOLDS, VISIBLY SELECTED — the row esc drops +// back into — so the first frame answers "where am I" before a key is pressed. `↑` OFF THE +// TOP ROW STAYS THERE: the field's column has no way up onto the tab bar, where every // other place's `↑` still climbs onto the bar (pages.go's [app.barReach]). func TestHomeOpensOnItsOwnConversationAndUpOffTheTopStaysInTheColumn(t *testing.T) { a, mine := bridgeLab(t) diff --git a/internal/tui3/homecardrhythm.go b/internal/tui3/homecardrhythm.go index 1674ce2c29..458b4c897d 100644 --- a/internal/tui3/homecardrhythm.go +++ b/internal/tui3/homecardrhythm.go @@ -2,13 +2,11 @@ package tui3 // ── THE CARD'S RHYTHM, AND ITS THREE ROLES ────────────────────────────────── // -// The right column of home is a stack of bands (homebands.go), and every one of -// them used to be separated from its neighbour by exactly one blank row. That is -// a rhythm with no information in it: the address under the title, the bill -// under the work and the verbs under the bill all stood the same distance apart, -// so a card of seven bands read as seven facts in a heap rather than as four -// readings of one conversation. The owner met it as "the right side preview — -// make the spacing a bit more wide… it seems small". +// The right column of home is a stack of bands (homebands.go), and every one of them used +// to be separated from its neighbour by exactly one blank row. That is a rhythm with no +// information in it: the address under the title, the bill under the work and the verbs +// under the bill all stood the same distance apart, so a card of seven bands read as seven +// facts in a heap rather than as four readings of one conversation. // // SO THE CARD HAS GROUPS, AND THE GAP IS WHAT SAYS SO. Four readings, in the // order somebody asks them: diff --git a/internal/tui3/homecell.go b/internal/tui3/homecell.go index 5db7f140e7..0e7e42c1af 100644 --- a/internal/tui3/homecell.go +++ b/internal/tui3/homecell.go @@ -307,11 +307,10 @@ func (h *homeView) marksPanel(at int) bool { // homeCellLeadBlank is the lead of a row that wears no mark. var homeCellLeadBlank = strings.Repeat(" ", homeGridLead) -// homeDescLeadCells is what a note in the description column stands in, and it -// is ONE CELL WIDER THAN A ROW'S LEAD so the mark and the first letter of the -// sentence it leads are not touching (owner, 2026-09-15). Every note takes it, -// marked or not, because notes are read down the column against each other -// rather than against the rows in the column beside them. +// homeDescLeadCells is what a note in the description column stands in, and it is ONE CELL +// WIDER THAN A ROW'S LEAD so the mark and the first letter of the sentence it leads are +// not touching. Every note takes it, marked or not, because notes are read down the column +// against each other rather than against the rows in the column beside them. const homeDescLeadCells = homeGridLead + 1 var homeDescLeadBlank = strings.Repeat(" ", homeDescLeadCells) @@ -542,11 +541,7 @@ func (a *app) homeCellLead(cell *homeCell, at int, pal palette) string { if spin := a.homeSpinCell(at); spin != "" && cell.mark != cellMarkNeeds { return pal.accent(spin) + " " } - // THE MARK LEADS THE ROW, ALWAYS. It used to move beside the question on a - // frame whose description column drew the question permanently (owner, - // 2026-09-15); the question is drawn only under the pointer or the cursor - // now, and the owner asked (2026-09-17) that the `?` always show — so it - // stands beside the title, where it is on every frame. + // THE MARK LEADS THE ROW, ALWAYS. switch cell.mark { case cellMarkNeeds: return pal.warn(pal.glyph(tokens.GNeedsHuman)) + " " @@ -563,12 +558,10 @@ func (a *app) homeCellLead(cell *homeCell, at int, pal palette) string { // homeCellBody is a row after its lead: the title, a note in the title's // shadow, and the facts at the right margin. // -// THE AGE OUTRANKS THE TAIL OF A TITLE (owner, 2026-09-10: `Generate and Display -// First 200 Primes, Sleep, Then Prin…` drew with no age beside rows that had -// one). The note gives way first, then the tag, then the title is cut — and the -// right-hand word, the age or the door word, is the last thing to go: only where -// the title would keep fewer than [homeCellTitleFloor] cells beside it, and a -// held word not even then. +// THE AGE OUTRANKS THE TAIL OF A TITLE. The note gives way first, then the tag, then the +// title is cut — and the right-hand word, the age or the door word, is the last thing to +// go: only where the title would keep fewer than [homeCellTitleFloor] cells beside it, and +// a held word not even then. // // A PROGRAM'S BADGE IS MEASURED AS PART OF THE TITLE AND PAID FOR OUT OF IT // ([homeCellWears]), so the note, the tag and the age give way to it exactly as @@ -649,7 +642,7 @@ func homeCellBody(cell *homeCell, width int, pal palette, lit bool) string { } // giveWay is the facts in the order a narrow row sheds them. A cell that -// KEEPS ITS NOTE (a chat on another machine: `running on studio` is the point +// KEEPS ITS NOTE (a chat on another machine: `running on desktop` is the point // of the row) sheds the tag alone and lets the title be cut, for as long as the // note still fits beside a title of [homeCellTitleFloor] cells; below that the // note goes as it always did. @@ -757,13 +750,12 @@ func homeCellWidth(title string, pad int, note, tag, right string) int { // on the line of the row whose `enter` raised it, and nil where there is no // question or its row is not in the field. // -// IT IS THE QUESTION BLOCK'S OWN CARD ([app.homeAskRows]) and not a second -// drawing of the same facts, so a person who has learnt one question on this -// surface has learnt this one. Until this column existed the grid had nowhere to -// put it: the card belongs to the detail column beside the typed search, which -// is not up at rest, so a raised question left only its one-line foot version — -// appended to the resting sentence, where it read as a run-on and was missed -// (owner, 2026-09-15). +// IT IS THE QUESTION BLOCK'S OWN CARD ([app.homeAskRows]) and not a second drawing of the +// same facts, so a person who has learnt one question on this surface has learnt this one. +// Until this column existed the grid had nowhere to put it: the card belongs to the detail +// column beside the typed search, which is not up at rest, so a raised question left only +// its one-line foot version — appended to the resting sentence, where it read as a run-on +// and was missed. // // IT IS PULLED UP RATHER THAN CUT where the card is taller than the room under // its row. A decision with its last answer off the bottom of the screen is worse diff --git a/internal/tui3/homedraft.go b/internal/tui3/homedraft.go index f79056c6ae..36c63fc7c1 100644 --- a/internal/tui3/homedraft.go +++ b/internal/tui3/homedraft.go @@ -40,8 +40,6 @@ import ( // which is what closes the disagreement. `alt+p` and `/model` pin it, and a pin // is a decision a person made. // -// ── OWNER RULING: WHAT PERSISTS AND WHAT IS SPENT ─────────────────────────── -// // BOTH PINS SURVIVE `esc` AND A REOPEN OF HOME. They are the session's, not the // screen's: "let me set the model before I start" is worth nothing if walking // into a conversation and back out forgets it. @@ -129,12 +127,9 @@ func (a *app) targetModelPinned() bool { // two of them did nothing whatever anybody typed ([app.openTargetPicker] arms // the fold now, and [targetDraft.levels] holds the rung). // -// `enter choose` and not `enter switch`, because nothing switches here: a choice -// made on this list is a pin on the NEXT conversation ([app.pinTargetModel]). The -// picker's own middle says `enter switch`, so the verb is swapped and home's own -// ending put back on. It said `use it` until the owner asked for one verb across -// the levels — every other row of this same fold already said `choose`, so `use -// it` was a second word for one gesture on one rung of it. +// `enter choose` and not `enter switch`, because nothing switches here: a choice made on +// this list is a pin on the NEXT conversation ([app.pinTargetModel]). The picker's own +// middle says `enter switch`, so the verb is swapped and home's own ending put back on. func (a *app) targetPickFoot() string { before, enter, after := a.target.pick.keysParts() // `choose` AND NOT `switch`, because nothing switches here: a choice made on @@ -494,13 +489,12 @@ func (a *app) pinTargetModel(id string) { if a.homeCreditWarning != "" { a.askCredits(credits.PaidSwitch) } - // NO NOTE. This used to say `model · <name> · for the next conversation you - // start here` on the line under the box, and the line it was answering — - // "did that change the conversation behind home?" — is answered better by the - // SEAM, which carries the pinned model beside the folder and carries it for as - // long as the pin lasts rather than until the next note replaces it. A - // sentence that repeats what is already on the screen is a sentence that costs - // the row something else could have used (the owner's ruling). + // NO NOTE. This used to say `model · <name> · for the next conversation you start here` + // on the line under the box, and the line it was answering — "did that change the + // conversation behind home?" — is answered better by the SEAM, which carries the pinned + // model beside the folder and carries it for as long as the pin lasts rather than until + // the next note replaces it. A sentence that repeats what is already on the screen is a + // sentence that costs the row something else could have used. a.touch() } diff --git a/internal/tui3/homeexchange.go b/internal/tui3/homeexchange.go index 19c7ae3c89..e6fb59e8bb 100644 --- a/internal/tui3/homeexchange.go +++ b/internal/tui3/homeexchange.go @@ -1676,7 +1676,7 @@ func (a *app) exchangeEnter(ex *homeExchange) tea.Cmd { // THE SIGNAL HAS TO EXIST BEFORE THE ANSWER DOES. A follow-up typed into a // settled exchange used to draw the sentence and then nothing at all until the // first token arrived seconds later — which is a person pressing enter and -// watching a still screen, the exact complaint this lane exists to answer. The +// watching a still screen, the exact complaint this implementation exists to answer. The // state word, the clock and the strip all hang off these three fields, so they // are set the moment the words leave the box. func (ex *homeExchange) startTurn(now time.Time) { diff --git a/internal/tui3/homefate_test.go b/internal/tui3/homefate_test.go index 5c3d6d00ae..d7137aaac7 100644 --- a/internal/tui3/homefate_test.go +++ b/internal/tui3/homefate_test.go @@ -97,10 +97,8 @@ func TestTheFateReadsTheArgumentWhereItChangesTheAnswer(t *testing.T) { // ── /project: the pin, and the browser behind it ──────────────────────────── -// BARE /project OPENS THE ONE BROWSER, AIMED AT THE TARGET, and a folder -// confirmed there PINS THE NEXT CONVERSATION'S FOLDER rather than moving the -// conversation behind home. Home comes back under it with the rule already -// saying the new folder, which is the whole of what the owner asked to see. +// BARE /project OPENS THE ONE BROWSER, AIMED AT THE TARGET, and a folder confirmed there +// PINS THE NEXT CONVERSATION'S FOLDER rather than moving the conversation behind home. func TestProjectAtHomeBrowsesForTheTargetAndPinsIt(t *testing.T) { a, _, root := mixedLab(t) runCmd(a.openHome()) diff --git a/internal/tui3/homegrid.go b/internal/tui3/homegrid.go index ed101a64a3..3c8cf68bd9 100644 --- a/internal/tui3/homegrid.go +++ b/internal/tui3/homegrid.go @@ -165,13 +165,11 @@ type homePanelSlot struct { // field (panels with rows) recent · needs · running · left · next // rail (pinned, then quiet) projects · spend · the quiet ones in the same rank // -// The keep column is the order a short frame takes rows away in and a tall one -// hands them out in, and rest and most are each panel's natural height and its -// growth budget (owner, 2026-09-10: a fifty-five-row terminal was two short -// columns over thirty rows of air). Spend's budget is its rest: it never grows. -// The head column is where a press on a heading goes. The conversation list -// has no heading; the projects heading opens nothing. The explainer is the dim clause a -// heading may carry after its word — see [homePanelSlot.explainer]. +// The keep column is the order a short frame takes rows away in and a tall one hands them +// out in, and rest and most are each panel's natural height and its growth budget. Spend's +// budget is its rest: it never grows. The head column is where a press on a heading goes. +// The conversation list has no heading; the projects heading opens nothing. The explainer +// is the dim clause a heading may carry after its word — see [homePanelSlot.explainer]. var homePanelOrder = []homePanelSlot{ {panel: sessionsPanel{homePanelBase{panelSessions}}, word: sessionsWord, keep: 7, least: 4, rest: homeSessionsLimit, most: homeSessionsLimit, place: pageTasks, head: pageTasks}, {panel: recentPanel{homePanelBase{panelRecent}}, keep: 5, least: 3, rest: tabsCap + homeClosedLimit, most: tabsCap + homeClosedLimit}, @@ -399,11 +397,9 @@ type homePanelGroup struct { // at is where the group's rows begin in [homePanelRows.lines]; everything // before it is the panel's own. at int - // word is the group's name — the whole of its line, and the word the - // panel's fold uses instead of `more` while the group is shut. A group line - // carries no count and no clause: the rows are under it, and the fold counts - // what it hides (owner, 2026-09-15; it used to say `to check · 8` with - // `finished, nobody has checked it` at its right). + // word is the group's name — the whole of its line, and the word the panel's fold uses + // instead of `more` while the group is shut. A group line carries no count and no clause: + // the rows are under it, and the fold counts what it hides. word string } @@ -486,12 +482,11 @@ type homeCell struct { // held row grows into under the cursor ([app.homeCellDoor]). hold bool door string - // thread is the conversation the row belongs to, spelled as `threads` - // spells it, and it heads the row's description as its own title line — - // `thread: <name>`, then a blank line, then [sub] (owner, 2026-09-17). It - // is drawn wherever the description is: in the description column, or - // under the row on a frame without one, where the row grows three lines - // rather than one ([homeCell.grownLines]). + // thread is the conversation the row belongs to, spelled as `threads` spells it, and it + // heads the row's description as its own title line — `thread: <name>`, then a blank + // line, then [sub]. It is drawn wherever the description is: in the description column, + // or under the row on a frame without one, where the row grows three lines rather than + // one ([homeCell.grownLines]). thread string // sub is the line under the row, and subRight what that line carries at // its right — the answers a key sends. @@ -922,10 +917,10 @@ func homeGridLayout(in *homeGridInput, cols, width, room int) [][]*homeGridPanel // homeDescCol is the column the selected row's description stands in, and // [homeNoLine] where this frame has no room for one. // -// IT IS THE MIDDLE COLUMN AND ONLY EXISTS AT THREE (owner, 2026-09-15). Two -// columns are the field and the rail with nothing between them, and one column -// is the whole screen read top to bottom — so at both of those a row keeps its -// description under itself, exactly as every row did before this column existed. +// IT IS THE MIDDLE COLUMN AND ONLY EXISTS AT THREE. Two columns are the field and the rail +// with nothing between them, and one column is the whole screen read top to bottom — so at +// both of those a row keeps its description under itself, exactly as every row did before +// this column existed. func homeDescCol(cols int) int { if !homeDescOn(cols) { return homeNoLine @@ -1089,12 +1084,11 @@ func (p homeGridPanel) lines() []homeLine { return out } -// fold is the panel's last line, and IT IS A TOGGLE (owner, 2026-09-15). Shut, -// it is `N more`, counting everything the panel is not showing — the rows past -// its budget, the rows the squeeze took, and the landings `needs you` aged out -// — and enter opens the panel: its cap is lifted, the other panels squeeze to -// their floors (law 5), and it takes the column. Open, it is `N fewer`, and -// enter shuts it again. +// fold is the panel's last line, and IT IS A TOGGLE. Shut, it is `N more`, counting +// everything the panel is not showing — the rows past its budget, the rows the squeeze +// took, and the landings `needs you` aged out — and enter opens the panel: its cap is +// lifted, the other panels squeeze to their floors (law 5), and it takes the column. Open, +// it is `N fewer`, and enter shuts it again. // // IT WEARS NO MARK. The places' fold doors are `▸ 11 more` and `▾ 11 fewer` // ([foldDoor]); this one is the words alone, because the grid has two marks and @@ -1250,16 +1244,12 @@ func (h *homeView) rowOf(at int) int { return row } -// THE ARROWS STAY IN THEIR COLUMN. `←` and `→` used to cross into the -// neighbouring column, onto the row nearest the one they left (DESIGN §6 ruling -// 6, "columns win the arrow"), and the foot named `ctrl+o open folder` on every -// field row because the strip was then not one arrow away. The owner ruled -// (2026-09-17) that nothing outside the left column is to be walked at all: the -// rail is read, not stood on — `projects` and `spend` have no stops — and a -// person on a field row who pressed `→` landed on a project and then opened its -// strip under the row they had just left. So the two arrows are the router's -// again on every column, as they are at one column: `→` opens the row's verbs -// and `←` closes them, and the foot is the resting sentence alone. +// THE ARROWS STAY IN THEIR COLUMN. `←` and `→` used to cross into the neighbouring column, +// onto the row nearest the one they left (DESIGN §6 ruling 6, "columns win the arrow"), +// and the foot named `ctrl+o open folder` on every field row because the strip was then +// not one arrow away. So the two arrows are the router's again on every column, as they +// are at one column: `→` opens the row's verbs and `←` closes them, and the foot is the +// resting sentence alone. // homeRowFolder is the folder `ctrl+o` opens for a row, and "" for a row that // belongs to no folder — a spend row, a fold. @@ -1504,11 +1494,9 @@ func (a *app) homeRowOffer(line homeLine) string { // this window has already answered it, and the row's own door word — `enter`, // `enter on standing` — on the row the cursor is standing on. // -// THE DOOR WORD IS SAID ONCE, UNDER THE CURSOR. It is a key legend, and a legend -// is for the key a person is about to press; drawn on every question at once it -// was a column of `enter`s that told nobody anything (owner, 2026-09-16, seen on -// a narrow frame where the second line is under every question rather than -// beside the cursor's). The description column already drew it only for the +// THE DOOR WORD IS SAID ONCE, UNDER THE CURSOR. It is a key legend, and a legend is for +// the key a person is about to press; drawn on every question at once it was a column of +// `enter`s that told nobody anything. The description column already drew it only for the // selected row ([app.homeDescNote]); this makes the second-line shape agree. func (a *app) homeRowAnswers(line homeLine, at int) string { // The option menu owns the letters while open; normal answer hints would diff --git a/internal/tui3/homegrid_test.go b/internal/tui3/homegrid_test.go index 6e5550ae0f..7053f5a719 100644 --- a/internal/tui3/homegrid_test.go +++ b/internal/tui3/homegrid_test.go @@ -134,10 +134,9 @@ func TestTheRailKeepsTheQuietPanelsAnExtraRowBelowThePinnedPair(t *testing.T) { // flush with the right edge at every width it exists at, and no panel is ever // drawn between them. // -// THE FIELD NEVER SPILLS SIDEWAYS (owner, 2026-09-15). What will not fit in one -// column folds, the way it always has at the widths with no second column, so -// the middle means one thing at every size instead of being a description -// sometimes and a panel other times. +// THE FIELD NEVER SPILLS SIDEWAYS. What will not fit in one column folds, the way it +// always has at the widths with no second column, so the middle means one thing at every +// size instead of being a description sometimes and a panel other times. func TestAtOneEightyTheFieldIsOneColumnAndTheMiddleIsNoPanels(t *testing.T) { a := newSwitchLab(t).open(180, 45) frame := homeText(a) @@ -222,12 +221,9 @@ func TestTheDescriptionColumnCarriesTheSelectedRowsOwnSentence(t *testing.T) { } } -// `needs you` DRAWS ITS QUESTION IN THE DESCRIPTION COLUMN ONLY WHILE ITS ROW IS -// BEING READ — under the pointer, or under the cursor — on its own row's line, -// and once; the `?` stays beside the title on every frame. It used to stand in -// the column whether or not the row was selected (owner, 2026-09-15), and the -// owner reversed that on 2026-09-17: the mark always shows, the description -// only under the mouse. +// `needs you` DRAWS ITS QUESTION IN THE DESCRIPTION COLUMN ONLY WHILE ITS ROW IS BEING +// READ — under the pointer, or under the cursor — on its own row's line, and once; the `?` +// stays beside the title on every frame. func TestTheNeedsYouQuestionIsInTheColumnOnlyWhileItsRowIsRead(t *testing.T) { lab := newAnswerLab(t, consentQuestion(7, "needs your ok to run bash"), time.Now()) a := lab.a @@ -280,11 +276,10 @@ func TestTheNeedsYouQuestionIsInTheColumnOnlyWhileItsRowIsRead(t *testing.T) { // A QUESTION HOME RAISES IS DRAWN IN THE DESCRIPTION COLUMN, beside the row // whose `enter` raised it — and the foot does not say it a second time. // -// Until the column existed the grid had nowhere to put the card: it belongs to -// the detail column beside the typed search, which is not up at rest, so a -// raised question left only its one-line foot version appended to the resting -// sentence. A person pressing enter saw the bottom of the screen change and read -// it as noise (owner, 2026-09-15). +// Until the column existed the grid had nowhere to put the card: it belongs to the detail +// column beside the typed search, which is not up at rest, so a raised question left only +// its one-line foot version appended to the resting sentence. A person pressing enter saw +// the bottom of the screen change and read it as noise. func TestARaisedQuestionIsDrawnInTheDescriptionColumnAndNotOnTheFoot(t *testing.T) { lab := newAnswerLab(t, consentQuestion(7, "needs your ok to run bash"), time.Now()) a := lab.a @@ -316,11 +311,7 @@ func TestARaisedQuestionIsDrawnInTheDescriptionColumnAndNotOnTheFoot(t *testing. } } -// THE `?` LEADS THE ROW, ALWAYS, and the question in the description column -// wears none. The mark used to move beside the question on a frame whose column -// drew the question permanently (owner, 2026-09-15); the question is drawn only -// while the row is being read now, and the owner asked (2026-09-17) that the -// mark always show — so it stands beside the title on every frame. +// THE `?` LEADS THE ROW, ALWAYS, and the question in the description column wears none. func TestTheNeedsMarkLeadsTheRowAndNotTheQuestion(t *testing.T) { lab := newAnswerLab(t, consentQuestion(7, "needs your ok to run bash"), time.Now()) a := lab.a @@ -361,12 +352,10 @@ func TestTheNeedsMarkLeadsTheRowAndNotTheQuestion(t *testing.T) { } } -// AND A FRAME TOO SHORT FOR THE CARD FALLS BACK TO THE FOOT rather than drawing -// a cut one. A card with its closing edge, its keys and usually an answer off -// the bottom of the screen is a decision a person cannot answer; the one-line -// foot version exists for exactly the frames with no room for a card, and this -// is one of them (owner, 2026-09-15: "what happens if we run out of vertical -// space?"). +// AND A FRAME TOO SHORT FOR THE CARD FALLS BACK TO THE FOOT rather than drawing a cut one. +// A card with its closing edge, its keys and usually an answer off the bottom of the +// screen is a decision a person cannot answer; the one-line foot version exists for +// exactly the frames with no room for a card, and this is one of them. func TestAFrameTooShortForTheQuestionCardSaysItOnTheFootInstead(t *testing.T) { lab := newAnswerLab(t, consentQuestion(7, "needs your ok to run bash"), time.Now()) a := lab.a @@ -764,10 +753,9 @@ func TestASinceYouLeftRowRestsOnTheOneFootAndOpensItsConversationsFolder(t *test } } -// THE ARROWS WALK THE FIELD AND NEVER LEAVE IT (owner, 2026-09-17): `↓` is -// the next row of the column, `→` is the row's own strip and not the rail, -// `←` closes it, and `↑` off the top row stays there rather than climbing onto -// the tab bar. +// THE ARROWS WALK THE FIELD AND NEVER LEAVE IT: `↓` is the next row of the column, `→` is +// the row's own strip and not the rail, `←` closes it, and `↑` off the top row stays there +// rather than climbing onto the tab bar. func TestTheArrowsWalkTheFieldAndNeverLeaveIt(t *testing.T) { a := newSwitchLab(t).open(120, 45) if got := focusedTitle(a); got != "Porting the Resume Picker" { @@ -829,11 +817,11 @@ func TestALongTitleIsCutBeforeItsAge(t *testing.T) { } } -// A PANEL'S FOLD IS A TOGGLE (owner, 2026-09-15). `66 more` under `where you -// were` is a stop; enter on it opens the panel — every conversation the column -// can hold, the other panels squeezed to their floors — and the fold now reads -// `N fewer`, with the cursor still on it. Enter again shuts it. It used to be -// `66 more · type to find one`, which could not be stood on at all. +// A PANEL'S FOLD IS A TOGGLE. `66 more` under `where you were` is a stop; enter on it +// opens the panel — every conversation the column can hold, the other panels squeezed to +// their floors — and the fold now reads `N fewer`, with the cursor still on it. Enter +// again shuts it. It used to be `66 more · type to find one`, which could not be stood on +// at all. func TestEnterOnAFoldOpensThePanelAndAgainShutsIt(t *testing.T) { a, _ := homeTabsFixture(t) a.height = 14 diff --git a/internal/tui3/homeneedsgroups_test.go b/internal/tui3/homeneedsgroups_test.go index 9b233d9ce4..aa10e5f44a 100644 --- a/internal/tui3/homeneedsgroups_test.go +++ b/internal/tui3/homeneedsgroups_test.go @@ -91,9 +91,8 @@ func TestTheAnswerChipsAreOnOneRowOfTheFrame(t *testing.T) { Question: consentQuestionAt(9, "needs your ok to run write", l.now.Add(-5*time.Minute))}) l.landed("4", "fix the flaky sieve", 30*time.Minute) a := l.open() - // AT REST NO ROW DRAWS ITS SENTENCE, so no chips are on the frame at all - // (owner, 2026-09-17: the description shows under the pointer or the - // cursor); the digit still answers the top question ([app.homeAnswerAt]). + // AT REST NO ROW DRAWS ITS SENTENCE, so no chips are on the frame at all; the digit still + // answers the top question ([app.homeAnswerAt]). frame := homeText(a) if got := strings.Count(frame, "1 allow once") + strings.Count(frame, needsYesKey+" accept"); got != 0 { t.Fatalf("a row nobody is reading drew its answers:\n%s", frame) @@ -127,12 +126,8 @@ func TestTheAnswerChipsAreOnOneRowOfTheFrame(t *testing.T) { } } -// NO QUESTION SAYS `enter`. On a two-column frame every question draws its -// second line, and every one of them used to end in `enter` — a column of -// legends for a key only one row is about to take (owner, 2026-09-16); then -// only the cursor's row said it, and the owner ruled (2026-09-17) that the -// word beside a description was noise wherever it stood. The answering row -// keeps its chips; every other question says nothing at its right. +// NO QUESTION SAYS `enter`. The answering row keeps its chips; every other question says +// nothing at its right. func TestNoQuestionSaysEnter(t *testing.T) { l := newLiveLab(t) l.live("-beta", "bbbb000000000001", session.SessionPresence{State: session.PresenceWaiting, diff --git a/internal/tui3/homepanel_left.go b/internal/tui3/homepanel_left.go index 54788e4bc4..667eb59259 100644 --- a/internal/tui3/homepanel_left.go +++ b/internal/tui3/homepanel_left.go @@ -50,10 +50,9 @@ func (leftPanel) rows(in *homeGridInput) homePanelRows { // task's and a file's doors are the row's own and not a place's. // // THE MARGIN IS WHEN IT HAPPENED. It used to be a task's cost on one row and a -// conversation's name on the next — two unrelated facts down one edge of one -// panel — and both are the row's description now, drawn under the cursor -// ([switcherRow.note]); the edge reads `3h`, `1h`, like every row of the field -// (owner, 2026-09-15). +// conversation's name on the next — two unrelated facts down one edge of one panel — and +// both are the row's description now, drawn under the cursor ([switcherRow.note]); the +// edge reads `3h`, `1h`, like every row of the field. // // A PROGRAM'S LANDING WEARS ITS BADGE BETWEEN ITS NAME AND WHAT IT CAME TO, so // the cell cuts the outcome before the badge and pays for the badge out of the diff --git a/internal/tui3/homepanel_live_test.go b/internal/tui3/homepanel_live_test.go index c814a17de4..c116a53b98 100644 --- a/internal/tui3/homepanel_live_test.go +++ b/internal/tui3/homepanel_live_test.go @@ -109,8 +109,8 @@ func TestNeedsYouOrdersTheWaitsAndDrawsAnswersOnTheTopRowOnly(t *testing.T) { if rows[1].sub != "needs your ok to run bash" || rows[1].right != "3h" { t.Fatalf("the top row is not the gate's own sentence with its age: %+v", rows[0]) } - // THE SENTENCE AND THE CHIPS ARE DRAWN UNDER THE ROW BEING READ, and at - // rest a row is its mark, its title and its wait (owner, 2026-09-17). + // THE SENTENCE AND THE CHIPS ARE DRAWN UNDER THE ROW BEING READ, and at rest a row is its + // mark, its title and its wait. frame := homeText(a) if under := homeLineAfter(frame, "Pricing Site"); strings.Contains(under, "needs your ok") || strings.Contains(under, "allow once") { t.Fatalf("the top row draws its sentence with nobody reading it:\n%s", frame) @@ -144,10 +144,9 @@ func TestNeedsYouCarriesATaskWaitingOnYourCall(t *testing.T) { FilesChanged: 3}) a := l.open() rows := homeAttentionRows(a) - // THE MARGIN IS WHEN IT LANDED AND NOTHING ELSE; its description leads with - // the thread it belongs to, spelled as `threads` spells it (owner, - // 2026-09-17), then the files it wrote (owner, 2026-09-15: the right margin - // of every field row is a time). It used to read `3 files · 30m`. + // THE MARGIN IS WHEN IT LANDED AND NOTHING ELSE; its description leads with the thread it + // belongs to, spelled as `threads` spells it, then the files it wrote. It used to read `3 + // files · 30m`. if len(rows) != 1 || rows[0].title != "fix the flaky sieve" || rows[0].right != "30m" || rows[0].thread != "Prime Sieve" || !strings.HasPrefix(rows[0].sub, "3 files · ") { t.Fatalf("the task's call is not a one-line row of needs you with its files in its description: %+v", rows) } @@ -441,9 +440,9 @@ func TestSinceYouLeftNamesEachLandedTaskAndFile(t *testing.T) { t.Fatalf("line %d is %q, want %q", i, rows[i].title, title) } } - // THE MARGIN IS WHEN EACH HAPPENED, and the conversation a file was made in - // and what a task cost are the rows' descriptions (owner, 2026-09-15). They - // used to be the margins — a name on one row, money on the next. + // THE MARGIN IS WHEN EACH HAPPENED, and the conversation a file was made in and what a + // task cost are the rows' descriptions. They used to be the margins — a name on one row, + // money on the next. if rows[0].right != "1h" || rows[1].right != "2h" || rows[2].right != "3h" { t.Fatalf("the right margins are not when each happened: %+v", rows) } diff --git a/internal/tui3/homepanel_machines.go b/internal/tui3/homepanel_machines.go index 2468468aa5..9a0870528c 100644 --- a/internal/tui3/homepanel_machines.go +++ b/internal/tui3/homepanel_machines.go @@ -14,7 +14,7 @@ import ( // // A chat somebody left running on another computer is a row like any other, in // the place they look for their chats. Its words come whole from [chatlist] -// (`running on studio`, `studio offline`, `2 turns from studio: merge / discard`), +// (`running on desktop`, `desktop offline`, `2 turns from desktop: merge / discard`), // so this screen and `codeaf cell list --all` never spell them twice. // // THE EMPTINESS LAW DECIDES WHAT IS SAID. A chat this machine holds says @@ -113,7 +113,7 @@ func (m machineReading) into(in *homeGridInput, own []homeLine) homePanelRows { // lines are the rows to draw: none of the kind that only this machine can hold, // and none for a chat this machine already lists unless another machine holds it -// live. That one is drawn WITH its door (`running on studio`, enter takes it), +// live. That one is drawn WITH its door (`running on desktop`, enter takes it), // because the local row of a chat taken elsewhere is a stale window, and the way // back to it is the same take the cold path runs. func (m machineReading) lines(in *homeGridInput, own []homeLine) []homeLine { diff --git a/internal/tui3/homepanel_needs.go b/internal/tui3/homepanel_needs.go index 7a977415cb..80f9f3ca46 100644 --- a/internal/tui3/homepanel_needs.go +++ b/internal/tui3/homepanel_needs.go @@ -23,12 +23,7 @@ type needsPanel struct{ homePanelBase } // question with more draws the first ones and stops; every answer is still one // enter away, and the row does not say so. // -// NO ROW OF THIS PANEL NAMES THE ENTER KEY. A question row used to say `enter` -// at the right of its sentence when its answers were not drawn, and a watch -// with no conversation behind it `enter on standing`; the owner ruled -// (2026-09-17) that the word beside every description was noise — the foot -// under the grid already says `enter open` once for every row, and a row that -// can be stood on is a row enter does something with. +// NO ROW OF THIS PANEL NAMES THE ENTER KEY. const needsAnswersCap = 3 // needsItem is one row before the panel orders it: when it was asked, and the @@ -72,14 +67,9 @@ func (needsPanel) rows(in *homeGridInput) homePanelRows { lines = append(lines, item.line) } out := homePanelCut(in, panelNeeds, lines) - // NEITHER THE HEADING NOR THE GROUP LINE CARRIES A COUNT. The heading used - // to count the live questions (`needs you · 2`) and the group line the - // landings (`to check · 8`); the owner cut both on 2026-09-15, because the - // rows are right there under the words and a figure beside them is a second - // thing to read that says nothing the rows do not. The fold still counts what - // it hides (`3 unread`, `N more`), which is the one place a count stands for - // rows that are NOT on the screen. The aged-out landings are counted on the - // same fold ([needsFresh]). + // NEITHER THE HEADING NOR THE GROUP LINE CARRIES A COUNT. The fold still counts what it + // hides (`3 unread`, `N more`), which is the one place a count stands for rows that are + // NOT on the screen. The aged-out landings are counted on the same fold ([needsFresh]). out.older = in.callsOlder if len(calls) > 0 { out.group = &homePanelGroup{at: len(asked), word: needsCheckWord} @@ -134,18 +124,17 @@ func needsAsked(in *homeGridInput) []needsItem { needsLandingsSpeakFor(row.session, needsCallTitlesOn(in, row.session.ID))) { continue } - // THE MARK ALWAYS SHOWS AND THE SENTENCE SHOWS UNDER THE POINTER OR THE - // CURSOR (owner, 2026-09-17): a row is its title and its wait at rest, - // like every row of the field, and grows the question when it is read. + // THE MARK ALWAYS SHOWS AND THE SENTENCE SHOWS UNDER THE POINTER OR THE CURSOR: a row is + // its title and its wait at rest, like every row of the field, and grows the question + // when it is read. cell := &homeCell{panel: panelNeeds, mark: cellMarkNeeds, title: row.title, grows: true} homeLiveMargin(cell, row, sinceAt(row.at, in.now)) item := needsItem{asked: row.at} switch row.kind { case switcherConversation: - // THE DESCRIPTION IS HEADED BY THE THREAD (owner, 2026-09-17), which - // for a stopped conversation is the row's own title — the label - // `threads` draws for it — said once more as the description's - // title line so every row of the panel reads the same way. + // THE DESCRIPTION IS HEADED BY THE THREAD, which for a stopped conversation is the + // row's own title — the label `threads` draws for it — said once more as the + // description's title line so every row of the panel reads the same way. cell.thread = row.title head, whole := needsSentence(row.session) cell.sub = head @@ -321,13 +310,12 @@ func needsCall(project session.Project, row session.SessionRow, entry session.Ta program = strings.TrimSpace(entry.Program) } asked := needsCallAt(entry) - // A LANDING WEARS NO MARK (law 8). The amber `?` means a thing has stopped - // and will not move until somebody answers it; a landing has already - // finished, and a column of question marks over work that is DONE was the - // screen saying the opposite of what was true. - // THE THREAD IT BELONGS TO HEADS THE DESCRIPTION (owner, 2026-09-17), - // spelled as `threads` spells the same conversation ([homeName]); under - // that title line come the files and what the work came to. + // A LANDING WEARS NO MARK (law 8). The amber `?` means a thing has stopped and will not + // move until somebody answers it; a landing has already finished, and a column of + // question marks over work that is DONE was the screen saying the opposite of what was + // true. THE THREAD IT BELONGS TO HEADS THE DESCRIPTION, spelled as `threads` spells the + // same conversation ([homeName]); under that title line come the files and what the work + // came to. cell := &homeCell{panel: panelNeeds, mark: cellMarkNeeds, title: title, program: program, right: sinceAt(asked, now), key: needsCallKey + entry.ID, thread: homeName(row), grows: true, sub: rowClauses(needsCallFiles(entry), needsCallSub(entry, status)), answers: needsCallAnswers(status)} @@ -354,11 +342,10 @@ func needsCallSub(entry session.TaskIndexEntry, status session.TaskStatus) strin // description — `3 files · <what it came to>` — and "" for one that wrote none, // never `0 files` (the emptiness law). // -// IT USED TO BE THE RIGHT MARGIN, as one clause with the age (`3 files · 1d`), -// so a landing that wrote nothing read `10h` beside one that read `1 file · 1d` -// — two shapes in one column for one kind of row. THE RIGHT MARGIN OF EVERY ROW -// OF THE FIELD IS A TIME (owner, 2026-09-15), and everything that is not a time -// is in the description column ([homeDescLines]). +// IT USED TO BE THE RIGHT MARGIN, as one clause with the age (`3 files · 1d`), so a +// landing that wrote nothing read `10h` beside one that read `1 file · 1d` — two shapes in +// one column for one kind of row. THE RIGHT MARGIN OF EVERY ROW OF THE FIELD IS A TIME, +// and everything that is not a time is in the description column ([homeDescLines]). func needsCallFiles(entry session.TaskIndexEntry) string { if entry.FilesChanged <= 0 { return "" diff --git a/internal/tui3/homepanel_recent.go b/internal/tui3/homepanel_recent.go index e529abaee4..9bf5699f21 100644 --- a/internal/tui3/homepanel_recent.go +++ b/internal/tui3/homepanel_recent.go @@ -27,12 +27,11 @@ func (recentPanel) rows(in *homeGridInput) homePanelRows { // a shell nobody has spoken in), so no tail read off the journal can put a line // under it first. // -// `here` IS THE FIRST WORD OF ITS DESCRIPTION, not its margin. THE RIGHT MARGIN -// OF EVERY ROW OF THE FIELD IS A TIME (owner, 2026-09-15): this row's is when -// its person last spoke in it, like every row under it, and the word that says -// it is this window's own stands where the row's other facts do — permanently, -// because it is true whether or not the cursor is here. On a frame with no -// description column the word is not said at all: it would cost the column a +// `here` IS THE FIRST WORD OF ITS DESCRIPTION, not its margin. THE RIGHT MARGIN OF EVERY +// ROW OF THE FIELD IS A TIME: this row's is when its person last spoke in it, like every +// row under it, and the word that says it is this window's own stands where the row's +// other facts do — permanently, because it is true whether or not the cursor is here. On a +// frame with no description column the word is not said at all: it would cost the column a // row on the frames that have the fewest, and the bold already says it. func recentOwnCell(row switcherRow, in *homeGridInput) *homeCell { said := "" @@ -51,13 +50,11 @@ func recentOwnCell(row switcherRow, in *homeGridInput) *homeCell { // key — and, under the cursor, its project's name and the last thing its person // said in it. // -// THE PROJECT IS A DESCRIPTION AND NOT A TAG. It used to stand beside the age -// (`infra 3h`) on a row from another folder and nowhere on a row from this -// window's own, so the margin was one word wide on some rows and two on others -// (owner, 2026-09-15: "what are these and why are they absent elsewhere?"). It -// is the first clause of the description now, still only where it says -// something — a row of this window's own folder, a scratch folder or the home -// directory has no project word ([chatProjectTag]). +// THE PROJECT IS A DESCRIPTION AND NOT A TAG. It used to stand beside the age (`infra +// 3h`) on a row from another folder and nowhere on a row from this window's own, so the +// margin was one word wide on some rows and two on others. It is the first clause of the +// description now, still only where it says something — a row of this window's own folder, +// a scratch folder or the home directory has no project word ([chatProjectTag]). func recentCell(row switcherRow, in *homeGridInput) *homeCell { // THE LAST THING THIS PERSON SAID IN IT, under the cursor — which is the one // fact that tells two conversations with similar names apart, and the same diff --git a/internal/tui3/homepanel_spend.go b/internal/tui3/homepanel_spend.go index 6f2c8ae047..e4758ee6fc 100644 --- a/internal/tui3/homepanel_spend.go +++ b/internal/tui3/homepanel_spend.go @@ -10,23 +10,20 @@ import ( "github.com/Agent-Field/codeaf/internal/session" ) -// spendPanel is `spend`: a small HUD, THREE LINES THAT EACH SAY ONE THING. The -// heading names the panel; today's cost and allowance are already on the top -// line. Once the day has spent enough of its allowance to see, one thin meter -// says how much is gone. Then the fortnight, one block cell a day with today at the right, its -// total and its loudest day. Then who it went to and what for: the two models -// most of it bought, and how many chats and tasks today has seen. NO ROW OF IT -// IS A DOOR: the lines under the heading are a reading and not things to do -// anything to, so the cursor steps over them and a press on one does nothing -// (owner, 2026-09-17: "nothing under the spend title should be selectable or -// clickable"). The heading itself still opens the spend place, as every -// heading that names a place does ([app.homeHeadPress]). +// spendPanel is `spend`: a small HUD, THREE LINES THAT EACH SAY ONE THING. The heading +// names the panel; today's cost and allowance are already on the top line. Once the day +// has spent enough of its allowance to see, one thin meter says how much is gone. Then the +// fortnight, one block cell a day with today at the right, its total and its loudest day. +// Then who it went to and what for: the two models most of it bought, and how many chats +// and tasks today has seen. NO ROW OF IT IS A DOOR: the lines under the heading are a +// reading and not things to do anything to, so the cursor steps over them and a press on +// one does nothing. The heading itself still opens the spend place, as every heading that +// names a place does ([app.homeHeadPress]). // -// IT WAS TWO CHARTS (owner, 2026-09-10). A gauge-cell bar under the heading -// read as a second sparkline, the braille fortnight beside it was noise at a -// column's width, and the allowance said `$500.00` under a pulse saying `$500`. -// The meter is a line now and not a chart, the fortnight is block cells, and the -// allowance is spelled the pulse's way ([railFigure]). +// IT WAS TWO CHARTS. A gauge-cell bar under the heading read as a second sparkline, the +// braille fortnight beside it was noise at a column's width, and the allowance said +// `$500.00` under a pulse saying `$500`. The meter is a line now and not a chart, the +// fortnight is block cells, and the allowance is spelled the pulse's way ([railFigure]). type spendPanel struct{ homePanelBase } const ( diff --git a/internal/tui3/homepanel_test.go b/internal/tui3/homepanel_test.go index 71b3813114..d086572cb8 100644 --- a/internal/tui3/homepanel_test.go +++ b/internal/tui3/homepanel_test.go @@ -102,11 +102,9 @@ func TestSinceYouLeftIsItsOwnPanelOfDoors(t *testing.T) { } } -// WHERE YOU WERE: this window's own conversation first, in bold, the last thing -// said in it under it, then the most recent quiet ones. A row from another -// folder carries its project as its description, under the cursor — the margin -// is a time on every row (owner, 2026-09-15; the project used to be a tag -// beside the age, and `here` the own row's margin). +// WHERE YOU WERE: this window's own conversation first, in bold, the last thing said in it +// under it, then the most recent quiet ones. A row from another folder carries its project +// as its description, under the cursor — the margin is a time on every row. func TestWhereYouWereLeadsWithThisWindowsOwnConversation(t *testing.T) { lab := newSwitchLab(t) a := lab.open(120, 45) @@ -497,9 +495,9 @@ func TestSpendIsASmallHudOfThreeLines(t *testing.T) { t.Fatalf("at 40 cells the panel draws %q", row) } } - // AND NOTHING UNDER THE HEADING IS A STOP OR A DOOR (owner, 2026-09-17): - // the cursor steps over every one of the panel's lines, and a press on one - // leaves home up. The heading is still the door into the spend place. + // AND NOTHING UNDER THE HEADING IS A STOP OR A DOOR: the cursor steps over every one of + // the panel's lines, and a press on one leaves home up. The heading is still the door + // into the spend place. for at, line := range a.home.lines { if line.cell == nil || line.cell.panel != panelSpend || line.cell.kind == cellHead { continue diff --git a/internal/tui3/homeslash.go b/internal/tui3/homeslash.go index f7c3d914c2..495d103b0a 100644 --- a/internal/tui3/homeslash.go +++ b/internal/tui3/homeslash.go @@ -58,14 +58,11 @@ func (h *homeView) commandLines() []homeLine { // in the right margin WHAT ENTER WILL DO WITH IT HERE, then the command's own // note (commands.go's [command.note]). // -// THE MARGIN USED TO SAY `a command`, which every row of the list already -// demonstrated by existing. What a person standing on home cannot know is the -// thing this list is now the only place to learn: that `/compact` opens a -// conversation before it runs, that `/model` changes a draft and touches nothing -// behind the screen, that `/quit` closes a conversation they cannot see. The -// owner asked for that to be readable BEFORE the key is pressed, including for -// the commands that do nothing useful here — so the fate leads the margin and -// the note follows it. +// THE MARGIN USED TO SAY `a command`, which every row of the list already demonstrated by +// existing. What a person standing on home cannot know is the thing this list is now the +// only place to learn: that `/compact` opens a conversation before it runs, that `/model` +// changes a draft and touches nothing behind the screen, that `/quit` closes a +// conversation they cannot see. // // AND THE FATE IS NEVER THE HALF THAT IS CUT. [overlayRow] fits the whole margin // to the room the label leaves, from the right, so a margin built as one string diff --git a/internal/tui3/homeslash_test.go b/internal/tui3/homeslash_test.go index ef34c5ab68..7910ec0f68 100644 --- a/internal/tui3/homeslash_test.go +++ b/internal/tui3/homeslash_test.go @@ -400,11 +400,10 @@ func TestModelAtHomePinsTheDraftAndSaysSo(t *testing.T) { if a.model != "zhipu/glm-5.3-flash" { t.Fatalf("/model at home re-modelled the conversation behind the screen: %q", a.model) } - // AND IT SAYS NOTHING ON THE LINE UNDER THE BOX. That line used to read `model - // · glm-5.3 · for the next conversation you start here`, and the question it - // was answering is answered by the RULE below instead — which carries the - // pinned model for as long as the pin lasts rather than until the next note - // replaces it (the owner's ruling). + // AND IT SAYS NOTHING ON THE LINE UNDER THE BOX. That line used to read `model · glm-5.3 + // · for the next conversation you start here`, and the question it was answering is + // answered by the RULE below instead — which carries the pinned model for as long as the + // pin lasts rather than until the next note replaces it. if a.home.msg != "" { t.Fatalf("home's line reads %q, want nothing — the rule says it instead", a.home.msg) } @@ -412,7 +411,7 @@ func TestModelAtHomePinsTheDraftAndSaysSo(t *testing.T) { if text := homeText(a); !strings.Contains(text, modelBase("zhipu/glm-5.3")) { t.Fatalf("the rule does not say the pinned model:\n%s", text) } - // AND IT SURVIVES LEAVING HOME AND COMING BACK (the owner's ruling). + // AND IT SURVIVES LEAVING HOME AND COMING BACK. a.closeHome() runCmd(a.showPage(pageHome)) if a.target.model != "zhipu/glm-5.3" { diff --git a/internal/tui3/homesnappy_test.go b/internal/tui3/homesnappy_test.go index 3fa65c7d21..6c9e5e9e72 100644 --- a/internal/tui3/homesnappy_test.go +++ b/internal/tui3/homesnappy_test.go @@ -17,9 +17,8 @@ import ( // stopwatches for the reason that file's doctrine gives: a count is a fact about // the code and the same fact on a loaded laptop as on idle CI. // -// WHAT THEY WERE WRITTEN AFTER. The owner reported that "when I hover or go up -// and down in home it's very laggy, I think it has something to do with git". -// Three separate things were true, and the guess was one of them: +// WHAT THEY WERE WRITTEN AFTER. Three separate things were true, and the guess was one of +// them: // // - the deliverables index was read and parsed inside a draw (fixed one commit // earlier, pinned by [TestTheDeliverablesIndexIsReadOnceForTheWholeScreen]); @@ -96,9 +95,6 @@ func TestMovingTheCursorOnHomeRunsNoCommand(t *testing.T) { // ([app.refreshGridReadings]), so an arrow has nothing to ask. } -// AND SO DOES A POINTER, which is the half the owner met first: a surface in -// AllMotion answers a sweep sixty times a second (coalesce.go), so one command -// per answered motion is sixty commands a second in front of the keys. func TestAPointerMotionOnHomeRunsNoCommand(t *testing.T) { ran := 0 a := snappyLab(t, 10*time.Millisecond, &ran) diff --git a/internal/tui3/hometip.go b/internal/tui3/hometip.go index f6e0ccb2e4..a1ce424f3e 100644 --- a/internal/tui3/hometip.go +++ b/internal/tui3/hometip.go @@ -36,14 +36,13 @@ import ( // homeTipLead is the bulb before a tip on the row. // -// IT IS AN EMOJI, AND THAT IS THE OWNER'S RULING (2026-09-22) against the -// vocabulary's own no-emoji-in-chrome law (internal/tui2/tokens's glyph.go): -// one bulb, on one row, asked for by name. It is not a slot in the vocabulary -// because the vocabulary refuses the emoji planes on purpose and its width -// gate would refuse this one; and it is not the icon law's to own, because the -// law owns the vocabulary's runes and no other. It measures two cells -// everywhere the renderer measures, and the row is laid out from that -// measurement rather than from a guess. +// IT IS AN EMOJI (2026-09-22) against the vocabulary's own no-emoji-in-chrome law +// (internal/tui2/tokens's glyph.go): one bulb, on one row, asked for by name. It is not a +// slot in the vocabulary because the vocabulary refuses the emoji planes on purpose and +// its width gate would refuse this one; and it is not the icon law's to own, because the +// law owns the vocabulary's runes and no other. It measures two cells everywhere the +// renderer measures, and the row is laid out from that measurement rather than from a +// guess. const homeTipLead = "💡" // homeTipGap is the cell between the bulb and the tip, and between the tip and diff --git a/internal/tui3/hop.go b/internal/tui3/hop.go index c47bc6d8d1..4caa2dddf6 100644 --- a/internal/tui3/hop.go +++ b/internal/tui3/hop.go @@ -54,14 +54,12 @@ import ( // // ── THE CARD WEARS THE ONE FRAME, AND THE DEPTH IS WHAT SAYS `LAYER` ──────── // -// This header used to say the card had no border, while the card drew one — a -// dim rounded box of its own, one of three copies of the same six pieces on this -// surface. It is drawn by the one frame now (frame.go, owner ruling 2026-09-11), -// dim, on the card's own raised ground. What says `layer` is still the depth: -// the body behind it is repainted at the FAINTEST stop of the depth ladder -// ([composerFade], depthfade.go) and the card's own rows are left at full ink. -// That is the same move SCREEN 2e's composer layer makes over a place, one -// mechanism rather than two, and the frame only says where the card ends. +// This header used to say the card had no border, while the card drew one — a dim rounded +// box of its own, one of three copies of the same six pieces on this surface. What says +// `layer` is still the depth: the body behind it is repainted at the FAINTEST stop of the +// depth ladder ([composerFade], depthfade.go) and the card's own rows are left at full +// ink. That is the same move SCREEN 2e's composer layer makes over a place, one mechanism +// rather than two, and the frame only says where the card ends. // // The rows themselves are home's rows — the same glyph door, the same bold // subject, the same dim tail dropped in the same order (switcher.go's @@ -660,11 +658,7 @@ func (a *app) hopRest(open []hopRow, now time.Time) []hopRow { if len(open)+len(rest) >= hopShown { break } - // THE FOLDER IS ASKED ABOUT ONCE AND BOTH READINGS TAKE THAT ANSWER. It - // used to be asked here for the GLYPH and left false on the row - // [hopRestNote] reads, so a conversation whose project had gone was drawn - // with the refusing `✕` and no clause saying why — a mark a person cannot - // account for, which is the whole of what the owner's report was about. + // THE FOLDER IS ASKED ABOUT ONCE AND BOTH READINGS TAKE THAT ANSWER. row.gone = !homeFolderThere(row.place) rest = append(rest, hopRow{ file: row.session.Transcript, title: row.title, project: row.project, @@ -1247,14 +1241,11 @@ func (a *app) hopOpenRows() int { return a.hop.tabs } // ── what the card looks like ──────────────────────────────────────────────── // -// THE CARD IS A BOX, AND IT IS THE ONE ON THIS SURFACE. The house rule is that -// nothing is outlined — emphasis is a raised ground and an accent, never a ring -// drawn round a thing (harnesscard.go states it) — and this is the deliberate -// exception, ruled by the owner off SCREEN 3b's own drawing. The reason it earns -// the exception is that it is the only thing here that FLOATS: every other panel -// on this surface takes the frame or hangs off an edge, so its bounds are the -// screen's. A list dropped into the middle of a dimmed transcript has no edge of -// its own, and without one the eye reads it as text that happens to be brighter. +// THE CARD IS A BOX, AND IT IS THE ONE ON THIS SURFACE. The reason it earns the exception +// is that it is the only thing here that FLOATS: every other panel on this surface takes +// the frame or hangs off an edge, so its bounds are the screen's. A list dropped into the +// middle of a dimmed transcript has no edge of its own, and without one the eye reads it +// as text that happens to be brighter. // // THE COLUMNS ARE FIXED AND THAT IS THE WHOLE OF WHY IT SCANS. Glyph, subject, // one clause, project, clock — the subjects form a straight edge you read down @@ -1288,11 +1279,8 @@ const ( // hopTightNote is what the clause narrows to on the way down, which is // `3 tasks running` whole. hopTightNote = 16 - // hopGutter is the air kept at the right-hand end of the subject column, so a - // name that fills its column does not touch the clause beside it. Without it - // the two run together as one word — `…parsing regres…nothing new` — which is - // the reading the owner reported, and no amount of extra column width fixes - // it, because a long enough name fills whatever it is given. + // hopGutter is the air kept at the right-hand end of the subject column, so a name that + // fills its column does not touch the clause beside it. hopGutter = 2 ) diff --git a/internal/tui3/hop_test.go b/internal/tui3/hop_test.go index b2c04093e7..0c5b569d0f 100644 --- a/internal/tui3/hop_test.go +++ b/internal/tui3/hop_test.go @@ -409,9 +409,6 @@ func TestTheCardHoldsTheWholeMachineAndOpensARowThatIsNotOpenYet(t *testing.T) { } } -// TestTheFoldKeepsTheCardAboutWhatIsOpen is the shape the owner asked for: the -// ring is the conversations this terminal is holding, and everything else on the -// machine is behind one door with a count on it. func TestTheFoldKeepsTheCardAboutWhatIsOpen(t *testing.T) { dir := t.TempDir() a := newTestApp(&fakeAgent{model: "m"}) @@ -859,8 +856,6 @@ func TestALongNameTakesTheRoomAndIsNotRepeatedUnderTheList(t *testing.T) { // what was behind the screen. These four are that door, asserted from a place // (hop.go's [app.hopLand]). -// TestTakingARowFromHomeLandsInTheConversation is the owner's own report: home -// up, `ctrl+k`, `enter`, and you are IN the conversation you chose. func TestTakingARowFromHomeLandsInTheConversation(t *testing.T) { a := newTestApp(&fakeAgent{model: "m"}) a.file = "/tmp/lab/this-one.jsonl" diff --git a/internal/tui3/host.go b/internal/tui3/host.go index a8a7fd0645..13aa1fcd20 100644 --- a/internal/tui3/host.go +++ b/internal/tui3/host.go @@ -170,7 +170,7 @@ import ( // the one that may type (internal/remote's driver.go). A // window that is not it becomes a WATCHER: its transcript // keeps arriving live, its composer is replaced by one dim -// line reading `typing from spark now` and +// line reading `typing from laptop now` and // `enter takes it back`, and its draft is KEPT — not // cleared, not sent. Enter takes the keyboard back in one // round trip and the other window is told in the same diff --git a/internal/tui3/hostlatency_test.go b/internal/tui3/hostlatency_test.go index 570e3e49f3..b6554a1d52 100644 --- a/internal/tui3/hostlatency_test.go +++ b/internal/tui3/hostlatency_test.go @@ -19,13 +19,11 @@ import ( // rather than stopwatches for the reason that file's doctrine gives: a count is // a fact about the code and the same fact on a loaded laptop as on idle CI. // -// WHAT THEY WERE WRITTEN AFTER. The owner reported that over a connection -// "even hover seems to slow everything down", and that clicks and keys felt -// dead. Both were one defect: the status row asked the agent what the model was -// dialled to while it was DRAWING (view.go's [app.statusRow]), a hover below -// the conversation rebuilds the chrome to find its row (view.go's -// [app.chromeAt]), and over a connection that read is a round trip on the ssh -// pipe. Measured on the loopback client at the commit before this file: +// WHAT THEY WERE WRITTEN AFTER. Both were one defect: the status row asked the agent what +// the model was dialled to while it was DRAWING (view.go's [app.statusRow]), a hover below +// the conversation rebuilds the chrome to find its row (view.go's [app.chromeAt]), and +// over a connection that read is a round trip on the ssh pipe. Measured on the loopback +// client at the commit before this file: // // 100 frames 100 far calls // 200 pointer motions over the foot 200 far calls diff --git a/internal/tui3/hostlink.go b/internal/tui3/hostlink.go index 037f635e55..94da0c8acd 100644 --- a/internal/tui3/hostlink.go +++ b/internal/tui3/hostlink.go @@ -335,12 +335,8 @@ const newsSilenceNote = "this window uses an older background engine; host and t // sayNewsSilence says [newsSilenceNote] once per window, the first time a turn // that produced an answer ends on an engine that has sent no news. // -// THE DEFECT IT ANSWERS. The news frames rode an existing wire version on -// purpose, so a surface attached to an engine from before them — which the door -// does, rather than retire a busy one — drew no `via` and no rate and nothing -// saying why, and the owner read the gap as those two vanishing at random. The -// engine's version is not the question; whether the news arrives is, so that is -// what is asked ([LinkSeam.NewsSilent]). +// THE DEFECT IT ANSWERS. The engine's version is not the question; whether the news +// arrives is, so that is what is asked ([LinkSeam.NewsSilent]). // // AN ANSWER HAS TO HAVE ARRIVED, because that is what makes silence a fact. An // engine with the news posts a phase on every request it makes, so a turn that diff --git a/internal/tui3/keeper.go b/internal/tui3/keeper.go index fec20d6def..52ecf135cb 100644 --- a/internal/tui3/keeper.go +++ b/internal/tui3/keeper.go @@ -31,12 +31,9 @@ import ( // window. `behind` describes a position on a screen nobody can see, which makes // it furniture; `open` describes what is true. -// NO DOOR ONTO A CONVERSATION IS EVER REFUSED FOR HOW MANY ARE ALREADY OPEN. -// There was a cap — eight — and its own comment said that a cap hit in practice -// by somebody who was not testing it is evidence the number is wrong. It was hit -// in a day of ordinary use, and the owner's ruling on 2026-08-31 was to remove -// the limit rather than to raise it: "that is pointless". That ruling stands, and -// nothing below is a limit: the fiftieth `/new` opens exactly like the first. +// NO DOOR ONTO A CONVERSATION IS REFUSED FOR HOW MANY ARE ALREADY OPEN. +// Quiet conversations can be released to bound resources without imposing a +// limit on the number of conversations a person can start. // // WHAT ONE OPEN CONVERSATION COSTS is what it always was — a few goroutines, its // transcript, one file descriptor, a five-second presence tick and its diff --git a/internal/tui3/keptsweep_test.go b/internal/tui3/keptsweep_test.go index 81f0ff4cb0..b593d0612d 100644 --- a/internal/tui3/keptsweep_test.go +++ b/internal/tui3/keptsweep_test.go @@ -11,10 +11,10 @@ import ( // THE SWEEP: what gives an open conversation's cost back without a person asking. // -// The keeper refuses nothing however many conversations somebody opens, which is -// the owner's own ruling — so the only honest way to bound what a window holds is -// to let go of the ones nothing would be lost from. These tests are the list of -// what "nothing would be lost" means, one claim at a time. +// The keeper refuses nothing however many conversations somebody opens — so the only +// honest way to bound what a window holds is to let go of the ones nothing would be lost +// from. These tests are the list of what "nothing would be lost" means, one claim at a +// time. // askingAgent is a conversation stopped on a question. No other double on this // surface answers [session.Agent.NeedsPerson], and the sweep asks that door diff --git a/internal/tui3/lanes.go b/internal/tui3/lanes.go index 2c9cc2fa19..d03c1b4b86 100644 --- a/internal/tui3/lanes.go +++ b/internal/tui3/lanes.go @@ -1193,14 +1193,10 @@ func (a *app) modelIdentity(id string) string { // and — while a lane is pinned — `@` and that lane: // `deepseek/deepseek-v4-flash@cloudflare`. // -// A PIN IS AN INSTRUCTION THAT CHANGES EVERY FUTURE REQUEST, and until this the -// chrome never said it. The picker's row said `via inception` only while the -// picker was open, the status rider said `via …` only for ten minutes after an -// answer, and the frame's head read `mercury-2.5 · ⠿ auto` — whose `auto` is the -// thinking rung, which the owner read as "lane: auto" and concluded the pin had -// failed (2026-09-10). So the pin rides the one word every place that names the -// model already draws: the seam, the status row's identity and the phone deck's -// chip all take it from here, and none of them spells it. +// A PIN IS AN INSTRUCTION THAT CHANGES EVERY FUTURE REQUEST, and until this the chrome +// never said it. So the pin rides the one word every place that names the model already +// draws: the seam, the status row's identity and the phone deck's chip all take it from +// here, and none of them spells it. // // On `auto` and `openrouter` it adds nothing — the emptiness law: a choice left // to the router is the unremarkable state and says no word. @@ -1285,19 +1281,13 @@ func (a *app) openPickerFromChip() { // retraction: the rescue this line promised has itself been refused, so the // promise goes and what is left is the fact. // -// AND ALL THREE ARE ABOUT AN ANSWER THAT IS FINISHED, which is why the phase -// clock takes the segment away from them while a request is actually in flight -// (render.go's [app.servedRider]). These read the past tense; that reads the -// present one. -// timed says whether the answer's own figures — the wait before its first word -// and, while a turn runs, how fast it was written — ride after the machine's -// name. The sheet's `served` row wants them (statusdeck.go); THE SEAM DOES NOT. -// On 2026-09-10 the owner read `via relace · 1.3s · 79 t/s` on the seam while -// an answer was being written and took the figure for the live rate, which by -// then stood at the right edge of the status row as `34 tok/s` (render.go's -// [app.liveRiderAt]) — one frame, two rates, and the one beside the model was -// the LAST answer's average. Who served is attribution and belongs beside the -// model; how fast is a claim about now and has one place on the frame. +// AND ALL THREE ARE ABOUT AN ANSWER THAT IS FINISHED, which is why the phase clock takes +// the segment away from them while a request is actually in flight (render.go's +// [app.servedRider]). These read the past tense; that reads the present one. timed says +// whether the answer's own figures — the wait before its first word and, while a turn +// runs, how fast it was written — ride after the machine's name. The sheet's `served` row +// wants them (statusdeck.go); THE SEAM DOES NOT. Who served is attribution and belongs +// beside the model; how fast is a claim about now and has one place on the frame. // // IT IS THE SHEET'S READING, AND THE SHEET KEEPS THE OLD SUPPRESSION: the row // above `served` there is the model's whole routing address, vendor and all, so @@ -1315,11 +1305,10 @@ const ( // `served` row and the phone deck's identity, said shorter when the row // is tight. riderVia riderStyle = iota - // riderBeside is ` (relace)`: the machine written onto the model's own - // cell on the seam — `deepseek-v4-flash (relace)` — whole or nothing, and - // never aged out. The owner's ruling of 2026-09-17: the model and the - // machine answering for it are one fact, read as one word, and the last - // machine to answer stays named until another does. + // riderBeside is ` (relace)`: the machine written onto the model's own cell on the seam — + // `deepseek-v4-flash (relace)` — whole or nothing, and never aged out. The model and the + // machine answering for it are one fact, read as one word, and the last machine to answer + // stays named until another does. riderBeside ) @@ -1335,13 +1324,12 @@ func riderWords(style riderStyle, machine, tail string) string { // talkLaneRider is the conversation's rider ON THE SEAM: who is answering, with // no figures, and WHOEVER SERVED. // -// live is the machine the request in flight has named ([PhaseNews.Lane]), and -// it is asked for here because the sighting is only posted when a whole step -// has FINISHED. So the first answer in a conversation, and a follow-up sent -// after the last sighting had aged out ([servedWindow]), drew no `via` at all -// for as long as the answer was being written — while the phase clock already -// knew exactly who was writing it. The owner's ruling is that `via` is always on -// the seam; a sighting that is not posted yet is not a reason to break it. +// live is the machine the request in flight has named ([PhaseNews.Lane]), and it is asked +// for here because the sighting is only posted when a whole step has FINISHED. So the +// first answer in a conversation, and a follow-up sent after the last sighting had aged +// out ([servedWindow]), drew no `via` at all for as long as the answer was being written — +// while the phase clock already knew exactly who was writing it. `via` is always +// on the seam; a sighting that is not posted yet is not a reason to break it. func (a *app) talkLaneRider() string { live := "" if news, ok := a.livePhase(); ok { @@ -1390,11 +1378,10 @@ func (a *app) roomLaneRider() string { // the default service — right by accident, and wrong the day the default is // a direct one. // -// named is the id the row beside it spells IN FULL, read for one thing only — -// the rule that a machine the id already carries is not said twice. Only the -// sheet passes one ([app.laneRider]); the seam and a room spell a basename, so -// the vendor is not on the screen and they pass nothing (the owner's ruling of -// 2026-09-09: the machine always on the seam). +// named is the id the row beside it spells IN FULL, read for one thing only — the rule +// that a machine the id already carries is not said twice. Only the sheet passes one +// ([app.laneRider]); the seam and a room spell a basename, so the vendor is not on the +// screen and they pass nothing. // // live is the machine the request in flight has named, or "" — see // [app.talkLaneRider] for why it outranks the last answer's sighting. diff --git a/internal/tui3/lanes_test.go b/internal/tui3/lanes_test.go index d85a5a89ee..d88514c480 100644 --- a/internal/tui3/lanes_test.go +++ b/internal/tui3/lanes_test.go @@ -974,7 +974,7 @@ func TestTheSparklineIsOurOwnLastAnswersAndNothingUntilThereAreTwo(t *testing.T) // not: EVERY first-token wait this file draws is said in SECONDS with one // decimal ([laneSecondsWord]), and there is no path from a belief or from // [LaneNews] to a millisecond word at all. `2ms` on that line is the CONNECTION -// segment of a `--host` session — `spark · 2ms`, the round trip to the machine +// segment of a `--host` session — `laptop · 2ms`, the round trip to the machine // the conversation is running on (hostlink.go's latencyWord, the only `ms` on // this surface) — which sits immediately before the state word and is true of // the whole line rather than of the answer. diff --git a/internal/tui3/lanewalk_test.go b/internal/tui3/lanewalk_test.go index c1bf466dc6..3cfa4e2fa5 100644 --- a/internal/tui3/lanewalk_test.go +++ b/internal/tui3/lanewalk_test.go @@ -15,9 +15,8 @@ import ( // ── THE PICKER IS A TREE, AND THE LANE IS WRITTEN ON THE MODEL ────────────── // -// docs/design/lanes-picker/DESIGN.md. The owner opened /model on 2026-09-10, -// pressed ← and →, and asked how anybody changes the provider of a model. Every -// test here is one of the four answers, driven the way a person drives it. +// docs/design/lanes-picker/DESIGN.md. Every test here is one of the four answers, driven +// the way a person drives it. // walkCatalog puts the model in use twelfth, which is where the owner's own // catalog put it: [picker.start] opens the cursor on it, and [listTop] leaves it diff --git a/internal/tui3/leaving.go b/internal/tui3/leaving.go index c7ff72699b..02812a1a45 100644 --- a/internal/tui3/leaving.go +++ b/internal/tui3/leaving.go @@ -30,9 +30,8 @@ import ( // [workOutlivesExit]), which is most of what the warning sentence existed // to say. // -// What is genuinely spent is the WARNING: a person who leaves with tasks running -// in this process is no longer told so first. That is the trade, and it is the -// one the owner asked for — the key means leave. +// What is genuinely spent is the WARNING: a person who leaves with tasks running in this +// process is no longer told so first. // ── WHAT LEAVES WITH YOU ──────────────────────────────────────────────────── diff --git a/internal/tui3/lifecycle_test.go b/internal/tui3/lifecycle_test.go index 2f82d85fb0..79ca668de6 100644 --- a/internal/tui3/lifecycle_test.go +++ b/internal/tui3/lifecycle_test.go @@ -248,10 +248,6 @@ func TestElapsedWordSpellsEveryScale(t *testing.T) { // for a person, and it is marked everywhere at once: the row it is about, the // question itself, and the word in the status line. Anything less was the defect // — a person who could not tell the agent had stopped and was waiting for them. -// -// It was a violet of its own until the owner retired it (2026-09-11, colour pick -// C): home, the places, the chip and the tab had always said this in amber, and -// one meaning may not wear two hues. func TestTheConsentQuestionIsAmberEverywhereAtOnce(t *testing.T) { agent, a := wired([]session.Event{ toolBegin("bash", "bash rm -rf build"), @@ -345,12 +341,10 @@ func TestTheEditPreviewAppearsOnAnnouncementAndCollapsesIntoTheStat(t *testing.T if strings.Contains(plain(toolRowText(t, a)), "+1") { t.Fatalf("a queued edit drew its stat: %q", plain(toolRowText(t, a))) } - // The header is DIM, like every other word about a call that has not run - // yet. It wore the question hue until the questions wave took the amber back - // to the marks (owner ruling 2026-09-11, colour pick C): the `?` in the - // gutter is what says a person is being waited on, and a second colour on a - // word meaning "not yet" was the hue spent on something that is not a - // question at all. + // The header is DIM, like every other word about a call that has not run yet. It wore the + // question hue until the questions wave took the amber back to the marks: the `?` in the + // gutter is what says a person is being waited on, and a second colour on a word meaning + // "not yet" was the hue spent on something that is not a question at all. for _, r := range rows(a) { if strings.Contains(plain(r.text), "pending") && !strings.Contains(r.text, a.pal.dim("pending")) { t.Fatalf("the pending header is not dim: %q", r.text) diff --git a/internal/tui3/livesteps.go b/internal/tui3/livesteps.go index 7e841557ac..f3691ec2f6 100644 --- a/internal/tui3/livesteps.go +++ b/internal/tui3/livesteps.go @@ -62,11 +62,10 @@ import ( // it again. // // AND COMPLETION ALWAYS COLLAPSES IT, whatever the reader chose while it ran -// ([app.collapseLiveWork], called at the settle). The expansion is a thing a -// person wanted WHILE the work was happening; a turn that is over is an exchange -// again — a question and an answer — and the machinery behind it goes back -// behind the chip. This is the owner's ruling and it is the one place on this -// surface where a reader's expansion does not outlive what it was about. +// ([app.collapseLiveWork], called at the settle). The expansion is a thing a person wanted +// WHILE the work was happening; a turn that is over is an exchange again — a question and +// an answer — and the machinery behind it goes back behind the chip. and it is the one +// place on this surface where a reader's expansion does not outlive what it was about. // // WHAT IT MAY NEVER COVER is [liveWorkKeeps], and the list is the conversation's // own: the person's words, a question waiting to be answered, an explicit diff --git a/internal/tui3/livesteps_test.go b/internal/tui3/livesteps_test.go index 2de7620203..6ae14fb2e6 100644 --- a/internal/tui3/livesteps_test.go +++ b/internal/tui3/livesteps_test.go @@ -343,8 +343,8 @@ func TestEachStepInTheOpenWindowStillOpensItsOwnCalls(t *testing.T) { // ── COMPLETION ALWAYS COLLAPSES THE WORK ──────────────────────────────────── -// The owner's ruling, and the one place a reader's expansion does not outlive -// what it was about: a turn that is over is an exchange again. +// The, and the one place a reader's expansion does not outlive what it was about: a turn +// that is over is an exchange again. func TestCompletionCollapsesWorkTheReaderOpenedWhileItRan(t *testing.T) { a := liveStepsApp(t) a.toggleLatestWorkfold() diff --git a/internal/tui3/manualcmd_test.go b/internal/tui3/manualcmd_test.go index 4f907578df..86fdc08274 100644 --- a/internal/tui3/manualcmd_test.go +++ b/internal/tui3/manualcmd_test.go @@ -62,10 +62,9 @@ func TestABareManualAsksTheModelForTheTour(t *testing.T) { } } -// ON HOME THE QUESTION OPENS A CONVERSATION FIRST AND IS ASKED THERE. It used to -// be an answer echoed to home's line, and the answer — the pages, printed — -// went into the conversation behind home, where the person who typed it could -// see nothing happen at all (the owner met it, 2026-09-22). +// ON HOME THE QUESTION OPENS A CONVERSATION FIRST AND IS ASKED THERE. It used to be an +// answer echoed to home's line, and the answer — the pages, printed — went into the +// conversation behind home, where the person who typed it could see nothing happen at all. func TestManualOnHomeOpensAConversationAndAsksThere(t *testing.T) { lab := newHomeLab(t) a := lab.door("") diff --git a/internal/tui3/markdown.go b/internal/tui3/markdown.go index eaae811f39..8283bab262 100644 --- a/internal/tui3/markdown.go +++ b/internal/tui3/markdown.go @@ -1215,7 +1215,7 @@ func taskLinkHotInk(pal palette, s string) string { return pal.underline(pal.ink // OSC ESC ] … BEL | ESC \ the hyperlink around a path (pathlink.go) // // AN OSC HAS TO BE SWALLOWED WHOLE OR IT IS NOT SWALLOWED AT ALL. Its payload -// is ordinary printable bytes — `8;;file:///Users/x/main.go` — so a walk that +// is ordinary printable bytes — `8;;file:///workspace/main.go` — so a walk that // stopped after `ESC ]` would count twenty-six cells of URI as text, and every // caller of [flatten] indexes a row by those counts. Task references would land // on the wrong columns and [paintLinks] would splice an SGR into the middle of a diff --git a/internal/tui3/modelservices_test.go b/internal/tui3/modelservices_test.go index e713928899..061967ce4b 100644 --- a/internal/tui3/modelservices_test.go +++ b/internal/tui3/modelservices_test.go @@ -738,8 +738,8 @@ func renamedRelistedApp(t *testing.T, model string) *app { a.adoptModelConnectResult(a.beginModelConnect(first)().(modelConnectResultMsg)) a.switchModel("homelab/"+model, 0) - // THE RENAME: an edit draft whose Written moved, exactly what the name step - // builds on an answer that differs from the stored one. + // THE RENAME: an edit draft whose Written moved, exactly what the name + // step builds on an answer that differs from the stored one. persisted := config.PersistedSources(dir) if len(persisted) != 1 { t.Fatalf("the connect did not persist exactly one row: %+v", persisted) @@ -1908,7 +1908,7 @@ func TestASettleWithNothingToSpendLeavesTheConnectPanelWhereItWas(t *testing.T) } // customConnectionApp is the picker-grouping fixture: the default service plus -// the two custom connections homelab (id custom) and studio (id custom-studio), +// the two custom connections homelab (id custom) and a second custom service (id custom-studio), // in persisted order, with each connection's own model list served from held by // the connection id. A connection missing from held has no model list, which is // the empty group the notice row stands for. diff --git a/internal/tui3/narrow_test.go b/internal/tui3/narrow_test.go index 9e06411539..20b8dee637 100644 --- a/internal/tui3/narrow_test.go +++ b/internal/tui3/narrow_test.go @@ -307,13 +307,8 @@ func pulseLab(t *testing.T) (*app, time.Time) { // THE TOP LINE GIVES THINGS UP IN THE OWNER'S ORDER. // -// The places and the pulse share the first row now, and the owner ruled the -// order a narrowing row gives things up in (2026-09-24): the clock first, with -// the machine's name, then the counts (the moving one before the one that -// wants you), then the allowance behind the day's figure, then the trailing -// places fold into `more ▾`, and the day's figure is the last clause standing. -// Every width is checked: a thing given up early may never be on the row while -// a thing given up later is gone, and every rung of the ladder is met. +// Every width is checked: a thing given up early may never be on the row while a thing +// given up later is gone, and every rung of the ladder is met. func TestTheTopLineGivesThingsUpInTheOwnersOrder(t *testing.T) { a, now := pulseLab(t) a.showPage(pageNone) diff --git a/internal/tui3/notice.go b/internal/tui3/notice.go index 0db586d10f..355bc7a2ae 100644 --- a/internal/tui3/notice.go +++ b/internal/tui3/notice.go @@ -34,17 +34,15 @@ import ( // The channel exists and is empty; a wave that ships something registers a // row with [notice.news] set and writes nothing else. // -// ONE TABLE, TWO BOXES, TWO RULES. Until 2026-09-22 a hint row named which box -// it could draw beside; the owner ruled that there is ONE set of tips, and the -// two boxes say them by rules of their own, because a conversation is a screen -// you sit in and home is a screen you pass through. A CONVERSATION RANKS: the -// first eligible row in the table's order takes the foot, so a tip that has -// just become true is said at once — `/compact summarizes the conversation -// now` when the window crosses half, not forty minutes later — and -// [noticeGap] keeps a busy first session from reading as a slideshow -// ([noticeBoard.rank]). HOME TAKES TURNS: every tip that is true gets one, the -// row moving on with every visit and every [hintEvery] at rest -// ([noticeBoard.rotate]). Both go through [noticeBoard.pick]. +// ONE TABLE, TWO BOXES, TWO RULES. Until 2026-09-22 a hint row named which box it could +// draw beside; there is ONE set of tips, and the two boxes say them by rules of their own, +// because a conversation is a screen you sit in and home is a screen you pass through. A +// CONVERSATION RANKS: the first eligible row in the table's order takes the foot, so a tip +// that has just become true is said at once — `/compact summarizes the conversation now` +// when the window crosses half, not forty minutes later — and [noticeGap] keeps a busy +// first session from reading as a slideshow ([noticeBoard.rank]). HOME TAKES TURNS: every +// tip that is true gets one, the row moving on with every visit and every [hintEvery] at +// rest ([noticeBoard.rotate]). Both go through [noticeBoard.pick]. // // THE TABLE BELOW IS THE ONE PLACE A NOTICE IS WRITTEN DOWN, the way commands.go // is the one place a command is. [checkNotices] runs over it at init and fails @@ -324,20 +322,10 @@ var ( // and the page say the same words — and notice_test.go holds the page to every // line here, so the table cannot say a thing the manual does not. // -// TWENTY-THREE ROWS, AND EVERY CUT WAS DELIBERATE. A survey of the surface on -// 2026-09-21 turned up forty-eight lines worth saying; thirty of those shipped, -// /project made thirty-one when it became a command of its own on 2026-09-22, -// and three reads of the whole list by the owner that same day took it to -// twenty-two; the way home by two spaces made it twenty-three on 2026-09-24, -// at the owner's word. `alt+3`, `alt+1`–`alt+7`, `/search` and `/subharness` came off -// as rows the foot or the tab bar already teaches; the two lines about a -// running answer became one; `/ask`'s came off ahead of the door it taught; -// `/folder`'s came off because it was not true and /attach's line now covers -// both kinds; the second /attach row was one row too many about one command; -// and `ctrl+.` came off on the owner's word. What was left out is -// what the foot already names — `alt+p`, `alt+e`, `alt+a`, `alt+k`, `/` — and -// the second spelling of anything already here. `/ shows every command` was a -// row until both feet started saying `/ commands` outright (footswap.go). +// TWENTY-THREE ROWS, AND EVERY CUT WAS DELIBERATE. What was left out is what the foot +// already names — `alt+p`, `alt+e`, `alt+a`, `alt+k`, `/` — and the second spelling of +// anything already here. `/ shows every command` was a row until both feet started saying +// `/ commands` outright (footswap.go). var notices = []notice{ // ── the rows this surface shipped with ───────────────────────────────── { @@ -405,15 +393,13 @@ var notices = []notice{ // until 2026-09-22 and came off with the command it taught. Asking from // home now uses the ask-here row, so that tip would point at a dead door. { - // THE WAY BACK, AT THE OWNER'S WORD ON 2026-09-24. The controls name - // the door as `space space home` ([app.idleHint]), but a label of three - // words reads as chrome after the first day, and this - // row says what it is in a sentence. It is never armed on home, where - // there is nowhere to go back to, and it retires on the gesture itself - // rather than on reaching home by `/home` or the tab. IT RANKS FIRST of - // the rows a conversation earns by talking, because a person who does - // not know the way back out of a conversation has no use yet for any - // of the commands below it. + // The controls name the door as `space space home` ([app.idleHint]), but a label of + // three words reads as chrome after the first day, and this row says what it is in a + // sentence. It is never armed on home, where there is nowhere to go back to, and it + // retires on the gesture itself rather than on reaching home by `/home` or the tab. IT + // RANKS FIRST of the rows a conversation earns by talking, because a person who does not + // know the way back out of a conversation has no use yet for any of the commands below + // it. id: "home-by-two-spaces", slot: slotHint, armed: awayFromHome, text: "space space takes you back to home", @@ -426,15 +412,10 @@ var notices = []notice{ retire: eventTaskTyped, }, { - // THE BIGGER HALF OF HANDING WORK OUT, at the owner's word on - // 2026-10-19: /task sends one piece of the work away, and the Teams - // dropdown's `+ New from this session` keeps this conversation and makes - // it the manager of a team for the rest (helpers.go). It names the row - // and not /helpers, because /helpers asks a team that already exists. It - // is armed only where the row would act: a conversation that has been - // spoken to, no team selected on the strip, and not already a manager - // ([helpersTipArmed]). It retires the first time the row is chosen or - // /helpers is typed. + // It names the row and not /helpers, because /helpers asks a team that already exists. + // It is armed only where the row would act: a conversation that has been spoken to, no + // team selected on the strip, and not already a manager ([helpersTipArmed]). It retires + // the first time the row is chosen or /helpers is typed. id: "helpers-team", slot: slotHint, armed: helpersTipArmed, text: "+ New from this session in the Teams menu makes this chat a team's manager", @@ -574,11 +555,7 @@ var notices = []notice{ // the keyboard is the one setting a person cannot guess exists until // it has already decided something for them (autonomysheet.go). // - // COPY MODE ITSELF IS NOT GONE, and this row is the only reason to - // think it might be. It was taken out on 2026-09-22 and put back on - // 2026-09-23 at the owner's word — "we don't need a hint, but don't - // remove the feature" — so `ctrl+b`, `/copy` and the frozen viewport - // all work and simply have no row here. + // COPY MODE ITSELF IS NOT GONE, and this row is the only reason to think it might be. id: "autonomy-rule", slot: slotHint, armed: spoken, text: "/autonomy sets how questions are handled while you are away", @@ -709,14 +686,13 @@ type noticeBoard struct { // counted from it when the tip leaves or the row goes out of sight // ([noticeBoard.settle]), and only if it stood [noticeReadTime]. since [noticeSlots]time.Time - // hidden is the cross on a tip row having been pressed: the row draws - // nothing at all until HOME ITSELF GOES OUT OF VIEW ([app.dropHome]), or - // for a conversation's row until the conversation does - // ([app.liftChatTipCross]), which is the only thing that lifts it. Deciding the slot again does not - // lift it, and neither does the two-minute beat: a cross answered with - // another sentence on the same screen is the surface talking over somebody - // who asked it to stop (the owner's ruling, 2026-09-22). It is this - // session's and never the ledger's — putting a tip away is not using it. + // hidden is the cross on a tip row having been pressed: the row draws nothing at all + // until HOME ITSELF GOES OUT OF VIEW ([app.dropHome]), or for a conversation's row until + // the conversation does ([app.liftChatTipCross]), which is the only thing that lifts it. + // Deciding the slot again does not lift it, and neither does the two-minute beat: a cross + // answered with another sentence on the same screen is the surface talking over somebody + // who asked it to stop. It is this session's and never the ledger's — putting a tip away + // is not using it. hidden [noticeSlots]bool // ── THE CONVERSATION'S HALF ──────────────────────────────────────────── @@ -815,13 +791,12 @@ type noticeCandidate struct { // returns "" for nothing, and it changes nothing on the board but the // [noticeBoard.advance] it spends — [noticeBoard.take] records the decision. // -// TWO BOXES, TWO RULES, ONE LIST (the owner's ruling, 2026-09-22). Home's row -// is a ROTATION and the conversation's is a RANKING, because the two rows are -// read in different ways: home is a screen somebody passes through, where -// every tip should get its turn; a conversation is a screen somebody sits in, -// where the tip worth saying is the one about what is happening RIGHT NOW. -// The conversation's rule is the one this surface shipped with and is restored -// here after a build that put it on the rotation with home. +// TWO BOXES, TWO RULES, ONE LIST. Home's row is a ROTATION and the conversation's is a +// RANKING, because the two rows are read in different ways: home is a screen somebody +// passes through, where every tip should get its turn; a conversation is a screen somebody +// sits in, where the tip worth saying is the one about what is happening RIGHT NOW. The +// conversation's rule is the one this surface shipped with and is restored here after a +// build that put it on the rotation with home. func (b *noticeBoard) pick(slot noticeSlot, cands []noticeCandidate, turn int) string { if slot == slotHint { return b.rank(cands, turn) @@ -1192,24 +1167,9 @@ func (a *app) noticeHomeQuiet() bool { a.paneExchange() == nil && !a.targetPickShowing() && !a.composer.open && !a.hopShowing() } -// noticeDismiss is the cross on a tip row, and what it means is ENOUGH OF -// THESE FOR NOW — not "say something else". The row goes blank and STAYS -// blank for the rest of this sitting: on home, until home is left and come -// back to; in a conversation, until the conversation is left and come back to -// ([noticeBoard.hidden] names both, and they are the same law — the cross is -// lifted by the row's screen going out of view). -// -// THE OWNER'S RULING, 2026-09-22: "do not show another hint until the user -// comes back to the home tab after leaving it". A cross answered with a second -// sentence in the same breath is the surface talking over somebody who has -// just asked it to stop. -// -// AND THE TIP THAT WAS PUT AWAY KEEPS ITS WHOLE ALLOWANCE. Its standing is -// thrown away rather than counted: a person who pressed the cross was telling -// the surface they did not want to read that line now, which is the opposite -// of having read it, and spending a showing on the gesture would retire a tip -// six dismissals in. The slot is asked to advance, so the row that comes back -// is a different one and this tip takes its turn again later in the ring. +// A new hint is shown only after the person returns home or sends another +// message. Updating the hint every few seconds would distract from the current +// work. func (a *app) noticeDismiss(slot noticeSlot) { b := &a.notices if b.seen == nil { @@ -1295,10 +1255,9 @@ func (a *app) chatTipReady() string { if a.notices.hidden[slotHint] || a.at(pageHome) { return "" } - // THE CLOSED SIDE COLUMN IS NOT ONE OF THOSE STATES. `alt+l tasks` is what - // the keys row says at rest once the column is put away ([app.sideBackHint]), - // and a tip that went quiet whenever it did was a tip that only ever - // appeared with the sidebar open (the owner's report, 2026-09-24). + // THE CLOSED SIDE COLUMN IS NOT ONE OF THOSE STATES. `alt+l tasks` is what the keys row + // says at rest once the column is put away ([app.sideBackHint]), and a tip that went + // quiet whenever it did was a tip that only ever appeared with the sidebar open. if word := a.hintWord(); a.questionRoomOpen() || (word != "" && word != a.sideBackHint()) || (a.chordLost && a.chords.meta == chordMetaWord) { return "" diff --git a/internal/tui3/offlooplaw_test.go b/internal/tui3/offlooplaw_test.go index b0009f781c..fecca6ee54 100644 --- a/internal/tui3/offlooplaw_test.go +++ b/internal/tui3/offlooplaw_test.go @@ -113,7 +113,7 @@ func engineDoors(t *testing.T) map[string]bool { // doorsStillOnTheLoop is the DEBT this law NAMES rather than hides. // -// THE ANSWER ROAD IS CLOSED AND THE REST OF THE SURFACE IS NOT. This lane fixed +// THE ANSWER ROAD IS CLOSED AND THE REST OF THE SURFACE IS NOT. this test fixed // the road a QUESTION'S ANSWER travels — every `Resolve…`, the dial, the record // a switch rebuilds from — because that is where the ten-second freeze was // measured and where a stalled call costs a person a decision rather than a diff --git a/internal/tui3/onboarding.go b/internal/tui3/onboarding.go index e49ea92e24..52ce64da4e 100644 --- a/internal/tui3/onboarding.go +++ b/internal/tui3/onboarding.go @@ -1869,15 +1869,11 @@ func setupShowcaseCount(at, count int) string { // beats of typing and one per line. It plays when an example arrives — on // reaching this screen, on ←/→, and on the turn — and then it is still. // -// THE TURN is the second clock. Left alone, the panel shows the next example -// every [setupTurnEvery], round and round, so a person reading the form sees -// all five without touching anything; ←/→ browse them by hand. ANY KEY HOLDS -// THE CLOCK for a full [setupTurnEvery] from that key, so the panel never -// turns under a person who is typing an amount or walking the rows, and -// browsing by hand is not raced by the clock. Until 2026-10-01 the design -// refused a carousel here and moved the example with the focus instead; new -// people read that as the panel jumping about as they walked the rows, and -// the owner asked for the clock. +// THE TURN is the second clock. Left alone, the panel shows the next example every +// [setupTurnEvery], round and round, so a person reading the form sees all five without +// touching anything; ←/→ browse them by hand. ANY KEY HOLDS THE CLOCK for a full +// [setupTurnEvery] from that key, so the panel never turns under a person who is typing an +// amount or walking the rows, and browsing by hand is not raced by the clock. // // AND ANY OTHER KEY SETTLES IT AT ONCE. Typing an amount, narrowing the model // list, opening a chooser — every one of those jumps the panel straight to its diff --git a/internal/tui3/onetaskpage_test.go b/internal/tui3/onetaskpage_test.go index 8b71f7050e..a6843fd707 100644 --- a/internal/tui3/onetaskpage_test.go +++ b/internal/tui3/onetaskpage_test.go @@ -1,11 +1,7 @@ package tui3 -// ONE TASK PAGE. The owner's ruling on the two pages a task could open — the -// task room for a node of this window's graph, and a store-backed page for a -// task on the run engine that looked like the room and was not one — was that -// they should be the same. These tests hold the ruling: a task on either -// engine opens the same room with the same two tabs, and a line typed into a -// run's task's room reaches its store as a note. +// A task on either engine opens the same room with the same two tabs. A line +// typed into a run task room reaches its store as a note. import ( "strings" @@ -14,7 +10,8 @@ import ( tea "charm.land/bubbletea/v2" ) -// roomTrailText is the room's trail row as it is drawn, without its inks. +// A task on either engine opens the same room with the same two tabs. A line +// typed into a run task room reaches its store as a note. func roomTrailText(t *testing.T, a *app) string { t.Helper() frame, _, _ := a.frame() @@ -32,11 +29,11 @@ func TestANewEngineTaskAndAnOlderEngineTaskOpenTheSameRoomWithTheSameTabs(t *tes stored bool work string }{ - // A task on the run engine has a page in the store; its work tab reads - // the run's working copy, which this fixture's engine has no door onto. + // A task on either engine opens the same room with the same two tabs. A line + // typed into a run task room reaches its store as a note. {name: "new engine", stored: true, work: "this engine does not read the run's working copy"}, - // A task on the older engine has none, and opens the room it always did; - // its work tab lists the files its record says it wrote. + // A task on either engine opens the same room with the same two tabs. A line + // typed into a run task room reaches its store as a note. {name: "older engine", stored: false, work: "the files this task changes are listed here when it lands"}, } { t.Run(tc.name, func(t *testing.T) { diff --git a/internal/tui3/openseam_test.go b/internal/tui3/openseam_test.go index 585845d107..82894f9fd9 100644 --- a/internal/tui3/openseam_test.go +++ b/internal/tui3/openseam_test.go @@ -26,7 +26,7 @@ func (*seamHistory) Append(string, string) {} func (*seamHistory) RecentFor(string, int) []history.Entry { return nil } func (*seamHistory) Recent(int) []history.Entry { return nil } -// TestAnAlwaysAfterNewReachesTheConversationInFront is this lane's proof. +// TestAnAlwaysAfterNewReachesTheConversationInFront is this test's proof. // // THE BUG IT REPRODUCES. The consent card's "always" does two things: it writes // the rule into the person's profile, and it hands the gate the running session @@ -36,7 +36,7 @@ func (*seamHistory) Recent(int) []history.Entry { return nil } // session that /new had just closed. The card said `saved`, it was saved, and // the very next call asked again, with nothing on screen to connect the two. // -// It cannot be written against the code this lane replaces, and that is the +// It cannot be written against the code this test replaces, and that is the // shape of the fault rather than a gap in the test: before [Options.Start] there // was exactly ONE save seam on the whole surface and no way for a second // conversation to carry its own, so there was nothing for an assertion to diff --git a/internal/tui3/pages.go b/internal/tui3/pages.go index bfedc54fd1..55ac04bd35 100644 --- a/internal/tui3/pages.go +++ b/internal/tui3/pages.go @@ -247,13 +247,12 @@ type place interface { caretRow(a *app, width int, rows []placeRow) (row, column int, drawn bool) // box is the editor this place types into, and nil where it has none. // - // ONLY HOME HAS A BOX THAT SENDS ANYTHING (the owner's ruling, 2026-09-17). - // Tasks and memory keep an editor because typing there FILTERS or - // SEARCHES, and each of them draws its own letters in its own body; the - // automations and spend places take no text at all, and the foot under - // every place but home draws no box. The shared composer that used to sit under - // all seven — `enter talk about it · alt+enter send it off as a task` — was a - // box on six pages where `enter` opened a row and the sentence went nowhere. + // ONLY HOME HAS A BOX THAT SENDS ANYTHING. Tasks and memory keep an editor because typing + // there FILTERS or SEARCHES, and each of them draws its own letters in its own body; the + // automations and spend places take no text at all, and the foot under every place but + // home draws no box. The shared composer that used to sit under all seven — `enter talk + // about it · alt+enter send it off as a task` — was a box on six pages where `enter` + // opened a row and the sentence went nowhere. box(a *app) *editor // note is the one line a place may say about what it is HOLDING, drawn under // the rule and above the composer. @@ -651,7 +650,7 @@ func (a *app) barChipWord(id page, numbered bool) string { } // placeMachineLead is the word in front of the machine's name on the nav's far -// end. It is there so that a bare `spark` on the row the places are drawn in +// end. It is there so that a bare `laptop` on the row the places are drawn in // cannot be read as one more place. const placeMachineLead = "on " @@ -808,10 +807,9 @@ func (a *app) barReach() bool { if pl == nil || a.bar.on || a.tabRow < 0 { return false } - // HOME'S COLUMN HAS NO WAY UP ONTO THE BAR (owner, 2026-09-17: "don't let - // users scroll up out of the left column onto the tabs"). `↑` at the top of - // the field stays where it is; the bar is reached by a press on it, `tab`, - // or a place's own chord. Every other place keeps the walk. + // HOME'S COLUMN HAS NO WAY UP ONTO THE BAR. `↑` at the top of the field stays where it + // is; the bar is reached by a press on it, `tab`, or a place's own chord. Every other + // place keeps the walk. if pl.id() == pageHome { return false } @@ -1490,12 +1488,11 @@ func scopeAddress(line homeLine) string { // The sentences the router says. Each is quoted in the manual exactly as it is // spelled here. const ( - // placeRestWord is what home's box row says with nothing typed into it: the - // promise the foot used to open with. It said `say what you want done` on - // every place until 2026-09-17, when the box came off every place but home - // and the owner ruled that the one box left says what it is for — both of - // its readings, the search and the start — and the foot under it keeps - // only the draft controls ([app.targetChordWords]). + // placeRestWord is what home's box row says with nothing typed into it: the promise the + // foot used to open with. It said `say what you want done` on every place until + // 2026-09-17, when the box came off every place but home and the one box left says what + // it is for — both of its readings, the search and the start — and the foot under it + // keeps only the draft controls ([app.targetChordWords]). placeRestWord = "type to search or start something new" // placeHintWords is the second line of the composer, AND IT IS THE DESIGN'S // OWN SENTENCE WORD FOR WORD (SCREEN 2b, and FIDELITY.md item 3 quotes it as @@ -2056,12 +2053,9 @@ func (a *app) placeMsgLine(width int) (string, bool) { // // ── EVERY PLACE OPENS, ALWAYS ─────────────────────────────────────────────── // -// This function used to have a second half: a place that refused to open put -// back whatever was standing, and three places refused — tasks with no task in -// the world, standing with nothing standing, memory with no store behind it. The -// owner ran the binary on a fresh machine and found that `alt+2`, `alt+3` and -// `alt+4` did nothing at all, because on a fresh machine all three of those are -// exactly the state a new person is in. +// This function used to have a second half: a place that refused to open put back whatever +// was standing, and three places refused — tasks with no task in the world, standing with +// nothing standing, memory with no store behind it. // // SCREEN 1f'S PREAMBLE IS THE LAW NOW: an almost-empty place is the best teacher // on the machine, so it always opens and spends the whole frame saying what it diff --git a/internal/tui3/pages_test.go b/internal/tui3/pages_test.go index 8652fce6db..0f164be416 100644 --- a/internal/tui3/pages_test.go +++ b/internal/tui3/pages_test.go @@ -670,11 +670,10 @@ func TestAnAmbiguousPrefixOffersNoPlaceAtAll(t *testing.T) { // ── the palette ───────────────────────────────────────────────────────────── -// WAITING ON YOU IS ONE COLOUR ON EVERY SCREEN. Home used to say it in two — a -// violet question hue on the strip and the amber on the finished-needs-your-look -// glyph — and it settled on the amber; since the owner's colour ruling of -// 2026-09-11 the CONVERSATION says it in the same amber too, so `ask` and `warn` -// are one hue wherever either is asked for (styles.go's [palette.ask]). +// WAITING ON YOU IS ONE COLOUR ON EVERY SCREEN. Home used to say it in two — a violet +// question hue on the strip and the amber on the finished-needs-your-look glyph — and it +// settled on the amber; since the CONVERSATION says it in the same amber too, so `ask` and +// `warn` are one hue wherever either is asked for (styles.go's [palette.ask]). func TestWaitingOnYouIsOneColourOnHome(t *testing.T) { a := placeApp(t) pal := a.pal diff --git a/internal/tui3/palette.go b/internal/tui3/palette.go index 8cef1484fe..8d80f9468a 100644 --- a/internal/tui3/palette.go +++ b/internal/tui3/palette.go @@ -620,8 +620,7 @@ func (p *picker) rowUnavailable(at int) bool { // list rows — because the drawing spends extra lines on a group's heading, on // the machines' heading and on a why line, and a window counted in rows // handed the cursor a place the frame never drew: the highlight vanished at -// the bottom of the list and on the frame the menu opened with (owner's -// report, 2026-09-30). [listTop]'s item arithmetic is the other lists' law; +// the bottom of the list and on the frame the menu opened with. [listTop]'s item arithmetic is the other lists' law; // this one is the picker's, because the picker is the list that grows headings. // // THE DRAW'S OWN CALL OWNS THE FINAL PLACEMENT. The keystroke-time calls pass @@ -730,12 +729,11 @@ func (p *picker) rowLines(at int, atTop bool) int { // place saying why there are none yet ([laneUnmeasured]). It draws no number: // the emptiness law is about figures nobody took, and it is kept. // -// It used to refuse to open at all, on the argument that a fold with one dim -// line in it punishes the person for trying. The gesture that punished was the -// one that did NOTHING: the row said `via together` and the key that should -// have shown that machine was dead, while the settings panel's `lane` row -// offered `auto` and `openrouter` for the very same model — two doors onto one -// list disagreeing about what it could do. Owner's report, 2026-09-10. +// It used to refuse to open at all, on the argument that a fold with one dim line in it +// punishes the person for trying. The gesture that punished was the one that did NOTHING: +// the row said `via together` and the key that should have shown that machine was dead, +// while the settings panel's `lane` row offered `auto` and `openrouter` for the very same +// model — two doors onto one list disagreeing about what it could do. // // AND OPENING ONE ASKS FOR ITS SHEET. [lane.WantSheet] hands the name to the // beat that already runs and returns at once — the same door [Agent.SetModel] @@ -2751,12 +2749,10 @@ const ( // the row the cursor is on and the caret in the box — the two things // [picker.foldKey] reads before it decides what `→`, `←` and `tab` mean. // -// IT IS CURSOR-AWARE BECAUSE THE FOLD WAS INVISIBLE WITHOUT IT. The slot used to -// read `enter switch · esc` wherever the cursor stood, and the only mention of -// `→ lanes` was the filter box's placeholder — which vanishes on the first -// typed character, exactly when a person has found their model and wants its -// machines. The owner opened /model, pressed `←` and `→`, and asked how anybody -// changes the provider of a model (2026-09-10). The placeholder has since given +// IT IS CURSOR-AWARE BECAUSE THE FOLD WAS INVISIBLE WITHOUT IT. The slot used to read +// `enter switch · esc` wherever the cursor stood, and the only mention of `→ lanes` was +// the filter box's placeholder — which vanishes on the first typed character, exactly when +// a person has found their model and wants its machines. The placeholder has since given // the keys up altogether ([pickerHint]) and this line carries them. func (p *picker) keysHint() string { before, enter, after := p.keysParts() diff --git a/internal/tui3/panes.go b/internal/tui3/panes.go index 9e8efbca73..aebc301189 100644 --- a/internal/tui3/panes.go +++ b/internal/tui3/panes.go @@ -10,17 +10,12 @@ import ( // ── TWO PANES, SIDE BY SIDE ───────────────────────────────────────────────── // -// ONE WIDTH DECIDES WHETHER A FRAME HOLDS TWO COLUMNS, AND THIS SURFACE ALREADY -// HAD IT. The task column stands beside the conversation from [railSlimFloor] -// up and under it "the transcript is the thing a person came for" (task.go); -// the owner's picks of 2026-09-11 put a question's answers beside the evidence -// of the one the pointer is on at the same width (preview A, page A, "≥100 -// cols") and fold that evidence under its row below it (preview-narrow B). So -// there is one reading of it, [besideFits], and one way to lay two columns out, -// [besides] — the panel and the page both ask here, and neither measures its -// own. (The asker's own two-pane layout block decides by its CONTENT instead: -// its panes stand side by side wherever both fit whole, which is the reason a -// fixed width was only ever standing in for — questionblocks.go.) +// ONE WIDTH DECIDES WHETHER A FRAME HOLDS TWO COLUMNS, AND THIS SURFACE ALREADY HAD IT. So +// there is one reading of it, [besideFits], and one way to lay two columns out, [besides] +// — the panel and the page both ask here, and neither measures its own. (The asker's own +// two-pane layout block decides by its CONTENT instead: its panes stand side by side +// wherever both fit whole, which is the reason a fixed width was only ever standing in for +// — questionblocks.go.) // // A SEAM, NOT A BOX. The two panes are one object split in two, so the line // between them is the frame's own side ([tokens.GFrameSide]) and the rules diff --git a/internal/tui3/pathlink.go b/internal/tui3/pathlink.go index 3f5e204749..92161cf98a 100644 --- a/internal/tui3/pathlink.go +++ b/internal/tui3/pathlink.go @@ -122,7 +122,7 @@ const pathSeenMax = 4096 // It is built through net/url rather than by concatenation because a path is // allowed to contain the characters a URI is not — a space, a '#', a '?' — and // `"file://" + path` hands the terminal a URI that stops at the first one of -// them. The authority is left empty (`file:///Users/...`), which is the form +// them. The authority is left empty (`file:///workspace`), which is the form // every terminal that implements OSC 8 reads; naming a host is a claim about // which machine the file is on, and this pass only ever links files on this one. func fileURI(path string) string { @@ -334,7 +334,7 @@ func (l linker) path(word string) (from, to int, target string, ok bool) { } // pathTrim finds the name inside a word by peeling the punctuation prose wraps -// names in. It is deliberately symmetric and deliberately dumb: it does not try +// names in. It is deliberately symmetric and deliberately simple: it does not try // to match a bracket to its partner, because the word it was handed may be one // fragment of a path a wrap broke in half, and half a path has no partners. // diff --git a/internal/tui3/payload_test.go b/internal/tui3/payload_test.go index cbd0e79f57..683395c507 100644 --- a/internal/tui3/payload_test.go +++ b/internal/tui3/payload_test.go @@ -103,7 +103,7 @@ func TestANoteChipsTheDoorItNames(t *testing.T) { t.Fatalf("the door in a note is not chipped:\n%q", rows[0]) } // AND A WORD THAT ONLY LOOKS LIKE ONE IS NOT PROMISED. The chip's second law - // (slashchip.go) survives the move into this lane. + // (slashchip.go) survives the move into this test. plain := noteRows(a, unknownCommandWord("tsak")) if strings.Contains(plain[0], a.pal.chip("/tsak")) { t.Fatalf("a word this surface refuses was chipped as though it ran:\n%q", plain[0]) diff --git a/internal/tui3/phase.go b/internal/tui3/phase.go index 4c7f659ab3..c1dae19304 100644 --- a/internal/tui3/phase.go +++ b/internal/tui3/phase.go @@ -100,18 +100,15 @@ type newsMsg struct{} // an address, which is why keying by it let two nodes on one model id overwrite // each other (see the header). // -// THE CONVERSATION'S OWN NEWS IS FILED UNDER THE CONVERSATION, AND UNDER ITS -// MODEL BESIDE IT. The conversation is the empty subject by the engine's own -// compatibility bargain ([provider.PhaseNews.Subject]), and it used to be filed -// under its model and nothing else. That was an address again, and the address -// moved while the identity did not: a model picked mid-turn changes this -// window's id at once while the engine finishes the turn on the old one, a -// stream-cut hop answers on another model, and a model changed from another -// window reaches the connection without reaching this window's field. Each -// filed the rate and the machine under a name nobody here was asking for, and -// the owner read it as `via` and tok/s vanishing at random. The conversation's -// id ([provider.PhaseNews.Session], the engine's own [session.Agent.NewsKey]) is -// what every one of those keeps, so it is the first name. +// THE CONVERSATION'S OWN NEWS IS FILED UNDER THE CONVERSATION, AND UNDER ITS MODEL BESIDE +// IT. The conversation is the empty subject by the engine's own compatibility bargain +// ([provider.PhaseNews.Subject]), and it used to be filed under its model and nothing +// else. That was an address again, and the address moved while the identity did not: a +// model picked mid-turn changes this window's id at once while the engine finishes the +// turn on the old one, a stream-cut hop answers on another model, and a model changed from +// another window reaches the connection without reaching this window's field. The +// conversation's id ([provider.PhaseNews.Session], the engine's own +// [session.Agent.NewsKey]) is what every one of those keeps, so it is the first name. // // THE MODEL COPY IS THE COMPATIBILITY BARGAIN AND NOT A SECOND OPINION. An older // peer across a connection sends no conversation at all, and a window that @@ -487,12 +484,9 @@ func phaseWords(news PhaseNews, now time.Time) string { // in one place: a phase's parts, which of them leads, and what each of them is // worth when the row runs out. // -// THE ORDER IS THE DATA HIERARCHY the owner asked for — the machine's name, then -// the phase and its clock and whatever the build will do about it, then the -// rate. A field is never cut, only said shorter: "3.1s" is "first word 3.1s" -// with the label taken off, where a clip at the same width would leave -// "first word 3.…", which is a fact about nothing. The fitting itself belongs to -// rowfit.go and is not repeated here. +// A field is never cut, only said shorter: "3.1s" is "first word 3.1s" with the label +// taken off, where a clip at the same width would leave "first word 3.…", which is a fact +// about nothing. The fitting itself belongs to rowfit.go and is not repeated here. // // TWO SPELLINGS OF A CLOCK, and the difference is what the number is for. The // phases a person is WAITING THROUGH with nothing arriving — the handshake and diff --git a/internal/tui3/place_sessions.go b/internal/tui3/place_sessions.go index ca8b99fd4a..7b59a0b1bb 100644 --- a/internal/tui3/place_sessions.go +++ b/internal/tui3/place_sessions.go @@ -1550,11 +1550,10 @@ func tasksTop(lines []tasksLine, cursor, top, room int) int { // note is the one line the place says on its rule, and it says ONE THING: that // the query has emptied the page. // -// THE COUNT IS OFF THE RULE. It used to read `9 finished today · 191 earlier` -// there, and the body already says every one of those numbers on its section -// headings — the same partition, a few rows up, on a page a person is looking -// at (the owner's ruling, 2026-09-17). A figure said twice on one frame is the -// defect the model's colon suffix made once (effortchip.go). +// THE COUNT IS OFF THE RULE. It used to read `9 finished today · 191 earlier` there, and +// the body already says every one of those numbers on its section headings — the same +// partition, a few rows up, on a page a person is looking at. A figure said twice on one +// frame is the defect the model's colon suffix made once (effortchip.go). // // THE FILTER IS NOT SAID BACK HERE EITHER. This line used to carry `filter · // zzz` because the box a person was typing into was invisible, so the only diff --git a/internal/tui3/place_tasks_test.go b/internal/tui3/place_tasks_test.go index 308cc9fd4e..12e9d179d3 100644 --- a/internal/tui3/place_tasks_test.go +++ b/internal/tui3/place_tasks_test.go @@ -256,8 +256,7 @@ func openTaskPlaceWithRows(a *app) bool { a.showPage(pageTasks) // AND IT OPENS THE FOLDS, because these tests are about the ROWS. // - // The place itself opens every conversation and every family SHUT (the owner's - // ruling, 2026-09-11 — [tasksReading.opens] states it and says why), so a test + // The place itself opens every conversation and every family SHUT, so a test // written to look at a piece of work would be looking at the root standing // over it instead. A person reaches the same page with `→`; a test says so by // calling this. The tests that are about the FOLDS ask for the place without diff --git a/internal/tui3/placebar_test.go b/internal/tui3/placebar_test.go index 98872ba648..c2417ab7b1 100644 --- a/internal/tui3/placebar_test.go +++ b/internal/tui3/placebar_test.go @@ -31,10 +31,9 @@ func barTop(t *testing.T, a *app) { for i := 0; i < len(pl.stops(a))+3 && !a.bar.on; i++ { drive(t, a, key("up")) } - // HOME HAS NO WAY UP ONTO THE BAR (owner, 2026-09-17; pages.go's - // [app.barReach]): `↑` stays in the field there, and the bar is reached by - // a press, `tab` or a chord. A test that wants the cursor on home's bar - // raises it the way a press would, after proving the walk did not. + // HOME HAS NO WAY UP ONTO THE BAR: `↑` stays in the field there, and the bar is reached + // by a press, `tab` or a chord. A test that wants the cursor on home's bar raises it the + // way a press would, after proving the walk did not. if !a.bar.on && a.at(pageHome) { a.barRaise() a.frame() diff --git a/internal/tui3/placeeverymouse_test.go b/internal/tui3/placeeverymouse_test.go index 74b353bb96..1b26411048 100644 --- a/internal/tui3/placeeverymouse_test.go +++ b/internal/tui3/placeeverymouse_test.go @@ -52,9 +52,6 @@ func TestClickingATabWordWorksFromEveryPlace(t *testing.T) { } // THE WHEEL IS `↑↓` UNDER THE POINTER, on every place and by the same distance. -// A wheel that moved a different number of rows per room — or none at all in -// some of them — would be one gesture with seven meanings, which is what the -// owner met when they turned it over the built binary. func TestTheWheelMovesListPlacesCursorAndLeavesTeamsFocusAlone(t *testing.T) { for _, place := range everyPlaceTable() { t.Run(place.id.word(), func(t *testing.T) { diff --git a/internal/tui3/placeeveryone_test.go b/internal/tui3/placeeveryone_test.go index 78920a755f..d6aed1935f 100644 --- a/internal/tui3/placeeveryone_test.go +++ b/internal/tui3/placeeveryone_test.go @@ -231,7 +231,7 @@ func settingsPlaceLab(t *testing.T) *app { // everyEmptyPlace is each place that can hold nothing, opened on a machine // that has put nothing in it. Settings is absent because it is never empty, and -// home because its empty panels are lane G's and are pinned beside the grid. +// home because its empty panels are pinned beside the grid. func everyEmptyPlace() []everyPlace { opened := func(id page) func(t *testing.T) *app { return func(t *testing.T) *app { diff --git a/internal/tui3/placehost_test.go b/internal/tui3/placehost_test.go index d0df9e108d..49c9daadaf 100644 --- a/internal/tui3/placehost_test.go +++ b/internal/tui3/placehost_test.go @@ -123,10 +123,7 @@ func TestTheTabBarNamesTheMachineOverHostAndNeverAtHome(t *testing.T) { } } -// The tasks place over --host draws THE FAR MACHINE'S work and not one row of -// this one's. It is the owner's own report, turned into a test: they attached to -// spark, pressed the tasks tab, and read "work codeaf ran on its own. 8, $22.54 -// of it." — the laptop's eight tasks and the laptop's money. +// The tasks place over --host draws THE FAR MACHINE'S work and not one row of this one's. func TestTheTasksPlaceOverHostDrawsTheFarMachinesWork(t *testing.T) { a := hostedPlaceLab(t) now := time.Now() diff --git a/internal/tui3/placelaws_test.go b/internal/tui3/placelaws_test.go index 30c68a1482..4809002396 100644 --- a/internal/tui3/placelaws_test.go +++ b/internal/tui3/placelaws_test.go @@ -91,10 +91,7 @@ func TestNothingSwitchesOnAPageIdOutsideTheRegistry(t *testing.T) { // LAW 2 · EVERY PLACE IS REGISTERED ONCE AND IS IN THE TAB ORDER. // -// The registry and [placeOrder] are two lists that have to be the same list. A -// place in the registry and not in the order is a room with no tab and no -// number; a place in the order and not in the registry is a tab that opens -// nothing, which is exactly what the owner met on a fresh machine. +// The registry and [placeOrder] are two lists that have to be the same list. func TestEveryPlaceIsRegisteredOnceAndInTabOrder(t *testing.T) { if len(placeRegistry) != len(placeOrder) { t.Fatalf("%d places are registered and %d are on the bar", len(placeRegistry), len(placeOrder)) diff --git a/internal/tui3/placemouse.go b/internal/tui3/placemouse.go index 375f8b8e82..973ee9da4d 100644 --- a/internal/tui3/placemouse.go +++ b/internal/tui3/placemouse.go @@ -136,14 +136,8 @@ func placeHoverMoved(at, cursor *int, next, row int, a *app) bool { // walkPage is `tab` and `shift+tab`: the next place, and round again from the // last. // -// IT USED TO ASK WHETHER THE NEXT ROOM WOULD LET IT IN. Tasks refused on a -// machine that had run no work and standing refused with no orders on it, so -// `tab` walked into the refusal, was put straight back where it started, and did -// it again on the next press — on a fresh machine the circle had one member and -// the key read as broken, which is what the owner met ("left right does not seem -// to move tabs, only shift does", shift+tab happening to land on settings, which -// always opened). The walk answered it by asking a `pageReady` before turning any -// handle. +// IT USED TO ASK WHETHER THE NEXT ROOM WOULD LET IT IN. The walk answered it by asking a +// `pageReady` before turning any handle. // // EVERY ROOM OPENS NOW (pages.go's [app.showPage]), so there is nothing to ask: // the next place is the next place, and a room with nothing in it spends the diff --git a/internal/tui3/placeprose.go b/internal/tui3/placeprose.go index f9b2f9ac9b..ede9db53c5 100644 --- a/internal/tui3/placeprose.go +++ b/internal/tui3/placeprose.go @@ -26,14 +26,11 @@ func placeMoneyInk(pal palette) func(string) string { return pal.money } // (homepanel_needs.go), spelled once here because the group line, the fold and // the manual all quote it. // -// THE WORD IS THE WHOLE EXPLANATION. The difference between a row that has -// stopped a conversation and a landing nobody has looked at used to be spelled -// under every landing — `landed unchecked · enter to look`, the same sub-line on -// nine rows (owner, 2026-09-11) — then once, as a clause at the group line's -// right margin (`finished, nobody has checked it`). The owner cut the clause on -// 2026-09-15: `unread` says it in one word, the way a mailbox does, and the -// group line carries neither a clause nor a count. The rows under it are one -// line each. +// THE WORD IS THE WHOLE EXPLANATION. The difference between a row that has stopped a +// conversation and a landing nobody has looked at used to be spelled under every landing — +// `landed unchecked · enter to look`, the same sub-line on nine rows — then once, as a +// clause at the group line's right margin (`finished, nobody has checked it`). The rows +// under it are one line each. const needsCheckWord = "unread" // ── THE FIVE-LEVEL SCALE (SCREEN 2a) ──────────────────────────────────────── diff --git a/internal/tui3/placewalk_test.go b/internal/tui3/placewalk_test.go index dc9af16b70..16e9d3c53d 100644 --- a/internal/tui3/placewalk_test.go +++ b/internal/tui3/placewalk_test.go @@ -8,12 +8,10 @@ import ( // WALKING BETWEEN THE PLACES. // -// The owner's report against the real binary: "in home left right does not seem -// to move tabs, only shift does". The cause was not the arrows — it was `tab` -// walking into the tasks place, being refused because this machine had run no -// work, and being put straight back on home. Every press did that, so the -// circle had one member and `shift+tab` (which lands on settings, and settings -// always opened) was the only key that appeared to work. +// The cause was not the arrows — it was `tab` walking into the tasks place, being refused +// because this machine had run no work, and being put straight back on home. Every press +// did that, so the circle had one member and `shift+tab` (which lands on settings, and +// settings always opened) was the only key that appeared to work. // // THE WALK ANSWERED IT BY STEPPING PAST A SHUT ROOM. Then the refusals went // (pages.go's [app.showPage]), and with them the idea of a shut room — so the diff --git a/internal/tui3/planrail.go b/internal/tui3/planrail.go index 167d536772..a97a814f42 100644 --- a/internal/tui3/planrail.go +++ b/internal/tui3/planrail.go @@ -2,12 +2,11 @@ package tui3 // planrail.go draws A RUN'S TASKS THE WAY EVERY OTHER TASK IS DRAWN. // -// A run's parts are rows of its plan store and not nodes of this window's graph, -// and for a while they had a renderer of their own: a still half-circle where -// every other working row has the spinner, no handle, no clock and price line, -// and the finished parts of a family folded into one `✓ N done` count. Two -// shapes for one kind of thing is a column a person has to learn twice, and the -// owner's ruling on it was plain — every task looks the same. +// A run's parts are rows of its plan store and not nodes of this window's graph, and for a +// while they had a renderer of their own: a still half-circle where every other working +// row has the spinner, no handle, no clock and price line, and the finished parts of a +// family folded into one `✓ N done` count. Two shapes for one kind of thing is a column a +// person has to learn twice, and on it was plain — every task looks the same. // // SO THERE IS ONE RENDERER AND THIS FILE IS ITS ADAPTER. A store row is lent a // [taskNode] ([planRailNode]) carrying only what the store knows — its title, diff --git a/internal/tui3/planroom.go b/internal/tui3/planroom.go index 8251ea0496..87b1a28f79 100644 --- a/internal/tui3/planroom.go +++ b/internal/tui3/planroom.go @@ -4,8 +4,7 @@ package tui3 // // A task on the run engine is a row of the run's plan store and not a node of // this window's graph: it has no journal and no live lane, and for a while it -// opened a page of its own that looked like the room and was not one. The owner -// ruled that the two should be the same page, so there is ONE PAGE TYPE and +// opened a page of its own that looked like the room and was not one. The two use ONE PAGE TYPE and // this file is its second source. A run's task opens the same [taskRoom], with // the same head, the same transcript renderer, the same box and the same keys; // what changes is where the page READS from. diff --git a/internal/tui3/programbadge.go b/internal/tui3/programbadge.go index f18c22e50e..9f05fcc9f7 100644 --- a/internal/tui3/programbadge.go +++ b/internal/tui3/programbadge.go @@ -3,13 +3,11 @@ package tui3 // THE PROGRAM'S BADGE: how a person tells work handed to a program codeaf // carries — senior-dev — from a task this conversation's own worker does. // -// The two looked the same everywhere a task is named. A senior-dev run and an -// ordinary `/task` drew the same first line on the side list — a state glyph, a -// title, a handle — and the card a person approved said `wants to start a -// task:` for both, so the one thing about the work that decides what it will do -// and how long it will take was not on the screen at all. The owner asked for a -// prominent badge like `[senior-dev]` on the task's row, none on an ordinary -// task's, and a badge of its own for every program that comes after it. +// The two looked the same everywhere a task is named. A senior-dev run and an ordinary +// `/task` drew the same first line on the side list — a state glyph, a title, a handle — +// and the card a person approved said `wants to start a task:` for both, so the one thing +// about the work that decides what it will do and how long it will take was not on the +// screen at all. // // SO THE BADGE IS THE PROGRAM'S NAME IN BRACKETS, AND NOTHING ELSE MAKES IT. A // program's [session.TaskNotice.Program] is the name its own command row says @@ -20,15 +18,10 @@ package tui3 // hyphen-separated parts — `[sd]`, `[dw]` for a doc-writer — which is what a // twenty-four-cell column can afford. // -// THE BRACKETS ARE ALWAYS DRAWN. The badge is painted in the accent, bold, -// because the owner asked for it to be prominent and the accent is this -// surface's one loud voice (docs/DESIGN-LANGUAGE.md's accent budget: it marks -// the live or chosen thing, and a program's work is the one row on a column that -// is a different kind of thing) — but ink is not always there to be read. A -// terminal with no colour draws none; a row somebody is standing in is laid on -// the selected ground, which swallows a chip's; and a screen reader reads words. -// The brackets are what is left in all three, so they are part of the badge and -// never decoration around it ([session.ProgramBadge] spells them once). +// THE BRACKETS ARE ALWAYS DRAWN. A terminal with no colour draws none; a row somebody is +// standing in is laid on the selected ground, which swallows a chip's; and a screen reader +// reads words. The brackets are what is left in all three, so they are part of the badge +// and never decoration around it ([session.ProgramBadge] spells them once). // // IT IS NEVER A LEAD AND NEVER A TARGET. The badge stands after the title, in // the row's trailing slot — never in front of it, where the column's law keeps diff --git a/internal/tui3/programbadge_test.go b/internal/tui3/programbadge_test.go index 0dad65670d..4ebd92a1e7 100644 --- a/internal/tui3/programbadge_test.go +++ b/internal/tui3/programbadge_test.go @@ -279,13 +279,10 @@ func TestTheRoomPanelAndItsTitleWearTheBadge(t *testing.T) { } } -// A PAGE ONTO ANOTHER CONVERSATION'S WORK WEARS THAT WORK'S BADGE, AND NEVER THE -// ONE A LOCAL TASK OF THE SAME NUMBER WEARS. Task ids restart with every -// conversation, so the page onto their task 7 stands beside this window's own -// task 7 — here a senior-dev run, whose plan row the surface holds. The page's -// header used to fall through to that row by the bare number and draw -// `[senior-dev]` over work no program had; and when the owner said its own work -// was a program's, the page dropped it. +// A PAGE ONTO ANOTHER CONVERSATION'S WORK WEARS THAT WORK'S BADGE, AND NEVER THE ONE A +// LOCAL TASK OF THE SAME NUMBER WEARS. Task ids restart with every conversation, so the +// page onto their task 7 stands beside this window's own task 7 — here a senior-dev run, +// whose plan row the surface holds. func TestAGuestPageWearsItsOwnWorksBadgeAndNeverTheLocalTasks(t *testing.T) { a, _ := planAppWith(t, []session.PlanTaskRow{programRow()}, nil) a.width, a.height = 120, 30 diff --git a/internal/tui3/programbrief.go b/internal/tui3/programbrief.go index b5f4ddb3ad..61fefda954 100644 --- a/internal/tui3/programbrief.go +++ b/internal/tui3/programbrief.go @@ -1,21 +1,10 @@ package tui3 -// programbrief.go draws a program's brief as a DOCUMENT: what `▸ brief` opens on -// a program's room (programroom.go). The brief is the work order codeaf handed -// the program — often thousands of words — and it used to be drawn between the -// head's rules, pinned, cut to half the frame with a count for the rest. The -// owner asked on 2026-09-28 for the whole of it, scrollable and well formatted, -// so while the dropdown is open the brief IS the room's body: the room's own -// scroll reads it, and the steps come back, where they were, when it shuts. -// -// IT IS NOT RENDERED AS MARKDOWN. A brief is a model's plain text about files, -// and markdown would read `__init__.py` as bold `init.py` and run a list the -// model wrote one item to a line into one paragraph. What it gets instead is -// the little a document needs: each part of a generated work order under its -// plain heading in bold (taskrequest.go's [requestSections]), every line the -// brief has kept as its own, a blank line between paragraphs, a list item's -// wrapped lines hung under its text rather than its marker, and a line that -// opens in capitals — `DONE WHEN`, `FIRST ACTION:` — with those words in bold. +// programbrief.go draws the program brief as a scrollable document. While its +// dropdown is open, the brief takes the room body and its scroll controls; +// closing it restores the steps at their previous position. Plain-text rendering +// preserves filenames, line breaks and list indentation that Markdown could +// reinterpret. import ( "regexp" diff --git a/internal/tui3/programroom.go b/internal/tui3/programroom.go index 0b02156e40..4a51179a86 100644 --- a/internal/tui3/programroom.go +++ b/internal/tui3/programroom.go @@ -649,21 +649,14 @@ func (a *app) programRoomKey(msg tea.KeyPressMsg) (tea.Cmd, bool) { // ── THE HEAD: ONE TITLE, AND THE BRIEF BEHIND A DROPDOWN ───────────────────── // -// A program's room used to open under two titles: the trail's crumb — the -// conversation's name, which a conversation named after its work spells the -// same as the task — and the task's own bold title under it, and a third in the -// box's `Reading:` label. The owner asked on 2026-09-25 for one: the head is -// the title row alone (the task's name, its badge, the dropdown, the pinned -// facts), and the brief the program was handed is behind the dropdown. The -// way back is `esc`, named on the key line, and the side list's `‹ Back to -// main`. +// A program's room used to open under two titles: the trail's crumb — the conversation's +// name, which a conversation named after its work spells the same as the task — and the +// task's own bold title under it, and a third in the box's `Reading:` label. The way back +// is `esc`, named on the key line, and the side list's `‹ Back to main`. // -// THE OPEN BRIEF IS THE BODY, NOT THE HEAD. It was drawn between the head's -// rules, pinned and cut to half the frame, and a brief of a few thousand words -// — which is what codeaf hands a program — was mostly a count of lines not -// shown. The owner asked on 2026-09-28 for all of it, scrollable: so it takes -// the body the steps were in, the room's wheel and page keys read it, and the -// steps come back where they were (programbrief.go). +// THE OPEN BRIEF IS THE BODY, NOT THE HEAD. It was drawn between the head's rules, pinned +// and cut to half the frame, and a brief of a few thousand words — which is what codeaf +// hands a program — was mostly a count of lines not shown. // programBriefChevron is the dropdown on the title row: shut, or open. func programBriefChevron(open bool) string { diff --git a/internal/tui3/programtab_test.go b/internal/tui3/programtab_test.go index d22acd3296..06172a40b3 100644 --- a/internal/tui3/programtab_test.go +++ b/internal/tui3/programtab_test.go @@ -1,13 +1,7 @@ package tui3 -// A PROGRAM'S TASK OPENS INSIDE THE CONVERSATION'S TAB, and the tab bar keeps -// working while it is open. These tests drive the owner's report of 2026-09-24 -// through the surface's own Update loop: open senior-dev's task by every door a -// person has onto it, then leave it by `esc`, by a press on the conversation's -// tab, and by a press on Home, and read what the FRAME shows after each — how -// many tabs are drawn selected, whether Home is on the bar, and whether the -// program's page is still covering whatever the press chose (tabbar_test.go -// holds the readings and the ordinary room they are held against). +// A PROGRAM'S TASK OPENS INSIDE THE CONVERSATION'S TAB, and the tab bar keeps working +// while it is open. import ( "strings" diff --git a/internal/tui3/projectcmd.go b/internal/tui3/projectcmd.go index bf6c882cc3..7e997956c5 100644 --- a/internal/tui3/projectcmd.go +++ b/internal/tui3/projectcmd.go @@ -2,12 +2,7 @@ package tui3 // /project — WHICH FOLDER THE NEXT CONVERSATION OPENS IN, AND NOTHING ELSE. // -// Until 2026-09-22 this was the home half of `/folder`, and the owner's word -// for that was that `/folder` was doing two different jobs: in a conversation -// it hands the conversation a directory to be about, the way `/attach` hands -// it a file; on home the same word pinned the project the NEXT conversation -// would open in. Two acts behind one command, told apart by which screen you -// happened to be standing on. +// Two acts behind one command, told apart by which screen you happened to be standing on. // // So the pin is its own command now. `/folder` means one thing everywhere — // give this conversation a folder — and typing it on home opens a conversation diff --git a/internal/tui3/providerword_law_test.go b/internal/tui3/providerword_law_test.go index e0ecb80711..30e09a7c7e 100644 --- a/internal/tui3/providerword_law_test.go +++ b/internal/tui3/providerword_law_test.go @@ -14,14 +14,10 @@ import ( // THE PERSON-FACING WORD FOR THE THING BEHIND A MODEL IS `provider`. // -// One model id is served by many machines, and until 2026-09-14 this surface -// called one of them a **lane**: the settings row was labelled `lane`, the -// picker's hint said `→ lanes`, the fold's empty line said `no machine has been -// measured`, and the manual's page was titled Lanes. The wire, OpenRouter's own -// refusals (`provider.only`) and the owner all said **provider**, so a person -// met two words for one thing and only one of them was ever written down -// anywhere they could check. The owner ruled on the word (issue #1023): it is -// `provider`, everywhere a person reads. +// One model id is served by many machines, and until 2026-09-14 this surface called one of +// them a **lane**: the settings row was labelled `lane`, the picker's hint said `→ lanes`, +// the fold's empty line said `no machine has been measured`, and the manual's page was +// titled Lanes. // // THE RULING IS ABOUT VOCABULARY AND NOT ABOUT ARCHITECTURE, which is why this // law reads STRING LITERALS and nothing else. `internal/lane`, `LanePin`, diff --git a/internal/tui3/pulse.go b/internal/tui3/pulse.go index 28389587b3..fc451ccbde 100644 --- a/internal/tui3/pulse.go +++ b/internal/tui3/pulse.go @@ -53,11 +53,7 @@ package tui3 // which is how sixty columns came to spend twelve cells on `thu 12:01am` // while the whole right end went unwritten.) // -// - THE LADDER IS THE NAV'S NOW (topnav.go's [app.navTails]). The line shares -// its row with the places, and the owner ruled the order the row gives -// things up in (2026-09-24): the clock, then the moving count, then the -// words of `2 want you` (never its count), then the places fold, and the -// day's figure is the last clause but one standing. +// - THE LADDER IS THE NAV'S NOW (topnav.go's [app.navTails]). // // - AND THE COUNT THAT WANTS YOU NEVER LEAVES THE ROW. It was allowed to, // for one wave, on the argument that a place's own rows and the strip's @@ -67,20 +63,13 @@ package tui3 // So `2 want you` shortens to `2 ?` in the same amber before anything // else is given up, and it outlasts the money and the places. // -// - THE ALLOWANCE IS A FRACTION HERE, AND THE OWNER OVERRULED THIS FILE TO PUT -// IT THERE. What stood here for four waves was the opposite law, and it read: -// "NEVER A QUOTA FRACTION HERE. What the day has spent belongs on the pulse; -// what the day is ALLOWED to spend is the machine card's `today` band and -// nowhere else. A ceiling on this line would turn a glance into an arithmetic -// problem." (That band is retired with home's resting state and this line is -// the only one left that draws either figure.) The design draws -// `$0.55 / $20.00`, the owner said "follow the -// exact design" on 2026-08-25, and the old law is retired rather than quietly -// dropped — this paragraph is its headstone. The argument it lost is worth -// keeping: the fraction is two figures where one would do. The argument that -// beat it is that "how much is left" is the only thing anybody ever wanted the -// first figure FOR, and a person who has to remember their own ceiling to read -// a spend segment is doing the arithmetic anyway, in their head, wrongly. +// What stood here for four waves was the opposite law, and it read: "NEVER A QUOTA +// FRACTION HERE. What the day has spent belongs on the pulse; what the day is ALLOWED +// to spend is the machine card's `today` band and nowhere else. The argument it lost +// is worth keeping: the fraction is two figures where one would do. The argument that +// beat it is that "how much is left" is the only thing anybody ever wanted the first +// figure FOR, and a person who has to remember their own ceiling to read a spend +// segment is doing the arithmetic anyway, in their head, wrongly. // // - AND THE FRACTION RETIRED THE COLOUR CHANGE THAT STOOD IN FOR IT. The figure // used to rise out of the dim into the warning hue as the bound came close, diff --git a/internal/tui3/question.go b/internal/tui3/question.go index 50ba6b88f7..97d420dbab 100644 --- a/internal/tui3/question.go +++ b/internal/tui3/question.go @@ -343,11 +343,10 @@ type questionShown struct { // questionOther is the answer that is not on the list, being written. // -// THE ROW IS THE BOX AND THERE IS NO MODE. Before the owner's ruling of -// 2026-09-11 a person had to press `c` first — a letter nothing on screen named, -// which pointed the MESSAGE BOX at the question and said so in a row where the -// answers had been. The last row is `something else…` now, the pointer arriving -// on it is what opens it, and the message box below stays the person's. +// THE ROW IS THE BOX AND THERE IS NO MODE. Previously a person had to press `c` first — a +// letter nothing on screen named, which pointed the MESSAGE BOX at the question and said +// so in a row where the answers had been. The last row is `something else…` now, the +// pointer arriving on it is what opens it, and the message box below stays the person's. type questionOther struct { // words is the sentence being typed, in the surface's own one-line editor, // so the caret, the word jumps and the undo stack are the ones every other @@ -763,14 +762,12 @@ func questionPointerStart(q session.Question) int { } } } - // AND WHERE NOBODY RECOMMENDED ANYTHING AND NOBODY BUT A PERSON MAY ANSWER, - // THE STAKES SAY WHERE `enter` LANDS (owner ruling, 2026-09-11, shipped as - // #953). The gate now grades its own questions — internal/approval's - // always-ask shapes come through as [session.StakesIrreversible] and every - // other consent stays [session.StakesCostly] — so the pointer opens on the - // answer that loses nothing for a grave call and on the first answer for an - // ordinary one. `enter` takes the answer the pointer is on: `deny` over - // `rm -rf` or a force-push, `allow once` over an `ls`. + // AND WHERE NOBODY RECOMMENDED ANYTHING AND NOBODY BUT A PERSON MAY ANSWER, THE STAKES + // SAY WHERE `enter` LANDS. The gate now grades its own questions — internal/approval's + // always-ask shapes come through as [session.StakesIrreversible] and every other consent + // stays [session.StakesCostly] — so the pointer opens on the answer that loses nothing + // for a grave call and on the first answer for an ordinary one. `enter` takes the answer + // the pointer is on: `deny` over `rm -rf` or a force-push, `allow once` over an `ls`. // // THE KEY IS THE STAKES AND ONLY THE STAKES. Reading the command's text or // the tool's name here would be a second judgement beside internal/approval's @@ -1043,9 +1040,8 @@ func (a *app) questionRows(width int) []string { } head, ok := a.questionHead() if !ok { - // A QUESTION PUT OFF FOLDS IN PLACE AND NOT TO THE FAR SIDE OF THE - // FRAME (owner ruling 2026-09-11, fold pick A): one titled rule where - // the panel was, saying what is waiting and how to open it again. + // A QUESTION PUT OFF FOLDS IN PLACE AND NOT TO THE FAR SIDE OF THE FRAME: one titled + // rule where the panel was, saying what is waiting and how to open it again. // // AND NOT UNDER THE PAGE THAT IS SHOWING IT. `o` folds the question it // opens, so the block will not draw it a second time with keys of its @@ -1143,12 +1139,9 @@ func (a *app) questionRows(width int) []string { // AND A RATIFY LINE IS NEVER COUNTED HERE: nothing waits on it, so a queue // count that included one would put a number on the block no key can clear. // - // (#954's clock aside is NOT appended here. It is a sentence, and the row - // under the frame is the second tier of KEYS and nothing else — a sentence - // mixed into it is the hierarchy the owner's hints ruling exists to prevent. - // It is drawn as the panel's own last body row instead, inside the frame: - // questionpanel.go's [app.questionPanelBody]. Agreed with lane A before - // either landed.) + // (#954's clock aside is NOT appended here. It is a sentence, and the row under the frame + // is the second tier of KEYS and nothing else — a sentence mixed into it breaks that hierarchy. It is drawn as the panel's own last body row instead, inside the + // frame: questionpanel.go's [app.questionPanelBody].) if more := a.questionWaitingCount() - 1; more > 0 { if _, panel := a.questionDialog(width); !panel { out = append(out, a.pal.dim(fit(" "+itoa(more)+" more", width))) @@ -1284,13 +1277,12 @@ func questionWaits(q session.Question) bool { // "waiting on a human (always amber)" in the vocabulary itself, and amber on // this surface means that and nothing else. // -// THE BLOCK'S WORDS ARE ORDINARY INK, and that is the half of this comment the -// owner's colour ruling of 2026-09-11 rewrote. They kept a question hue of their -// own — a violet spent on the head, every answer label and every key — while -// home, the places and the chip said the same "waiting on you" in this amber, so -// one meaning wore two colours and whole rows stood in a status hue. The violet -// is retired from both ladders (docs/DESIGN-LANGUAGE.md), and the marks carry -// the meaning: this one, the pointer and the recommended diamond. +// THE BLOCK'S WORDS ARE ORDINARY INK. They +// kept a question hue of their own — a violet spent on the head, every answer label and +// every key — while home, the places and the chip said the same "waiting on you" in this +// amber, so one meaning wore two colours and whole rows stood in a status hue. The violet +// is retired from both ladders (docs/DESIGN-LANGUAGE.md), and the marks carry the meaning: +// this one, the pointer and the recommended diamond. func (a *app) questionMark() string { return a.pal.warnBold(a.icon(tokens.GNeedsHuman)) } @@ -2237,13 +2229,9 @@ func (a *app) questionHint() string { if !ok { return "" } - // THE SLOT ABOVE THE BLOCK DOES NOT RE-LIST THE ANSWERS (owner ruling - // 2026-09-11, hints pick A). Every view but the chip's draws the answers and - // their keys itself, two rows below this one, and a rule that spelled them - // again — in a second order, with its own idea of which keys exist — was the - // owner's "the hint line names keys that are not there". Where the question - // is NOT on this screen the slot is the only place its keys can be said, and - // there it still says them. + // THE SLOT ABOVE THE BLOCK DOES NOT RE-LIST THE ANSWERS. Where the question is NOT on + // this screen the slot is the only place its keys can be said, and there it still says + // them. if width, _ := a.size(); a.questionViewOf(head, width) != viewNone { return "" } @@ -2430,13 +2418,12 @@ func (a *app) questionReceiptLine(record questionRecord, width int) string { // questionReceiptTail is what the receipt says after the decision's own words: // that the turn is moving again. // -// THE WORK RESUMES ON THE ANSWER AND THE ROW SAYS SO UNTIL THE MODEL'S FIRST -// OUTPUT (owner ruling 2026-09-11). A block that vanished into a still line left -// a person watching an unmoving screen wondering whether their key had landed; -// the tail is that key's receipt, in the one moving glyph this surface spends -// ([tokens.Spinner], on the house grid so it never beats against another). -// It is derived and never a timer: the moment there is anything to read the -// conversation is drawing it, and this stops. +// THE WORK RESUMES ON THE ANSWER AND THE ROW SAYS SO UNTIL THE MODEL'S FIRST OUTPUT. A +// block that vanished into a still line left a person watching an unmoving screen +// wondering whether their key had landed; the tail is that key's receipt, in the one +// moving glyph this surface spends ([tokens.Spinner], on the house grid so it never beats +// against another). It is derived and never a timer: the moment there is anything to read +// the conversation is drawing it, and this stops. func (a *app) questionReceiptTail(record questionRecord) string { if record.withdrawn != "" || a.state != stateWorking || !a.questionQuietSince(record) { return "" @@ -2519,8 +2506,7 @@ type questionAnswer struct { // second answering path. // // IT TAKES A LIST BECAUSE ONE FRAME CAN HOLD SEVERAL QUESTIONS. A step that -// asks for three permissions at once is drawn as one thing to decide (the -// grouped frame, lane P), and the person answering it is making one gesture; a +// asks for three permissions at once is drawn as one thing to decide, and the person answering it is making one gesture; a // loop of single answers would be as many round trips as there are rows, each // one a separate command, with the refusals arriving over several frames. Here // every row settles on the keystroke, the doors are asked in order on ONE @@ -3262,14 +3248,10 @@ func (a *app) questionEnter(head questionShown, typing bool) (tea.Cmd, bool) { // answer that says so ([questionOwnsBox] is the same fact from the other // side, and takes this key while there ARE words). // - // AND THE WAY OUT IS NOT THE WHOLE QUESTION. A correction, a connect key or - // an automation card is still a question WITH ANSWERS, and every question - // with answers has a pointer the arrows walk ([questionPointerStart]) — a - // standing card whose Enter did nothing while the pointer stood on - // `1 keep this rule` was the owner, 2026-09-25 (#1506). So the give-up below - // yields to a pointer: enter over an empty box takes the answer the pointer - // is on, and only a question with nothing under the pointer — and no - // asker's pick beside it — hands the key back untouched. + // AND THE WAY OUT IS NOT THE WHOLE QUESTION. So the give-up below yields to a pointer: + // enter over an empty box takes the answer the pointer is on, and only a question with + // nothing under the pointer — and no asker's pick beside it — hands the key back + // untouched. if head.question.Input.Kind == session.InputText { // THE POINTER STANDS FOR A PICK ONLY WHERE A PICK EXISTS. A connect // question keeps exactly one answer, the way out, and that answer is @@ -3465,16 +3447,14 @@ func (a *app) questionWriting() bool { return false } -// questionWritingRow is the answers row while the box is writing to the -// question: what the box means now, which answer the words go with, and the -// way back. It replaces the keys, because the keys are letters and every -// letter types while this row is up. -// TWO KEYS REACH IT NOW AND NOT FOUR. `?` asks the asker back, where there is -// no answer to attach the words to; `c` reaches it only on a question that asked -// for WORDS, where there is no `something else…` row to write them in — the -// owner's ruling of 2026-09-11 (your own answer, pick A) gave every other -// question that row instead, and the row says which answer the words go with -// rather than a sentence three rows below the pointer. +// questionWritingRow is the answers row while the box is writing to the question: what the +// box means now, which answer the words go with, and the way back. It replaces the keys, +// because the keys are letters and every letter types while this row is up. TWO KEYS REACH +// IT NOW AND NOT FOUR. `?` asks the asker back, where there is no answer to attach the +// words to; `c` reaches it only on a question that asked for WORDS, where there is no +// `something else…` row to write them in — (your own answer, pick A) gave every other +// question that row instead, and the row says which answer the words go with rather than a +// sentence three rows below the pointer. func (a *app) questionWritingRow(q questionShown) string { if q.writing == questionNoteKey { return "write your change, then enter" + questionWritingGap + "esc back" @@ -4023,7 +4003,7 @@ func (a *app) dialKind(kind session.AskKind) tea.Cmd { // how to take it back. const questionDialFromNowWord = " from now on · /autonomy to change it" -// openQuestionRoom walks into the room over this question — lane S2's page. +// openQuestionRoom walks into the room over this question in its own page. // // THE DOOR IS CALLED AND NEVER RE-IMPLEMENTED. The page is questionroom.go's, // and everything it needs travels in the [questionShown] this block was already @@ -4105,10 +4085,10 @@ func (a *app) questionRowMark(i int) chromeRow { // has no block to look at. The chip is the one thing that is always there while // anything is waiting. // -// IT CARRIES THE QUESTION'S OWN WORDS (owner ruling 2026-09-11). `1 question` -// says that something is waiting and nothing about whether it is worth crossing -// the room for; the head says which decision is parked, and a person who can -// read it from the status row does not have to open anything to know. +// IT CARRIES THE QUESTION'S OWN WORDS. `1 question` says that something is waiting and +// nothing about whether it is worth crossing the room for; the head says which decision is +// parked, and a person who can read it from the status row does not have to open anything +// to know. // // AND IT NEVER COUNTS A LINE THAT IS NOT WAITING. A ratify line is a statement // about something already done ([questionWaits]); counting it put a number on diff --git a/internal/tui3/question_test.go b/internal/tui3/question_test.go index e9c471637f..afc484fa0c 100644 --- a/internal/tui3/question_test.go +++ b/internal/tui3/question_test.go @@ -324,12 +324,11 @@ func consentAsk() session.Question { // shape of a permission, asserted as rows rather than as a substring: a block // that grew a row nobody decided on is a block that moved the box. // -// IT IS THE PANEL AND NOT A LINE. A person allowing a call has to READ the call -// (owner ruling 2026-09-11, consent pick B), so the chooser sends every -// permission here: the head and who is asking in the frame's top edge, the call -// and the policy's own words on the first row, a blank, a row per answer, a -// blank, the keys that answer in the bottom edge, and the quieter keys on one -// dim row under it. +// IT IS THE PANEL AND NOT A LINE. A person allowing a call has to READ the call, so the +// chooser sends every permission here: the head and who is asking in the frame's top edge, +// the call and the policy's own words on the first row, a blank, a row per answer, a +// blank, the keys that answer in the bottom edge, and the quieter keys on one dim row +// under it. // // AND NO LIFETIMES ROW, though this fixture offers two. The consent gate reads // an answer's key and never [session.Answer.Scope], so the row is off a @@ -409,9 +408,8 @@ func TestEscIsLaterAndCancelsNothing(t *testing.T) { if len(lab.answer) != 0 { t.Fatalf("esc answered something: %+v", lab.answer) } - // A QUESTION PUT OFF FOLDS IN PLACE TO ONE TITLED RULE (owner ruling - // 2026-09-11, fold pick A): it never jumps to the status line, and the rule - // says what is waiting and which key opens it again. + // A QUESTION PUT OFF FOLDS IN PLACE TO ONE TITLED RULE: it never jumps to the status + // line, and the rule says what is waiting and which key opens it again. folded := lab.rows() if len(folded) != 1 { t.Fatalf("the folded question is not one rule:\n%s", strings.Join(folded, "\n")) @@ -636,13 +634,12 @@ func TestACardDrawsARowPerAnswerAndMarksTheAskersPick(t *testing.T) { // TestEnterOnAPermissionSplitsOnTheStakes is where the pointer stands when the // asker named no pick, and it is the half of the pointer that keeps it safe. // -// `enter` takes the answer the pointer is on, so the ruling (owner, 2026-09-11) -// is one keystroke wide: an ORDINARY call opens on `allow once` and a GRAVE one -// on `deny`, and the engine's grade — [session.Question.Stakes], written by the -// gate out of internal/approval's own judgement — is the only thing that says -// which is which. #933 could not ship the split because nothing upstream graded -// a call; it shipped deny-first for all of them, and this test is what its -// successor proves now that the grade arrives. +// `enter` takes the answer the pointer is on, so the ruling is one keystroke wide: an +// ORDINARY call opens on `allow once` and a GRAVE one on `deny`, and the engine's grade — +// [session.Question.Stakes], written by the gate out of internal/approval's own judgement +// — is the only thing that says which is which. #933 could not ship the split because +// nothing upstream graded a call; it shipped deny-first for all of them, and this test is +// what its successor proves now that the grade arrives. // // ONE CASE EACH WAY, read off the question and never spelled as an answer // number: a test naming `3` would still pass the day the engine renumbered its @@ -1475,9 +1472,8 @@ func TestALongNoteUnderEveryAnswerIsCutToWhatTheScreenHolds(t *testing.T) { Reason: "a tour needs a shape", Options: options, Input: session.InputShape{Kind: session.InputChecklist}, Stakes: session.StakesReversible, }) - // THE NOTE IS UNDER THE POINTER AND NOWHERE ELSE (owner ruling 2026-09-11, - // recommended pick A). Eight answers each carrying a paragraph is a panel - // taller than the conversation under it; the pointer is the person saying + // THE NOTE IS UNDER THE POINTER AND NOWHERE ELSE. Eight answers each carrying a paragraph + // is a panel taller than the conversation under it; the pointer is the person saying // which one they are weighing, and `o open full` holds the rest. screen := lab.plain() if n := strings.Count(screen, glyphMore); n > 1 { @@ -1518,9 +1514,8 @@ func TestArrowsWalkThePointerOnACardAndEnterTakesIt(t *testing.T) { if !strings.Contains(screen, tokens.GlyphPointer+" 2 Adaptive") { t.Fatalf("the pointer does not start on the asker's pick:\n%s", screen) } - // THE PICK IS A MARK AND A WORD AT THE RIGHT EDGE OF ITS ROW, never a word - // appended to what the answer costs (owner ruling 2026-09-11, recommended - // pick A) — `needs a watch · suggested` read as one more thing it would do. + // THE PICK IS A MARK AND A WORD AT THE RIGHT EDGE OF ITS ROW, never a word appended to + // what the answer costs — `needs a watch · suggested` read as one more thing it would do. if !strings.Contains(screen, tokens.GlyphRecommended+" "+questionRecommendedWord) { t.Fatalf("the asker's pick is not said on its row:\n%s", screen) } @@ -1620,12 +1615,11 @@ func TestTheTaskRecordPageDrawsTheLandingQuestionAndTakesItsKeys(t *testing.T) { } } -// `c` AND `?` POINT THE BOX AT THE QUESTION, VISIBLY. The answers row becomes -// a prompt saying what the box is writing now, every letter types (a `d` is a -// letter, not `you decide`), enter sends the words with the pointed answer -// (`c`) or to the asker with the question still open (`?`), and esc points the -// box back at the conversation. Before this the keys changed nothing on the -// screen and the words went out as a chat message (the owner, 2026-09-10). +// `c` AND `?` POINT THE BOX AT THE QUESTION, VISIBLY. The answers row becomes a prompt +// saying what the box is writing now, every letter types (a `d` is a letter, not `you +// decide`), enter sends the words with the pointed answer (`c`) or to the asker with the +// question still open (`?`), and esc points the box back at the conversation. Before this +// the keys changed nothing on the screen and the words went out as a chat message. func TestChangeAndAskBackTurnTheRowIntoAPromptAndEnterSendsTheWords(t *testing.T) { lab := newQuestionLab(t) lab.a.width = 120 diff --git a/internal/tui3/questionaskback_test.go b/internal/tui3/questionaskback_test.go index 9415cf0ca5..3e462c3577 100644 --- a/internal/tui3/questionaskback_test.go +++ b/internal/tui3/questionaskback_test.go @@ -149,10 +149,9 @@ func TestTheChipCountsTheWaitingOneBesideTheRatify(t *testing.T) { if n := lab.a.questionCount(); n != 1 { t.Fatalf("the chip counts %d with one ratify and one permission open, want just the permission", n) } - // AND IT SAYS WHICH ONE, in that question's own words rather than as a - // number (owner ruling 2026-09-11): with exactly one thing waiting, a count - // is a fact somebody has to press a key to act on. The count above is what - // proves the ratify was filtered; this proves the words are the right + // AND IT SAYS WHICH ONE, in that question's own words rather than as a number: with + // exactly one thing waiting, a count is a fact somebody has to press a key to act on. The + // count above is what proves the ratify was filtered; this proves the words are the right // question's. chip := plain(lab.a.questionSegment()) if !strings.Contains(chip, "allow this?") { diff --git a/internal/tui3/questionchange.go b/internal/tui3/questionchange.go index 9f36679415..d15ff23147 100644 --- a/internal/tui3/questionchange.go +++ b/internal/tui3/questionchange.go @@ -217,7 +217,7 @@ func (a *app) changeAnswer(record questionRecord) { // AND NOTHING IS WAITING ON IT. The turn that asked has long since been // answered and moved on — that is what the receipt was — so a row that still // said `waiting` would be telling somebody their work had stopped for a - // decision they are only revisiting. Seen on the Spark, 2026-09-11. + // decision they are only revisiting. Seen in a test run, 2026-09-11. q.Blocking = session.Blocking{} q.Asked = a.now() if a.priorAnswers == nil { diff --git a/internal/tui3/questionchooser.go b/internal/tui3/questionchooser.go index fcb913e57b..18c33fc6f8 100644 --- a/internal/tui3/questionchooser.go +++ b/internal/tui3/questionchooser.go @@ -39,9 +39,8 @@ const ( // viewPanel is the framed panel a question hangs in above the box // (questionpanel.go). It is the ordinary answer. viewPanel - // viewSplit is the same panel with its answers in a list on the left and - // the evidence of the one the pointer is on in a pane on the right, which - // follows the pointer (owner ruling 2026-09-11, preview pick A). + // viewSplit is the same panel with its answers in a list on the left and the evidence of + // the one the pointer is on in a pane on the right, which follows the pointer. viewSplit // viewRow is one row: a question whose whole decision fits beside its own // answers, and the ratify line, which is not asking anything. @@ -176,10 +175,9 @@ func questionAnswersCarryBlocks(q session.Question) bool { // answers' own words: what taking one produces, what one means, a pick the asker // gave a reason for, or a call the question is about. // -// THE CALL IS ONE OF THEM, and it is the permission's whole case: a person -// allowing a command has to READ the command, so it stands on the panel's first -// row in the payload hue with what it touches beside it (owner ruling -// 2026-09-11, consent pick B). +// THE CALL IS ONE OF THEM, and it is the permission's whole case: a person allowing a +// command has to READ the command, so it stands on the panel's first row in the payload +// hue with what it touches beside it. func questionCarriesWeight(q session.Question) bool { if q.Subject.Kind == session.SubjectCall { return true diff --git a/internal/tui3/questiondemo.go b/internal/tui3/questiondemo.go index e5f63ce66f..7b80bccc06 100644 --- a/internal/tui3/questiondemo.go +++ b/internal/tui3/questiondemo.go @@ -10,15 +10,9 @@ import ( // THE FIXTURE DOOR ONTO THE QUESTION PAGE, and why one exists at all. // -// A question with a diagram under each answer, four axes to compare on and a -// dial for an input shape is a question NOTHING IN THIS PROGRAM RAISES YET: the -// tool that lets a model ask one is lane E2's and the cards that promote into -// this page are lane S1's, so on the day this page landed there was no way to -// put a real one on a real screen. The alternative to this file was a page whose -// author had only ever seen it through a test's string comparison, and -// CLAUDE.md's `make demo-home` exists because the owner has already ruled on -// that trade once: a fixture with something on every place is how you SEE a page -// full, and a page nobody has looked at is not done. +// These fixtures make diagrams, comparisons and input forms inspectable in a +// real terminal without calling a model. A populated example exposes layout +// problems that a string comparison alone can miss. // // SO IT IS THE SAME SHAPE AS `make demo-home` AND UNDER THE SAME TERMS. It is // reached only by naming a case in the environment, it is read through @@ -274,7 +268,7 @@ func demoQuestionLayout() session.Question { // OWN BUILDERS wherever there is one, so a fixture cannot drift from the thing // it is a picture of. var blockDemos = map[string]func() session.Question{ - // THE EVIDENCE ON THE PANEL (lane R): the page's own worked example and its + // THE EVIDENCE ON THE PANEL: the page's own worked example and its // layout case, raised onto the block instead of the page, so the list with // the evidence beside it — and, narrower, unfolded under the pointer — can be // seen without a model. diff --git a/internal/tui3/questionevidence.go b/internal/tui3/questionevidence.go index 699cc2efc7..ddb48c18ed 100644 --- a/internal/tui3/questionevidence.go +++ b/internal/tui3/questionevidence.go @@ -9,12 +9,10 @@ import ( // ── ONE ANSWER'S CASE, AND THE EVIDENCE IT BROUGHT ────────────────────────── // -// A QUESTION IS A DECISION HANDED TO THE PERSON WITH ITS EVIDENCE ATTACHED -// (owner ruling 2026-09-09), and the evidence is per answer: what it means, what -// taking it leaves true, why the asker would take it, what would change its -// mind, how sure it is, and whatever it drew — a diagram, a diff, a table, a -// layout, a picture. The owner's picks of 2026-09-11 draw that evidence in three -// places: +// A QUESTION IS A DECISION HANDED TO THE PERSON WITH ITS EVIDENCE ATTACHED, and the +// evidence is per answer: what it means, what taking it leaves true, why the asker would +// take it, what would change its mind, how sure it is, and whatever it drew — a diagram, a +// diff, a table, a layout, a picture. // // - beside the list, in a pane that follows the pointer (preview A, a panel at // a hundred columns and wider, and page A, the page `o` opens); diff --git a/internal/tui3/questionevidence_test.go b/internal/tui3/questionevidence_test.go index 5936a5239a..1ccc285563 100644 --- a/internal/tui3/questionevidence_test.go +++ b/internal/tui3/questionevidence_test.go @@ -179,7 +179,7 @@ func TestAPressOnTheEvidenceBesideTheListPressesNothing(t *testing.T) { // THE ANSWER THE POINTER IS ON IS ALWAYS ON SCREEN, in one column and in two // panes, however far down the arrows walk and however tall the evidence under -// it — the defect lane F measured on the old page, where the window moved only +// it — the regression on the old page, where the window moved only // under the wheel. func TestTheAnswerThePointerIsOnIsAlwaysOnScreen(t *testing.T) { q := tallEvidence() diff --git a/internal/tui3/questionhand_test.go b/internal/tui3/questionhand_test.go index ba4716a82d..1cdb9f160a 100644 --- a/internal/tui3/questionhand_test.go +++ b/internal/tui3/questionhand_test.go @@ -278,10 +278,6 @@ func TestTheAnswersRowIsWhereTheBlockSaysItIsWithAReceiptAboveIt(t *testing.T) { } // ── THE BOX KEEPS THE FIRST LETTER ────────────────────────────────────────── -// -// The defect, in the owner's own words: "the first key typed into an empty box -// must not answer — a digit picks, `d` hands the call back today." The rule and -// the reason the ANSWERS' keys are not on this road are in questionkeys.go. // handLab is one question on the block, settled, with an empty box under it. func handLab(t *testing.T) *questionLab { @@ -462,7 +458,7 @@ func TestAKeyDroppedByTheSettleGuardDoesNotGiveTheHand(t *testing.T) { // ── THE DOOR TAKES A LIST ─────────────────────────────────────────────────── // // One frame can hold several questions — a step that asks for three permissions -// at once is one thing to decide (lane P's grouped frame) — and the person +// at once is one thing to decide — and the person // answering it makes one gesture. [app.answerQuestions] is that gesture: every // row settles on the keystroke, the doors are asked in order on ONE goroutine // off the loop, and a refusal comes back against its own row. diff --git a/internal/tui3/questioninput.go b/internal/tui3/questioninput.go index 4f5a8f5e3e..8fb54d70b1 100644 --- a/internal/tui3/questioninput.go +++ b/internal/tui3/questioninput.go @@ -748,11 +748,10 @@ func (a *app) questionDialFace(width int) string { return a.pal.ink(strconv.Itoa(in.notch+1) + " of " + strconv.Itoa(in.notches) + questionSep + in.dialWord()) } - // With words, the dial IS its words: the one it is on wears the POINTER and - // the weight, the rest are dim. The brackets it used to wear were punctuation - // standing in for a mark this surface has ([tokens.GPointer], the same one - // every answer's row uses for "here"), and the amber they were painted in - // belongs to that mark now (owner ruling 2026-09-11, colour pick C). + // With words, the dial IS its words: the one it is on wears the POINTER and the weight, + // the rest are dim. The brackets it used to wear were punctuation standing in for a mark + // this surface has ([tokens.GPointer], the same one every answer's row uses for "here"), + // and the amber they were painted in belongs to that mark now. if len(in.dial.Labels) > 0 { parts := make([]string, 0, len(in.dial.Labels)) for i, label := range in.dial.Labels { diff --git a/internal/tui3/questionkeys.go b/internal/tui3/questionkeys.go index e618238535..852274b57e 100644 --- a/internal/tui3/questionkeys.go +++ b/internal/tui3/questionkeys.go @@ -16,7 +16,7 @@ import ( // // IT IS ONE TABLE BECAUSE FOUR READERS AGREE THROUGH IT. The line, the card and // the ratify row draw their answers row from it ([app.questionKeyRow]); the room -// reads it for its foot (lane S2 imports [questionKeys] rather than spelling a +// reads it for its foot (it imports [questionKeys] rather than spelling a // second set); `internal/manual/chat/questions.md` lists exactly these keys and // exactly these words; and the tmux suite's needles come out of the same words. // A key spelled in two places is a key that means two things the first week one @@ -52,9 +52,8 @@ type questionVerb struct { // form. The emptiness law lives here: no pick means no `enter →` line, no // rule to offer means no `r`, nothing real to undo means no `u`. needs questionNeed - // tier is which of the two rows a question draws this key on: the primary - // keys are written into the frame's bottom edge and the rest stand on one - // dim row under the frame (owner ruling 2026-09-11, hints pick A). + // tier is which of the two rows a question draws this key on: the primary keys are + // written into the frame's bottom edge and the rest stand on one dim row under the frame. // // IT IS A COLUMN AND NOT A LIST OF NAMES SOMEWHERE ELSE. The primary tier is // "what a person needs in order to answer this at all" — walk, take, later, @@ -111,8 +110,8 @@ const ( formsGroup ) -// formsBlock is the three forms THIS lane draws — the pinned block above the -// box. The room is lane S2's and is named here so its keys travel in the same +// formsBlock is the three forms this block draws — the pinned block above the +// box. The room is named here so its keys travel in the same // table rather than in a second one beside it. const formsBlock = formsLine | formsCard | formsRatify @@ -152,7 +151,7 @@ const ( // would be the surface deciding an irreversible thing on somebody's behalf // — which is exactly what the question exists to prevent. needHands - // ── the room's own conditions (lane S2) ──────────────────────────────── + // ── the room's own conditions ──────────────────────────────── // // They are HERE and not in a second table beside this one, because a key is // a key wherever it is drawn: the room's `a`/`b`/`=` and its `n` have to be @@ -253,7 +252,7 @@ const ( // questionWalkDownKey is the same walk spelled for a card, whose answers // stand in a column. questionWalkDownKey = "↑↓" - // The room's own keys (lane S2). `a` and `b` are the two sides of a pair and + // The room's own keys. `a` and `b` are the two sides of a pair and // `a` is also the checklist's "take its suggestion" — the one collision the // grammar has, and it is the same instinct at two shapes: take the thing on // the left. @@ -288,10 +287,7 @@ const ( // on it, and let the person type. Nothing is cancelled, so the word may not say // cancelled. var questionKeys = []questionVerb{ - // THE WALK COMES FIRST, because every drawing the owner picked reads its - // keys in the order a hand uses them: choose, then take it, then put it - // off (docs/design/questions/picked — `↑↓ choose · enter take it · esc - // later`). It is given up early all the same; the order is not the rank. + // It is given up early all the same; the order is not the rank. // // THE POINTER'S KEYS ARE SPELLED THE WAY THE FORM LAYS ITS ANSWERS OUT: // across on a line, down on a card. Both pairs walk on both. diff --git a/internal/tui3/questionlaw_test.go b/internal/tui3/questionlaw_test.go index 73a3140f3e..ed2f681c30 100644 --- a/internal/tui3/questionlaw_test.go +++ b/internal/tui3/questionlaw_test.go @@ -11,10 +11,6 @@ import ( ) // ── THE TWO LAWS OF THE QUESTION VIEWS ────────────────────────────────────── -// -// Both are owner rulings of 2026-09-11, and both are the kind of law that is -// kept by a test or not at all: one is about a colour that is easy to reach for -// and the other is about a ladder that is easy to grow an `if` on. // COLOUR IS STROKE AND NEVER FILL: NO ROW OF A QUESTION IS PAINTED IN THE // QUESTION HUE (colour pick C). diff --git a/internal/tui3/questionnarrow.go b/internal/tui3/questionnarrow.go index 4b1a3103e1..eb053832a6 100644 --- a/internal/tui3/questionnarrow.go +++ b/internal/tui3/questionnarrow.go @@ -294,12 +294,11 @@ func (a *app) questionBandWord(word, key string, width int) string { // is, the key it also answers to, its word, and `◆ recommended` at the right // edge where the asker named this one. // -// IT IS THE PANEL'S ROW GRAMMAR ON A PHONE (owner ruling 2026-09-11, colour -// pick C and recommended pick A): the marks are amber, the key is the payload -// hue, the word is ordinary ink, and the row the pointer stands on takes the -// GROUND ladder rather than a colour. The sheet used to paint every band in the -// question hue with its key in brackets, which was the one surface still -// shouting — and it was the one surface where the pick was not said at all. +// IT IS THE PANEL'S ROW GRAMMAR ON A PHONE: the marks are amber, the key is the payload +// hue, the word is ordinary ink, and the row the pointer stands on takes the GROUND ladder +// rather than a colour. The sheet used to paint every band in the question hue with its +// key in brackets, which was the one surface still shouting — and it was the one surface +// where the pick was not said at all. // // Under the mouse it takes the hover background every pressable row on this // surface takes (hover.go) — an affordance for a mouse and a no-op for a thumb, diff --git a/internal/tui3/questionpage.go b/internal/tui3/questionpage.go index 71814b0c11..3e1e433452 100644 --- a/internal/tui3/questionpage.go +++ b/internal/tui3/questionpage.go @@ -12,11 +12,10 @@ import ( // ── THE PAGE, DRAWN ───────────────────────────────────────────────────────── // -// `o` OPENS THE QUESTION AS TWO PANES (owner ruling 2026-09-11, page pick A): -// the question and its reason across the top, the answers in a list on the left -// with what the asker showed for the whole decision under them, and the evidence -// of the answer the pointer is on in a pane on the right — its word, what it -// means, what taking it leaves true, why the asker would take it, what would +// `o` OPENS THE QUESTION AS TWO PANES: the question and its reason across the top, the +// answers in a list on the left with what the asker showed for the whole decision under +// them, and the evidence of the answer the pointer is on in a pane on the right — its +// word, what it means, what taking it leaves true, why the asker would take it, what would // change its mind, how sure it is, and everything it drew. // // ? Which storage for the session index? model asks · the turn waits on it @@ -511,8 +510,7 @@ func (a *app) questionRoomRows(width int) []row { // one place the list's window is moved for anything other than the wheel. // // An arrow that walks the pointer below the fold with nothing moving on screen -// is a key that reads as doing nothing (lane F measured it on the old page, where -// the window was moved only by the wheel). It scrolls the LEAST it can: a row +// is a key that reads as doing nothing. It scrolls the LEAST it can: a row // already on screen does not move, and one off it is brought just inside the // edge it left by — the reading position a person built is kept, not // re-anchored under them. diff --git a/internal/tui3/questionpanel.go b/internal/tui3/questionpanel.go index b453a4fdcb..dc0a4c3420 100644 --- a/internal/tui3/questionpanel.go +++ b/internal/tui3/questionpanel.go @@ -11,11 +11,10 @@ import ( // ── THE PANEL ─────────────────────────────────────────────────────────────── // -// A QUESTION HANGS ABOVE THE BOX AS ONE OBJECT (owner ruling 2026-09-11, frame -// pick A). It is the one drawing every question with anything to weigh gets — -// the model's own `ask`, a permission, a task proposal, an automation card, a -// landing, a confirmation — and the chooser (questionchooser.go) is what decides -// that a question has anything to weigh. +// A QUESTION HANGS ABOVE THE BOX AS ONE OBJECT. It is the one drawing every question with +// anything to weigh gets — the model's own `ask`, a permission, a task proposal, an +// automation card, a landing, a confirmation — and the chooser (questionchooser.go) is +// what decides that a question has anything to weigh. // // ╭─ ? Which storage for the session index? ─────────────── model asks ─╮ // │ │ @@ -391,14 +390,13 @@ func (a *app) questionPanelBodyIn(q questionShown, inner, evidence int) []string // reaches, and a row a person could land the pointer on would make `enter` // mean two things. // - // THIS IS WHERE A QUESTION'S OWN DIM LINES GO, and the reason is the second - // key tier. The row UNDER the frame carries the quieter keys and nothing - // else — the owner's hints ruling put exactly `↑↓ choose · enter take it · - // esc later` in the bottom edge and the dropped keys on one dim row below — - // so a sentence mixed in there is the "no hierarchy in the hints" that ruling - // exists to prevent. A line about the question belongs inside the object: one - // blank row, then `questionPanelGap + a.pal.dim(fit(line, room))`, which - // framed.draw then sets to the frame's one width. + // THIS IS WHERE A QUESTION'S OWN DIM LINES GO, and the reason is the second key tier. The + // row UNDER the frame carries the quieter keys and nothing else — put exactly `↑↓ choose + // · enter take it · esc later` in the bottom edge and the dropped keys on one dim row + // below — so a sentence mixed in there is the "no hierarchy in the hints" that ruling + // exists to prevent. A line about the question belongs inside the object: one blank row, + // then `questionPanelGap + a.pal.dim(fit(line, room))`, which framed.draw then sets to + // the frame's one width. if row := a.questionScopeRow(q, room); row != "" { rows = append(rows, "", row) } @@ -415,18 +413,10 @@ func (a *app) questionPanelBodyIn(q questionShown, inner, evidence int) []string } } } - // AND A QUESTION WHOSE CLOCK ANSWERS SAYS WHAT A PERSON CAN DO ABOUT IT, on - // one dim line, INSIDE the frame (#954, and this is the place lane A and I - // agreed it goes). - // - // IT IS A SENTENCE, AND THE ROW UNDER THE FRAME IS THE SECOND TIER OF KEYS. - // The owner's hints ruling is that the bottom edge carries exactly - // `↑↓ choose · enter take it · esc later` and one dim row under it carries - // the rest of the KEYS, dropped right-to-left — so a sentence appended to - // that region is a third kind of thing in a place with a stated grammar, and - // the hierarchy it creates is the one that ruling exists to prevent. Inside - // the frame it is what it is: a fact about this question, under this - // question, in the same dim the panel's other asides wear. + // A question answered by its clock names the available action on a dim line + // inside the frame. The bottom edge carries the primary keys, and the row below + // carries secondary keys; mixing a sentence into either would obscure that + // hierarchy. if aside := a.questionClockAside(q, room); aside != "" { rows = append(rows, questionPanelGap+aside) } diff --git a/internal/tui3/questionroom.go b/internal/tui3/questionroom.go index b070c8ba7a..e9fb1e6372 100644 --- a/internal/tui3/questionroom.go +++ b/internal/tui3/questionroom.go @@ -175,7 +175,7 @@ type questionDoor interface { } // questionDialDoor is `D`: let it decide every question of THIS SHAPE from now -// on ([session.Agent.SetAutonomy], lane E2). +// on ([session.Agent.SetAutonomy]). // // IT IS A SECOND OPTIONAL INTERFACE AND NOT A METHOD ON THE ONE ABOVE, for // room.go's stated reason about widening an interface: a session that can @@ -472,12 +472,9 @@ func questionConfidenceWord(c session.Confidence) string { // questionAfterIf makes the asker's own sentence read as the tail of `would // switch if `. // -// IT EXISTS BECAUSE A MODEL WRITES A SENTENCE AND THIS ROW IS A CLAUSE. Asked -// what would change its mind, a model answers "If you are targeting a calm -// audience…" — and the row drew `would switch if If you are targeting…`, which -// is what the owner saw on 2026-09-10. So a leading `if` the person is about to -// read twice is dropped, and the capital that opened a sentence is lowered, -// because what follows the word `if` is mid-sentence wherever it came from. +// IT EXISTS BECAUSE A MODEL WRITES A SENTENCE AND THIS ROW IS A CLAUSE. So a leading `if` +// the person is about to read twice is dropped, and the capital that opened a sentence is +// lowered, because what follows the word `if` is mid-sentence wherever it came from. // // A WORD WHOSE SECOND LETTER IS ALSO A CAPITAL IS LEFT ALONE — `SQLite`, `HRV`, // an acronym the asker meant — because lowering one of those is changing what diff --git a/internal/tui3/questionroom_test.go b/internal/tui3/questionroom_test.go index 695474350a..49b0a22f1f 100644 --- a/internal/tui3/questionroom_test.go +++ b/internal/tui3/questionroom_test.go @@ -833,10 +833,7 @@ func TestTheLanesNewsAboutAnAnswerGivenHereAddsNoSecondLine(t *testing.T) { // ── THE POINTER ON THE PAGE, AND WHAT IT LOOKS LIKE ───────────────────────── // -// The owner opened a question out on 2026-09-10 and reported two things about -// the page it opened into: "no arrow or click", and "make sure there is some -// textual hierarchy in design in options like the same line and next line in -// options look same and a bit weird". These are what closes both. +// These are what closes both. // pagePlainRows is the page, a row at a time, with every escape taken off — for // the assertions that are about WHICH ROW a thing landed on. @@ -1052,9 +1049,8 @@ func TestAnAnswersLabelBodyAndAsidesAreThreeDifferentInks(t *testing.T) { if head == "" || body == "" || aside == "" { t.Fatalf("the open answer should draw a heading, a body and an aside:\n%s", pageText(a)) } - // THE KEY IS THE PAYLOAD HUE AND THE WORD IS INK, which is the panel's own - // grammar for an answer (owner ruling 2026-09-11, colour pick C: the amber - // stays on the marks) — the page's rows ARE the panel's. + // THE KEY IS THE PAYLOAD HUE AND THE WORD IS INK, which is the panel's own grammar for an + // answer — the page's rows ARE the panel's. inkOpen := strings.SplitN(a.pal.ink("x"), "x", 2)[0] if !strings.Contains(head, a.pal.data("1")) || !strings.Contains(head, inkOpen+"postgres") { t.Errorf("the label is not the key in the payload hue and the word in ink: %q", head) diff --git a/internal/tui3/questionscope.go b/internal/tui3/questionscope.go index ddf7d1f593..ab20b2bbae 100644 --- a/internal/tui3/questionscope.go +++ b/internal/tui3/questionscope.go @@ -9,15 +9,12 @@ import ( // ── HOW LONG AN ANSWER LASTS, ON THE FRAME THAT ASKS FOR IT ───────────────── // -// "STOP ASKING ME FOR THIS" IS A THING PEOPLE SAY AT A PERMISSION GATE, and -// until this row there was nowhere to say it. The question already carried the -// answer — [session.Question.Scope] is the lifetimes the lane said an answer -// could have, and [session.Answer.Scope] is the one it went out with — but the -// only way to reach a wider one from the block was the `always` ANSWER, which -// grants a different thing (every later call of that tool) and is the lane's -// choice rather than the person's. The owner ruled one row (2026-09-11): the -// offered lifetimes drawn under the answers, cycled by a key, defaulting to the -// narrowest, and OFFERED NOWHERE ELSE. +// "STOP ASKING ME FOR THIS" IS A THING PEOPLE SAY AT A PERMISSION GATE, and until this row +// there was nowhere to say it. The question already carried the answer — +// [session.Question.Scope] is the lifetimes the lane said an answer could have, and +// [session.Answer.Scope] is the one it went out with — but the only way to reach a wider +// one from the block was the `always` ANSWER, which grants a different thing (every later +// call of that tool) and is the lane's choice rather than the person's. // // │ which store should the ledger sit on? // │ @@ -96,10 +93,10 @@ func questionScopeNow(q questionShown) session.AnswerScope { // questionScopeRow is the row itself: every offered lifetime in the person's // own words, with the one that is on wearing the vocabulary's tick. // -// THE TICK IS THE MARK AND THE HUE IS NOT. Colour is stroke and never fill on -// this block (the owner's colour ruling), so the lifetime that is on is ordinary -// ink beside a tick and the rest are dim — which is the same drawing a checklist -// gives an item that is ticked, and it survives a terminal with no colour at all. +// THE TICK IS THE MARK AND THE HUE IS NOT. Colour is stroke and never fill on this block, +// so the lifetime that is on is ordinary ink beside a tick and the rest are dim — which is +// the same drawing a checklist gives an item that is ticked, and it survives a terminal +// with no colour at all. func (a *app) questionScopeRow(q questionShown, room int) string { scopes := questionScopes(q.question) if len(scopes) == 0 { diff --git a/internal/tui3/questionscreens_test.go b/internal/tui3/questionscreens_test.go index b3674b1d7f..40c58542ee 100644 --- a/internal/tui3/questionscreens_test.go +++ b/internal/tui3/questionscreens_test.go @@ -233,12 +233,10 @@ func TestQuestionScreens(t *testing.T) { l.rows() }) - // THE EVIDENCE, AT THE THREE WIDTHS THE OWNER PICKED FOR (2026-09-11). - // Preview A beside the list at a hundred columns and wider, preview-narrow B - // unfolded under the pointer below that, and page A — the page `o` opens — - // as two panes where they fit and one column where they do not. Each is the - // same answer's evidence through the same renderer, so the six pictures are - // one account of it drawn at three widths. + // Preview A beside the list at a hundred columns and wider, preview-narrow B unfolded + // under the pointer below that, and page A — the page `o` opens — as two panes where they + // fit and one column where they do not. Each is the same answer's evidence through the + // same renderer, so the six pictures are one account of it drawn at three widths. for _, width := range []int{120, 96, 56} { shot("evidence-"+itoa(width), func(l *questionLab) { l.a.width, l.a.height = width, 40 diff --git a/internal/tui3/questionset.go b/internal/tui3/questionset.go index 4bd823f090..4f39ddb7a7 100644 --- a/internal/tui3/questionset.go +++ b/internal/tui3/questionset.go @@ -32,10 +32,10 @@ import ( // // ── THE TWO DRAWINGS, EXACTLY AS THEY ARE DRAWN ───────────────────────────── // -// TABS (owner pick `multi — A`): one panel, a tab per question across the top -// edge and a review tab after them. `←→` move between questions, `↑↓` walk the -// answers of the one on screen, and `enter` takes an answer FOR THIS TAB — it is -// held, and the panel moves on to the next question still waiting. +// TABS: one panel, a tab per question across the top edge and a review tab after them. +// `←→` move between questions, `↑↓` walk the answers of the one on screen, and `enter` +// takes an answer FOR THIS TAB — it is held, and the panel moves on to the next question +// still waiting. // // ╭─ ● storage ○ naming ○ tests ✓ review ───────────────── 1 of 3 ─╮ // │ │ diff --git a/internal/tui3/render.go b/internal/tui3/render.go index 5e4525d2a0..d784e0e12c 100644 --- a/internal/tui3/render.go +++ b/internal/tui3/render.go @@ -2452,24 +2452,22 @@ func (a *app) servedRiderAt(width int) string { // It never carries a rate. How fast the machine is writing is a claim about now // and stands beside the state word instead ([app.liveRiderAt]). // -// IT IS WHOLE OR NOTHING, AND IT DOES NOT AGE OUT. Until 2026-09-17 it was -// ` · via deepinfra`, said as `· deepinfra` on a tight line and gone ten -// minutes after the last answer ([servedWindow]). The owner ruled that the -// machine is written beside the model as one word — `deepseek-v4.1-flash -// (baidu)` — and that the last machine to answer stays named until another -// does: a conversation read half an hour later still ran on that machine. -// The sheet's `served` row keeps the window, because the figures beside its -// name are about one answer ([app.servedRiderAt]). -// -// IT IS DRAWN WHOEVER SERVED, AND THAT IS THE OWNER'S OWN RULING (2026-09-09). -// It used to go silent when the server's name was already inside the model id — -// `z-ai/glm-5.3-flash` answered by z-ai — on the argument that the reader -// already had the word. On this line they do not: the seam spells the model as -// its BASENAME ([modelBase]), so the vendor half of the id is not on the screen -// at all, and a rider that appeared for one endpoint and vanished for another -// read as the sighting having been lost rather than as the vendor having served -// its own model. The sheet's `served` row keeps the old rule, because the row -// above it there is the model's WHOLE routing address (statusdeck.go). +// IT IS WHOLE OR NOTHING, AND IT DOES NOT AGE OUT. Until 2026-09-17 it was ` · via +// deepinfra`, said as `· deepinfra` on a tight line and gone ten minutes after the last +// answer ([servedWindow]). The machine is written beside the model as one word — +// `deepseek-v4.1-flash (baidu)` — and that the last machine to answer stays named until +// another does: a conversation read half an hour later still ran on that machine. The +// sheet's `served` row keeps the window, because the figures beside its name are about one +// answer ([app.servedRiderAt]). +// +// IT IS DRAWN WHOEVER SERVED (2026-09-09). It used to go silent when the server's name was +// already inside the model id — `z-ai/glm-5.3-flash` answered by z-ai — on the argument +// that the reader already had the word. On this line they do not: the seam spells the +// model as its BASENAME ([modelBase]), so the vendor half of the id is not on the screen +// at all, and a rider that appeared for one endpoint and vanished for another read as the +// sighting having been lost rather than as the vendor having served its own model. The +// sheet's `served` row keeps the old rule, because the row above it there is the model's +// WHOLE routing address (statusdeck.go). // // THE RULING WAS KEPT HERE AND BROKEN ONE CALL DOWN until 2026-09-10: the lane // layer's rider, which speaks first, still went silent for a vendor serving its @@ -2508,15 +2506,13 @@ func (a *app) modelRiderAt(width int) string { // so it is drawn ONLY while it is being measured, and the line is empty the // moment it is not. // -// TWO OTHER FIGURES WERE HERE AND BOTH WERE ABOUT THE PAST. The served -// sighting's rate is what SOME answer within the last ten minutes averaged, and -// it sat on an idle line as a live figure nobody was producing; the per-turn -// burn ([app.burnSegment]) is a turn's whole output over a turn's whole wall -// time, waits and tool calls included, which is a different quantity from "how -// fast is this writing" and reads low by a factor of several on any turn that -// ran a tool. The owner rejected both on 2026-09-09. The burn is still on -// /status and the phone sheet under its own label, where it is not claiming to -// be now. +// TWO OTHER FIGURES WERE HERE AND BOTH WERE ABOUT THE PAST. The served sighting's rate is +// what SOME answer within the last ten minutes averaged, and it sat on an idle line as a +// live figure nobody was producing; the per-turn burn ([app.burnSegment]) is a turn's +// whole output over a turn's whole wall time, waits and tool calls included, which is a +// different quantity from "how fast is this writing" and reads low by a factor of several +// on any turn that ran a tool. The burn is still on /status and the phone sheet under its +// own label, where it is not claiming to be now. // // WHILE IT WRITES, THE RATE IS THE WHOLE SEGMENT. `writing · 4s · friendli 61 // t/s` said three things a person already had: the state word two runs to the diff --git a/internal/tui3/roomwork_test.go b/internal/tui3/roomwork_test.go index 930f429554..26ebaba519 100644 --- a/internal/tui3/roomwork_test.go +++ b/internal/tui3/roomwork_test.go @@ -10,13 +10,10 @@ package tui3 // "▸ worked · 10 tool calls · ctrl+e" and the person who walked in to watch the // work was handed the report and nothing else. // -// The owner ruled the other way on 2026-09-01 (issue #252, ruling 1): the task -// page folds settled work into phase chips by default and the machinery stays -// one keypress away. The chip is spent per SETTLED PHASE now — the work that -// preceded each paragraph the node wrote — so the machinery collapses, every -// paragraph stays standing, and the live frontier does not fold at all. That -// answers the original complaint without building the page on the premise that -// every call has to be read. +// The chip is spent per SETTLED PHASE now — the work that preceded each paragraph the node +// wrote — so the machinery collapses, every paragraph stays standing, and the live +// frontier does not fold at all. That answers the original complaint without building the +// page on the premise that every call has to be read. // // So these tests are rewritten WITH the design: what folds, what may never // fold, and every door that opens what did. diff --git a/internal/tui3/runlane_test.go b/internal/tui3/runlane_test.go index e4f225fcb5..122c94335f 100644 --- a/internal/tui3/runlane_test.go +++ b/internal/tui3/runlane_test.go @@ -12,7 +12,7 @@ import ( // A run is not a node: no row, no roster, nothing on screen that knows it // exists. Its three event kinds are the whole of the surface's knowledge of one, // and they arrive on a subscription of the session's own — never on a turn's -// stream, because the run outlives the turn that started it. Until this lane was +// stream, because the run outlives the turn that started it. Until this test was // opened the events fired into nothing and the run's page could not be reached. // runLaneAgent is a session driving adaptive runs: the standing lane, and diff --git a/internal/tui3/scrollback_test.go b/internal/tui3/scrollback_test.go index 7bd01a098c..4a8b80ea8a 100644 --- a/internal/tui3/scrollback_test.go +++ b/internal/tui3/scrollback_test.go @@ -84,7 +84,7 @@ func TestAResumedConversationOpensOnItsTail(t *testing.T) { } } -// SCROLLING UP REACHES THE BEGINNING. This is the bug Santosh reported: he +// SCROLLING UP REACHES THE BEGINNING. This is the bug example reported: he // resumed a chat, scrolled up, and hit a wall a long way short of where the // conversation actually started. func TestScrollingUpReachesTheBeginningOfAResumedConversation(t *testing.T) { diff --git a/internal/tui3/settings.go b/internal/tui3/settings.go index 8b0739c6ab..9137681ee8 100644 --- a/internal/tui3/settings.go +++ b/internal/tui3/settings.go @@ -559,8 +559,6 @@ var settingUI = map[string]settingMeta{ // this door and `codeaf config` say the same word. config.KeyHints: { tab: tabWorkspace, label: "disable hints", widget: widgetToggle, - // NO `about` OF ITS OWN: the line under the row is the registry's hint, - // the owner's own wording (2026-09-24), said once ([settingMetaFor]). }, config.KeySplitPct: { tab: tabDisplay, label: "chat width", widget: widgetText, diff --git a/internal/tui3/settingsautonomy.go b/internal/tui3/settingsautonomy.go index 961fada5c3..48152b9d32 100644 --- a/internal/tui3/settingsautonomy.go +++ b/internal/tui3/settingsautonomy.go @@ -11,11 +11,10 @@ import ( // ── WHAT THIS PROJECT DOES WHILE NOBODY IS THERE, ON THE SETTINGS PAGE ────── // -// A SETTING THAT CHANGES WHAT THE PROGRAM DOES ON ITS OWN IS NEVER REACHABLE -// ONLY BY A SLASH COMMAND (owner ruling 2026-09-11). `/autonomy` has been the -// only door to these rules since they landed, and slash commands are invisible: -// a person who has never been told the word cannot find it, and this is the one -// setting that decides whether their work is answered without them. +// A SETTING THAT CHANGES WHAT THE PROGRAM DOES ON ITS OWN IS NEVER REACHABLE ONLY BY A +// SLASH COMMAND. `/autonomy` has been the only door to these rules since they landed, and +// slash commands are invisible: a person who has never been told the word cannot find it, +// and this is the one setting that decides whether their work is answered without them. // // So the rules have a row where settings are browsed. It is the SAME reader and // the SAME writer as the command — [app.autonomySheetText] prints what these diff --git a/internal/tui3/settingsautonomy_test.go b/internal/tui3/settingsautonomy_test.go index d71dec6625..78280abee4 100644 --- a/internal/tui3/settingsautonomy_test.go +++ b/internal/tui3/settingsautonomy_test.go @@ -39,8 +39,8 @@ func autonomySettingsApp(t *testing.T) *app { return a } -// A SETTING THAT CHANGES WHAT THE PROGRAM DOES ON ITS OWN IS NEVER REACHABLE -// ONLY BY A SLASH COMMAND (owner ruling 2026-09-11). +// A SETTING THAT CHANGES WHAT THE PROGRAM DOES ON ITS OWN IS NEVER REACHABLE ONLY BY A +// SLASH COMMAND. // // `/autonomy` was the only door to these rules, and a slash command is invisible: // somebody who has never been told the word cannot find the one setting that diff --git a/internal/tui3/settle_test.go b/internal/tui3/settle_test.go index cd82556500..467bb9993c 100644 --- a/internal/tui3/settle_test.go +++ b/internal/tui3/settle_test.go @@ -207,7 +207,7 @@ func TestBelowThe256RungAStreamingReplyIsUnpainted(t *testing.T) { } for _, row := range a.assistantRows(at, e, 60) { // The head is prose's, and prose answers the profile question for - // itself; only the tail is this lane's to leave alone. + // itself; only the tail is this test's to leave alone. if strings.Contains(plain(row), "length prefix") && row != plain(row) { t.Fatalf("at %v the streaming tail carries SGR: %q", profile, row) } diff --git a/internal/tui3/settledreceiptlaw_test.go b/internal/tui3/settledreceiptlaw_test.go index 04e537da06..f77066df60 100644 --- a/internal/tui3/settledreceiptlaw_test.go +++ b/internal/tui3/settledreceiptlaw_test.go @@ -25,8 +25,7 @@ import ( // other way — so the figure cannot be interpolated the way ONE SOURCE OF TRUTH // asks for (CLAUDE.md). What can be done is this: read the other number out of // the tree and fail when the relationship breaks, so the day somebody raises the -// surface's count the build says which other file has to move. The reason is -// lane A's (#954): the constant's own doc states the constraint, names this +// surface's count the build says which other file has to move. The the constant's own doc states the constraint, names this // figure, and says which half of its own value is the rule and which half is a // guess. func TestTheEngineKeepsAtLeastAsManyReceiptsAsTheSurfaceDraws(t *testing.T) { diff --git a/internal/tui3/slashchip.go b/internal/tui3/slashchip.go index f90f978c48..80eb5ee212 100644 --- a/internal/tui3/slashchip.go +++ b/internal/tui3/slashchip.go @@ -94,8 +94,8 @@ func knownCommand(word string) bool { // left to right. // // A CANDIDATE STARTS AT A WORD BOUNDARY and runs to the next space or newline. -// That one rule is what keeps a path out of this: "/Users/example" is a single -// candidate whose word is "Users/santosh" and matches nothing, rather than two +// That one rule is what keeps a path out of this: an absolute path is a single +// candidate whose whole word matches no command, rather than two // candidates one of which might. A slash with a letter in front of it — the one // in "http://", the one in "cmd/codeaf" — is not a candidate at all. A QUOTE IS // A WORD BOUNDARY TOO, on either side: prose that says '/budget 50' is naming @@ -136,7 +136,7 @@ func scanCommandSpans(value []rune, boundary, quoted bool) []segment { } // Everything up to the end of this token has been decided, chip or no // chip: the slashes inside a path are not boundaries, and re-examining - // them is how "/Users/example" would grow a chip on its second half. + // them is how "/workspace" would grow a chip on its second half. i = end } return out diff --git a/internal/tui3/startpagekeys_test.go b/internal/tui3/startpagekeys_test.go index 5e573b08a7..0c8adaa4b6 100644 --- a/internal/tui3/startpagekeys_test.go +++ b/internal/tui3/startpagekeys_test.go @@ -91,7 +91,7 @@ func TestTheQuestionIsAnsweredAgainOnceTheStartPageIsClosed(t *testing.T) { // AND THE PAGE IS NOT REFUSED OVER THE ROWS IT WAS ABOUT TO RECLAIM. // -// WHAT WAS MEASURED, on a merge of this branch with lane P's. A permission was +// THE REGRESSION SCENARIO. A permission was // waiting on a twenty-row terminal, and `ctrl+t` did nothing at all — no page, // no word. [app.openChatStart] asks whether there is a body region to stand the // page in, and it was asking [app.viewHeight], which is charged for the question diff --git a/internal/tui3/steer.go b/internal/tui3/steer.go index 0b65654fc6..9ac4361e00 100644 --- a/internal/tui3/steer.go +++ b/internal/tui3/steer.go @@ -427,11 +427,8 @@ func (a *app) tookSteer(msg steeredMsg) tea.Cmd { // typingHint is the send half of the running-turn hint while there is something // in the box or on the tray. // -// It teaches plain enter first, then the queue key where the terminal can send -// it and there are words to queue. THE STOP-AND-SEND CHORD IS NOT NAMED HERE, -// by the owner's call (2026-09-30): `ctrl+shift+enter` still stops and sends -// (bargein.go) and the key sheet lists it, but the slot it held on this line -// went to the queue key, which is pressed far more often. +// It teaches plain enter first, then the queue key where the terminal can send it and +// there are words to queue. // // enter steers it in · ctrl+enter queue var steerShortHint = "enter " + steerSendWord diff --git a/internal/tui3/steerelbow.go b/internal/tui3/steerelbow.go index 8032a7eef9..67bec22cdd 100644 --- a/internal/tui3/steerelbow.go +++ b/internal/tui3/steerelbow.go @@ -159,12 +159,11 @@ import ( // // ── AND THE SAME MARK SERVES THE OTHER PAGE ──────────────────────────────── // -// A task's page is one question — the instruction the work was given — and -// everything the person says on it after that is, by the nature of the page, a -// correction to work already moving. So it is drawn with this mark too: the -// elbow where it was said, no turn opened, and on replay a correction that reads -// as a correction rather than as a second brief (docs/design/lens/DESIGN.md, -// Decision 2 and the owner's ruling 2). +// A task's page is one question — the instruction the work was given — and everything the +// person says on it after that is, by the nature of the page, a correction to work already +// moving. So it is drawn with this mark too: the elbow where it was said, no turn opened, +// and on replay a correction that reads as a correction rather than as a second brief +// (docs/design/lens/DESIGN.md, Decision 2). // // ONE THING IS TRUE THERE THAT IS NOT TRUE HERE, and it earns the one field this // file added for it ([steerElbow.receipt]). A correction typed into this @@ -173,8 +172,7 @@ import ( // correction typed into a TASK crosses to ANOTHER AGENT, and there is a moment — // sometimes a long one, when the node had parked on the pieces it handed out — // in which nothing at all happens on the page. That silence is -// indistinguishable from the words having gone nowhere, and it is why the owner -// ruled (2026-09-01) that every task steer confirms delivery: +// indistinguishable from the words having gone nowhere, so every task steer confirms delivery: // // └ use the staging bucket, not production · delivered // diff --git a/internal/tui3/styles.go b/internal/tui3/styles.go index 1f0b078938..010f503da8 100644 --- a/internal/tui3/styles.go +++ b/internal/tui3/styles.go @@ -63,15 +63,13 @@ import ( // // ── THERE IS NO FIFTH COLOUR, AND THE VIOLET IS RETIRED ── // -// A question had a hue of its own here for a year — a violet (#C08FE8 dark, -// #6F3FA8 light), reserved for the moment the agent is WAITING FOR A PERSON and -// spent on the whole of it: the head, every answer, every key, the word in the -// status line. The owner retired it on 2026-09-11 (colour pick C) and the reason -// was not the hue. It was the AREA: home and the places had always said the same -// "waiting on you" in amber on ONE MARK, so the one object a person must act on -// was the one thing this surface said in two vocabularies, and a block painted -// four rows deep in a colour nobody else used read as an alarm rather than as a -// question. +// A question had a hue of its own here for a year — a violet (#C08FE8 dark, #6F3FA8 +// light), reserved for the moment the agent is WAITING FOR A PERSON and spent on the whole +// of it: the head, every answer, every key, the word in the status line. It was the AREA: +// home and the places had always said the same "waiting on you" in amber on ONE MARK, so +// the one object a person must act on was the one thing this surface said in two +// vocabularies, and a block painted four rows deep in a colour nobody else used read as an +// alarm rather than as a question. // // SO THE QUESTION IS AMBER AND THE AMBER IS STROKE, NEVER FILL. [palette.ask] // paints with `warn` — the same amber every other surface already spent on @@ -445,14 +443,9 @@ var ( // would be a surface where a tint said nothing, and the three steps that DO say // something are only legible because the fourth state is empty. // -// ── THE PAINTED PAGE THAT WAS TRIED, AND WHAT THE OWNER SAID ABOUT IT ─────── -// -// FIDELITY.md item 13 asked the places to bring their own ground — #12121A over -// every cell of home and the six places — on the reasoning that a surface which -// paints its own page no longer has to guess what is under it. It was built, and -// on 2026-08-25 the owner tested it and reversed it in one sentence: "i want bg -// color and text color to be same as in inside chat please this new bg looks -// weird i think we were taking user terminal stuff or something previously." +// FIDELITY.md item 13 asked the places to bring their own ground — #12121A over every cell +// of home and the six places — on the reasoning that a surface which paints its own page +// no longer has to guess what is under it. // // So THE TERMINAL'S OWN BACKGROUND SHOWS THROUGH EVERYWHERE, and the reason the // law originally gave for itself turns out to be the reading a person actually @@ -697,86 +690,10 @@ var ( lightMark = mustHue("#B7C0D1", flat) ) -// ── THE PLACE LADDER ──────────────────────────────────────────────────────── -// -// Everything above this line is the CONVERSATION's palette. Home and the six -// places beside it (pages.go) PAINT FROM IT TOO, and this block is the record of -// why there is no second table any more. -// -// FIDELITY.md item 1 asked for the design's own nine hexes on the places: three -// greys (#E6E6F0 / #A0A6BB / #7C8296), three colours (amber #EECE96, cyan -// #A4D7EA, green #A2E2BC) and three grounds (#12121A / #1D1D28 / #262633). It -// was built exactly, with place-scoped variants of the glare law, the isoluminant -// band and the ground ladder to admit it. Then the owner ran it, on 2026-08-25: -// -// "i want bg color and text color to be same as in inside chat please this new -// bg looks weird i think we were taking user terminal stuff or something -// previously" -// -// THE INKS ARE THE CHAT'S, MAPPED BY ROLE. That is the whole of what a place -// palette is now, and it is why [placeRampFrom] is nine lines rather than a -// table: every role a place paints has a reading the conversation already -// authored for the same reading, so the design's own semantics survive without a -// single new colour. -// -// the design's role what a place asks for the hue it gets -// the subject p.ink (bold for tier 1) [hueInk] #C6CDDA -// what is true of it p.muted [hueMuted] #7FA6C9 -// demoted prose p.narr [hueNarr] #848FA6 -// the margin p.dim [hueDim] #6B7280 -// NEEDS A HUMAN p.warn / p.ask [hueWarn] #EBCB8B (one hue) -// ALIVE p.accent [hueAccent] #9DC3E6 -// MONEY p.money [hueMoney] #90D0AA -// -// THE DESIGN'S THREE MEANINGS ARE KEPT AND ONLY THE HEXES ARE THE CHAT'S: amber -// is a person being waited on, the accent is work in flight this instant, and -// green is a figure in dollars. Home already warned in [hueWarn] before the -// fidelity wave, so the amber reading did not move at all — only the two points -// of lightness the design's own token table carried. -// -// ── THE ONE-ACCENT LAW, AS THE DESIGN'S OWN PREAMBLE STATES IT ────────────── -// -// The designer wrote it down and then flagged it as unresolved: "one accent per -// screen vs. two live states. I read the law as one accent per meaning — amber -// for waiting on a person, cyan for in flight, and nothing else in colour." -// -// That reading survives the reversal, because it is arithmetic about how many -// meanings a screen carries rather than a claim about which hexes carry them. So -// a place still RETIRES two of the conversation's roles rather than merely -// re-pointing them ([placeRampFrom]): -// -// - [hueData]'s cyan — the payload rule's identity ink — becomes the body ink -// on a place, because a lifted datum on a screen with three meanings lifts by -// being the SUBJECT tier, which is what SCREEN 2a says every hierarchy step -// past the fourth must do. -// - the question hue became the amber, because home used to say "a person is -// needed" in two colours and the design says it in one. Since 2026-09-11 that -// is true of the conversation too ([palette.ask]), so this one is no longer a -// re-point: there is nothing left to retire. -// - [hueAdd]'s olive — the tick on work that landed — becomes the second voice, -// because the glyph already says it landed and a hue saying it again spends -// the screen's colour budget on the least urgent fact on it. -// -// The conversation keeps the other two, untouched: a datum inside a conversation -// and a landed diff are different objects from a row on a list. -// -// The ONE hue that survives outside the design's three is [hueBad]'s orange-red. -// It is a deviation and it is flagged rather than hidden: the design's own token -// table has a Coral for broken, its preamble does not name it, and a failed row -// stripped of every non-glyph signal is a row whose failure is carried by one -// cell of punctuation. It stays until the owner says otherwise. -// -// ── AND THE GROUND IS THE TERMINAL'S, ON A PLACE AS IN A CHAT ─────────────── -// -// The painted page is gone with the inks that were authored against it. THE -// GROUND LADDER above is the only ladder, on every surface: rest is not a colour, -// and a place lifts a row off the terminal's own background only where a person -// put a pointer or a cursor on it ([hueCursor], [hueSelected], [hueMark]). -// -// The NoColor and plain profiles therefore need no special case here at all — -// there is nothing to suppress — and TestEveryPlaceHoldsAtThePlainFloor still -// walks every place with both floors on, because "legible as text with every -// escape removed" is a law about the layout rather than about the ground. +// THE PLACE LADDER. Home and the other places use the conversation palette by +// role. Sharing values keeps the failure hue, diff pair, identity ring, ground +// steps and thinking fade consistent. The terminal background shows through so +// the surface fits the active theme. // ramp is one whole ladder: every role this surface paints, resolved once. // @@ -838,12 +755,8 @@ var lightRamp = ramp{ // PALETTE IS ALREADY HOLDING, with the three roles THE ONE-ACCENT LAW retires // pointed at readings that table already carries. // -// IT AUTHORS NO COLOUR AND IT TAKES NO TABLE OF ITS OWN, and both halves of that -// are the point. The owner asked for the chat's inks on the places, and the -// shortest way to keep that true forever is for there to be nothing here to -// retune — every role a place does not retire (the failure hue, the diff pair, -// the identity ring, the three ground steps, the thinking fade) is the same -// colour on both surfaces because it is LITERALLY the same value. +// IT AUTHORS NO COLOUR AND IT TAKES NO TABLE OF ITS OWN, and both halves of that are the +// point. // // It takes the ramp rather than naming [darkRamp] or [lightRamp] so that a // MEASURED terminal reaches the places too: adaptive.go derives a whole ladder @@ -1164,21 +1077,10 @@ func resolveTheme(t theme, env func(string) string) theme { return t } -// onPlaces is THE PLACE LADDER'S ONE DOOR: the same terminal, the same profile, -// the same glyph floor, the same inks, with the three roles THE ONE-ACCENT LAW -// retires pointed elsewhere ([placeRampFrom]). -// -// It is called once per frame, by the two functions that draw a whole place — -// pages.go's [placeFrameWithBar] and home.go's [app.homeFrame] — and it is a -// VALUE returned rather than a field mutated, so a caller that forgets to put -// the old palette back gets a compile-time nothing rather than a conversation -// painted in home's colours. -// -// A MEASURED GROUND REACHES THE PLACES EXACTLY AS IT REACHES THE CONVERSATION, -// and that is a consequence of the reversal rather than a special case: this -// swap re-points three roles of whatever ladder the palette is already holding -// — adaptive.go's derived one included — and touches nothing else, so a place -// stands on the terminal's own background wearing the terminal's own ladder. +// THE PLACE LADDER. Home and the other places use the conversation palette by +// role. Sharing values keeps the failure hue, diff pair, identity ring, ground +// steps and thinking fade consistent. The terminal background shows through so +// the surface fits the active theme. func (p palette) onPlaces() palette { p.ramp = placeRampFrom(p.ramp) return p @@ -1359,9 +1261,6 @@ func (p palette) fading() bool { return false } -// ask is THE QUESTION HUE, and it is the amber every other surface already says -// "waiting on you" in ([hueWarn], owner ruling 2026-09-11, colour pick C). -// // IT IS A ROLE AND NOT A SECOND COLOUR. The conversation spent a violet of its // own on questions — and spent it on whole rows, which is COLOUR IS STROKE, // NEVER FILL broken on the one object a person must act on — while home, the diff --git a/internal/tui3/tabsignal_test.go b/internal/tui3/tabsignal_test.go index 4d6106f415..8f719e8595 100644 --- a/internal/tui3/tabsignal_test.go +++ b/internal/tui3/tabsignal_test.go @@ -439,7 +439,7 @@ func TestConversationWorkEdgesAndObservedRootCompletionsAreWorthAStir(t *testing } // A STATE THIS SURFACE CANNOT READ IS NOT EVIDENCE THAT WORK STOPPED. A -// proposal arrives on this lane before its node exists and carries no state at +// proposal arrives on this test before its node exists and carries no state at // all; treating "not a state I know" as settled is how a strip goes dark on a // conversation that is still working. A background job is left out for the // reason the roster leaves it out — it is counted in its own place. diff --git a/internal/tui3/taskcardhost_test.go b/internal/tui3/taskcardhost_test.go index 8b5c5e4464..0ad1c419b8 100644 --- a/internal/tui3/taskcardhost_test.go +++ b/internal/tui3/taskcardhost_test.go @@ -266,7 +266,7 @@ func TestAHostedRunningRoomFillsOnItsOwnBoundedBeat(t *testing.T) { // A HOSTED CARD NEVER OPENS A FILE ON THIS DISK. The path on the record is the // engine's; a read of it here is either nothing or a stranger's file, and it is // the read that produced the wrong sentence in the first place. The pin is a -// REAL journal at the far path, made on this machine — if anything in this lane +// REAL journal at the far path, made on this machine — if anything in this test // ever falls back to the local disk, this is what it would find. // // A HOSTED JOB'S LOG IS THE SAME LAW ON THE OTHER SURFACE, and it is pinned diff --git a/internal/tui3/taskphone.go b/internal/tui3/taskphone.go index 88c7ca8cc4..dad12ec78f 100644 --- a/internal/tui3/taskphone.go +++ b/internal/tui3/taskphone.go @@ -157,7 +157,7 @@ func (a *app) stripPhoneState() string { // PAGE and reads the project's record in behind it, exactly the door // [app.taskSheetKeyPress] opens on its key. It answers whether it took the press. // -// IT IS THE PAGE AND NOT THE OVERLAY COLUMN. The page is the surface this lane +// IT IS THE PAGE AND NOT THE OVERLAY COLUMN. The page is the surface this implementation // shaped into cards a thumb goes into, with a `‹ back` bar at its foot // (taskview.go); the overlay column ([app.railTake]) is a keyboard list under a // key legend, and a door that landed there would open the very thing this tier diff --git a/internal/tui3/taskrecord.go b/internal/tui3/taskrecord.go index 179cbc0338..a4800b8cbd 100644 --- a/internal/tui3/taskrecord.go +++ b/internal/tui3/taskrecord.go @@ -630,13 +630,12 @@ func (a *app) taskCardFrame(width, height int) ([]string, []taskCardHit, int, in } add(pal.dim(rule(width)), taskCardHitNone) - // THE PAGE ENTER LANDS ON FROM A `needs you` ROW SHOWS THE QUESTION IT - // NEEDS YOU FOR. The landing has been on the block above the conversation's - // box all along ([session.Agent.publishLandingQuestion]); this card is a - // place, the block is neither drawn nor keyed under a place, and a person - // sent here by `enter` read the whole report and found nothing to press - // (the owner, 2026-09-10). So the card draws the question's own head and - // answers row, from the block's own object, above its foot. + // THE PAGE ENTER LANDS ON FROM A `needs you` ROW SHOWS THE QUESTION IT NEEDS YOU FOR. The + // landing has been on the block above the conversation's box all along + // ([session.Agent.publishLandingQuestion]); this card is a place, the block is neither + // drawn nor keyed under a place, and a person sent here by `enter` read the whole report + // and found nothing to press. So the card draws the question's own head and answers row, + // from the block's own object, above its foot. asking := false if q, ok := a.taskRecordLanding(entry); ok { asking = true diff --git a/internal/tui3/tasksconversation_test.go b/internal/tui3/tasksconversation_test.go index ef82f108f9..6a70463bc9 100644 --- a/internal/tui3/tasksconversation_test.go +++ b/internal/tui3/tasksconversation_test.go @@ -153,8 +153,8 @@ func tasksCursorOn(a *app, name string) (int, bool) { // THE WORK HANGS UNDER THE CHAT THAT ASKED FOR IT, and the chat is a row. func TestEveryPieceOfWorkIsDrawnUnderItsOwnConversation(t *testing.T) { r := tasksChatReading() - // EVERY CONVERSATION OPENS SHUT (the owner's ruling, 2026-09-11) and what this - // test is about is the SHAPE behind that fold, so it reads the page after `→`. + // EVERY CONVERSATION OPENS SHUT and what this test is about is the SHAPE behind that + // fold, so it reads the page after `→`. if shut := tasksLineOf(t, r.lay(120), "Shipping the Gate"); !shut.folds || !shut.open { t.Fatalf("a conversation came out folds=%v open=%v, and every fold on this page opens open", shut.folds, shut.open) diff --git a/internal/tui3/tasksplace_test.go b/internal/tui3/tasksplace_test.go index 5fede192fa..59b794e740 100644 --- a/internal/tui3/tasksplace_test.go +++ b/internal/tui3/tasksplace_test.go @@ -600,9 +600,8 @@ func tasksPolishFixture() (session.World, session.UsageWindow, time.Time) { // tasksOpen is one reading with every fold open, for the tests that are about // something other than folding. // -// EVERY CONVERSATION AND EVERY FAMILY OPENS SHUT (the owner's ruling — see -// [tasksReading.opens]). A test written to look at a piece of work would be -// looking at the root standing over it instead, so it says which it means by +// EVERY CONVERSATION AND EVERY FAMILY OPENS SHUT. A test written to look at a piece of +// work would be looking at the root standing over it instead, so it says which it means by // asking for this. The tests that are ABOUT the folds do not call it. func tasksOpen(r tasksReading) tasksReading { r.unfolded = true diff --git a/internal/tui3/taskstable_test.go b/internal/tui3/taskstable_test.go index bbf6766508..2bb66806b8 100644 --- a/internal/tui3/taskstable_test.go +++ b/internal/tui3/taskstable_test.go @@ -335,10 +335,10 @@ func TestTheTasksFootNamesThePagesKeysOverAConversationToo(t *testing.T) { // ── the folds ─────────────────────────────────────────────────────────────── -// EVERY CONVERSATION AND EVERY FAMILY OPENS SHUT (owner, 2026-09-11), `→` opens -// one, and A TYPED FILTER OPENS EVERY CONVERSATION WITH A MATCHING ROW — then -// gives the person their own folds back when it clears. A row that matched and -// is sitting behind a fold is a row the query appears not to have found. +// EVERY CONVERSATION AND EVERY FAMILY OPENS SHUT, `→` opens one, and A TYPED FILTER OPENS +// EVERY CONVERSATION WITH A MATCHING ROW — then gives the person their own folds back when +// it clears. A row that matched and is sitting behind a fold is a row the query appears +// not to have found. func TestTasksOpenAllLevelsAndFilterRestoresExplicitFolds(t *testing.T) { a := tasksTableApp(t) width, _ := a.size() diff --git a/internal/tui3/teamcrew.go b/internal/tui3/teamcrew.go index 10dd5a2de2..107730dbb0 100644 --- a/internal/tui3/teamcrew.go +++ b/internal/tui3/teamcrew.go @@ -13,8 +13,7 @@ import ( // ── A TEAM'S MEMBERS: ACTIVE ONES ON THE HEADER, EVERYONE ON A CARD ───────── // -// The pane's header is one line (owner feedback 2026-09-24, which replaced two -// wrapped rows of every member as prose): +// The pane's header is one line: // // ● harbor ◆ Manager @news ⠿ working @review ? asking +4 idle $0.42 today Settings Close… Open ▦ // diff --git a/internal/tui3/teamlink.go b/internal/tui3/teamlink.go index 1c8f09e3eb..0d6c6b0627 100644 --- a/internal/tui3/teamlink.go +++ b/internal/tui3/teamlink.go @@ -36,7 +36,7 @@ import ( // opened so the row is there. Over --host against an engine without the teams // doors ([app.teamsOff]) the page cannot open, so the press still opens the // conversations view on that team, and the hint says that rather than the -// page. A member's hint names the title: `Open @security · santosh dev2 +// page. A member's hint names the title: `Open @security · example dev2 // branch… · click`. // // THE HOVER IS A GROUND, as every other control on this surface answers the diff --git a/internal/tui3/teams_test.go b/internal/tui3/teams_test.go index 0d4d69ddb5..4efca7ee3e 100644 --- a/internal/tui3/teams_test.go +++ b/internal/tui3/teams_test.go @@ -131,8 +131,7 @@ func TestTeamTabsMergeLiveAndKeepStoredOrder(t *testing.T) { } } -// A MEMBER THIS WINDOW DOES NOT HAVE OPEN GETS NO TAB. The strip is what is -// open here, narrowed to the team; the owner saw three tabs over a wall of one. +// A MEMBER THIS WINDOW DOES NOT HAVE OPEN GETS NO TAB. func TestTeamTabsDrawNoTabForAMemberNotOpenHere(t *testing.T) { sp := team{Name: "test", Members: []teamMember{ {Key: "a", File: "fa", Word: "alpha"}, diff --git a/internal/tui3/tokencol.go b/internal/tui3/tokencol.go index 6933e7787b..8161d0e56d 100644 --- a/internal/tui3/tokencol.go +++ b/internal/tui3/tokencol.go @@ -99,10 +99,10 @@ import ( // whole conversation, not the step it happens to be in, and a figure that // divided it between steps would be arithmetic nobody performed. // -// A ROW THAT HAS FINISHED CARRIES NOTHING. The column is a sign of motion, so -// it lives exactly as long as the motion does: a settled step drops its figure, -// and the whole column goes with the turn — this is the owner's ruling, and the -// session's totals are the status line's, which never go away. +// A ROW THAT HAS FINISHED CARRIES NOTHING. The column is a sign of motion, so it lives +// exactly as long as the motion does: a settled step drops its figure, and the whole +// column goes with the turn —, and the session's totals are the status line's, which never +// go away. // // IT IS SPARE CELLS AND NEVER A RESERVATION. The words are the point of every // row it lands on, so the column takes what is left at the right edge after the @@ -306,18 +306,13 @@ func (c *tokenCol) tick(written, turn, slots int, snap bool, now time.Time) bool // chaseFigure is one half's step toward its reading, and whether that step is // MOTION — the thing the glow is lit for. // -// A FIGURE THAT WAS NOT ON THE SCREEN ARRIVES WHOLE AND UNLIT. Every page opens -// its column at nothing ([tokenCol.open], a new room, a conversation taken up -// from a tab), and its first reading is a figure that already existed before -// anybody looked — the weight of a request, a task's tokens read off its -// journal. Walking it up from zero and lighting it on the way was the surface -// performing work that was not happening: the owner opened a task page, watched -// `↑ 79.6k ↓ 37.6k` count up and glow, switched away and back, watched it do -// the same climb to the same figures, and read a page being redrawn as a task -// being busy. It is [tokenCol.receiptOf]'s rule said for the walk and the glow -// too: THE FIRST READING IS A FIGURE ARRIVING, NOT A FIGURE GROWING, and only -// growth is drawn as growth. So from nothing the figure is simply there, and -// the first thing that lights it is the first time it actually moves. +// A FIGURE THAT WAS NOT ON THE SCREEN ARRIVES WHOLE AND UNLIT. Every page opens its column +// at nothing ([tokenCol.open], a new room, a conversation taken up from a tab), and its +// first reading is a figure that already existed before anybody looked — the weight of a +// request, a task's tokens read off its journal. It is [tokenCol.receiptOf]'s rule said +// for the walk and the glow too: THE FIRST READING IS A FIGURE ARRIVING, NOT A FIGURE +// GROWING, and only growth is drawn as growth. So from nothing the figure is simply there, +// and the first thing that lights it is the first time it actually moves. func chaseFigure(shown, target, slots int) (next int, grew bool) { if shown == 0 { return target, false diff --git a/internal/tui3/tokencol_test.go b/internal/tui3/tokencol_test.go index f2a91b49b3..58b25221e2 100644 --- a/internal/tui3/tokencol_test.go +++ b/internal/tui3/tokencol_test.go @@ -451,12 +451,9 @@ func TestATaskRoomCarriesItsOwnColumn(t *testing.T) { } } -// OPENING A TASK PAGE DOES NOT REPLAY THE CLIMB. The owner's report: every -// time a task was taken from the rail, its page counted `↑ 79.6k ↓ 37.6k` up -// from zero and lit both figures, then did the same climb to the same figures -// on the next visit — a page being built, drawn as a task being busy. A room is -// a new page with its column at nothing, so its first reading ARRIVES: whole, -// on the first frame, and at rest. The next visit is the same. +// OPENING A TASK PAGE DOES NOT REPLAY THE CLIMB. A room is a new page with its column at +// nothing, so its first reading ARRIVES: whole, on the first frame, and at rest. The next +// visit is the same. func TestOpeningATaskPageShowsItsFiguresWholeAndUnlit(t *testing.T) { a, fake, _ := roomApp(t) a.agent = &weighedRoomFake{roomFake: fake, weight: 79600} @@ -787,13 +784,10 @@ func TestASplitTurnCarriesTheColumnOnItsFrontierAlone(t *testing.T) { } } -// AND THE RUN ABOVE THE SPLIT DRAWS NO DOOR OF ITS OWN. It holds nothing but -// reasoning that is over — no step — and a window with no steps in it draws -// itself as `▸ Work · ctrl+e` (livesteps.go). Two of those on one page, keyed -// alike, is one turn claiming to be two pieces of running work; the owner read -// it as "things opening that don't need to". The reasoning goes back under the -// ordinary `thought for …` row, which is the chip a finished turn draws and -// which carries its own door onto the working. +// AND THE RUN ABOVE THE SPLIT DRAWS NO DOOR OF ITS OWN. It holds nothing but reasoning +// that is over — no step — and a window with no steps in it draws itself as `▸ Work · +// ctrl+e` (livesteps.go). The reasoning goes back under the ordinary `thought for …` row, +// which is the chip a finished turn draws and which carries its own door onto the working. // // Every `ctrl+e` on the page is counted and named, because the defect was not a // missing row but a second one that looked exactly like the right one. diff --git a/internal/tui3/toolclamp_test.go b/internal/tui3/toolclamp_test.go index fed7590649..1a8d207b2a 100644 --- a/internal/tui3/toolclamp_test.go +++ b/internal/tui3/toolclamp_test.go @@ -44,7 +44,6 @@ func clampArgs(field, value string) string { return string(b) } -// The command from the owner's report, which is the length this is all about. const clampCommand = `gh api "search/issues?q=repo:Agent-Field/codeaf+commenter:AbirAbbas&sort=created&order=desc&per_page=30" -q '.items[] | .number'` // callRowsOf is every row the transcript draws for a tool call — the line and diff --git a/internal/tui3/toolview.go b/internal/tui3/toolview.go index 3c8b248e2a..b86da13af9 100644 --- a/internal/tui3/toolview.go +++ b/internal/tui3/toolview.go @@ -1482,11 +1482,10 @@ func countUpRungs(big int, bigUnit string, small int, smallUnit string) string { // waiting on a person, in which case the whole row is the question. func (a *app) paintName(e *entry, name string) string { if e.status == toolConsent { - // THE WORDS ARE INK AND THE MARK IS THE AMBER (owner ruling 2026-09-11, - // colour pick C). A row waiting on a person already wears `?` in the - // gutter; painting its name and its target in the question hue as well - // was the same claim made three times, and it made the transcript shout - // at the exact moment a person was trying to READ a command. + // THE WORDS ARE INK AND THE MARK IS THE AMBER. A row waiting on a person already wears + // `?` in the gutter; painting its name and its target in the question hue as well was + // the same claim made three times, and it made the transcript shout at the exact moment + // a person was trying to READ a command. return a.pal.ink(name) } return a.pal.muted(name) diff --git a/internal/tui3/topnav.go b/internal/tui3/topnav.go index 3c86f7387d..fa9f7d6b42 100644 --- a/internal/tui3/topnav.go +++ b/internal/tui3/topnav.go @@ -262,7 +262,7 @@ func (a *app) navTails(pal palette, mode pulseMode) [7]string { if name := strings.TrimSpace(a.host); name != "" { // THE MACHINE THESE PAGES ARE ABOUT, dim, and nothing at all on a local // session: it is invisible when there is nothing to say (host.go). It is - // `on spark` rather than a bare `spark` so it cannot read as a place. + // `on laptop` rather than a bare `laptop` so it cannot read as a place. host = pal.dim(placeMachineLead + name) } rung := func(parts ...string) string { diff --git a/internal/tui3/vianews_test.go b/internal/tui3/vianews_test.go index 21775cc267..0b5e0c11d3 100644 --- a/internal/tui3/vianews_test.go +++ b/internal/tui3/vianews_test.go @@ -2,10 +2,8 @@ package tui3 // WHY `via <provider>` AND tok/s WENT MISSING, one test per cause. // -// The owner, 2026-09-10: "at some times I don't see infra provider and tok/sec, -// I am not sure when it does not show up, maybe when I have follow up or -// something". It was not one bug with a random trigger; it was six, each with a -// trigger a person would never connect to the gap: +// It was not one bug with a random trigger; it was six, each with a trigger a person would +// never connect to the gap: // // 1. any model with a reasoning level set lost the live rate, because the // status row lent the model field `id:level` for its draw and the rate is @@ -105,11 +103,10 @@ func TestAReasoningLevelNoLongerHidesTheLiveRate(t *testing.T) { // ── 2. the vendor serving its own model ───────────────────────────────────── -// `via` IS ON THE SEAM WHOEVER SERVED, which is the owner's ruling of -// 2026-09-09. The seam spells the model as its basename, so the vendor is not on -// the screen; the lane layer's rider still went quiet when the machine's name -// was inside the id, and over an engine host nothing under it had anything to -// say — so `deepseek/…` answered by DeepSeek drew no provider at all. +// `via` IS ON THE SEAM WHOEVER SERVED. The seam spells the model as its basename, so the +// vendor is not on the screen; the lane layer's rider still went quiet when the machine's +// name was inside the id, and over an engine host nothing under it had anything to say — +// so `deepseek/…` answered by DeepSeek drew no provider at all. func TestTheSeamSaysViaWhenTheVendorServesItsOwnModel(t *testing.T) { a, now := newsApp(t, flash) PostLaneNews(LaneNews{Model: flash, Lane: "DeepSeek", Role: lane.RoleTalk, At: now}) @@ -303,13 +300,10 @@ func TestAnEngineWithTheNewsIsNeverCalledOlder(t *testing.T) { // ── 7. the machine stays ──────────────────────────────────────────────────── -// THE MACHINE IN BRACKETS DOES NOT AGE OUT. Until 2026-09-17 the seam's `via` -// went quiet ten minutes after the last answer, so a conversation read after -// lunch said `deepseek-v4-flash ·` and nothing — the owner read that as the -// provider having gone missing. Who answered last is a fact until somebody -// else answers, and the seam says it for as long as the window is open; the -// sheet's `served` row keeps the window, because the figures beside its name -// are about one answer (lanes.go's [riderBeside]). +// THE MACHINE IN BRACKETS DOES NOT AGE OUT. Who answered last is a fact until somebody +// else answers, and the seam says it for as long as the window is open; the sheet's +// `served` row keeps the window, because the figures beside its name are about one answer +// (lanes.go's [riderBeside]). func TestTheSeamKeepsNamingTheLastMachineAfterTheWindowClosed(t *testing.T) { a, now := newsApp(t, flash) PostLaneNews(LaneNews{Model: flash, Lane: "Baidu", Role: lane.RoleTalk, At: now.Add(-servedWindow - time.Hour)}) diff --git a/internal/tui3/view.go b/internal/tui3/view.go index 4e3ce9fefe..f419cd9516 100644 --- a/internal/tui3/view.go +++ b/internal/tui3/view.go @@ -1023,7 +1023,7 @@ func (a *app) chromeBaseHeight() int { // the status line, where a place draws one blank, its rule, its box and its hint // on the same clearance ([spacingRuleClearance], pages.go's [placeFrame]). It // used to keep a second blank under the box that no place has, so `esc` from -// home into a chat moved the box and the rule up a row (PLACES-AUDIT.md, lane K). +// home into a chat moved the box and the rule up a row. // // AND A QUESTION'S PAGE BRINGS ITS OWN RULE (questionroom.go's // [app.questionFootRows]): the rule that closes its two panes meets their seam @@ -1258,8 +1258,7 @@ func (a *app) viewHeight() int { // that cannot honestly act. So the rows the block is holding are rows the page // is about to reclaim, and measuring the frame as it stands would refuse the // page over its own space: on a twenty-row terminal with a permission waiting, -// `ctrl+t` did exactly nothing, and said nothing either (#677, found on the -// taller frame lane P draws a consent in). +// `ctrl+t` did exactly nothing, and said nothing either. // // IT IS THE ONLY QUESTION THIS ANSWERS. A page whose own content will not fit is // still the page's business ([startTinyWord]); what is settled here is whether diff --git a/internal/tui3/walldock.go b/internal/tui3/walldock.go index c091c7b9fd..a1c0d9107b 100644 --- a/internal/tui3/walldock.go +++ b/internal/tui3/walldock.go @@ -11,10 +11,8 @@ import ( // ── THE DOCK: EVERY OPEN CONVERSATION, UNDER THE BOX ──────────────────────── // -// The wall's door used to be a `⊞` at the right end of the tab strip, which is -// the far end of the frame from where a person's hands are. The owner asked for -// it to come down to where people type, so the row under the box ends in a -// small map of every conversation this window has open: +// The wall's door used to be a `⊞` at the right end of the tab strip, which is the far end +// of the frame from where a person's hands are. // // › say what you want done // alt+k chats · / commands ▦ All ▪▪▣▪ diff --git a/internal/tui3/walldock_test.go b/internal/tui3/walldock_test.go index 5c47b49cab..a9d4155ae7 100644 --- a/internal/tui3/walldock_test.go +++ b/internal/tui3/walldock_test.go @@ -60,7 +60,7 @@ func TestDockDrawsEveryConversationInStripOrder(t *testing.T) { // AN INERT WATCHER, as the strip's own signal tests use (tabsignal_test.go's // [signalLab]). The live one's goroutine stores its first reading of the // agent when it starts, and a flag set here before that could be put - // back to idle under the second render: red 4 times in 30 on Spark. + // back to idle under the second render: red 4 times in 30 on test machine. held.watch = &behindWatch{key: tab.key, agent: held.conv.Agent} if working == "" { held.watch.turning.Store(true) diff --git a/internal/tui3/watching.go b/internal/tui3/watching.go index 12650a66ea..d3ca4e02ca 100644 --- a/internal/tui3/watching.go +++ b/internal/tui3/watching.go @@ -56,7 +56,7 @@ type Driving struct { // and it draws nothing at all. Yours bool // Machine is the name of the machine whose window has the keyboard — - // `spark`, `macbook` — and the empty string when the far end could not say. + // `laptop`, `macbook` — and the empty string when the far end could not say. Machine string // Here says the window with the keyboard is another window on THIS machine, // which a person reads as one they forgot rather than as a machine they @@ -81,7 +81,7 @@ func (a *app) watching() bool { // watchWord is the line that stands where the composer stands, and it is the // whole of what a watcher is told: // -// typing from spark now · enter takes it back +// typing from laptop now · enter takes it back // // `another window` is what it says about a window on this same machine, because // that is the word codeaf already uses at home for a conversation open somewhere diff --git a/internal/tui3/welcome.go b/internal/tui3/welcome.go index 44f00b3359..bb05ce605a 100644 --- a/internal/tui3/welcome.go +++ b/internal/tui3/welcome.go @@ -455,7 +455,7 @@ func (a *app) resumeSession(chosen Session) tea.Cmd { // is holding, and it is ONE SENTENCE IN ONE PLACE. // // It replaces the engine's own error, which reads -// `session file: /Users/…/b9c0d3ad…/transcript.jsonl is open in another codeaf` +// `session file: /workspace/b9c0d3ad…/transcript.jsonl is open in another codeaf` // — a full path, wrapped across two lines of somebody's conversation, naming a // directory they have never had a reason to look at and a fact they cannot act // on. The path is not the news. The news is that the conversation is open @@ -637,12 +637,8 @@ func (a *app) welcomePress(slot int) tea.Cmd { // first screen of a fresh install (TestTheWordmarkCanSpellTheProductsWholeName // is what holds the two together). // -// THE WORD IS SPELLED `codeaf` AND DRAWN `CodeAF`. The table is keyed by the -// letters of [product], which is the one spelling every sentence uses, but the -// forms under `a` and `f` are capitals: the owner wants the two letters at the -// end to stand up out of the word (2026-09-17), and a letterform table is the -// one place a drawing may differ from the text without the text changing. The -// terminal that gets the word instead of the drawing still gets `codeaf`. +// THE WORD IS SPELLED `codeaf` AND DRAWN `CodeAF`. The terminal that gets the word instead +// of the drawing still gets `codeaf`. // // THE TOP ROW IS THE CAP LINE AND THE BASELINE IS ONE LINE, and both come from // one fact about box-drawing: a bar sits at the MIDDLE of its cell and only a @@ -688,12 +684,9 @@ var wordmarkGlyphs = map[rune][4]string{ // make a hole of the two blanks below. 'e': {" ", "┌─┐", "├─╴", "└─┘"}, 'n': {" ", "┌─┐", "│ │", "╵ ╵"}, - // A CAPITAL: the apex on the cap line, the crossbar a third of the way up, - // and two legs that reach the baseline apart. It used to be `┌─┐ / ├─┤ / - // └─┘`, which is not an `a` but two closed bowls of equal size stacked on - // each other, and two equal closed bowls are an `8` — which is what the - // owner read on the first screen. Opening the bottom is what makes it a - // letter, and the crossbar is what keeps it from being the `n` above. + // A CAPITAL: the apex on the cap line, the crossbar a third of the way up, and two legs + // that reach the baseline apart. Opening the bottom is what makes it a letter, and the + // crossbar is what keeps it from being the `n` above. 'a': {"┌─┐", "│ │", "├─┤", "╵ ╵"}, // A CAPITAL, AND THE TOP ARM IS THE LONGER ONE. Both arms of the old `f` // were two cells, which is a lowercase `f` drawn without its hook and reads diff --git a/internal/tui3/wiring_test.go b/internal/tui3/wiring_test.go index 6abdfb65a1..4fa9bd554c 100644 --- a/internal/tui3/wiring_test.go +++ b/internal/tui3/wiring_test.go @@ -463,7 +463,7 @@ func TestTheWideningYesTakesItsOwnRoad(t *testing.T) { // The line puts the question and its answers on one row, and on a frame with no // room for that the honest shape is the card — an offer with its tail truncated // is an offer that hides an answer, and the answer it hides is the last one, -// which on this lane is `deny`. Forms promote and never demote +// which on this test is `deny`. Forms promote and never demote // (docs/design/questions/DESIGN.md). func TestANarrowFrameGivesEveryAnswerARowRatherThanCuttingOne(t *testing.T) { _, a := wired([]session.Event{ @@ -593,11 +593,7 @@ func TestCtrlEnterQueuesAMessageForAfterTheTurnAndDrawsTheQueue(t *testing.T) { if a.input.String() != "" { t.Fatalf("the box kept %q", a.input.String()) } - // THE QUEUE IS DRAWN MESSAGE BY MESSAGE, in a register nothing sent wears: - // the row sits above the box led by the return arrow in dim ink, and - // NOTHING is drawn under it — the line that once explained the block is - // gone by the owner's call (followup.go). A count alone made a person guess - // which of their sentences were still queued. + // A count alone made a person guess which of their sentences were still queued. w, _ := a.size() rows := a.followRows(w) if len(rows) != 1 { diff --git a/internal/tui3/workfold.go b/internal/tui3/workfold.go index 68171b256e..c7d1aacbfb 100644 --- a/internal/tui3/workfold.go +++ b/internal/tui3/workfold.go @@ -46,47 +46,9 @@ type workfold struct { phase bool } -// deckFolds is the chips ONE PAGE draws, resolved through the lens's fold style -// (lens.go's [folders]). -// -// ── THE LAW THIS USED TO STATE, AND THE RULING THAT REVERSED IT ───────────── -// -// ~~A ROOM FOLDS NOTHING. The chip is an affordance of the conversation and it -// earns its place there. A turn out in the thread is a question somebody asked -// and the answer they were given, and the machinery between the two is work -// they delegated precisely so they would not have to watch it — so it -// collapses, and the page reads back as the exchange it was. A room is the -// opposite errand. It is the page somebody opened BECAUSE they want to read the -// machinery, and a node's whole life is one long turn with a report at the end -// of it — so the same rule swallowed the entire page the instant the node -// stopped running, leaving `▸ worked · 10 tool calls · ctrl+e` and the report -// under it. It is stated as an absence of folds rather than as a fold that -// opens itself, because [deck.workOpen] is the READER'S own answer and a -// default that had to be inverted for one kind of page would give that map two -// meanings.~~ -// -// > RULED BY THE OWNER, 2026-09-01 (issue #252, ruling 1): FOLD THE PAST. -// > "The task page folds settled work into phase chips by default; the -// > machinery stays one keypress away (ctrl+e / scroll-up). This reverses -// > the written law at workfold.go:26-52 … and the three tests pinning it." -// -// THE ARGUMENT THE RULING ENCODES, because the struck text above is a good -// argument for the wrong page. It optimises the RARE visit — the audit — at the -// cost of the common one. A person goes to a task to steer and to check, not to -// read a transcript, and a page built on the premise that every call must be -// read is the industry's linear machinery scroll reproduced one level down. The -// reversal was possible without giving up the audit because the old law's own -// objection — a chip per TURN swallows a page that is one turn — is answered by -// folding per PHASE instead ([derivePhaseFolds]): settled machinery and its -// narration collapse together, while the latest paragraph and live frontier -// remain visible. And [deck.workOpen] keeps its one meaning: chips default shut -// and the reader's expansion is still the reader's. -// -// THE DOORS, all three, because DISCOVERABILITY BEFORE PURITY: `ctrl+e` opens -// the newest chip ([app.toggleLatestWorkfold]), a click opens any of them -// (app.go's [app.press]), and a scroll up at the top of a room opens the one -// nearest the top (room.go's [app.roomUnfoldAtTop]) — which is what keeps the -// disclosure ladder from dead-ending (docs/THREAD-UX.md). +// deckFolds resolves a page's chips through its lens fold style. Settled task +// work folds into phase chips by default so the result is readable; ctrl+e and +// scrolling keep the details reachable. func (a *app) deckFolds(d deck) map[int]workfold { fold, ok := folders[d.lens.foldPast] if !ok { diff --git a/internal/wirelog/wirelog.go b/internal/wirelog/wirelog.go index 1fe8987f1f..0886e4e1dd 100644 --- a/internal/wirelog/wirelog.go +++ b/internal/wirelog/wirelog.go @@ -18,7 +18,7 @@ // as it did before. The cost of the meter when it is off is one LookupEnv at // boot. // -// The log is deliberately dumb — four space-separated integers per line, one +// The log is deliberately simple — four space-separated integers per line, one // line per wall-clock second, silent seconds included as zeros so a reader can // tell "nothing was drawn" from "the process was gone": // diff --git a/scripts/ledger.py b/scripts/ledger.py index 2495269a98..cbb30ee0d0 100755 --- a/scripts/ledger.py +++ b/scripts/ledger.py @@ -1,18 +1,7 @@ #!/usr/bin/env python3 -"""Assemble docs/design/polish/LEDGER.md from the per-surface audits beside it. - -The audits are where a defect is written down in full: what it is, the line -that decides it, why it costs a developer something, the fix shape, the -severity and the frames it was seen on. The ledger is the one ORDERED list the -owner reads, so it is GENERATED from them and never edited by hand — an edit -here would be a second copy of a number that is already written down somewhere -else, and a second copy is a copy that will drift. - -A row CLOSES when the audit that holds it names its number under `## fixed`, -which is the same thing as saying it closes on a captured before/after pair, -because that is what a lane has to put there. The spellings below are the ones -the lanes actually write — a table row, a bolded number, a `Row N` heading — -and a spelling nobody uses is not worth matching. +"""Assemble an ordered report from the adjacent surface reports. + +Rows close when their source report lists them under the fixed heading. """ import datetime @@ -43,7 +32,7 @@ ROW = re.compile(r"^(\d+)\. (.*)$") # A `## fixed` SECTION IS NOT ALL CLOSURES. Every lane writes its own account of # what it did NOT do under a sub-heading — `### skipped, and why`, `### Not fixed -# here`, `### Not done by this lane` — and those paragraphs name row numbers too. +# here` and deferred-work sections — and those paragraphs name row numbers too. # Reading them as closures counted twenty-eight rows as done that their own audit # says are open, in a ledger whose whole purpose is to be believable. So the # closures are the sub-blocks that are not disclaimers, and a heading has to earn @@ -102,7 +91,7 @@ def closures_only(fixed: str) -> str: for line in fixed.splitlines(): # A `##` OPENS A NEW SECTION AND CLEARS BOTH GATES. A lane that comes back # for a second pass writes `## fixed — the second pass` under the first - # pass's closing `### Not done by this lane`, and a gate that only ever + # pass's closing deferred-work section, and a gate that only ever # reset on `###` swallowed the entire second pass — four rows of real work # read as nothing at all. A ledger errs in both directions or it is not a # ledger, so this is checked the same way the generous direction is. diff --git a/scripts/measure/benchmove/summarize.py b/scripts/measure/benchmove/summarize.py index 685c7ed81a..8ea88347d3 100644 --- a/scripts/measure/benchmove/summarize.py +++ b/scripts/measure/benchmove/summarize.py @@ -1,13 +1,5 @@ #!/usr/bin/env python3 -"""summarize.py <out dir>: rows.jsonl -> summary.json and summary.md (median [min-max] of the reps). - -Dollars use the hosted price table of docs/STAGE-1H-DECISION.md (marginal, beyond every free tier), rule (a): - Worker request $0.30/M (every relay request), Worker CPU 3 ms assumed per request at $0.02/M ms, - Durable Object request $0.15/M (every directory request), R2 Class A $4.50/M (a frame put), - R2 Class B $0.36/M (an object get; one B per get is a lower bound), R2 storage $0.015/GB-month. -Operation counts come from the client's own wire meter, so they are what the Worker would be asked, not -what the docker relay did. -""" +"""Summarize repeated runs from rows.jsonl into summary.json and summary.md.""" import json, statistics, sys from collections import defaultdict from pathlib import Path @@ -115,7 +107,7 @@ def summary(rows): def usermonth(rows): - """dollars per active user-month for the STAGE-1H session shape (8 sessions of 30 minutes, a publish every 30 s, + """dollars per active user-month for the sampled session shape (8 sessions of 30 minutes, a publish every 30 s, 30 lease keepalives, 20% of sessions end in a move) from the measured per-operation counts.""" g = group(rows) env = sorted({k[0] for k in g}, key=lambda e: (e != "same-box", e))[0] diff --git a/scripts/qv-drive.sh b/scripts/qv-drive.sh index 7fbf1736b6..902b686117 100755 --- a/scripts/qv-drive.sh +++ b/scripts/qv-drive.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# THE SCREEN DRIVE FOR THE QUESTION VIEWS (lane P, tracking issue #830). +# THE SCREEN DRIVE FOR THE QUESTION VIEWS. # # It opens THIS worktree's own binary in a tmux session of its own, on a home of # its own, with one of questiondemo.go's fixtures named in the environment, and From f8b013dc170166f045ffbda60953f5eb079e1627 Mon Sep 17 00:00:00 2001 From: santoshkumarradha <instrument.santosh@gmail.com> Date: Sat, 24 Oct 2026 13:05:27 -0400 Subject: [PATCH 2/3] Number the change entry Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --- .../unreleased/{source-comments.md => 1923-source-comments.md} | 1 + 1 file changed, 1 insertion(+) rename docs/changes/unreleased/{source-comments.md => 1923-source-comments.md} (92%) diff --git a/docs/changes/unreleased/source-comments.md b/docs/changes/unreleased/1923-source-comments.md similarity index 92% rename from docs/changes/unreleased/source-comments.md rename to docs/changes/unreleased/1923-source-comments.md index 8395cf151d..8dd9e99332 100644 --- a/docs/changes/unreleased/source-comments.md +++ b/docs/changes/unreleased/1923-source-comments.md @@ -1,6 +1,7 @@ --- kind: changed title: Tidy source comments and add a comment style check +pr: 1923 surface: [build] invalidates: [] --- From 11f32bae6b4ef23680385cb18d66e636ef0a479e Mon Sep 17 00:00:00 2001 From: santoshkumarradha <instrument.santosh@gmail.com> Date: Sat, 24 Oct 2026 13:11:28 -0400 Subject: [PATCH 3/3] Keep the comment check free of private terms Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --- internal/commentlaw/commentlaw_test.go | 97 ++++++++++++++++++-------- 1 file changed, 68 insertions(+), 29 deletions(-) diff --git a/internal/commentlaw/commentlaw_test.go b/internal/commentlaw/commentlaw_test.go index e9a8d498d4..f8112f5d6e 100644 --- a/internal/commentlaw/commentlaw_test.go +++ b/internal/commentlaw/commentlaw_test.go @@ -17,7 +17,6 @@ import ( var rules = []*regexp.Regexp{ regexp.MustCompile(`(?i)\b(?:the\s+owner|owner's)\s+(?:has\s+(?:already\s+)?)?(?:asked|ruled|decided|ruling|feedback|report|review|wants|picks?)\b|ruled by the owner`), regexp.MustCompile(`(?i)\bthis lane\s+(?:added|fixes|proves|ends|may not edit|measured|replaces)|(?-i:\blane [A-Z][0-9]*\b)|\b(?:ai|coding|development) lane\b`), - regexp.MustCompile(`(?i)\b(?:spark|blackmac|dgx|dumb|studio|santosh|abir|zeropoint)\b`), regexp.MustCompile(`(?i)(?:^|[\s"'(\x60])/(?:home|Users)/[^/\s]+|(?-i:STAGE-[0-9][A-Z0-9-]*(?:\.md)?)|\b(?:LEDGER|DECISION)\.md`), regexp.MustCompile(`(?i)\b(?:opencode|claude code|codex|pi)\b`), regexp.MustCompile(`(?i)\b(?:faster|slower|better|worse|versus|compared|unlike)\b[^.\n]{0,80}\b(?:opencode|claude code|codex|pi)\b|\b(?:opencode|claude code|codex|pi)\b[^.\n]{0,80}\b(?:faster|slower|better|worse|versus)\b`), @@ -28,13 +27,34 @@ var rules = []*regexp.Regexp{ var exceptions = []struct { path, text *regexp.Regexp rule int - term string + terms map[string]struct{} }{ - {regexp.MustCompile(`\.go$`), regexp.MustCompile(`(?i)codex/gpt|CLI|provider|transport|codexauth|sign.in|model|catalog|account|credential|service|backend|profile|272k|window|context|skills?|plugin|agentskills\.io`), 4, "codex"}, // Codex is an authenticated model service. - {regexp.MustCompile(`^(internal/(skills|home|store|resident|session)/|cmd/codeaf/)`), regexp.MustCompile(`(?i)skills?|plugins?|agentskills\.io|registry|settings\.json`), 4, "skills"}, // Skill discovery reads other tools' file formats. - {regexp.MustCompile(`^(internal/exec/bare/|internal/session/|internal/tui3/toolstat\.go|cmd/harness-design/)`), regexp.MustCompile(`(?i)\bpi\b`), 4, "pi"}, // The tool library preserves compatible wire schemas and results. - {regexp.MustCompile(`\.go$`), regexp.MustCompile(`(?i)TERM.?=.?dumb|dumb terminal|TERM unset or.*dumb|found a dumb|LM Studio`), 2, "terminal"}, // Terminal capabilities and provider names are protocols. - {regexp.MustCompile(`^internal/tui3/(spark|wallcontract|wallview|render|spendplace|homegrid)\.go$`), regexp.MustCompile(`(?i)\bspark\b`), 2, "spark"}, // Spark names a chart sample or field in these renderers. + {regexp.MustCompile(`\.go$`), regexp.MustCompile(`(?i)codex/gpt|CLI|provider|transport|codexauth|sign.in|model|catalog|account|credential|service|backend|profile|272k|window|context|skills?|plugin|agentskills\.io`), 3, map[string]struct{}{"codex": {}}}, // Codex is an authenticated model service. + {regexp.MustCompile(`^(internal/(skills|home|store|resident|session)/|cmd/codeaf/)`), regexp.MustCompile(`(?i)skills?|plugins?|agentskills\.io|registry|settings\.json`), 3, map[string]struct{}{"claude code": {}, "opencode": {}, "codex": {}}}, // Skill discovery reads other tools' file formats. + {regexp.MustCompile(`^(internal/exec/bare/|internal/session/|internal/tui3/toolstat\.go|cmd/harness-design/)`), regexp.MustCompile(`(?i)\bpi\b`), 3, map[string]struct{}{"pi": {}}}, // The tool library preserves compatible wire schemas and results. +} + +func exempt(rule int, path, text, term string) bool { + for _, ex := range exceptions { + if _, ok := ex.terms[term]; ok && ex.rule == rule && ex.path.MatchString(path) && ex.text.MatchString(text) { + return true + } + } + return false +} + +// Private terms stay in the test environment rather than the public rules. +func commentRules() []*regexp.Regexp { + var terms []string + for _, term := range strings.Split(os.Getenv("COMMENTLAW_PRIVATE_TERMS"), ",") { + if term = strings.TrimSpace(term); term != "" { + terms = append(terms, regexp.QuoteMeta(term)) + } + } + if len(terms) == 0 { + return rules + } + return append(append([]*regexp.Regexp(nil), rules...), regexp.MustCompile(`(?i)\b(?:`+strings.Join(terms, "|")+`)\b`)) } func TestSourceComments(t *testing.T) { @@ -48,6 +68,7 @@ func TestSourceComments(t *testing.T) { } func violations(root string) []string { + rules := commentRules() var found []string for _, scope := range []string{"cmd", "internal", "scripts", "relay/src", "bench/canary", "bench/run.sh"} { err := filepath.WalkDir(filepath.Join(root, scope), func(path string, d fs.DirEntry, err error) error { @@ -87,14 +108,7 @@ func violations(root string) []string { } for _, match := range matches { term := strings.ToLower(c.text[match[0]:match[1]]) - allowed := false - for _, ex := range exceptions { - if ex.rule == i && ex.path.MatchString(rel) && ex.text.MatchString(c.text) && (i != 2 || ex.term == "spark" && term == "spark" || ex.term == "terminal" && (term == "dumb" || term == "studio")) && (i != 4 || ex.term == term || ex.term == "skills" && (term == "claude code" || term == "opencode" || term == "codex")) { - allowed = true - break - } - } - if !allowed { + if !exempt(i, rel, c.text, term) { found = append(found, fmt.Sprintf("%s:%d: comment should describe product behavior: %s", rel, c.line+strings.Count(c.text[:match[0]], "\n"), term)) } } @@ -268,20 +282,20 @@ func scriptComments(path, body string) []comment { } func TestCommentPatternsAndBoundaries(t *testing.T) { + t.Setenv("COMMENTLAW_PRIVATE_TERMS", "") cases := []struct { name, path, body string want int }{ {"Go attribution", "internal/example/source.go", "package example\n// The owner asked for this behavior.\nvar x=1\n", 1}, - {"block and inline comments", "cmd/example/source.go", "package main\n/* Abir requested this. */\nvar x=1 // lane A measured this.\n", 2}, - {"JavaScript", "relay/src/source.js", "const url='https://example.com'; // measured on Spark\n/* /Users/name/work */", 2}, - {"Python docstring", "scripts/source.py", "\"\"\"Measured on Spark.\"\"\"\n", 1}, - {"Python", "scripts/source.py", "text = '# Spark'\n# STAGE-1-CONTRACTS.md\n", 1}, - {"shell heredoc", "scripts/example.sh", "cat <<'EOF'\n# Spark\nEOF\n# Describe the product.\n", 0}, - {"Python string", "scripts/source.py", "data=\"\"\"# Spark\"\"\"\n", 0}, - {"template literal", "relay/src/source.js", "const text=`// Spark`; // Describe the product.\n", 0}, - {"shell", "bench/run.sh", "echo '# Spark' # blackmac\n", 1}, - {"quoted words", "internal/example/source.go", "package example\nvar x=\"the owner asked on Spark\"\n", 0}, + {"block and inline comments", "cmd/example/source.go", "package main\n/* The owner asked for this. */\nvar x=1 // lane A measured this.\n", 2}, + {"JavaScript", "relay/src/source.js", "const url='https://example.com'; // the owner asked\n/* /Users/name/work */", 2}, + {"Python docstring", "scripts/source.py", "\"\"\"The owner asked for this.\"\"\"\n", 1}, + {"Python", "scripts/source.py", "text = '# the owner asked'\n# STAGE-1-CONTRACTS.md\n", 1}, + {"shell heredoc", "scripts/example.sh", "cat <<'EOF'\n# the owner asked\nEOF\n# Describe the product.\n", 0}, + {"Python string", "scripts/source.py", "data=\"\"\"# the owner asked\"\"\"\n", 0}, + {"template literal", "relay/src/source.js", "const text=`// the owner asked`; // Describe the product.\n", 0}, + {"quoted words", "internal/example/source.go", "package example\nvar x=\"the owner asked\"\n", 0}, {"multiline attribution", "internal/example/source.go", "package example\n// The owner\n// ruled that this works.\n", 1}, {"documentation URL", "internal/example/source.go", "package example\n// https://example.com/docs/home/getting-started\n", 0}, {"public issue", "internal/example/source.go", "package example\n// Avoid duplicate delivery after reconnect (#123).\n", 0}, @@ -289,11 +303,11 @@ func TestCommentPatternsAndBoundaries(t *testing.T) { {"comparison", "internal/config/source.go", "package config\n// The Codex model service is faster than other tools.\n", 1}, {"authentication", "internal/config/source.go", "package config\n// The Codex model service requires an account bearer.\n", 0}, {"no cross-name exception", "internal/config/source.go", "package config\n// The Codex model service outperforms opencode.\n", 1}, - {"fixture", "internal/example/testdata/source.go", "// Spark\n", 0}, - {"Go test", "internal/example/source_test.go", "// Spark\n", 0}, - {"manual", "internal/manual/example.go", "// Spark\n", 0}, - {"hosted tree", "relay/hosted/src/source.js", "// Spark\n", 0}, - {"excluded scripts", "scripts/test_example.py", "# Spark\n", 0}, + {"fixture", "internal/example/testdata/source.go", "// the owner asked\n", 0}, + {"Go test", "internal/example/source_test.go", "// the owner asked\n", 0}, + {"manual", "internal/manual/example.go", "// the owner asked\n", 0}, + {"hosted tree", "relay/hosted/src/source.js", "// the owner asked\n", 0}, + {"excluded scripts", "scripts/test_example.py", "# the owner asked\n", 0}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { @@ -315,3 +329,28 @@ func TestCommentPatternsAndBoundaries(t *testing.T) { }) } } + +func TestPrivateTerms(t *testing.T) { + root := t.TempDir() + if err := os.MkdirAll(filepath.Join(root, "scripts"), 0755); err != nil { + t.Fatal(err) + } + body := "# ALPHA and bravo.\n# alphabet and bravocado.\n" + if err := os.WriteFile(filepath.Join(root, "scripts", "example.sh"), []byte(body), 0644); err != nil { + t.Fatal(err) + } + for _, tc := range []struct { + name, terms string + want string + }{ + {"disabled", "", ""}, + {"whole words", " alpha, ,bravo,", "scripts/example.sh:1: comment should describe product behavior: alpha\nscripts/example.sh:1: comment should describe product behavior: bravo"}, + } { + t.Run(tc.name, func(t *testing.T) { + t.Setenv("COMMENTLAW_PRIVATE_TERMS", tc.terms) + if got := strings.Join(violations(root), "\n"); got != tc.want { + t.Fatalf("got %q, want %q", got, tc.want) + } + }) + } +}