1jehuang / 1jehuang/jcode

Resumed session shows empty transcript: live sessions orphaned across selfdev reload (picker preview still works)

Open
#753 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

autonomous: no bug priority: high regression triage: needs-decision
Dominant language
Rust
Stars
19.9k
Forks
2.3k
Avg merge
2d 7h
Merged PRs (30d)
30

Description

Summary

Resuming a session from the session picker shows an empty transcript, even though the picker's own preview renders the conversation correctly. The on-disk transcript is fully intact — this is an attach/render bug, not data loss.

The session is status: Active with a live PID, but the running server group reports zero sessions, so the session sits in orphan_sessions instead. Resume finds the file but cannot attach to the live session, and the orphan path does not replay the stored messages into the UI.

Version

v0.66.0 (b45bb9b52), Linux x86_64. Session was started under v0.65.0 (d847d62e4) and survived a selfdev reload into 0.66.0.

Reproduction

  1. Start a session and build up some history.
  2. Trigger selfdev reload (or have another session trigger one) so the binary swaps underneath the running session.
  3. Open the session picker. The preview shows the conversation.
  4. Resume that session. The transcript pane is empty.

Evidence

Picker cache (~/.jcode/cache/session-picker-list-v1.json), generated while the session was live:

server_groups: observatory (is_running=true, v0.66.0) → sessions = 0
orphan_sessions: 128
  session_wolf_1785705679673_… status=Active msgs=345 needs_catchup=false

The session process is alive and is in fact the parent of the tools running inside it:

last_pid: 41330 → PID ALIVE
(a shell spawned by that very session reports ppid=41330)

Transcript on disk is complete and still being appended to:

session_wolf_….json  604K, messages=333 (179 user / 154 assistant)
… later in the same run: messages=392, snapshot_bytes=616606, result=ok

So persistence is healthy — SESSION_PERSISTENCE … phase=save_done result=ok status=Active keeps firing normally. Only the registry/UI association is lost.

The reload snapshot only captures the triggering session

~/.jcode/reload-traces/reload_1785759155118_….jsonl:

phase=signal_received  pid=41330  hash=d847d62e4  triggering_session=session_cat_…
phase=candidate_snapshot   members recorded at reload: 1
    session_cat_1785759152503_…  ready
phase=intent_skipped
phase=graceful_shutdown_complete
phase=background_tasks_finalized
phase=exec_start

Only 1 member was snapshotted (the session that triggered the reload). Other live sessions, including session_wolf_…, were not in the candidate set, so nothing re-adopts them after exec_start. An earlier trace from the previous reload shows the same shape with a different triggering session.

This looks like the direct cause: the reload hands over only the triggering session's membership, and every other live session is orphaned on the far side of the exec.

Scale of the symptom

On this machine: 128 orphans, 24 with needs_catchup: true, 25 of them native session_* (rest are imported claude:/codex: entries with 0 messages).

Several orphans carry crash statuses that look like the same handover gap rather than genuine crashes:

Crashed: "Process 3293084 exited unexpectedly (no shutdown signal captured)"   ×5 (same PID)
Crashed: "Terminal or window closed (SIGHUP)"

Five sessions attributing their death to one shared PID suggests they were all children of a server process that went away during a reload, and none of them were re-adopted.

Nothing in ~/.jcode/logs/jcode-2026-08-03.log mentions orphan, adopt, or reattach — grep returns zero hits — so the reclassification is currently silent.

Expected behaviour

  1. On server start after a reload, any session whose last_pid is still alive should be re-adopted into the server group rather than reclassified as an orphan.
  2. Reload's candidate_snapshot should capture all live session members, not only the triggering session.
  3. Failing both, resuming an orphan that has an intact transcript should replay its stored messages into the UI. The picker already proves the data is readable — resume should use the same path.
  4. Orphaning/adoption decisions should be logged, so this is diagnosable without hand-parsing the picker cache.

Impact

The work is recoverable (the JSON is intact, and session_search can still find it), but the user loses all visible scrollback and any sense that the session is continuous. Because selfdev reload is routine during self-dev work, this hits often — hence 128 orphans on a single machine.

Workarounds

  • Avoid selfdev reload while sessions you care about are live.
  • Use session_search to recover content from an orphaned session.
  • The agent process itself retains in-context history, so a resumed session can still be asked to recap even when the pane looks empty.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing selfdev reload from candidate_snapshot through server startup and orphan classification, then inspect the session picker resume path. Verify how live PIDs and session membership are discovered. Done means all live sessions are re-adopted after reload, intact orphan transcripts render on resume, and adoption decisions are logged.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.