dsh-structured 0.0.0-stage → 0.7.4
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/ACCEPTANCE.md +3 -0
- package/CHANGELOG.md +53 -0
- package/LICENSE +21 -0
- package/README.md +239 -2
- package/assets/screenshots/01-title-card.png +0 -0
- package/assets/screenshots/06-status-table.png +0 -0
- package/assets/screenshots/07-code-block.png +0 -0
- package/assets/screenshots/08-narrow.png +0 -0
- package/cordis.patch.yml +20 -0
- package/docs/CARD-SYSTEM.md +62 -0
- package/docs/DESIGN-REFERENCES.md +51 -0
- package/docs/METRICS.md +89 -0
- package/docs/RISK-ROLLBACK.md +129 -0
- package/docs/ROADMAP.md +85 -0
- package/docs/TROUBLESHOOT-VISUAL.md +78 -0
- package/docs/VISUAL-ACCEPTANCE.md +224 -0
- package/docs/VISUAL-CRITIQUE.md +57 -0
- package/docs/VISUAL-PLAN.md +133 -0
- package/icon.svg +10 -0
- package/lib/client.js +467 -0
- package/lib/index.js +483 -0
- package/locale/en.json +1 -0
- package/locale/zh.json +1 -0
- package/package.json +83 -4
- package/screenshots.json +6 -0
- package/scripts/build.mjs +22 -0
- package/scripts/desktop-check.mjs +129 -0
- package/scripts/lib/session-log.mjs +176 -0
- package/scripts/measure-prose.mjs +227 -0
- package/scripts/session-inspect.mjs +123 -0
- package/scripts/uninstall.mjs +53 -0
- package/src/client.js +465 -0
- package/src/index.js +481 -0
- package/test/structured.test.mjs +537 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# 视觉方案:风险评估与回滚路径(0.7.3)
|
|
2
|
+
|
|
3
|
+
评估对象:`src/client.js` 的视觉层(CSS 皮肤 + 语义装饰)+ `src/index.js` 注入的标题卡契约。
|
|
4
|
+
实装状态:desktop profile 已装 0.7.3(`file:<repo>/dsh-structured-0.7.3.tgz`,`dsh.profile.bundles` 中一行)。
|
|
5
|
+
基线:0.7.3 源码 + 当前 desktop 配置;本轮未重启、未改 profile。
|
|
6
|
+
|
|
7
|
+
## 结论
|
|
8
|
+
|
|
9
|
+
没有 P0:视觉层只加 `<style>` 和属性,选择器失配时退化为原生 markdown,不会打断会话。
|
|
10
|
+
两个 P1 都在“可控性”,不在“正确性”:
|
|
11
|
+
|
|
12
|
+
1. **皮肤没有运行时开关。** `/structured off` 只停提示词注入,`apply()` 无条件注入样式;要关皮肤只能删 bundle 行重开,或整包卸载。
|
|
13
|
+
2. **语义判定靠中文前缀 + “首个引用块”猜。** 任何以 `结论/判断/风险` 开头的 blockquote 会被做成卡;任何非卡的首个 blockquote 会被升成 16.5px/600 的 lead。文本不变,但层级会撒谎。
|
|
14
|
+
|
|
15
|
+
## 风险清单
|
|
16
|
+
|
|
17
|
+
| 级别 | 风险 | 证据 | 触发 / 影响 |
|
|
18
|
+
| --- | --- | --- | --- |
|
|
19
|
+
| P1 | 皮肤无法热关闭 | `src/client.js:401-411` 无条件注入;config 只有 4 项(`cordis.patch.yml:16-20`);status 明示“视觉层始终开启”(`src/index.js:297`) | 任何“先关掉看看”都要重开 Desktop;无法用 `/structured off` 做视觉 A/B |
|
|
20
|
+
| P1 | 首个引用块 / 前缀误判 | `isFirstBlockquote`(`src/client.js:301-304`)只看“是不是第一个 blockquote”;`decorate` 把它升为 lead(`:337`);`cardTypeFor` 只看开头两字(`:276-279`) | 引用报错信息、用户原话、外部文档会被当成“主结论/风险卡”;不改文本,改观感 |
|
|
21
|
+
| P2 | 每帧全量重扫 | `MutationObserver` 监听 `body`(`:433-434`),rAF 后 `decorate(document)` 跑 7 组 `querySelectorAll`(`:321-397`) | 长会话 + 流式输出时每帧扫全量 DOM;开销随会话长度线性增长 `[I]`,未实测 |
|
|
22
|
+
| P2 | 宿主内部标记耦合 | `_markdown_`、`.md-code-block`、`[data-code-block-banner]`、`[data-theme="dark"]`(`:54-269`) | 宿主改名后不报错、静默半失效;暗色强调色可能不生效,不是干净降级 |
|
|
23
|
+
| P2 | desktop 卸载脚本会失败 | `scripts/uninstall.mjs:29` 调 `dsh plugin --profile <p> remove`;`README.md:36` 明确 desktop 被 CLI 拒绝;失败时脚本在删状态前退出(`:35-39`) | “一条命令卸载”在 desktop 上无效,state 目录残留;必须手工 pnpm |
|
|
24
|
+
| P3 | 视觉逻辑无 DOM 测试 | `test/structured.test.mjs:491-499` 只 grep 字符串;statement/lead/status 分支无断言 | 0.7.1/0.7.2 的 statement 失效这类回归,单测拦不住 |
|
|
25
|
+
| P3 | GenUI / 作用面靠猜 | `inGenui` 只认 `[data-genui]`、`[class*="genui-root"]`(`:281-287`);皮肤选择器不区分消息角色 | 标记改名会套进 GenUI;是否也作用到用户消息/设置文档未验证 |
|
|
26
|
+
|
|
27
|
+
## 回滚阶梯
|
|
28
|
+
|
|
29
|
+
按影响面从小到大。每档写明生效条件与代价。
|
|
30
|
+
|
|
31
|
+
### L0 会话级:只停注入(立即生效)
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
/structured off
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
下一轮起 system prompt 不再有规则段与尾部提醒。**皮肤仍在**,表格、卡片、状态色照旧。
|
|
38
|
+
代价:0 重启;局限:不能用来判断“视觉方案本身有没有问题”。
|
|
39
|
+
|
|
40
|
+
### L1 全局停注入(重启生效)
|
|
41
|
+
|
|
42
|
+
profile 的 `cordis.patch.yml` 覆盖同一 id(config 整份替换,不是深合并):
|
|
43
|
+
|
|
44
|
+
```yaml
|
|
45
|
+
- id: dsh-structured
|
|
46
|
+
config: { defaultEnabled: false, tailReminder: false, includeSubagents: false, genui: auto }
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
新会话默认不注入;已显式 `/structured on` 的会话仍注入(显式优先)。皮肤仍在。
|
|
50
|
+
|
|
51
|
+
### L2 停插件(推荐的视觉回滚)
|
|
52
|
+
|
|
53
|
+
1. 退出 Desktop。
|
|
54
|
+
2. 从 `profiles/desktop/package.json` 的 `dsh.profile.bundles` 删掉 `"dsh-structured"`。
|
|
55
|
+
3. 重开 Desktop。
|
|
56
|
+
|
|
57
|
+
host 一定不加载;client 预期随 bundle 卸载(未实测)。`node_modules` 原封不动,把行加回去即可恢复——这是最轻的“能关皮肤”档。
|
|
58
|
+
若重开后 Console 仍出现 `[dsh-structured] visual layer active`,说明 client 由依赖图加载而非 bundle 行,需要走 L3 的 `pnpm remove`。
|
|
59
|
+
|
|
60
|
+
### L3 完整卸载(desktop)
|
|
61
|
+
|
|
62
|
+
1. 退出 Desktop。
|
|
63
|
+
2. 删 `dsh.profile.bundles` 里的 `"dsh-structured"` 行。
|
|
64
|
+
3. 清状态目录(脚本从仓库跑,删包前后都行):
|
|
65
|
+
|
|
66
|
+
```powershell
|
|
67
|
+
node <repo>\scripts\uninstall.mjs
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**不要带 `--profile desktop`**:CLI 会拒绝,脚本随即退出,state 不会被删。
|
|
71
|
+
4. 在 profile 目录移除依赖:
|
|
72
|
+
|
|
73
|
+
```powershell
|
|
74
|
+
$profileDir = Join-Path $env:DSH_HOME 'profiles\desktop'
|
|
75
|
+
Set-Location $profileDir
|
|
76
|
+
pnpm remove dsh-structured
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
5. 重开 Desktop。
|
|
80
|
+
|
|
81
|
+
不要整份恢复 `package.json.bak-*` 快照:会把快照之后安装/调整的其他插件一起回滚。定向删依赖 + bundle 行更安全。
|
|
82
|
+
|
|
83
|
+
### L4 版本回退
|
|
84
|
+
|
|
85
|
+
用于“0.7.3 引入新问题”。退出 Desktop 后:
|
|
86
|
+
|
|
87
|
+
```powershell
|
|
88
|
+
Set-Location (Join-Path $env:DSH_HOME 'profiles\desktop')
|
|
89
|
+
pnpm add <repo>\dsh-structured-0.7.2.tgz
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
0.7.2 缺“多段落首卡也识别为 statement”的修复,会把已修好的首卡打回去;只在 0.7.3 确认回归时用。
|
|
93
|
+
|
|
94
|
+
## 回滚验收
|
|
95
|
+
|
|
96
|
+
```powershell
|
|
97
|
+
$d = Join-Path $env:DSH_HOME 'profiles\desktop'
|
|
98
|
+
Test-Path "$d\node_modules\dsh-structured" # L3 后 False;L2 仍 True
|
|
99
|
+
Select-String -Path "$d\package.json" -Pattern 'dsh-structured' # L2/L3 后无输出
|
|
100
|
+
Test-Path (Join-Path $env:DSH_HOME 'dsh-structured') # L3 后 False
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
重启后目检 / DevTools:
|
|
104
|
+
|
|
105
|
+
- `document.documentElement.dataset.dshStructured` 为 `undefined`
|
|
106
|
+
- 新回复上不再出现 `data-dsh-structured-*` 属性
|
|
107
|
+
- Console 不再打印 `[dsh-structured] visual layer active`
|
|
108
|
+
|
|
109
|
+
注入是否真的停了:
|
|
110
|
+
|
|
111
|
+
```powershell
|
|
112
|
+
node <repo>\scripts\session-inspect.mjs --last-system --grep "结构化输出(本会话已启用"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## 未验证(别当成结论)
|
|
116
|
+
|
|
117
|
+
1. L2 后 client 是否随 bundle 一并卸载:需要一次重启 + DevTools 探针。
|
|
118
|
+
2. `[data-theme="dark"]` 是否是宿主真实的暗色标记:DevTools 看 `documentElement`。
|
|
119
|
+
3. 流式长会话的扫描开销:Performance 面板看 long task,当前只有静态推断。
|
|
120
|
+
4. 皮肤作用面:是否也命中用户消息、设置页、插件文档;选择器没有角色范围。
|
|
121
|
+
5. GenUI 当前版本的根标记:0.6.2 实测有 `data-genui`,0.7.3 未复测。
|
|
122
|
+
|
|
123
|
+
## 结构性建议(按性价比)
|
|
124
|
+
|
|
125
|
+
1. 加 `visual: on|off` 配置,client 启动时读取,与 `/structured` 解耦。这与 `docs/VISUAL-PLAN.md:131-133` 的“不增加 visual 配置”冲突,需要明确改计划;收益是视觉试错不再需要重启。
|
|
126
|
+
2. lead 判定收紧:只在“回复开头 3 个块内、且没有卡片”时升级;或要求模型显式标记首卡。
|
|
127
|
+
3. `decorate` 只扫 MutationRecord 的 target 子树,或流式期间做 100ms 节流,避免每帧全量。
|
|
128
|
+
4. 选择器自检:`markdownRoots=0` 时把 `<html data-dsh-structured>` 置为 `degraded` 并 warn 一次,让静默失败可见。
|
|
129
|
+
5. 补 DOM 测试(happy-dom / jsdom)覆盖 statement / lead / status / row 四类分支;现在的 client 测试只证明字符串存在。
|
package/docs/ROADMAP.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# 路线图:结构化 → 视觉热点
|
|
2
|
+
|
|
3
|
+
> Boss 2026-10-20 定调:**卡片样式是方向**;第一阶段先实现结构化,第二阶段在结构化基础上实现视觉热点的规范引导,用多样的呈现方式让输出美观的同时提升人类阅读效率。
|
|
4
|
+
|
|
5
|
+
## 阶段划分
|
|
6
|
+
|
|
7
|
+
| 阶段 | 目标 | 状态 |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| Phase 1 | 结构化输出:首句结论 + 表格/清单/步骤 + 会话开关 + style.md + fail-open + desktop 实装 | ✅ 已完成(0.1–0.3.1 基线) |
|
|
10
|
+
| Phase 2 | 视觉热点规范引导:卡片系统、热点预算、多样呈现、GenUI 软联动、阅读效率验收 | 🚧 进行中(2.1–2.4 已落地,2.5–2.6 待做) |
|
|
11
|
+
|
|
12
|
+
## Phase 1(已完成,作为底座)
|
|
13
|
+
|
|
14
|
+
- host 每请求注入结构契约;`/structured on|off|status`;`style.md` 覆盖。
|
|
15
|
+
- desktop 实装,client 视觉层是 Phase 2 的 P0 预览,不是终点。
|
|
16
|
+
- 指标:历史首屏散文率 38.7% → 改后 0/12;22/22 测试;desktop live 注入已验证。
|
|
17
|
+
|
|
18
|
+
## Phase 2(明天开工)
|
|
19
|
+
|
|
20
|
+
### 2.1 卡片系统与设计 token
|
|
21
|
+
|
|
22
|
+
定义固定卡片类型,不让模型自由发明样式:
|
|
23
|
+
|
|
24
|
+
| 卡片 | 使用时机 | 无 GenUI 时的 fallback |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| 结论卡 | 每条实质回复 1 个,第一段 | `> **结论:**` + client 卡片 |
|
|
27
|
+
| 判断/决策卡 | 有取舍、需要拍板 | `> **判断:**` + 两列对比 |
|
|
28
|
+
| 指标卡 | 2–4 个关键数字 | 加粗数字 + 紧凑 stat 行 |
|
|
29
|
+
| 风险卡 | 风险/阻塞/未验证项 | `> **风险:**` warn 色 |
|
|
30
|
+
| 下一步卡 | 行动/待办 | `> **下一步:**` + 编号步骤 |
|
|
31
|
+
| 证据表 | 对比、清单、状态 | markdown 表格 + 表格结论 |
|
|
32
|
+
| 结果卡 | 工具输出、diff、文件变更 | 宿主工具卡 / GenUI diff 卡 |
|
|
33
|
+
|
|
34
|
+
规则:每条回复 **最多 1 个主卡 + 1 个行动/风险卡**;卡片必须有 eyebrow / 标题 / 正文 / 来源或下一步;颜色不超过 3 个语义色。
|
|
35
|
+
|
|
36
|
+
### 2.2 host 契约:卡片选择与热点预算
|
|
37
|
+
|
|
38
|
+
- 首段必须是结论卡;表格前一行 `**表格结论:**`;状态行用 ✅/⚠️/❌。
|
|
39
|
+
- 模型按内容类型选择卡片,不按“好看”选择;短答不套卡。
|
|
40
|
+
- 全文最多两个强调块;没有证据的数字不单独做指标卡。
|
|
41
|
+
|
|
42
|
+
### 2.3 client:fallback 渲染与热点样式
|
|
43
|
+
|
|
44
|
+
- 不依赖 GenUI:用 CSS + 轻量 DOM 属性渲染结论/风险/下一步卡、状态行/行底色、表格/代码块。
|
|
45
|
+
- 增加 `data-dsh-structured-card-type` 等归属标记,便于和 GenUI 区分。
|
|
46
|
+
- 流式安全:只加属性/class,不搬 React 节点;MutationObserver + rAF 合批。
|
|
47
|
+
|
|
48
|
+
### 2.4 GenUI 软联动(可选,不硬依赖)
|
|
49
|
+
|
|
50
|
+
- 检测到 `dsh-genui` 已安装时,host 规则追加一句:交互/图表/大表格用 ` ```dsh-ui `;普通说明用 markdown。
|
|
51
|
+
- 检测失败/未安装:不出现任何 `dsh-ui` 指令,走 2.3 fallback。
|
|
52
|
+
- 同一内容只渲染一次:有 `dsh-ui` fence 的区域不再套我们的卡片样式;我们的 CSS 只作用于原生 markdown。
|
|
53
|
+
- 不新增 `peerDependencies`,不自动安装 GenUI;需要一键装两个时用独立 meta-package。
|
|
54
|
+
|
|
55
|
+
### 2.5 多样呈现与阅读效率
|
|
56
|
+
|
|
57
|
+
- 呈现方式按内容选:表格、卡片、时间线、步骤、对比网格、callout、状态 badges、代码块、diff 结果卡。
|
|
58
|
+
- 验收代理指标:
|
|
59
|
+
- 首屏命中率:12 条固定 prompt 中,首屏出现主卡/结论的比例 ≥80%。
|
|
60
|
+
- 热点预算:每条回复强调块 ≤2;无“全是重点”。
|
|
61
|
+
- 表格结论覆盖率:带表格的回复 100% 有表格结论。
|
|
62
|
+
- 状态可扫读:状态行/状态表 100% 有 ✅/⚠️/❌ 或文字标签。
|
|
63
|
+
- 散文率:沿用 `measure-prose`,目标 <10%。
|
|
64
|
+
- 用户体感:desktop 截图对比,至少 3 组 before/after。
|
|
65
|
+
|
|
66
|
+
### 2.6 单一视觉方案定稿与回归
|
|
67
|
+
|
|
68
|
+
- 锁定一套「工程蓝图」视觉:token、字号、间距、卡片样式;不提供主题菜单,不增加 `theme` 命令。
|
|
69
|
+
- `/structured on|off` 是唯一开关;明暗由宿主 token 自动跟随。
|
|
70
|
+
- 验收:同一套视觉在明/暗、不同桌面宽度下不溢出、不遮挡;没有主题选择入口。
|
|
71
|
+
|
|
72
|
+
## 非目标
|
|
73
|
+
|
|
74
|
+
- 不替换宿主 markdown 渲染器。
|
|
75
|
+
- 不接管 GenUI,不重复渲染 `dsh-ui` 内容。
|
|
76
|
+
- 不引入 pre-step 消息 append、不改 agent 循环、不改工具权限。
|
|
77
|
+
- 不硬依赖 GenUI,不把卡片样式写死在 host 规则里。
|
|
78
|
+
|
|
79
|
+
## 明天开工顺序
|
|
80
|
+
|
|
81
|
+
1. 2.1 卡片 token/类型定稿(`docs/CARD-SYSTEM.md`)。
|
|
82
|
+
2. 2.2 host 契约改为“按内容选卡 + 热点预算”。
|
|
83
|
+
3. 2.3 client fallback 卡片与归属标记。
|
|
84
|
+
4. 2.4 GenUI 软联动检测与 fallback 分流。
|
|
85
|
+
5. 2.5 12 条 prompt 的 before/after 与阅读效率验收。
|
|
@@ -0,0 +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 后扫一次)。
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# 12 条 prompt 视觉验收方案(v0.7.3)
|
|
2
|
+
|
|
3
|
+
状态:设计稿,未执行。执行后把计分表写进 `artifacts/visual-<stamp>/scorecard.md`,本文件只定义方法与门槛。
|
|
4
|
+
|
|
5
|
+
> **结论**
|
|
6
|
+
> **这是 12 个受控视觉态,不是 12 个随机问题**
|
|
7
|
+
> 每条 prompt 只负责逼出一种组件形态;渲染门与生成门分开判,避免模型这一次没按格式写,就被记成 CSS 坏了。截图是主证据,DOM 只做确认。
|
|
8
|
+
|
|
9
|
+
## 1. 边界
|
|
10
|
+
|
|
11
|
+
- **测什么**:desktop 应用内,0.7.3 的卡片、表格、状态、代码块、宽窄屏与明暗主题的渲染结果。
|
|
12
|
+
- **不测什么**:回答内容是否正确、注入是否命中、流式性能、卸载残留——那些在 `TASK.md` / `ACCEPTANCE.md` 的验收项,不重复。
|
|
13
|
+
- **与旧 12 条的关系**:T4 的 12 条是内容话题,服务散文率对照;本套是视觉探针,服务组件覆盖。两套不要混算,也不要用本套的通过率去替代散文率。
|
|
14
|
+
- **判定原则**:一条回复可以内容很差但视觉通过;也可以内容很好但视觉挂。两类问题分开记。
|
|
15
|
+
|
|
16
|
+
## 2. 用例
|
|
17
|
+
|
|
18
|
+
### 2.1 原文(12 行,行号即用例号;每行单独发一条,不要一次发 12 行)
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
pnpm 和 npm 二选一,给结论和一张不超过 4 行的对比表。
|
|
22
|
+
给我这版的三个关键数字:测试通过数、注入命中率、散文率;没实测的标待验证,先给判断。
|
|
23
|
+
宿主下次升级把 markdown class 改名,会怎样?影响和排查路径。
|
|
24
|
+
把 Phase 2 剩余工作拆成接下来 3 步,每步一个验收信号。
|
|
25
|
+
只看现有证据,这版能发吗?缺什么,一条条列。
|
|
26
|
+
一句话:插件会改工具权限吗?
|
|
27
|
+
把注入、开关、fail-open、卸载残留四项检查列成状态表,没验证的标待做。
|
|
28
|
+
用 12 行的表列出你建议的视觉验收用例:编号、目标组件、判定门、压力条件。
|
|
29
|
+
给一段 PowerShell:截当前屏幕存到 artifacts\shots,文件名带时间戳。
|
|
30
|
+
从打包、安装、验证到回滚,给我 5 步,每步一句验收信号。
|
|
31
|
+
对比表格、卡片、时间线、代码块四种呈现方式:适用内容、扫读优势、代价、800px 窗口表现。
|
|
32
|
+
把 0.6 → 0.7 → 0.8 的发版节奏做成时间线,标出每版的验收门。
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 2.2 期望矩阵
|
|
36
|
+
|
|
37
|
+
| # | 目标视觉态 | 必须看到 | 反模式(出现即记缺陷) |
|
|
38
|
+
| --- | --- | --- | --- |
|
|
39
|
+
| P01 | 判断/决策卡 + 对比表 | 一句明确选择;≤4 行表;表前 `**表格结论:**` | 两段散文收尾;表格无前导;建议含糊 |
|
|
40
|
+
| P02 | 指标卡 | 3 个数字紧凑成组;未实测项 `⚠️ 待验证` | 编造实测值;把 3 个数字铺成 3 段 |
|
|
41
|
+
| P03 | 风险卡 | warn 色卡;写清影响 + 触发条件;排查路径 | 全篇中性色;只说“可能有问题” |
|
|
42
|
+
| P04 | 下一步卡 | next 卡 + 3 步;每步一个验收信号 | 超过 2 个强调块;步骤没有验收信号 |
|
|
43
|
+
| P05 | 验收卡或风险卡 | 明确“能/不能发”;缺项逐条;状态符号 | “应该可以”式结论;缺项与证据脱节 |
|
|
44
|
+
| P06 | 短答(负控) | ≤2 句;0 卡、0 表、0 列表 | 套结论卡;为凑格式加清单 |
|
|
45
|
+
| P07 | 状态表 | 4 行;状态列 `✅/⚠️`;未验证写待做 | 全 ✅ 伪造;状态写成普通文字 |
|
|
46
|
+
| P08 | 长表 | 12 行 4 列;表头可辨;长表不撑破页面 | 拆成多张表;行数不足;横向溢出 |
|
|
47
|
+
| P09 | 代码块 | `powershell` 语言标签;banner 贴合;复制可见;长行不裁 | 裸围栏;语言标签缺失;代码被截断 |
|
|
48
|
+
| P10 | 编号步骤 | 1–5 步;每步一句验收信号;列表 marker 清晰 | 用表格代替步骤;卡片超过 2 个 |
|
|
49
|
+
| P11 | 宽表 + 窄屏 | 5 列表;800px 下可读(收缩或容器内滚动) | 页面级横向滚动;列被挤成竖排 |
|
|
50
|
+
| P12 | GenUI / 时间线 | `dsh-ui` 组件与 markdown 共存;或 fallback 表 | 同一内容双渲染;组件内被套卡片样式 |
|
|
51
|
+
|
|
52
|
+
## 3. 判定门
|
|
53
|
+
|
|
54
|
+
### 3.1 渲染硬门(任一适用用例失败 = S1,禁止发版)
|
|
55
|
+
|
|
56
|
+
| 门 | 判据 | 方法 |
|
|
57
|
+
| --- | --- | --- |
|
|
58
|
+
| R1 卡层级 | 标签 13px;标题独立成块、16px/700;正文 15.5px;普通首段走 16.5px/600 lead 兜底 | DOM 测字号;无 DevTools 时只判层级(标签 < 标题 < 正文),字号记未验证 |
|
|
59
|
+
| R2 热点预算 | 强调块 ≤2;无卡中卡;结论不在普通段落重复一遍。强调块 = 卡片 blockquote + 带色 callout,不含表格与代码 | 原文 + 截图 |
|
|
60
|
+
| R3 表格 | 表前一行 `**表格结论:**`;无竖线;表头底色可辨;状态只染单元格/行首,不整行铺色 | 原文 + 截图 |
|
|
61
|
+
| R4 状态 | ✅/⚠️/❌ 字形保留;色不是唯一语义;状态文字对比度 ≥4.5:1 | DOM 取色;无 DevTools 时目检并标未验证 |
|
|
62
|
+
| R5 代码 | banner 与代码体贴合;语言点色正确;复制控件可见不压字;长行(>120 字符)不裁切 | 截图 |
|
|
63
|
+
| R6 布局 | 1440 与 800 宽均无页面级横向滚动;卡片不出界;表格要么自适应要么容器内滚动 | 截图 + `scrollWidth` |
|
|
64
|
+
| R7 主题 | 明/暗下卡片边界、表头、代码块、状态色都可辨;无写死白底 | 明暗成对截图 |
|
|
65
|
+
| R8 隔离 | `dsh-ui` 区域内无 `data-dsh-structured-*`;`<html data-dsh-structured="active">`;控制台 0 error | DOM + 控制台 |
|
|
66
|
+
|
|
67
|
+
### 3.2 契约门(未达记 S2)
|
|
68
|
+
|
|
69
|
+
| 门 | 判据 | 门槛 |
|
|
70
|
+
| --- | --- | --- |
|
|
71
|
+
| C1 首屏主卡 | 回复第一块就是卡(P06 豁免) | ≥9/11(82%) |
|
|
72
|
+
| C2 表格前导 | 凡 ≥2 行表格,前一行有 `**表格结论:**` | 100% |
|
|
73
|
+
| C3 状态符号 | 凡状态行/状态表,保留 ✅/⚠️/❌ | 100% |
|
|
74
|
+
| C4 代码语言 | 凡围栏代码块,有语言标签 | 100% |
|
|
75
|
+
| C5 短答克制 | P06:0 卡、0 表、≤2 句 | 1/1 |
|
|
76
|
+
| C6 长度 | 去代码块、表格行、卡片标签行后的可见字符 ≤500(P08/P09 豁免) | 100% |
|
|
77
|
+
|
|
78
|
+
> 目标组件命中率(实际出现的卡型是否等于期望)只**报告**,不单独判失败;低于 8/12 时复盘 prompt 与注入契约,不要直接改 CSS。
|
|
79
|
+
|
|
80
|
+
### 3.3 判定
|
|
81
|
+
|
|
82
|
+
- **PASS**:R1–R8 全部适用用例通过,C1–C6 全达,无 S1。
|
|
83
|
+
- **PASS WITH DEFECTS**:R 全过,C 差 1–2 项,只有 S2/S3。
|
|
84
|
+
- **FAIL**:任一 R 失败,或 C1 < 9/11。
|
|
85
|
+
|
|
86
|
+
## 4. 执行协议
|
|
87
|
+
|
|
88
|
+
### 4.1 固定条件
|
|
89
|
+
|
|
90
|
+
- 版本:0.7.3(与 `package.json` 一致);若 desktop 已升级,先记录实际版本再跑。
|
|
91
|
+
- 窗口 1440×900、缩放 100%;窄屏组改 800×900。
|
|
92
|
+
- 同一模型;从输入框模型名抄进报告,不猜。
|
|
93
|
+
- 每条 prompt **新开会话**,不在同一会话连发;避免上下文影响首屏。
|
|
94
|
+
- 跑前 `/structured status`,记录开关、style.md、GenUI 检测三项。
|
|
95
|
+
|
|
96
|
+
### 4.2 单条流程
|
|
97
|
+
|
|
98
|
+
1. 新建会话,原样粘贴 prompt,等流式结束、工具卡折叠。
|
|
99
|
+
2. 把**这条回复的顶部**滚到视口顶部(不是页面顶部),不再滚动。
|
|
100
|
+
3. 截 `pNN-light.png`;需要时切暗色/窄屏重截。
|
|
101
|
+
4. 从会话 JSONL 的 `final.text` 取原文,供文本门与字数统计。
|
|
102
|
+
5. 在计分表填 `P/F/–`(– 表示该门不适用)。
|
|
103
|
+
|
|
104
|
+
### 4.3 截图预算(24 张)
|
|
105
|
+
|
|
106
|
+
| 组 | 用例 | 数量 |
|
|
107
|
+
| --- | --- | --- |
|
|
108
|
+
| 明色主图 | 全 12 条 | 12 |
|
|
109
|
+
| 暗色对照 | P01 P03 P07 P08 P09 P11 | 6 |
|
|
110
|
+
| 窄屏 800 | P08 P11 P12 | 3 |
|
|
111
|
+
| 插件前基线 | P01 P03 P08(无插件 profile) | 3 |
|
|
112
|
+
|
|
113
|
+
命名:`artifacts/visual-<YYYYMMDD-HHMM>/p01-pnpm-light.png`,同目录放 `scorecard.md`。
|
|
114
|
+
|
|
115
|
+
> 基线必须是**没装本插件**的 profile:只执行 `/structured off` 仍有 CSS,测到的是生成差异,不是视觉差异。没有干净 profile 就把基线记 `N/A`,不要伪造。
|
|
116
|
+
|
|
117
|
+
## 5. 计分表
|
|
118
|
+
|
|
119
|
+
```markdown
|
|
120
|
+
# 视觉验收 <YYYY-MM-DD> · dsh-structured <version>
|
|
121
|
+
模型:<composer 显示名> · 窗口:1440/800 · 主题:light/dark · GenUI:on/off
|
|
122
|
+
结论:PASS / PASS WITH DEFECTS / FAIL
|
|
123
|
+
|
|
124
|
+
| # | 目标视觉 | 适用门 | 结果 | 缺陷 |
|
|
125
|
+
| --- | --- | --- | --- | --- |
|
|
126
|
+
| P01 | 判断卡 + 表 | R1 R2 R3 R6 C1 C2 C6 | | |
|
|
127
|
+
| P02 | 指标卡 | R1 R2 R6 C1 C6 | | |
|
|
128
|
+
| P03 | 风险卡 | R1 R2 R7 C1 C6 | | |
|
|
129
|
+
| P04 | 下一步卡 | R1 R2 C1 C6 | | |
|
|
130
|
+
| P05 | 验收卡 | R1 R2 R7 C1 C3 C6 | | |
|
|
131
|
+
| P06 | 短答负控 | R2 R6 C5 | | |
|
|
132
|
+
| P07 | 状态表 | R1 R3 R4 R7 C1 C2 C3 C6 | | |
|
|
133
|
+
| P08 | 长表 | R3 R6 R7 C1 C2 | | |
|
|
134
|
+
| P09 | 代码块 | R5 R6 R7 C1 C4 | | |
|
|
135
|
+
| P10 | 步骤 | R2 R6 C1 C6 | | |
|
|
136
|
+
| P11 | 宽表/窄屏 | R1 R3 R6 C1 C2 C6 | | |
|
|
137
|
+
| P12 | GenUI 隔离 | R8 R6 C1 C6 | | |
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## 6. 前后对照与阅读效率
|
|
141
|
+
|
|
142
|
+
结构增量在这批短问题上可能本来就是 0(`docs/METRICS.md` 已披露同 prompt 配对为 0)。所以对照看**视觉增量**:
|
|
143
|
+
|
|
144
|
+
| 指标 | 基线(无插件,预期) | 目标 |
|
|
145
|
+
| --- | --- | --- |
|
|
146
|
+
| 卡壳(边框/图标/eyebrow) | 0/3 | 3/3 |
|
|
147
|
+
| 标题独立层级 | 0/3 | 3/3 |
|
|
148
|
+
| 表格前导有样式 | 0/3 | 3/3 |
|
|
149
|
+
| 状态行着色 | 0/3 | 3/3 |
|
|
150
|
+
| 首屏可扫读组件数(卡+表) | 记录 | ≥2 |
|
|
151
|
+
| 强调块数 | 记录 | ≤2 |
|
|
152
|
+
|
|
153
|
+
阅读效率只用**代理指标**:首卡字符距离、首屏组件数、强调块数、表格前导率。不测眼动、不计时,也不写“节省 X 秒”。
|
|
154
|
+
|
|
155
|
+
## 7. 缺陷与停止规则
|
|
156
|
+
|
|
157
|
+
| 级别 | 定义 | 处理 |
|
|
158
|
+
| --- | --- | --- |
|
|
159
|
+
| S1 | 渲染断裂:卡没样式、标题塌成正文、溢出/裁切、对比度不达标、GenUI 双渲染 | 停跑,修完重跑全套 |
|
|
160
|
+
| S2 | 契约未达:无卡、>2 卡、缺表格结论、缺状态符号、代码无语言、超 500 字 | 记录,修完只复跑相关用例 |
|
|
161
|
+
| S3 | 观感:间距、图标语义、色调偏差 | 记录,可延后 |
|
|
162
|
+
|
|
163
|
+
- 每个用例只按第一次结果计分。模型没按格式写,就是没写,不靠重跑刷到通过;诊断性重跑单独记,不计入分数。
|
|
164
|
+
- 同一道门在 2 个以上用例失败,停止全量跑,先修根因——否则后面 10 张截图都是废证据。
|
|
165
|
+
|
|
166
|
+
## 8. 跑之前必须确认的已知缺口
|
|
167
|
+
|
|
168
|
+
1. **卡标题层级**:0.7.3 起,one-p 首段由 16.5px/600 lead 兜底;首段带 `<strong>` 的 one-p 由 statement 兜底;R1 不再要求两个 `<p>`。
|
|
169
|
+
2. **GenUI 是否安装未知。** 以 `/structured status` 为准;未装时 P12 记 `N/A`,不能算通过,覆盖数写 11/12。
|
|
170
|
+
3. **DevTools 不一定可用。** desktop 是 Electron,若打不开控制台,R1/R4 退化为 200% 截图目检,R8 的控制台项记“未验证”,并在报告方法列写明,不要写成测量。
|
|
171
|
+
|
|
172
|
+
## 9. 附录:命令
|
|
173
|
+
|
|
174
|
+
截图(每条前改 `$name`):
|
|
175
|
+
|
|
176
|
+
```powershell
|
|
177
|
+
Add-Type -AssemblyName System.Windows.Forms,System.Drawing
|
|
178
|
+
$name = 'p01-pnpm-light' # 每条截图前改这里
|
|
179
|
+
$stamp = Get-Date -Format 'yyyyMMdd-HHmm'
|
|
180
|
+
$dir = Join-Path (Get-Location) "artifacts\visual-$stamp"
|
|
181
|
+
New-Item -ItemType Directory -Force -Path $dir | Out-Null
|
|
182
|
+
$b = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
|
|
183
|
+
$bmp = New-Object System.Drawing.Bitmap $b.Width, $b.Height
|
|
184
|
+
$g = [System.Drawing.Graphics]::FromImage($bmp)
|
|
185
|
+
$g.CopyFromScreen($b.Location, [System.Drawing.Point]::Empty, $b.Size)
|
|
186
|
+
$bmp.Save((Join-Path $dir "$name.png"), [System.Drawing.Imaging.ImageFormat]::Png)
|
|
187
|
+
$g.Dispose(); $bmp.Dispose()
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
文本门与散文率:
|
|
191
|
+
|
|
192
|
+
```powershell
|
|
193
|
+
node scripts/session-inspect.mjs --session <id> --replies --json
|
|
194
|
+
node scripts/measure-prose.mjs --sessions <12 个 id,逗号分隔> --json
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
DevTools 控制台自检(在最后一条回复渲染完后执行):
|
|
198
|
+
|
|
199
|
+
```js
|
|
200
|
+
(() => {
|
|
201
|
+
const roots = [...document.querySelectorAll('[class*="_markdown_"]')];
|
|
202
|
+
const root = roots[roots.length - 1];
|
|
203
|
+
if (!root) return { error: 'no markdown root' };
|
|
204
|
+
const cards = [...root.querySelectorAll('blockquote[data-dsh-structured-card="1"]')];
|
|
205
|
+
const px = (el) => (el ? getComputedStyle(el).fontSize : null);
|
|
206
|
+
return {
|
|
207
|
+
root: document.documentElement.getAttribute('data-dsh-structured'),
|
|
208
|
+
cards: cards.length,
|
|
209
|
+
detail: cards.map((card) => {
|
|
210
|
+
const ps = [...card.children].filter((el) => el.tagName === 'P');
|
|
211
|
+
return {
|
|
212
|
+
paragraphs: ps.length,
|
|
213
|
+
labelPx: px(card.querySelector('p:first-child > strong:first-child')),
|
|
214
|
+
titlePx: px(card.querySelector('p:nth-child(2) > strong')),
|
|
215
|
+
bodyPx: px(ps[ps.length - 1]),
|
|
216
|
+
};
|
|
217
|
+
}),
|
|
218
|
+
tableLead: root.querySelectorAll('[data-dsh-structured-lead="table"]').length,
|
|
219
|
+
statusTables: root.querySelectorAll('[data-dsh-structured-status-table="1"]').length,
|
|
220
|
+
codeLangs: [...root.querySelectorAll('[data-dsh-structured-lang]')].map((el) => el.getAttribute('data-dsh-structured-lang')),
|
|
221
|
+
docOverflow: document.documentElement.scrollWidth > window.innerWidth + 1,
|
|
222
|
+
};
|
|
223
|
+
})()
|
|
224
|
+
```
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# 视觉诊断:从“有结构”到“有视觉热点”
|
|
2
|
+
|
|
3
|
+
## 结论
|
|
4
|
+
|
|
5
|
+
当前输出不是没有结构,而是**没有唯一焦点**:H1、表格、蓝色提示卡、文件 diff 卡在抢注意力,主结论却是普通正文;强调色被 H2 左边条、表头、链接分摊,视觉上等于没有强调。修法不是再加装饰,而是建立一条**热点预算**:每条回复最多 1 个主结论卡 + 1 个行动/风险卡;表格只做证据,表格前必须有一句“表格结论”。
|
|
6
|
+
|
|
7
|
+
## 对截图的具体诊断
|
|
8
|
+
|
|
9
|
+
| 现象 | 问题 | 理论 |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| 主结论是普通正文,蓝色“它问的四件事”反而最抢眼 | 焦点错位:装饰块比结论更重 | 视觉层级 / 信号噪声比 |
|
|
12
|
+
| H1、H2、表头、链接都用同一强调蓝 | 强调色平摊,10% 强调变成 50% | 60-30-10 色彩法则 |
|
|
13
|
+
| 表格没有“表格结论”,读者要自己总结 | 证据与结论没有分组 | 格式塔「接近性 / 共同区域」 |
|
|
14
|
+
| 状态词 active / in-sync / gap 是普通文本 | 状态不可扫读,没有 chips/行底色 | 前注意加工 / F 型扫读 |
|
|
15
|
+
| 代码块语言 banner 像独立浮条 | banner 与代码体分离,形成两个对象 | 格式塔「接近性」 |
|
|
16
|
+
| H1 26px、H2 21px、正文 15px,但 H2 与 H1 差距小 | 层级靠字号不足,缺少 eyebrow/lead | 模数比例 / 字体层级 |
|
|
17
|
+
| 表格全边框、表头与正文对比弱 | 非数据墨水过多,表头不突出 | Tufte 数据墨水比 |
|
|
18
|
+
| 蓝色组件卡、文件 diff 卡与我们的 markdown 样式混在一起 | 来源不可辨,无法判断谁负责 | 可观测性 / 归属标记 |
|
|
19
|
+
|
|
20
|
+
## 设计理论映射
|
|
21
|
+
|
|
22
|
+
1. **视觉层级(Visual Hierarchy)**:每屏一个主焦点,2 个次级焦点,其余三级。主焦点用「结论卡」;次级用「风险/下一步」;表格、正文退到三级。
|
|
23
|
+
2. **格式塔(Gestalt)**:结论与证据用接近性/共同区域分组;代码 banner 与代码体必须贴合成一个对象;同一主题的内容间距小于不同主题。
|
|
24
|
+
3. **F 型扫读(Nielsen)**:左上先落结论卡;表格第一列做标签,关键行加底色;每段首句承载信息。
|
|
25
|
+
4. **数据墨水比(Tufte)**:表格去竖线、减边框、表头轻底色、斑马纹极淡;让数字和文字成为墨水主体。
|
|
26
|
+
5. **60-30-10 色彩**:60% 中性底、30% 次级灰、10% 强调色。强调色只给结论卡、关键数字、风险/成功状态,不给每个 H2。
|
|
27
|
+
6. **信号噪声比**:每条回复最多 2 个强调块、每段最多 1 个加粗重点;图标只给语义标题,不做装饰。
|
|
28
|
+
7. **字体模数**:15 → 18.5 → 23 → 28(约 1.25 比例);正文 1.6–1.75 行高,表格 13.5px,代码 13px;中文字距 0.01em。
|
|
29
|
+
8. **无障碍(WCAG AA)**:状态不能只靠颜色,必须同时有 ✅/⚠️/❌ 或文字标签;对比度 ≥4.5:1;`prefers-reduced-motion` 关闭动效。
|
|
30
|
+
|
|
31
|
+
## 热点预算(v0.3.1 的规则)
|
|
32
|
+
|
|
33
|
+
| 层级 | 元素 | 规则 |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| 主焦点 | `> **结论:** ...` | 每条回复 1 个,放第一段;客户端渲染成强调卡;不得再用普通段落重复 |
|
|
36
|
+
| 证据 | 表格 | 表格前一行 `**表格结论:** ...`;表头轻底色;状态行按 ✅/⚠️/❌ 着色;最多 5–7 行 |
|
|
37
|
+
| 行动 | `> **风险:**` / `> **下一步:**` / `> **验收:**` | 每条回复最多 1 个,颜色区分 warn/success/info |
|
|
38
|
+
| 状态 | 行首 ✅/⚠️/❌ | 行级浅底色;状态表整行着色;不单靠颜色,保留符号 |
|
|
39
|
+
| 其余 | 正文 / 列表 / 链接 | 中性色,不加第二个强调色 |
|
|
40
|
+
|
|
41
|
+
## 归属:哪些是插件,哪些是 GenUI
|
|
42
|
+
|
|
43
|
+
- **本插件**:只给原生 markdown 节点加 CSS/属性。可验证标记:`<html data-dsh-structured="active">`,节点上的 `data-dsh-structured-card/icon/tone/status/row/lang`;浏览器控制台 `[dsh-structured] visual layer active`。
|
|
44
|
+
- **GenUI**:只渲染 ` ```dsh-ui ` fence 成 React 组件;它有自己的 root/类名,不带 `data-dsh-structured-*`。
|
|
45
|
+
- 截图里的蓝色「它问的四件事」标题卡、底部「已编辑 2 个文件」diff 卡,形态上不是我们的 CSS(我们不创建标题卡/文件卡),更可能是 GenUI 或宿主工具呈现。要确认,复制该回复原文看是否含 ` ```dsh-ui ` fence,或看 DevTools 里是否有 `data-dsh-structured-*` 属性。
|
|
46
|
+
|
|
47
|
+
## 本次落地(0.3.1)
|
|
48
|
+
|
|
49
|
+
- host 规则:首段强制 `> **结论:**`;表格前 `**表格结论:**`;状态行 ✅/⚠️/❌;全文最多两个强调块。
|
|
50
|
+
- client:结论卡加强(4px 强调边 + 渐变 + 标签图标)、callout 标签图标、状态行/表格行着色、代码 banner 贴合、表格去竖线/表头轻底色、根标记 + console 日志。
|
|
51
|
+
- 验收:desktop 应用内下一条回复应看到 1 个结论卡 + 1 个表格结论 + 0–1 个行动卡;DevTools 里 `document.documentElement.dataset.dshStructured === 'active'`。
|
|
52
|
+
|
|
53
|
+
## 下一步
|
|
54
|
+
|
|
55
|
+
- P1:单一「工程蓝图」视觉定稿、关键数字高亮、明暗/密度回归;不做主题菜单。
|
|
56
|
+
- P2:代码块复制/行号、表格横向滚动与复制、标题锚点。
|
|
57
|
+
- P3:GenUI 软联动(检测到才加 `dsh-ui` 路由规则),不硬依赖。
|