Skip to content

feat: search cost, recovery confirmation, TUI scroll, and session directories - #4

Merged
Owen718 merged 15 commits into
Owen718:mainfrom
FeiSong123:feat/search-cost
Aug 12, 2026
Merged

feat: search cost, recovery confirmation, TUI scroll, and session directories#4
Owen718 merged 15 commits into
Owen718:mainfrom
FeiSong123:feat/search-cost

Conversation

@FeiSong123

@FeiSong123FeiSong123 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What

This branch carries several related fixes and features on top of the search-cost work:

1. Price web search usage into the session cost

Web search runs on a separate Responses API call whose token usage was parsed into the tool artifact but never counted, so knownSessionCost under-reported searching sessions. The usage is now recorded durably on the web_search tool result (an optional searchUsage field on tool_result_committed, present only for successful searches) and priced with the same flash price book into the session and lineage cost. The usage stays out of the chat-prefix cache metrics.

2. Require confirmation before recovery executes pending tool calls

Recovery can reach a pending tool call whose result was never committed. Executing it silently would run a command the operator never approved. This adds an explicit operator gate:

  • interactive terminals are asked y/N before execution
  • non-interactive invocations require the --confirm-execute flag
  • declining stops the recovery fail-closed and records a not_executed_denied reconciliation resolution, which replays as a static permission-denied result instead of a fabricated or bypassed effect

3. Scroll rendered history with wheel, PageUp/PageDown, Home/End

The TUI base gains a scroll offset and the main-screen renderer gains a history viewport. Inside tmux, SGR button-event tracking (1002 + 1006) is enabled so the wheel reaches the Screen layer and scrolls the internal history; it is disabled on exit. Outside tmux the terminal keeps owning the mouse and its own scrollback, so native selection and scrolling are unchanged.

4. Click-drag text selection with OSC 52 copy (tmux)

Inside tmux, left-button drag selects text within the rendered window with reverse-video highlight, and release copies the plain text to the system clipboard via OSC 52. Selection rows are mapped through the viewport top so the highlight stays under the cursor after scrolling or resizing. tmux mouse (window) and set-clipboard (session) are enabled automatically at startup, so no manual tmux.conf changes are needed.

5. Show each session's workspace directory in the session list

The session list resolves the durable cwd fact during the fast JSONL scan (no second log read) and in the verified fallback, then appends a shortened workspace path to both the plain flashcoder sessions output and the interactive session picker. Sessions are summarized concurrently.

6. Polish and hardening

  • Restore terminal state (mouse tracking, bracketed paste, Kitty protocol, raw mode) on process exit when a crash or SIGTERM bypasses the normal stop() path.
  • English tmux hint, shortened ~ paths, and local session times.
  • recover/inspect report "no such session in this workspace" instead of a bootstrap internals error when the session belongs to another directory.
  • npm debug logs removed and ignored.
  • Compatibility test for journals written before the searchUsage field existed.

Tests

All suites pass locally:

  • bootstrap 4/4
  • protocol 103/103
  • journal 49/49
  • context 113/113
  • effects 116/116
  • session 170/170
  • recovery 84 pass, 1 skip (legacy v4 fixture revision absent from this checkout's history)

Web search runs on a separate Responses API call whose token usage was
written into the tool artifact but never counted, so knownSessionCost
under-reported searching sessions. Record the usage durably on the
web_search tool result (an optional searchUsage field on
tool_result_committed, present only for successful searches) and have the
cost projector price it with the same flash price book into the session
and lineage cost. The usage is cost-only: it stays out of the chat-prefix
cache metrics.
Recovery can reach a pending tool call whose result was never committed.
Executing it silently would run a command the operator never approved, so
add an explicit operator gate: interactive terminals are asked y/N, and
non-interactive invocations require the --confirm-execute flag. Declining
stops the recovery fail-closed and records a not_executed_denied
reconciliation resolution, which replays as a static permission-denied
result instead of a fabricated or bypassed effect.
Add a scroll offset to the TUI base and a history viewport to the
main-screen renderer: wheel (via SGR mouse reports), PageUp/PageDown,
Home and End move a window over the rendered content without touching
the terminal's own scrollback. Enable SGR button-event tracking
(1002 + 1006) only inside tmux so the wheel reaches the Screen layer,
and disable it on exit; outside tmux the terminal keeps owning the
mouse and its scrollback.
Resolve the durable cwd fact during the fast JSONL scan (no second log
read) and in the verified fallback, then append the workspace path to
both the plain sessions output and the interactive session picker.
Add a compatibility test that writes a web_search result without the
searchUsage field and verifies the journal still replays and projects
cost correctly, matching the schema's backward-compatible read.
@FeiSong123FeiSong123 changed the title feat(cost): price web search usage into the session costfeat: search cost, recovery confirmation, TUI scroll, and session directoriesAug 12, 2026
The fast session list parses log.jsonl lines for a read-only projection,
the recovery confirmation parses a tool call's arguments only to disclose
the command, and the screen probes TMUX for the mouse hint. All three are
display/read-only paths, not credential or invariant mutations.
- The tmux mouse hint was the only Chinese string in the CLI; make it English.
- Shorten the workspace path to ~ for home and ellipsize long paths so the
session rows stay within the terminal instead of wrapping.
- Show local times in both the plain sessions output and the picker; the raw
ISO timestamp with T/Z only appeared in the plain output before.
A crash or SIGTERM left the terminal in raw mode with mouse tracking,
bracketed paste and Kitty protocol enabled. Register a best-effort
process exit handler in start() that writes the disable sequences and
restores raw mode, and remove it in stop() once the normal path has
already cleaned up. SIGKILL still cannot be helped.
Each session summary reads independent files, so wait for them together
instead of one at a time. The result set and sort order are still decided
after the awaits.
Inside tmux the mouse now selects text within the rendered window: left
press anchors, drag extends with reverse-video highlight, and release
copies the plain text to the system clipboard via OSC 52. Wheel scrolling
still works, and the selection never lets raw mouse bytes reach the
editor.
…tmux mouse
- Selection rows were indexed into the full rendered content as if row 0
were the top of the screen; add previousViewportTop so dragging selects
the row under the cursor after the window has scrolled or resized.
- Enable tmux mouse mode for the current window and set-clipboard for the
current session at startup instead of asking the operator to edit their
tmux.conf. Both are scoped (window/session), not global.
@Owen718
Owen718 merged commit f18d443 into Owen718:mainAug 12, 2026
1 check passed
@Owen718

Copy link
Copy Markdown
Owner

Merged and released in v0.1.0-rc.7.

Verified before merging:

  • Suites on the merged tree: protocol 103, journal 49, context 113, effects 116, session 171, recovery 85, bootstrap 4, acceptance 3/3, check-package: ok dependencies=6. Your report mentioned one recovery skip; it passes here, 85/85.
  • The search-cost fix measured against the released binary rather than asserted: the same search turn reports $0.0001 under rc.6 and $0.0003 under this build.
  • The Journal schema moved, so the check that matters: a session created by the rc.6 tarball — including a web_search turn, so it holds tool results without searchUsage — is read by inspect and takes another turn under the new build.
  • The three check-package allowlist entries are additions with reasons, not relaxations. The recovery gate discloses the actual command, defaults to No, and refuses non-interactively naming the flag to re-run with — an approval gate on a state-changing action, scoped to the one place the operator genuinely never approved the call.

Two edits on top of the merge:

  • Dropped iphone-buying-guide-2026-08.md from .gitignore. The rest of that block stays, and I wrote down why it exists: bash children run with HOME set to the workspace, so anything writing to $HOME lands in the user's project directory. That is how .npm/ got committed here in the first place.
  • Removed the three .npm/_cacache files left behind after the debug logs went.

Thanks — the search-cost gap had been on the list unfixed for two days.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@FeiSong123@Owen718