Repository navigation
Replies: 2 comments
|
Confirmed on Repro (2026-10-19, 25 idle sessions)
Verified workaround (25/25 recovered, message contents intact)
This is exactly what |
|
One clarification from Desktop 0.2.1-rc.3 that may help separate two different states:
The brief appearance while Workspace state is pending is read-time Ungrouped/bootstrap rendering, not evidence of membership. When checking attach candidates, I excluded parented/subagent logs and considered only top-level, cwd-matching Sessions. An additive, backup-first edit re-attached those out-of-band logs; it does not prove that they had previously been members. A public attach operation, together with an authoritative or repairable header index, would address both cases without manual |
Uh oh!
There was an error while loading. Please reload this page.
What happens
A Workspace owns a directory, and a Session is a log whose header carries a
cwd. Creating a Session inside a Workspace works as expected (session/createwithworkspaceId→attachSession). The gap is the other direction: a Session that exists on disk but is not accounted by any Workspace cannot be attached again — there is no API and no UI for it.Concretely, this state is reachable and I hit it today:
$DSH_HOME/sessions/<slug>/session-<id>/session.v4.jsonl.zstdcwdequals the Workspacepathsession/listreturns it (so the Host can read it)workspace/insertSessionBefore→workspace/move-invalid("the session is not accounted")…menu only offers pin / rename / fork / archiveonDropis gated onsameGroupDrag, so cross-Workspace drop is impossibleworkspace/archiveSession/pinSessionrequire the session to be known tooThe only way I found is an undocumented side effect: call
session/createwith an explicitsessionIdplus the targetworkspaceId. That path runsensureSession(restore)→rememberSessionPath→attachSession, which both re-indexes the path and attaches. It works, but it is not a public "attach" operation and I would not want to depend on it.How the Sessions ended up unaccounted: a bulk re-encode of the session logs produced single-frame Zstandard files, and
readFirstZstdLinerequires the first frame to contain exactly the header line (assertZstdHeaderFrame). Those Sessions were reported as corrupt at startup, silently dropped from the header index and fromsession/list, and then pruned out ofworkspace.sessionIdsby the filter insidemutate():Once
sessionPath(id)is undefined, the next write removes the id permanently. (Restoring the frames brought the Sessions back in the list, but the membership was already gone.)What I would expect
workspace/attachSession(sessionId)(or anattachoption on an existing method) that validatesrealpath(header.cwd) === workspace.path, callsrememberSessionPath, and adds the id — i.e. exactly whatattachSessionalready does internally, exposed as a command.…menu, enabled only for Workspaces whosepathmatches the sessioncwd. Cross-Workspace drag would be nice, but thecwd === pathinvariant makes it a move-between-directories problem, so a filtered menu item seems like the honest version.With (1) alone, a broken registry is recoverable without editing
workspace.jsonby hand. With (2), the "Ungrouped" bucket stops being a dead end.Related robustness issue (separate, but this is how it surfaced)
When a stored log cannot be read,
listArtifactscatchesSessionPersistenceCorruptionErrorandcontinues, so the Session vanishes fromsession/listwith no signal. Two things would have saved me a few hours:\ninstead of requiring the frame to be exactly one line), orsession/repair-style command) instead of dropping them silently.Environment
dsh
0.2.0-rc.2, web profile, Windows 11,$DSH_HOME=A:\dsh\home, 11 stored Sessions across 6 Workspaces.All reactions