Repository navigation
Releases: PianoPrince/dsh-workspace-mover
Release list
v2.4.1
v2.4.0
Added
- Agent tools mover_create_workspace (register an existing folder) and mover_rename_workspace (display title only), from PR #7. Duplicate names/folder aliases are rejected. Rename asks for approval unless the calling session has full access.
- Sidebar edge autoscroll from PR #9, with pointer bounds, scroll limits, drag cancellation and hot-unload cleanup.
- pluginVersion in status and doctor output.
Fixed
-
Issue #5: also detect opening/closing JSONL writer claims even after the session leaves memory. Unknown handle backends wait safely. Keep header rewrite and relocation synchronous after the final writer check.
-
Fresh-install scans treat only missing storage roots as empty (PR #8); permission and I/O failures remain visible.
-
Optional tools/approval no longer disable the whole plugin. Tools follow host service load/unload; approval requests carry ACP callId. Missing approval or agent context refuses operations requiring confirmation.
-
Queue resident sessions until unloading instead of mutating private writer state or frozen live headers; await backend flush before cold migration. Workspace repoint refuses resident writers before changing registry paths.
-
Preserve existing working-directory history and append the destination directory when needed; invalidate the corresponding projection checkpoint. Unsupported sequences are rejected before migration.
-
Restore v3/v4 backup filenames from the official header version; preserve unversioned legacy filenames.
-
Read Portable Bundle pluginVersion from package.json.
Validation
- Desktop
0.2.1-rc.2: user accepted candidate2.4.0-rc.1; opened-session queueing, continued A2 replies while pending, migration after restart, B1/B2 replies across a second restart, destination working directory and doctor checks passed. - Workspace registration, rename rejection/approval, name conflicts, no-op renames and full-access rename passed in Desktop.
- Windows local gate: 315 tests passed; installed official JSONL/ToolRuntime backend check passed. Sidebar autoscroll is covered by automated DOM checks; the user waived manual autoscroll acceptance.
- Open sessions finish migration only after their writer is unloaded or DSH is restarted. Switch to another session before restarting so Desktop does not immediately reopen the pending session.
v2.3.0
Added
- Persistent busy-session migration queue with idle retries, cancellation, and individual/batch retry.
- Migration preview and explicit target-workspace selection, adapter diagnostics, and v3/v4/plain/Zstd format checks.
- Optional descendant migration and Portable Bundle export/inspection/dry-run import APIs (sandbox verified; real-runtime validation remains pending).
- npm weekly downloads badge and documentation of the expected filesystem adapter warning.
Changed
- Identical content reuses a recovery snapshot, ignoring migration-only cwd changes. Changed content creates a new snapshot; every move remains in history. Legacy backup filenames remain supported.
- Preview displays newly required backup bytes and snapshot reuse. Retention limits count physical snapshots.
Fixed
- Return-move workspace resolution and stale hover targets; failed or stale previews cannot execute against an earlier target.
- Default backup restoration chooses the newest saved snapshot.
- Portable Bundle space estimates include attachments and known insufficient space blocks execution.
Validation
- User confirmed Desktop idle-session migration and snapshot reuse. Web, full runtime rollback smoke, and DSH process-restart queue recovery remain unverified; see the dated compatibility report.
v2.2.0
Changed (behavior)
- Batch and multi-select moves no longer guess a session id. When the authoritative row-to-id channel (the React fiber carrying
node.id) is unavailable, the client used to fall back to positional order and, on a title mismatch, take the next id in sequence. Because the official sidebar hides blank and archived rows, that fallback could shift a group by one and move a different but valid set of sessions — undetectable host-side. The fallback now refuses to guess: unresolvable rows are reported to the user, and a move either aborts (nothing resolvable) or proceeds with only the rows that resolved, after an explicit confirmation that names the skipped count. This is the one intentional behavior change in this release. - Workspace resolution verifies instead of trusting DOM order. The positional fallback that mapped the i-th sidebar header to the i-th registry item is now accepted only when the header text actually matches that item's title or path; otherwise the move aborts with the existing "list out of sync" message. Previously a single hidden header (for example a workspace whose folder was moved) shifted every later index by one.
workspace-moverstyles and dialog semantics unchanged in appearance; dialogs gained an accessible name, initial focus, and a Tab trap.
Added
screenshots.json: declares the plugin's screenshots in-repository so plugin storefronts (dsh-market and peers) show them App Store style in a controlled order instead of scraping the README.peerDependenciesfor the official packages the plugin integrates with, declared as*and marked optional inpeerDependenciesMeta. These peers are declarative only — the plugin fail-softs at runtime and reports any real degradation throughmover.statuscapabilities andmover_doctor— so they exist for storefront metadata, not as a compatibility gate. The real floor isengines.dsh.- Fixed: the first attempt at those peer ranges made the host declare the plugin incompatible with
0.2.0-rc.2. The ranges were written in the ecosystem's "explicit prerelease branch" idiom, e.g.>=0.0.1-rc.1 <0.1.0 || >=0.1.0-rc.1 <0.2.0-0. npm's prerelease rule evaluates each||alternative as a set and only admits a prerelease when a comparator in that set shares the version's exactmajor.minor.patchtuple and carries a prerelease tag; then every comparator is checked normally. Because0.2.0-rc.2 > 0.2.0-0, the upper bound<0.2.0-0excluded every 0.2.0 prerelease — i.e. the plugin's own tested host line. Enumerating release lines would reproduce this on each new line (a<0.3.0-0bound breaks the moment 0.3 lands), so all eight peers are now*. A regression test asserts the declared ranges plusengines.dshyieldcompatible(neverincompatible) for every DSH line from 0.1.5-rc.1 through 1.0.0. - Storage-layout self-check. The plugin re-implements the session-store directory encoding, and the persistence root it derives from is not a documented part of the
SessionPersistencecontract. A new read-only check reverse-derives one real session's directory frompersistence.list()and verifies it exists; the result appears asmover.status.capabilities.storageLayoutand as adata-layoutcheck inmover_doctor, so a host layout change becomes a visible degraded state instead of sessions that silently cannot be found. - Archive-truncation visibility. The rescue scan parses only the newest 400 session archives, and archived sessions are typically old — so on large libraries they could drop out of the archived list with no explanation. The archived view now reports when the underlying scan was truncated.
- Client test coverage.
test/client-dom.test.mjsexercises the client half against a hand-rolled DOM stub (no new dependencies): workspace resolution, row-to-id mapping, the drop payload, listener teardown, dialog dismissal and the RPC failure matrix.
Fixed
- Client half had no teardown. Seven document-level listeners and a
document.bodysubtreeMutationObserverwere never released. The project's own hot-reload path (the desktop client disposes and recomposes the plugin fiber) could therefore stack a second copy of every listener, causing duplicate confirm dialogs, duplicate RPC calls, and two copies fighting over the same selection highlight. All listeners and the observer are now registered through the plugin context's disposal channel, and a module-level guard prevents a duplicateapply. - The menu observer no longer runs for the whole page lifetime. It is connected after an ellipsis click and disconnected on injection or timeout, instead of observing every DOM mutation in the app forever.
- Dead and contradictory client strings.
ungroupedUnsupportedwas never referenced.pickEscHintwas never referenced and contradicted the implementation; Escape now respects the copy (it does not clear the multi-selection while a text input has focus). Two hard-coded English strings that leaked into the Chinese UI are now localized. - Documentation drift: the READMEs and
docs/ARCHITECTURE.mddescribed three agent tools while four are registered (mover_doctorwas missing), and the compatibility section still claimed verification against0.1.5-rc.1while the README badge claimed0.2.0-rc.2. Tool tables, the compatibility boundary, and the test-suite description are now consistent and dated. - Tests 108 → 144: 10 new client DOM cases (row/workspace resolution, drag payload, listener teardown, dialog dismissal and the RPC failure matrix, against a hand-rolled DOM stub), 13 policy/Config/peer-range cases, and host-side coverage for the storage-layout self-check, archive truncation, backup orphan GC, the unarchive dual path, setTitle decoupling, and the official-API capability flags.
- Fixed a latent policy bug found while wiring the tunables:
cleanupOldDatadestructured{ days = 30 }, so "not supplied" became30and theNumber(days) || cleanupDays()fallback could never seeundefined— the configured cleanup age was silently shadowed by the default.
v2.1.1
Added
mover.doctorself-check: a read-only diagnostics endpoint, a "Doctor" button in the rescue panel, and amover_doctoragent tool. ~13 checks cover host services (registry, persistence, projection cache, archive channel, agents, approval seam), agent-tool registration, data directories (recycle bin, backups, move history, task records), pending manual-recovery records, and workspace folder presence — each reported as pass / warn / fail with details and a summary. Intended for after DSH upgrades: see what is degraded before attempting anything else. Stays sub-second (no full scan), never mutates, and never throws — degraded hosts get fail/warn checks instead of errors.- Install and trust assets in the README: a
dsh://plugin/installone-click deep-link button (Hub-aligned clients run the full flow; the official desktop client degrades it to window focus), a dsh.so risk badge (listed, L5 run-tested, risk low), a dsh-plugin-registry listing badge, and a "DSH tested 0.2.0-rc.2" badge. - Compatibility report:
docs/compatibility/dsh-0.2.0-rc.2-2026-10-04.mdrecords the real desktop verification (shared data home, in-app plugin install, drag move, dialog, hot-reload fix, agent tools) and the web-profile regression status; future DSH adaptations add a dated copy each. - Safety Ledger: the security-guarantees section is now branded around the backup-first pipeline (backup → stepwise rollback → post-move verification → recovery ledger) with an explicit never-does list (no git writes, no unbacked edits, no silent data loss, no unconfirmed destructive actions, no uploads — the plugin makes no network requests).
- Tests 105 → 108 (doctor all-green in sandbox, degraded-registry fail/warn behavior, recovery-record warning; agent-tool roster updated).
v2.1.0
Added
- Agent tools: the plugin now registers three model-callable tools through the official
dsh-toolsregistry —mover_list_sessions(read-only listing of workspace groups and sessions with their rescue statuses, for resolving a user-named group or conversation into exact ids),mover_move_session(moves one session through the same locked, backup-first, verified pipeline the panel uses), andmover_repair_sessions(one accounting-only repair pass). Tools are plain zero-dependency tool definitions; registration is skipped silently on hosts withoutdsh-tools, leaving the panel and drag flows untouched. - User approval for mutating tools:
mover_move_sessionandmover_repair_sessionsrequest an explicit user decision through the host approval seam (dsh-user-approval, mounted by dsh-base) before touching anything; a denial, dismissal, or unavailable answerer fails closed with a clear message, and approval-seam errors also block the call. Cancellation propagates cooperatively into the RPC layer, which finishes any in-flight rollback before stopping. mover.statusreports anagentToolscapability flag.- Tests 97 → 104 (tool registration and capability flag, listing composition, approval-gated move success, fail-closed outcomes for denied / cancelled / unavailable / seam-error, error-code passthrough with no approval round-trip for invalid input, repair with approval).
Fixed
- Opaque confirm dialog on the desktop (0.2). The desktop theme defines
--dsw-specific-menuas a translucent glass color, so the cross-workspace confirm card blended with the text underneath. The card now forces the themed color to full alpha via CSS relative-color syntax (browsers without support keep the previous translucent behavior). - Desktop (0.2) hot-reload no longer breaks moves. The client half accessed
ctx.connectionlazily on every RPC. After the desktop app hot-reloads or recomposes its client, the plugin's old cordis fiber is disposed, and that access throwscannot get required service "connection" in inactive context— surfacing as a failed-move toast even though nothing was wrong with the session. The connection service instance is now captured once at apply time (while the context is active) and reused for every call; if capture is not possible, a clear "refresh the page" message replaces the internal error in both the drag toast and the rescue-panel note paths (newcontextStalestrings, zh/en).
v2.0.3
Engineering
- First publish to the public npm registry as
dsh-workspace-mover(installs viadsh plugin --profile web add dsh-workspace-mover). - Local quality gate
npm run check(syntax + tests + pack dry-run); CI runs the same steps on ubuntu / windows / macos × Node 22/24. - README (zh/en): CI / npm version / plugin / DSH engines badges and a host compatibility matrix (
0.1.5-rc.1/rc.2;0.1.6-alphapending verification). - CONTRIBUTING: release checklist keeps
package.jsonversion, CHANGELOG, and git tags aligned; PR template requiresnpm run check.
v2.0.2
- Fixed GitHub Traffic badge updates when a Gist patch would delete a file that is not present; the workflow now skips missing-file deletes and avoids HTTP 422 failures.
- Completed the architecture documentation: the RPC endpoint list and workspace projection refresh behavior now match the implementation.
- Published
.tgzassets now include the architecture documentation and screenshots, and duplicate historical changelog entries were removed.
v2.0.1
- Compatible with DeepSeek Harness
0.1.5-rc.1. - Release downloads stay off the README until the total exceeds 10; when shown they use shields.io like the other badges instead of a gist SVG that GitHub renders as a broken text link.
- Host half waits for
webServerbefore registering RPC, fixing boot failures on 0.1.5. - Session relocation follows the highest canonical generation (
session.vN.jsonl[.zstd]) instead of a hard-codedsession.jsonl.zstd. - Refuse conflicting operations through in-process session/workspace locks; no
session.lockfile is created. - Keep full mover feature set (rescue, repoint, trash/backup, task center); official DSH still has no cross-workspace true move.
v1.3.0
Added
- Data protection summary and time-based cleanup: one combined line over the recycle bin and backups (item counts and footprint), plus a clean-older-than-30-days action — dry-run first (shows exactly how many entries and how much space would be freed), explicit confirmation, then per-item cleanup with the freed-space report. Corrupt or stale entries never block the rest.
- New RPC endpoint:
mover.data.cleanup(withdryRun). - Tests 69 → 70.