Skip to content

Ask <app> and the assistant: a reload keeps notices in place and tool rows named - #281

Merged
ymote merged 1 commit into
mainfrom
fix/reload-keeps-notices-and-tool-names
Oct 2, 2026
Merged

ymote merged 1 commit into
mainfrom
fix/reload-keeps-notices-and-tool-names

Conversation

@ymote

@ymote ymote commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

A headless instrument run of the desktop shell (main f52620c) found two things wrong once a transcript is loaded again from history, after "Ask " or the system chat's pane is reopened.

1. The panel's notices moved below newer rows (frames 21, 22). Notices such as "Stopped.", "Nothing of yours was running.", "Stopped the system agent's task." and a turn's "turn interrupted by client" all ended up below the turn that ran while the panel was closed.

  • Cause: Conversation::load_history (app_chat/model.rs) appended everything history cannot know after the whole history. That covers notices, an open question and a running turn's rows.
  • Fix: keep_in_place puts each such item back right after the row it followed. It finds that row again in the new history by its kind and turn. An item from before any row stays first. An item whose rows history no longer has goes last, as before.

2. Reloaded tool rows read "⚙ tool · done" instead of the tool's name (frames 24, 35; system_chat/model.rs:580, app_chat/model.rs:262).

  • Cause: both models looked for name, then tool_name, and history rows have neither. At the pinned octos ae230ce, session/hydrate returns HydratedMessage rows: seq, role, content, thread_id, persisted_at, message_id and the like. They carry no tool name and no tool call id. The name is only on the assistant's tool call, which hydrate does not return. octos-web and Octoscode skip these rows for that reason; they draw tool cards from v2 tool envelopes, which the shell's stdio link does not negotiate. The broker's merged history (merged_history) adds no name either. So there is no field to read.
  • Fix: a reloaded tool row keeps the name the transcript already showed for the same call (system_chat::model::ToolNames). octos stamps every row a turn persists with thread_id = that turn's id (pre_stamp_turn_thread_id). A turn's tool rows are matched in order with the tool calls the transcript showed for that turn, from live tool/started or an earlier reload, when there are as many of each.
  • A row of a turn the transcript never followed in full still says "tool", never another call's name. That includes a row from before this run of the shell. Naming those needs octos to return the tool name in hydrate rows; that is a possible follow-up there.
  • The system chat now takes a row's turn from thread_id too (history_turn), as the panel already did.

Tests (Linux build host, from phone/; this branch alone):

  • cargo test --locked --features mobile-apps -p octosense-shell app_chat: 11 passed, including the new a_reload_keeps_the_notices_where_they_stood (the instrument run's order, across two reloads; first and last) and a_reload_keeps_the_tool_names_the_panel_showed.
  • … system_chat: 66 passed, including the new a_reload_keeps_the_tool_names_the_chat_showed (hydrate-shaped rows: across reloads, a turn seen only in part stays "tool").
  • … approvals: 58 passed. … questions: 9 passed.
  • The whole shell suite as phone.yml runs it (cargo test --locked --features mobile-apps -p octosense-shell, with OCTOS_SHELL_TEST_KERNEL): 778 passed.
  • The two-lane scenario against the real kernel (pinned ae230ce): 5 passed.

Instrument (the same harness, on the Linux build host; before = main, after = this branch):

  • Before (main 4f73ab3; the same on f52620c): after the reopen (S7, frame 21), the panel's notices ("Stopped.", "turn interrupted by client", "Nothing of yours was running.", "Stopped the system agent's task.", "turn interrupted by client") stood below "System agent: SLOW:3 / News's agent, to the system agent: SLOW DONE after 3 s", the turn that ran while the panel was closed. In the system chat, the reloaded row of the MAIL_NOTIFY turn read "⚙ tool · done" (frame 35).
  • After (this PR's head): the notices stand where they stood, between "You: SLOW:40 the person, in parallel" and "System agent: SLOW:3" (frame 21). The same reloaded row reads "⚙ peer_send_input · done", as it did live (frame 35).
  • Harness note: on this main, System apps: every one has its own agent that can notify #274 gave Photos an agent, so the harness now uses AI providers as its app without one (S2). Its S9 step presses the switch on the third agent row in Settings, which is now Maps's rather than News's, so S9 fails on main and on every branch alike.

Overlap. This branch is on main 4f73ab3, after #272, #273 and #274 merged; the rebase had no conflicts. #272 rewrote system_chat/view.rs; this PR changes only system_chat/model.rs. #274 added asserts to other tests in app_chat/tests.rs. The open #230 and #255 merge with this branch cleanly. The four fixes from the same run are independent, and each pair merges without conflicts: this one, #279, #280 and #282.

🤖 Generated with Claude Code

…rows' names

Two things changed when a transcript was loaded again from history (the
"Ask <app>" panel reopened, the system chat's pane reopened):

- The panel's notices ("Stopped.", "Nothing of yours was running.", a
  turn's "turn interrupted by client", ...) were appended after the whole
  history, so on every reopen they moved below newer rows (instrument run,
  frames 21 and 22). Conversation::load_history now puts what history
  cannot know (notices, an open question, a running turn's rows) back
  where it stood: right after the row it followed, found again by its kind
  and turn (keep_in_place).
- Reloaded tool rows read "⚙ tool · done" instead of the tool's name
  (frames 24 and 35). Both models read `name` or `tool_name`, which no
  history row has: octos's session/hydrate row (HydratedMessage at the
  pinned ae230ce) is seq, role, content, thread_id, persisted_at and the
  like, with neither the tool's name nor its call id (the name is only on
  the assistant's tool call, which hydrate does not return; octos-web and
  Octoscode skip these rows), and the broker's merged history adds none.
  So a reloaded tool row keeps the name the transcript already showed for
  the same call (system_chat::model::ToolNames): a turn's tool rows in
  order, matched by the turn every persisted row carries as `thread_id`,
  when the transcript showed as many for that turn. A row of a turn the
  transcript never followed in full (another run's) still says "tool",
  never another call's name; octos would have to return the name for those.
  The system chat now reads a row's turn from `thread_id` too, as the panel
  did.

Tests: app_chat (the instrument run's notices, and tool names, across two
reloads) and system_chat (tool names across reloads; a turn seen in part).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ymote
ymote force-pushed the fix/reload-keeps-notices-and-tool-names branch from fdf57a6 to 73c66f4 Compare October 2, 2026 19:14
@ymote

ymote commented Oct 2, 2026

Copy link
Copy Markdown
Contributor Author

Local CI passed on 73c66f4 (tools/ci-local.sh --only all --linux-host, 17m41s, Darwin arm64; the ubuntu jobs on the Linux build host, Linux x86_64).

GitHub would run for this PR: desktop.yml, phone.yml, apps.yml. Merged on this local pass (macOS runner queue); GitHub CI runs on the merge commit on main.

Job Step Result Time
ci-local / drift The local mapping fits the workflows PASS -
desktop.yml / desktop Prepare the pinned framework sources PASS 1s
desktop.yml / desktop Compile the desktop with the shared runtime PASS 1m53s
desktop.yml / desktop One copy of every shell source PASS -
desktop.yml / desktop Desktop tools and scripts PASS 8s
desktop.yml / desktop One Makepad, App Hub, octos and Rinx in the locked graph PASS 1s
desktop.yml / desktop The native apps' generated places match native-apps.json PASS 0s
phone.yml / home Prepare pinned sources and the reviewed runtime patch PASS 0s
phone.yml / home Compile Home and its bundled modules PASS 1m29s
phone.yml / home Verify the single runtime graph PASS 1s
phone.yml / home The native apps' generated places match native-apps.json PASS 0s
phone.yml / home The pinned octos revision PASS -
phone.yml / home Build octos (unless cached) PASS -
phone.yml / home Build Home, App Hub admission and runtime policy tests PASS 2m22s
phone.yml / home Test Home, App Hub admission and runtime policy PASS 7m32s
phone.yml / home Two-lane scenario (real kernel, scripted model) PASS 28s
apps.yml / services (linux) python3 tools/setup.py PASS 0s
apps.yml / services (linux) Kernel service PASS 10s
apps.yml / services (linux) App peers PASS 23s
apps.yml / services (linux) AI providers config PASS 3s
apps.yml / services (linux) L0 in-card chat (sys.chat, host side) PASS 8s
apps.yml / services (linux) System toolbox (workflow templates) PASS 1m28s
apps.yml / kernel-security (linux) python3 tools/setup.py PASS 0s
apps.yml / kernel-security (linux) The pinned octos revision PASS -
apps.yml / kernel-security (linux) Build octos (unless cached) PASS -
apps.yml / kernel-security (linux) Real-kernel tests PASS 30s
apps.yml / apps python3 tools/setup.py PASS 0s
apps.yml / apps Host services (Mail, AI providers, News) PASS 1m05s
apps.yml / apps Shell AI services (crates/ai-host) PASS 1m52s
apps.yml / apps AppCard runtime setup safeguards PASS 0s
apps.yml / apps AppCard clippy (own crates; shared runtime compiles) PASS 31s
apps.yml / apps AppCard transport and store PASS 12s
apps.yml / apps One Makepad, App Hub, octos and Rinx in the locked graph PASS 4s
rom.yml / product (linux) python3 -m unittest discover -s tests -v SKIPPED (!) -
rom.yml / product (linux) Check generated Agent Binder client SKIPPED (!) -
rom.yml / product (linux) bash -n scripts/stage-forks.sh scripts/publish-release.sh scripts/apply-to-tree.sh scripts/build-rom.sh PASS -
rom.yml / web-installer (linux) npm ci --ignore-scripts --no-audit --no-fund SKIPPED (!) -
rom.yml / web-installer (linux) npm test SKIPPED (!) -
rom.yml / web-installer (linux) npx playwright install --with-deps chromium SKIPPED (!) -
rom.yml / web-installer (linux) npm run test:browser SKIPPED (!) -
rom.yml / web-installer (linux) python3 -m unittest discover -s tests -p test_installer_manifest.py -v SKIPPED (!) -
rom.yml / web-installer (linux) bash -n scripts/release.sh SKIPPED (!) -
linux-host / sandbox (linux) python3 tools/setup.py PASS 0s
linux-host / sandbox (linux) Process sandbox on Linux (Landlock, seccomp) PASS 1m16s

Skipped (these did NOT pass; (!) marks a skip that blocks tools/ci-local-merge.sh):

  • rom.yml / product (linux): python3 -m unittest discover -s tests -v: javac -version does not work here: install a JDK (17 or newer) and put its bin/ on PATH or set JAVA_HOME
  • rom.yml / product (linux): Check generated Agent Binder client: needs build-tools/35.0.0/aidl, platforms/android-35/framework.aidl in the Android SDK (no Android SDK found): install the SDK packages 'build-tools;35.0.0' and 'platforms;android-35' (sdkmanager) and set ANDROID_HOME
  • rom.yml / web-installer (linux): npm ci --ignore-scripts --no-audit --no-fund: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): npm test: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): npx playwright install --with-deps chromium: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): npm run test:browser: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): python3 -m unittest discover -s tests -p test_installer_manifest.py -v: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): bash -n scripts/release.sh: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH

Notes:

  • GitHub runs Python 3.12; this run used Python 3.9.6
  • GitHub runs Python 3.12; the Linux host used Python 3.14.4

@ymote
ymote merged commit a478a63 into main Oct 2, 2026
5 checks passed
Sign up for free to 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.

1 participant