dsh-ppt-studio 1.1.0

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.
Files changed (179) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +480 -0
  3. package/agent-presets/ppt/agent.cordis.yml +308 -0
  4. package/agent-presets/ppt/preset.yml +3 -0
  5. package/cordis.patch.yml +29 -0
  6. package/docs/00-/350/256/276/350/256/241/346/272/220.md +537 -0
  7. package/docs/01-/351/234/200/346/261/202/344/270/216/347/233/256/346/240/207.md +136 -0
  8. package/docs/02-/346/212/200/346/234/257/346/212/245/345/221/212.md +483 -0
  9. package/docs/03-/346/233/264/346/226/260/346/227/245/345/277/227.md +2898 -0
  10. package/docs/04-/350/267/257/347/272/277/345/233/276/344/270/216/351/207/214/347/250/213/347/242/221.md +113 -0
  11. package/docs/05-/350/277/255/344/273/243/346/265/201/347/250/213.md +210 -0
  12. package/docs/06-/350/257/204/345/256/241/344/270/216/346/265/213/350/257/225.md +296 -0
  13. package/docs/fidelity-report.md +225 -0
  14. package/examples/fx/fx-mini/deck.yaml +39 -0
  15. package/examples/fx/fx-mini/pages/01.yaml +6 -0
  16. package/examples/fx/fx-mini/pages/02.yaml +2 -0
  17. package/examples/fx/fx-mini/pages/03.yaml +6 -0
  18. package/examples/fx/fx-pro/deck.yaml +48 -0
  19. package/examples/fx/fx-pro/pages/01_cover.yaml +40 -0
  20. package/examples/fx/fx-pro/pages/02_arch.yaml +55 -0
  21. package/examples/fx/fx-pro/pages/03_table.yaml +20 -0
  22. package/examples/fx/fx-pro/pages/04_chart.yaml +40 -0
  23. package/examples/fx/fx-pro/pages/05_timeline.yaml +71 -0
  24. package/examples/fx/fx-pro/pages/06_longtext.yaml +13 -0
  25. package/examples/fx/fx-pro/pages/07_safearea.yaml +33 -0
  26. package/examples/fx/fx-pro/pages/08_contrast.yaml +22 -0
  27. package/examples/fx/fx-pro/pages/09_custgeom.yaml +32 -0
  28. package/examples/fx/fx-pro/pages/10_numbers.yaml +25 -0
  29. package/examples/fx/fx-pro/pages/11_section.yaml +20 -0
  30. package/examples/fx/fx-pro/pages/12_summary.yaml +57 -0
  31. package/examples/fx/fx-pro/preview/01_pages_01_cover.html +1 -0
  32. package/examples/fx/fx-pro/preview/02_pages_02_arch.html +3 -0
  33. package/examples/fx/fx-pro/preview/03_pages_03_table.html +1 -0
  34. package/examples/fx/fx-pro/preview/04_pages_04_chart.html +3 -0
  35. package/examples/fx/fx-pro/preview/05_pages_05_timeline.html +2 -0
  36. package/examples/fx/fx-pro/preview/06_pages_06_longtext.html +4 -0
  37. package/examples/fx/fx-pro/preview/07_pages_07_safearea.html +2 -0
  38. package/examples/fx/fx-pro/preview/08_pages_08_contrast.html +1 -0
  39. package/examples/fx/fx-pro/preview/09_pages_09_custgeom.html +1 -0
  40. package/examples/fx/fx-pro/preview/10_pages_10_numbers.html +1 -0
  41. package/examples/fx/fx-pro/preview/11_pages_11_section.html +1 -0
  42. package/examples/fx/fx-pro/preview/12_pages_12_summary.html +1 -0
  43. package/examples/fx/fx-pro/preview/deck.html +10 -0
  44. package/examples/fx/fx-pro/preview/layout.json +2325 -0
  45. package/examples/fx/fx-pro/preview/measured.json +814 -0
  46. package/examples/fx/fx-pro.pptx +0 -0
  47. package/examples/fx/ren-single/01.png +0 -0
  48. package/examples/fx/ren-spliced/01.png +0 -0
  49. package/examples/fx/ren-spliced/03.png +0 -0
  50. package/examples/fx/seed.pptx +0 -0
  51. package/examples/fx/single.pptx +0 -0
  52. package/examples/fx/spliced.pptx +0 -0
  53. package/examples/smoke/deck.yaml +26 -0
  54. package/examples/smoke/imported/deck.yaml +30 -0
  55. package/examples/smoke/imported/import-styles.json +126 -0
  56. package/examples/smoke/imported/pages/slide_01.yaml +31 -0
  57. package/examples/smoke/imported/pages/slide_02.yaml +38 -0
  58. package/examples/smoke/imported/pages/slide_03.yaml +55 -0
  59. package/examples/smoke/imported/preview-rt/01_pages_slide_01.html +1 -0
  60. package/examples/smoke/imported/preview-rt/02_pages_slide_02.html +1 -0
  61. package/examples/smoke/imported/preview-rt/03_pages_slide_03.html +1 -0
  62. package/examples/smoke/imported/preview-rt/deck.html +1 -0
  63. package/examples/smoke/imported/preview-rt/layout.json +434 -0
  64. package/examples/smoke/imported/reference/previews/01.png +0 -0
  65. package/examples/smoke/imported/reference/previews/02.png +0 -0
  66. package/examples/smoke/imported/reference/previews/03.png +0 -0
  67. package/examples/smoke/imported/source.pptx +0 -0
  68. package/examples/smoke/media-test.png +0 -0
  69. package/examples/smoke/out-smoke.pptx +0 -0
  70. package/examples/smoke/pages/01_cover.yaml +27 -0
  71. package/examples/smoke/pages/02_content.yaml +42 -0
  72. package/examples/smoke/pages/03_chart.yaml +35 -0
  73. package/examples/smoke/preview/01_pages_01_cover.html +1 -0
  74. package/examples/smoke/preview/02_pages_02_content.html +1 -0
  75. package/examples/smoke/preview/03_pages_03_chart.html +1 -0
  76. package/examples/smoke/preview/deck.html +1 -0
  77. package/examples/smoke/preview/layout.json +378 -0
  78. package/lib/autodeclare.js +40 -0
  79. package/lib/commands.js +161 -0
  80. package/lib/crosscheck.js +300 -0
  81. package/lib/imgmeta.js +55 -0
  82. package/lib/index.js +239 -0
  83. package/lib/measurement.js +209 -0
  84. package/lib/msrender.js +123 -0
  85. package/lib/pptd/export-pptx.js +686 -0
  86. package/lib/pptd/import-pptx.js +774 -0
  87. package/lib/pptd/layout.js +209 -0
  88. package/lib/pptd/render-html.js +254 -0
  89. package/lib/pptd/schema.js +518 -0
  90. package/lib/pptd/svgCharts.js +147 -0
  91. package/lib/pptxPy.js +205 -0
  92. package/lib/preset-delivery.js +195 -0
  93. package/lib/preview-server.js +164 -0
  94. package/lib/router.js +165 -0
  95. package/lib/scaffold.js +315 -0
  96. package/lib/skill.js +174 -0
  97. package/lib/splice.js +219 -0
  98. package/lib/state.js +88 -0
  99. package/lib/surgical.js +369 -0
  100. package/lib/templates.js +400 -0
  101. package/lib/tools.js +955 -0
  102. package/lib/verify.js +828 -0
  103. package/lib/xmljs.js +112 -0
  104. package/lib/zips.js +117 -0
  105. package/package.json +81 -0
  106. package/scripts/audit-manual-facts.mjs +294 -0
  107. package/scripts/audit-template-fidelity.mjs +162 -0
  108. package/scripts/bench-m2.mjs +48 -0
  109. package/scripts/build-templates.mjs +63 -0
  110. package/scripts/build.mjs +14 -0
  111. package/scripts/build.sh +7 -0
  112. package/scripts/check-lib-freshness.mjs +70 -0
  113. package/scripts/check-preset.mjs +189 -0
  114. package/scripts/check-tracked-lf.mjs +84 -0
  115. package/scripts/dbg-import.mjs +13 -0
  116. package/scripts/dbg-media.mjs +10 -0
  117. package/scripts/dbg-tpl-inventory.mjs +23 -0
  118. package/scripts/dump-workflow-baseline.mjs +38 -0
  119. package/scripts/e2e-1.0.mjs +129 -0
  120. package/scripts/eval-skills-blind.mjs +91 -0
  121. package/scripts/eval-skills-score.mjs +129 -0
  122. package/scripts/export-orig-templates.ps1 +17 -0
  123. package/scripts/fixtures/workflow-baseline.json +300 -0
  124. package/scripts/fixtures.mjs +501 -0
  125. package/scripts/import-user-templates.mjs +60 -0
  126. package/scripts/install-desktop.mjs +312 -0
  127. package/scripts/install.mjs +209 -0
  128. package/scripts/migrate-templates-dualtrack.mjs +71 -0
  129. package/scripts/preflight-1.0.mjs +198 -0
  130. package/scripts/probe-asset-freshness.mjs +57 -0
  131. package/scripts/probe-effect-semantics.mjs +69 -0
  132. package/scripts/probe-reparse-safety.mjs +32 -0
  133. package/scripts/rebuild-templates-c11.mjs +69 -0
  134. package/scripts/regression-real.mjs +84 -0
  135. package/scripts/release-sync.mjs +425 -0
  136. package/scripts/shot-templates.mjs +49 -0
  137. package/scripts/smoke.mjs +2512 -0
  138. package/scripts/verify-bundle-install.mjs +281 -0
  139. package/scripts/verify-fresh-install.mjs +260 -0
  140. package/skills/ppt-studio-copy/SKILL.md +139 -0
  141. package/skills/ppt-studio-craft/SKILL.md +171 -0
  142. package/skills/ppt-studio-data/SKILL.md +173 -0
  143. package/skills/ppt-studio-manual/SKILL.md +104 -0
  144. package/templates/academic-white/deck.yaml +24 -0
  145. package/templates/academic-white/pages/_chart.yaml +43 -0
  146. package/templates/academic-white/pages/_compare.yaml +37 -0
  147. package/templates/academic-white/pages/_content.yaml +35 -0
  148. package/templates/academic-white/pages/_cover.yaml +28 -0
  149. package/templates/academic-white/pages/_ending.yaml +28 -0
  150. package/templates/academic-white/pages/_flow.yaml +61 -0
  151. package/templates/academic-white/preview.png +0 -0
  152. package/templates/academic-white/template.yaml +14 -0
  153. package/templates/business-blue/deck.yaml +28 -0
  154. package/templates/business-blue/pages/_chart.yaml +36 -0
  155. package/templates/business-blue/pages/_compare.yaml +45 -0
  156. package/templates/business-blue/pages/_content.yaml +80 -0
  157. package/templates/business-blue/pages/_cover.yaml +39 -0
  158. package/templates/business-blue/pages/_ending.yaml +32 -0
  159. package/templates/business-blue/pages/_flow.yaml +87 -0
  160. package/templates/business-blue/preview.png +0 -0
  161. package/templates/business-blue/template.yaml +14 -0
  162. package/templates/pitch-bold/deck.yaml +23 -0
  163. package/templates/pitch-bold/pages/_chart.yaml +32 -0
  164. package/templates/pitch-bold/pages/_compare.yaml +36 -0
  165. package/templates/pitch-bold/pages/_content.yaml +58 -0
  166. package/templates/pitch-bold/pages/_cover.yaml +31 -0
  167. package/templates/pitch-bold/pages/_ending.yaml +27 -0
  168. package/templates/pitch-bold/pages/_flow.yaml +46 -0
  169. package/templates/pitch-bold/preview.png +0 -0
  170. package/templates/pitch-bold/template.yaml +14 -0
  171. package/templates/tech-dark/deck.yaml +24 -0
  172. package/templates/tech-dark/pages/_chart.yaml +27 -0
  173. package/templates/tech-dark/pages/_compare.yaml +38 -0
  174. package/templates/tech-dark/pages/_content.yaml +51 -0
  175. package/templates/tech-dark/pages/_cover.yaml +30 -0
  176. package/templates/tech-dark/pages/_ending.yaml +25 -0
  177. package/templates/tech-dark/pages/_flow.yaml +80 -0
  178. package/templates/tech-dark/preview.png +0 -0
  179. package/templates/tech-dark/template.yaml +14 -0
@@ -0,0 +1,113 @@
1
+ # 04 · 路线图与里程碑(长期任务清单)
2
+
3
+ > 原则:**每次迭代只带一个主目标 + 若干小修**;按"真实反馈驱动"排序(哪痛先治哪)。
4
+ > 每里程碑验收 = smoke 全绿 + 对应真实回归/场景复现 + 文档同步。
5
+
6
+ ## M1(进行中/大半完成)· 门禁语义补完 —— C2/C3/audit/D4
7
+ - [x] C3 出界分级声明制(expectedOutOfSafeArea;回滚 decoration 豁免出界)(v0.3.2)
8
+ - [x] C1 自动回退链(v0.3.1)|[x] C2 audit 禁 autoDeclare(v0.3.1)|[x] D4 导入安全区探测(v0.3.2)
9
+ - [x] audit 导出回读断言(页数/尺寸/最小字号)+ 审计提示词铁律(v0.3.2)
10
+ - [ ] 验收:audit 档用 19 页 deck 实测(何时 deck 可用再跑)。
11
+ - 注:完整"证据链(数据来源核查)"归 M3,audit 第一版不做。
12
+
13
+ ## M2 · 文本实测档(渲染回读测量)—— 解决 D4 的"估算被样式骗过"(v0.12.0 完成)
14
+ - [x] 设计:headless 测量通道(页面内 JS + Range 行盒 → `#__ppt_measured` → Edge dump-dom)→ `preview/measured.json`(独立档,不污染 layout.json 契约)。
15
+ - [x] **D3 决策落地**:实测=终审、估算=预检——`ppt_verify measured=true`:实测溢出且估算未报 = error(估算漏报,M2 核心捕获);实测复现 = warning;估算过报 = relief warning;无浏览器 → 降级估算 + 标注"未实测"。
16
+ - [x] 性能:100 页基准(render 70-406ms / measure 220-320s → 并发4+独立 profile 2.2s/页)→ 技术报告 §6。
17
+ - [ ] 导出 auto-fit 参考实测档(后续:实测与估算同源 HTML 渲染 vs PPTD 链路一致,收益评估后决策——保留估算门槛防浏览器字体缺失差异)。
18
+ - 注:验收"漏报样例"以行数差异捕获实证(文本框 5:估算 1 行 vs 实测 6 行——真实断行差异)。
19
+
20
+ ## M2.5 · 出界 bleed(C11)按需
21
+ - [ ] 仅当真实任务出现有意出血设计时:讨论 `expectedOutOfPage` 或在设计规范中明确"出血=安全区级声明";当前超页=绝对 ERROR。【待议,勿提前做】
22
+
23
+ ## M3 · 整体性与数据连贯(设计决策 6.5 的实现,v0.13.0 完成)
24
+ - [x] ~~跨页对账:`ppt_crosscheck`(同数字/百分比跨页 → 页号+上下文清单;单页数字不入组;cap 30)~~ **2026-09-18 用户质疑后实测证伪并废除**:按数字字符串分组只能确认"本来就一致"的数、看不见"同指标不同值"(32%/38% 埋点 0 命中),噪声 6 组/0 可行动(40 字 vs 40px、v1.0.0 拆成两组)。详见 docs/02 §2.17。
25
+ - [x] ~~证据状态机 v1:页面 `source` 标注 → grounded/unmapped~~ **同日废除**:`source` 是作者自述而非证据、不进成品,按页判 ⇒ 伪状态;改为**材料包 + 审阅协议**(工具不判定,判定交审阅者,四分类含"无法核实")。
26
+ - [x] 材料包重写:`ppt_crosscheck` = 全页正文(阅读顺序)+ 工作区素材清单 + 审阅协议(子代理优先;**用户禁止子代理时严格自审并标注**)+ 完整包落盘 `preview/review-pack.md`。
27
+ - [x] 总览图:`ppt_shot overview=true`(deck.html 整览 PNG,N 页纵排,>30 截前 30)——跨页节奏视觉审阅。
28
+ - [x] theme token 符合性断言:`$ref`(fill/color/style/stop/background/theme 内)缺失 → resolveDeck error(防字面 `$xxx` 上屏静默回退;正确引用零影响)。
29
+ - [ ] ~~证据状态机 v2(candidate/conflicted/missing)~~ 已并入上一条的四分类判定的**语义审阅**(不再由脚本维护状态机)。
30
+
31
+ ## M4 · 体验与预览
32
+ - [x] 导入保样式(v0.4.0,P0-1)→ import 工程预览基本还原原稿视觉
33
+ - [x] **pptx 产物直接截图**(v0.8.0 Office COM 真渲染通道:audit 档导出自动渲染 + ppt_visual;无 Office 自动降级并标注)
34
+ - [x] 性能基准(v0.12.0:100 页 render/measure 实测进 §6;截图复用独立 profile 已在前;大媒体流式写入/scale 探测仍留待)
35
+ - [ ] dsh 网页 client 内嵌预览面板(渲染器复用,对话内翻页/总览)——需要 client 插件基建(Slot UI + client 构建链),列为下一独立批次;现有 ppt_preview 同源链接 + 整览 PNG 已覆盖对话内看稿。
36
+ - [ ] `pptxgenjs` 第三引擎(**D6 已定:发布与自动回退链演进等 v1.0 再动**)。
37
+ - [ ] 大媒体流式写入 / scale 上限探测(Edge 超大截图;overview 已自动截 30)。
38
+
39
+ ## M5 · 分发与生态
40
+ - [x] **一键安装(2026-09-14 完成;2026-09-15 本机真机切换)**:包声明 `dsh.bundle.patch` + 根 `cordis.patch.yml` ⇒
41
+ `dsh plugin --profile web add <Releases 页面上的资产 URL>` **装完即挂载**(launcher 按已安装状态自动入 `dsh.profile.bundles`)。
42
+ 真机自证 `npm run test:bundle`(隔离 DSH_HOME);**本机已把旧装法(junction + 预设插件行)卸载并切到这条路径**,
43
+ 终态:`--dump-config` 出 `ppt-studio` 行、预设 0 行残留、挂载副本 == 部署副本(逐文件 sha256)。**不需要 npm 账号。**
44
+ 资产名带构建戳(实测"同 URL 覆盖后包管理器不重取",固定名会让升级静默失败);发布流程 ⑤b 自动同步挂载副本并自证同源。
45
+ - [ ] **npm registry 发布 —— 用户已决定不做**(2026-09-14:"算了,只要确保能用 `dsh plugin` 一键安装")。
46
+ 如将来要做:删 `package.json` 的 `private`、加 `publishConfig.access=public`、`npm login && npm publish`;包名三处需同改(smoke 有断言盯住)。
47
+ - [ ] 预设目录出厂化(`agent presets copy` 流程文档化)。
48
+
49
+ ## M6 · 内置制作技能(2026-09-14 完成 —— 用户诉求"skills 能不能提升制作能力")
50
+ > 用户硬约束:**技能只是锦上添花,绝不能影响既有工作流;老用户更新后用法零变化**。本轮全部设计以此为准。
51
+ - [x] **调研**(借鉴不采用):读透 humanizer / humanizer-zh / nature-paper2ppt / skill-creator / writing-skills → 条目骨架「信号→诊断→改法(含 before/after)+ 成组才判」、description 只写触发、正文短。
52
+ - [x] **三本自研技能**:`ppt-studio-craft`(叙事与版式)/ `ppt-studio-data`(图表与数据)/ `ppt-studio-copy`(中文文案与去 AI 味),与原有 `ppt-studio-manual` 并列。
53
+ - [x] **接入**:`src/skill.js` 扫 `skills/*/SKILL.md` 逐本内嵌注册(`ctx.skills.register`,落 PPT 预设层);工作流**只加一行**"何时加载"指引(标准档,quick 档逐字节不变);`install.mjs` 镜像全部技能。
54
+ - [x] **"老用户不受影响"机器断言**:工作流段**逐行超集**(基线 `scripts/fixtures/workflow-baseline.json`,10 变体)+ quick 档逐字节不变 + 技能包结构/长度/优先级边界断言 + 写死数值扫描(5 条校准正则)。
55
+ - [x] **对照评测**(方法见 docs/06 §7;打分器 `scripts/eval-skills-score.mjs` 随包提供):同一 brief、同模型、两轮有效对照——B 臂两轮文本都更省(1202→1073 / 1524→860)、建议项一轮更少一轮持平、无任何指标回退;并在 B 中把"行业报告显示"改写成页内来源提醒 + `source:` 标注"暂不可引用"。**如实结论:不回退 + 更精简 + 一处定性改进**(门禁错误两臂皆为 0,差异不在"过不过门禁")。
56
+ - [x] **结构化盲评**(协议 + `scripts/eval-skills-blind.mjs` 随包提供,见 docs/06 §7.6):匿名化 + 随机分配后由独立评审员按 6 维打分——**含技能那份 26/30 vs 无技能 22/30**,独立结论"更适合直接交付的是含技能那份";关键证据命中三本技能的原定目标(标题 5/5 结论句、文案 5/5 无 AI 腔、数据页主动标注"口径不可比/来源未注"),并抓出无技能那份**夹了一句材料里没有的结论**。
57
+ - ~~下一轮候选(盲评暴露):`ppt_verify` 对"含 chart 的页缺少图表标签文本"给一条 `[·]` 建议~~ —— **用户判定不成立,已撤销**:
58
+ 图表常常就是装饰/示意/背景,本来就不需要标签文本,不该在这上面加机器提示。相应地把 `ppt-studio-data` §0 改成
59
+ "先分清这张图是**证据还是装饰**"的判据(承载数据才要求标签四件齐;装饰性图表允许无标签,但交付说明标注"仅作示意"、
60
+ 且页面结论不得依赖它)。**不做机器提示**,避免把风格偏好变成门禁。
61
+ - [x] **独立评审**:交独立 agent 逐条对源码评审,抓出 7 类真实缺陷(变相写死数值、不可执行的 table 右对齐、被扩大的出界声明语义、缺失的降级路径、三本自检重复、标题写法归属不清、字号/图片主线缺失)并全部修补。
62
+ - [x] smoke 169 → 177 → **180**(末次为"借鉴经典 skill"一轮 + 3 条文档完整性断言)/ preflight 11 / e2e-1.0 13 / 预设自检 0 漂移;发行产物真进程验证 4 本技能 `registered:true` 且 `visible: runtime/runtime/len=N`。
63
+ - [ ] 下一轮候选:**版式配方做成模板母版**(机器可验证的几何,比散文技能更硬);**技能触发率评估**(本轮只评了效果,没测"该加载时是否真加载"——可借 skill-creator 的触发率方法)。
64
+ - 注:技能效果属"软收益",评测为 n=2 单一 brief 的**方向性证据**,不是统计结论(docs/06 §7.3 已如实标注)。
65
+
66
+ ## 常备维护(每轮)
67
+ - 反馈 → 1 个 ★ 项 + 最多 3 个小修;文档同步(01/02/03);smoke 增量断言;真实回归(19 页 deck + WPS fixture)。
68
+ - 每轮结束更新本文件的勾选状态与"下一轮建议"。
69
+ - [x] **图表颜色不受 `theme-conformance` 管辖**(2026-09-14 自检的独立评审判为 X-4)——**已按"建议级"处置**:
70
+ `chart.colors` **显式**写了主题外颜色 → 出一条 `[·] aesthetic-theme`(`layout.json` 的 chart snap 随之带上 `colors`,否则建议永不触发);
71
+ **不写 colors**(用内置调色板)不提示;**不门禁化**(门禁化会给既有工程/模板凭空新增 ERROR,且 `theme-conformance` 不可声明 = 让老用户变差)。
72
+ 仍未做(保留为待议):把"图表调色板"纳入主题体系本身(`theme.chartsPalette` 或强制 `$ref`)——那是一次会改变既有成品观感的变更,需用户拍板。
73
+ - [ ] **待议:`ppt_splice` 注入 deck 侧新写的 `notes`**(2026-09-14 讲稿通道落地时的已知缺口):
74
+ 现状(**已在 README / 技能手册 / docs/02 如实写明**):讲稿导出在**常规 `ppt_export`** 路径完整可用;
75
+ `ppt_splice` 走的是"替换源包里的幻灯 XML"的**手术路径**,它保留**源文件该页既有**的备注关系,
76
+ 但**不会把 deck 里为这一页新写的 `notes:` 写进被替换的源页**。
77
+ 要做的话是在 splice 里复用导出器的 notesSlide 构造 + 重接源幻灯 rels(并同步 Content_Types 与 notesMaster),
78
+ 属**高保真路径**的改动,必须配 e2e 真机回归(Office 可开 + 未手术条目 sha256 不变)——值得单独一轮,不在本轮硬塞。
79
+
80
+ ## 模板保真候选(fidelity-report.md 延伸;用户定优先级)
81
+ - [x] **候选 A(v0.9.1 完成)**:常见 prst 形状直通(17 种:箭头/多边形/星/流程图)+ 渐变双 stop 闭环(schema/import/render/export/verify 五端);export→import 回环验证 111 断言;真实模板 upArrow/roundRect/ellipse 直通实测。**注**:简约商务原稿 gradFill=0("渐变观感"实为 custGeom 弧带+半透明,97 个自定义几何),渐变闭环正确未误触发。
82
+ - [x] **候选 B 手术模式(v0.10.0 完成)**:`ppt_patch`——模板真身贴内容(文本/表格槽替换,只改 <a:t>,rPr/几何/渐变/字体/图片原样;未动页内容 sha256 验证);真实模板 24 页实测 patched 恰 2 页 / 158 条目一致;工作流 6b 新增"贴模板保真"路线(与双轨互补,常规导出不变)。**v1.1 预留**:rels 增量/资源注入、grpSp 组合内文本、新增页合并(手术 + 渲染混合成品)。
83
+ - [x] **候选 C(v0.11.0 完成)**:custGeom 几何闭环(import/render/export 三端直通:moveTo/lnTo/quadBezTo/cubicBezTo/arcTo/close;SVG 弧几何转换)+ alpha 透明度(solid/渐变 stop)+ 非 rect 形状内文本提取(20 个实证);简约商务 custGeom 提取 95/97(其余为母版层装饰——背景层边界)。**保真缺陷矩阵关闭**(A/B/C 全完成)。
84
+ - [ ] **保真矩阵残余(诚实边界,不阻塞)**:母版/布局层装饰与背景(2 个 custGeom)、LOGO 圆环/组合内图片细节、字体资产(模板专属字体回退)——双轨真身参考 + 手术模式覆盖这些场景;字体资产与背景层分析可作独立小项待议。
85
+
86
+ ---
87
+
88
+ ## 评审基线(来自用户测试反馈 3.3)
89
+ > 这套工作流在"可验证的 PPT 生产"上是合格的、甚至优秀的;但学习曲线集中在
90
+ > "DSL 规则与两套度量的边界"上。如果工具面能把 **schema 自述(✓v0.3)、
91
+ > 安全区(✓v0.3)、声明生成(✓v0.3)、度量归一(✓v0.3 保守档;实测档=M2)**
92
+ > 做掉,就可以从"熟练工才能用得顺"变成"人人可用"。
93
+
94
+ → 四个卡点 v0.3 已解决三个半;**M2 实测档是最后半个**;M3/M4 是"从能用变好用"的纵深。
95
+
96
+ ## 第一轮端到端测试记录(2026-09-05,萨尔浒之战 10 页)
97
+ > 测试会话结论(报告 §3.1):用户链路(模板库→创作→审阅→实测→导出→真渲染→预览)**成熟可靠**;痛点集中在**开发侧自维护链路**与 **autoDeclare 崩溃**。
98
+ - [x] **§A P0 真修复**(0.14.6):autodeclare yaml@2 崩溃(doc.get()=YAMLSeq;首版修复 `raw.toJS?.()` 裸调用仍抛 "A document argument is required"——smoke 30 回归当场捕获后改 `doc.toJS()`)+ smoke 回归 4 断言。
99
+ - [x] **§F P1 降噪**(0.14.6):themeConformance 字号建议 >3 处 → 聚合一条。
100
+ - [x] **§G P2 局部校验**(0.14.6):`ppt_verify pages=`(不改写 layout.json)。
101
+ - [x] **§B/§C(开发链)配套**(注入器 0.3.4):dev_build_plugin 去掉 checkout 前置门槛;dev_reload_package 对非注入器装配包明确诊断;dev_plugin_status 支持过滤;**单装配源定论**(preset 行;注入器 registry 残留清除,junction 保留)。
102
+ - [ ] **待重启端到端验证**:PPT 工作区 `ppt_verify autoDeclare=true` 回归(下轮)。
103
+ - [ ] 证据状态机 v2 / M4 client 面板 / M5 评测集 —— 按下一轮反馈排期。
104
+
105
+ ## 第二轮端到端测试记录(2026-09-05,AIC5 第15页:生产流程仿真 × 本体论)
106
+ > 任务性质:**编辑既有精美 PPT 的某一页**(20 页原稿只换第 15 页、其余逐字节不动、保留母版横幅)。测试会话结论:主流程闭环优秀,**两类核心困难**:①隐性契约(样式必须写在 content 内——schema 不拦曾致 146 条假错误);②保真交付(无"单页替换/单页导出"能力,被迫手工 zip 手术 + 哈希自证)。交付本身达标(0 错误审阅/64 对声明/Office 真渲染复核/其余页 SHA256 一致),列为高价值正面样本。
107
+ - [x] **A3/A9 ★★ 保真交付**(0.15.0):`ppt_splice`(替换进原稿,保留母版/备注/媒体,其余条目 SHA256 自证)+ `ppt_slice`(单页 + 完整母版体系);**E2E 真实资产 + Office COM PASS**(380 条目仅 2 变化,splice/slice 均真渲染成功)。
108
+ - [x] **A6 ★ 度量修正**:加粗 CJK ×1.06(Office 实际排版与估算的系统差)。
109
+ - [x] **B1 ★ 隐性契约拦截**:元素级样式键 → ppt_check 明确报错 + 指引;SCHEMA_REF 正/反例。
110
+ - [x] **A2/A7/A8/C3/B2/C1/A4/A5**:缺失媒体自检+占位兜底+python 错误完整化(A2);导入全量色板(A7);对比度渐变承载面(A8);内边距 near-align 豁免(C3);YAML 解析错误指引(B2);README 实现/度量速查(C1);存量溢出→splice 指引(A4);`ppt_visual pages`(A5)。
111
+ - [x] smoke 133 → **139**(全绿)+ 真实回归 2/2。
112
+ - [ ] **待重启端到端**:工作区内真实调用 splice/slice/visual pages(下轮验证)。
113
+ - [ ] **边界(诚实记录,未承诺)**:EMF 媒体在 pptd 管线的兼容性(D1);WPS 等其他实现打开 splice/slide 产物(D3);M2 浏览器档与 Office 档并存为大校验矩阵(D2,建议作为后续度量源选择项)。
@@ -0,0 +1,210 @@
1
+ # 05 · 迭代流程(每次改动的检查单 + Git/发布约定)
2
+
3
+ ## 一次迭代的标准循环(推荐顺序)
4
+
5
+ 1. **读文档**:`docs/01-需求与目标.md`(冲突清单 C* 是否受影响)+ `docs/04-路线图.md`(本迭代目标)。
6
+ 2. **定目标**:1 个主目标 + ≤3 个小修;写进 `docs/03-更新日志.md` 待办行。
7
+ 3. **改代码**:只改 `src/`(lib 由 build 生成,勿手改)。
8
+ 4. **同步文档**(铁律,缺一不可):
9
+ - `docs/02-技术报告.md`:模块/机制/契约变了就改;波及面速查表对应行打勾。
10
+ - `docs/01-需求与目标.md`:需求/决策/冲突清单有变化就改(推翻决策必须写"为什么")。
11
+ - `README.md`:使用者可见的行为变化(工具面/参数/规则/子集表)。
12
+ - `src/scaffold.js` `SCHEMA_REF`:DSL 语法有变化就改(与 README/技术报告三处一致)。
13
+ - 工作流提示词(`src/router.js`):铁律/入门段有变化就改(模型看到的 = 文档)。
14
+ 5. **构建**:`node scripts/build.mjs`(src → lib)。
15
+ 6. **回归**:
16
+ - `node scripts/smoke.mjs`(必须全绿;新增特性 → 增量断言,坏例优先"先写失败测试")。
17
+ - `node scripts/regression-real.mjs`(真实资产:19 页 deck + WPS fixture)。
18
+ 7. **生效**:首选**重启 DSH host**(保底且干净——注入器注册表自动恢复全部插件;无任何挂起状态)。
19
+ - 备选:`dev_reload_package dsh-ppt-studio`——**已知缺陷(2026-09-04 排查)**:build 后立即手动重载与 watcher 自动重载并发时,`ctx.loader.import` 可能产生"僵尸 in-flight job",同 URL 后续 import 永久排队 → 工具调用卡死(注入器已加超时/锁/cache-bust 三重防护,但**僵尸 job 通道为宿主侧限制,不能保证 100% 免疫**)。**实践经验:build 后若 30 秒内 watcher 自动重载未完成,直接重启,不要反复手动重载**。
20
+ - **新增事实(2026-09-05 确认)**:本插件经 agent preset 行**会话级装配**(include 机制),不在注入器 loader 域——`dev_reload_package` 无法命中(重载空转),`dev_plugin_status` 也不显示。**改码 → 重启 host 是唯一可靠生效路径**(注入器 0.3.4 起该工具会给出明确诊断)。
21
+ 8. **记录**:`docs/03-更新日志.md` → `## [版本号] 日期` 目的/改动/验证/影响;改 `package.json` version(semver);git commit(message 含版本号)。
22
+
23
+ ## Git 约定
24
+
25
+ - 仓库根 `D:\SharkCode\dsh-ppt-studio`;远程 `https://github.com/zbsph/dsh-ppt-studio`(发布与同步纪律见下文"发布-同步纪律"一节,别再写成"无远程")。
26
+ - `.gitignore`:`node_modules/`、`lib/`(build 生成)、`examples/*/preview/`、`examples/*/imported/`、`examples/*/out-*.pptx`、`examples/*/media-test.png`、构建产物目录(import-realtest* 等)。
27
+ - 提交粒度:一个功能/修复一个 commit;message:`v0.x.y: <一句话目的>(反馈 Dx)`。
28
+ - **基线 commit**(v0.3.0 + 文档体系)已于 2026-09-04 建立——从此任何改动可 diff/回滚。
29
+
30
+ ## 版本与发布
31
+
32
+ - semver:`major` 破坏中间层/接口兼容;`minor` 新特性;`patch` 修复/文档。
33
+ - 发布清单:smoke 全绿 → 真实回归全过 → README/SCHEMA_REF/更新日志同步 → **重启 DSH host 确认 active**(dev_reload_package 仅作补充,见步骤 7 已知缺陷)→ (未来)`dev_release_plugin` + npm pack。
34
+ - 运行时装配路径(勿动):profile `node_modules/dsh-ppt-studio`(**归 pnpm 管**,别手工建 junction);预设 = 插件激活时向 `agentPresets` 注册表**声明**(`lib/preset-delivery.js`),**不写磁盘预设目录**。
35
+ > **2026-09-24 更正**:上一版这里写的是"`C:\Users\11867\.dsh\.agent-presets\ppt\` = 唯一装配源"(1.0.1 隔离时代的记录)。
36
+ > DSH 0.1.7 起目录发现已被上游删除 → 唯一受支持装法是 **profile bundle(全局)**;`--isolate` 由安装器拒绝。见 README §1.6。
37
+
38
+ ## 装配注意(2026-09-04 教训入库,v0.14.2)
39
+ - **本插件有两个装配源**:注入器 registry 恢复(host 启动)+ agent preset 插件行(agent 挂载)——同包可能装配两次(时序竞态曾导致 duplicate 路由崩溃)。
40
+ - **凡 host 资源注册(webServer 路由等)必须幂等**:globalThis refcount(模块级变量在 junction/真实路径双加载下不可靠)——见 preview-server.js ROUTE_REG 范式(首个注册者真注册、最后卸载者真卸载)。
41
+ - 新资源注册一律 `ctx.effect`(清理即净)。
42
+
43
+ ## 装配定论(2026-09-05 定;**2026-09-24 按 DSH 0.1.7 改判**)
44
+ - **装配源 = profile bundle 行(唯一)**:包的 `cordis.patch.yml`(`dsh.bundle.patch`)插入 `id: ppt-studio` 行 → profile 级 ⇒ 该 profile 所有会话都能用。
45
+ - **预设 = 注册表声明**(不是磁盘目录):插件激活时 `ctx.agentPresets.register({id:'ppt', …})`,`plugins` 取自包内 `agent-presets/ppt/agent.cordis.yml`。0.1.6 及以前"写 `<dshHome>/.agent-presets/ppt/`"的做法在 0.1.7 上**没有任何效果**(上游不再扫描目录),安装器会清理该历史目录。
46
+ - **注入器 registry 的 ppt-studio 记录已清除**(历史残留,来源:09-03 dev_inject_plugin 实验)——保证永不出现双源。历史 junction(`profiles/web/node_modules/@dsh-external/dsh-ppt-studio`)**不要保留**:包名已改无 scope,且 0.1.7 的装配不再需要任何 junction。
47
+ - **开发工具的现实约束**(注入器 0.3.4 起已诊断化):`dev_reload_package` / `dev_plugin_status` 只覆盖注入器 loader 域;bundle 行装配不在其中 → 改码 = 重启 host;`dev_build_plugin` 不再把 DSH_CHECKOUT 当构建前置(copy-only 插件无需 checkout;需要 tsc 的插件由其 build.sh 报明确错误)。
48
+ - **yaml@2 节点 API 教训**:`parse()`(纯值)/ `Document.toJS()`(Document 级纯值,推荐)/ `doc.get()`+`node.toJS()`(AST 层,裸 toJS 抛 "A document argument is required")——parseDocument 场景读值一律 `doc.toJS()`。
49
+
50
+ ## 装配与安装(2026-09-14 新增 profile bundle 路径后)
51
+ - **两条路径,二选一**:① `dsh plugin --profile <p> add <包>`(走包里的 `cordis.patch.yml`,**profile 级**);② `install.mjs` 写 agent preset 行(**会话级**)。
52
+ 同时装 = 同进程挂两次 → 插件有**装配防重**(首个生效 + 告警)不会崩,但纪律是二选一(README §0.7)。
53
+ - **"能不能用标准姿势装"取决于包自己**:依赖必须声明 `dsh.bundle.patch`(且该文件在 `files` 里),否则 `dsh plugin add` 只装不挂、仅打一行警告。
54
+ 改这件事后**必须跑 `npm run test:bundle`**(隔离 DSH_HOME 真装一遍),别因为本地 junction 还能用就以为没事。
55
+ - **包名是单一事实源**:改名(例如为发布改 scope)时 `package.json.name` / `cordis.patch.yml` / 预设插件行必须同改;smoke 有断言钉住三处。
56
+ - **`ctx.effect(cb)` = 立即执行 cb + 用返回值当 disposer**(真库探针实测,见 docs/01 决策 12):凡"注册即副作用"这样写;凡"清理逻辑"必须**包在返回的函数里**。
57
+ 写反的后果不是报错而是**静默失效**(路由 refcount 就这么失效了很久)。
58
+ - **假对象必须复刻真契约**:smoke 的假 ctx 曾把 `effect` 语义写反,于是"清理体写在 cb 里"的真 bug 在测试里看起来是对的。
59
+ **测试替身的契约错了,测试就在替 bug 背书**——契约可疑时,先用真库写一个最小探针(本轮就是这么定位的)。
60
+
61
+ ## 新反馈的处理模板
62
+
63
+ 1. 归类:插件层(工具/DSL/断言)/ 提示词层(工作流/铁律)/ 环境层(DSH/系统,记录但不改插件)。
64
+ 2. 标 ★(影响面):≥1 个★ → 进下一轮主目标;无★ → 进 backlog(docs/04 维护段)。
65
+ 3. 写复现:先造"坏例"进 smoke(红)→ 修(绿)——防回归。
66
+ 4. 更新 docs/01 §5 冲突清单(新张力就开新 C 行)。
67
+
68
+ ## 反馈文件纪律(2026-09-06 起)
69
+
70
+ - **测试反馈 .md 是易失文件,随时可能被删除/移动——不得作为后续工作的依据**。每条反馈的实质(现象/根因/修复/验证)必须**当轮落入 git**:docs/03(更新日志)/ docs/04(记录)/ docs/06(评审);反馈文件名只作溯源引用,不依赖其存在。
71
+ - 复盘与后续迭代一律从 git 记录出发;反馈文件还在时只做交叉核对。
72
+
73
+ ## 发布-同步纪律(两种模式:日常本地迭代 / 发版同步)
74
+
75
+ - **日常迭代 = `node scripts/release-sync.mjs --local`**(`npm run sync -- --local`):**不发 GitHub**。原子完成
76
+ build → pack(带构建戳)→ **跳过上传** → 同一 tgz 部署本机安装根(`D:\plugins\package`)→ 用**本地 tgz 的 `file:` 规格**
77
+ 把同一份字节装进 profile(挂载源 = 本地构建产物)→ 终验"**挂载副本 == 刚构建的字节**"(逐文件 sha256)→ 写 `.sync-state.json`。
78
+ - 构件落在 `D:\plugins\_artifacts\<资产名>.tgz`,**必须是稳定目录而不是 tmpdir**:这个路径就是 profile 的依赖规格,
79
+ 放临时目录的话系统清理后该 profile 的 `pnpm install` 会在**下一次**安装时莫名失败(离本次构建很远,极难归因)。旧构件每次自动清理,只留当前那一个。
80
+ - **为什么用 `file:` 而不是切回 junction/preset 装法**:junction 会**新增一条挂载路径**——"我改的是哪份代码"于是有两种答案,
81
+ 答错**不报错**。`file:` 仍然只有一条路径(profile bundle 行),只把"从哪取字节"从远端资产换成本地 tgz。
82
+ 机制由 `npm run test:bundle` 自证(同版本号、不同路径的 tgz ⇒ 装到的就是新字节)。
83
+ - **⓪ 落后检查**:跑之前先 `git fetch` 比对 `HEAD` 与 `origin/<branch>`,落后 >0 个提交就**直接失败**(`--allow-behind` 绕过)。
84
+ 理由:**"本地永不落后于 GitHub"不会自动成立**——有人在 GitHub 上直接改、或换机器提交,本地就落在后面,
85
+ 而"在最新版本上迭代"这个前提破了以后**没有任何症状**,直到发版时才发现分叉。离线(fetch 失败)明确标注"未能确认"并继续。
86
+ - **发版 = `node scripts/release-sync.mjs`**(不带 `--local`):build → pack → sha256 比对/上传(`--clobber`,幂等)→ 同一 tgz 部署本机安装根
87
+ → 按 **GitHub 资产 URL** 重装 profile → 终验 sha256 三向一致 → 写 `.sync-state.json`。**发版把本机与 GitHub 拉回同源。**
88
+ - **`.sync-state.json` 的 `mode` 字段区分两种状态**(`local` / `release`):本地模式下 `remoteSha` 保留**上一次发版**的值并记 `lastReleaseAt`——
89
+ **绝不把"未上传"伪装成"已同步"**。这是本地模式唯一新增的风险,必须让它可读。
90
+ - **回退到 GitHub 版本**:`dsh plugin --profile web add <Releases 页面的资产 URL>`(发版模式做的就是这件事)。
91
+ - 两种模式都**需要重启 `dsh web` 才生效**(profile bundle 挂载不热更)。本机安装包由当次构建用的**同一个 tgz** 解压而来,部署副本与挂载副本逐文件同源。
92
+ - **挂载模式(决定"谁看得见工具/skills")与 `--local`(决定"从哪取字节")是两件事,正交**:
93
+ bundle 行 = 该 profile **所有会话**可见(含官方标准预设);**预设行 + junction = 仅「PPT 工作室」预设可见**。
94
+ 想要会话级隔离就切后者(`dsh plugin --profile web remove <包>` → `node scripts/install.mjs` → 重启;README §10 有切换与回退命令),
95
+ 日常迭代照旧 `--local`——它现在**两种挂载模式都自证**(非 bundle 走"穿过 junction 读到的字节")。
96
+ 插件**无法**在 bundle 挂载下自己按预设过滤:注册发生在插件 `apply`(profile 级),要按预设隔离就得从预设组合里注册。
97
+ - 版本号:未获用户指示不改(当前 **1.0.3**;1.0.0–1.0.2 的历史值见 docs/03);**资产名带构建时间 + 构建戳**(2026-09-15 起):`dsh-ppt-studio-<版本>-<YYYYMMDD-HHmm>-<sha256 前 8 位>.tgz`。
98
+ > 2026-09-18 改名说明:包名由 `@dsh-external/dsh-ppt-studio` 改为**无 scope** 的 `dsh-ppt-studio`(发布到 npm),
99
+ > 于是 `npm pack` 产出的资产名也从 `dsh-external-dsh-ppt-studio-…` 变成 `dsh-ppt-studio-…`;v1.0.2 及更早的资产仍在 Releases 页上(老用户重装不受影响)。
100
+ **时间段的用处**:老资产**不删**(已装用户靠它重装),页面上会并排多条名字近似者,sha 段看不出新旧 ⇒ 取时间最新那条即当前版本;发布日志里同时打印本轮的完整资产名。
101
+ 原因(本轮实测):用 `--clobber` 覆盖**同一 URL** 的内容后,**`dsh plugin add <同一 URL>` 不会重新下载**
102
+ (pnpm 按 URL 规格复用旧副本,`--force` 也没绕过;独立 GET 证明 URL 侧已是新字节 ⇒ 复用发生在包管理器侧)
103
+ ⇒ 用户"重跑同一条命令升级"会拿到旧版本。换名 ⇒ URL 必变 ⇒ 必然重取。因此**取消"同 tag 资产原地更新"这条口径**:
104
+ 每次构建产出新资产名,旧资产保留(历史可回溯)。
105
+
106
+ ## 宿主升级纪律(DSH 换版本时必做,2026-09-12 起)
107
+
108
+ - **先确认版本再动手**:`dsh --version` + `npm view @deepseek-ai/dsh dist-tags`(`latest` 与 `next` 可能不同;本机基线写进 README §0.1 与 package.json 的 peer 范围)。
109
+ - **契约逐项核对,不靠记忆**:对本机活进程用 Inspect 取权威签名——`Service.listService`(`tools` / `commands` / `systemPrompt` / `webServer` / `skills` / `agent*`)与 `Event.listEvents`(`session/event` / `system-prompt/assemble`)。**服务名与事件载荷都可能变**(本轮实例:DSH 只有 `agents` 服务,`agent` 服务并不存在)。
110
+ - **会话身份只走官方通道**:工具内 = `execute(args, exec)` 的 `exec.agent`;waterfall/命令内 = `context.agent` / `invocation.agent`。禁止 `ctx.get('agent')`。
111
+ - **升级后必须"真进程验证",不能只跑单测**:临时覆盖层(`dsh --profile headless --patch <overlay.yml> "<任务>"`)+ 落盘探针,实测三件事——① 插件 host 装配成功且工具可调;② 内嵌 skill 在技能注册表里可见(`ppt_state.manualSkill.visible`);③ `system-prompt/assemble` 里确实出现 `ppt-workflow` 段(探针计数,别问模型"你看到没有"——模型自述不可信)。
112
+ - 覆盖层与探针文件属临时物,验证完立即删除;headless profile 的 junction 用 `cmd /c rmdir` 删(`Remove-Item -Recurse` 有跟随重解析点删目标内容的风险)。
113
+ - **绝不对可能含 junction 的目录做 `Remove-Item -Recurse`(2026-09-14 事故,已修复)**:
114
+ 本机 `~/.dsh/profiles/web/node_modules/yaml` 与 `D:\plugins\package\node_modules\yaml` 都是 junction,
115
+ 而 PowerShell 5.1 的 `Remove-Item -Recurse` **会跟随重解析点**。事故链条:临时对照包被 `install.mjs` 链上
116
+ `node_modules/yaml`(指向 dsh 安装内的 yaml)→ 随后 `Remove-Item -Recurse` 该临时目录 →
117
+ **把 `@deepseek-ai/dsh/node_modules/yaml` 的内容清空**(目录还在、包没了)→ dsh 整棵插件树加载失败
118
+ (`dsh-settings-file` / `dsh-credentials-local` 找不到 `yaml`)。
119
+ 修复:从本机同版本副本(`~/.dsh/profiles/web/node_modules/yaml`,yaml@2.9.1,满足 `^2.9.0` 与 `^2.4.2`)**普通复制**回
120
+ `@deepseek-ai/dsh/node_modules/yaml`,用 `dsh --version` + `dsh --profile headless --help` 验证插件树恢复。
121
+ 规矩:① 删任何目录前先 `cmd /c rmdir <里面的 junction 子目录>`;② 临时包用 `cmd /c rmdir /s /q` 或 Node `fs.rmSync`(不跟随重解析点);
122
+ ③ **造对照包一律用普通复制(`Copy-Item`)并自带 `node_modules/yaml`,不要用 `install.mjs`**(它会建 junction);
123
+ ④ 指向宿主的链接用完立刻删。
124
+ - **预设也要比对(2026-09-12 血案)**:`agent-presets/ppt/agent.cordis.yml` 是**随包 standard 预设的全量副本 + 本插件人格**,宿主的预设配置会随版本漂移(实例:0.1.5-rc.2 把 dsh-persona 的 `text` 改成 `prefix`+`suffix`,副本没跟 → 一切换预设就弹 `$.prefix missing required value`,单测与工具契约核对都发现不了)。每轮升级后跑 `node scripts/check-preset.mjs`(`npm run test:preset`),有漂移即修。
125
+ - **2026-09-24:参照物的位置和格式都变过,脚本必须都认**。0.1.6- 是 `dsh-agent-presets/presets/standard/agent.cordis.yml`(条目数组);0.1.7+ 是 `dsh-web-app/presets/standard.patch.yml` 的 `insert → config.plugins`。脚本按文档形状自动识别并**在输出里写明认到哪种**;`--ref <文件>` 可钉住参照(本机装了 DSH 时无法制造"找不到参照"的场景,测试靠它)。
126
+ - **不许静默跳过**:0.1.7 升级当天的实际教训是——脚本找不到旧路径就打印一行跳过、退出码 0,于是 `npm test` 报 250/0 全绿,而**整套 DSH 相关检查其实一条都没跑**(本轮真问题恰恰是"预设永远不会出现")。现在找不到参照会醒目告警,`--require`(发布/干净安装门禁用)直接失败。
127
+ - **跨层验证(2026-09-14 连线方向血案)**:同一份内容有三层产物——HTML 预览(render-html.js)、OOXML 成品(export-pptx.js)、真渲染图(Office/Edge)。**任何一层单独通过都不算过**:实测出现过"预览全对、PowerPoint 里斜线镜像/× 少一笔"(`straightConnector1` 丢 `flipH`/`flipV`)。规矩:凡新增/修改元素类型的导出编码,必须 ① 加**从产物反推的自证断言**(如 `connectorEndsFromXml` 端点比对进 `report.parity`)② 至少一页 `ppt_visual` 真渲染人眼复核。
128
+
129
+ ## 内置技能的增改纪律(2026-09-14 起)
130
+
131
+ 技能是**内容**,不是代码——它会直接影响模型行为,且用户看不到 diff。因此按以下规矩增改:
132
+
133
+ 0. **禁令准入(借 ppt-master 的 prompt-style 判据,2026-09-14 引入)**:手册里每一条"禁止/必须/配额"都必须能说出**让它变硬的机制**
134
+ (`ppt_verify` 的哪条断言、导出器行为、格式限制、门禁顺序、读入成本);说不出机制的 → **降级为"经验值(可覆盖)"或删掉**。
135
+ 这条是防止手册越写越僵、越写越像说教的唯一闸门。配套两条:
136
+ - **单一所有者 + 指针**:同一规则只在一处写全,别处只写"见 §N / 见某工具";复述即产生第二所有者,两边必然漂移。
137
+ - **标签强度分级**:用 `**硬规则**` / `**默认(可覆盖)**` / `**参考·非约束**` 把"必须"和"建议"在字面上分开——
138
+ 模型把风格建议当硬规则执行,正是我们出过事故的样子。
139
+ - 反向红线:**绝不把别家 skill 里的具体数值当默认基线抄进来**(它们的"Default — X"读起来像推荐默认值,抄进来同时违反第 2 条并让插件变差)。
140
+ 0a. **外部经验值的两道闸(2026-09-14 用户抓到的失误,务必照做)**:从外部 skill / 文章吸收任何经验值前必须过两关——
141
+ ① **机制闸**:这条能说出机制吗?说不出 → 不进手册(顶多写成"参考")。
142
+ ② **原则闸**:它与我方既有门禁 / 原则冲突吗?冲突 → **一律不进**,哪怕它在别处是主流做法。
143
+ 失误实例:从 ppt-master / 归藏的调研报告里抄了"同一明暗基调连续 3 页以上就该换",它**说不出机制**,
144
+ 而且与 `theme-conformance`(颜色必须出自 theme)和"模板基调统一"直接冲突——会把模型推向"中途换底色"这种更差的结果。
145
+ 已删除,并把正确口径写成"**节奏靠密度与构图,不靠改底色**;深/浅切换只跟随模板或用户既有的分区设计";
146
+ 同时加了一条 smoke 防线(劝人改全册底色/主色 = 违规),校准:5 条植入违规全抓、6 条合法表述零误报。
147
+ 0b. **不吸收第二套门禁**:外部 skill 的校验脚本/自检命令/配额表一律不搬——我们只有 `ppt_verify` 一套门禁语义;外部能做而我们不能做的(联网、生图、HTML 运行时)不写进手册。
148
+ 0c. **手册里的"事实"是第二类风险,与经验值分开管(2026-09-14 全面自检新增)**:0a/0b 管"该不该说",
149
+ 这里管"说得对不对"——手册写错一个工具名/字段形状/错误码/严重度标记,模型就会照着错一次(而且看不出来)。
150
+ 规矩:**手册里的每个事实都要能指回源码行**——工具名 → 注册表;DSL 形状 → `pptd/schema.js` 的校验器;
151
+ 错误码与严重度 → `verify.js`;预览/交付行为 → 渲染器与导出器;阈值 → 那个常量本身。
152
+ 本轮自检抓到的 6 类实例:① `chart` 的 `data` 形状写成 `[{label, value}]`(schema 只认 `{cols, rows}`,照写必被拒);
153
+ ② 三本手册把 warning 标记写成 `[⚠]`(`ppt_verify` 主清单实际是 `[~]`);③ `density`/`near-align` 被归到 `[·]` 建议(实际 `[~]` 警告);
154
+ ④ 手册门禁清单漏了**默认就开**的 `theme-conformance`;⑤ "预览里图表带分类名"对 pie 不成立(pie 连分类名都不画);
155
+ ⑥ 6 处 "smoke 181 断言" 只能靠人工同步。
156
+ 已落成 **13 条机器断言**(smoke §37/§38,套件 181 → 194):`ppt_*` 工具名存在 / 门禁错误码集合与源码一致 / 每个错误码都写进手册 /
157
+ 手册门禁清单里的 code 名真实存在 / 警告标记是 `[~]` 而非 `[⚠]` / `density`·`near-align` 不得归到 `[·]` / chart 的 `data` 形状 /
158
+ 预览截断阈值与 `svgCharts.js` 一致 / `/ppt` 子命令存在 / 讲稿章节写明"不导出备注" / 缩字下限常量与导出器一致 /
159
+ `SCHEMA_REF` 自洽(不得声称 decoration 豁免出界)/ **引用计数自证**(文档里的 "smoke N 断言 / N/N" 必须等于本次真实断言数——
160
+ 这条实现当轮先红后绿,一次点出 6 处过期引用,是治"加断言忘了同步文档"这个反复疏漏的根)。
161
+ 同时清理掉的同类问题:`非对称是默认`(把设计偏好写成默认,会跟用户的对称模板打架)、`约三成面积的低细节区`
162
+ 与"3–5 条讲稿要点"(裸经验值未打"经验值(可覆盖)"标签)、"宁可拆两页"(与"页数由用户定"冲突)。
163
+ 0d. **产物必须用真消费者验(2026-09-14 血案)**:加备注页时先写了 `<p:notesMasterIdLst>`——**python-pptx 照读不误,真 PowerPoint 直接报"文件或目录损坏"(0x80070570)**。
164
+ 第三方库通过 ≠ 能打开。凡改**导出编码/OOXML 结构**,必须至少走一次真消费者(真 PowerPoint `ppt_visual` / 真浏览器 `ppt_shot`),
165
+ 自证断言(parity)只证明"我写出去的和我以为的一致",不证明"别人能读"。定位手段:以**已知能打开的同类原生文件**为底做**减量二分**
166
+ (逐个撤掉自己新增的部件/元素,看撤掉哪一个是它开不了的),比读规范猜快得多、也可靠得多。
167
+ 0e. **触发面纪律:技能描述里的触发条件,不许对"正在干活的模型"恒真(2026-09-15 用户反馈)**:
168
+ 症状:PPT 任务**开工时**模型先加载了答疑手册 `ppt-studio-manual`——它的描述写着"如何开始 / DSL 语法速查",`whenToUse` 写着
169
+ "**或模型不确定某一 DSL 写法、工具语义、交付路径时**"。后半句对正在做 PPT 的模型**永远成立**,于是每轮任务白付一次几千字符成本,
170
+ 而正文讲的是"怎么回答用户提问"。这不是模型不守规矩,是描述把"自触发条件"写成了触发条件。
171
+ 三查规矩:① **问答类技能**只由"用户提问"触发,并显式写出否定句("制作任务进行中不要加载");② **工作类技能**由具体工作面触发(定纲/放图表/写文案);
172
+ ③ 禁止"不确定时 / 拿不准时 / 需要时"这类**恒真或半恒真**触发语——模型在干活时永远"可能需要"。替代写法:在描述里直接给出**权威来源**
173
+ ("写法不确定 → 调 `ppt_schema`/`ppt_check` 拿输出,不要读手册")。机器防线:smoke §42 三条(描述与 whenToUse 的问答触发 + 否定句、
174
+ 正文开头横幅、制作三本正文零指向答疑手册);`audit-manual-facts.mjs` 两条证据检查。**另一条同源教训**:交叉引用也是触发面——
175
+ 制作手册正文里写一句"详见 `ppt-studio-manual` §5",工作期读到就会把模型引去加载答疑手册(本轮已清掉)。
176
+ 1. **只增不改**:工作流提示词由 `scripts/fixtures/workflow-baseline.json` 做**逐行超集**断言(`npm test` 里两条"★老用户不受影响")。新增指引=加一行;**任何对旧行的改写或删除都必须先经用户确认**,确认后跑 `node scripts/dump-workflow-baseline.mjs` 重建基线(不确认就别重建——重建会让护栏失效)。
177
+ 重建后**必须逐行审查 diff**:本轮(2026-09-14,用户确认修 `router.js` 括注错位)相对 HEAD 只有两类变化——
178
+ 5 条"改后的溢出行" + 5 条**此前漏进基线的技能指引行**(纯增行不会被超集断言发现,所以基线里的"新增行"也要靠重建补齐)。任何第三类变化都要停下来查。
179
+ 2. **不许写死数值**:技能正文不得出现"默认 12pt""必须 ≤8 页""每页 ≤40 字"这类**规范性数值**。smoke 有 5 条校准过的正则做机器防线(8 条植入违规全抓、8 条合法表述零误报)。经验值一律写成"经验值(可覆盖)",并把优先级写成"用户指令 > 手册 > 工具默认"。
180
+ 2b. **自检条目要可核对**:自检章节的每条都应能"数出来或对照某个工具输出"(存在性/计数/一致性),不写"是否美观""是否清晰"这类无法核对的话
181
+ (借归藏 checklist 的"现象→做法→机械自检"形状;P0 项必须先清零)。
182
+ > **这道守卫的诚实边界**:正则只能抓"规范性措辞 + 数值"这一形状,**抓不到**"裸阈值当建议写"(如"列 ≤5、行 ≤7 才好读")、也抓不到语义偏移(把"逐元素手工声明"写成"站在带上就声明")、不可执行的指令(要求 table 右对齐)与三本之间的重复。所以 `docs/06 §7.4` 的**独立评审**是必需的第二步:新写或大改技能后,交一个独立 agent 逐条对照源码评审,把缺陷清单落进 docs/03。
183
+ > **2026-09-14 补充**:smoke §37 之后,"工具名 / 错误码 / 严重度标记与分级 / DSL 形状 / 预览阈值 / 引用计数"这几类**已进机器防线**(对照源码,不靠人眼);仍然只能靠独立评审的是:裸阈值当建议写、语义偏移、不可执行指令、跨本重复——所以 §7.4 那一步不能省。
184
+ 3. **每本自包含且短**:描述 ≤500 字符且**只写触发**(描述会常驻系统提示,正文按需加载);正文几千字符量级;不放脚本、不依赖外部文件。新增一本=新建 `skills/<kebab-name>/SKILL.md`,`install.mjs` 与 `lib/skill.js` 自动纳入(无需改代码)。
185
+ 4. **不与用户自装技能抢位置**:一律 `ppt-studio-*` 前缀;通用能力(去 AI 味、润色)写"优先用用户已装的同类技能,本手册兜底",不复制别人的内容。
186
+ 5. **改动要有前后对照**:技能效果属"软收益",必须用 A/B 评测(同一 brief、同模型、同装配,门禁分数 + 信号扫描)落到 docs/03/04;不做"感觉更好了"的结论。
187
+
188
+ ## 文档文风范围(2026-09-18 用户拍板)
189
+
190
+ "去 AI 味 / 面向用户重写"这类**文风**改动,只做在**仅给用户看**的文件上:
191
+
192
+ - **要改**:`README.md`(GitHub 仓库页 / 包页)、GitHub Release 说明。用户真的会读它们。
193
+ - **不要改**:`skills/*/SKILL.md`(模型运行时读)、`docs/*.md`(开发与决策档案)、`agent-presets/**`(persona 提示词)、代码注释。
194
+ 这些是给模型和开发看的,**信息密度与精确性优先**;重写文风只会增加破坏机器断言的风险(4 本手册被 `audit:facts` 的 39 条与
195
+ smoke 的多条断言钉着,2026-09-18 实测:一次"顺手润色"就踩红了两条)。
196
+ - 判据一句话:**问"这份文件是给谁读的"**。只给用户读 → 可以重写文风;同时给模型或开发读 → 只做**事实更正**,不动文风。
197
+ - 两边都需要的同一内容 → **写两版**(用户版放 README,权威版放 docs 或技能),不要用一份文件同时满足两类读者。
198
+ - 边界案例:技能手册的内容会影响用户最终看到的话(模型照它回答),但**文件本身不是用户读物** ⇒ 按本条**不改文风**;
199
+ 要改的是它的事实准确性(走上面的 §0c 事实链与 `audit:facts` 断言)。
200
+ - 文风改动的验收方式:`npm test` 的"文档计数自证"必须仍绿(README 里引用的 smoke 断言数要与真实数一致),
201
+ 且改后**事实零变化**——命令、路径、版本、断言数、FAQ 里历轮反馈的事实一条都不能少。
202
+
203
+ ## 禁止事项(保护性底线)
204
+
205
+ - 不删标准预设任何行(预设 = standard 全量 + 插件行)。
206
+ - 不把任何 ERROR 降级为 warning(严格性只升不降;降 = 必须用户确认 + 更新 01 文档)。
207
+ - 不静默切换引擎(auto 语义 = pptd;切换必须显式或用户确认)。
208
+ - 不做无视用户指令的自动缩字(下限 = 用户指令 theme.minFontSize;未设仅 60% 原字号防荒谬保底,绝不升字)。
209
+ - 不引入新的运行时 npm 依赖(yaml 是唯一例外;新增须论证)。
210
+ - **不拿"能跑通"当"没问题"**:凡"机制应当生效"的断言(提示词注入、技能交付、会话状态、路由判据),必须有**可观测证据**(探针计数 / 注册表查询 / 状态文件),否则记为"未验证"。