76 Commits
Author SHA1 Message Date
zhu1090093659 dc7e26b9f0 refactor(shared): drop dead shared artifacts and realign references
- Remove the sync-manifest entry for shared/host/run-guarded.ts and the three
  generated copies under packages/{dsh-usage,dsh-task-board,dsh-git-graph}/src/host/:
  nothing in this repository imported the module (the satellite repositories
  carry their own copies), so the entry only kept three unread files in sync.
  The shared source and its spec stay.
- Delete the unused mobileBundle helper and its node:module createRequire import
  from shared/tsdown.client.ts; the standalone mobile bundle has been gone since
  0.4.0.
- Update the sync composition guard in scripts/sync-shared.test.mjs (99 -> 96
  copies, 48 -> 45 host copies) and refresh scripts/lib-artifact-fingerprints.json.
- Re-point the notes, READMEs, CONTRIBUTING and docs that still linked the
  skin-center contract files to the dsh-skins repository, and prune the stale
  screenshots.
- Record the decision in
  .agents/notes/implemented/simplification/2026-09-26-dead-shared-artifacts-removed.md
  and correct the run-guarded facts in the aggregate fault-isolation note.
2026-09-27 20:47:07 +08:00
zhu1090093659 32e6a83a39 refactor(panels): render every family panel through the native layout seats
ssh is the last panel that took the center column over at the DOM level. It
now registers a row in the shell's own panel list (sidebar.panellist) and a
keyed page in the layout's main slot, like the task board and the skill
center, so the shell owns the row box, label, highlight, rail and switch.
That retires the whole takeover apparatus:

- shared/client/panel-mount-core.ts and shared/client/sidebar-entry-core.ts
  are deleted along with every synced copy; ssh's mount.tsx, sidebar-entry.ts,
  panel-mount-core.ts and sidebar-entry-core.ts go with them. The
  body-mutations hub now serves only the aggregate shell and the usage card.
- The dsh-panel-activate handshake and PANEL_FAMILY occupancy table are gone:
  the layout's keyed main slot is the single occupancy authority, so the board
  and the skill center no longer coordinate with anyone.
- The terminal survives the move because the PTY session is host-owned (see
  the previous commit): the layout unmounting a deselected page costs the view
  its xterm instance, not the remote shell, and the terminal tab reattaches by
  session id. The panel's tab, connect request and session id live in the
  controller rather than in component state.

Tests move with the design: the takeover specs (center-panel-lifecycle,
center-column-css, sidebar-entry, the layout specs, board/ssh coexistence) are
replaced by native-panel-registry specs that drive the real SlotCore, plus a
controller-state spec for ssh's view state.

Validation: pnpm typecheck; pnpm test (ssh 202, task-board 561, skill-explorer
121, shared 107, all packages green); pnpm test:scripts 342/342;
pnpm test:standards; pnpm docs:check; pnpm i18n:check; pnpm aggregate:check;
pnpm libs:check; pnpm market:check.
2026-09-26 17:23:04 +08:00
zhu1090093659 208bb2c10e feat(skill-explorer): render the skill center through the native layout seats
The skill center stops taking the center column over at the DOM level. It
contributes a row into the shell's own panel list (sidebar.panellist) and a
keyed page into the layout's main slot, and drives ctx.layout.selectPanel —
the same shape the task board already uses, so the shell owns the row box,
the label, the active highlight and the collapsed rail. mount.tsx, the
hand-drawn sidebar row, and the package-local panel-mount-core /
sidebar-entry-core / body-mutations copies are gone.

The panel's tab and editor target move from SkillPanel component state into
PanelController. The layout mounts a keyed page only while its panel is
selected, so component-local state dropped the open tab and any in-progress
edit on every panel switch; SkillPanel now reads the controller snapshot
through useSyncExternalStore. panel-state.spec.ts locks that contract, and
native-panel-registry.spec.ts drives the registration against the real
SlotCore.

ssh still takes the column over at the DOM level, so native-panel.tsx keeps a
transitional dsh-panel-activate handshake with it (and the task board keeps
its side). Both go away when ssh moves to the native seats too.

sync-shared loses the skill center's three copies: the copy-count buckets are
102 total / 42 client, and ssh is now the only consumer of
sidebar-entry-core and panel-mount-core.

Validation: pnpm typecheck, pnpm test (skill-explorer 121, ssh 210,
task-board 565+1 skipped), pnpm test:scripts 342/342, pnpm test:standards,
pnpm docs:check, pnpm i18n:check, pnpm aggregate:check, pnpm libs:check and
pnpm market:check all pass.
2026-09-26 17:10:00 +08:00
zhu1090093659 68b095272b Merge origin/dev into dev: one center-column panel family
Brings in the 11 upstream commits, chiefly 305a3863 (skill-explorer moves
into the center column). Both sides had reworked the same panel subsystem
from opposite directions, so the merge integrates rather than picks a side.

- shared/client/panel-mount-core.ts keeps the upstream PANEL_FAMILY table
  (one occupancy row per panel instead of pairwise sibling options) and
  documents that the task board left the core for the native layout seats.
- The board keeps its native panel registration and its dsh-panel-activate
  handshake, widened from ssh alone to every DOM-takeover family panel:
  coordinateWithFamilyPanels plus TAKEOVER_PANEL_NAMES now cover
  skill-explorer too, so the new third panel can no longer paint over the
  board while its row still looks selected. panel-coexistence.spec.ts
  covers the new direction.
- sync-shared drops the board's body-mutations / sidebar-entry-core /
  panel-mount-core copies and keeps ssh plus skill-explorer for the core;
  copy-count buckets are 105 total / 45 client.
- The panel-mount-core extraction note records the merged design and
  refreshed facts; both sides and the sidecar are re-recorded.

Merge conflicts: 14 files. Validation: pnpm typecheck, pnpm test
(ssh 210, task-board 565+1 skipped, skill-explorer 115), pnpm docs:check,
pnpm i18n:check, pnpm test:scripts 342/342, pnpm libs:check,
pnpm market:check, and the panel suites all pass.

pnpm test:standards reports 3 new violation groups, all in
dsh-plugin-manager gateway specs that another session has unstaged; they
are not part of this merge.
2026-09-26 16:37:10 +08:00
zhu1090093659 da32f628a5 feat(task-board): render the board through the native layout panel
Move the task board off its DOM takeover: the board now registers a
sidebar.panellist row and a keyed main page through the official slots
system, and the package-local panel-mount-core, sidebar-entry-core and
body-mutations copies are retired. The shared panel-mount-core returns to
the single ssh consumer with sibling activation names.

Also folds in the plugin-manager update-patch rework (the settings tab is
replaced by a patch row on the official Plugins page, plus the desktop
launch-profile repair) and the matching Agent Notes.

Committed as a checkpoint before merging origin/dev.
2026-09-26 16:14:14 +08:00
EDDYCRAZY-CC ad90e46b28 fix(settings): bind family cards to the profile entry the Host serves
A family settings card addresses its form by PROFILE ENTRY ID, but each card
knew only its own namespace. When the family binder is not loaded the cards
fell back to ctx.configForms.get(namespace) — an entry the Host does not serve
on an aggregate install. The write was rejected with "No configurable plugin
entry \"liangshen\"" while the card reported "the deployment did not accept
these values", which is what the LiangShen settings page showed for every edit.

The fallback now lives once in shared/client/settings/settings-entry-form.ts
(synced to the six packages whose card binds a family namespace) and binds the
entry id the shared describe mirror justifies, REBINDING when the mirror names
a different one of the package rows. A one-shot guess cannot be right for every
deployment: the mirror answers asynchronously — at plugin activation it usually
holds nothing yet, and the aggregate mounts its client children in order — the
bare namespace is no entry id on an aggregate install, and the aggregate row id
is wrong on a standalone one, whose row id is the namespace or the package own
ui-* row. An unanswered or EMPTY mirror counts as unanswered, not as absence;
only a mirror that answers with other packages rows falls back to the
namespace itself, which is the pre-0.1.7 keying shape.

Affected cards: dsh-liangshen, dsh-remote-web-ui, dsh-task-board, dsh-market,
dsh-usage and dsh-session-archive (the last three carried the same defect).
The aggregate and market specs now model a mirror that names the served row
instead of asserting the namespace.

Verified in the real Web GUI: the save now posts ns "web-ui-liangshen" and the
Host answers ok. The refreshed aggregate lib/ and the new fingerprints ship
with the change; the owning 0.1.7 cohort note records the binding rule.

pnpm typecheck, pnpm test, pnpm docs:check, pnpm i18n:check,
pnpm aggregate:check, pnpm libs:check, pnpm sync-shared:check,
pnpm test:standards, pnpm runtime-deps:check and pnpm emoji:check pass.
pnpm test:scripts fails only in the tar --force-local suites, which Windows
bsdtar rejects (GNU flag) and which this change does not touch.
2026-09-25 15:39:12 +08:00
EDDYCRAZY-CC 67f421a5cc test(sync-shared): move the copy-count buckets for the third panel core
The skill center's panel-mount-core.ts copy is a 102nd generated copy and the
42nd under src/client/, so the two bucket assertions in the sync-shared test
move with the manifest. Caught by CI: the assertion reported 102 against the
stale 101.
2026-09-25 15:00:18 +08:00
zhu1090093659 e09bd211d3 feat(dsh-update): split the self-update surface into its own plugin row
The self-update surface lived inside dsh-remote-web-ui, so disabling or removing the remote-access plugin also removed the update entry, and the desktop application - which owns its own updater - had no way to keep the seat off one page while keeping it elsewhere. It now ships as @linxin666/dsh-update with its own bundle row (update / web-ui-update) and its own host half behind the loopback fence.

The aggregate gains the child (aggregate.yml, cordis.patch.yml, children.*), the shared-file sync manifest carries the new consumer targets, the ru dictionary moves its update namespace to the new file, the three old note records are updated in place for the new owner of the surface, and the market's committed lib is rebuilt for the shared guard it carries.
2026-09-25 10:22:27 +08:00
zhu1090093659 21f3b4d72a refactor(preset-center): consume the extracted preset center instead of carrying it
The preset center now lives in its own repository (dsh-presets) and is consumed
here as the published npm package @linxin666/dsh-client-ui-preset-center, the
way the skin center, the pet plugin and the community plugin index already are.

- packages/dsh-preset-center leaves this tree (plugin sources, tests and the
  presets/ catalog; history stays in this repository);
- the aggregate mounts it through an external rows: entry (web-ui-preset-center)
  with a hand-written ^0.4.1 range, and ./preset-center stays in the exports map
  as a tombstone so profiles written against the patchFrom era keep importing;
- market-inputs.lock.json gains a presets input pinned to the
  satellites/dsh-presets gitlink, and scripts/market-build reads
  .market-inputs/presets with the in-repo fallback kept for the fixture tests;
- scripts/sync-shared.mjs stops mirroring five host helpers into the package
  (101 -> 96 copies); the lib fingerprints, coverage baseline, test-standards
  baseline, runtime-deps scan and i18n audit each shrink by one package;
- the contribution gate has no exception left: reject-non-content-pr.yml
  redirects a 新预设收录 declaration to dsh-presets, and the PR template,
  CONTRIBUTING.md, PR_TRIAGE.md and ISSUE_TRIAGE.md now state that this
  repository accepts no external contribution directly;
- docs, the family-satellite owning note and the two preset notes follow, and
  the new Agent Note records the split.

Gated by: typecheck, aggregate:check, libs:check, sync-shared:check,
runtime-deps:check, i18n:check, emoji:check, docs:check, market:check,
test:standards, test:scripts (340 tests), test (every package) and build.

Not yet safe to merge on its own: the satellites/dsh-presets gitlink needs that
repository to exist on GitHub, so the satellite commits and this pin have to be
pushed together.
2026-09-24 13:13:17 +08:00
zhu1090093659 57d1499ddf test(vitest): give the family test setups a usable localStorage
Node 25 defines localStorage on the global object, and without a usable
--localstorage-file its getter returns an empty object: getItem, setItem and
clear are all missing. Vitest's jsdom environment fills in globals only where
the name is still free, and under vitest window is globalThis, so that stub
survived into every DOM test: the packages whose code reads storage took their
degraded paths instead of the code under test, and dsh-task-board's specs failed
outright on window.localStorage.clear.

The shared setup now installs a Storage in a DOM environment and removes the
stub where there is no DOM, which is what Node 22 leaves behind. dsh-git-graph
and dsh-task-board join its copy manifest, and dsh-skill-explorer's own setup
imports the shared source.

Measured on Node 25 against Node 22, the repair is what moves the numbers back:
dsh-git-graph 79.53 -> 81.32 lines, dsh-remote-web-ui 69.66 -> 70.34,
dsh-skill-explorer 77.61 -> 80.22, dsh-web-settings 78.66 -> 82, with branches,
functions and statements following. Coverage no longer depends on the
interpreter that ran the suite, which is what makes one recorded baseline mean
the same thing in both.
2026-09-24 09:54:51 +08:00
zhu1090093659 9004d0ee7d refactor: consume the extracted plugins instead of carrying them
The skin center, pet and community-index plugins now live in their own
repositories and are consumed as published npm packages, so this tree drops
them and everything that only existed to serve them in-repo.

Removed: packages/dsh-pet, packages/dsh-community-plugins and
packages/skins/skin-center (history stays in this repository), plus the root
scripts that moved with them (skin center catalog check, the reviewed-hooks
registry, the skin and pet authoring CLIs and their tests, community-index).
scripts/skins-montage.mjs stays: it renders the root README collage from
market/dist, which is this repository's tooling.

Decoupled:
- scripts/sync-shared.mjs no longer mirrors the settings trio, host helpers or
  http/mount-once copies into the three packages (114 copies -> 99);
- lib-artifact-fingerprints.json tracks three committed lib/ packages now that
  skin-center left;
- packages/dsh-usage drops an unused @linxin666/dsh-pet devDependency;
- the skin/pet/community gates leave ci.yml and the root scripts (they run in
  the satellite repositories' own CI);
- scripts/i18n-audit.mjs no longer reads pet's client locale file, and the
  test-standards and emoji audits skip .market-inputs (fetched content is not
  ours to audit);
- the market build pins the community index in market-inputs.lock.json like the
  skin and pet content, so the plugin list the site serves is reproducible from
  a commit instead of following whatever npm resolves, and the catalog's skin
  repo URLs point at dsh-skins;
- docs (root AGENTS.md, architecture, plugins, development, publish-prep) and
  CONTRIBUTING point at the new repositories.

Gated by: aggregate:check, libs:check, runtime-deps:check, market:check,
sync-shared:check, test:standards, docs:check, i18n:check, emoji:check,
typecheck and 307/307 script tests.

Not yet safe to merge: the aggregate's three dependencies resolve from npm,
and the published 0.3.24 still injects the retired settingsScope service, so
the mount smoke stays red until the satellite repositories publish a build
containing the migration.
2026-09-23 23:19:08 +08:00
EDDYCRAZY-CC 0da5046cd2 feat(usage): seat a collapsible price glance card below the sidebar Settings row
The 2026-09-18 removal left the usage overview reachable only from the
settings section. The user asked for the sidebar card back, redesigned at
the bottom-left below Settings. The new surface is a glance plus gateway,
not the retired panel: one card with a price-first headline (today's
estimated spend, falling back to today's tokens when nothing priced is
recorded), a tokens/calls line, and up to two configured-provider
balances. The card body opens the settings panel on the usage section;
a corner chevron folds it into a one-line strip persisted in localStorage
(dsh-usage.foot-card.collapsed).

- UsageFootCard.tsx + foot-card-mount.tsx: the mount appends the container
  as the shell foot area's last child (no slot exists below
  sidebar.settings) and self-heals through the shared body-mutation hub;
  the card shares the section's store/poll and runs its own 30 s
  visible-tab loop; it bows out while disabled or while the host answers
  404, and hides in the 56 px rail.
- New zh/en keys usage.foot.* with ru mirrors; the body-mutations
  sync-shared target returns for dsh-usage.
- The semantic-attrs contract gains the foot-card part rows and drops the
  stale usage sidebar anchors; the README pair, the package description,
  and the agent notes move with the change (the new foot-card note
  partially supersedes the removal note, which keeps its decision with a
  cross-link).

Live GUI evidence (Edge via Playwright against the running host at
127.0.0.1:3080): the card seats as the foot area's last child below the
settingsArea (256x96 expanded, 256x28 collapsed), the collapse choice
survives a reload, clicking the body opens the settings panel with the
usage section active, and the card hides in the collapsed rail; zero
console errors.
2026-09-23 19:48:33 +08:00
zhu1090093659 ef637f657d feat(aggregate)!: remove dsh-doctor and dsh-tool-describe-image from the family
Both plugins are no longer useful and leave the family per owner direction.
The packages are deleted from the workspace; the aggregate drops their
patchFrom/deps rows and inactive entries, keeps one tombstone shell export
per removed id so old profiles degrade to an inert plugin instead of
ERR_PACKAGE_PATH_NOT_EXPORTED, and drops the stale retire block whose
target row the 0.1.7-alpha.2 host no longer mounts. The reference sweep
covers sync-shared targets and counts, the i18n audit, the ru dictionaries,
the web-settings allowlist, plugin-manager fixtures, the skin-center
semantic-attrs contract, the labeler, coverage baseline, lockfile, and
docs; desktop/runtime/profile-web stays pinned to the published 0.3.19
that still contains both packages.
2026-09-23 17:05:26 +08:00
EDDYCRAZY-CC 0520e8a479 fix(sidebar): align entry rows with the shell panel rows and drop the usage row
The injected sidebar entry rows (task board / SSH / skill explorer) carried their
own box - 10px padding, 8px radius, 13px type - so their icons and labels sat on
different x positions than the shell panel rows next to them. They now reproduce
the shell panel-row geometry: 2px inset, 12px radius, 7px 8px padding, 36px row,
14/22 type, primary ink, and a 16px glyph box (18px on the 56px rail).

The usage sidebar entry and its collapsible panel are removed: the settings
section already renders the same overview, and the row duplicated it in a
permanent navigation slot. With its only consumer gone, the shared entry core
drops the trailing-actions API (SidebarEntryAction, the composite container, the
entryAction/entryMain CSS contract) it had grown for that row.

The pet bubble is untouched: dsh-pet has no changes here, and its announcement
API and bubble rendering are intact.
2026-09-20 21:48:43 +08:00
zhu1090093659 40f5f2927d chore(sdk): move the family to the 0.1.6-alpha.2 cohort on the permanent alpha branch
Adapt dsh-web to the experimental @deepseek-ai/dsh-* 0.1.6-alpha.2 cohort in the
same isolated alpha worktree and DSH home, so the accepted 0.1.5-rc.1 stable
environment, its profile tree and the global dsh CLI stay untouched.

Cohort: every consumed range, the plugin scaffold, the root README badges, the
CI and release mount-smoke pins, the desktop runtime pin and its lockfile, both
release-age exclusion lists and the desktop overrides block move to
0.1.6-alpha.2; the declared host floor becomes dsh.engines.dsh >=0.1.6-alpha.2.
cordis, cosmokit and schemastery keep their independent support pins.
@deepseek-ai/dsh-client-ui-workspace joins the repository exclusion list and the
packages that navigate gained it as a devDependency, because the family now
consumes it directly.

Adaptation of the SDK delta - the multi-instance Client Session model:
- SessionListState.current/currentAddress and SessionSummary.completed are gone,
  and ISessions.open()/openSubagent()/clear() are removed. View selection now
  belongs to the workspace UI, which owns the main-area reference and publishes
  it as retainedBy.mainView; navigation is ctx.uiWorkspace.openSession(target).
- shared/client/main-session.ts adds mainViewSessionId(byId), the catalog-level
  reading of that marker, and sync-shared copies it into the seven consumers.
  Ten call sites across eight packages read the removed faces; two of them
  (git-graph auto-isolation, session-archive) type-checked against local
  structural doubles and never appeared in the compiler's error list, so the
  inventory was built by searching for the removed names rather than by
  trusting tsc.
- dsh-task-board's framework-free controller port changes from a list snapshot
  to { current(), open(), subscribe() }; the wiring resolves current() from the
  marker. dsh-git-graph navigates new worktree sessions through the workspace UI.
  dsh-pet, dsh-plugin-manager, dsh-doctor, dsh-liangshen, dsh-session-id and
  dsh-session-archive read the marker instead of the removed selection.

Upstream packaging defect: dsh-client-ui-primitives@0.1.6-alpha.2 imports
simple-icons from its emitted lib/index.js while the published manifest still
declares no runtime dependencies; packageExtensions restores it at the exact pin
the official source resolves (16.31.0), beside the existing diff/shiki/micromark
restorations. No installed file is patched.

Native-first: no family row registers the new sidebar panel slots, and the
alpha.1 to alpha.2 slot-key comparison is additive only. dsh-plugin-manager
already extends the official Plugins section through settings.plugins.tab rather
than mounting a parallel page, and that stays the right native extension. The
aggregate declares no external npm plugin, so the new runtime plugin dependency
resolution has no external hard-binding to unmask. The inject contract records
dsh-client-ui-workspace as an approved inject module with its rationale.

Testing: pnpm typecheck, sync-shared:check, skin-center:check, community:check,
libs:check, build, test, test:scripts, test:desktop, runtime-deps:check,
aggregate:check, emoji:check, test:standards, docs:check, i18n:check and
market:check pass, and pnpm install --frozen-lockfile --ignore-scripts resolves
the lockfile. The alpha host in ~/.dsh-alpha is upgraded to 0.1.6-alpha.2 and
every profile @deepseek-ai copy is a symlink into it (235 ok, 0 warn, 0 fail);
dsh --profile alpha-web --dump-config composes the family rows with the retired
ui-settings-unarchive-sessions row.
2026-09-20 21:48:39 +08:00
EDDYCRAZY-CC 8ad234c0dc fix(dsh-web): resolve issues #1587, #1588, #1589, #1592, #1597, #1600
- task-board: pick the newest SETTLED execution for session reuse; the
  launch path appends this run's open record before the rule reads it
  (#1587)
- plugin-manager: resolve the packaged desktop runtime's own lib/bin.js
  and run it through the host interpreter when no PATH entry or .bin shim
  exists (#1588)
- plugin cards: contribute to whichever plugin-card seat the host
  declares (family list seat, else the official keyed settings.plugin.item
  seat) and log a refused registration instead of swallowing it (#1589)
- usage: sidebar entry + collapsible panel over the same overview
  document, with the family pairing fence on the host routes (#1592)
- usage: serve the zai route, key plan windows by the provider unit,
  use the exact credit ratio, and skip TIME_LIMIT/unknown units (#1597)
- plugin-manager + remote-web-ui: accumulate child output as bytes and
  decode once, so a Windows CP936 console renders readable text (#1600)
2026-09-17 00:58:01 +08:00
zhu1090093659 7d236e315e perf(web-all,skin-center): share one body mutation observer and coalesce shell DOM syncs
Family plugins each installed their own document.body subtree MutationObserver,
so per-mutation cost grew with the number of installed plugins during chat
streaming. Add shared/client/body-mutations.ts: one page-wide observer
registered on globalThis under Symbol.for, delivering accumulated records to
subscribers at most once per animation frame. sidebar-entry-core,
panel-mount-core and the aggregate shim subscribe to it instead of observing
body themselves.

skin-center: cache the composer seat and skip the unchanged
--dsh-composer-height write, coalesce mutation-driven height and
conversation-content checks to one per frame, and write backdrop markers only
when they differ. The aggregate caches the [data-dsh-frame] lookup instead of
re-querying per mutation batch.

Controlled Chromium harness, 301 frames over 5 s, mean of 3 runs: body observer
callbacks 1503 -> 902, callback time 237 ms -> 2.9 ms, ScriptDuration
69.6 ms -> 13.6 ms, TaskDuration 984 ms -> 725 ms; LayoutCount unchanged
(natural per-frame paint layout). See
.agents/notes/implemented/bug-fix/2026-09-11-combined-plugin-mutation-cost.md.
2026-09-11 11:56:12 +08:00
zhu1090093659 d6ad39cb91 feat(preset-center): community agent presets through the Workshop
New package @linxin666/dsh-client-ui-preset-center owns the community
preset domain: an inert library at $DSH_HOME/agent-presets/<id>/ (no
discovery root scans it), enable/disable by moving the directory into
$DSH_HOME/.agent-presets/<id>/, loopback-only /api/preset-center/* routes,
a composition profile (plugins, local code files, !!js expressions), the
reserved-id and default-preset guards, and the Presets panel the Workshop
card renders through its new dsh-workshop.panel child slot.

dsh-market gains the preset asset kind (downloads into the library, never
into a discovery root), the install-preset route, the fourth tab, and
records the manifest version in provenance. scripts/market-build publishes
packages/dsh-preset-center/presets/<id>/ as manifest/presets.json plus
assets/presets/<id>/; the worker asset allowlist and the market site gain
the preset kind. Only installed and enabled presets appear under
Settings - Agent presets.

Gates: typecheck, test, docs:check, i18n:check, market:check,
aggregate:check, test:scripts all pass.
2026-09-09 19:07:01 +08:00
zhu1090093659 f4e2dc72af fix(dsh-model-capabilities): close review findings in capability editing
- sync-shared copy counts follow the new mount-once consumer, so pnpm test:scripts is green again
- the archive footer lists only entries whose route is still down; a failed toggle re-reads instead of keeping a stale disabled view
- a route the composition layer also declares is refused with base-profile instead of reporting a disable that did not take effect
- refresh is scoped to llm-pi-ai and the archive namespace, concurrent describes coalesce onto one wire call, and an open draft survives a background refresh while staying fenced at its own revision
- the Agent Note ships as the standard English/Chinese/sidecar triplet with canonical Status and section names
- package AGENTS.md, cordis.patch.yml, and the semantic-attrs contract now state what shipped
2026-09-08 21:42:17 +08:00
zhu1090093659 7c497a135f refactor(perf)!: remove the built-in dsh-perf plugin
BREAKING CHANGE: the dsh-perf package, its aggregate rows, ru dictionary
namespace, CI labeler rule, and issue-template option are removed. The
session-persistence-jsonl tuning patch goes with it; installs fall back
to the stock harness row. The npm badge allowlist keeps the published
name so download totals are unchanged.
2026-09-04 18:36:26 +08:00
zhu1090093659 55d5a1d387 chore(desktop-launcher): remove the desktop launcher plugin entirely
The Electron desktop app (desktop/) takes over the desktop story, so the
plugin retires: package, aggregate rows and regenerated outputs (patch
block, family subpath export, workspace dependency, client-children
entry), settings-bridge allowlist rows, the remote-channel local-only
control plane (three remain), the central ru namespace, i18n-audit and
sync-shared rows, labeler path, publish-prep row, and README entries.
The npm name stays retired-but-published; the desktop runtime seed keeps
pinning the 0.3.13 aggregate until its next bump. Existing generated
desktop icons keep working (they shell out to dsh directly).

Gates: typecheck, test, test:scripts, docs:check, i18n:check,
aggregate:check all green; web-all lib rebuilt launcher-free.

Takes effect after a dsh web restart (bundle-layer change).
2026-09-03 23:22:52 +08:00
zhu1090093659 5902cc4987 refactor(shared): extract the center-column panel-mount core
mount.tsx and board-mount.tsx carried ~100 identical lines of the
single-occupant takeover lifecycle (injection, sibling eviction,
remount resilience, sidebar click-out) that the fix history forced
through twice (#243/#107, c0a98c715, 170b3df31, d73bffc2a). The
lifecycle now lives once in shared/client/panel-mount-core.ts with
two sync-shared generated copies; both wrappers keep their public
exports and only wire the seven per-plugin parameters. Attribute
names stay wrapper-supplied: CSS, skins, and the semantic-attrs
contract pin them. Agent note included.
2026-09-02 16:25:19 +08:00
zhu1090093659 eb2e135686 fix(shared): de-collide css module style tags and lift settings card contrast
The aggregate client bundle keyed every injected stylesheet tag by
basename, so the eight same-named settings-card.module.css copies
suppressed each other and seven family packages rendered their settings
cards with UA defaults under every skin. Style tags now carry the full
repo-relative file id. The shared card chrome lifts 12-13px hint text
from label-tertiary to label-secondary (orca-link measures ~3.4:1 on
tertiary) and points the error roles at state-error-primary, which the
suite defines, instead of the nonexistent label-error token. sync-shared
gains dsh-perf for the card chrome pair only: its settings-form.ts still
runs the pre-0.1.2 per-field generation and must not be overwritten.
Live GUI verified on 127.0.0.1:3080 under the orca-link skin and the
default appearance.
2026-09-02 13:06:53 +08:00
zhu1090093659 4b25dd7714 feat(aggregate): isolate per-plugin boot failures behind the dsh-web-all shell
The DSH loader mounts every patch row as one transactional group: a single
plugin that fails to import or start rolls back the whole family and aborts
'dsh web'. Redefine the fault unit to one plugin.

- scripts/aggregate.mjs emits each family insert row with the aggregate's own
  never-failing shell module as the row name and the real plugin package in
  the row config (config.plugin, original config under config.config);
  dsh-i18n and all external npm rows keep mounting directly
- @linxin666/dsh-web-all main entry is the shell: it imports the real module
  at start time, contains import/shape/activation failures to that entry
  (logged + recorded), and mounts the real plugin as a nested plugin so
  cordis service scoping, lifecycle, and retraction semantics stay intact
- loopback-only GET /api/dsh-web-all/degraded reports the degradation ledger
  for doctor/monitoring consumption
- shared/host/run-guarded.ts (+ synced copies in the four packages with
  in-process HTTP/poll faces) converts fire-and-forget rejections into logged
  errors against the host's installFailLoud whole-process exit
- tests: shell-isolation.spec.ts runs the real installed host boot through
  start-failure / import-failure / no-webServer scenarios plus the control
  case proving today's direct-mount shape still kills the boot

Evidence: pnpm typecheck, pnpm test (22 packages), pnpm docs:check,
pnpm i18n:check, pnpm aggregate:check, pnpm test:scripts (234), and full
pnpm build all pass. Bundle-layer change: needs a dsh web restart.
2026-09-01 20:34:14 +08:00
zhu1090093659 e1d650976d feat(session-archive): add built-in session archive manager plugin
New family plugin dsh-session-archive (@linxin666/dsh-session-archive):
complete session inventory (active, archived, blank, sub-agent,
workspace-less and metadata-incomplete rows), filter/search/sort,
full-result-set multi-select, batch archive/unarchive/physical delete
with family cascade and protected-session skipping, loopback-fenced
routes, and independent default-off auto-archive / auto-delete policies
(archive-time ledger, same-tick guard, catch-up scheduler).

Registered in the dsh-web-all aggregate; ru copy ships centrally in
dsh-i18n; sync-shared grows four copies; root/aggregate devDeps gain the
dsh-workspace and dsh-api-session-controller host-face closure; bilingual
README triplet and Agent Note included.
2026-08-31 19:45:10 +08:00
zhu1090093659 48637c9b6f feat(dsh-usage): add the usage statistics plugin with pet announcement linkage
- new packages/dsh-usage: host service folds session usage into a persistent
  per-day/per-provider ledger and probes every configured provider's balance
  or coding-plan endpoint (DeepSeek, Moonshot, Kimi For Coding, GLM Coding
  Plan, OpenCode Go, MiniMax, OpenRouter, SiliconFlow, ZenMux) through the
  credential seam; keys stay host-side
- first-level settings section (id dsh-usage, order 151, below the Workshop):
  usage tab (today totals, balances, 30-day trend) plus plans tab (quota
  windows with percent and reset), served via loopback-fenced
  /api/dsh-usage/overview|refresh
- dsh-pet grows the in-process pet.announce contract: bounded, validated
  announcements render as a dedicated styled bubble on top of the session
  bubble stack; dsh-usage announces the current provider's balance or
  tightest plan window (bubbleMode: always/change/off)
- wire the family: aggregate membership, sync-shared copies with count gates,
  publish-prep row, semantic-attrs entries, bilingual READMEs and Agent Notes
2026-08-29 13:34:15 +08:00
zhu1090093659 3a4c4b114e chore(sdk): refresh sync-shared copy buckets and stale apiproxy wording
- the copy-count buckets lose the four dsh-aionui-panel entries removed
  with the package (98/39/47)
- the not-exposed settings copy and the shared settings-form comment now
  describe the 0.1.2 exposure model (owning plugin settings domain) instead
  of the deleted host-apiproxy allowlist
2026-08-28 10:18:30 +08:00
zhu1090093659 22b55a8a90 refactor(dsh-perf): carry the better-session card in perf, not a new package
Using better-session is itself session-performance governance, so its
management surface belongs in dsh-perf rather than a standalone family
package. The whole surface moves from the (short-lived) better-session-
manager package into packages/dsh-perf/src/bsm: core pipeline modules,
child-process service with atomic profile writes and store backup, plus
loopback-fenced /api/dsh-perf/better-session routes registered next to
the stats route. The browser half adds a Better Session card to the Web
Plugins group (slot id better-session, order 145) with its own locale
namespace; tsdown gains a companion entry emitting
lib/better-session-import.mjs, which scripts/dsh-better-session.mjs now
imports and which keeps semantic ownership single.

packages/better-session-manager is deleted again before any release;
aggregate reverts to 18 source blocks / 19 rows / 17 deps and publish-
prep inventory back to 18 packages. Tests move into dsh-perf (11 vitest,
node environment per file) and keep passing alongside the package's own
suite (51 total); CLI suite unchanged. Gates green: sync-shared/
aggregate/typecheck/test/test:scripts/docs. Composition verified via
dump-config: no manager row, integration rows still disabled. The host
picks up the moved routes only after the user restarts dsh web.
2026-08-27 20:07:11 +08:00
zhu1090093659 d46fb792ba feat(better-session-manager): opt-in card with automatic legacy migration
The inactive better-session integration was reachable only through a
repository checkout CLI and hand-edited profile YAML, with the storage-
switch warnings living far from the decision. A new public family package
(@linxin666/dsh-client-ui-better-session-manager) ships a Better Session
card under Settings -> Web Plugins: it declares the third-party origin on
the card, shows live posture plus both stores' counters, and gates
enable/disable behind confirm dialogs that carry the full trade-off list.

Enable runs the jsonl-to-sqlite migration first (child process; existing
store auto-backed-up; store bootstraps when absent) and only then writes
the managed override block into the boot profile's patch file - the hot-
reloaded user layer - so failures leave the profile untouched. The card
keeps no settings namespace: the patch layer is the single source of
truth shared by the card and the maintenance CLI, which now loads the
package-built lib/better-session-import.mjs instead of carrying its own
copy of the pipeline.

The importer core moved verbatim into src/core (drop/prune/dense-bridge/
head-cursor semantics mirrored from @morlay/session-rdb@0.0.11); package
vitest suite covers codec, projection, store writes, discovery across
naming eras, runImport e2e and block/posture logic (11 tests), while the
CLI node:test suite keeps argv/profile-write/status wiring coverage (3).
Aggregate grows to 20 rows / 18 deps with the active carrier row; all
better-session integration rows ship disabled as before. Gates: sync-
shared/typecheck/test/test:scripts/aggregate/docs all green; dump-config
confirms the new row activates while integration rows stay disabled.
Loading the new package requires one dsh web restart by the user.
2026-08-27 20:07:11 +08:00
zhu1090093659 598fc333bb feat(web-ui-all): replace dsh-chat-recovery with external better-session
Ingest @morlay/better-session@0.0.10 as a pinned external npm dependency following the better-sidebar/archive-manager pattern (upstream author approval); register its bundle row after the patchFrom blocks so session-persistence rewiring applies after the jsonl tuning row.

Remove packages/dsh-chat-recovery: capability overlap with better-session in-place edit/retry (fork-only approach superseded), including aggregate entries, telemetry sync target, publish-prep row, and test fixtures.

Docs: root README bilingual feature/table/licensing updates; agent note pair records the decision under implemented/architecture.

Gates: aggregate --check, docs:check, test:scripts, sync-shared:check, typecheck, full vitest all pass.
2026-08-27 20:07:11 +08:00
zhu1090093659 73e456f536 refactor(shared): sync vitest.setup.ts to consumers; web-settings re-exports shared vitest config
The test-harness ModuleLoader shim existed as four byte-identical copies
with no drift guard; it is now a sync-shared source with generated
package copies. The web-settings vitest.config duplicated shared's
byte-for-byte and now re-exports it, matching the tsdown preset pattern.
2026-08-27 01:24:34 +08:00
zhu1090093659 e7c74daefa refactor(shared): consolidate the pairing trust fence into shared/host/pair-access.ts
Git-graph, pet, and skill-explorer carried byte-identical fence logic.
The decision now lives in one shared source distributed as generated
sync-shared copies; each package keeps a self-describing thin wrapper.
Canonical tests added under shared/tests; wrapper specs stay as wiring
tests.
2026-08-27 01:20:12 +08:00
zhu1090093659 60e6e75d06 feat(dsh-git-graph): git worktree parallel sessions
Four layers inside the plugin, zero DSH source changes:

- host: managed worktree verbs (worktrees/addWorktree/removeWorktree) over
  the existing workspace gate; all managed worktrees live at
  $DSH_HOME/worktrees/<repo-key>/<name>/ on a new wt/<name> branch; target
  paths are host-constructed (clients never supply them); removal enforces
  canonical-path containment on both sides, rejects dirty trees without
  force, and deletes the wt/ branch only on request
- client: branch popover gains a create-worktree dialog (name + base
  branch) and a worktree manager (dirty-guarded removal with inline force
  confirm); created worktrees register as workspaces and open blank
  sessions
- auto-isolation (settings-gated, default off): runtime-wrapped
  WorkspacesService.startSession redirects a git workspace's New Session
  into a fresh managed worktree (autoBaseline current|default); shape
  probing degrades to official behavior, workspaces under the managed home
  are never re-isolated
- agent tool (settings-gated, default off): opt-in git_worktree
  create/list/remove via ctx.tools.register, scoped by the calling
  session's cwd; create also registers the worktree as a workspace so it
  stays useful under workspace-write sandboxing

Records the deliberate exception to the package's "git stays off the
model-visible surface" rule in the package AGENTS.md and the decision in
an Agent Note.
2026-08-26 19:27:09 +08:00
zhu1090093659 ea49cead81 chore(dsh-web-all): drop dsh-miku-pet from the aggregate and sync tables
Follow-up to the package removal: regenerate the aggregate (18 rows, 17
workspace deps), refresh the pnpm lockfile, drop the miku mount-once and
loopback rows from sync-shared (96 entries / 44 host copies), document the
frames2d + gameplay contract in the dsh-pet README pair, and expect miku
in the repo-checkout registry scan.
2026-08-25 15:36:55 +08:00
涂山苏苏andzhu1090093659 ef0cbe88e4 feat(miku-pet): add Miku pet plugin package with work/shop/stats gameplay (#1031)
* feat(miku-pet): add Miku pet plugin package with work/shop/stats gameplay

* fix(miku-pet): address maintainer review (mount-once, path guards, config preservation, frame timers, compliance)

* chore(miku-pet): re-sync mount-once and aggregate after dev rebase

* test(sync-shared): bump copy counts after adding dsh-miku-pet mount-once

* feat(miku-pet): sleep/affection touch gameplay, lottery shop, menu revamp

- sleep animation (fall-asleep frames then resting loop) + energy restore
- affection stat (0-500): idle decay 300s -1, zone touch outcomes with 3s anims
- passive coin income +1/min, click mood +0~3
- shop: game coin exchange item + lucky lottery (10 game coins, all stats +10,
  instant prize draw with dedicated result popup)
- light anime hover menu + play-guide page (rules line-by-line, lottery odds/EV)
- robustness: frame-chain watchdog anti-hotloop, drag-end position corner fix
- new thumb assets: sleep/happy/shy/flirty/angry, shop4/6; README sync

* chore(miku-pet): refresh root lockfile for aggregate dependency

* feat(miku-pet): add host write fence, character notice, and GUI evidence (PR #1031)

---------

Co-authored-by: zhu1090093659 <1090093659@qq.com>
2026-08-25 13:39:18 +08:00
zhu1090093659 bfa4a6e788 feat(dsh-web): auto-migrate legacy aggregate during upgrade
Dual-publish the final @linxin666/dsh-web-ui-all for the two-release transition window, then stop automatically. Plugin-manager recognizes the legacy aggregate and performs a transactional CLI migration. Doctor introduces autoMigrate (default true) and migrates before DSH launch, preserving bundle order and verifying --dump-config before boot. Add compatibility audit gates, Agent Notes, and isolation evidence.
2026-08-24 15:24:43 +08:00
zhu1090093659 c055491cb3 feat(telemetry): version and channel dimensions, skin inventory, all-package wiring, bot filtering 2026-08-24 13:23:10 +08:00
zhu1090093659 2f56ff231f feat(telemetry): anonymous install heartbeats and market UV/PV summary 2026-08-24 13:23:10 +08:00
zhu1090093659 9c59e27600 refactor(task-board): migrate JSON responses onto shared writeJson 2026-08-23 20:07:30 +08:00
zhu1090093659 ef3deddc6d refactor(shared): add unified http json body/response helpers 2026-08-23 18:06:40 +08:00
zhu1090093659 626d1fac68 chore(shared): drop the retired market tab seat machine
The seat machine was removed with the DSH Market hub; delete its shared test and drop the community-plugins consumer from the settings trio manifest (the package no longer ships a client half).
2026-08-23 13:27:53 +08:00
zhu1090093659 24c33b4c16 feat(market): reduce DSH Market to the store; category cards back to first-level sections
The four-tab market hub is gone: dsh-market registers only the store section; Skin Center and Pet register first-level sections (installed-only); the community plugin card is retired and its package becomes the community.json data source (inert cordis row keeps profiles and the aggregate resolving). The shared market tab seat machine and its sync copies are deleted; skin catalog now lists shipped builtins plus user dirs.
2026-08-23 13:20:42 +08:00
zhu1090093659 6c7abfab68 docs(market): record DSH Market hub, two-seat tab contract and default-skin plan
- READMEs for market, skin-center, pet and community-plugins describe the
  single DSH Market section with category tabs and the standalone fallback;
  skin-center documents the on-demand skin plan (package ships blue-fantasy
  only, market installs into /Users/zcl/.dsh/skins, default activation and the
  upgrade fallback)
- semantic-attrs contract: dsh-market row and updated anchors for the
  category cards (hub tabs vs standalone sections)
- root AGENTS.md layout and docs/plugins|publish-prep updated to the same
  facts
- rebuild market and skin-center lib bundles; shared market-tab seat gains
  the slots/settings devDeps for its own typecheck; sync-shared test covers
  the new copy
2026-08-23 13:03:56 +08:00
zhu1090093659 b9f43e9df7 test(scripts): expect nine settings-trio consumers after adding dsh-market 2026-08-23 13:03:33 +08:00
EDDYCRAZY-CC b6fea32d4a refactor: remove retired dsh-skins package and dsh-aionui-panel host archive 2026-08-22 22:47:49 +08:00
EDDYCRAZY-CC cf967e5fd7 refactor: remove dead functions, unused variables, and orphaned probe file 2026-08-22 22:32:58 +08:00
Solitude 996add4a1e fix(scripts): sync copy-count assertions with doctor consumer (#935) 2026-08-22 07:30:14 +08:00
zhu1090093659 1dd12c266d chore(doctor): declare DSH runtime floor and align shared copy contract (#754) 2026-08-22 07:12:00 +08:00
Solitude 500e89a544 fix(ssh,desktop-launcher,settings): honor DSH_HOME for data paths (#802) (#894) 2026-08-21 18:50:36 +08:00
thinkmoonandCursor b749bebd77 merge(main): keep pet pairing fence with decoration routes and desktop-launcher
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-20 07:02:10 +08:00