# Changelog

## 1.5.1

Fix: every archived-session route was unreachable in the **Desktop application**.

### Fixed

* The Host gate demanded `Origin === http://<Host>` exactly. That holds for `dsh web`, whose page is served
  from the same origin, but the Desktop application serves this UI from its own `dsh-app://app/` scheme and
  forwards plugin calls to the local server, so its requests carry an opaque page origin and all four
  `/plugins/dsh-session-delete/*` routes answered 403 — reading a transcript, content search, restore, and
  permanent deletion were all dead there while they worked in `dsh web`.
* The gate now lives in one place (`src/host/same-origin.mjs`) and accepts either a strict same-origin web
  request, or a request carrying this plugin's own action header from an opaque or loopback page origin. A
  cross-site page cannot add a custom header without a CORS preflight this server never approves, so the
  header is the real CSRF gate: a public site origin is still refused even with the header, and a loopback
  origin must also match the request's port.
* Each route now sends and requires its own action header — `read-archive-detail`, `search-archive-content`,
  `restore-session`, and the existing `delete-session` confirmation. A plain web client still passes without
  any header (strict same-origin), so a browser holding the previous client module keeps working against the
  new Host half.
* The refusal message now names the observed `origin` and `host`, so a future mismatch reports its own
  evidence instead of requiring a debugging session.

### Verification

* Assertions across the four suites (host 79, client 146, package 28, profile 13), including the Desktop
  shell origin, a `null`/absent origin, the `localhost`-vs-`127.0.0.1` alias, a public site origin, a
  differing port, and the existing cancel-sends-nothing contract.

## 1.5.0

Route C: the plugin is rebuilt as an **official-slot plugin** for DSH `0.2.0-rc.2`. It no longer replaces
the official workspace client, so it no longer drifts with upstream UI changes.

### Changed — naming and attribution

* The user-facing product name is now **DSH Chat Manager Wide**, and both READMEs carry an unofficial-fork
  statement directly under the title: forked from `dsh-chat-manager` by WSL043 (MIT), not affiliated with or
  endorsed by DeepSeek or by the upstream author. The previous heading and tagline were upstream's exact
  product name and tagline, which a fork must not present as its own — MIT covers the code, not a product
  name.
* `package.json`'s description records the same caveat, and the generated `lib/client.js` header names the
  fork.
* `LICENSE` and `THIRD_PARTY_NOTICES.md` are unchanged; the MIT notices and attribution were already correct.

### Changed — architecture

* `lib/client.js` is now this package's own small browser module (37,185 bytes) that registers into three
  official slots instead of a 303,999-byte modified build of `@deepseek-ai/dsh-client-ui-workspace`:
  * `settings.section` with id `archived-sessions` — the seat the official settings navigation already
    reserved (including its archive icon); the left-list/right-transcript browser lives here.
  * `sidebar.workspaces.session.menu.item` — **View archived transcript** (order 500, shown only for an
    archived row, which the official UI refuses to open) and the red **Delete session** (order 510).
  * `shell.overlay` — the wide transcript dialog and the two-step permanent-deletion confirmation.
* `cordis.patch.yml` no longer disables the official `ui-workspace` row; it only inserts this bundle. The
  official archive/unarchive actions, the archived-row filter, and archived-content search keep working.
* `peerDependencies` are re-pinned to the runtime the plugin is built for. The peer gate compares every
  `@deepseek-ai/dsh-*` peer against the **dsh runtime version**, so `0.2.0-rc.2` is the exact claim and a
  future runtime fails loudly instead of loading an unverified client.

### Added

* A public source repository: <https://github.com/WindAndWood/dsh-chat-manager-wide>. `package.json` now
  carries `repository` / `bugs` / `homepage`, `SECURITY.md` points at GitHub's private vulnerability
  report form, and the READMEs link the repository and its issue tracker instead of saying none exists.
* Three interface screenshots under `docs/assets/` (`menu-entries.png`, `archive-transcript.png`,
  `archive-search.png`), referenced from both READMEs by absolute `raw.githubusercontent.com` URLs and
  shipped in the tarball so other viewers can reach them too.

### Changed — archived transcript

* The detail route now reads `sessionQuery.readSurface()` instead of `filterEvents()`, so the Host returns
  the original content blocks (`text` / `reasoning` / `tool-call` / `image` / `file`) instead of one
  flattened string. `filterEvents` joined assistant prose, tool names and raw tool arguments with newlines
  and dropped reasoning entirely — that is where the crowded transcript came from. A backend without
  `readSurface` degrades to the old flattened text and says so in the UI.
* Tool calls render as collapsed cards: the tool name, a one-line summary taken from the arguments'
  `description` / `command` / `path`, the raw arguments (pretty-printed when they are JSON), and the paired
  `tool/result` output. Failed calls are marked as errors.
* Reasoning blocks get their own collapsed card. Loop-owned runtime-context snapshots
  (`source.kind === 'runtime-context'`, with a preamble fallback for older logs) are folded into a
  "system-injected runtime context" card instead of being presented as a user turn.
* Assistant prose renders through the official `ui-primitives` `MarkdownText`; authored user text stays
  literal, so a user's own asterisks and underscores are never reinterpreted as Markdown.
* A `user/message` event carries **both** the human prompt and synthetic `agent.inject()` contexts
  (`source.kind` distinguishes them, per `dsh-session`'s own `SessionEventMap`). The reader now reports the
  source kind, and the client stops presenting an injection as the user's own turn: it gets a
  "system-injected" label instead of "Me".
* Workspace-instruction snapshots (`source.kind === 'agent-instructions'`, which carries the reconciled file
  list) are parsed into an intro, one entry per file and the verbatim original. Each file's Markdown now
  **renders as Markdown** instead of showing raw source, with the file list and its set/replace/remove
  action beside it; the untouched `<system-reminder>` framing stays one click away under "verbatim injected
  text" so the transcript never misreports what the model read.
* Any other synthetic `user/message` (skill content, file-change notices, …) also renders as Markdown,
  because it is not the user's own prose. Authored prompts keep their literal rendering.
* Role recognition: user turns align right in a filled bubble, assistant turns align left, each with a role
  chip, timestamp, `interrupted` marker and token usage; synthetic injections align left in a dashed card.
* Search counts its matches, scrolls to and outlines the first matching turn, and highlights plain-text
  matches in the transcript and in the list snippets. Same-day messages are separated by a date line.
* Read limits are unchanged in spirit and now per block: 4000 messages, 40 000 characters per prose block,
  20 000 per reasoning block, 8 000 per tool-argument blob, 20 000 per tool result, 4 MiB total.

### Removed

* `compatibility.json` — no upstream client version matrix any more.
* `scripts/build-client-local.mjs` and the 20+ `replaceOnce` anchors of the old `scripts/build-client.mjs`.
  The new composer only wraps `src/client/factory.js` and derives the module id from `package.json#name`.
* All fixture `devDependencies` (11 workspace fixtures, `playwright`), the `clsx` runtime dependency, and
  `pnpm-lock.yaml`.
* `scripts/smoke-ui.mjs` — it drove the removed sidebar archive button. Its non-destructive intent is now
  covered by `_work/verify/verify-client.mjs`; live-UI acceptance is a manual checklist in `AGENTS.md`.
* The test scripts that pointed at a `tests/` directory this repository never had.

### Kept

* `src/host/archive-manager.mjs` (including the archived-transcript reader and its 4000/40,000/4 MiB
  limits), `src/host/delete-session.mjs`, and the four `/plugins/dsh-session-delete/*` routes.
* The wide `min(1120px, 100%)` master/detail layout and its copy-conversation, truncation, restore and
  delete affordances; the task name is still shown before the second confirmation.
* Upstream `dsh-chat-manager` MIT attribution in `LICENSE` and `THIRD_PARTY_NOTICES.md`.

### Verification

* `_work/verify/verify-host.mjs` — 59/59 host assertions pass (block mapping, the injected-snapshot split
  both by marker and by preamble, the `agent-instructions` snapshot parse including its file list, the
  synthetic/human source split, tool-call/result pairing, per-block clamping, the 4000-message and 4 MiB
  limits, the degraded backend, and the HTTP boundary).
* `_work/verify/verify-client.mjs` — 142/142 browser-half assertions pass (slot ids and orders, locale
  dictionary balance and coverage, hook-order stability across re-renders, the structured transcript
  rendering, synthetic-injection lanes and cards, search highlighting, clipboard assembly, the
  legacy-payload fallback, and the contract that a cancelled confirmation sends **no** delete request).
* `_work/verify/verify-package.mjs` — 28/28: the real `evaluatePluginCompatibility` from the installed dsh
  accepts the package, the published file list is complete, and `lib/client.js` rebuilds byte-for-byte.
* `_work/verify/verify-profile.mjs` — 13/13: the profile loader `dsh web` uses composes the installed
  bundle with no skipped bundle while `@deepseek-ai/dsh-web-app` still loads.

## 1.4.1

Documentation and package-metadata release. `lib/client.js` and the host half (`src/`) are unchanged
from 1.4.0, so this version carries an identical bundle.

### Changed

* `package.json` gains an `author` (`windandwood <liangjinzhou22@qq.com>`). `repository`, `bugs` and
  `homepage` deliberately stay unset until this fork has a public source repository of its own.
* `README.md` and `README.en.md` no longer point at upstream's repository. Removed: the GitHub
  release / checks / license / stars badges, the Awesome DSH badge and its listing link, the
  image-viewer link, all three `raw.githubusercontent.com/WSL043/...` screenshots, and both
  issue-form links. Kept: the npm version and download badges, the DSH compatibility badge, and a
  static MIT license badge linked to `LICENSE`.
* The removed screenshots are replaced with written descriptions of the wide master/detail archive
  dialog and of the permanent-delete confirmation.
* The README agent-install sections link to this package's own `AGENTS.md` instead of upstream's
  `v1.3.4` raw URL.
* `README.en.md`'s compatibility line is corrected to `0.1.5-rc.1`, matching `compatibility.json` and
  `README.md`.
* `SECURITY.md` no longer points at a repository security form that does not exist yet.
* `PUBLISH.md` no longer claims the local build produced the shipped bundle. It now records that
  `lib/client.js` in this tree is the dual-fixture release build (303,999 bytes, sha256
  `116C07122100B3C8BB024FE2CC83469F07FA1ABB6FA1B6599A536D3C6AB4DEF2`) and that
  `scripts/build-client-local.mjs` overwrites it with the local form.

### Kept

* `LICENSE` and `THIRD_PARTY_NOTICES.md` are unchanged. Upstream's MIT copyright notice stays, as the
  license requires, and the README fork notice still credits WSL043.

## 1.4.0

Fork of [`dsh-chat-manager@1.3.4`](https://www.npmjs.com/package/dsh-chat-manager) by WSL043.

### Changed — archived sessions dialog

* The archive manager dialog is now full width (`min(1120px, 100%)`) instead of the shared `Modal`
  default of 380 px, and it lays out as a master/detail browser:
  * left pane: search box plus the archived session list; a row is selectable, and every row keeps
    its Restore / Delete actions;
  * right pane: the complete current user/assistant transcript of the selected archived session,
    with role labels, timestamps, internal scrolling, a message count and a "copy conversation"
    action.
* The dialog injects its own stylesheet (`#dcm-archive-style`) instead of relying on the workspace
  client's CSS modules, so the layout survives upstream style drift.

### Added — archived conversation reads

* Host route `POST /plugins/dsh-session-delete/archive-detail`
  (`readArchivedSessionDetail` in `src/host/archive-manager.mjs`) returns one archived session's
  transcript. It re-checks archive membership, reads only `user/message` and `assistant/message`
  events on the `current` surface through `sessionQuery.filterEvents`, and clamps the payload
  (4000 messages, 40000 characters per message, 4 MiB of text in total).
* `scripts/build-client-local.mjs` rebuilds `lib/client.js` from the
  `@deepseek-ai/dsh-client-ui-workspace` client that the local DSH installation serves, for
  installations without the pinned upstream fixture devDependencies.

### Changed — packaging

* Renamed to `dsh-chat-manager-wide`. The browser module id is now derived from `package.json#name`
  instead of being hard-coded, so a future rename only touches `package.json` and
  `cordis.patch.yml` before a rebuild.
* The composed bundle carries an upstream-attribution header. Upstream's own artifact notice sits
  ahead of `factory: (require) => {` and was dropped by the bundle extractor, so a published fork
  shipped without it.
* Upstream `author` / `repository` / `bugs` / `homepage` metadata was removed so a fork does not
  advertise upstream's coordinates.
* `npm run build` keeps the upstream fixture-based build; `npm run build:local` builds from the
  installed DSH client.

### Limitations

* The transcript contains user and assistant messages only — no tool calls, reasoning blocks or
  subagent traffic.
* The custom dialog is only used when the host exposes no official `archived-sessions` settings
  section; where one exists (DSH-Portable) the plugin still delegates to it.
