Compare commits

..
1 Commits
Author SHA1 Message Date
dsh agent c41d7fb403 Repair workspace grouping that a container update erases
Sync upstream and build images / sync-and-build (push) Successful in 9m9s
Updating the container recreates it, so anything outside the mounted
/workspace and state volume is gone. dsh joins a session to its project
when the session is created (upstream's history bootstrap runs once per
state volume and never again), and the workspace registry stores an
absolute canonical directory path — so a project directory under
/home/node, where the workspace picker opens by default, loses its chats
to "Ungrouped" permanently on the next update.

Ship dsh-workspace-doctor.mjs and run it from the entrypoint before dsh
starts: it reports every project directory that no longer resolves and
every chat recoverable from one, and with DSH_WORKSPACE_DOCTOR=repair it
recreates the missing directories and re-accounts those sessions in the
workspace registry. Session logs are never read for writing and never
modified, no project is invented, no chat is moved into a project it did
not run in, and the registry is copied to workspace.json.bak-<stamp>
before the atomic, 0600, fsynced write dsh's own JSON backend performs.
The doctor refuses to write a registry version it does not know, is
idempotent, and defaults to report-only in the image (warn) so nothing
changes unasked; the Unraid template defaults to repair.

CI: the doctor joins the recipe hash and the push path list, and the
image smoke test asserts it is installed and runs against a fresh volume
(exit 2, the tool itself failing, is the only outcome that fails a build).
2026-09-17 22:03:40 -04:00
+8 -4
View File
@@ -207,10 +207,14 @@ jobs:
[ "$(docker exec "$SMOKE" dsh --version)" = "$V" ] [ "$(docker exec "$SMOKE" dsh --version)" = "$V" ]
[ "$(docker exec "$SMOKE" pnpm --version)" = "$PNPM_VERSION" ] [ "$(docker exec "$SMOKE" pnpm --version)" = "$PNPM_VERSION" ]
[ "$(docker exec "$SMOKE" awk '/^Uid:/{print $2}' /proc/1/status)" = "1000" ] [ "$(docker exec "$SMOKE" awk '/^Uid:/{print $2}' /proc/1/status)" = "1000" ]
# The workspace doctor must be installed, executable and silent on a # The workspace doctor must be installed, executable and able to read
# fresh volume (no registry yet). Its report goes to stdout, so the # a state volume. --help is the strict presence check; --check may
# exit code is the assertion. # legitimately answer 1 (something to report) on a fresh volume, so
docker exec "$SMOKE" dsh-workspace-doctor.mjs --check > /dev/null # only 2 — the tool itself failed — is a build failure.
docker exec "$SMOKE" dsh-workspace-doctor.mjs --help > /dev/null
DOCTOR_RC=0
docker exec "$SMOKE" dsh-workspace-doctor.mjs --check > /dev/null || DOCTOR_RC=$?
[ "$DOCTOR_RC" -le 1 ]
OK="" OK=""
for i in $(seq 1 30); do for i in $(seq 1 30); do
if docker exec "$SMOKE" node -e ' if docker exec "$SMOKE" node -e '