dsh-structured 0.7.4 → 0.8.2

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
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.2 — 2026-10-22
4
+
5
+ - 视觉层从“始终开启”改为 profile 级 `visual` 配置(`Config` + `.volatile()`,默认 true);通过 DSH 插件设置页(bundle 详情表单)切换,不再写共享的 `state.json`。
6
+ - `/structured on|off` 保持原义:只控制按会话的提示词注入;视觉层由 `visual` 控制,`/structured status` 会显示两者状态。
7
+ - client 通过 `configForms.get('dsh-structured')` 读取 `visual` 并启用/停用视觉层;`configForms` 不可用时保持默认开启,不阻断回复。
8
+ - 严格卡片识别:只认完整标签(结论/总结/答案、判断/决策、指标/数据、风险/注意/警告、下一步/行动/待办、验收/通过/完成、重点/关键);前缀/复合词不染色;普通引用不再自动 lead;statement 仅第一块;GenUI 跳过。
9
+ - 新增 `@deepseek-ai/schemastery` peer/dev 依赖;`desktop-check` 允许宿主 schemastery import 并检查 `Config` 导出;版本 0.8.2。
10
+
11
+ ## 0.8.1 — 2026-10-22
12
+
13
+ - 规则文本从“500 字硬上限”改为清晰度约束:标题即结论、按信息类型选组件、一段一主题、证据优先、短答不套卡、长答不设硬性篇幅上限。
14
+ - 表格优先 ≤5 行;信息确实多时用 `dsh-ui` 大表或拆表,不硬砍内容;不为了格式加内容,也不为了字数删信息。
15
+ - 同步 README、`docs/METRICS.md`、`docs/CARD-SYSTEM.md` 与测试断言;无运行时截断、无字数统计、无长度预算;不改 client/注入通道。
16
+
17
+ ## Unreleased
18
+
19
+ - 新增 `docs/MAINTENANCE.md`(每日巡检手册)与 `docs/MAINTENANCE-LOG.md`(巡检记录);两者不进 npm 包(`files` 增加 `!docs/MAINTENANCE*.md`,打包仍为 34 文件)。
20
+
3
21
  ## 0.7.4 — 2026-10-21
4
22
 
5
23
  - 发布准备:加入 `assets/screenshots/`(4 张)、`screenshots.json`、README Screenshots 与 npm/市场/GitHub Release 安装说明。
package/README.md CHANGED
@@ -81,7 +81,7 @@ pnpm add $tgz
81
81
 
82
82
  ### 兼容性门禁
83
83
 
84
- 本包不声明 `@deepseek-ai/*` peerDependencies:插件只使用 host service,不直接 import 官方包。`engines.dsh` 与 `dsh.compatibility.dshReleases` 是 advisory;本机 `evaluatePluginCompatibility` 只读 peer,因此版本门禁不生效(P2 风险)。实测 DSH CLI `0.1.7-rc.2` 与 desktop `0.2.1-rc.2`。
84
+ 本包声明 `@deepseek-ai/schemastery` peer:`Config`(visual/defaultEnabled/tailReminder/includeSubagents/genui)用它生成设置表单;这是 host 提供的服务,不是门禁。真正门禁是 `engines.dsh`(`>=0.1.7-rc.2 <0.3.0-0`),`dsh-app-boot` 在有 `engines.dsh` 时读取它;`dsh.compatibility.dshReleases` 是 advisory。实测 DSH CLI `0.1.7-rc.2` 与 desktop `0.2.1-rc.2`。
85
85
 
86
86
  ## 使用
87
87
 
@@ -94,8 +94,9 @@ pnpm add $tgz
94
94
 
95
95
  - 开关按会话独立,状态落在 `$DSH_HOME/dsh-structured/state.json`(tmp + rename 原子写)。
96
96
  - 新会话默认开启;`defaultEnabled: false` 可改默认值(见配置)。
97
+ - 视觉层由插件设置 `visual` 控制(默认开启),不写 `state.json`;`/structured on|off` 只控制提示词注入,不影响视觉层。
97
98
  - 自定义规则:写 `$DSH_HOME/dsh-structured/style.md`,**非空即整份覆盖**内置文本,保存后下一轮生效;文件为空或删除时回落内置。
98
- - 内置文本与 `~/.dsh/AGENTS.md` 第 7 节同源:首句结论、组件化正文、禁过程叙事与复述、结构化不等于变长、500 字上限。
99
+ - 内置文本与 `~/.dsh/AGENTS.md` 第 7 节同源:首句结论、组件化正文、一段一主题、禁过程叙事与复述、证据优先、短答不套卡;清晰优先,不设硬性篇幅上限。
99
100
 
100
101
  ### 视觉层(desktop 主目标;web 兼容)
101
102
 
@@ -103,7 +104,7 @@ pnpm add $tgz
103
104
 
104
105
  视觉方向只做一套:**Linear 的秩序 + Notion 的卡片 + Stripe 的信息密度 + Vercel AI Elements 的回复结构**,见 [`docs/DESIGN-REFERENCES.md`](docs/DESIGN-REFERENCES.md)。卡片用图标方块 + 13px 标签 + 淡色表面;状态只在 68px 状态列着色,不再整行 pastel;表格结论用强调左规线。不做主题菜单。
105
106
 
106
- 设计与分阶段计划见 [`docs/VISUAL-PLAN.md`](docs/VISUAL-PLAN.md),视觉热点/层级诊断见 [`docs/VISUAL-CRITIQUE.md`](docs/VISUAL-CRITIQUE.md),卡片类型与热点预算见 [`docs/CARD-SYSTEM.md`](docs/CARD-SYSTEM.md)。视觉层默认开启,**只提供一套「工程蓝图」方案,不做主题选择**;`/structured on|off` 是唯一开关。
107
+ 设计与分阶段计划见 [`docs/VISUAL-PLAN.md`](docs/VISUAL-PLAN.md),视觉热点/层级诊断见 [`docs/VISUAL-CRITIQUE.md`](docs/VISUAL-CRITIQUE.md),卡片类型与热点预算见 [`docs/CARD-SYSTEM.md`](docs/CARD-SYSTEM.md)。视觉层由插件设置 `visual` 控制(默认开启);`/structured on|off` 只控制提示词注入。仍只提供一套「工程蓝图」视觉,不做主题选择。
107
108
 
108
109
  Phase 2 已落地 2.1–2.4:卡片类型(结论/判断/指标/风险/下一步/验收/重点)、`data-dsh-structured-card-type` 归属标记、GenUI 软联动(检测到才追加 `dsh-ui` 路由,未检测走纯 markdown fallback,不硬依赖)。
109
110
 
@@ -130,8 +131,11 @@ Phase 2 已落地 2.1–2.4:卡片类型(结论/判断/指标/风险/下一
130
131
  tailReminder: true # system prompt 末尾追加一句提醒
131
132
  includeSubagents: false # 子代理会话不注入(它的产出不直接面向用户)
132
133
  genui: auto # auto | on | off;auto 检测到 GenUI 才追加 dsh-ui 路由
134
+ visual: true # 客户端视觉层;由插件设置页切换,不写 state.json
133
135
  ```
134
136
 
137
+ `visual`、`defaultEnabled`、`tailReminder`、`includeSubagents`、`genui` 都是 `.volatile()` 配置,插件设置页(bundle 详情表单)可编辑;写入走 active profile 的 Cordis patch,home patch / CLI overlay 优先。`/structured on|off` 只影响 `state.json` 里的按会话提示词开关。
138
+
135
139
  ## 验证注入生效
136
140
 
137
141
  会话日志是 `$DSH_HOME/sessions/<cwd-group>/<session-id>/session.v4.jsonl.zstd`(独立 zstd 帧拼接,普通 grep 读不了)。仓库自带读取脚本:
@@ -153,7 +157,7 @@ node scripts/session-inspect.mjs --session session-xxxx --last-system --grep "
153
157
  搜索:"结构化输出(本会话已启用" → 命中 1 条 system/message
154
158
  ```
155
159
 
156
- 关闭后(`/structured off` 或把该会话在 `state.json` 里置为 `false`),同一个会话下一轮应看到 `命中 0 条`。视觉样式仍保留;`/structured` 只控制提示词注入,不关闭 client 视觉层。
160
+ 关闭后(`/structured off` 或把该会话在 `state.json` 里置为 `false`),同一个会话下一轮应看到 `命中 0 条`。视觉层由插件设置 `visual` 控制,`/structured` 只控制提示词注入,不关闭 client 视觉层。
157
161
 
158
162
  > 以上命令在仓库根执行。已装到 profile 时,脚本路径是 `<profile>\node_modules\dsh-structured\scripts\`;把命令里的 `scripts/` 换成 `node_modules/dsh-structured/scripts/` 即可。
159
163
 
@@ -222,6 +226,8 @@ scripts/desktop-check.mjs desktop 兼容性预检
222
226
  scripts/measure-prose.mjs 散文率统计(可复跑)
223
227
  scripts/lib/session-log.mjs v4 会话日志 zstd 帧读取
224
228
  test/structured.test.mjs 单元测试 + 边界测试
229
+ test/client-visual.test.mjs client visual 配置开关测试
230
+ test/client-cards.test.mjs 严格卡片识别 DOM 测试
225
231
  docs/METRICS.md A/B 指标与原始明细
226
232
  docs/ROADMAP.md Phase 1/2 路线图与 Phase 2 任务
227
233
  docs/CARD-SYSTEM.md 卡片类型、anatomy 与热点预算
package/cordis.patch.yml CHANGED
@@ -6,6 +6,7 @@
6
6
  # tailReminder 是否在 system prompt 末尾追加一句提醒(默认 true)
7
7
  # includeSubagents 是否也给子代理会话注入(默认 false,子代理产出不直接面向用户)
8
8
  # genui auto | on | off;auto 检测到 dsh-genui 才追加 dsh-ui 路由(默认 auto)
9
+ # visual 是否启用客户端视觉层(默认 true;由插件设置页切换,不写 state.json)
9
10
  #
10
11
  # 需要改默认值时,在 profile 的 cordis.patch.yml 里覆盖同一行(整份 config 替换,不是深合并):
11
12
  # - id: dsh-structured
@@ -18,3 +19,4 @@
18
19
  tailReminder: true
19
20
  includeSubagents: false
20
21
  genui: auto
22
+ visual: true
@@ -0,0 +1,3 @@
1
+ [AC-001/002] `npm test` 30/30、`node scripts/desktop-check.mjs` 全 PASS;`BUILTIN_STYLE_TEXT`/`TAIL_REMINDER_TEXT` 不再含 `500 字`、`≤500`、`字数上限`,仍含标题即结论、组件、去过程叙事、去重复、证据、短答不套卡。
2
+ [AC-003] 12 条固定 prompt 全部 completed;首屏标题卡 12/12;`> **结论` 0;最大强调块 2;表格结论 12/12;散文 0;过程叙事命中 0;3 条最长回复(08/04/01,2453/1306/1265 字)人工抽查信息完整,未因字数删信息。
3
+ [AC-005/006] README、METRICS、CARD-SYSTEM 明确清晰优先、不设硬性篇幅上限;未改 client/注入通道、无运行时截断;未 push、未 publish、未提市场 PR;本地提交见 `git log -1`。
@@ -0,0 +1,3 @@
1
+ [AC-001/002] `npm test` 36/36(含严格卡片 10 反例 + 9 正例 + GenUI 跳过);`node scripts/desktop-check.mjs` 全 PASS;`lib/index.js`、`lib/client.js` 与 src 一致。
2
+ [AC-003] `structured-test` 已安装 0.8.2(B 构建,`lib/client.js` hash 与仓库一致),headless 一轮 `completed`;`session-inspect --session session-343e363b-73ca-4c9c-80ed-52d099f5cb8b --last-system --grep "结构化输出(本会话已启用"` 命中 1;`npm pack` 38 文件 / 763106 B / unpacked 962368 B。
3
+ [AC-004/005] `visual` 配置与 client `configForms` 读取测试通过,`/structured off` 仍只控制提示词;桌面 bundle 详情页 `visual` 字段的实机可见/可切换 **未验**(未触碰 desktop profile);未 push、未 publish、未提市场 PR。
@@ -6,6 +6,7 @@
6
6
  2. **热点预算**:每条实质回复最多 **1 个主卡 + 1 个行动/风险卡**;全文强调块 ≤2。
7
7
  3. **卡片必须可回退**:没有 GenUI 时用原生 markdown + 我们的 CSS;有 GenUI 时交互/图表卡片走 `dsh-ui`,普通卡片仍走 fallback。
8
8
  4. **颜色不超过 3 个语义色**:品牌色(结论/判断/指标/下一步)、warn(风险)、success(验收)。不用第四种装饰色。
9
+ 5. **清晰优先,不设硬性篇幅上限**:按信息量组织,不为了字数删信息;表格优先 ≤5 行,信息确实多时拆表或用 `dsh-ui` 大表,不硬砍内容。
9
10
 
10
11
  ## 卡片类型
11
12
 
package/docs/METRICS.md CHANGED
@@ -34,7 +34,7 @@ node scripts/measure-prose.mjs --since-days 30 --before "2026-10-20T21:35:00+08:
34
34
 
35
35
  ## 2. 改后样本(插件开启,测试 profile)
36
36
 
37
- - profile:`structured-test`(`dsh-base` + `dsh-headless` + `dsh-structured@0.1.2`)。测试构建是 0.1.2;交付的 0.7.4 为发布准备(截图/README/市场 YAML/npm 包),host 注入与统计口径未变。
37
+ - profile:`structured-test`(`dsh-base` + `dsh-headless` + `dsh-structured@0.1.2`)。测试构建是 0.1.2;0.8.1 只改规则文本(清晰度约束,无运行时截断/字数统计),host 注入与统计口径未变;0.7.4 为上一发布版。
38
38
  - 模型:headless 默认 `deepseek-flash`。
39
39
  - 样本:12 个新会话,同一组 12 条问题;**12/12 会话的 `system/message` 都同时命中主规则段与尾部提醒**。
40
40
  - 命令:
@@ -82,6 +82,7 @@ node scripts/measure-prose.mjs --since-days 30 --before "2026-10-20T21:35:00+08:
82
82
  node scripts/measure-prose.mjs --sessions session-xxxx
83
83
 
84
84
  # 换首屏阈值 / 换整篇口径
85
+ # 500 是视口高度像素,不是字数;0.8.1 起不设硬性篇幅上限
85
86
  node scripts/measure-prose.mjs --first-screen 500
86
87
  node scripts/measure-prose.mjs --whole
87
88
  ```
@@ -1,78 +1,78 @@
1
- # 宿主升级后 markdown class 改名:影响与排查
2
-
3
- ## 结论
4
-
5
- 视觉层全部依赖宿主内部标记(`[class*="_markdown_"]`、`.md-code-block`、`[data-code-block-banner]`)。宿主把这些 token 改名后,插件**不报错、静默降级**:CSS 0 命中、JS 半死、文字半区照常。现有测试与验收都拦不住它,只能靠渲染进程内的探针确认。
6
-
7
- ## 会发生什么
8
-
9
- | 半区 | 依赖 | 改名后 |
10
- | --- | --- | --- |
11
- | CSS(`src/client.js` 内 `CSS` 常量,全部规则) | `[class*="_markdown_"]` | 0 命中:字号层级、表格、代码块、引用卡、状态色、语言色全部回退宿主原生样式 |
12
- | JS 装饰(6 处 `querySelectorAll`,行 276/300/310/320/330/339) | `[class*="_markdown_"] …` | 全部返回空:标题图标、状态属性、状态表、表格结论条、代码语言色都不再加 |
13
- | JS 装饰(1 处,行 283) | 裸 `blockquote` | **仍然生效**:会给引用块加 `data-dsh-structured-card`,但没有任何 CSS 消费它 → 「属性在、样式无」 |
14
- | 文字半区(`ctx.systemPrompt.section`) | 无 DOM 依赖 | 完全不受影响:注入、`/structured status`、开关都正常,模型仍按结构化输出 |
15
-
16
- 三个后果值得单独记住:
17
-
18
- 1. **没有错误信号。** `console.info('[dsh-structured] visual layer active')` 照样打印,`<style>` 标签也在 DOM 里;这两条只能证明插件加载了,不能证明选择器命中了。
19
- 2. **检测盲区。** 测试只 grep 源码里的标记(`test/structured.test.mjs:470`),验收只看 system prompt 注入;选择器命中失败没有任何断言覆盖。
20
- 3. **边界。** `[class*="_markdown_"]` 对 CSS Module 的 hash 后缀(`_markdown_1a2b3` → `_markdown_9x8y7`)免疫,只有 **token 本身**改了(`_markdownBody_`、`_md_`、`_prose_`、`markdown-body`)才断。所以「升级后样式全丢」基本等于 token 改名,不是 hash 变化。
21
-
22
- ## 怎么排查(3 分钟)
23
-
24
- 1. Desktop 打开 DevTools(`Ctrl+Shift+I`;被禁用时走窗口菜单的开发者工具)。
25
- 2. 在 Console 粘贴探针:
26
-
27
- ```js
28
- (() => {
29
- const roots = document.querySelectorAll('[class*="_markdown_"]');
30
- const n = (s) => document.querySelectorAll(s).length;
31
- const tokens = new Set();
32
- for (const el of document.querySelectorAll('[class*="markdown" i], [class*="message" i]')) {
33
- String(el.className).split(/\s+/).filter((t) => /markdown|md|prose/i.test(t)).forEach((t) => tokens.add(t));
34
- }
35
- console.table({
36
- styleTag: !!document.getElementById('dsh-structured-skin-style'),
37
- rootFlag: document.documentElement.getAttribute('data-dsh-structured'),
38
- markdownRoots: roots.length,
39
- cardAttrs: n('blockquote[data-dsh-structured-card]'),
40
- headingIcons: n('[data-dsh-structured-icon]'),
41
- statusAttrs: n('[data-dsh-structured-status]'),
42
- codeLang: n('[data-dsh-structured-lang]'),
43
- accentVar: roots[0] ? getComputedStyle(roots[0]).getPropertyValue('--ds-accent').trim() : '(no root)',
44
- });
45
- console.log('class tokens:', [...tokens]);
46
- })()
47
- ```
48
-
49
- 3. 按表判定:
50
-
51
- | 探针结果 | 判定 | 下一步 |
52
- | --- | --- | --- |
53
- | `styleTag=false` | 插件没加载 | 查 profile bundle 行、`cordis.patch.yml`、安装完整性,与改名无关 |
54
- | `styleTag=true`、`markdownRoots=0`、`cardAttrs>0` | **改名确诊**:JS 半挂、CSS 全挂 | 取新 token 修选择器 |
55
- | `styleTag=true`、`markdownRoots=0`、`cardAttrs=0` | 改名确诊(当前屏没有引用块) | 同上 |
56
- | `markdownRoots>0`、`headingIcons=0` | 选择器没问题,是装饰链路没跑/抛错 | 看 Console 报错、确认 `apply` 执行过 |
57
- | 全部 >0、`accentVar` 为空 | 样式被覆盖或优先级不足 | 查宿主/其他插件的 `!important` |
58
-
59
- 4. 取新 token(在普通 PowerShell 里跑,不在沙箱内):
60
-
61
- ```powershell
62
- rg -a -o --no-filename '_[A-Za-z]*[Mm]arkdown_[A-Za-z0-9_-]{0,12}' "$env:DSH_APP_ASAR" | Sort-Object -Unique
63
- ```
64
-
65
- 5. 定因:把新 token 与 `src/client.js` 里的 `_markdown_` 对照,再看应用版本(关于页 / `navigator.userAgent`)是否刚升级;`package.json` 的 `dsh.compatibility.dshReleases` 目前只声明到 `0.2.1-rc.2`,新版本一律算未验证。
66
-
67
- ## 修法(推荐,尚未实施)
68
-
69
- - **别再把 CSS 挂在宿主类名上。** JS 先用候选选择器 + 结构启发式(同时含 `h1–h6`、`table`、`blockquote`、`pre` 的最近公共容器)定位 markdown 根,打上 `data-dsh-structured-root`,CSS 全部改挂这个属性。宿主改名只影响「找容器」这一处,失败可观测。
70
- - **加启动自检。** 命中 0 → 打一次 `console.warn('[dsh-structured] markdown root not found, selectors drifted')`,并把 `<html>` 的 `data-dsh-structured` 置为 `degraded`,让退化可见。
71
- - 改 `src/client.js` 后必须 `npm run build`:`lib/client.js` = banner + `src/client.js`,有测试校验(`test/structured.test.mjs:480`)。
72
-
73
- ## 修完回归
74
-
75
- 1. 探针表:`markdownRoots>0`、`headingIcons>0`、`accentVar` 非空。
76
- 2. 四类元素目检:标题层级 + 图标、表格(表头/斑马纹/状态列)、代码块(banner 贴合 + 语言色)、引用卡(结论/风险/验收三色)。
77
- 3. 明暗两主题各一遍;窄窗(<720px)不横向溢出。
78
- 4. 流式输出 30 秒不冻结(MutationObserver 只在 rAF 后扫一次)。
1
+ # 宿主升级后 markdown class 改名:影响与排查
2
+
3
+ ## 结论
4
+
5
+ 视觉层全部依赖宿主内部标记(`[class*="_markdown_"]`、`.md-code-block`、`[data-code-block-banner]`)。宿主把这些 token 改名后,插件**不报错、静默降级**:CSS 0 命中、JS 半死、文字半区照常。现有测试与验收都拦不住它,只能靠渲染进程内的探针确认。
6
+
7
+ ## 会发生什么
8
+
9
+ | 半区 | 依赖 | 改名后 |
10
+ | --- | --- | --- |
11
+ | CSS(`src/client.js` 内 `CSS` 常量,全部规则) | `[class*="_markdown_"]` | 0 命中:字号层级、表格、代码块、引用卡、状态色、语言色全部回退宿主原生样式 |
12
+ | JS 装饰(6 处 `querySelectorAll`,行 276/300/310/320/330/339) | `[class*="_markdown_"] …` | 全部返回空:标题图标、状态属性、状态表、表格结论条、代码语言色都不再加 |
13
+ | JS 装饰(1 处,行 283) | 裸 `blockquote` | **仍然生效**:会给引用块加 `data-dsh-structured-card`,但没有任何 CSS 消费它 → 「属性在、样式无」 |
14
+ | 文字半区(`ctx.systemPrompt.section`) | 无 DOM 依赖 | 完全不受影响:注入、`/structured status`、开关都正常,模型仍按结构化输出 |
15
+
16
+ 三个后果值得单独记住:
17
+
18
+ 1. **没有错误信号。** `console.info('[dsh-structured] visual layer active')` 照样打印,`<style>` 标签也在 DOM 里;这两条只能证明插件加载了,不能证明选择器命中了。
19
+ 2. **检测盲区。** 测试只 grep 源码里的标记(`test/structured.test.mjs:470`),验收只看 system prompt 注入;选择器命中失败没有任何断言覆盖。
20
+ 3. **边界。** `[class*="_markdown_"]` 对 CSS Module 的 hash 后缀(`_markdown_1a2b3` → `_markdown_9x8y7`)免疫,只有 **token 本身**改了(`_markdownBody_`、`_md_`、`_prose_`、`markdown-body`)才断。所以「升级后样式全丢」基本等于 token 改名,不是 hash 变化。
21
+
22
+ ## 怎么排查(3 分钟)
23
+
24
+ 1. Desktop 打开 DevTools(`Ctrl+Shift+I`;被禁用时走窗口菜单的开发者工具)。
25
+ 2. 在 Console 粘贴探针:
26
+
27
+ ```js
28
+ (() => {
29
+ const roots = document.querySelectorAll('[class*="_markdown_"]');
30
+ const n = (s) => document.querySelectorAll(s).length;
31
+ const tokens = new Set();
32
+ for (const el of document.querySelectorAll('[class*="markdown" i], [class*="message" i]')) {
33
+ String(el.className).split(/\s+/).filter((t) => /markdown|md|prose/i.test(t)).forEach((t) => tokens.add(t));
34
+ }
35
+ console.table({
36
+ styleTag: !!document.getElementById('dsh-structured-skin-style'),
37
+ rootFlag: document.documentElement.getAttribute('data-dsh-structured'),
38
+ markdownRoots: roots.length,
39
+ cardAttrs: n('blockquote[data-dsh-structured-card]'),
40
+ headingIcons: n('[data-dsh-structured-icon]'),
41
+ statusAttrs: n('[data-dsh-structured-status]'),
42
+ codeLang: n('[data-dsh-structured-lang]'),
43
+ accentVar: roots[0] ? getComputedStyle(roots[0]).getPropertyValue('--ds-accent').trim() : '(no root)',
44
+ });
45
+ console.log('class tokens:', [...tokens]);
46
+ })()
47
+ ```
48
+
49
+ 3. 按表判定:
50
+
51
+ | 探针结果 | 判定 | 下一步 |
52
+ | --- | --- | --- |
53
+ | `styleTag=false` | 插件没加载 | 查 profile bundle 行、`cordis.patch.yml`、安装完整性,与改名无关 |
54
+ | `styleTag=true`、`markdownRoots=0`、`cardAttrs>0` | **改名确诊**:JS 半挂、CSS 全挂 | 取新 token 修选择器 |
55
+ | `styleTag=true`、`markdownRoots=0`、`cardAttrs=0` | 改名确诊(当前屏没有引用块) | 同上 |
56
+ | `markdownRoots>0`、`headingIcons=0` | 选择器没问题,是装饰链路没跑/抛错 | 看 Console 报错、确认 `apply` 执行过 |
57
+ | 全部 >0、`accentVar` 为空 | 样式被覆盖或优先级不足 | 查宿主/其他插件的 `!important` |
58
+
59
+ 4. 取新 token(在普通 PowerShell 里跑,不在沙箱内):
60
+
61
+ ```powershell
62
+ rg -a -o --no-filename '_[A-Za-z]*[Mm]arkdown_[A-Za-z0-9_-]{0,12}' "$env:DSH_APP_ASAR" | Sort-Object -Unique
63
+ ```
64
+
65
+ 5. 定因:把新 token 与 `src/client.js` 里的 `_markdown_` 对照,再看应用版本(关于页 / `navigator.userAgent`)是否刚升级;`package.json` 的 `dsh.compatibility.dshReleases` 目前只声明到 `0.2.1-rc.2`,新版本一律算未验证。
66
+
67
+ ## 修法(推荐,尚未实施)
68
+
69
+ - **别再把 CSS 挂在宿主类名上。** JS 先用候选选择器 + 结构启发式(同时含 `h1–h6`、`table`、`blockquote`、`pre` 的最近公共容器)定位 markdown 根,打上 `data-dsh-structured-root`,CSS 全部改挂这个属性。宿主改名只影响「找容器」这一处,失败可观测。
70
+ - **加启动自检。** 命中 0 → 打一次 `console.warn('[dsh-structured] markdown root not found, selectors drifted')`,并把 `<html>` 的 `data-dsh-structured` 置为 `degraded`,让退化可见。
71
+ - 改 `src/client.js` 后必须 `npm run build`:`lib/client.js` = banner + `src/client.js`,有测试校验(`test/structured.test.mjs:480`)。
72
+
73
+ ## 修完回归
74
+
75
+ 1. 探针表:`markdownRoots>0`、`headingIcons>0`、`accentVar` 非空。
76
+ 2. 四类元素目检:标题层级 + 图标、表格(表头/斑马纹/状态列)、代码块(banner 贴合 + 语言色)、引用卡(结论/风险/验收三色)。
77
+ 3. 明暗两主题各一遍;窄窗(<720px)不横向溢出。
78
+ 4. 流式输出 30 秒不冻结(MutationObserver 只在 rAF 后扫一次)。
@@ -55,7 +55,7 @@ pnpm 和 npm 二选一,给结论和一张不超过 4 行的对比表。
55
55
 
56
56
  | 门 | 判据 | 方法 |
57
57
  | --- | --- | --- |
58
- | R1 卡层级 | 标签 13px;标题独立成块、16px/700;正文 15.5px;普通首段走 16.5px/600 lead 兜底 | DOM 测字号;无 DevTools 时只判层级(标签 < 标题 < 正文),字号记未验证 |
58
+ | R1 卡层级 | 标签 13px;标题独立成块、16px/700;正文 15.5px;普通首段不升级 lead,只有 `**表格结论:**` 段落使用表格 lead | DOM 测字号;无 DevTools 时只判层级(标签 < 标题 < 正文),字号记未验证 |
59
59
  | R2 热点预算 | 强调块 ≤2;无卡中卡;结论不在普通段落重复一遍。强调块 = 卡片 blockquote + 带色 callout,不含表格与代码 | 原文 + 截图 |
60
60
  | R3 表格 | 表前一行 `**表格结论:**`;无竖线;表头底色可辨;状态只染单元格/行首,不整行铺色 | 原文 + 截图 |
61
61
  | R4 状态 | ✅/⚠️/❌ 字形保留;色不是唯一语义;状态文字对比度 ≥4.5:1 | DOM 取色;无 DevTools 时目检并标未验证 |
@@ -73,7 +73,7 @@ pnpm 和 npm 二选一,给结论和一张不超过 4 行的对比表。
73
73
  | C3 状态符号 | 凡状态行/状态表,保留 ✅/⚠️/❌ | 100% |
74
74
  | C4 代码语言 | 凡围栏代码块,有语言标签 | 100% |
75
75
  | C5 短答克制 | P06:0 卡、0 表、≤2 句 | 1/1 |
76
- | C6 长度 | 去代码块、表格行、卡片标签行后的可见字符 ≤500(P08/P09 豁免) | 100% |
76
+ | C6 篇幅 | 不设硬性字数上限;长回复信息完整、不因字数删信息(人工抽查) | 100% |
77
77
 
78
78
  > 目标组件命中率(实际出现的卡型是否等于期望)只**报告**,不单独判失败;低于 8/12 时复盘 prompt 与注入契约,不要直接改 CSS。
79
79
 
@@ -157,7 +157,7 @@ pnpm 和 npm 二选一,给结论和一张不超过 4 行的对比表。
157
157
  | 级别 | 定义 | 处理 |
158
158
  | --- | --- | --- |
159
159
  | S1 | 渲染断裂:卡没样式、标题塌成正文、溢出/裁切、对比度不达标、GenUI 双渲染 | 停跑,修完重跑全套 |
160
- | S2 | 契约未达:无卡、>2 卡、缺表格结论、缺状态符号、代码无语言、超 500 字 | 记录,修完只复跑相关用例 |
160
+ | S2 | 契约未达:无卡、>2 卡、缺表格结论、缺状态符号、代码无语言、信息不完整或为凑长度删信息 | 记录,修完只复跑相关用例 |
161
161
  | S3 | 观感:间距、图标语义、色调偏差 | 记录,可延后 |
162
162
 
163
163
  - 每个用例只按第一次结果计分。模型没按格式写,就是没写,不靠重跑刷到通过;诊断性重跑单独记,不计入分数。
@@ -165,7 +165,7 @@ pnpm 和 npm 二选一,给结论和一张不超过 4 行的对比表。
165
165
 
166
166
  ## 8. 跑之前必须确认的已知缺口
167
167
 
168
- 1. **卡标题层级**:0.7.3 起,one-p 首段由 16.5px/600 lead 兜底;首段带 `<strong>` 的 one-p 由 statement 兜底;R1 不再要求两个 `<p>`。
168
+ 1. **卡标题层级**:0.8.2 起只认完整卡型标签;只有第一块、首行加粗标题、且有正文/第二段的 blockquote 才升级 statement;普通 one-p 引用不再兜底 lead;表格 lead 只属于 `**表格结论:**` 段落。
169
169
  2. **GenUI 是否安装未知。** 以 `/structured status` 为准;未装时 P12 记 `N/A`,不能算通过,覆盖数写 11/12。
170
170
  3. **DevTools 不一定可用。** desktop 是 Electron,若打不开控制台,R1/R4 退化为 200% 截图目检,R8 的控制台项记“未验证”,并在报告方法列写明,不要写成测量。
171
171