dsh-m 0.9.25 → 0.9.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,12 @@ The full release history of dsh-m, maintained bilingually: **Chinese first, Engl
8
8
 
9
9
  ## 中文
10
10
 
11
+ ### 0.9.26 变更:跨区搜索精选稳定前置——摘要行计数与首页所见一致
12
+
13
+ - **问题(装机实测 2026-10-03)**:搜索「sidebar」摘要行报「⭐ 精选 3 · 社区 315」,首页精选段只见 1 条。非重复计算——`sourceCounts` 不读分类计数(`alsoCategories` 无涉),3 条为真实精选命中;错位根因是摘要行报全局命中数,而相关性排序叠加社区区默认 downloads 降序 tie-break 把弱命中精选压进后页。
14
+ - **修复**:`listMarket` 新增 `curatedFirst`——`source='all'` 且 query 非空时精选命中**稳定前置**(稳定分区,分区内相关序不变,社区命中随后);仅 host-api GUI 通道携带,tools/CLI 不传,搜索排序三端同序不变;单分区/浏览态天然无效。跨页精选段头悬空与计数错位随之消失(精选命中 ≤ 页大小时全数落在首页段内)。
15
+ - **验证**:新增测试 ⑮(无 flag 保持交织相关序 / 带 flag 精选前置 / 空 query 与单分区无效);全量 1025 pass / 0 fail。
16
+
11
17
  ### 0.9.25 变更:跨区搜索——浏览分区、搜索全局(社区 + 精选一并命中)
12
18
 
13
19
  - **跨区搜索**:任一分区(社区/精选)的搜索框升级为全局——`query` 非空时底层查询切 `source=all`,两分区条目统一相关性排序;清空关键词回到本区浏览态。分区制浏览(ADR-0004)与 `dshm_search`/CLI 三端同序不动;服务端唯一增量是 `MarketResult.sourceCounts` 分桶计数。
@@ -263,6 +269,12 @@ The full release history of dsh-m, maintained bilingually: **Chinese first, Engl
263
269
 
264
270
  ## English
265
271
 
272
+ ### Changed in 0.9.26 — curated hits first in cross-zone search: summary counts now match page one
273
+
274
+ - **Problem (observed on install, 2026-10-03)**: searching "sidebar" showed "⭐ Curated 3 · Community 315" but only one curated card on the first page. Not double counting — `sourceCounts` never reads category counts (`alsoCategories` is unrelated) and all 3 were genuine curated hits. The mismatch: the summary line reports global hit counts while the relevance ranking plus the community zone's default downloads-desc tie-break pushed weakly-matching curated entries onto later pages.
275
+ - **Fix**: `listMarket` gains `curatedFirst` — with `source='all'` and a non-empty query, curated hits are stably moved to the front (stable partition; relevance order preserved within each segment, community hits follow). Carried only by the host-api GUI channel — tools/CLI don't pass it, so the shared search ordering across the three surfaces is unchanged; single-zone and browse states are naturally unaffected. Dangling cross-page section headers and the count mismatch disappear (with curated hits ≤ page size, all of them land in the first-page section).
276
+ - **Verification**: new test ⑮ (no flag keeps the interleaved relevance order / flag moves curated first / empty query and single-zone are no-ops); full suite 1025 pass / 0 fail.
277
+
266
278
  ### Changed in 0.9.25 — cross-zone search: browsing stays zoned, searching goes global (community + curated together)
267
279
 
268
280
  - **Cross-zone search**: either zone's (Community/Curated) search box now searches globally — with a non-empty `query` the underlying query switches to `source=all` and both zones' entries are ranked by the shared relevance pipeline; clearing the keyword returns to the zone's own browse state. The zoned browsing model (ADR-0004) and the `dshm_search`/CLI shared ordering are untouched; the only server-side addition is the `MarketResult.sourceCounts` bucket count.
package/docs/DESIGN.md CHANGED
@@ -87,7 +87,7 @@
87
87
  - 排序:`downloads | stars | added × asc/desc`,默认 `downloads-desc`;**无下载量(github-only)≠ 0 下载**(永远排在有真实计数条目之后,彼此按 stars 排);时间窗过滤明确不做(`added` 排序覆盖「找最新」诉求)。
88
88
  - 卡片 byline:`owner / downloads / ★stars`(旁路数据已透传,Tooltip 给精确数);`deprecated` 徽章 + 详情内 replacement 替代链接(适配层补透传原生字段)。
89
89
  - 分页:页码窗口化(`1 … n-1 n n+1 … total`,≤7 页全显)+ 页大小 24/48/96 + 筛选变化重置页 1 + 翻页回顶;仅 prev/next 的旧分页退役。
90
- - 搜索:相关性加权管线——NFKC 归一化 + 中西文边界插空格 + 字段权重(name/npm > owner > 描述 > 分类)+ 命中类型加分 + 按条目缓存归一化结果;输入 250ms debounce + IME composition 全程处理 + draft/已提交 query 分离。**0.9.25 起搜索跨区全局**(两分区搜索框同语义):摘要行报两分区精确命中数(`sourceCounts`),结果页内按精选段置顶分组,分类 chips 搜索态隐藏、「筛选」按钮随摘要行保留(页大小组)。
90
+ - 搜索:相关性加权管线——NFKC 归一化 + 中西文边界插空格 + 字段权重(name/npm > owner > 描述 > 分类)+ 命中类型加分 + 按条目缓存归一化结果;输入 250ms debounce + IME composition 全程处理 + draft/已提交 query 分离。**0.9.25 起搜索跨区全局**(两分区搜索框同语义):摘要行报两分区精确命中数(`sourceCounts`),结果页内按精选段置顶分组,分类 chips 搜索态隐藏、「筛选」按钮随摘要行保留(页大小组)。**0.9.26 补充**:GUI 跨区搜索通道精选命中稳定前置(`curatedFirst`,分区内相关序不变;tools/CLI 不传,三端同序不变)——摘要行全局计数与首页所见一致,弱命中精选不被 downloads tie-break 埋进后页。
91
91
  - 描述 5 行钳制(真实溢出才显示展开钮);**数据层双语**——描述按 UI 语言取 zh/en(数据现成),UI 完整双语字典列 backlog。
92
92
  - **详情 = Modal 且为卡片超集**(「detail 显示少于摘要就是倒退」):byline / 分类 / 收录日期 / 下载量窗口三要素(计数 + 窗口 + 核对时间)/ 描述全文 / 截图灯箱(←→/Esc、**禁自动轮播**)/ 能力披露 + 红线(**默认收起**)/ 安装命令折叠行(0.9.14 起按上下文显隐:desktop 上下文与已安装条目整行隐藏——命令两来源恒为 `--profile web` 语义,desktop 装机走弹窗内安装按钮)/ deprecated 替代链接;精选条目超集另加 verified 与 tags。**安装确认走 Modal**。安装信息就地显示(0.9.15):进行中进度行与终态结果行挂 Modal 内、底层同源进度行让位——展示派生自全局操作记录,§2.6「状态不挂卡片」所有权模型不变。卡片瘦身:能力披露、截图、安装命令全部迁出卡片(Q44 精神「只在详情层、默认收起」不变,载体升级)。
93
93
  - **全局操作记录**:每个变更操作一条 record(`queued / running / input=冲突待决 / done / warned / failed`),**状态不挂卡片**——翻页、搜索、切 tab 不丢;**localStorage 持久化队列**,宿主重载恢复时逐条校验「此刻仍成立才执行,否则报告」;覆盖安装、升级、卸载、开关。已装侧跟随一致化:「全部更新 (N)」批量入口 + tab 更新红点 + 卡片视觉与发现侧同体系;组管理、个人备注列 backlog。
@@ -366,6 +366,9 @@ export function createApiDispatcher(ctx) {
366
366
  category,
367
367
  source,
368
368
  sort,
369
+ // 0.9.26:GUI 跨区搜索精选稳定前置(listMarket 内部仅在 source='all' 且 query 非空时生效)。
370
+ // 本参数仅 GUI 通道携带——tools/CLI 走各自调用面不传,搜索排序三端同序不变。
371
+ curatedFirst: true,
369
372
  offset,
370
373
  limit,
371
374
  force: boolArg(body.force),
@@ -503,12 +503,16 @@ export async function listMarket(cfg = {}, opts = {}, deps = {}) {
503
503
  });
504
504
  // 排序:显式 sort 先行;query 命中时相关性优先(稳定 tie-break 回到既有序——merged 现序或用户排序)
505
505
  const afterSort = opts.sort ? sortEntries(filtered, opts.sort) : filtered;
506
- const ordered = terms.length > 0
506
+ const ranked = terms.length > 0
507
507
  ? afterSort
508
508
  .map((entry, idx) => ({ entry, score: relevanceScore(entry, terms), idx }))
509
509
  .sort((a, b) => b.score - a.score || a.idx - b.idx)
510
510
  .map((s) => s.entry)
511
511
  : afterSort;
512
+ // curatedFirst 稳定前置(0.9.26):见 MarketQuery 注释——稳定分区不破坏分区内相关序
513
+ const ordered = opts.curatedFirst === true && source === 'all' && terms.length > 0
514
+ ? [...ranked.filter((entry) => !isCommunityEntry(entry)), ...ranked.filter(isCommunityEntry)]
515
+ : ranked;
512
516
  const total = ordered.length;
513
517
  // sourceCounts 分桶(0.9.25 跨区搜索摘要行):filtered(分区 ∩ query ∩ category)计数,与排序/分页无关
514
518
  const communityHitCount = filtered.reduce((n, entry) => n + (isCommunityEntry(entry) ? 1 : 0), 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-m",
3
- "version": "0.9.25",
3
+ "version": "0.9.26",
4
4
  "description": "可自定义收录清单的 DSH 插件市场:收录、安装、卸载、升级一站完成,附 agent 工具与 dshm CLI。",
5
5
  "license": "MIT",
6
6
  "type": "module",