DSH 0.1.6-alpha.2 made two plugin-facing contracts stricter, and both broke
this plugin silently:
- `SidebarRightGuideEntry.id` is now required and unique per provider. The
native tab registrations sent guide entries without one, so the second kind
collided on `undefined` and `SidebarRightTabRegistry.register` threw
'duplicate guide entry id'. The throw happens inside `ctx.inject`'s callback
body, which cordis swallows, so the whole native surface stayed empty with no
symptom beyond a missing guide row.
- `conversation.chat.turnTail` changed from a `chain` to an additive `list`.
The chain's `select` made one entry render and let this plugin REPLACE the
host's produced-files row; a list cannot express that, and the registration
now throws 'list slot ... requires options.id'. Upstream chose the list
deliberately ('An additive list lets both plugins contribute without either
knowing the other's data or rendering'), so the plugin's row can only ever
duplicate the host's deliverables row -- which itself opens files through the
host's openFile, i.e. into this plugin's editor. The contribution is removed
and the row is the host's alone.
The file-opening half survives as `sidebar-file.ts` (the changes tab and the
editor host still use it), and `resolveSidebarPath` moves to the `paths.ts`
path-helper module beside its siblings. `registerNativeSurface` grows an
optional `reportFailure` so a future contract break reaches the visible
diagnostic strip instead of a silently empty guide, and one bad descriptor can
no longer take the remaining registrations down with it.
#1 GitView: hide/disable 'open in editor' for external linked worktrees
(path outside session workspace is rejected by the fence); add
isWithinWorkspace client helper for the gate.
#2 DiffTab: untracked diff read resolves against diff.repoRoot (child-repo
paths are repo-root-relative, not cwd-relative); fs.read route threads
selectedRepoOf into resolveGitPath so the host resolves the right base.
#3 GitView: chooseRepo handler mirrors chooseWorktree — clears status/
history/log and bumps generation before async refresh, preventing stale
rows from acting on the newly selected repository.
#4 git.ts: repoRoots/repoRoot compare roots via pathIdentity() (platform-
aware) instead of raw includes(), fixing win32 forward/backslash
mismatch that silently fell back to roots[0].
#5 markdown-images: mask fenced code blocks and inline code spans before
rewriting; only rewrite reference definitions whose label is actually
referenced by image syntax (not plain links). +3 tests.
#6 package.json: downgrade unrun ^0.3.1 → ^0.2.39 (0.3.x requires Node
^22.13, incompatible with declared engines >=20).
#7 market-manifest.spec: shell:true on win32 so execFileSync resolves the
pnpm .cmd shim.
#8 smoke.spec: build html-route URL via encodeHtmlUrl() (production
encoder) so the Windows drive separator is correct.
#9 index.ts git.worktrees route: thread selectedRepoOf so a workspace
container's selected child repo's linked worktrees appear.
- fs-tree joins listed paths with the platform separator (Windows rows
previously leaked mixed separators)
- media route containment check goes through isWithin(): separator-
tolerant and case-insensitive on win32, so case-mismatched Windows
paths are not misclassified
- relativeTo compares case-insensitively (Windows / case-insensitive
macOS volumes) while keeping the caller's own casing in the output
- tests: platform-conditional path assertions, os.tmpdir() instead of
/tmp, isWithin/relativeTo/resolveSidebarPath win32 coverage
- Tabs, the + menu, and empty-pane cards carry per-type icons (folder /
branch / terminal / code file); a terminal glyph joins the icon set
- Hovering an explorer row reveals an @文件 button at the far right that
appends @<relative path> to the composer draft (session-scoped input
service, space-separated append)
- Right-clicking a row opens a context menu: copy relative / absolute
path (writeClipboard + transient in-row "copied" label)
- Rows become div role=button (Enter/Space) to host the inner button;
relativeTo helper unit-tested