dsh-ppt-studio 1.1.1 → 1.1.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/README.md +41 -18
- package/agent-presets/ppt/agent.cordis.yml +22 -15
- package/cordis.patch.yml +19 -14
- package/docs/01-/351/234/200/346/261/202/344/270/216/347/233/256/346/240/207.md +1 -1
- package/docs/02-/346/212/200/346/234/257/346/212/245/345/221/212.md +9 -5
- package/docs/03-/346/233/264/346/226/260/346/227/245/345/277/227.md +153 -0
- package/docs/05-/350/277/255/344/273/243/346/265/201/347/250/213.md +34 -3
- package/docs/06-/350/257/204/345/256/241/344/270/216/346/265/213/350/257/225.md +5 -3
- package/examples/fx/fx-pro/preview/04_pages_04_chart.html +1 -1
- package/examples/fx/fx-pro/preview/deck.html +1 -1
- package/examples/fx/fx-pro/preview/measured.json +1 -1
- package/examples/fx/fx-pro.pptx +0 -0
- package/examples/fx/seed.pptx +0 -0
- package/examples/fx/single.pptx +0 -0
- package/examples/fx/spliced.pptx +0 -0
- package/examples/smoke/imported/deck.yaml +6 -6
- package/examples/smoke/imported/import-styles.json +1 -33
- package/examples/smoke/imported/loss-audit.json +99 -0
- package/examples/smoke/imported/pages/slide_03.yaml +5 -36
- package/examples/smoke/imported/preview-rt/03_pages_slide_03.html +1 -1
- package/examples/smoke/imported/preview-rt/deck.html +1 -1
- package/examples/smoke/imported/preview-rt/layout.json +26 -78
- package/examples/smoke/imported/reference/previews/03.png +0 -0
- package/examples/smoke/imported/source.pptx +0 -0
- package/examples/smoke/out-smoke.pptx +0 -0
- package/examples/smoke/preview/03_pages_03_chart.html +1 -1
- package/examples/smoke/preview/deck.html +1 -1
- package/lib/capabilities.js +189 -0
- package/lib/commands.js +12 -11
- package/lib/home.js +32 -0
- package/lib/index.js +278 -112
- package/lib/office-qa.js +111 -0
- package/lib/pptd/export-pptx.js +203 -13
- package/lib/pptd/import-pptx.js +12 -0
- package/lib/pptd/loss-audit.js +363 -0
- package/lib/pptd/nativeChart.js +454 -0
- package/lib/pptd/schema.js +48 -1
- package/lib/pptd/svgCharts.js +180 -37
- package/lib/pptxPy.js +96 -11
- package/lib/preset-delivery.js +107 -9
- package/lib/preview-server.js +41 -16
- package/lib/router.js +3 -2
- package/lib/scaffold.js +1 -1
- package/lib/state.js +8 -6
- package/lib/templates.js +9 -6
- package/lib/tools.js +102 -25
- package/lib/verify.js +12 -1
- package/package.json +2 -1
- package/scripts/audit-manual-facts.mjs +4 -2
- package/scripts/e2e-1.0.mjs +2 -2
- package/scripts/fixtures/workflow-baseline.json +10 -10
- package/scripts/install.mjs +13 -11
- package/scripts/smoke.mjs +473 -66
- package/scripts/verify-loss-audit.mjs +245 -0
- package/scripts/verify-native-charts.mjs +529 -0
- package/scripts/verify-preset-scope.mjs +593 -0
- package/skills/ppt-studio-data/SKILL.md +5 -7
- package/skills/ppt-studio-manual/SKILL.md +2 -2
package/README.md
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
在 DeepSeek Harness 里说需求,它把 PPT 做出来:先定大纲和版式,再逐页制作,每页过一遍自动检查,最后交付一个能用 PowerPoint 打开、继续改的 `.pptx`。
|
|
4
4
|
|
|
5
|
-
当前版本 **1.1.
|
|
5
|
+
当前版本 **1.1.4**,安装包约 **890 kB**(1.0.3 及更早的版本是 35 MB,因为随包带着 4 套没人用过的导入模板,1.0.4 把它们删了)。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**隔离是默认的**:装好之后,这套能力**只出现在「PPT 工作室」预设里**,其他预设与"没装插件"完全一样(§1.6)。
|
|
8
|
+
新建会话时选「PPT 工作室」即可;预设提供的是"完整工作台"——人格 + 22 个工具 + `/ppt` 命令 + 4 本手册 + 工作流提示段。
|
|
8
9
|
|
|
9
10
|
---
|
|
10
11
|
|
|
@@ -60,13 +61,23 @@ dsh --profile web --dump-config # 组合树里应出现 ppt-studio 插件
|
|
|
60
61
|
### 1.4 升级 / 卸载
|
|
61
62
|
|
|
62
63
|
```powershell
|
|
63
|
-
#
|
|
64
|
-
dsh plugin --profile web add
|
|
64
|
+
# 升级:再跑一次同名命令即可(走 npm),不需要先卸载
|
|
65
|
+
dsh plugin --profile web add dsh-ppt-studio
|
|
66
|
+
# 桌面端:在「插件管理」里对 dsh-ppt-studio 重新安装 / 升级,然后重启应用
|
|
65
67
|
|
|
66
68
|
# 卸载
|
|
67
69
|
dsh plugin --profile web remove dsh-ppt-studio
|
|
68
70
|
```
|
|
69
71
|
|
|
72
|
+
> **刚发布的版本可能装不上(会静默装回旧版)**。宿主给 pnpm 带了供应链策略(`minimumReleaseAge`,实测窗口约 12 小时):
|
|
73
|
+
> 新版本在窗口期内**不是**合法候选,于是按名字安装会**静默解析回旧的成熟版本**(命令成功、无警告、界面却仍显示旧版本号)。
|
|
74
|
+
> 要第一时间用上刚发布的版本,两条路:
|
|
75
|
+
> 1. 用 `.tgz` 装(tarball 规格不经过 registry 版本解析):把 `dsh-ppt-studio-<版本>-….tgz` 放到一个**稳定目录**,
|
|
76
|
+
> 在插件管理里填它的绝对路径(**桌面端不要用 https 资产 URL**,会撞 `ERR_PNPM_MISSING_TARBALL_INTEGRITY`,见 §1.7);
|
|
77
|
+
> 2. 等窗口过去(约 12 小时)再按名字升级。
|
|
78
|
+
>
|
|
79
|
+
> 另外别把 tgz 装在会被清理的临时目录里(例如发版脚本的 `_artifacts/`):那条 `file:` 依赖一旦悬空,下次装依赖会直接失败。
|
|
80
|
+
|
|
70
81
|
从 v1.0.2 或更早升上来的注意一件事:那时的包名是 `@dsh-external/dsh-ppt-studio`。旧包会作为独立依赖留在 profile 里,和新包一起被挂载两次。先摘掉它:
|
|
71
82
|
|
|
72
83
|
```powershell
|
|
@@ -90,21 +101,26 @@ node D:\plugins\package\scripts\install.mjs
|
|
|
90
101
|
|
|
91
102
|
如果你已经在用 dsh-super-injector,在注入器环境里对解压目录(或源码目录)跑 `dev_inject_plugin` 也行,注入器负责建链接和重启恢复。
|
|
92
103
|
|
|
93
|
-
### 1.6
|
|
104
|
+
### 1.6 隔离:默认只有「PPT 工作室」能看到这些工具
|
|
105
|
+
|
|
106
|
+
**默认就是隔离的**:装完之后,**其他预设完全不受影响**——看不到 `ppt_*` 工具、看不到那 4 本手册,
|
|
107
|
+
也不会被注入任何 PPT 工作流提示段;只有在「PPT 工作室」预设里才有完整能力面(22 个工具 + `/ppt` + 4 本手册 + 工作流)。
|
|
108
|
+
要切换:新建会话时选「PPT 工作室」;已经开着的会话也可以直接切预设,工具会立刻出现。
|
|
94
109
|
|
|
95
|
-
|
|
110
|
+
怎么做到的(一句话):插件声明预设时,会给自己那份组合**追加一行自定位行**——内容是本包入口的**绝对 `file://` 地址**,
|
|
111
|
+
于是预设的常驻组合会把插件再挂一次,那一次的工具/技能/提示段全部注册在**预设作用域**里。
|
|
112
|
+
用绝对地址是必须的:预设里的行都在**注册表所在那一层**的路径下解析(那里既不是你的 profile、也不是预设目录),
|
|
113
|
+
所以裸包名/相对路径都解析不到、预设会被判 `broken`;而绝对 `file://` 不受这个基准影响,且每次启动按 `import.meta.url` 现算——升级换代不会陈旧。
|
|
96
114
|
|
|
97
|
-
|
|
98
|
-
所以隔离可以靠"预设目录里放一个链接 + 预设里写一行相对路径"实现;**0.1.7 把目录发现整个删掉了**
|
|
99
|
-
(上游原文:*the harness discovers no preset on disk*),预设改为向 `agentPresets` 注册表**声明**,
|
|
100
|
-
而预设里的每一行都要在**注册表所在那一层**的路径下解析——那里既不是你的 profile,也不是预设目录,
|
|
101
|
-
所以相对路径和包名都解析不到,预设会被判 `broken`,选择器里根本不会列出它。
|
|
115
|
+
**两条保证**:
|
|
102
116
|
|
|
103
|
-
|
|
104
|
-
|
|
117
|
+
- **一条命令安装不变**:`dsh plugin --profile web add dsh-ppt-studio`(桌面端在插件管理里填同一个包名),不需要任何额外开关。
|
|
118
|
+
- **不会"装了却没能力"**:如果预设声明失败、或这台部署根本没有预设注册表(`headless`/`sdk` 这类),
|
|
119
|
+
插件会**自动回落到全局能力面**并在日志里说明——功能完整,只是没隔离。真实状态可查:调一次 `ppt_state`,
|
|
120
|
+
看 `presetDelivery.isolation`(`preset` = 隔离生效 / `profile-fallback` = 已回落 / `profile` = 你显式关掉了隔离)。
|
|
105
121
|
|
|
106
|
-
|
|
107
|
-
|
|
122
|
+
**想回到"所有预设都能用"**(传统档):把 profile 里那行 `ppt-studio` 的 config 改成
|
|
123
|
+
`scope: profile`,或在 `cordis.patch.yml` 里显式写 `scope: 'profile'`。`install.mjs --isolate` 已无意义(隔离就是默认),保留只为兼容旧脚本。
|
|
108
124
|
|
|
109
125
|
### 1.7 桌面端(DeepSeek Harness 应用)
|
|
110
126
|
|
|
@@ -212,7 +228,7 @@ ppt_template_remove id=我的模板 # 删掉(只能删你自己
|
|
|
212
228
|
ppt_templates # 看清单:你的 + 随包的分别列出
|
|
213
229
|
```
|
|
214
230
|
|
|
215
|
-
你的模板库在 `~/.dsh/ppt-studio/templates
|
|
231
|
+
你的模板库在 `<DSH_HOME>/ppt-studio/templates/`(没设 `DSH_HOME` 时就是 `~/.dsh/ppt-studio/templates/`;Windows:`C:\Users\<你>\.dsh\ppt-studio\templates`)。它**不在插件包里**,所以升级插件不会丢;随包那 4 套是只读的,删不掉(删了升级也会回来,不如不删)。入库之后,你自己的模板和随包模板在清单里同等可选,而且按上面的政策,**你给的模板优先级最高**——要用它就直接说。
|
|
216
232
|
|
|
217
233
|
> **1.0.4 变更**:随包不再带 4 套"从真实 PPT 导入"的重型模板(实用毕业设计论文答辩、极简实用部门工作总结、深蓝质感论文答辩、简约商务)。它们合计 46.2 MB,占安装包 96%,实际从未被用过。想找回来:从 [v1.0.3 的资产](https://github.com/zbsph/dsh-ppt-studio/releases/tag/v1.0.3) 里取 `package/templates/<id>/`,或从 git 历史取 `git show v1.0.3:templates/<id>/...`(注意 `previews/` 是 Office 渲染产物,没进 git,只在资产里)。放回 `templates/` 就能用。
|
|
218
234
|
|
|
@@ -267,7 +283,11 @@ ppt_visual(pptx=<spliced 产物>, pages="15") # 抽查这页真实观
|
|
|
267
283
|
能。截图、实测、真渲染会自动降级并标注,HTML 预览和结构检查照常。交付说明里会写"未经视觉审阅"。
|
|
268
284
|
|
|
269
285
|
**图表支持哪些?**
|
|
270
|
-
bar / line / pie
|
|
286
|
+
bar / line / pie,**矢量拼绘**:我们在 pptx 里画的是**普通形状**(柱=矩形、折线=连接线+圆点、饼=按角度切分的饼形扇区),
|
|
287
|
+
**不是 PowerPoint 的图表对象**。所以成品里:移动/缩放/改色/改字号照常(它们就是形状),但**没有"编辑数据"**、不能切换图表类型,
|
|
288
|
+
改一个数字也不会让柱子高度或扇形角度跟着变(图形和文字是各自独立的对象)。
|
|
289
|
+
另外 `chart` 只画**图形本身**,分类名/数值/单位/图例要用文本元素自己写(DSL 里没有这些字段)——改了数字记得同时改形状或回来改 DSL 重导。
|
|
290
|
+
用 python-pptx 兜底引擎时图表是**原生可编辑图表**(带内嵌数据工作簿:PowerPoint 里能"编辑数据"、能换图表类型)——正好补上引擎 A 矢量图表不可改数据的短板。复杂图表也可以直接用图片或形状拼;引擎 A 要不要也改成原生图表,见 docs/04 的「原生图表」路线项。
|
|
271
291
|
|
|
272
292
|
**讲稿能进 pptx 吗?**
|
|
273
293
|
能。页面写 `notes:`(多行用 `|` 块标量),导出就成了 PowerPoint 备注页,`ppt_import` 也能读回来改。没写 `notes:` 的页不会产生备注部件,老工程导出结果不变。翻页和计时属于放映设置,不在插件范围内。
|
|
@@ -325,6 +345,9 @@ v1.0.0 修订前旧引擎的结构 bug(graphicFrame 里嵌了 `<a:xfrm>`,Pow
|
|
|
325
345
|
- line 只有两个点,多点折线要拆成首尾相接的多条。
|
|
326
346
|
- chart 支持 bar/line/pie;图表里的分类名、数值、单位、图例需要你自己用文本元素补上(DSL 里没有这些字段)。
|
|
327
347
|
- 背景支持 hex、主题引用、纯色、图片(cover/contain/fill)。
|
|
348
|
+
- 图片 `src` 是相对 deck 根的路径:`media/子目录/图.png`、中文或带空格的文件名都可以(预览会正确处理)。
|
|
349
|
+
两个**不同目录下的同名文件**也没问题——导出会自动给包内部件名加哈希避免互相覆盖(PPT 里的图片内容不受影响,导出输出里会说明改了什么)。
|
|
350
|
+
`src` 写 http(s) 网址时**只有预览能显示**,导出会写 1×1 白色占位并醒目警告(插件不联网取图)。
|
|
328
351
|
|
|
329
352
|
**这些不做,都有替代路径**:
|
|
330
353
|
|
|
@@ -439,7 +462,7 @@ ppt_visual # Office 真渲染复核(有 Office 时;audit
|
|
|
439
462
|
|
|
440
463
|
```bash
|
|
441
464
|
node scripts/build.mjs # 免 tsc:src → lib 复制(纯 ESM JS,源码即产物)
|
|
442
|
-
npm test # build + LF 守卫 + smoke(
|
|
465
|
+
npm test # build + LF 守卫 + smoke(303 断言)+ 预设漂移自检
|
|
443
466
|
npm run check:eol # 发行字节守卫:跟踪的文本文件必须全 LF(--fix 就地修)
|
|
444
467
|
npm run fresh # 用户视角终验:干净克隆 npm test + 真装一遍
|
|
445
468
|
npm run test:bundle # 安装路径自证:隔离 DSH_HOME + 真 dsh plugin add + dump-config
|
|
@@ -289,20 +289,27 @@
|
|
|
289
289
|
name: '@deepseek-ai/dsh-plugin-manager/tools'
|
|
290
290
|
disabled: true
|
|
291
291
|
|
|
292
|
-
# ──
|
|
292
|
+
# ── 本插件的"预设档"行**不写在这里**(2026-09-26 第四次修订)─────────────────────────────
|
|
293
293
|
# 本文件是「PPT 工作室」预设的组合真相:装配时由 lib/preset-delivery.js 声明给 agentPresets 注册表。
|
|
294
|
-
#
|
|
295
|
-
#
|
|
296
|
-
#
|
|
294
|
+
# 隔离靠**一行自定位行**实现,但那一行**由声明时程序化追加**(`preset-delivery.js` 的 `selfPresetRow()`):
|
|
295
|
+
# { id: 'ppt-studio-scope', name: 'file:///<本包绝对路径>/lib/index.js', config: { scope: 'preset', autoPreset: false } }
|
|
296
|
+
# 为什么不写死在 YAML 里:
|
|
297
|
+
# ① 写死就要在安装期把绝对路径填进来 ⇒ 换 profile/升级换代会陈旧;`import.meta.url` 现算永远是对的;
|
|
298
|
+
# ② 本文件的"不含插件行"是**被门禁断言**的(`scripts/verify-bundle-install.mjs` 断言预设组合里没有
|
|
299
|
+
# `ppt-studio` 插件行、`scripts/check-preset.mjs` 做逐行意图比对)——程序化追加让 YAML 保持干净,门禁全绿。
|
|
300
|
+
# 为什么必须是**绝对 file://**(而裸包名不行):
|
|
301
|
+
# 预设的行由注册表在**它自己 ctx 的 baseUrl** 下 mount(源码 `mountPreset(scope.ctx.extend({ baseUrl: record.context.baseUrl }), …)`,
|
|
302
|
+
# 而 `register()` 里 `context = this.ctx`)——那是 `dsh-web-app` 的包目录,**不是** profile、也不是预设目录
|
|
303
|
+
# ⇒ 裸包名 `dsh-ppt-studio` 解析不到 ⇒ 预设被判 `broken` ⇒ 前端选择器只渲染健康预设
|
|
304
|
+
# (`presetOptions() = presets.filter(p => p.broken === void 0)`)⇒ 用户根本选不到;
|
|
305
|
+
# 而 Loader 对**非 `.` 开头**的名字是**原样 `import(name)`** ⇒ `file://` 绝对名不查 baseUrl。
|
|
306
|
+
# (0.1.7-rc.2 上真宿主实测:工具 22/0、技能 4/0、提示段有/无、切换预设、负面对照,全过。)
|
|
297
307
|
#
|
|
298
|
-
#
|
|
299
|
-
# ①
|
|
300
|
-
#
|
|
301
|
-
#
|
|
302
|
-
#
|
|
303
|
-
#
|
|
304
|
-
#
|
|
305
|
-
|
|
306
|
-
# 结论:**默认(全局)装法**是本版本唯一受支持的装配路径(`scripts/install.mjs` 的默认分支,
|
|
307
|
-
# 也是 `dsh plugin add` 那一条)。真要"只在「PPT 工作室」里生效",得把插件行放进**预设声明本身**
|
|
308
|
-
# 并给它一个安装期算出的**绝对 `file://` 名字**——这块尚未实现,`--isolate` 会明确拒绝而不是静默失败。
|
|
308
|
+
# 历史沿革(两次"证伪"的正确结论,别再按旧结论行事):
|
|
309
|
+
# ① 2026-09-18 的"按 agent 动态门控"(`agent/created` 钩子 + 子层注册)**确实不可行** ——
|
|
310
|
+
# 空白会话切预设时 agent 已存在、钩子不会为它触发。但那只是"插件自己按 agent 门控"这一种写法;
|
|
311
|
+
# **预设行挂载**不经过 agent 生命周期:声明即挂载,切换预设时宿主把 agent 的 scope 父指针 `rebind`
|
|
312
|
+
# 到新代,可见性自动跟随。
|
|
313
|
+
# ② "技能分层 ⇒ 子层注册父层看不见"方向对、**但不是障碍**:技能读路径按"查看方 scope 的链"合并
|
|
314
|
+
# (含 agent 自己那一层)⇒ 注册进**预设作用域**正是技能能被该预设看到的**充要姿势**。
|
|
315
|
+
|
package/cordis.patch.yml
CHANGED
|
@@ -8,24 +8,29 @@
|
|
|
8
8
|
# `dsh plugin` 会在 profile 目录里跑 pnpm,然后核对 package.json 的 dsh.profile.bundles:
|
|
9
9
|
# **声明了 dsh.bundle.patch 的依赖自动入栈**(本文件即由 package.json 的 dsh.bundle.patch 指向)。
|
|
10
10
|
#
|
|
11
|
-
# 装配模型(2026-09-
|
|
12
|
-
# · 本行 = 把插件挂进 **profile
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
# `
|
|
24
|
-
#
|
|
11
|
+
# 装配模型(2026-09-26 **第四次修订:按预设隔离**)
|
|
12
|
+
# · 本行 = 把插件挂进 **profile 层**。`config.scope` 决定它的角色:
|
|
13
|
+
# - `auto`(缺省,= 本行现在写的值):声明「PPT 工作室」预设,并给它追加一行**自定位行**
|
|
14
|
+
# (本包入口的绝对 `file://`)⇒ 预设的常驻组合会再挂本包一次(`scope: 'preset'`),
|
|
15
|
+
# **那一次**把 22 个 `ppt_*` 工具 / `/ppt` 命令 / `ppt_state` / 4 本内嵌技能 / 语义路由 / 工作流提示段
|
|
16
|
+
# 全部注册在**预设作用域** ⇒ 只有「PPT 工作室」的会话看得到,**其他预设零影响**。
|
|
17
|
+
# 本档自己不注册任何能力面;只有判定隔离没生效时才**自动回落**到全局(功能不丢,只是没隔离)。
|
|
18
|
+
# - `profile`:传统档,一律全局(所有预设都能用)。想回到旧行为就改成这个。
|
|
19
|
+
# - `preset`:由自定位行使用,**不要**手工写进本行。
|
|
20
|
+
# 为什么"绝对 file://"是关键:预设里的每一行都在**注册表所在 ctx 的 baseUrl** 下解析
|
|
21
|
+
# (= harness 包目录,不是 profile、也不是预设目录)⇒ 裸包名/相对名解析不到 ⇒ 预设被判 broken
|
|
22
|
+
# ⇒ 前端选择器只渲染健康预设 ⇒ 用户根本选不到。绝对 URL 不受 baseUrl 影响,且每次启动按
|
|
23
|
+
# `import.meta.url` 现算,升级换代不会陈旧。(0.1.7-rc.2 上真宿主实测通过。)
|
|
24
|
+
# · 预设本身由插件**声明**:`ctx.agentPresets.register({id:'ppt', …plugins})`,随插件同生共死
|
|
25
|
+
# (卸载即注销)。0.1.6 及以前是"写到 `<dshHome>/.agent-presets/ppt/`"——那条发现路径在 0.1.7 已被上游删除。
|
|
26
|
+
# · 健康与降级:预设挂不上/无预设注册表时**自动回落全局能力面**;真实状态见 `ppt_state` 的
|
|
27
|
+
# `presetDelivery.isolation`(preset / profile-fallback / profile)。详见 README §1.6 与 docs/02。
|
|
25
28
|
- insert:
|
|
26
29
|
- id: ppt-studio
|
|
27
30
|
name: 'dsh-ppt-studio'
|
|
28
31
|
config:
|
|
32
|
+
# auto = 想隔离(缺省):声明预设 + 自定位行;不健康时自动回落全局。改 'profile' 可放弃隔离(传统档)。
|
|
33
|
+
scope: 'auto'
|
|
29
34
|
# 仅诊断用(插件日志打印 presetIds),**不再门控任何东西**——历史字段,保留以免改动既有装配行的形状
|
|
30
35
|
presetIds: ['ppt']
|
|
31
36
|
autoPreset: true
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
5. **样式只用 theme token**;**字号下限 = 用户指令**(2026-09-06 用户拍板:插件不设默认下限——用户给出最小字号 → 写入 theme.minFontSize 并严格执行,导出缩字不得低于它;未给下限不设强制,auto-fit 仅 60% 原字号防荒谬保底、绝不升字)。
|
|
49
49
|
6. **Aesthetic `[·]` 建议永远不是门禁**(用户要求审美改进不得引入冲突错误)。
|
|
50
50
|
7. 产物 = 中间层项目 + .pptx;`1px = 1pt`;尺寸默认 960×540。
|
|
51
|
-
8. 预设 = standard 全量 +
|
|
51
|
+
8. 预设 = standard 全量 + 本插件人格 + **自定位行**(声明时程序化追加,YAML 里不写)。装配**唯一**走 profile bundle(一条 npm 命令);预设由插件激活时向 `agentPresets` 注册表**声明**(2026-09-24 适配 DSH 0.1.7:宿主已删除磁盘预设目录发现)。**2026-09-26 第四次修订**:自定位行让插件以**预设作用域**再挂一次 ⇒ 工具/技能/提示段**只对该预设的会话可见、其他预设零影响**;预设声明失败或无预设注册表时自动回落全局(`scope: 'profile'` 可显式回到全局档)。
|
|
52
52
|
9. **内置制作技能按"介质"分派,且纯增量(2026-09-14 用户提出、当轮落地)**:
|
|
53
53
|
- 门禁类不可协商的规则 → 工作流铁律(`system-prompt/assemble` 注入);
|
|
54
54
|
- 版式配方 → 模板母版(机器可验证的几何),不写成散文;
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
├─ router.js 语义路由 + 工作流提示词注入(system-prompt/assemble)
|
|
13
13
|
├─ commands.js /ppt 命令面(档位/引擎/质量/pause-after)
|
|
14
14
|
├─ tools.js 模型工具面(ppt_check/render/shot/verify/export/import/status/media/schema/new/state/template_*/visual)
|
|
15
|
-
├─ state.js 会话级
|
|
15
|
+
├─ state.js 会话级 `<dshHome>/ppt-studio/session-<id>.json` + 项目级 state.json
|
|
16
16
|
├─ templates.js 模板库(双轨:YAML 骨架层 + template.pptx 真相层 + styleAudit)
|
|
17
17
|
├─ msrender.js Office 真渲染通道(PowerPoint COM → 整页 PNG;无 Office 自动隐藏)
|
|
18
18
|
├─ preview-server.js 对话内预览(webServer /ppt-preview 静态服务)
|
|
@@ -100,6 +100,7 @@
|
|
|
100
100
|
③ **包围盒精确等于线段跨度**:不能 `max(1,…)` 兜底,否则水平线 `cy=1pt` 会被画成"12pt×1pt 的对角线"=假斜线(`cy=0`/`cx=0` 合法,Office 自己也这么写);只有零长线给 1×1 兜底。
|
|
101
101
|
**自证**:`connectorEndsFromXml()` 从写出的 XML 反解端点并与源 `points` 逐条比对(<0.01pt),并断言 arrow=true 时 `tailEnd` 在 `a:ln` 内;
|
|
102
102
|
结果进 `report.parity.lines{Exp,Out,Wrong}`,`parity.ok` 同时要求表/图/线三项归零。这是"预览层对、成品层错"这类跨层不一致的机器防线。
|
|
103
|
+
**2026-09-26 补媒体 parity**:`mediaExp`(不同 `srcPath` 数)== `mediaOut`(包内 `ppt/media/` 部件数)并纳入 `ok`。起因是审计实测:不同目录下的**同名**媒体(`media/a/logo.png` + `media/b/logo.png`)按 basename 命名时会塌成同一个部件(后写覆盖先写)⇒ **成品里一张图被静默换成另一张**,而图数量 parity 依旧 N/N、`warnings=[]`、`mediaPlaceholders=[]` 全绿 —— 只有"媒体身份"这条判据抓得到。
|
|
103
104
|
- 页面背景:`p:bg` 原生(solidFill / blipFill + 媒体嵌入 + rels,v0.3 修复)。
|
|
104
105
|
- `out`:**绝对路径原样使用 / 相对路径相对 deck 目录**(E1)。
|
|
105
106
|
- **auto-fit 与下限**(E2 修复;2026-09-06 下限语义修订):只缩当 `overflowY > 1`(与 verify 同阈值)→ verify 通过 ⇒ 不缩字;**下限 = 用户指令**:`theme.minFontSize` 显式 → `min(原字号, 用户下限)`(绝不升字);未设置 → 无强制(60% 原字号防荒谬保底,最低 6pt);到下限仍溢出 → `floorHit: true` 进 report(工具输出 ✗ 警告,绝不静默)。
|
|
@@ -172,6 +173,7 @@
|
|
|
172
173
|
- 关键参数语义:
|
|
173
174
|
- `ppt_verify autoDeclare=true`:写声明 → 重新 load + render + verify,报告"已写入声明 + 剩余错误"。
|
|
174
175
|
- `ppt_verify pages="2,5-7"`(v0.14.6):局部校验——只在内存过滤 layout.pages(**不改写 layout.json**,防部分校验静默漏检其余页);`autoDeclare` 路径不支持 pages(声明必须整册)。
|
|
176
|
+
**2026-09-26 修"局部假绿"**:门禁行必须带审阅范围(`门禁(局部):✓ 选中的 N 页通过 —— 其余 M 页本次未检查`)。旧实现先过滤 `layout.pages` 再计数,于是"只审 1 页且其干净"会打印与整册通过**完全同形**的 `门禁:✓ 通过`——恰恰是这一段自述要防的"静默漏检",只是从文件搬到了报告里。同轮 `verifyDeck` **增量**返回 `errors/warns/suggestions`(每条带 `page/pageName`),`tools.js`/`templates.js` 不再反解文本(后者旧正则 `\[✗\] (\w+)` 会把 `out-of-page` 截成 `out`)。
|
|
175
177
|
- `ppt_export engine auto = pptd`(写死);`out` 支持绝对路径。
|
|
176
178
|
- `ppt_schema`(无参,输出 SCHEMA_REF 速查)/ `ppt_new(dir, name)`(scaffoldProject,已存在 deck.yaml 拒绝覆盖)。
|
|
177
179
|
- `shotOne`:每张截图独立临时 `--user-data-dir` + `--disk-cache-size=1`(修复过 Edge 缓存导致截图雷同)。
|
|
@@ -220,7 +222,8 @@
|
|
|
220
222
|
### 2.12 msrender.js / preview-server.js — Office 真渲染通道 + 对话内预览
|
|
221
223
|
- **msrender.js(v0.8.0)**:`findPowerPoint()`(POWERPNT.EXE 候选路径探测,无则 null → 通道自动隐藏);`renderPptxToPng(pptx, outDir, {width,height,timeoutMs})`——写 BOM ps1(Windows PowerShell 按 GBK 读无 BOM 文件会乱码中文路径)→ spawn powershell.exe -File → COM `Presentations.Open(只读)` + 逐页 `Slides.Item(i).Export(...,'PNG',1920,1080)` → 解析 `OK:<n>`;安全:只读打开、finally Quit、超时 SIGKILL 并清理残留 POWERPNT。
|
|
222
224
|
- **用途三点**:① 理解用户原稿(参考任务先看后做,工作流 6a)② 成品视觉审核(导出后审核真实观感,audit 档自动联动)③ 模板真相层整页(2.11)。
|
|
223
|
-
- **preview-server.js(v0.6.x)**:`buildPreview(dir)` → 预览根
|
|
225
|
+
- **preview-server.js(v0.6.x)**:`buildPreview(dir)` → 预览根 `<dshHome>/ppt-studio/preview/<token>/`(`DSH_HOME` 优先,缺省 `~/.dsh`;**2026-09-26 起改为调用时求值** —— 此前是模块常量、忽略 `DSH_HOME`,会让隔离部署与 `npm test` 写进真实家目录);pages/ + media/ 复制 + .meta.json 源映射;`registerPreviewRoute` 在 webServer 注册**无尾斜杠** prefix `/ppt-preview`(prefix 语义是前缀匹配,带尾斜杠永不命中);`resolveToken` 持久回退。
|
|
226
|
+
**2026-09-26 修两处(都是"预览坏、成品正常")**:① media 改用 `cp(recursive)` **整目录镜像** —— 旧实现只 `readdir` 顶层再逐个 `copyFile`,遇到 `media/子目录` 会把目录当文件拷,Windows 上直接 `EPERM: copyfile …`,`ppt_preview` **整体失败**(不是"缺图")且在预览根留下半成品;② 抽出并导出 `previewFileFor(root, rawRel)` —— 先 `decodeURIComponent`(浏览器把 `中文 图.png` 请求成 `%E4%B8%AD%E6%96%87%20…`,而 `new URL().pathname` 保留编码 ⇒ 旧实现 `existsSync` 必失败、图片明明已拷进预览根却 404),`..` 改为**按路径段**判定(不再误杀 `a..b.png` 这类合法文件名)。
|
|
224
227
|
- **`ctx.effect` 真语义与随之修正的两处(2026-09-14,真库探针实测)**:`ctx.effect(cb)` **立即执行 cb**,用 **cb 的返回值**作 disposer。
|
|
225
228
|
实测(`new Context()` + 探针):调用后立刻观察到 `cb-body-ran`,手动 dispose 后才 `returned-fn-ran`。
|
|
226
229
|
① 路由 refcount 原先把清理体写在 cb 体内 ⇒ 注册当刻 `count--` 并 `cancelled=true`,**文档承诺的"首个注册者真注册、最后卸载者真卸载"从未成立**(注册后立即被取消);已改为 cleanup 包在返回函数里。
|
|
@@ -408,13 +411,13 @@
|
|
|
408
411
|
2. **双轨审阅**:数字门禁(快、可全自动)+ 视觉审阅(截图、防估算漏报)。估算档被真实任务证明会骗过(第 6 页溢出截图才发现),视觉审阅因此是"必要"而非"可选"。
|
|
409
412
|
3. **声明制成本控制**:四个缓冲——`autoDeclare` 一键批量(重叠)、`declaredClosure` 嵌套闭包(相邻层声明隔层自动)、`overlapMode: lenient`(草稿)、`role: decoration`(装饰豁免重叠)+ `contrastExempt`(对比度误报豁免)。
|
|
410
413
|
4. **度量一致性**:三端共用 normalizePage + wrapLines;verify 的 TOL(1px) 与 export 的 FIT_TOL(1) 相同 ⇒ 门禁通过 = 导出不缩字 = 承诺兑现(14pt/12pt 下限)。
|
|
411
|
-
5. **引擎质量优先**:auto=pptd;python-pptx
|
|
414
|
+
5. **引擎质量优先**:auto=pptd;python-pptx 与 pptd 的保真差异是「透明度/渐变按纯色近似」,其图表反而是**原生可编辑图表**(带内嵌工作簿),仅显式切换 —— 与设计文档"自动回退链"存在 C1 冲突(待确认,见 01 文档)。
|
|
412
415
|
|
|
413
416
|
## 4. 验证矩阵(质量保障体系)
|
|
414
417
|
|
|
415
418
|
| 层 | 手段 | 触发点 | 覆盖 |
|
|
416
419
|
|---|---|---|---|
|
|
417
|
-
| L0 单测 | `scripts/smoke.mjs`(
|
|
420
|
+
| L0 单测 | `scripts/smoke.mjs`(303 断言) | 每次改动后 | schema/渲染/校验/导出/导入/媒体/背景/声明制(含闭包)/美学/Quick/引擎/样式回环/噪声过滤/**连线方向** |
|
|
418
421
|
| L1 真实回归 | `scripts/regression-real.mjs` | 每次改动后(有资产则跑) | 19 页产能 deck(0 错误 + 0 缩字)、WPS UTF-16 文件导入 |
|
|
419
422
|
| L2 数字门禁 | render→verify 逐页 | 每页制作后(工作流内) | overlap/出界/溢出/对齐 |
|
|
420
423
|
| L3 视觉审阅 | shot + read_image / **Office 真渲染 + read_image**(v0.8,有条件) | 每页/整体(工作流内) | 构图/断行/对比度/孤字(估算漏报兜底)/真实观感 |
|
|
@@ -426,7 +429,7 @@
|
|
|
426
429
|
## 5. 已知边界(诚实声明,README §已知边界 同步)
|
|
427
430
|
|
|
428
431
|
- 文本度量 = 估算档(保守系数);**实测档(渲染回读精确测量)为下一里程碑 R1**。
|
|
429
|
-
- chart 在 python-pptx
|
|
432
|
+
- chart 在 python-pptx 引擎下是**原生可编辑图表**(`ppt/charts/chartN.xml` + 内嵌数据工作簿,可"编辑数据");pptxgenjs 第三引擎未实现。
|
|
430
433
|
- 导入器不做布局逆推(内容保真、版式可从新);渐变/阴影/动画/超链接不支持。**模板双轨(v0.9)缓解**:模板类场景直接看真相层(template.pptx + previews 真渲染),不依赖导入近似;导入近似仅剩"从零改版"场景的参考价值。
|
|
431
434
|
- **模板参考通道依赖 Office**:无 Office 时真相层缺失 → 退化为 YAML 骨架 + styleAudit(如果有);收纳时无 Office 也不生成 previews/。
|
|
432
435
|
- client 端 dsh 网页内嵌预览面板未实现(设计 §8 已拍板形态,属里程碑 M4)。
|
|
@@ -479,5 +482,6 @@ docs/ 本档案库(00 设计源 / 01 需求目标 / 02 技术报告
|
|
|
479
482
|
- validatePage:**元素级 TEXT_STYLE_KEYS 报错**(样式必须在 content 内)+ YAML 解析错误附笔误提示。
|
|
480
483
|
- import:theme colors = 原稿**全量色板**(c1-7 高频 + c8 起扩展);媒体引用一致性自检(缺失 → 提示 + 1×1 占位)。
|
|
481
484
|
- export:缺失媒体占位兜底(mediaPlaceholders 进报告);msrender `renderPptxToPng({pages})` 按页 COM 渲染(png 文件名 = 原页号)。
|
|
485
|
+
- **媒体部件命名(2026-09-26)**:整册共享、按 `srcPath` 唯一 —— ASCII 且未被占用 ⇒ **原名不动**(既有工程产物逐字节不变);非 ASCII/空格或**重名** ⇒ `stem-<hash8>.<ext>`(hash 取相对路径,跨机器确定;`ppt/media/` 是包内部件名,用户看不到)。同一个名同时用于 rels Target 与包内条目;改名进 `report.mediaRenamed` 并在导出输出里**明说**(不静默)。
|
|
482
486
|
README.md 使用者入口(轻量,指向 docs/)
|
|
483
487
|
```
|
|
@@ -5,6 +5,147 @@
|
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
+
## [1.1.4] 2026-09-26 —— 三个批次:按预设隔离(默认)+ office 接入与兜底增强 + pptd 原生可编辑图表
|
|
9
|
+
|
|
10
|
+
> 本批按「发布列车」攒着:`package.json` 版本号与 tag 在发版那一步才推进(见 docs/05「发版节奏」)。
|
|
11
|
+
> 三个主目标各自走完整验证(smoke + 各自真机/真渲染自证),发版只是把三个**已验证批次**打包。
|
|
12
|
+
|
|
13
|
+
### 批次 A:按预设隔离(默认)—— 其他预设零影响
|
|
14
|
+
|
|
15
|
+
### 触发(用户原话)
|
|
16
|
+
"将插件里的所有 tools 和 skills 都限制为仅在「ppt 工作室」中启用,其他预设里看不到这些 skills 和 tools,就和没有安装插件的时候完全一样,不受影响。"
|
|
17
|
+
—— 并明确要求"做好隔离之后其他预设应该不会受到影响",**不要**任何全局兜底指引。
|
|
18
|
+
|
|
19
|
+
### 结论:可行(源码 + 真宿主实测)
|
|
20
|
+
两次历史"证伪"经复核都**不是"隔离不可行"**,而是实现姿势不对:
|
|
21
|
+
| 历史判据 | 复核结论 |
|
|
22
|
+
|---|---|
|
|
23
|
+
| ① `agent/created` 对已存在 agent 不触发 ⇒ 切预设拿不到工具 | 只对"**插件自己按 agent 动态门控**"成立。走**预设行挂载**不经过 agent 生命周期:声明即挂载,切换预设时宿主把 agent 的 scope 父指针 `rebind` 到新代,可见性自动跟随 |
|
|
24
|
+
| ② 技能注册表分层 ⇒ 子层注册父层看不见 ⇒ 技能永不出现 | 方向对但**不是障碍**:技能读路径按"查看方 scope 的链"合并(含 agent 自己那一层)⇒ 注册进**预设作用域**正是技能能被该预设看到的**充要姿势** |
|
|
25
|
+
| ③ "预设行挂载"被 baseUrl 封死(裸包名/相对名解析不到 ⇒ 预设 broken) | 只对**裸包名/相对名**成立;Loader 对非 `.` 开头的名字**原样 `import(name)`** ⇒ **绝对 `file://` 行不受 baseUrl 影响**——用 `import.meta.url` 现算本包入口即可,且升级换代不陈旧 |
|
|
26
|
+
|
|
27
|
+
### 改动
|
|
28
|
+
- `src/preset-delivery.js`:新增 `pluginEntryFile()` / `selfPresetRow()`(**自定位行**:`file://` 绝对入口 + `config.scope='preset'` + `autoPreset:false`);`presetDeclaration(dir, {selfRow})` 在末尾追加该行;`declareAgentPreset(ctx, config, hooks)` 新增 `hooks.onSettled(health)` 与 `notePresetStatus()`。
|
|
29
|
+
- `src/index.js`(第四次修订):`apply()` 按**作用域档**分两种——profile 档=全局管道 + 预设声明(含自定位行)+健康判定;**preset 档=22 工具 / `/ppt` 命令 / `ppt_state` / 4 本内嵌技能 / 语义路由 / 工作流提示段全部注册在预设作用域**。防重改为**按作用域**(profile 固定键;preset 按 ctx 身份发号,随释放回收)。健康判定用**挂载自证信号**(`globalThis.__pptScopeApplied`)而不是审计注册表——后者 docstring 明确警告"不得在宿主行自己的激活过程中调用"(会等整棵树落定 ⇒ 死锁风险)。**自动回落**三条触发点:声明失败/注册表不可见、声明成功但预设档实例未装配(400ms 宽限)、`inject` 回调始终不触发(3s 兜底超时——这条是实测中发现的**真漏洞**:无 `agentPresets` 的部署里 `inject` 回调根本不触发,只按 `onSettled` 判定会"装上了却零能力面")。
|
|
30
|
+
- `cordis.patch.yml`:插件行加 `scope: 'auto'`;装配模型注释重写。
|
|
31
|
+
- `agent-presets/ppt/agent.cordis.yml`:末尾"为什么没有插件行"那段重写为"自定位行由程序化追加"及其三条理由。
|
|
32
|
+
- `scripts/smoke.mjs` §40 整段重写(自定位行形状/入口存在性、缺省档 20 行、健康判定期间零能力面、自动回落、隔离生效零能力面、预设档全能力面且不声明预设、传统档 19 行、无注册表兜底超时回落、同作用域防重);§52 两处改用 `scope:'profile'`(那些用例测的是**管道韧性**,与隔离无关)。
|
|
33
|
+
- 文档:README §1.6 从"不支持隔离"改写为"隔离是默认"(含两条保证与回退方法);README §1 开头口径同步;docs/01、docs/05 装配纪律同步。
|
|
34
|
+
|
|
35
|
+
### 验证
|
|
36
|
+
- **真宿主隔离矩阵**(新增 `scripts/verify-preset-scope.mjs`:隔离 `DSH_HOME` + 真 `dsh --profile web` + 宿主自己的建会话配方,无需模型/凭据/浏览器):**24 通过 / 0 失败**。覆盖:预设健康(无 `broken`)|`agent@ppt` 工具 22 / `agent@standard` **0**|技能 4 / **0**|**提示段:ppt 含 `ppt-workflow`、standard 不含**|会话内切换 `standard→ppt` 后工具/技能/提示段全部到位|全局视图 `ppt_*` = 0(**零全局残留**)|负面对照(故意写错行 ⇒ `broken … never started`,且坏预设不影响好预设)。
|
|
37
|
+
- `npm test` = **285 通过 / 0 失败**(§40 重写;预设漂移自检 0)。
|
|
38
|
+
- 量化收益(权威测量:宿主 `Tool.listTools`):非 PPT 预设每次请求省下 **22 个工具 schema ≈3,789(字节/4)/ 4,426(CJK 口径)token** + 技能目录 ≈346/443 token ⇒ **≈4.1k–4.9k token**;「PPT 工作室」内能力面与提示词一字不减。
|
|
39
|
+
|
|
40
|
+
### 影响(**行为变更,请务必知道**)
|
|
41
|
+
- **装完默认只在该预设里可用**:其他预设看不到工具/技能/提示段(正是用户要求)。新建会话时选「PPT 工作室」;已开的会话可直接切预设,工具立刻出现。
|
|
42
|
+
- **"一条命令安装"不变**:`dsh plugin --profile web add dsh-ppt-studio`(桌面端插件管理里填同一包名),无任何安装期开关;升级换代不需要重写路径(自定位行每次启动现算)。
|
|
43
|
+
- **不会"装了却没能力"**:预设声明失败/无预设注册表 ⇒ 自动回落全局能力面(功能完整、只是没隔离),原因写进 `ppt_state` 的 `presetDelivery.isolation`。
|
|
44
|
+
- 想回到旧行为:`scope: 'profile'`(在 `cordis.patch.yml` 或 profile 的用户覆盖里改这一行)。
|
|
45
|
+
- **未做/未测**(如实记录):`/ppt` 命令面的预设可见性未测;**提示词文本零改动**(本轮只改"注入作用域",字节超集基线无需重建);`install.mjs --isolate` 的措辞仍待下一批同步。
|
|
46
|
+
|
|
47
|
+
### 批次 B:office 接入与兜底增强(兜底 ①②③④ + 启发 A/B/D + 提示词)
|
|
48
|
+
|
|
49
|
+
**背景**:桌面端多出三个官方技能 `office-docx/pptx/xlsx`(来自 npm 包 `dsh-skill-office`,由 `dsh-desktop-host` 程序化挂载,**web/headless/acp 出厂组合不挂**),它们假定"捆绑 Python + LibreOffice kit"。于是我们做两件事:**把兜底路径变强**、**先探测再说话**。
|
|
50
|
+
|
|
51
|
+
- **① 能力探测(新 `src/capabilities.js`)**:`resourcesFrom()` 逐级上溯(以 `app.asar` 为锚点)找 `<install>/resources`——桌面端里插件可能跑在深层子进程 node 中;`primaryRuntimeRoots()` 顺序 = env 缝 > 安装副本 `dsh-runtimes/dsh-primary-runtime` > carrier;`findBundledPython/BundledNode/LibreOfficeCli/OfficeAssets`、`findAnyPython`(check_office.py 只用标准库)。`ppt_state` 新增 `capabilities`(含 `officeSkills` 探测结果)与 `assembly`。
|
|
52
|
+
- **④ python-pptx 兜底优先用捆绑 Python**:`findPython()` 先探捆绑(自带 python-pptx/lxml/Pillow/XlsxWriter),再退 PATH(`python`/`py`/`python3`),且"能跑但缺库"的解释器不再挡住后面的候选;导出报告里带出 `interpreter/interpreterSource`。
|
|
53
|
+
- **② 官方 QA 通道(新 `src/office-qa.js`)**:`runOfficeStructureCheck()` 跑官方 `check_office.py`(ZIP/XML/rels 完整性 + 文本抽取 + `--contains/--count`),**每次导出**都给一行第三方结构自证(✅/✗/ℹ 三态,探不到就明说"未执行");`runLibreOfficeRender()` 让**没有 Office 的机器也能真渲染**(实测 kit 要求输出目录必须不存在,预建会撞 EEXIST),`ppt_visual` 在无 COM 时自动降级到它并标注"引擎不同、不能当逐像素等于 PowerPoint 的判据"+缺字诊断。
|
|
54
|
+
- **③ 兜底图表改原生**:`pptxPy.js` 的 chart 分支从"降级为表格"改为 python-pptx **原生图表**(bar/line/pie;单系列关图例、`vary_by_categories=False` 规避默认模板"按分类上色";饼图百分比标签;上色失败不拖垮导出)。实测三页图表 → chart 部件 6 / 内嵌工作簿 3 / python-pptx 读回 3 个 CHART 对象。
|
|
55
|
+
- **启发 A:成品内容自证**(`export-pptx.js` parity 新字段):`textExp/textMissing`(文本逐行 + 表格每格,按写盘同样的转义在产物 XML 里反查)与 `chartShapesExp/Out`——此前 parity **完全没数图表**,"预览对、成品丢字/漏格/图表没画"都抓不到。
|
|
56
|
+
- **启发 B:重建有损审计**(新 `src/pptd/loss-audit.js` + `ppt_import` 落盘 `loss-audit.json` + 工具输出一行):7 类(动画/阴影发光/超链接/切换/SmartArt/不可嵌入媒体/主题渐变),每处带页码与元素级证据;✓/⚠/ℹ 三档,**⚠ 命中即提示"只改某几页优先 `ppt_splice`"**。防误报是重点:空 `effectLst`、主题 `effectStyleLst`、形状渐变、可内嵌 png 都不计(自产 7 个产物回环 **0 命中**)。
|
|
57
|
+
- **启发 D + 纪律**:提示词第 13 条写明"就地手术优先"与"Excel 数字要么用 kit `recalculate` 重算、要么在交付说明标注未重算";引擎分工写明"**PPT 制作唯一通道 = pptd**,不要用 python-pptx/office-pptx 从零拼版绕过门禁,它们只适合读取既有 pptx 或兜底"。**提示词改动经用户批准并重建基线**(10 变体/225 行)。
|
|
58
|
+
|
|
59
|
+
**验证**:`npm test` = **303 通过 / 0 失败**(新增 §56×10:能力探测契约/候选顺序/解释器优先级/office 技能两态/resources 上溯合成树/官方 QA 三态 + §16b×4 损失审计);`node scripts/verify-loss-audit.mjs` **33/33**;`node scripts/e2e-1.0.mjs` **13/0**;`node scripts/audit-manual-facts.mjs` **39/0**。真机实测:`findPython()` 命中 `bundled:installed(dsh-runtimes)`;`check_office.py` 对我们自己的产物 `verdict=pass`(截断文件被独立抓住 `File is not a zip file`);LibreOffice kit 渲染出 `page-0001.png`+`manifest.json`(缺字诊断为空)。
|
|
60
|
+
|
|
61
|
+
### 批次 C:pptd **原生可编辑图表**(默认)
|
|
62
|
+
**触发**:用户对比实测后拍板——"图表"特指数据统计图,这里原生可编辑明显更优;其他绘图(布局/流程图/架构图)保持 pptd 现状(它们本来就是原生 OOXML 对象)。旧的矢量拼绘"看起来是图表但不是图表对象":没有"编辑数据"、不能换类型、改数字不重算、包里没有内嵌工作簿。
|
|
63
|
+
|
|
64
|
+
- **DSL(全可选有默认,旧 deck 不写 `render` 即默认 native)**:`chart.render: native|vector`、`legend: bool|top|bottom|left|right`、`labels: bool`、`axes: bool`;`render: vector` 与显式 `legend/labels/axes` 同时写会**报错**(不静默忽略,沿用既有纪律)。
|
|
65
|
+
- **部件生成(新 `src/pptd/nativeChart.js`)**:`ppt/charts/chartN.xml`(barChart/lineChart/pieChart + catAx/valAx + legend + dataLabels)、`_rels`、**内嵌数据工作簿** `ppt/embeddings/*.xlsx`(自写最小 xlsx:workbook + sheet + rels + Content_Types);slide 里 `p:graphicFrame` + `c:chart r:id`,rId 统一分配(媒体→讲稿→图表,不串号)。
|
|
66
|
+
- **预览与成品对齐**:`svgCharts.js` 抽出 `resolveChart()`(预览/导出**同一**图表模型),SVG 补画图例/轴线/刻度/网格/数据标签——旧版"预览画了刻度、成品却没有"的错位消除。
|
|
67
|
+
- **parity 扩展 8 字段**:`chartsExp/chartsOut`(声明数 == 包内部件数)、`chartEmbedsOut`、`chartSheetsChecked`、`chartDataMismatch`(解 `xl/worksheets/sheet1.xml`,网格与 deck **逐格**比对)、`chartRelsMissing`、`chartFramesMissing`、矢量路径仍用形状计数。
|
|
68
|
+
|
|
69
|
+
**验证**(`node scripts/verify-native-charts.mjs`,**PASS 51 / FAIL 0**):① 真实 **PowerPoint COM** 逐页渲染(并做像素统计确认图形画出来了);② **LibreOffice kit** 也能打开并渲染(兼容性);③ **python-pptx/openpyxl 独立反读**:`has_chart=true`、`chart_type` 与 DSL 一致、`series.values` 与 deck 一致、内嵌工作簿网格逐格一致;④ 官方 `check_office.py` 结构自证 pass;⑤ **三条负面对照**(改数值 / 删工作簿 / 删图表部件)全部按预期报红;⑥ "无图表工程新旧产物逐部件零变化"与"图片+图表+讲稿同页 rId 不串号"两条回归。smoke 里相应改为"默认产出图表部件 + 数据逐格一致"与"`render: vector` 仍走矢量拼绘"两条断言。
|
|
70
|
+
|
|
71
|
+
**兼容性**:`chart` 元素默认行为**变了**(旧 deck 不写 `render` 即 native);要旧观感请写 `render: vector`。**旧 deck 若当年为矢量图表手工补过分类名/数值文本框,改默认 native 后会出现"图表自带标签 + 你补的标签"并存**(真渲染实测可见)——这类既有工程建议保留 `render: vector`,或删掉手写标签。其余元素类型零改动。**诚实边界**:未用 UI 点过"编辑数据",自动化证据是完整关系链自证(graphicFrame→slide rels→chartN.xml→`c:externalData`→chart rels→内嵌 xlsx)+ 工作簿被独立阅读器读通。
|
|
72
|
+
|
|
73
|
+
## [并入 1.1.4] 2026-09-26 —— 用户目录口径统一(认 `DSH_HOME`)+ smoke 整轮隔离;附记宿主供应链策略与发版节奏
|
|
74
|
+
|
|
75
|
+
> 本批按新的「发布列车」攒着:`package.json` 版本号与 tag **在发版那一步才推进**(见 docs/05「发版节奏」)。
|
|
76
|
+
|
|
77
|
+
### 触发(用户原话)
|
|
78
|
+
"那我就等等吧。不过这样无法第一时间安装最新版是否会影响你的开发与测试?如果不会的话,就继续做1.1.3吧。同时我想问个问题:像现在这样过于频繁地发版是不是也会有些不好?我在想能不能平时的小更新就在本地一步步来,然后等攒够一波之后再统一发版(Github+npm包)?"
|
|
79
|
+
|
|
80
|
+
### 改动
|
|
81
|
+
- 新增 `src/home.js`:`dshHome()` = `DSH_HOME || homedir()/.dsh`、`pptStudioDir()` —— **全插件唯一的用户目录解析**,且**每次调用求值**(不是模块常量)。
|
|
82
|
+
- `src/state.js`、`src/preview-server.js`:会话状态与预览根由**模块常量**改为调用时求值(导出 `sessionDir()` / `previewRoot()`;旧常量 `SESSION_DIR` / `PREVIEW_ROOT` 经全库检索**无外部消费者**,已移除);`src/templates.js`、`src/index.js`(diag) 改用同一个 helper。
|
|
83
|
+
- `src/index.js`:`ppt_state` 增 `paths` 字段(`dshHome` / `pptStudio` / `sessionState` / `templates` / `preview`)——排查"各落在哪"不用猜。
|
|
84
|
+
- `scripts/smoke.mjs`:**整轮隔离**(开头把 `DSH_HOME` 指到 `examples/smoke/.tmp-home`,收尾恢复并清理);修掉三处"清理删错目标"(旧代码删的是**随包层** `TEMPLATES_DIR`,实际写进用户层的 smoke 模板从未被删掉);新增 §55 四条断言。
|
|
85
|
+
- 文档:README §1.4(升级章节补"刚发布装不上"的陷阱与两条解法)、§3(模板库路径注明 `DSH_HOME`);docs/05 新增「发版节奏(发布列车)」与"用户目录只有一个根"的纪律;docs/02 状态/预览路径描述改为认 `DSH_HOME`。
|
|
86
|
+
|
|
87
|
+
### 验证
|
|
88
|
+
- `npm test` = **280 通过 / 0 失败**(新增 §55×4);预设自检漂移 0。
|
|
89
|
+
- **隔离实证(本轮的核心验收)**:在 `DSH_HOME` 指向真实家目录的 shell 里跑 `npm test`,运行**前后**真实 `~/.dsh/ppt-studio` 均**不存在**(此前会留下 `templates/smoke-*` 与 `preview/<token>` 缓存——本机实测复现过并清理两次);仓库内也无 `.tmp-*` 残留。
|
|
90
|
+
- **真宿主验证**(隔离 `DSH_HOME` + 真 `dsh --profile web --port 0`):插件激活无"did not activate"警告,诊断 `debug.log` 落在**隔离** home 下,真实 home 下**没有**该文件。
|
|
91
|
+
- §55 覆盖:`dshHome()` 设/未设两种取值(未设回落 `~/.dsh`)、四个消费方同源、会话状态真写进当前 `DSH_HOME` 且真实家目录不出现该文件、整轮 smoke 处于隔离态。
|
|
92
|
+
- **兼容性(诚实标注)**:未设 `DSH_HOME` 时解析结果与旧行为**逐字节等价**(`homedir()/.dsh`)⇒ 普通用户零变化;
|
|
93
|
+
设了 `DSH_HOME` 的部署里,会话状态与预览会**移动到该 home 下**——旧 `~/.dsh` 下的会话标志不再被读取(会按语义路由重新判定),旧预览链接失效(`ppt_preview` 重新生成即可)。**不做静默迁移**。
|
|
94
|
+
|
|
95
|
+
### 附:本轮排查出的宿主行为(不是插件 bug,但会反复咬人)
|
|
96
|
+
DSH 调 pnpm 时带**发布年龄策略** `minimumReleaseAge`(实测窗口约 12 小时),且 profile 的 `pnpm-workspace.yaml` 里
|
|
97
|
+
`minimumReleaseAgeExclude` 只列着**当初装过的那个版本**(pnpm 首次安装时自动写入)。于是新版本发布后的窗口期内,
|
|
98
|
+
按名字安装会**静默解析回旧的成熟版本**(exit 0、无警告、界面仍显示旧版本号)。用桌面端自带的 pnpm 11.7.0 实测:
|
|
99
|
+
`add <包>` / `add <包>@latest` / `update <包>` / `remove`+`add` **全部回落**;可用路径只有两条 ——
|
|
100
|
+
① 用 `.tgz`(**本地绝对路径**;`https` 资产 URL 在桌面端会撞 `ERR_PNPM_MISSING_TARBALL_INTEGRITY`,见 README §1.7);
|
|
101
|
+
② 等窗口过去。已写进 README §1.4 与 docs/05「发版节奏」。
|
|
102
|
+
|
|
103
|
+
## [1.1.2] 2026-09-26 —— 媒体链路与成品对齐(同名静默错图 / 中文名预览 404 / 子目录预览崩)+ 局部审阅假绿 + `--page` 假承诺
|
|
104
|
+
|
|
105
|
+
### 触发(用户原话)
|
|
106
|
+
"既然你倾向B,那就按B来吧。"(承接上一轮"先审后改":用户要求先确认问题**真实存在**、再用不违背原目标的改法;本轮为方案 B 的第一批)
|
|
107
|
+
|
|
108
|
+
### 审计与证伪(全部只读;先审后改)
|
|
109
|
+
| 原怀疑 | 结论 |
|
|
110
|
+
|---|---|
|
|
111
|
+
| 门禁靠 `[✗]` 文本计数(元素 id 注入) | **原理由不成立**:`verify.js:472` 固定格式生成、message 无合法注入点(YAML 键不能含换行)⇒ 不拿它当理由;真问题是下面的"局部假绿" |
|
|
112
|
+
| 预览 media 不递归 | 成立,且**症状更重**:不是缺图,是 `EPERM: copyfile '<deck>\media\sub'` 让 `ppt_preview` **整体失败** |
|
|
113
|
+
| `/ppt fidelity --page` 空操作 | 成立:回执称"已记录",而 `<dir>/state.json` 的 `spec` 仍为 `{}`;页级字段在 DSL/state 里根本不存在 |
|
|
114
|
+
| `DSH_HOME` 口径分裂 | 成立(state/preview 是模块常量、templates/index 是调用时求值)⇒ 按方案 B **本轮不做**,挪到 1.1.3 |
|
|
115
|
+
| **新发现**:不同目录同名媒体 → 成品静默用错图 | 成立:2 张不同的图 ⇒ 包内仅 1 个 `ppt/media/logo.png`,而 `parity.ok=true`、`warnings=[]`、`mediaPlaceholders=[]` 全绿 |
|
|
116
|
+
| **新发现**:非 ASCII/空格文件名 → 预览 404 | 成立:图已拷进预览根,但请求路径 `%E4%B8%AD%E6%96%87%20…` 未解码 ⇒ `existsSync=false`(导出正常) |
|
|
117
|
+
| **新发现**:templates.js 错误码被 `\w+` 截断 | 成立(`out-of-page` → `out`) |
|
|
118
|
+
|
|
119
|
+
### 改动
|
|
120
|
+
- `src/pptd/export-pptx.js`:媒体部件名改为**整册共享、按 srcPath 唯一** —— ASCII 且未被占用 ⇒ **原名不动**(既有产物逐字节不变);非 ASCII/空格或**重名** ⇒ `stem-<hash8>.<ext>`(hash 取相对路径)。同一个名同时用于 rels Target 与包内条目;改名进 `report.mediaRenamed` 并在导出输出里**明说**。
|
|
121
|
+
- `src/pptd/export-pptx.js`:parity 增 `mediaExp/mediaOut`(不同 srcPath 数 == 包内媒体部件数)并计入 `ok` —— 这条才抓得到"两张图塌成一个部件"(图数量 parity 是 2/2,抓不到)。
|
|
122
|
+
- `src/preview-server.js`:media 改 `cp(recursive)` **整目录镜像**(修 EPERM 崩溃);抽出并导出 `previewFileFor()`:先 `decodeURIComponent`(修中文/空格 404),`..` 改为**先判后 normalize、按路径段**判定(不误杀 `a..b.png`,越级一律拒绝)。
|
|
123
|
+
- `src/verify.js`:`verifyDeck` **增量**返回 `errors/warns/suggestions`(每条带 `page/pageName`);`text/total/size` 与文本格式零变化。
|
|
124
|
+
- `src/tools.js`:门禁计数改用结构化 `v.errors.length`;`pages=` 局部审阅时门禁行改带范围;导出输出新增"媒体部件改名"提示与新 parity 字段。
|
|
125
|
+
- `src/templates.js`:收纳报告改用结构化错误码(修 `\w+` 截断)。
|
|
126
|
+
- `src/commands.js`:`/ppt fidelity --page` 改为**明确拒绝**(照 engine/pptxgenjs 先例);会话级回执如实标注"记录/展示用,当前不改门禁与流程"。
|
|
127
|
+
- 未改:**提示词零改动**(`router.js` workflowSection 不动 ⇒ 工作流基线无需重建)、任何门禁阈值/严格性、DSL schema 的既有字段语义。
|
|
128
|
+
|
|
129
|
+
### 验证
|
|
130
|
+
- `npm test` = **276 通过 / 0 失败**(新增 §54×6);预设自检漂移 0。
|
|
131
|
+
- §54 覆盖:同名媒体各占一个部件(4 部件、A 内容×3、B 内容×1、rels 与包内一一对应)/ASCII 名保持原名且改名仅 2 例/媒体 parity=4/4/预览子目录递归镜像 + 中文名可服务/`..` 与畸形编码被拦而 `a..b.png` 放行/真 `ppt_verify` handler 的局部门禁措辞(`门禁(局部):✓ 选中的 1 页通过 —— 其余 1 页**本次未检查**`)。
|
|
132
|
+
- **真消费者复核(P1 纪律:改 OOXML 部件名/rels 必须过真 PowerPoint)**:本机 `POWERPNT.EXE` COM 渲染成功(1920×1080 PNG),**读图确认左/中/右三张图内容各不相同**(左=小图 A、中=学术模板截图 B、右=中文名图 A)——修复前中间那张会与左边相同。渲染图落 `%TEMP%/ppt-office-*/rendered/01.png`(临时物,复核后即删)。
|
|
133
|
+
|
|
134
|
+
### 影响
|
|
135
|
+
- 修复前:不同目录同名媒体会在成品里**静默显示错图**(所有自证全绿);含 `media/子目录/` 的工程 `ppt_preview` 直接失败;中文/空格文件名预览 404 而导出正常。
|
|
136
|
+
- 兼容性:**普通工程(ASCII 唯一文件名)产物逐字节不变**;改名只发生在冲突/非 ASCII 时且**明说**;`verifyDeck` 的返回是纯增量(旧消费方零影响)。
|
|
137
|
+
- 未做(方案 B 第二批,1.1.3):`DSH_HOME` 口径统一 + smoke 全局隔离(含"`npm test` 会把 smoke 模板与预览缓存写进开发机真实 `~/.dsh/ppt-studio/`")。
|
|
138
|
+
|
|
139
|
+
### 发布结果(1.1.2,2026-09-26)
|
|
140
|
+
| 环节 | 实测 |
|
|
141
|
+
|---|---|
|
|
142
|
+
| 构件 | `dsh-ppt-studio-1.1.2-20260926-1555-93ba44f8.tgz`(sha256 `93ba44f8…`);`npm run sync` 三向一致 + 用户视角终验 9/0 + 安装路径自证 28/0 |
|
|
143
|
+
| CI 自动发布 | run [`36228252836`](https://github.com/zbsph/dsh-ppt-studio/actions/runs/36228252836) **success**(release 事件 → 等资产 → 取最新 → OIDC `npm publish` → 发后自证 integrity) |
|
|
144
|
+
| registry | `dsh-ppt-studio@1.1.2`、`latest = 1.1.2`、`fileCount 179`;`dist.integrity = sha512-YDAHDynC…`、`shasum 2464b146…` |
|
|
145
|
+
| 发布身份 | `_npmUser = {"name":"GitHub Actions","trustedPublisher":{"id":"github","oidcConfigId":"oidc:987851d7-…"}}` ⇒ 仍是 **Trusted Publishing(OIDC)**,零长期 token |
|
|
146
|
+
| provenance | `dist.attestations.provenance.predicateType = https://slsa.dev/provenance/v1` |
|
|
147
|
+
| 同字节 | registry 下载的 tarball sha256 `93ba44f8…` == 本地发版构件(逐字节相同) |
|
|
148
|
+
|
|
8
149
|
## [1.1.1] 2026-09-26 —— 修复桌面端激活失败(`webServer.register` 真契约 + 晚激活改走 `inject`);npm 定为默认安装通道
|
|
9
150
|
|
|
10
151
|
### 触发(用户原话)
|
|
@@ -47,6 +188,18 @@ ws.register(...).then is not a function at registerPreviewRoute
|
|
|
47
188
|
- 安装口径统一后用户只记一句话:**web** `dsh plugin --profile web add dsh-ppt-studio`;**桌面端**「插件管理」里填 `dsh-ppt-studio`。
|
|
48
189
|
- 版本:`package.json` → **1.1.1**(patch:修复 + 文档)。发布走上一轮建好的 OIDC 全自动通道(`release: published` → 下载 Release 资产 → `npm publish`),零手工、零长期 token。
|
|
49
190
|
|
|
191
|
+
### 发布结果(1.1.1,2026-09-26)—— 上一条建的 OIDC 通道首次真跑即成功
|
|
192
|
+
| 环节 | 实测 |
|
|
193
|
+
|---|---|
|
|
194
|
+
| 构件 | `dsh-ppt-studio-1.1.1-20260926-0551-412bff17.tgz`(sha256 `412bff17…`);`npm run sync` 三向一致 + 用户视角终验 9/0 + 安装路径自证 28/0 |
|
|
195
|
+
| CI 自动发布 | run [`36193791853`](https://github.com/zbsph/dsh-ppt-studio/actions/runs/36193791853) **success**:release 事件触发 → 等资产 → 取最新那条 → OIDC `npm publish` → 发后自证 `registry integrity == 本地 sha512` |
|
|
196
|
+
| registry | `dsh-ppt-studio@1.1.1`、`latest = 1.1.1`、`fileCount 179`;`dist.integrity = sha512-uwWnpKvP…`、`shasum 885e8e58…` |
|
|
197
|
+
| **发布身份** | `_npmUser = {"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:987851d7-…"}}` ⇒ **确证走的是 Trusted Publishing(OIDC),不是任何 token** |
|
|
198
|
+
| provenance | `dist.attestations.provenance.predicateType = https://slsa.dev/provenance/v1`(公开仓库 + 公开包 + OIDC ⇒ 自动生成,无需 `--provenance`) |
|
|
199
|
+
| 同字节 | 从 registry 下载的 tarball sha256 `412bff17…` == 本地发版构件(915,527 B) |
|
|
200
|
+
| 顺带确证 | 上一轮的悬案"信任关系是否放行 `npm publish`"**已确证放行**——否则这一步会以 `E_STAGE_REQUIRED` 失败(预检时只是"强烈提示") |
|
|
201
|
+
| 本机 | `npm run sync` 按文档流程把本版装进本机 **web** profile(依赖规格 = v1.1.1 资产 URL);**桌面端** profile 仍为 1.1.0(CLI 拒绝 `--profile desktop`,需在桌面端插件管理里重新安装/升级) |
|
|
202
|
+
|
|
50
203
|
## [发布通道 · npm 全自动] 2026-09-26 —— npm 已发布 1.1.0(逐字节核对);发布改走 Trusted Publishing(OIDC),发版零手工
|
|
51
204
|
|
|
52
205
|
### 触发(用户原话)
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
- 发布清单:smoke 全绿 → 真实回归全过 → README/SCHEMA_REF/更新日志同步 → **重启 DSH host 确认 active**(dev_reload_package 仅作补充,见步骤 7 已知缺陷)→ (未来)`dev_release_plugin` + npm pack。
|
|
35
35
|
- 运行时装配路径(勿动):profile `node_modules/dsh-ppt-studio`(**归 pnpm 管**,别手工建 junction);预设 = 插件激活时向 `agentPresets` 注册表**声明**(`lib/preset-delivery.js`),**不写磁盘预设目录**。
|
|
36
36
|
> **2026-09-24 更正**:上一版这里写的是"`C:\Users\11867\.dsh\.agent-presets\ppt\` = 唯一装配源"(1.0.1 隔离时代的记录)。
|
|
37
|
-
> DSH 0.1.7 起目录发现已被上游删除 →
|
|
37
|
+
> DSH 0.1.7 起目录发现已被上游删除 → 装法只有 **profile bundle(一条命令)**;隔离不靠安装开关,而靠插件**声明预设时追加的自定位行**(本包入口的绝对 `file://`)。见 README §1.6。
|
|
38
38
|
|
|
39
39
|
## 装配注意(2026-09-04 教训入库,v0.14.2)
|
|
40
40
|
- **本插件有两个装配源**:注入器 registry 恢复(host 启动)+ agent preset 插件行(agent 挂载)——同包可能装配两次(时序竞态曾导致 duplicate 路由崩溃)。
|
|
@@ -42,7 +42,10 @@
|
|
|
42
42
|
- 新资源注册一律 `ctx.effect`(清理即净)。
|
|
43
43
|
|
|
44
44
|
## 装配定论(2026-09-05 定;**2026-09-24 按 DSH 0.1.7 改判**)
|
|
45
|
-
- **装配源 = profile bundle 行(唯一)**:包的 `cordis.patch.yml`(`dsh.bundle.patch`)插入 `id: ppt-studio` 行 → profile
|
|
45
|
+
- **装配源 = profile bundle 行(唯一)**:包的 `cordis.patch.yml`(`dsh.bundle.patch`)插入 `id: ppt-studio` 行 → profile 级。
|
|
46
|
+
能力面**归属哪一层**由 `config.scope` 决定(2026-09-26 第四次修订):缺省 `auto` = 声明预设时追加**自定位行**
|
|
47
|
+
⇒ 插件以**预设作用域**再挂一次,能力面只在「PPT 工作室」预设里可见(**其他预设零影响**);`profile` = 传统档(全局);
|
|
48
|
+
`preset` 由自定位行使用,别手工写。健康与回落规则见 `src/index.js` 顶部与 README §1.6。
|
|
46
49
|
- **预设 = 注册表声明**(不是磁盘目录):插件激活时 `ctx.agentPresets.register({id:'ppt', …})`,`plugins` 取自包内 `agent-presets/ppt/agent.cordis.yml`。0.1.6 及以前"写 `<dshHome>/.agent-presets/ppt/`"的做法在 0.1.7 上**没有任何效果**(上游不再扫描目录),安装器会清理该历史目录。
|
|
47
50
|
- **注入器 registry 的 ppt-studio 记录已清除**(历史残留,来源:09-03 dev_inject_plugin 实验)——保证永不出现双源。历史 junction(`profiles/web/node_modules/@dsh-external/dsh-ppt-studio`)**不要保留**:包名已改无 scope,且 0.1.7 的装配不再需要任何 junction。
|
|
48
51
|
- **开发工具的现实约束**(注入器 0.3.4 起已诊断化):`dev_reload_package` / `dev_plugin_status` 只覆盖注入器 loader 域;bundle 行装配不在其中 → 改码 = 重启 host;`dev_build_plugin` 不再把 DSH_CHECKOUT 当构建前置(copy-only 插件无需 checkout;需要 tsc 的插件由其 build.sh 报明确错误)。
|
|
@@ -54,6 +57,11 @@
|
|
|
54
57
|
写进 profile 的 `dependencies` + `dsh.profile.bundles`)。目标口径是"**一句话无脑安装**"——用户不需要账号、不需要配 registry、
|
|
55
58
|
不需要知道资产 URL。GitHub Release 的 `.tgz` 资产与 `scripts/install*.mjs` 降级为**离线/归档备选**,
|
|
56
59
|
两条通道的字节由发布流程与 smoke 断言保证相同(README §1.2/§1.7 是用户版口径,答疑手册同步)。
|
|
60
|
+
- **用户目录只有一个根(2026-09-26 起)**:`src/home.js` 的 `dshHome()` = `DSH_HOME || ~/.dsh`,**每次调用求值**;
|
|
61
|
+
会话状态 / 预览根 / 用户模板层 / 诊断日志全部挂在 `<dshHome>/ppt-studio/` 下。
|
|
62
|
+
**别在任何模块里自己实现家目录解析**——此前 `state.js`/`preview-server.js` 写成模块常量、忽略 `DSH_HOME`,
|
|
63
|
+
后果是隔离部署里状态与预览逃出隔离目录、开发机跑 `npm test` 会写进**真实** `~/.dsh/ppt-studio/`;
|
|
64
|
+
smoke 现在整轮把 `DSH_HOME` 指向 `examples/smoke/.tmp-home`,收尾恢复并清理。`ppt_state` 的 `paths` 字段可直接看解析结果。
|
|
57
65
|
- **两条路径,二选一**:① `dsh plugin --profile <p> add <包>`(走包里的 `cordis.patch.yml`,**profile 级**);② `install.mjs` 写 agent preset 行(**会话级**)。
|
|
58
66
|
同时装 = 同进程挂两次 → 插件有**装配防重**(首个生效 + 告警)不会崩,但纪律是二选一(README §0.7)。
|
|
59
67
|
- **"能不能用标准姿势装"取决于包自己**:依赖必须声明 `dsh.bundle.patch`(且该文件在 `files` 里),否则 `dsh plugin add` 只装不挂、仅打一行警告。
|
|
@@ -104,7 +112,7 @@
|
|
|
104
112
|
想要会话级隔离就切后者(`dsh plugin --profile web remove <包>` → `node scripts/install.mjs` → 重启;README §10 有切换与回退命令),
|
|
105
113
|
日常迭代照旧 `--local`——它现在**两种挂载模式都自证**(非 bundle 走"穿过 junction 读到的字节")。
|
|
106
114
|
插件**无法**在 bundle 挂载下自己按预设过滤:注册发生在插件 `apply`(profile 级),要按预设隔离就得从预设组合里注册。
|
|
107
|
-
- 版本号:未获用户指示不改(当前 **1.1.
|
|
115
|
+
- 版本号:未获用户指示不改(当前 **1.1.4**;历史值见 docs/03);**资产名带构建时间 + 构建戳**(2026-09-15 起):`dsh-ppt-studio-<版本>-<YYYYMMDD-HHmm>-<sha256 前 8 位>.tgz`。
|
|
108
116
|
> 2026-09-18 改名说明:包名由 `@dsh-external/dsh-ppt-studio` 改为**无 scope** 的 `dsh-ppt-studio`(发布到 npm),
|
|
109
117
|
> 于是 `npm pack` 产出的资产名也从 `dsh-external-dsh-ppt-studio-…` 变成 `dsh-ppt-studio-…`;v1.0.2 及更早的资产仍在 Releases 页上(老用户重装不受影响)。
|
|
110
118
|
**时间段的用处**:老资产**不删**(已装用户靠它重装),页面上会并排多条名字近似者,sha 段看不出新旧 ⇒ 取时间最新那条即当前版本;发布日志里同时打印本轮的完整资产名。
|
|
@@ -129,6 +137,29 @@
|
|
|
129
137
|
- **能力边界**:仅支持云托管 runner(self-hosted 不支持);`npm whoami` 不反映 OIDC 状态;OIDC 只能跑 `npm publish` / `npm stage publish`,其它 stage 子命令与 `install`/`view`/`access` 仍需传统认证;npm CLI ≥ 11.5.1(OIDC)/ ≥ 11.15.0(stage 命令)、Node ≥ 22.14.0 ⇒ 工作流用 node 24 并带版本门禁。
|
|
130
138
|
- **两条已实测的运行期坑**(2026-09-26 两次预检跑,run `36189160940` / `36190325252`):① 工作流**不 checkout** 时 `gh` 会报 `fatal: not a git repository` ⇒ 必须给 job 级 `GH_REPO: ${{ github.repository }}`;② `actions/setup-node` 一旦传 `registry-url`,运行期会注入 `NPM_CONFIG_USERCONFIG` 与一个占位 `NODE_AUTH_TOKEN`(env 里可见)——**正是会顶掉 OIDC 的东西** ⇒ 不要传 `registry-url`,并在发布前 `unset NODE_AUTH_TOKEN` 兜底。两条都由 smoke §51 钉住。
|
|
131
139
|
|
|
140
|
+
## 发版节奏("发布列车",2026-09-26 用户提出后定)
|
|
141
|
+
|
|
142
|
+
> 用户原话:"像现在这样过于频繁地发版是不是也会有些不好?我想能不能平时的小更新就在本地一步步来,然后等攒够一波之后再统一发版(GitHub + npm 包)?"
|
|
143
|
+
> 结论:**对,改成列车**。发版本身就是"把一个批次交给所有用户"的动作,不是开发循环的一部分。
|
|
144
|
+
|
|
145
|
+
- **默认不发版**:平时一律 `npm run sync -- --local`(本机跑刚构建的字节,不上 GitHub、不动 npm)。
|
|
146
|
+
开发与测试**都不经过 registry**(`npm test` 跑仓库构建与断言、`--local` 用本地 `file:` 规格),
|
|
147
|
+
所以宿主的供应链策略(见下)**不影响我们的迭代速度**;它只影响"用户按名字装刚发布的版本"。
|
|
148
|
+
- **攒够一波再发**:一批 = 1 个主目标 + ≤3 个小修(与"一次迭代"同粒度)。
|
|
149
|
+
上限建议:不超过 ~2 周的改动量或 1 个主目标——攒太大,单次发布的 diff 与真机终验覆盖面会失衡。
|
|
150
|
+
- **三条"必须发"的信号**(任一):① 有用户"拿不到就受影响"的修复(如 1.1.1 的桌面端激活失败);
|
|
151
|
+
② 一批目标全部验证通过且文档同步完;③ 用户明确说"发"。
|
|
152
|
+
- **发一次的固定开销**(所以别频繁发):`git push` + `gh release create --target HEAD` + `npm run sync`
|
|
153
|
+
(构建 / 上传 / 三向字节自检 / 干净克隆终验)+ CI OIDC 发布 + 文档链同步(01/02/03/README/SCHEMA_REF + 计数自证)
|
|
154
|
+
+ 版本号推进(**npm 版本不可覆盖、错了不可重发**,这是频繁发版最贵的风险)。
|
|
155
|
+
- **副作用(2026-09-26 实测)**:宿主给 pnpm 带 `minimumReleaseAge`(实测窗口约 12 小时),
|
|
156
|
+
且 profile 的 `pnpm-workspace.yaml` 里 `minimumReleaseAgeExclude` 只列了当初装过的那个版本
|
|
157
|
+
⇒ **窗口期内按名字安装会静默解析回旧的成熟版本**(命令成功、无警告、界面仍显示旧版本号)。
|
|
158
|
+
要第一时间用上刚发布的版本:用 `.tgz`(本地绝对路径;`https` 资产 URL 在桌面端会撞 `ERR_PNPM_MISSING_TARBALL_INTEGRITY`)
|
|
159
|
+
或等窗口过去。**发版当天就要在发布说明里写明这一点。**
|
|
160
|
+
- **未发版的批次怎么记**:docs/03 用 `## [<版本> · 待发]` 记录本批改动;`package.json` 的版本号与 tag
|
|
161
|
+
**在发版那一步才推进**(保持"仓库里累积、发版时才认领版本号")。
|
|
162
|
+
|
|
132
163
|
## 宿主升级纪律(DSH 换版本时必做,2026-09-12 起)
|
|
133
164
|
|
|
134
165
|
- **先确认版本再动手**:`dsh --version` + `npm view @deepseek-ai/dsh dist-tags`(`latest` 与 `next` 可能不同;本机基线写进 README §0.1 与 package.json 的 peer 范围)。
|