dsh-thesis 2.0.2 → 2.1.1
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 +5 -4
- package/docs/config.md +12 -0
- package/docs/design.md +95 -2
- package/docs/release.md +94 -85
- package/docs/tools.md +8 -5
- package/docs/troubleshooting.md +18 -0
- package/docs/usage.md +4 -1
- package/lib/config.d.ts +13 -0
- package/lib/config.js +8 -1
- package/lib/figure/actions.d.ts +83 -0
- package/lib/figure/actions.js +439 -0
- package/lib/figure/index.d.ts +24 -0
- package/lib/figure/index.js +40 -0
- package/lib/figure/lib/check.d.ts +83 -0
- package/lib/figure/lib/check.js +214 -0
- package/lib/figure/lib/drawio.d.ts +123 -0
- package/lib/figure/lib/drawio.js +156 -0
- package/lib/figure/lib/export.d.ts +120 -0
- package/lib/figure/lib/export.js +308 -0
- package/lib/figure/lib/layout.d.ts +78 -0
- package/lib/figure/lib/layout.js +496 -0
- package/lib/figure/lib/spec.d.ts +114 -0
- package/lib/figure/lib/spec.js +290 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +5 -1
- package/lib/paper/lib/check.d.ts +5 -0
- package/lib/paper/lib/check.js +21 -0
- package/lib/paper/lib/docx.d.ts +26 -0
- package/lib/paper/lib/docx.js +190 -27
- package/lib/paper/lib/image.d.ts +19 -0
- package/lib/paper/lib/image.js +82 -0
- package/lib/paper/lib/layout.js +26 -1
- package/lib/paper/lib/lit-refs.d.ts +30 -0
- package/lib/paper/lib/lit-refs.js +394 -0
- package/lib/paper/lib/lit-verify.d.ts +79 -0
- package/lib/paper/lib/lit-verify.js +556 -0
- package/lib/paper/register.d.ts +1 -1
- package/lib/paper/register.js +37 -1
- package/lib/paper/tools/build.d.ts +4 -0
- package/lib/paper/tools/build.js +79 -4
- package/lib/paper/tools/lit-verify.d.ts +35 -0
- package/lib/paper/tools/lit-verify.js +193 -0
- package/lib/ppt/check.js +5 -0
- package/lib/ppt/design.d.ts +86 -0
- package/lib/ppt/design.js +218 -0
- package/package.json +4 -1
- package/skills/thesis-defense/SKILL.md +25 -1
- package/skills/thesis-eng-design/SKILL.md +40 -20
- package/skills/thesis-literature/SKILL.md +28 -5
- package/skills/thesis-opener/SKILL.md +1 -1
- package/skills/thesis-pipeline/SKILL.md +4 -3
- package/skills/thesis-writing/SKILL.md +4 -1
package/README.md
CHANGED
|
@@ -68,12 +68,12 @@ node scripts/install-into-profile.ts --profile web # 没有 pnpm 时的兜
|
|
|
68
68
|
|---|---|
|
|
69
69
|
| [docs/usage.md](./docs/usage.md) | 使用手册:第一次会话、九阶段、常见动作、产出物、中断续跑 |
|
|
70
70
|
| [docs/autopilot.md](./docs/autopilot.md) | 自动驾驶:四档意图、关卡拍板、何时不介入、降级与关闭 |
|
|
71
|
-
| [docs/tools.md](./docs/tools.md) |
|
|
71
|
+
| [docs/tools.md](./docs/tools.md) | 24 个工具 + 11 个技能一览(名字即契约) |
|
|
72
72
|
| [docs/config.md](./docs/config.md) | 全部配置字段、默认值与约束 |
|
|
73
73
|
| [docs/troubleshooting.md](./docs/troubleshooting.md) | 装了没反应、没弹选择题、PDF/pptx 失败等 |
|
|
74
74
|
| [docs/design.md](./docs/design.md) | 设计文档与 ADR(架构、分层、质量策略、已知边界) |
|
|
75
75
|
| [docs/host-api.md](./docs/host-api.md) | 宿主契约:用到的 DSH 接口与实测行为 |
|
|
76
|
-
| [docs/release.md](./docs/release.md) |
|
|
76
|
+
| [docs/release.md](./docs/release.md) | 发版:`npm run release:minor` + push → GitHub Actions → npm(含 provenance)|
|
|
77
77
|
|
|
78
78
|
## 开发
|
|
79
79
|
|
|
@@ -89,8 +89,9 @@ npm run verify # build + 两个 typecheck + 全部单测 + 审
|
|
|
89
89
|
质量分层:单测/契约、真实场景端到端、真实 cordis 装配、真实 dsh 引擎装载、对外表面审计
|
|
90
90
|
(见 [docs/design.md](./docs/design.md) §9)。
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
**发版**:`npm run release:minor`(改版本号并提交)+ `git push` 即发布——workflow 发现 npm 上没有这个版本
|
|
93
|
+
就发布,发完自动补 tag 与 Release,**不需要手动打 tag**。由 GitHub Actions 跑构建、校验与
|
|
94
|
+
`npm publish --provenance`,见 [docs/release.md](./docs/release.md)。
|
|
94
95
|
|
|
95
96
|
## 许可
|
|
96
97
|
|
package/docs/config.md
CHANGED
|
@@ -65,6 +65,18 @@ profile 的 `cordis.patch.yml` 里,那一行插件的 `config:` 下面:
|
|
|
65
65
|
| `defense.questionsRel` | `07-答辩/预答辩问题库.md` | 问题库位置 |
|
|
66
66
|
| `defense.defaultPages` | `11` | 幻灯默认页数(规范 10-12)|
|
|
67
67
|
|
|
68
|
+
### 插图
|
|
69
|
+
|
|
70
|
+
| 字段 | 默认 | 说明 |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| `figure.drawioPath` | 无 | draw.io 桌面版可执行文件的绝对路径。缺省在 PATH 与常见安装目录(`%LOCALAPPDATA%\Programs\draw.io`、`Program Files\draw.io`、`/Applications/draw.io.app`、`/usr/bin/drawio`)里探测 |
|
|
73
|
+
| `figure.scale` | `3` | PNG 导出倍率。3× 在 15cm 栏宽下约 370dpi;印刷要求更高可调到 4 |
|
|
74
|
+
| `figure.timeoutMs` | `60000` | 单次导出超时(draw.io 冷启动较慢)|
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
figure: { drawioPath: 'D:/Program Files/draw.io/draw.io.exe', scale: 4 }
|
|
78
|
+
```
|
|
79
|
+
|
|
68
80
|
### 代码演练
|
|
69
81
|
|
|
70
82
|
| 字段 | 默认 | 说明 |
|
package/docs/design.md
CHANGED
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
| `src/intake/**` | 问题库 + 状态机 + 意图规格渲染 + 规格闸门 | `registerIntake` |
|
|
65
65
|
| `src/paper/**` | 论文流水线(纯逻辑 + 工具 + 子命令词) | `registerPaper` |
|
|
66
66
|
| `src/dedup/**` | 归一化 + 相似度 + 改写处方 + 报告 | `registerDedup` |
|
|
67
|
+
| `src/figure/**` | 插图:规格校验 + 版面 + mxfile 渲染 + draw.io 导出 + 图表体检 | `registerFigure` |
|
|
67
68
|
| `src/ppt/**` | 幻灯计划 + Marp 渲染 + 转换器探测 | `registerPpt` |
|
|
68
69
|
| `src/codewalk/**` | 代码演练:阶段状态机 + 验证门 + 可评分追问 | `registerCodewalk` |
|
|
69
70
|
| `src/memory/**` | SQLite 跨会话事实 + 相关时回灌 | `registerFacts` / `installFactRecall` |
|
|
@@ -84,12 +85,12 @@
|
|
|
84
85
|
|
|
85
86
|
## 3. 对外表面契约
|
|
86
87
|
|
|
87
|
-
### 3.1 工具(
|
|
88
|
+
### 3.1 工具(24 个,三个命名空间)
|
|
88
89
|
|
|
89
90
|
`thesis_*` / `defense_code_*` / `fact_*` 三组,名字即契约(改名就是破坏性变更)。
|
|
90
91
|
**逐个工具的用途、参数与边界见 [tools.md](./tools.md)**,这里只保留设计约束:
|
|
91
92
|
|
|
92
|
-
- 工具名与命名空间不允许游离:`npm run audit` 断言注册数恰好
|
|
93
|
+
- 工具名与命名空间不允许游离:`npm run audit` 断言注册数恰好 22、且全落在三个前缀内;
|
|
93
94
|
- 每个工具都必须有 `output.schema` 与 `output.render`,返回值是**有界字符串**(不返回对象、不做流式);
|
|
94
95
|
- 工具只操作论文工作区里的东西,跨会话的东西一律走 `fact_*`,两者不混用。
|
|
95
96
|
### 3.2 命令面:**一条斜杠命令都没有**
|
|
@@ -281,6 +282,97 @@ DSH 的 profile 预检(`dsh-app-boot` 的 `evaluatePluginCompatibility`,在
|
|
|
281
282
|
|
|
282
283
|
之前的中间形态(一条 /thesis + 九个动词)在这个版本里被整体替换:它解决了「列表太吵」,
|
|
283
284
|
但没解决「人不该操作命令行」。留在这里作为教训:**先问清人要的是入口还是自动化**。
|
|
285
|
+
|
|
286
|
+
### ADR-16 论文插图用 draw.io 的源文件,而不是 Mermaid 文本
|
|
287
|
+
|
|
288
|
+
原先的设计是「流程图用 Mermaid(源文件留在仓库)」。真实使用暴露了三个问题:
|
|
289
|
+
|
|
290
|
+
1. **排版不可控**:Mermaid 的自动布局在 5 个以上节点时会把图排成一团,论文插图最忌讳这个;
|
|
291
|
+
字号、线型、配色也由渲染器决定,和正文风格对不上。
|
|
292
|
+
2. **进不了 docx**:pandoc 不认 Mermaid 代码块,内置引擎原来也不处理图片,学生最后拿到的是
|
|
293
|
+
一段代码块而不是图。
|
|
294
|
+
3. **改不动**:Mermaid 改一个模块可能整图重排;答辩前导师说「把这块挪到下面」,学生只能重画。
|
|
295
|
+
|
|
296
|
+
于是改成 **draw.io 源文件 + 高分辨率 PNG**:
|
|
297
|
+
|
|
298
|
+
- `thesis_figure create` 只接收**结构化规格**(层与模块 / 节点与边 / 实体与字段 / 参与者与消息),
|
|
299
|
+
坐标由 `figure/lib/layout.ts` 的确定性版面算法生成——同样输入永远同一张图,可测试、可 diff;
|
|
300
|
+
- 落盘两类文件:`.drawio`(唯一真源,可继续在 draw.io 里改)与 `.png`(3× 导出,约 370dpi);
|
|
301
|
+
- 导出走 draw.io 桌面版的 CLI,**探测不启动 GUI**(`drawio --version` 会拉起窗口);
|
|
302
|
+
没有桌面版时给三条替代路径(在线版 / VS Code 扩展 / winget 安装),绝不假装导出成功;
|
|
303
|
+
- `thesis_build` 同时补上内置引擎的嵌图能力:`` 会变成「居中的图 + 图下方的图题」,
|
|
304
|
+
路径解析失败时在 docx 里留一行可读占位,并把问题写进构建说明——缺图必须一眼看见。
|
|
305
|
+
|
|
306
|
+
取舍:多了一个外部依赖(draw.io 桌面版)才能自动导出。这个依赖是**可选**的:
|
|
307
|
+
没有它时源文件照样生成,学生按指引手工导出一次即可,不阻塞写作与构建。
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
### ADR-17 幻灯的"丑"当作可检查的版面问题,而不是审美问题
|
|
312
|
+
**背景**:答辩幻灯最常见的失败形态是「标题 + ▪ 列表」贯穿全篇——11 页里 9 页同一种版式,
|
|
313
|
+
没有图、没有数据、没有层级。学生不是不想做好看,是不知道"好"长什么样,也不知道哪里不对。
|
|
314
|
+
|
|
315
|
+
**决定**:
|
|
316
|
+
1. 定义 10 种版面(`src/ppt/design.ts` 的 `DECK_LAYOUTS`:cover / agenda / compare / rows /
|
|
317
|
+
steps / cards / figure / columns / stats / closing),每页在 Markdown 里用
|
|
318
|
+
`<!-- _class: xxx -->` 标注;配套四条硬规则(每页 ≤4 条要点、不许连续 4 页纯文字、
|
|
319
|
+
全文 ≥2 页视觉锚点、标题 ≤20 字)。
|
|
320
|
+
2. 把规则做成 `thesis_slides check` 里可判定的告警(`design-bullet-wall`、`design-no-visual`、
|
|
321
|
+
`design-no-visual-run`、`design-too-many-bullets` 等),不再靠"记得叮嘱"。
|
|
322
|
+
3. 版心、四档字号、纸色/墨色/单一强调色写成 `DESIGN` 常量;生成器与检查器共用同一套口径。
|
|
323
|
+
|
|
324
|
+
**借鉴与边界**:版面语言(瑞士风:一个强调色、大号序号、色块分区不画边框、留白呼吸)
|
|
325
|
+
借鉴 [歸藏设计 dsh-guizang-design](https://github.com/op7418/dsh-guizang-design)(AGPL-3.0)的
|
|
326
|
+
设计规则**思路**;实现是本仓库自己的 TypeScript 与 pptx 几何,不复制其代码与样式表。
|
|
327
|
+
|
|
328
|
+
**取舍**:插件本身不做 pptx 渲染(仍依赖 marp/pandoc),所以版面规则对 Markdown 生效;
|
|
329
|
+
真正的 pptx 由工作区脚本(如 `07-答辩/build_pptx.py`)按同一套 `DESIGN` 常量绘制。
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
### ADR-18 排版细节按「可验证的规范条目」逐条落实
|
|
334
|
+
|
|
335
|
+
**背景**:论文正文"看起来不对"往往不是文笔问题,而是几条硬规范没落实:封面带页码、目录把自己列进去、
|
|
336
|
+
参考文献没有悬挂缩进、表是全框线网格。这些都能被确定性检查出来。
|
|
337
|
+
|
|
338
|
+
**决定**:
|
|
339
|
+
1. **分节**:封面(无页眉页脚)/ 前置(罗马数字页码)/ 正文+参考文献(题目页眉 + 阿拉伯数字从 1)。
|
|
340
|
+
每节独立 `pgNumType` 与 header/footer 部件;分节后首段抑制 `pageBreakBefore`,避免多出空白页。
|
|
341
|
+
2. **目录**:`TOC \o "1-3" \h \z \u` 域 + `w:dirty`(Word 打开即更新页码);
|
|
342
|
+
「目 录」标题不写 `outlineLvl`,否则目录会把自己列进去;TOC 1–3 样式预置五号宋体、1.5 倍行距、
|
|
343
|
+
点线引导到 15.5 cm;Hyperlink 字符样式改黑色无下划线(否则目录条目是蓝色链接)。
|
|
344
|
+
3. **表格**:三线表(见 ADR-16 旁的表格口径);表题在表上方、五号居中。
|
|
345
|
+
4. **参考文献**:五号、1.5 倍行距、悬挂缩进 0.95 cm。
|
|
346
|
+
5. **元素顺序**:`tblPr` / `pPr` 的子元素一律按 OOXML 架构顺序插入——顺序错了 Word 会报"内容有问题"。
|
|
347
|
+
|
|
348
|
+
**验证**:没有 Word/LibreOffice 时,用 `python-docx` 回读 + XML 顺序校验做断言(分节数、页码格式、
|
|
349
|
+
页眉域、目录 dirty、缩进值、pPr 顺序),而不是"看起来应该没问题"。
|
|
350
|
+
|
|
351
|
+
**取舍**:内置过渡引擎只落实表格与页边距(A4、上 2.5/下 2.5/左 3.0/右 2.5 cm);
|
|
352
|
+
分节页码、目录域、页眉依赖模板级排版,交给 `build_docx.py` 或 pandoc + 学校模板。
|
|
353
|
+
|
|
354
|
+
### ADR-19 发布由「版本号」驱动,tag 是产物而不是开关
|
|
355
|
+
|
|
356
|
+
**背景**:原来发版要先打 tag 再推,tag 名还必须与 `package.json` 逐字一致——漏一步就是一次红 run,
|
|
357
|
+
而 tag 本身没有携带任何信息,只是"我现在要发版了"的暗号。
|
|
358
|
+
|
|
359
|
+
**决定**:
|
|
360
|
+
1. 触发条件改为 `push: branches: [main]`,同时保留 `tags: ['v*']` 兼容手动打 tag;
|
|
361
|
+
2. 是否发布由「`package.json` 的版本在 npm 上是否已存在」决定——**版本号没变就不发**;
|
|
362
|
+
3. 发布成功后由 workflow 自己 `git tag v<version>` 并推上去,再建 Release;
|
|
363
|
+
4. 版本号只有一个来源:`package.json`。`npm run release:minor` 同时改
|
|
364
|
+
`package.json` 与 `package-lock.json`(顶层 + `packages[""]`)并提交,提交信息从版本号派生。
|
|
365
|
+
|
|
366
|
+
**为什么不从 commit message 解析版本**:发布包里写的是 `package.json` 的 version。
|
|
367
|
+
让提交信息决定发什么版本,要么包与 tag 不一致,要么 CI 临时改包导致仓库与 npm 永久错位,
|
|
368
|
+
要么机器人提交回 main 撞保护分支。三者都比"多跑一条 `npm run release:*`"更贵。
|
|
369
|
+
|
|
370
|
+
**取舍**:每次推 main 都会多跑一个 `npm ci` + `npm view`(约 40 秒)才判定跳过;
|
|
371
|
+
换来的是"日常提交随便推、发版只需升版本号"。
|
|
372
|
+
|
|
373
|
+
**验证**:`npm run release:minor -- --dry-run` 只打印不落盘;`publish.yml` 用 PyYAML 解析校验结构与条件;
|
|
374
|
+
真正的判定(已发布则跳过)由 npm 侧 `npm view` 保证,重复触发不会覆盖已发布版本。
|
|
375
|
+
|
|
284
376
|
---
|
|
285
377
|
|
|
286
378
|
## 7. 数据与产物
|
|
@@ -292,6 +384,7 @@ DSH 的 profile 预检(`dsh-app-boot` 的 `evaluatePluginCompatibility`,在
|
|
|
292
384
|
| 进度台账 / 决定日志 / 时间线 | `00-管理/` | `thesis_init` / `thesis_progress` / `thesis_decide` |
|
|
293
385
|
| 文献库与检索审计 | `02-文献/refs.bib`、`检索记录.md`、`笔记/` | `thesis_lit_*` |
|
|
294
386
|
| 章节与产出 | `06-论文/章节/*.md`、`产出/论文.docx` | 写作 + `thesis_build` |
|
|
387
|
+
| 插图 | `06-论文/assets/图/*.drawio`(源)、`*.png/.svg`(导出件)、`图表清单.md`、`导出说明.md` | `thesis_figure` |
|
|
295
388
|
| 合规报告 | `08-合规/`(引用/格式/AI 味/降重/复测) | `thesis_check` / `thesis_stylecheck` / `thesis_originality` |
|
|
296
389
|
| 答辩材料 | `07-答辩/答辩素材.md`、`预答辩问题库.md`、`PPT.md` | `thesis_defense` / `thesis_slides` |
|
|
297
390
|
| 插件状态 | `<cwd>/.paper/`(追问状态、代码演练状态) | `intake/` / `codewalk/` |
|
package/docs/release.md
CHANGED
|
@@ -1,138 +1,147 @@
|
|
|
1
1
|
# 发布
|
|
2
2
|
|
|
3
3
|
发版由 GitHub Actions 完成([`.github/workflows/publish.yml`](../.github/workflows/publish.yml))。
|
|
4
|
-
**打 tag 即发布**,本地不需要 `npm login`,也不需要任何 npm token。
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
**升版本号 + push 就发版,不用打 tag。** 推上去以后 workflow 会自己看 npm 上有没有这个版本,
|
|
6
|
+
没有就发布,发完**自动补 tag 与 GitHub Release**——tag 是发布的产物,不再是发布的前提。
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
```bash
|
|
9
|
+
npm run release:minor # 2.1.0 -> 2.2.0(改 package.json 与 package-lock.json 并提交)
|
|
10
|
+
git push origin main # 推完就自动发布
|
|
11
|
+
```
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
**Select publisher: GitHub Actions**,填四个字段:
|
|
13
|
+
就这两条。`npm run release:patch` / `release:major` 同理。
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|---|---|
|
|
16
|
-
| Organization or user | `booondenz` |
|
|
17
|
-
| Repository | `dsh-thesis` |
|
|
18
|
-
| Workflow filename | `publish.yml`(只写文件名,不带路径)|
|
|
19
|
-
| Environment name | **留空**(除非 workflow 里写了 `environment:`)|
|
|
15
|
+
本地不需要 `npm login`,也不需要任何 npm token。
|
|
20
16
|
|
|
21
|
-
|
|
17
|
+
## 它怎么判断该不该发
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
| 检查 | 结果 |
|
|
20
|
+
|---|---|
|
|
21
|
+
| push 到 `main` | 进入发布流程 |
|
|
22
|
+
| push 的 tag(`v*`) | 同样进入(兼容手动打 tag 的老做法) |
|
|
23
|
+
| `package.json` 的版本 npm 上**没有** | `npm pack --dry-run` → 守卫 → `npm publish` → 自动打 tag → 建 Release |
|
|
24
|
+
| `package.json` 的版本 npm 上**已有** | 只跑检查,跳过发布(不会红,也不会覆盖)|
|
|
25
|
+
| 手动触发(`workflow_dispatch`) | 只做打包预览,不发布、不打 tag |
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
所以:**版本号没变 = 这次 push 不发版**。日常提交随便推,只有 `release:*` 那次会发。
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
3. 不需要 `NPM_TOKEN`,**之前建过的话建议在 Settings → Secrets 里删掉**,免得以后误用。
|
|
29
|
+
## 为什么版本号只认 `package.json`,不从 commit message 解析
|
|
33
30
|
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
发布包里真正写进去的是 `package.json` 的 `version`。如果让提交信息里的 `v2.2.0` 决定发什么版本,
|
|
32
|
+
只有三条路,都不好:
|
|
36
33
|
|
|
37
|
-
|
|
34
|
+
1. **照抄提交信息 → 包里版本不对**:提交写 `v2.2.0`、`package.json` 还是 `2.1.0`,
|
|
35
|
+
npm 上会出现两个"2.1.0"(第二次直接被拒),或者发出去的包版本与 tag 不一致;
|
|
36
|
+
2. **CI 里临时改 `package.json` 再发**:npm 上是 2.2.0,仓库里还是 2.1.0,
|
|
37
|
+
下次谁从仓库装就是旧版本,provenance 里的 commit 也对不上;
|
|
38
|
+
3. **CI 里改完再提交回 main**:机器人提交 + 可能撞保护分支 + 每次发版两个 commit。
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
存成仓库 secret `NPM_TOKEN`,然后在 workflow 的 publish 步骤加回:
|
|
40
|
+
现在的做法是:**版本号只有一处真相(`package.json`),`npm run release:*` 负责同时改两处并提交**,
|
|
41
|
+
提交信息与 tag 名都从它派生(`chore: release v2.2.0` → tag `v2.2.0`),三者不可能不一致。
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
env:
|
|
45
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
46
|
-
```
|
|
43
|
+
## 一次性设置(只做一次,已完成)
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
npm 侧认证走 **Trusted Publishing(OIDC)**:npm 只接受「这个仓库的这个 workflow」发来的包,
|
|
46
|
+
凭据每次运行临时签发,不落盘、不过期、没有 2FA 输 OTP 的问题;provenance 自动附带。
|
|
50
47
|
|
|
51
|
-
|
|
48
|
+
<https://www.npmjs.com/package/dsh-thesis/access> → **Trusted Publishers**:
|
|
52
49
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
50
|
+
| 字段 | 值 |
|
|
51
|
+
|---|---|
|
|
52
|
+
| Organization or user | `booondenz` |
|
|
53
|
+
| Repository | `dsh-thesis` |
|
|
54
|
+
| **Workflow filename** | **`publish.yml`**(只写文件名,不带路径)|
|
|
55
|
+
| Environment name | 留空 |
|
|
56
|
+
|
|
57
|
+
**`publish.yml` 这个文件名不能改**(也不能把发布逻辑挪进 `ci.yml`):npm 的配置绑的就是文件名,
|
|
58
|
+
改名后第一次发布会 403。改了触发条件是安全的,改文件名不是。
|
|
59
|
+
|
|
60
|
+
同一页 **Allowed actions** 里要勾 **Allow npm publish**,只勾 stage 的话每次发版还得去网页做 2FA 批准。
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
## workflow 干了什么
|
|
62
63
|
|
|
63
64
|
| 步骤 | 失败就停 |
|
|
64
65
|
|---|---|
|
|
65
|
-
| `npm ci` | 锁文件与 package.json
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
| `npm
|
|
70
|
-
|
|
|
66
|
+
| `npm ci` | 锁文件与 `package.json` 不同步会红(所以别手改版本号,用 `npm run release:*`)|
|
|
67
|
+
| 读 `package.json` 版本 | — |
|
|
68
|
+
| 手动 tag 与版本一致(仅 tag 触发时)| 防止「tag 写 v2.2.0、包里是 2.1.0」|
|
|
69
|
+
| 该版本是否已发布 | 已存在则跳过发布 |
|
|
70
|
+
| `npm pack --dry-run` | 日志里能直接看到这次包里有什么 |
|
|
71
|
+
| `npm publish` | 内部跑 `prepublishOnly` 守卫:构建 + 类型 + 单测 + 审计 + 端到端;**main 红了在这里被拦下** |
|
|
72
|
+
| 自动打 tag | `git tag v<version>` + push;用 `GITHUB_TOKEN` 推的 tag 不会再触发 workflow,不会套娃 |
|
|
73
|
+
| 建 Release | 标题 `v<version>`,正文自动生成 |
|
|
71
74
|
|
|
72
|
-
|
|
75
|
+
## 手动打 tag(仍然可以,但不再是发版的必要条件)
|
|
73
76
|
|
|
74
|
-
|
|
77
|
+
```bash
|
|
78
|
+
git tag v2.2.0
|
|
79
|
+
git push origin v2.2.0
|
|
80
|
+
```
|
|
75
81
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
workflow 第一步的版本比对就会红);
|
|
80
|
-
4. 标题写 `v2.0.1`,正文可以留空——workflow 里是 `gh release view || gh release create`,
|
|
81
|
-
发现 Release 已存在会跳过;
|
|
82
|
-
5. **Publish release**。
|
|
82
|
+
行为与以前完全一致:先校验 tag 与 `package.json` 一致,再发布。适合"版本号早就提交了、只是补发"的场景。
|
|
83
|
+
|
|
84
|
+
## 备选:用 token(不推荐)
|
|
83
85
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
可信发布不可用时,在 npm 建 **Classic → Automation** token(Granular token 在开了 2FA 的账号上会报 `EOTP`),
|
|
87
|
+
存成仓库 secret `NPM_TOKEN`,然后在 publish 步骤加回:
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
env:
|
|
91
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
并把 `setup-node` 的 `with:` 里加回 `registry-url: https://registry.npmjs.org`。
|
|
95
|
+
Automation token 专为 CI 设计,不受 2FA 影响。
|
|
86
96
|
|
|
87
97
|
## 确认发成功了
|
|
88
98
|
|
|
89
99
|
| 看哪 | 期望 |
|
|
90
100
|
|---|---|
|
|
91
|
-
| Actions → **publish** |
|
|
92
|
-
| `npm view dsh-thesis version` | `2.0
|
|
93
|
-
| `npm view dsh-thesis dist-tags` | `{ latest: '2.0
|
|
94
|
-
|
|
|
95
|
-
|
|
|
96
|
-
|
|
97
|
-
Actions 里**根本没出现 publish 这个 run**,说明 tag 没推上去(或名字不是 `v` 开头);
|
|
98
|
-
出现 run 但红在第一步,通常是 tag 与 `package.json` 版本对不上。
|
|
101
|
+
| Actions → **publish** | 绿;Summary 里有 `https://www.npmjs.com/package/dsh-thesis/v/2.2.0` |
|
|
102
|
+
| `npm view dsh-thesis version` | `2.2.0`(registry 立刻生效,网页可能慢一分钟)|
|
|
103
|
+
| `npm view dsh-thesis dist-tags` | `{ latest: '2.2.0' }` |
|
|
104
|
+
| 仓库 **Tags / Releases** | 自动多了 `v2.2.0` |
|
|
105
|
+
| <https://www.npmjs.com/package/dsh-thesis> | 版本号旁有 **Provenance** 徽章 |
|
|
99
106
|
|
|
100
107
|
## 发完之后:让 DSH 用上新版
|
|
101
108
|
|
|
102
|
-
profile 把版本钉在 `~/.dsh/profiles/<profile>/package.json`
|
|
103
|
-
所以 npm 上发了新版**不会自动生效**。到插件管理器里移除再装一次(会取 `latest`),或者把那条依赖
|
|
104
|
-
改成 `"^2.0.1"` 后重装,然后**重启 DSH**——2.0 删掉了全部斜杠命令,不是热更新能覆盖的。
|
|
109
|
+
profile 把版本钉在 `~/.dsh/profiles/<profile>/package.json` 里,npm 发了新版**不会自动生效**:
|
|
105
110
|
|
|
106
|
-
|
|
111
|
+
```bash
|
|
112
|
+
dsh plugin --profile web add dsh-thesis@2.2.0
|
|
113
|
+
dsh plugin --profile desktop add dsh-thesis@2.2.0
|
|
114
|
+
```
|
|
107
115
|
|
|
108
|
-
|
|
109
|
-
想真发版,还是打 tag。
|
|
116
|
+
然后**重启 DSH**(2.0 删掉了全部斜杠命令,不是热更新能覆盖的)。
|
|
110
117
|
|
|
111
118
|
## 失败排查
|
|
112
119
|
|
|
113
120
|
| 现象 | 原因 |
|
|
114
121
|
|---|---|
|
|
115
|
-
|
|
|
116
|
-
|
|
|
117
|
-
| `
|
|
118
|
-
| `
|
|
119
|
-
| `
|
|
120
|
-
| `
|
|
121
|
-
|
|
|
122
|
+
| Actions 里**根本没有** publish run | push 的不是 `main`,也不是 `v*` tag |
|
|
123
|
+
| publish 绿但 Summary 写"已存在,未发布" | 版本号没升(`npm run release:*` 没跑)|
|
|
124
|
+
| `EOTP` / 要求一次性密码 | 用的是需要 OTP 的 token → 改用可信发布或 Automation token |
|
|
125
|
+
| 被拒、提示只能 `npm stage publish` | 可信发布里没勾 **Allow npm publish** |
|
|
126
|
+
| `403 … OIDC permission denied for this action` | 同上:认证过了,但没给「直接发布」权限 |
|
|
127
|
+
| `401 Unauthorized` | token 过期,或可信发布配置里 workflow 文件名写错 |
|
|
128
|
+
| `npm ci … not in sync` | 手改了 `package.json` 版本没同步锁文件 → 改用 `npm run release:*` |
|
|
129
|
+
| `403 … cannot publish over previously published version` | 版本号没升;workflow 里"已存在则跳过"会挡住,手动发版时要注意 |
|
|
130
|
+
| 守卫里单测红 / 端到端红 | 与 `npm run verify` 同一套;本地先复现 |
|
|
122
131
|
| 守卫警告「未找到 DSH 安装」 | CI 里正常(没有宿主);**发版前请在本地跑一次 `npm run test:host-load` 与 `npm run test:host`** |
|
|
132
|
+
| 自动打 tag 失败但 npm 已发布 | tag 只是标记,事后手动 `git tag v2.2.0 && git push origin v2.2.0` 补上即可 |
|
|
123
133
|
|
|
124
134
|
## 撤回与补救
|
|
125
135
|
|
|
126
|
-
- **已发布的版本不能改**,只能 `npm deprecate dsh-thesis@2.0
|
|
136
|
+
- **已发布的版本不能改**,只能 `npm deprecate dsh-thesis@2.2.0 "原因与替代版本"`。
|
|
127
137
|
- 72 小时内理论上可以 `npm unpublish`,但那会让依赖它的人突然装不上,**不要用**。
|
|
128
|
-
- 发错了就立刻发一个 patch:`
|
|
138
|
+
- 发错了就立刻发一个 patch:`npm run release:patch` + `git push`。
|
|
129
139
|
|
|
130
|
-
##
|
|
140
|
+
## 本地发布(应急)
|
|
131
141
|
|
|
132
142
|
```bash
|
|
133
143
|
npm login
|
|
134
144
|
npm publish --access public # 会跑同一个 prepublishOnly 守卫,会交互式要 OTP
|
|
135
145
|
```
|
|
136
146
|
|
|
137
|
-
|
|
138
|
-
CI 只是把「构建 → 校验 → 发布」串起来,判据完全一样。
|
|
147
|
+
本地发布用你登录后的凭据,不需要 token,也不需要可信发布配置。CI 只是把「构建 → 校验 → 发布」串起来,判据完全一样。
|
package/docs/tools.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# 工具与技能
|
|
2
2
|
|
|
3
3
|
工具名、命令面、技能名都是**对外契约**:改名就是破坏性变更。`npm run audit` 会把这三样
|
|
4
|
-
都核对一遍(
|
|
4
|
+
都核对一遍(24 个工具 / 0 条斜杠命令 / 11 个技能 + 命名与 BOM 检查)。
|
|
5
5
|
|
|
6
6
|
## 命名空间
|
|
7
7
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
| `defense_code_*` | 答辩层的代码演练(把系统拆成讲得清的模块) |
|
|
12
12
|
| `fact_*` | 跨会话事实(学校规范、导师要求、写作偏好) |
|
|
13
13
|
|
|
14
|
-
## `thesis_*`(
|
|
14
|
+
## `thesis_*`(16 个)
|
|
15
15
|
|
|
16
16
|
| 工具 | 一句话 | 关键约束 |
|
|
17
17
|
|---|---|---|
|
|
@@ -23,13 +23,16 @@
|
|
|
23
23
|
| `thesis_lit_search` | 真实检索文献 | Semantic Scholar → DBLP → arXiv → Crossref 降级;写检索缓存与审计记录 |
|
|
24
24
|
| `thesis_lit_save` | 收录进 `refs.bib` | **只接受检索缓存里的 id**(零假文献的落点);DOI 重复自动跳过 |
|
|
25
25
|
| `thesis_lit_note` | 生成阅读笔记骨架 | 五节模板;已存在不覆盖 |
|
|
26
|
+
| `thesis_lit_verify` | 核验候选文献是否真实存在 | Crossref/OpenAlex/DataCite/PubMed 对账;只出结论不改 bib;报告落 08-合规 |
|
|
27
|
+
| `thesis_lit_import` | 导入 Undermind/Elicit/Consensus 导出 | .bib/.ris/.csv;只收录核验通过的;网络不通不入库 |
|
|
26
28
|
| `thesis_review` | 单章六项评审 | 字数区间 / 大纲小节 / 引用编号 / 图表编号 / 未完成标记 / G2 清单 |
|
|
27
|
-
| `thesis_check` | 全文五项检查 |
|
|
29
|
+
| `thesis_check` | 全文五项检查 | 引用双向一致、字数、图表编号与**表题缺失**(有表无「表 x-y 名称」)、术语定义顺序、学校模板探测 |
|
|
28
30
|
| `thesis_stylecheck` | 六条 AI 味启发式 | 模板套话、空洞结论、自我暴露、翻译腔、句式单一、无锚点长段落 |
|
|
29
|
-
| `thesis_build` | 出 `论文.docx` | 有 pandoc 用 pandoc +
|
|
31
|
+
| `thesis_build` | 出 `论文.docx` | 有 pandoc 用 pandoc + 学校模板,没有用内置零依赖生成器(显式标注);章节里的 `` 会嵌进 docx 并配图题 |
|
|
32
|
+
| `thesis_figure` | 论文插图(draw.io) | create 按结构化规格生成可编辑 `.drawio` + 3× PNG(架构/流程/ER/时序/手写 XML);export 批量导出;check 核对源文件↔导出件↔正文引用↔图号;没有 draw.io 桌面版时给三条替代路径,绝不假装成功 |
|
|
30
33
|
| `thesis_originality` | 本地降重度量 | scan / verify / report;**不接收费查重**,报告里是本地估算 |
|
|
31
34
|
| `thesis_defense` | 答辩素材 + 六类问题库 | 每个问题带证据锚点(哪个文件哪一行) |
|
|
32
|
-
| `thesis_slides` | 答辩幻灯 | Marp 兼容 Markdown;outline / convert / check / guide;pptx 依赖外部引擎 |
|
|
35
|
+
| `thesis_slides` | 答辩幻灯 | Marp 兼容 Markdown;outline / convert / check / guide;check 含版面设计规则(禁 bullet wall、≥2 页视觉锚点);pptx 依赖外部引擎 |
|
|
33
36
|
|
|
34
37
|
## `defense_code_*`(3 个)
|
|
35
38
|
|
package/docs/troubleshooting.md
CHANGED
|
@@ -60,6 +60,24 @@ pandoc 07-答辩/PPT.md -o 07-答辩/PPT.pptx
|
|
|
60
60
|
两者都没有时,`thesis_slides convert` 会写一份 `07-答辩/PPT转换说明.md`(探测结果 + 确切命令 + 退出码),
|
|
61
61
|
**绝不假装成功**。装了 marp 之后重跑即可。
|
|
62
62
|
|
|
63
|
+
## 图没有导出成 PNG
|
|
64
|
+
|
|
65
|
+
论文插图的真相是 `.drawio` 源文件(`06-论文/assets/图/`),PNG 由外部工具导出。三条路:
|
|
66
|
+
|
|
67
|
+
1. 装桌面版(推荐):`winget install --id JGraph.Draw -e`,装完重跑 `thesis_figure action=export`;
|
|
68
|
+
2. 在线版:https://app.diagrams.net → 打开 `.drawio` → 文件 → 导出为 → PNG(缩放 300%);
|
|
69
|
+
3. VS Code:安装 `hediet.vscode-drawio`,打开 `.drawio` 后 `F1` → `Draw.io: Export`。
|
|
70
|
+
|
|
71
|
+
`thesis_figure action=export` 会把探测结果、确切命令、退出码写进 `06-论文/assets/图/导出说明.md`,
|
|
72
|
+
**绝不假装成功**。装了桌面版但不在 PATH 时,在配置里写 `figure.drawioPath`。
|
|
73
|
+
|
|
74
|
+
## 论文里图片显示不出来 / 位置不对
|
|
75
|
+
|
|
76
|
+
- 路径:章节里的图片路径**相对章节文件**(`06-论文/章节/`),标准写法是 `../assets/图/x.png`;
|
|
77
|
+
写成相对仓库根的 `06-论文/assets/图/x.png` 也能解析,但换编辑器预览会挂。
|
|
78
|
+
- 图题:图片下一行的 `` 就是图题来源;alt 为空时 docx 里不会有图题。
|
|
79
|
+
- 查一遍:`thesis_figure action=check` 会列出断链、缺图题、旧导出与编号跳号。
|
|
80
|
+
|
|
63
81
|
## 旧格式打不开
|
|
64
82
|
|
|
65
83
|
`.doc` / `.xls` / `.ppt` 不支持,先另存为 `.docx` / `.xlsx` / `.pptx`。
|
package/docs/usage.md
CHANGED
|
@@ -59,7 +59,9 @@
|
|
|
59
59
|
| 换学校模板 | 把模板放进 `06-论文/assets/学校模板/`,再跑 `thesis_check`(探测到就用,探测不到显式标注「非学校模板」)|
|
|
60
60
|
| 只改某一章 | 直接说「改第三章的方法部分」,改完 `thesis_review 03-设计` |
|
|
61
61
|
| 回填学校查重结果 | `thesis_originality action=report detected_rate=12 detected_system=知网` |
|
|
62
|
-
| 出 Word | `thesis_build`(有 pandoc 用 pandoc +
|
|
62
|
+
| 出 Word | `thesis_build`(有 pandoc 用 pandoc + 模板,没有就用内置零依赖生成器;章节里的图会嵌进去并配图题)|
|
|
63
|
+
| 画论文插图 | `thesis_figure action=create kind=architecture chapter=04-系统设计 spec=...` → 生成 `.drawio` + PNG + 图题;改了图重跑 `action=export` |
|
|
64
|
+
| 图对不上(断链/旧图/编号跳号) | `thesis_figure action=check` → `06-论文/assets/图/图表清单.md` |
|
|
63
65
|
| 只做答辩 | `thesis_defense` → `thesis_slides` → 代码演练 `defense_code_*` |
|
|
64
66
|
| 记住学校规范 | `fact_remember key=school.dedup.system value="知网,查重阈值 20%"` |
|
|
65
67
|
| 看进度 | `thesis_progress action=report` |
|
|
@@ -73,6 +75,7 @@
|
|
|
73
75
|
| 进度台账 / 决定日志 / 时间线 | `00-管理/` |
|
|
74
76
|
| 文献库与检索审计 | `02-文献/refs.bib`、`检索记录.md`、`笔记/` |
|
|
75
77
|
| 章节与 Word | `06-论文/章节/*.md`、`06-论文/产出/论文.docx` |
|
|
78
|
+
| 插图(源文件 / 导出件 / 清单) | `06-论文/assets/图/`(`.drawio`、`.png`、`图表清单.md`、`导出说明.md`) |
|
|
76
79
|
| 答辩素材 / 幻灯 / 问题库 | `07-答辩/` |
|
|
77
80
|
| 检查报告(引用 / 格式 / AI 味 / 降重) | `08-合规/` |
|
|
78
81
|
|
package/lib/config.d.ts
CHANGED
|
@@ -35,6 +35,15 @@ export interface PptOptions {
|
|
|
35
35
|
/** 单次外部转换的超时(毫秒)。 */
|
|
36
36
|
timeoutMs: number;
|
|
37
37
|
}
|
|
38
|
+
/** 论文插图(draw.io 源文件 + 外部导出)。 */
|
|
39
|
+
export interface FigureOptions {
|
|
40
|
+
/** 显式指定的 draw.io 可执行文件;缺省在 PATH 与常见安装目录里探测。 */
|
|
41
|
+
drawioPath?: string;
|
|
42
|
+
/** 导出倍率:3× 在 15cm 栏宽下约 370dpi。 */
|
|
43
|
+
scale: number;
|
|
44
|
+
/** 单次导出超时(毫秒):draw.io 冷启动较慢,给足余量。 */
|
|
45
|
+
timeoutMs: number;
|
|
46
|
+
}
|
|
38
47
|
/** 材料到手后的逐题追问。 */
|
|
39
48
|
export interface IntakeOptions {
|
|
40
49
|
/** 单轮追问最多问几个问题(一次一问,但允许上限)。 */
|
|
@@ -101,6 +110,8 @@ export interface PaperConfig extends GateOptions {
|
|
|
101
110
|
stylecheck?: Partial<StylecheckOptions>;
|
|
102
111
|
ppt?: Partial<PptOptions>;
|
|
103
112
|
defense?: Partial<DefenseOptions>;
|
|
113
|
+
/** 论文插图(draw.io)。 */
|
|
114
|
+
figure?: Partial<FigureOptions>;
|
|
104
115
|
/** 代码演练(答辩层)。 */
|
|
105
116
|
codeWalkthrough?: Partial<CodeWalkthroughOptions>;
|
|
106
117
|
/** 自动驾驶(后台推进 + 开头一道选择题 + 关卡拍板)。 */
|
|
@@ -116,6 +127,7 @@ export declare const PAPER_DEFAULTS: {
|
|
|
116
127
|
stylecheck: StylecheckOptions;
|
|
117
128
|
ppt: PptOptions;
|
|
118
129
|
defense: DefenseOptions;
|
|
130
|
+
figure: FigureOptions;
|
|
119
131
|
codeWalkthrough: CodeWalkthroughOptions;
|
|
120
132
|
autopilot: AutopilotOptions;
|
|
121
133
|
recall: RecallOptions;
|
|
@@ -130,6 +142,7 @@ export interface ResolvedPaperConfig {
|
|
|
130
142
|
readonly stylecheck: StylecheckOptions;
|
|
131
143
|
readonly ppt: PptOptions;
|
|
132
144
|
readonly defense: DefenseOptions;
|
|
145
|
+
readonly figure: FigureOptions;
|
|
133
146
|
readonly codeWalkthrough: CodeWalkthroughOptions;
|
|
134
147
|
readonly autopilot: AutopilotOptions;
|
|
135
148
|
readonly recall: RecallOptions;
|
package/lib/config.js
CHANGED
|
@@ -28,6 +28,7 @@ export const PAPER_DEFAULTS = {
|
|
|
28
28
|
questionsRel: '07-答辩/预答辩问题库.md',
|
|
29
29
|
defaultPages: 11,
|
|
30
30
|
},
|
|
31
|
+
figure: { scale: 3, timeoutMs: 60_000 },
|
|
31
32
|
codeWalkthrough: {
|
|
32
33
|
stateDir: '.paper',
|
|
33
34
|
gates: {
|
|
@@ -43,7 +44,7 @@ export const PAPER_DEFAULTS = {
|
|
|
43
44
|
};
|
|
44
45
|
/** 补全嵌套块默认值。 */
|
|
45
46
|
export function resolveConfig(config = {}) {
|
|
46
|
-
const { workspace, memoryPath, ingest, intake, similarity, stylecheck, ppt, defense, codeWalkthrough, autopilot, recall, writingGate, destructiveGate, writingIntentPatterns, criteriaMarkers, bypassMarkers, maxQuestions, destructiveToolNames, destructiveRules, } = config;
|
|
47
|
+
const { workspace, memoryPath, ingest, intake, similarity, stylecheck, ppt, defense, figure, codeWalkthrough, autopilot, recall, writingGate, destructiveGate, writingIntentPatterns, criteriaMarkers, bypassMarkers, maxQuestions, destructiveToolNames, destructiveRules, } = config;
|
|
47
48
|
return {
|
|
48
49
|
workspace,
|
|
49
50
|
memoryPath,
|
|
@@ -53,6 +54,7 @@ export function resolveConfig(config = {}) {
|
|
|
53
54
|
stylecheck: { ...PAPER_DEFAULTS.stylecheck, ...stylecheck },
|
|
54
55
|
ppt: { ...PAPER_DEFAULTS.ppt, ...ppt },
|
|
55
56
|
defense: { ...PAPER_DEFAULTS.defense, ...defense },
|
|
57
|
+
figure: { ...PAPER_DEFAULTS.figure, ...figure },
|
|
56
58
|
codeWalkthrough: {
|
|
57
59
|
...PAPER_DEFAULTS.codeWalkthrough,
|
|
58
60
|
...codeWalkthrough,
|
|
@@ -113,6 +115,11 @@ export const Config = z.object({
|
|
|
113
115
|
questionsRel: z.string().default(PAPER_DEFAULTS.defense.questionsRel),
|
|
114
116
|
defaultPages: z.natural().min(1).default(PAPER_DEFAULTS.defense.defaultPages),
|
|
115
117
|
}),
|
|
118
|
+
figure: z.object({
|
|
119
|
+
drawioPath: z.string(),
|
|
120
|
+
scale: z.natural().min(1).default(PAPER_DEFAULTS.figure.scale),
|
|
121
|
+
timeoutMs: z.natural().default(PAPER_DEFAULTS.figure.timeoutMs),
|
|
122
|
+
}),
|
|
116
123
|
codeWalkthrough: z.object({
|
|
117
124
|
stateDir: z.string().default(PAPER_DEFAULTS.codeWalkthrough.stateDir),
|
|
118
125
|
gates: z.dict(z.object({
|