Skip to content

fix: mount the Advisor card on the Plugins page (dsh 0.1.6-alpha.2) - #87

Open
q1692306918 wants to merge 2 commits into
omdsh-dev:mainfrom
q1692306918:fix/dsh-0.1.6-alpha.2
Open

q1692306918 wants to merge 2 commits into
omdsh-dev:mainfrom
q1692306918:fix/dsh-0.1.6-alpha.2

Conversation

@q1692306918

Copy link
Copy Markdown

中文摘要:0.1.6-alpha.2 的 web shell 不再声明 settings.plugin.item 这个 keyed slot
ui-plugin-configui-plugin-manager)。ctx.slots.inject 是「等声明」语义,槽位
永不声明 → 回调永不执行 → 卡片静默消失(两侧都不报错,宿主半仍是 active)。本 PR
把卡片迁到宿主真正声明的 plugins.bundle.config(key = 组合包包名 dsh-advisor),
并适配同一版本线的第二个 seam:agent/created 变成 serial 事件(载荷新增必填
source,监听器在 creation 解析前被 await)。

Root cause

dsh-advisor@0.4.1 registers its single UI contribution into the
settings.plugin.item keyed slot (src/client/index.ts). That slot does not
exist on the 0.1.6-alpha.2 line:

  • cordis_inspect_query (client Slots.listSubTree, root settings.plugin.item)
    available: false;
  • no shipped package in the 0.1.6-alpha.2 install references the name (the only
    hit is a stale doc comment in dsh-client-ui-settings-models' .d.ts);
  • the shell's own slot catalog (dsh-cordis-client-runner, generated from the
    client packages' slot-contract.ts) lists plugins.item,
    plugins.bundle.config and plugins.row.config instead, declared by
    dsh-client-ui-plugin-manager — the package that replaced
    dsh-client-ui-plugin-config.

ctx.slots.inject(key, cb) runs the callback when the declaration lands, so a
registration into a seat nobody declares is a silent no-op: the host half
stays active and healthy while the card never mounts, and nothing throws on
either side. That is why the plugin looked "installed but invisible".

The fix

  • Seat migration — register into plugins.bundle.config, keyed by the
    bundle package name (dsh-advisor; the page renders the entry with
    entryKey = pkg.name). That seat is view: 'page'-only, so the
    self-chromed card keeps its shape; plugins.row.config
    (dsh-advisor#advisor) was the alternative, but it also owes a
    view: 'summary' one-liner and this bundle's card edits the whole
    bundle's advisor configuration.
  • Type contract — the type-only SlotMap merge now comes from
    @deepseek-ai/dsh-client-ui-plugin-manager/client, and the peer/dsh.client.inject
    package moves with it. AdvisorCardProps becomes
    PropsRuntime<'plugins.bundle.config'>.
  • Markup — the card root becomes a <div>: the owner renders a
    <section>, not the old card <ul> (list-style: none dropped with it).
  • Second seam: agent/created is now serial — the payload requires
    source, and listeners are awaited before creation resolves; a throw
    fails creation. The handler returns undefined per the new listener
    contract and now contains its own failures (logged, never propagated): an
    advisory-only plugin must not be able to fail the primary agent's startup.
  • Peer line — every @deepseek-ai/dsh-* peer bumped to ^0.1.6-alpha.2,
    minimumReleaseAgeExclude synced to the re-resolved lockfile, README badges
    updated. pnpm-workspace.yaml's ui-primitives metadata repair gains
    diff + simple-icons: that package's 0.1.6-alpha.2 build still moves its
    runtime modules to devDependencies, and without the two new modules the
    Vitest card suite fails with Failed to resolve import "diff".

Verification

  • pnpm typecheck → 0; pnpm build → 0 (lib/client.js emitted);
  • pnpm vitest run tests/advisor-card.spec.tsx tests/client-build.test.ts tests/integration.test.ts tests/settings-live.test.ts72 passed;
  • full pnpm test → 371 passed, 10 failed — all 10 in
    tests/prepare-release.test.ts, which installs a #!/bin/sh git shim into
    the fixture PATH. On Windows an extensionless POSIX script is not
    executable, so the shim never intercepts and the real git answers; the
    file and scripts/prepare-release.mjs are untouched by this PR (fails at
    HEAD too on this host, passes on the Linux CI runner);
  • live, against a running 0.1.6-alpha.2 web profile with the built package
    linked in: client Slots.listSubTree root plugins.bundle.config reports
    available: true with occupants: [{ key: "dsh-advisor", active: true }].

Regression pins

  • tests/client-build.test.ts asserts the emitted bundle carries
    plugins.bundle.config and not settings.plugin.item, so the next seat
    move fails the build gate instead of disappearing at runtime.
  • tests/advisor-card.spec.tsx pins the new keyed seat and key.

Notes for review

  • The host half of an already-running dsh web needs a restart to pick up the
    new module generation; the client half is served fresh (verified live above).
  • docs/screenshots/advisor-settings-card.webp still shows the old settings
    page — worth re-capturing on the new surface before merging.
  • CHANGELOG.md is generated from git log at release prep, so nothing was
    written there.

Bump every @deepseek-ai/dsh-* peer to the 0.1.6-alpha.2 line and move the
client-half declaration's owner package: ui-settings-plugins (which declared
the 0.1.5-rc.2 `settings.plugin.item` card slot) -> ui-plugin-manager (the
Plugins page, which declares `plugins.bundle.config` / `plugins.row.config`).

Sync minimumReleaseAgeExclude to the re-resolved lockfile, and extend the
ui-primitives packageExtensions repair: that package's 0.1.6-alpha.2 build
still moves its runtime modules to devDependencies, and its closure now also
needs `diff` + `simple-icons` (without them the Vitest card suite fails to
resolve the import).
The 0.1.6-alpha.2 shell no longer declares the `settings.plugin.item` keyed
slot (ui-plugin-config -> ui-plugin-manager). `ctx.slots.inject` waits for a
declaration that never lands, so the card's registration became a SILENT
no-op: the host half stayed active and healthy while the web card simply never
mounted, with no error on either side.

Register into the seat the host actually declares - `plugins.bundle.config`,
keyed by the bundle package name (`dsh-advisor`), rendered on the bundle's own
page in the Plugins panel. That seat is `view: 'page'`-only, so the
self-chromed card keeps its shape; its root becomes a `<div>` (the owner
renders a `<section>`, not the old card `<ul>`).

Adapt to the line's second seam: `agent/created` is now a SERIAL event whose
listeners are awaited before creation resolves, and whose payload carries a
required `source`. The handler returns `undefined` per the new listener
contract and contains its own failures - an advisory-only plugin must never be
able to fail the primary agent's creation.

Regression pins: the emitted bundle must carry `plugins.bundle.config` and
must not carry the removed `settings.plugin.item`; the card spec pins the new
keyed seat.
@btspoony

Copy link
Copy Markdown
Member

Thank you for the Contribution!!! but generally I prefer to wait for the RC to be merged into main and releasing a new version (to prevent the case where someone installs it directly via git, and might end up with an old RC version that doesn't work). I will merge this PR after the RC is released, then release a new version.

@q1692306918

q1692306918 commented Sep 20, 2026 via email

Copy link
Copy Markdown
Author

@btspoony btspoony left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Verdict: needs fixes · Confidence 65%

Findings Count
🔴 must-fix 0
🟠 should-fix 1
🔵 nit 0
❓ unverified 2

📋 Review

What this PR does: migrates the Advisor card registration from the removed settings.plugin.item seat to plugins.bundle.config keyed by the bundle package name, adapts the now-serial agent/created seam (required payload source, awaited listeners, a throw fails creation), and bumps the dsh peer line to ^0.1.6-alpha.2 (lockfile, release-age exclusions, the dsh-client-ui-primitives workspace repair gaining diff + simple-icons, README badges, docs, two regression pins).

Findings

🟠 README Quick Start still routes web users to the old Settings page

  • Evidence: README.md:23 and README.zh.md:23 — the dsh plugin --profile web add dsh-advisor comment still reads # web profile (Settings → Advisor card) / # web profile(设置 → Advisor 卡片), while line 16 of the same two files (changed by this PR) now documents sidebar → Plugins → dsh-advisor → Advisor card.
  • Impact: the copy-paste Quick Start instruction contradicts the mount surface this PR exists to fix; a user following it is sent to the page where the card no longer renders.
  • Merge class: should-fix
  • Confidence: HIGH
  • Fix sketch: update both Quick Start comments to the Plugins route (one line each).

Linked-issue AC

none

✅ Verified

  • Seat migration: plugins.bundle.config is declared by dsh-client-ui-plugin-manager (packages/client/ui-plugin-manager/src/client/slot-contract.ts:21-45 at dsh 0.1.6-alpha.2), is bundle-name-keyed, is view: 'page'-only, and is rendered by the owner inside a <section> (PluginManagerPage.tsx:466-471); settings.plugin.item is absent from that revision's settings slot contract and client slot catalog.
  • Type and peer move: the type-only SlotMap merge and the dsh.client.inject package both move to @deepseek-ai/dsh-client-ui-plugin-manager/client, which exists and re-exports the owner type; PropsRuntime<'plugins.bundle.config'> matches the host owner share ({ view }).
  • Markup: the card root is now a <div> under the owner's <section>; dropping list-style: none matches the removed <li> root, and no selector mismatch remains.
  • agent/created seam: serial, awaited and failure-propagating in 0.1.6-alpha.2 (packages/core/agent/src/runtime-types.ts:248-261, src/index.ts:524-551); the new handler is synchronous, contains its own failures, and explicitly returns undefined, so an advisory-only plugin cannot veto primary agent creation.
  • Regression pins are non-tautological: tests/client-build.test.ts:174-187 asserts the emitted registration carries plugins.bundle.config + dsh-advisor and excludes settings.plugin.item (it would fail on the pre-PR shape); tests/advisor-card.spec.tsx:333-369 requires the bundle seat entry and key.
  • Packaging: all 20 @deepseek-ai/dsh-* peers use ^0.1.6-alpha.2 with no exception and both README badges follow; minimumReleaseAgeExclude covers exactly the 59 @deepseek-ai/* names resolved in the lockfile, with no third-party exemption and minimumReleaseAge unchanged.
  • Supply chain: the only new third-party lock records are diff@9.0.0 and simple-icons@16.31.0, both integrity-pinned; the packageExtensions repair touches only the local workspace manifest of dsh-client-ui-primitives (not the published plugin manifest and not a consumer install); no new registry host, lifecycle script, requiresBuild surface, CI file, or executable was added.
  • Diff hygiene: the 18 changed files match the PR body's inventory — no unmentioned file, hidden payload, or dynamic evaluation.
  • ❓ Registry-side provenance and publication ages of the new dependency records were not verified (static review; no network install).
  • ❓ This PR's runtime verification claims (live card mount against a running 0.1.6-alpha.2 web profile; the targeted test subset; the 10 tests/prepare-release.test.ts failures) were not reproduced here — the review is static by request.

🗑️ Considered & rejected

  • minimumReleaseAgeExclude "diverges from the re-resolved lockfile": rejected — recomputed; the exemption list's package-name set is exactly the lockfile's 59 names. 34 entries carry the new 0.1.6-alpha.2 coordinate while the lock still resolves those names at 0.1.5-rc.2 (transitive pins), which is the intended line-scoped exemption, not a policy hole.
  • "72 passed" unsupported: rejected — the four test files contain exactly 72 it/test definitions at this head (34 + 8 + 19 + 11) with no skip, only or .each, so the stated count matches the checked-in selection.
  • Knowledge docs still prescribe settings.plugin.item: real staleness, but .mstar/knowledge/ is maintainer-owned process SSOT refreshed at iteration close — handled as a maintainer follow-up (§ Plan to fix), not as a contributor action.
  • Historical provenance comment naming ui-plugin-config: rejected — a deliberately pinned historical citation; that package's absence from 0.1.6-alpha.2 is expected.
  • Stale banner screenshot: the image contains only the card with no page chrome, so it cannot be shown stale from the file itself; the alt text was updated by this PR. Not filed.

🛠️ Plan to fix

Expand fix plan
1. README.md:23 + README.zh.md:23 — change the `dsh plugin --profile web add dsh-advisor`
   comment to the Plugins route, worded consistently with line 16 of both files.
   Verify: no "Settings → Advisor" / "设置 → Advisor" route text remains in
   README.md / README.zh.md / docs/*.

Maintainer-side (not a contributor requirement):
2. Refresh .mstar/knowledge/architecture-patterns/dsh-plugin-config-card-surface.md and the
   knowledge index line to the `plugins.bundle.config` bundle-name seat, marking the
   `settings.plugin.item` recipe superseded (knowledge maintenance), so the next card change
   cannot re-register into the removed seat.
3. Optional: recapture docs/screenshots/advisor-settings-card.webp on the Plugins page for the
   next release notes.

Comment thread README.md
@btspoony

Copy link
Copy Markdown
Member

Correction to the review's Considered & rejected entry on minimumReleaseAgeExclude (the figures in that entry were partly miscomputed; the disposition is unchanged).

Exact recomputation at this head:

  • The exemption list holds 59 entries: 5 non-dsh@deepseek-ai/cordis@4.0.2, @deepseek-ai/cordis-plugin-include@1.0.7, @deepseek-ai/cordis-plugin-loader@1.0.3, @deepseek-ai/cosmokit@1.8.3, @deepseek-ai/schemastery@3.18.2, each matching a lock entry exactly — plus 54 @deepseek-ai/dsh-* entries all written at 0.1.6-alpha.2.
  • Of those 54, 25 match a lock entry exactly; 29 name a coordinate the lock currently resolves at 0.1.5-rc.2 (transitive pins whose dependents' ranges have not moved to the new line).
  • 30 of the 59 entries (25 + 5) match lock coordinates exactly.
  • The package-name set still equals the lockfile's 59 @deepseek-ai/* names with no orphan in either direction, which is what keeps the rejection reasoning intact; the earlier "34" count incorrectly folded in the five non-dsh exemptions.

The exemption table's own comment (pnpm-workspace.yaml, "Keep versions in sync with the lockfile when bumping dsh peers") is inert today (minimumReleaseAge: 0, no release-age check), so this remains a convention/wording nuance rather than a policy hole — worth a maintainer decision (clarify whether the convention is name-set equality or exact coordinate equality), not a merge blocker.

@btspoony

Copy link
Copy Markdown
Member

Would you like the advisor's provider and model to be per-session? If there's no plan for that on main, I'll just handle it locally on my end — I wanted to check with you first so I don't submit a change that wouldn't be useful. At 2026-09-20 15:13:38, "BT.Wood(Tang Bo Hao)" @.> wrote: btspoony left a comment (omdsh-dev/dsh-advisor#87) Thank you for the Contribution!!! but generally I prefer to wait for the RC to be merged into main and releasing a new version (to prevent the case where someone installs it directly via git, and might end up with an old RC version that doesn't work). I will merge this PR after the RC is released, then release a new version. — Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today! You are receiving this because you authored the thread.Message ID: @.>

This PR will be merged after the release of the DSH RC version.
And Issue created: #88 for your proposal, also I will implement it after new dsh RC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants