Skip to content

shell: History, every chat the person has had, and Continue with an agent of theirs - #866

Merged
futurepaul merged 18 commits into
masterfrom
claude/history-view
Oct 31, 2026
Merged

futurepaul merged 18 commits into
masterfrom
claude/history-view

Conversation

@futurepaul

Copy link
Copy Markdown
Collaborator

Paul (2026-10-31): a History view, like the Apps page, to browse and search old chats instead of scrubbing the sidebar; every chat goes there (imports, archived, new), so archiving is cheap, and an archived chat can be resumed with the agent of your choosing. Paul on FIN-321: "history view is perfect no notes". Screenshots and videos: FIN-321 (History, and the agent picker).

History (cell/shell/history-page.js, /history, the sidebar's History above Apps; the Session Archive's sidebar section goes):

  • every chat the person has had, newest first: theirs live and archived, those shared with them, and their Session Archive's conversations; a delegation thread's chat stays its thread's line. All · Archived · Imported.
  • a row: face, title, whom with ("Shared", "Imported"), first words, a date, "Archived" on archived ones. 100 rows, then Show more; honest empty states.
  • a chat nothing was said in is no history: one with no previewAt has its first record read once (?after=0&limit=1) while its row is the same; a continued chat's history card gives its date and newest words; none leaves it out. No row shows without its time, nor sorts as newest for want of one.
  • search: titles (and an import's first words) at once; then GET /api/search finds chats by their messages, each with its snippet; a failed search says so. The archive's own search (sessions: an import writes its archive's search #774) plugs in at h.archive.search.
  • a chat opens in the middle column, an import read-only; one Back is History again (an open archive frame is now navigated in place, location.replace, not pushed).
  • a message the person sends in an archived chat brings it back ({fragment: "said"} from the chat page; the shell unarchives).

Continue (cell/shell/continue.js, from the Session Archive agent): "Continue with [agent ▾]" on archived and imported rows, and the archive reader's Continue through the same picker; one chat per (source, agent), its name made from both, so Continue again opens it; the history card says with whom; the old continued/<key>.json markers are gone (never in production).

Docs: api.md's wire facts only (/history, said, the session-archive message), chat-records.md's History, the inventory's shell row.

Tests:

  • cell/shell-tests/history-page.test.mjs (rows, filters, words, the search hint, dates, first records); xtask/src/continue_js.rs (Continue in a scripted platform).
  • e2e shell-ui: History as the person uses it (valid / invalid / replay: a message brings an archived chat back / restart: a reload at /history); sessions-ui goes in through History and Continues through the picker.
  • On this head (merged with master): cargo xtask check green; cargo xtask e2e --only shell-ui,sessions,sessions-ui 360 passed, 0 failed.

🤖 Generated with Claude Code

futurepaul and others added 16 commits October 31, 2026 14:26
One page (`/history`, the sidebar's History above Apps) lists every chat
the person has had, the newest first: their chats, archived ones too,
those shared with them, and their Session Archive's conversations. A row
says its title, whom it was with, its first words, when it was last said
and Archived on the archived ones; All, Archived and Imported filter it.
The search box filters by title as it is typed, and asks the person's
search for the messages that hold its words. The sidebar's Session
Archive section goes: History lists its conversations (Paul, 2026-10-31).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A chat's page tells the shell as the person's message is sent there
(`{fragment: "said"}`), and the shell unarchives a chat they archived,
as an email thread comes back once it is written in again (History;
Paul, 2026-10-31).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A chat whose list row says nothing was said yet has its first record
read, once while its row is the same: a continued chat's history card
gives its time and newest words, a message its time and first line, and
a chat with none, never used, is no history and is left out. A row
without its time is not shown until it has one, and nothing sorts as
the newest for want of a time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opening one of the archive's conversations in its frame, already shown,
set the frame's src, which adds to the tab's history: Back then went to
the conversation before, in the frame, not to History. The frame's page
is replaced in place instead (a cross-origin frame's location.replace),
so one Back is the view before, as it is for a frame made new.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Continue's history card put the conversation's last summary first and
then the newest messages, among them messages from before the summary:
a compressed conversation read "Earlier, summarized" above what it had
summarized. The summary covers what came before it, so the card's
messages are now drawn from what was said after the last summary alone;
`earlier` still counts every other message the conversation holds.

Test (fails before): a conversation of two messages, a summary and two
more keeps the summary and the last two, `earlier` 2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…archived chat

Paul (FIN-223, after the Session Archive screenshots): a History view
lists every chat, and "an archived chat can be resumed with the agent of
your choosing". Continue moves out of session-archive.js into
continue.js, the seam the History page (shell agent) calls:

- `createContinue(...)` → `{ agents, defaultAgent, continued,
  continueInto, continueControl, ask }`, for a source `{ archive, key }`
  (an import) or `{ chat }` (an archived chat), and an agent's identity.
- One chat a (source, agent): its name is made from both (the agent's
  chat label and a hash), so Continue asked again in any tab opens it,
  and each step can be taken again (409 on its own name holding this
  source's history goes on; the same history id; the membership a PUT).
  A name another fragment holds gives way to one at random, kept until
  done. A chat an archive marker names (Continue before this) still
  opens for its agent.
- The agent offered first: an import's, the person's agent of its own
  agent's name; an archived chat's, its lead agent when theirs; else
  their main one.
- An archived chat's history is made from its `chat` records; `agent`
  says whose the agent's words were when another agent continues it,
  and the chat's page and the bridge's note say so (add-only: an older
  page or bridge reads them as before).
- `continueControl(source)`: "Continue with [agent ▾]" on one line, its
  CSS its own block in shell.css; the archive's page asks the shell,
  which shows it in a dialog. The page no longer reads its marker.

Tests: xtask/src/continue_js.rs (29 cases: bounds, summary order, the
agent offered, one chat a source and agent across tabs, every step cut
short or its answer lost, a refused create, a taken name, an old
marker, an archived chat's history); images bridge `note` tests for
`agent` and `chat`; the e2e sessions-ui section continues through the
shell's dialog and reopens the same chat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This section's agent is not named as the conversation's was (Juniper),
so Continue's history names Juniper, and the bridge's note says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Its sidebar rows went to History: the module takes `changed` in their
place, and no longer `$`, `el`, `patch`, `current` or `page`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A continued chat listed with its card's time and words, a chat nothing
was said in left out; archived, under Archived with its chip and gone
from the sidebar; its title filtering at once, words nothing holds said
so; opened and one Back to History; a message sent in it bringing it
back to the sidebar; a word only its messages hold finding it with its
snippet; and a reload at /history staying there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	crates/e2e/src/lanes/shell.rs
#	docs/api.md
…istory

- History lists 49 published shell files (its page and continue.js).
- A Continue that makes its chat tells every control on the page, so a
  History row's control made before says Open for it at once.
- The e2e's sessions-ui section goes in through History (its link, the
  Imported filter, the row's open), continues through the archive's
  dialog, and finds the row's control an Open that opens that chat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…/history-continue

# Conflicts:
#	cell/shell/session-archive.js
#	crates/templates/src/lib.rs
#	docs/chat-records.md
#	xtask/src/session_archive_js.rs
Marker-based Continue never reached production; the chats it made on dev
and preview stay, their rows offering "Continue with" until continued again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s are listed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@futurepaul futurepaul added the full-e2e Run the e2e shards on this pull request's runs too (the merge queue always runs them) label Oct 31, 2026

@alexlwn123 alexlwn123 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fail for now at 9fcd7fdb765667d493b16d68fb3e1924231f4fca.

Blocking:

  1. Continue's UI treats a partially created chat as complete. In cell/shell/continue.js:137–142, continued() checks only that the named chat exists and is owned; continueControl() then bypasses continueInto() and opens it directly (lines 255–264). If creation succeeds but posting history or adding the agent fails, once the list reflects creation (including after a reload), the control says “Open”. Clicking it never finishes the missing steps, leaving a chat without its agent and possibly without its history. This affects both History rows and the archive dialog, for imported and archived sources, and violates the documented promise that Continue again finishes an interrupted attempt.

I reproduced both failures on the pinned Node using this PR's scripted platform and the actual continueControl() click handler: after a one-shot 503 on history posting, both clicks leave 0 records / 0 agents; after a one-shot 503 on membership, both leave 1 history record / 0 agents. The second click simply opens the incomplete chat. Existing retry tests call continueInto() directly, so they miss this bypass.

Only offer the direct Open path once completion is established; otherwise resume the idempotent completion steps. Cover the control itself after failures/lost responses at each step, with the list refreshed, and after reload/in another tab.

The History/Continue module split is appropriate for the feature; I found no separate complexity blocker. Validation: all 28 shell tests and the extracted Continue scripted cases pass. CI source and image checks pass; e2e jobs remain pending. Full local Rust/e2e suites were not run. The prescribed engineering-style file is absent on this machine.

The control said Open once a Continue's chat was in the person's list,
and pressing Open only opened it: a Continue whose history or agent's add
failed, or whose answer was lost, left a chat without its agent (or its
history) that no press finished (Alex on #866). `continued` now names a
chat only once it is finished: the person's own, with the agent in it as
their list has it (adding it is the last step, after the history), or
finished by this page (the list names an agent a moment after it joins).
One cut short says Continue, and pressed, here or in another tab, is
finished in that chat. A chat found finished lets go of the name kept for
it. The control's own cases drive its press after a failure or a lost
answer at each step, in the same tab and after a reload, and with the
list lagging; they fail on the code before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@futurepaul

Copy link
Copy Markdown
Collaborator Author

Thanks, Alex. You were right: the control's Open bypassed continueInto() for a chat that existed but wasn't finished. Fixed in 486c39b.

1. Continue's UI treated a partly made chat as complete.

  • continued() (cell/shell/continue.js) now names a chat only once it's finished: the person's own chat with the agent in it, as their list has it. Adding the agent is the last step, after the history post, so its presence means every step ran.
  • A chat this page finished itself also counts, because the list names a new agent a moment after it joins.
  • Any other chat is one cut short. The control says "Continue with", and pressing it runs continueInto(), which finishes the steps in that same chat (create 409 → ours → history replayed or posted → member PUT). That holds for History rows and the archive's dialog, for imports and archived chats alike.
  • A chat found finished also lets go of the random-name fallback kept for it in the browser.

Tests (xtask/src/continue_js.rs, the scripted platform), now driving the control's own press:

  • For a failure or a lost answer at each step (history 503, member 503, create's answer lost, history's answer lost, member's answer lost):
    • what it says after the cut;
    • that the agent is in the chat only once every step is done (the order, pinned);
    • what a reloaded tab (a new module and store) says;
    • pressing it there finishes and opens the same chat, creating once and posting once;
    • pressing again in the first tab makes nothing new.
  • With the list lagging: the page that finished it says Open; another tab says Continue, and pressing it opens the same chat, making nothing again.
  • Against the old continue.js, 8 of the 39 cases fail; all pass now.

On this head merged with master, cargo xtask check is green, and cargo xtask e2e --only sessions,sessions-ui passed 20 of 20.

@futurepaul
futurepaul requested a review from alexlwn123 October 31, 2026 21:23

@alexlwn123 alexlwn123 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass at 486c39b36902eee6e25088ee69d05032068a7a99.

The earlier blocker is fixed: Continue no longer treats an owned but incomplete chat as ready to Open. It requires the chosen agent in the list row (membership is added after history), or completion observed by this page. Interrupted attempts therefore resume the existing completion steps. The new tests exercise the actual control after failed requests and lost responses, across reloads and delayed list updates.

I reviewed the two-file revision against my previous verdict and traced the membership projection. The correction is appropriately scoped, and I found no new blocking regression or complexity concern.

Validation: cargo test -p xtask continue_makes_one_chat_a_source_and_agent -- --nocapture and all 28 shell tests pass on pinned Node. CI images check passes; source check, Docker and e2e jobs are still running. Full local check/e2e suites were not run. The prescribed engineering-style file is absent on this machine.

# Conflicts:
#	cell/shell/shell.js
#	xtask/src/js_syntax.rs
@futurepaul
futurepaul enabled auto-merge October 31, 2026 21:48

@alexlwn123 alexlwn123 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass at c3f33affb2dfeb54ed58c40dd3a78c3398f9fe84.

The earlier Continue completion blocker remains fixed. This revision merges master into the previously approved head; I checked the merge resolutions and interactions with History, Continue, chat rendering and the bridge history note. The shell retains the new agent-specific app prompts without restoring the removed archive sidebar renderer, and the JavaScript test inventory includes both new suites. No new blocking regression or complexity concern found.

Validation: all 31 shell tests pass on pinned Node; cargo test -p xtask continue_makes_one_chat_a_source_and_agent -- --nocapture and cargo test -p xtask js_syntax -- --nocapture pass. CI source, image, Docker and e2e checks were still running when inspected. Full local check/e2e suites were not run. The prescribed engineering-style file is absent on this machine.

@futurepaul
futurepaul added this pull request to the merge queue Oct 31, 2026
Merged via the queue into master with commit 4bce634 Oct 31, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

full-e2e Run the e2e shards on this pull request's runs too (the merge queue always runs them)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants