chat: the /model menu's current model wears no band and the picker owns the wheel - #1693
Closed
ZeroPoint95 wants to merge 56 commits into
Closed
ZeroPoint95 wants to merge 56 commits into
ZeroPoint95 wants to merge 56 commits into
Conversation
…ns the wheel The chosen row of the /model list used to wear the ladder's selected ground — a full-width band that read as a highlighted row wherever the cursor happened to be. The band on an overlay is the cursor's language, so the menu's front mark now keeps its accent and its weight and takes no ground: the cursor alone lifts a row ([palette.frontUnlifted], the picker's own grammar, said on its draw and nowhere else). And a wheel notch with the list up used to fall all the way through to the transcript and scroll words nobody can see move. The picker claims the wheel like every modal above it, walking its cursor — which clamps at both ends, so neither the wheel nor the keys run past the list.
ZeroPoint95
marked this pull request as draft
September 30, 2026 18:07
ZeroPoint95
force-pushed
the
task/fix-model-current-row-styling-an-60beed
branch
from
September 30, 2026 18:07
9953867 to
269e2e5
Compare
added 26 commits
September 30, 2026 14:41
…w is always drawn The picker's scroll window was counted in list rows while the drawing spends extra lines on a service's heading, the machines' heading and a why line, so the cursor could sit inside the logical window and still fall past the rendered bottom edge: the highlight vanished once the list bottomed out, and the menu opened with no highlight anywhere because cursorToCurrent put it on the model in use at the bottom of just such a window. follow now counts screen lines (picker.rowLines, the same costs picker.height reserves the frame with), and the menu's own door opens with the cursor visibly on the list's first selectable row. The doors that open to confirm — a settings slot, a role, a task's model word, home's draft, alt+o — keep opening ON the row they hold, and ctrl+u still returns the emptied box to the model in use.
The rendered-ground assertion must use a color palette even when the runner has no terminal profile. Assisted-by: CodeAF (gpt-6-sol) Co-Authored-By: CodeAF <267109073+agentfield-bot@users.noreply.github.com>
ZeroPoint95
marked this pull request as ready for review
September 30, 2026 19:39
ZeroPoint95
marked this pull request as draft
September 30, 2026 19:55
ZeroPoint95
added a commit
that referenced
this pull request
Sep 30, 2026
The two change entries were written for #1693, which this pull request replaces with the same change on a clean history, so they are renamed to the new number and their pr field says it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
Superseded by #1696 — same change, rebuilt on a clean branch without senior-dev's per-write wip commits. |
AbirAbbas
added a commit
that referenced
this pull request
Oct 1, 2026
…ns the wheel (#1696) * chat: the /model menu's current model wears no band and the picker owns the wheel The chosen row of the /model list used to wear the ladder's selected ground, a full-width band that read as a highlighted row wherever the cursor happened to be. The band on an overlay is the cursor's language, so the menu's front mark now keeps its accent and its weight and takes no ground: the cursor alone lifts a row (palette.frontUnlifted, the picker's own grammar, said on its draw and nowhere else). Every other list that draws through the shared overlay renderer keeps the ladder's selected step for its front mark. A wheel notch with the list up used to fall all the way through to the transcript and scroll words nobody can see move. The picker now claims the wheel like every modal above it, walking its cursor, which clamps at both ends so neither the wheel nor the keys run past the list. The picker's scroll window was counted in list rows while the drawing spends extra lines on a service's heading, the machines' heading and a why line, so the cursor could sit inside the logical window and still fall past the rendered bottom edge: the highlight vanished once the list bottomed out, and the menu opened with no highlight anywhere because cursorToCurrent put it on the model in use at the bottom of just such a window. picker.follow now counts screen lines (picker.rowLines, the same costs picker.height reserves the frame with), and the menu's own door opens with the cursor visibly on the list's first selectable row. The doors that open to confirm (a settings slot, a role, a task's model word, home's draft, alt+o) keep opening ON the row they hold, and ctrl+u still returns the emptied box to the model in use. The fold tests that mean the model in use now walk to it explicitly, and the rendered-ground assertion pins a color palette so it holds on a headless runner with no terminal profile. The manual's key sheet, Scrolling section and models page name the wheel, the first-row cursor and the mark's look. Co-Authored-By: codeaf <agentfield-bot@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(changes): the /model menu's entries carry their pull request, #1696 The two change entries were written for #1693, which this pull request replaces with the same change on a clean history, so they are renamed to the new number and their pr field says it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(chat): the manual says once where the /model cursor opens models-and-cost.md still said the list opens on the model in use, in the picker paragraph and in the sort-key section, while commands.md said /model opens on the first row. Both now say what the code does: /model opens on the first row, and the doors that open to confirm open on the model they hold. Two comments that cited the old rule are corrected, and picker.follow says why the keystroke-time callers may pass a row count as their line budget. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * tui3: /model opens on the held model; every model list owns the wheel Opening /model on the first row made Enter switch models without a choice, and a refreshed task list could replace the task's confirmation model. Every model door now opens and refreshes on the model it holds, visibly on screen. A missing held model falls back to the first selectable row. The window still counts screen lines, including service and machine headings and reason lines. Opening a fold keeps preceding context when it fits and scrolls by the least otherwise, with the cursor kept visible. Settings slot and role lists, home's draft list and the task composer's list now own wheel gestures while open and leave the page beneath still. The manual and change entries describe confirmation, refresh, wheel ownership and the current model's bold accent without a band of its own. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: codeaf <agentfield-bot@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Abir Abbas <abirabbas1998@gmail.com>
AbirAbbas
added a commit
that referenced
this pull request
Oct 1, 2026
…er self-fixes (#1716) * senior-dev: a run makes no wip commits; its work is codeaf's one commit Every file senior-dev's model wrote or edited was committed on the run's branch as it happened, `wip(write): <path>` / `wip(edit): <path>` under the identity `senior-dev <senior-dev@localhost>`. It was a checkpoint from the benchmark harness senior-dev was built in, and under codeaf it bought nothing: the run works in a private worktree copy on a branch of its own, its recorder snapshots through a temporary index and keeps its candidates as commit-tree objects outside the branch, and codeaf commits whatever the run leaves as one commit when it ends, crash or not. What it cost was #1693 — fifty wip commits with senior-dev as an author, every one of which the repository's squash merge would have written into dev's message. The checkpoint is deleted rather than switched off: EagerCommit and its opt-out SENIOR_DEV_EAGER_COMMIT, the recorders' CommitsOnWrite, and on codeaf's side SENIOR_DEV_EXPECTED_BRANCH and DelegateSetup.Branch, which existed only to fence those commits to the run's branch. The start-time ignore and input lists stay, because the recorders read them. A new test drives write and edit in a repository shaped the way codeaf hands one over, task/ branch and old variable included, and fails on dev with `senior-dev wip(write): added.txt`. The senior-dev and delegates manual pages said the wip commits stay and nothing squashes them; they now say there are none, and a probe asks why a pull request has them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * senior-dev: asked to leave its work uncommitted, and to write the message for codeaf's commit A senior-dev run whose brief asked it to commit and push did exactly that: its model ran `git -c user.name=codeaf … commit` and `git push` from its own shell, and codeaf's finishing commit found nothing left to take. The owner wants codeaf, not the program, to own the commit, and chose steering over a shell that refuses git's writing verbs — parsing every road to git is a guard that guesses. So the line codeaf puts at the head of the brief now tells the program to leave its work uncommitted and not to push, switch branches or rewrite history, even where the brief below asks it to, and — when the program has a notes folder of its own, as senior-dev does — to write the commit's message to `.senior-dev/commit-message`: a subject of at most 72 characters in the repository's own style, a blank line, and a body saying what changed and why. codeaf reads that file before the notes leave the copy and makes it the finishing commit's message, signed once (signOnce, so a line the program already wrote is not repeated). With no message, or a blank one, the commit is what it was: the task's title over the run's ending. Nothing is blocked: a commit the program makes anyway stays on its branch. senior-dev's own code is untouched. The chat's guide for senior-dev was not lengthened, because the prompt-prefix budget refuses the bytes and the brief's head line already overrides a brief that asks for commits. The senior-dev page gains its own section on whether senior-dev commits or pushes and who writes the message; delegates.md says the same in brief. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * senior-dev: on the turn its run ends, handing it back counts as fixing it yourself The page the chat reads when a program's run ends told it to finish "a small, clear gap" itself on the program's branch, in its own worktree, and to fix or hand back a failure it saw in its own checks. A model reading that did the follow-up work itself, in a worktree, where the program it had just used was built for it — and that turn is the one moment a hand-off carries on from the program's own branch, since the person's next message starts any later run from their checkout again. The page now says that wherever it tells the chat to fix or finish something itself, handing the work back to the same program counts as doing it, and is the road for anything beyond a line or two; the chat edits the branch itself only for a trivial gap, or once the program can be sent back no more. The failed and unverified bullets and the failed outcome's next line say the same. The page is read on the wake turn only, so the fixed prompt's byte budget is untouched. The two-hand-back cap is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(changes): senior-dev's clean commits and hand-backs, #1716 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(changes): the #1716 entry is valid YAML and its title fits one line Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * review: the design note dates the end of wip commits; PathIgnoredAtStart has its own test From the review of #1716. The italic note under "Landing a tree delegate" still said senior-dev's wip(edit) commits stay on its branch while the decisions table above it said they ended on 2026-09-30; it now says so too. And deleting the eager-commit tests took PathIgnoredAtStart's only direct test with them; a table test makes its rule explicit again — the file itself or anything under it as a folder, never a sibling sharing its prefix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * senior-dev: keep nudges uncommitted and measure new files With eager commits gone a run's work is always uncommitted, so the unsubmitted-work nudge and landing turn told every run's model to commit before verifying, the opposite of its brief, and the patch summary diffed the base against the working tree, which leaves out untracked files: a run that wrote three files was shown as "measured its change 1 file · +28 -0", and one that only added files as "its change is empty". The git-status finding is gone (the candidate is frozen from the working tree through a temporary index), and the summary measures the same snapshot tree the run would hand in, keeping the working-tree diff only when that capture fails. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * session: a program's finishing commit is safe to read and truthful The message a program writes for codeaf's finishing commit was read with a plain open, so a named pipe there hung the finish with the copy held, a symlink was followed, and a NUL byte made git refuse the commit; a message of only credit lines or an unchanged copy the repository already tracked was taken as this run's. It is now read only as a regular file, without following links or blocking, and those cases fall back to the title and ending. A message written early also replaced the run's ending, so a stopped, failed, limited or broken run's commit read as finished work. The message is used alone only when the run passed; otherwise the ending follows it before the credits, and a run codeaf found gone says so. The brief now also asks the program not to stash, reset, clean, or check out or restore files over its work, which no longer sits in HEAD. Once a program can be sent back no more, the wake page agrees with its note: tell the person what still does not work. Manual and change entry follow. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * session: a stale commit message is judged from where this run began The check that a tracked commit message is not this run's own kept a starting commit of its own (MessageBase), while #1705's ownBase already answers where this run began, carried on or not. It reads ownBase, and the extra persisted field is gone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * manual: split the senior-dev and task-landing sections the merge overfilled With #1705's text beside this branch's, the senior-dev sections on what codeaf does when a run ends and where its work goes outgrew a retrievable section, and the "codeaf committed to dev" probe stopped reaching its page. The hand-back rule, the checks-passed-but-not-submitted ending and the finishing commit's credit get headings of their own, taking the work home is split from why a branch was kept, and an automatic hand-off is the rest of this work, as the wake page says, not a next piece. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Abir Abbas <abirabbas1998@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Two fixes to the
/modelmenu, from the owner's Misc TODO:The current model's row wears no band. The chosen row of the list drew
through the shared overlay renderer with the ladder's selected ground — a
full-width highlighted row wherever the cursor happened to be. The band on an
overlay is the cursor's language, so the menu's front mark now keeps its accent
and its weight and takes no ground: the cursor alone indicates the
highlighted row. The grammar is the picker's own (
palette.frontUnlifted, setby
picker.rowsOwnedand nowhere else); every other list that draws through theshared renderer keeps the selected step for its front mark, and under the
cursor the chosen row still lifts like any other.
The picker owns the wheel while it is up. Every other overlay claimed the
wheel in
tea.MouseWheelMsg's chain; the model picker had no branch, so a notchfell all the way through to
a.scrolland moved the transcript behind themodal. It is claimed now, like every modal above it, walking the list's cursor —
which
picker.moveclamps at both ends, so neither the wheel nor the keys canrun past the last row or before the first.
Tests
New
internal/tui3/modelmenu_test.go:TestTheCurrentModelKeepsBoldAccentButNoGround— the marked row draws boldaccent with no background run; the cursor's row carries the ground; the
cursor on the marked row still lifts it.
TestTheModelPickerOwnsTheWheelAndClampsAtBothEnds— twenty notches down andup against a scrollable transcript: the cursor clamps at the ends, the list
window stays inside the list, and
a.offsetnever moves while the picker isopen.
TestThePickerCursorStopsAtTheEndsOfTheList— thirty downs and ups plus pagekeys stop at the ends, and the walk still moves from the top.
TestTheWiderTiersAreByteIdenticalToTheOneLineLawnow paints its expectationwith the picker's front-mark grammar — the law it holds (rows draw through the
shared row function, byte for byte) is unchanged.
TestHoverReachesTheChoicesAndThePickerRowsexempts the keyboard cursor's ownrow from its "hovered too" check: since the mark takes no ground, the cursor's
row wears the cursor step by design.
Manual: the Scrolling section and the model picker's key sheet in
keys.mdname the wheel, and
models-and-cost.mdstates the mark's look.docs/changes/unreleased/1693-model-menu-front-mark-and-wheel.mdcarries theinvalidations.