dsh-thesis 1.0.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 (188) hide show
  1. package/DESIGN.md +390 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE.md +10 -0
  4. package/README.md +253 -0
  5. package/cordis.patch.yml +17 -0
  6. package/docs/host-api.md +640 -0
  7. package/lib/codewalk/commands.d.ts +23 -0
  8. package/lib/codewalk/commands.js +168 -0
  9. package/lib/codewalk/engine.d.ts +108 -0
  10. package/lib/codewalk/engine.js +449 -0
  11. package/lib/codewalk/errors.d.ts +31 -0
  12. package/lib/codewalk/errors.js +20 -0
  13. package/lib/codewalk/fs-types.d.ts +34 -0
  14. package/lib/codewalk/fs-types.js +10 -0
  15. package/lib/codewalk/gate.d.ts +30 -0
  16. package/lib/codewalk/gate.js +60 -0
  17. package/lib/codewalk/host-types.d.ts +198 -0
  18. package/lib/codewalk/host-types.js +11 -0
  19. package/lib/codewalk/prestep.d.ts +17 -0
  20. package/lib/codewalk/prestep.js +62 -0
  21. package/lib/codewalk/register.d.ts +23 -0
  22. package/lib/codewalk/register.js +31 -0
  23. package/lib/codewalk/skill.d.ts +15 -0
  24. package/lib/codewalk/skill.js +57 -0
  25. package/lib/codewalk/tools.d.ts +18 -0
  26. package/lib/codewalk/tools.js +314 -0
  27. package/lib/codewalk/types.d.ts +151 -0
  28. package/lib/codewalk/types.js +9 -0
  29. package/lib/commands.d.ts +33 -0
  30. package/lib/commands.js +60 -0
  31. package/lib/config.d.ts +125 -0
  32. package/lib/config.js +139 -0
  33. package/lib/dedup/commands.d.ts +21 -0
  34. package/lib/dedup/commands.js +93 -0
  35. package/lib/dedup/index.d.ts +75 -0
  36. package/lib/dedup/index.js +331 -0
  37. package/lib/dedup/normalize.d.ts +125 -0
  38. package/lib/dedup/normalize.js +329 -0
  39. package/lib/dedup/report.d.ts +114 -0
  40. package/lib/dedup/report.js +309 -0
  41. package/lib/dedup/rewrite.d.ts +71 -0
  42. package/lib/dedup/rewrite.js +228 -0
  43. package/lib/dedup/similarity.d.ts +169 -0
  44. package/lib/dedup/similarity.js +323 -0
  45. package/lib/gates/dangerous.d.ts +22 -0
  46. package/lib/gates/dangerous.js +47 -0
  47. package/lib/gates/detect.d.ts +54 -0
  48. package/lib/gates/detect.js +106 -0
  49. package/lib/gates/messages.d.ts +39 -0
  50. package/lib/gates/messages.js +74 -0
  51. package/lib/gates/prompt.d.ts +21 -0
  52. package/lib/gates/prompt.js +56 -0
  53. package/lib/gates/writing-intent.d.ts +49 -0
  54. package/lib/gates/writing-intent.js +68 -0
  55. package/lib/index.d.ts +36 -0
  56. package/lib/index.js +76 -0
  57. package/lib/ingest/code.d.ts +71 -0
  58. package/lib/ingest/code.js +356 -0
  59. package/lib/ingest/commands.d.ts +23 -0
  60. package/lib/ingest/commands.js +74 -0
  61. package/lib/ingest/docx.d.ts +29 -0
  62. package/lib/ingest/docx.js +92 -0
  63. package/lib/ingest/index.d.ts +179 -0
  64. package/lib/ingest/index.js +640 -0
  65. package/lib/ingest/ooxml.d.ts +58 -0
  66. package/lib/ingest/ooxml.js +393 -0
  67. package/lib/ingest/pdf.d.ts +86 -0
  68. package/lib/ingest/pdf.js +1016 -0
  69. package/lib/ingest/pptx.d.ts +32 -0
  70. package/lib/ingest/pptx.js +116 -0
  71. package/lib/ingest/text.d.ts +25 -0
  72. package/lib/ingest/text.js +180 -0
  73. package/lib/ingest/types.d.ts +48 -0
  74. package/lib/ingest/types.js +47 -0
  75. package/lib/ingest/xlsx.d.ts +72 -0
  76. package/lib/ingest/xlsx.js +411 -0
  77. package/lib/ingest/zip.d.ts +76 -0
  78. package/lib/ingest/zip.js +393 -0
  79. package/lib/intake/definitions.d.ts +65 -0
  80. package/lib/intake/definitions.js +42 -0
  81. package/lib/intake/gate-rules.d.ts +57 -0
  82. package/lib/intake/gate-rules.js +118 -0
  83. package/lib/intake/gate.d.ts +24 -0
  84. package/lib/intake/gate.js +86 -0
  85. package/lib/intake/index.d.ts +76 -0
  86. package/lib/intake/index.js +468 -0
  87. package/lib/intake/questions.d.ts +169 -0
  88. package/lib/intake/questions.js +720 -0
  89. package/lib/intake/spec.d.ts +66 -0
  90. package/lib/intake/spec.js +221 -0
  91. package/lib/intake/state.d.ts +192 -0
  92. package/lib/intake/state.js +420 -0
  93. package/lib/memory/recall.d.ts +69 -0
  94. package/lib/memory/recall.js +177 -0
  95. package/lib/memory/register.d.ts +37 -0
  96. package/lib/memory/register.js +52 -0
  97. package/lib/memory/service.d.ts +39 -0
  98. package/lib/memory/service.js +39 -0
  99. package/lib/memory/store.d.ts +45 -0
  100. package/lib/memory/store.js +123 -0
  101. package/lib/memory/tools.d.ts +19 -0
  102. package/lib/memory/tools.js +195 -0
  103. package/lib/memory/types.d.ts +55 -0
  104. package/lib/memory/types.js +6 -0
  105. package/lib/paper/commands.d.ts +13 -0
  106. package/lib/paper/commands.js +84 -0
  107. package/lib/paper/lib/aicheck.d.ts +38 -0
  108. package/lib/paper/lib/aicheck.js +241 -0
  109. package/lib/paper/lib/bibtex.d.ts +21 -0
  110. package/lib/paper/lib/bibtex.js +114 -0
  111. package/lib/paper/lib/check.d.ts +32 -0
  112. package/lib/paper/lib/check.js +215 -0
  113. package/lib/paper/lib/defense.d.ts +48 -0
  114. package/lib/paper/lib/defense.js +220 -0
  115. package/lib/paper/lib/docx.d.ts +35 -0
  116. package/lib/paper/lib/docx.js +213 -0
  117. package/lib/paper/lib/layout.d.ts +41 -0
  118. package/lib/paper/lib/layout.js +572 -0
  119. package/lib/paper/lib/ledger.d.ts +112 -0
  120. package/lib/paper/lib/ledger.js +349 -0
  121. package/lib/paper/lib/lit-api.d.ts +59 -0
  122. package/lib/paper/lib/lit-api.js +296 -0
  123. package/lib/paper/lib/lit-cache.d.ts +32 -0
  124. package/lib/paper/lib/lit-cache.js +91 -0
  125. package/lib/paper/lib/project.d.ts +29 -0
  126. package/lib/paper/lib/project.js +93 -0
  127. package/lib/paper/lib/review.d.ts +37 -0
  128. package/lib/paper/lib/review.js +194 -0
  129. package/lib/paper/lib/zip.d.ts +14 -0
  130. package/lib/paper/lib/zip.js +124 -0
  131. package/lib/paper/register.d.ts +20 -0
  132. package/lib/paper/register.js +183 -0
  133. package/lib/paper/tools/aicheck.d.ts +6 -0
  134. package/lib/paper/tools/aicheck.js +38 -0
  135. package/lib/paper/tools/build.d.ts +27 -0
  136. package/lib/paper/tools/build.js +166 -0
  137. package/lib/paper/tools/check.d.ts +7 -0
  138. package/lib/paper/tools/check.js +79 -0
  139. package/lib/paper/tools/decision.d.ts +13 -0
  140. package/lib/paper/tools/decision.js +53 -0
  141. package/lib/paper/tools/defense.d.ts +11 -0
  142. package/lib/paper/tools/defense.js +74 -0
  143. package/lib/paper/tools/init.d.ts +23 -0
  144. package/lib/paper/tools/init.js +99 -0
  145. package/lib/paper/tools/lit.d.ts +27 -0
  146. package/lib/paper/tools/lit.js +236 -0
  147. package/lib/paper/tools/progress.d.ts +18 -0
  148. package/lib/paper/tools/progress.js +77 -0
  149. package/lib/paper/tools/review.d.ts +11 -0
  150. package/lib/paper/tools/review.js +41 -0
  151. package/lib/ppt/actions.d.ts +97 -0
  152. package/lib/ppt/actions.js +263 -0
  153. package/lib/ppt/check.d.ts +64 -0
  154. package/lib/ppt/check.js +185 -0
  155. package/lib/ppt/commands.d.ts +28 -0
  156. package/lib/ppt/commands.js +71 -0
  157. package/lib/ppt/convert.d.ts +146 -0
  158. package/lib/ppt/convert.js +423 -0
  159. package/lib/ppt/index.d.ts +45 -0
  160. package/lib/ppt/index.js +57 -0
  161. package/lib/ppt/marp.d.ts +74 -0
  162. package/lib/ppt/marp.js +165 -0
  163. package/lib/ppt/outline.d.ts +206 -0
  164. package/lib/ppt/outline.js +695 -0
  165. package/lib/shared/define-tool.d.ts +77 -0
  166. package/lib/shared/define-tool.js +235 -0
  167. package/lib/shared/fs-errors.d.ts +50 -0
  168. package/lib/shared/fs-errors.js +90 -0
  169. package/lib/shared/index.d.ts +31 -0
  170. package/lib/shared/index.js +32 -0
  171. package/lib/shared/spawn.d.ts +38 -0
  172. package/lib/shared/spawn.js +50 -0
  173. package/lib/shared/text.d.ts +14 -0
  174. package/lib/shared/text.js +26 -0
  175. package/package.json +82 -0
  176. package/skills/code-walkthrough/SKILL.md +94 -0
  177. package/skills/code-walkthrough/references/examples.md +129 -0
  178. package/skills/paper-dedup/SKILL.md +58 -0
  179. package/skills/paper-intake/SKILL.md +64 -0
  180. package/skills/thesis-citation/SKILL.md +67 -0
  181. package/skills/thesis-defense/SKILL.md +87 -0
  182. package/skills/thesis-eng-design/SKILL.md +97 -0
  183. package/skills/thesis-inquiry/SKILL.md +55 -0
  184. package/skills/thesis-inquiry/references/intent-spec-template.md +39 -0
  185. package/skills/thesis-literature/SKILL.md +56 -0
  186. package/skills/thesis-opener/SKILL.md +77 -0
  187. package/skills/thesis-pipeline/SKILL.md +121 -0
  188. package/skills/thesis-writing/SKILL.md +86 -0
package/DESIGN.md ADDED
@@ -0,0 +1,390 @@
1
+ # dsh-thesis 设计文档
2
+
3
+ **一句话**:让一个对流程不了解的本科生,把「学校模板 + 论文要求 + 实验数据 + 代码 + 参考文献」这堆材料,
4
+ 在 AI 的带教下变成**一篇真实系统与真实数据背书、符合学校规范、经得起查重与答辩的论文**,
5
+ 外加**一个能在答辩席上讲清自己系统的作者**。
6
+
7
+ ---
8
+
9
+ ## 1. 设计目标(五条可验收标准)
10
+
11
+ 不是功能数量,而是五件能被检查的事:
12
+
13
+ 1. **零假文献**:每条参考文献都来自真实学术检索,工具层强制(`thesis_lit_save` 只接受检索缓存 id)。
14
+ 2. **零假成果**:每个实验数据、截图都来自真实运行;原创性自查明文禁止为降重改动数据与结论。
15
+ 3. **人是作者**:关键决策有用户书面拍板(G1-G4 闸门 + 决定日志),答辩能讲清「为什么」。
16
+ 4. **规范驱动**:格式/引用/字数/模板以学校真实文件为准;缺失时显式标注「通用过渡模板」。
17
+ 5. **真的能跑**:所有工具可执行、可失败、有测试;文档描述与实现一一对应。
18
+
19
+ **唯一的领域模型**:材料 → 要求 → 九阶段 → 论文与答辩。对外工具只有两个命名空间,
20
+ `thesis_*`(操作论文工作区)与 `fact_*`(跨会话仍成立的事实),答辩层的代码演练是 `defense_code_*`。
21
+
22
+ **最重要的一条设计取舍**:**先追问、后动手**。写错方向的代价是整章重写,而问清楚只要十分钟。
23
+ `thesis_intake` 把模糊口述收敛成《意图规格》(`00-管理/意图规格.md`),
24
+ 后续写作、检查、原创性自查、幻灯、答辩**只依据这份文件**。
25
+
26
+ ---
27
+
28
+ ## 2. 总体架构
29
+
30
+ ```
31
+ ┌──────────────────────────────────────────────────────────────────────┐
32
+ │ DSH(Web / CLI):自然语言 + /thesis-* 命令 │
33
+ ├──────────────────────────────────────────────────────────────────────┤
34
+ │ 单一插件 dsh-thesis(Cordis 插件,纯 TypeScript,一行 cordis.patch.yml)│
35
+ │ │
36
+ │ 入口层 ingest/(材料摄取) intake/(逐题追问 → 意图规格) │
37
+ │ 流水线 paper/(台账/关卡/文献/评审/检查/docx/答辩素材) │
38
+ │ 合规层 dedup/(本地相似度 + 改写处方 + 复测) │
39
+ │ 答辩层 ppt/(Marp Markdown + 外部转换器) codewalk/(代码演练) │
40
+ │ 横切层 memory/(跨会话事实 + 相关时自动回灌) │
41
+ │ 闸门层 gates/(写作意图闸门 + 不可逆操作闸门) intake/gate(规格闸门)│
42
+ │ 共享层 shared/(工具定义器、文本与文件系统错误工具、子进程助手) │
43
+ ├──────────────────────────────────────────────────────────────────────┤
44
+ │ 技能包 skills/**(11 个方法论技能,`thesis_init` 复制到论文仓库 │
45
+ │ .dsh/skills/,项目级 rank 100 最高优先级,随论文 git 版本化) │
46
+ ├──────────────────────────────────────────────────────────────────────┤
47
+ │ 论文工作区(git 仓库,唯一数据真相):00-管理 … 08-合规 + 意图规格 │
48
+ └──────────────────────────────────────────────────────────────────────┘
49
+ ```
50
+
51
+ ### 2.1 目录与模块职责
52
+
53
+ | 路径 | 职责 | 对外表面 |
54
+ |---|---|---|
55
+ | `src/index.ts` | 唯一装配层:`apply()` 调各模块 register,最后装闸门 | `name` / `inject` / `Config` / `apply` |
56
+ | `src/config.ts` | 统一配置 schema + 默认值单一来源 + `resolveConfig` | `Config` / `PAPER_DEFAULTS` |
57
+ | `src/commands.ts` | 斜杠命令的聚合层(`/thesis-defense` 同时覆盖幻灯与代码演练) | `registerDefenseCommand` |
58
+ | `src/shared/**` | 工具胶水、`definePaperTool`、文本与 fs 错误工具、`spawnCommand` | `definePaperTool` 等 |
59
+ | `src/gates/**` | 写作意图闸门(`agent/pre-step`)+ 不可逆操作闸门(`tools/pre-execute`) | `installWritingGate` / `installDangerousGate` |
60
+ | `src/ingest/**` | ZIP/OOXML/PDF 解析 → 文本;源码目录 → **代码结构摘要**(不贴正文) | `registerIngest` |
61
+ | `src/intake/**` | 问题库 + 状态机 + 意图规格渲染 + 规格闸门 | `registerIntake` |
62
+ | `src/paper/**` | 论文流水线(纯逻辑 + 工具 + 命令) | `registerPaper` |
63
+ | `src/dedup/**` | 归一化 + 相似度 + 改写处方 + 报告 | `registerDedup` |
64
+ | `src/ppt/**` | 幻灯计划 + Marp 渲染 + 转换器探测 | `registerPpt` |
65
+ | `src/codewalk/**` | 代码演练:阶段状态机 + 验证门 + 可评分追问 | `registerCodewalk` |
66
+ | `src/memory/**` | SQLite 跨会话事实 + 相关时回灌 | `registerFacts` / `installFactRecall` |
67
+
68
+ ### 2.2 分层规则(全仓库唯一的硬性架构约束)
69
+
70
+ > **纯逻辑不依赖宿主,宿主胶水不含业务判断。**
71
+
72
+ 每个模块都拆成「零宿主依赖的纯函数层」(可 `node --test` 直跑)+「很薄的 register 层」。
73
+ 收益是可测性与可替换性:记忆的 SQL 语义、原创性度量的相似度、幻灯渲染、追问排序、
74
+ 代码演练的状态机,全都能在没有 DSH 运行时的环境里被完整验证。
75
+
76
+ 第二条规则:**面向学生的概念不来自模块名**。模块可以叫 `memory/`,
77
+ 但学生看到的说法是「跨会话记住学校规范」,而不是某个以「记忆」命名、需要学生自己调用的工具
78
+ (对外工具是 `fact_*`:`fact_search` / `fact_remember` / `fact_context`)。
79
+
80
+ ---
81
+
82
+ ## 3. 对外表面契约
83
+
84
+ ### 3.1 工具(21 个,三个命名空间)
85
+
86
+ **`thesis_*`:操作论文工作区里的东西**
87
+
88
+ | 工具 | 学生视角的一句话 |
89
+ |---|---|
90
+ | `thesis_ingest` | 把我的材料读进来(docx/xlsx/pptx/pdf/csv/代码 → 文本与结构摘要 + 材料清单) |
91
+ | `thesis_intake` | 一次问我一个要求问题,问完写成《意图规格》 |
92
+ | `thesis_init` | 建论文工作区(目录、台账、决定日志、七章模板、技能包) |
93
+ | `thesis_progress` | 看进度 / 过闸门 G1-G4 |
94
+ | `thesis_decide` | 记下我为什么这么定(答辩要用的证据) |
95
+ | `thesis_lit_search` / `thesis_lit_save` / `thesis_lit_note` | 真实检索文献 / 收录进 refs.bib / 生成阅读笔记 |
96
+ | `thesis_review` | 单章六项评审(字数、大纲、引用、图表编号、未完成标记、G2 清单) |
97
+ | `thesis_check` | 全文五项检查(引用双向一致、字数、编号、术语、学校模板探测) |
98
+ | `thesis_stylecheck` | 写作风格自查(六条启发式,附行号与改写建议) |
99
+ | `thesis_build` | 出论文 `.docx`(优先 pandoc + 学校模板,无 pandoc 用内置零依赖生成器) |
100
+ | `thesis_originality` | 原创性自查:scan 定位高风险段落 → verify 复测降幅 → report 汇总 |
101
+
102
+ **`thesis_*` 的答辩部分**
103
+
104
+ | 工具 | 学生视角的一句话 |
105
+ |---|---|
106
+ | `thesis_defense` | 提取答辩素材 + 六类必问问题库(附证据锚点) |
107
+ | `thesis_slides` | 生成 10-12 页 Marp 幻灯,并可选转换为 `.pptx` |
108
+
109
+ **`defense_code_*`:代码演练(答辩层)**
110
+
111
+ | 工具 | 学生视角的一句话 |
112
+ |---|---|
113
+ | `defense_code_status` | 我的系统我讲得清吗(阶段、里程碑、验证门、未通过的问题) |
114
+ | `defense_code_next` | 下一个该弄懂的模块(含 todo 与评分要点) |
115
+ | `defense_code_update` | 登记/推进/评分/重试(每次改动立即落盘) |
116
+
117
+ **`fact_*`:跨会话事实**
118
+
119
+ | 工具 | 学生视角的一句话 |
120
+ |---|---|
121
+ | `fact_search` / `fact_remember` / `fact_context` | 上次记下的学校规范还在吗 / 记住这条稳定事实 / 把这个课题已知事实拉回来 |
122
+
123
+ ### 3.2 命令(9 个)
124
+
125
+ `/thesis-status` `/thesis-decide` `/thesis-lit` `/thesis-check` `/thesis-build`
126
+ `/thesis-ingest` `/thesis-intake` `/thesis-originality` `/thesis-defense`
127
+
128
+ 命令名必须匹配 DSH 的 `/^[a-z][a-z0-9_-]*$/`;`/thesis-defense` 的子命令按侧分派:
129
+ 幻灯侧 `prepare`(= outline)/ `convert` / `check` / `guide`,代码演练侧 `new` / `status` / `check`。
130
+
131
+ ---
132
+
133
+ ## 4. 配置契约
134
+
135
+ 所有字段都有出厂默认值,`PAPER_DEFAULTS` 是 schema `.default()` 与代码侧回退的**单一来源**
136
+ (绝不让「缺配置」退化成「静默关闸门」)。配置面只用论文领域词汇:
137
+
138
+ ```ts
139
+ export interface PaperConfig extends GateOptions {
140
+ workspace?: string // 缺省从会话 cwd 向上探测 00-管理/进度台账.md
141
+ memoryPath?: string // 缺省 $DSH_HOME/paper-memory.db
142
+ ingest?: Partial<IngestOptions>
143
+ intake?: Partial<IntakeOptions>
144
+ similarity?: Partial<SimilarityOptions>
145
+ stylecheck?: Partial<StylecheckOptions>
146
+ ppt?: Partial<PptOptions>
147
+ defense?: Partial<DefenseOptions>
148
+ codeWalkthrough?: Partial<CodeWalkthroughOptions>
149
+ recall?: Partial<RecallOptions>
150
+ }
151
+ ```
152
+
153
+ `GateOptions` 管两个闸门:`writingGate`(要求没立稳时拦截「开始写」)、
154
+ `destructiveGate`(不可逆命令前提请人类拍板),以及它们各自的模式列表与 `maxQuestions`。
155
+
156
+ **`workspace` 的语义是确定的**:配置了就只认它;该路径下没有台账时**明确报错**,
157
+ 绝不悄悄退回到 cwd 探测去写到别的目录。
158
+
159
+ ---
160
+
161
+ ## 5. 领域闭环:要求与被约束的产出物必须可达
162
+
163
+ 追问问题声明它影响哪些产出物:`affects: IntakeAffect[]`。这不是描述性文字,
164
+ 而是一条**可达性契约**(`AFFECT_TOOLS` 映射):
165
+
166
+ ```ts
167
+ export type IntakeAffect =
168
+ | '格式检查' // → thesis_check
169
+ | '引用规范' // → thesis_lit_* · thesis_check
170
+ | '字数分配' // → thesis_review · thesis_check
171
+ | '写作规范' // → thesis_stylecheck
172
+ | '原创性' // → thesis_originality
173
+ | '答案PPT' // → thesis_slides
174
+ | '答辩问答' // → thesis_defense · defense_code_*
175
+ | '文献检索' // → thesis_lit_search
176
+ ```
177
+
178
+ 约束:**每个 `IntakeAffect` 必须至少被一个真实工具兑现**。
179
+ 新增问题若声明了一个没有工具兑现的产出物,测试立刻变红——
180
+ 这消灭了「问了一堆用不上的要求」这类退化。
181
+
182
+ ---
183
+
184
+ ## 6. 关键设计决策(ADR)
185
+
186
+ ### ADR-1 单一包、单一插件行
187
+
188
+ `dsh plugin add` 一次装完,一个 `Config`,一套技能,模块间共享上下文(intake 写规格、写作读规格、
189
+ 原创性自查读章节、幻灯读答辩素材)。代价是包变大;用「目录即模块 + 无跨模块反向依赖」控制耦合。
190
+ `/thesis-defense` 需要同时覆盖幻灯与代码演练,因此它的注册放在装配层(`src/commands.ts`),
191
+ 而不是让 `ppt/` 与 `codewalk/` 互相依赖。
192
+
193
+ ### ADR-2 材料先追问、后动手
194
+
195
+ `thesis_intake` 的硬约束:**一次只返回一个问题**、每问必带「为什么问 / 影响哪个产出 / 合格答案形态」、
196
+ 材料里能读出来的不重复问、`required` 齐了才允许 `done`。
197
+
198
+ ### ADR-3 零第三方运行时依赖(含 Office 解析)
199
+
200
+ - ZIP 读取器自实现(EOCD + 中央目录 + STORE/DEFLATE,DEFLATE 用内置 `node:zlib`);
201
+ - docx/xlsx/pptx 走 OOXML 文本抽取,不引入 mammoth/xlsx/jszip;
202
+ - PDF 用内置能力**尽力而为**,抽不出来就诚实报错;
203
+ - 记忆用内置 `node:sqlite`;
204
+ - 唯一非内置依赖是 `@deepseek-ai/schemastery`(Config schema 的 `z<Config>` 双重语义无法伪造)。
205
+
206
+ 收益:离线可构建、可评审、供应链风险为零、插件体积小。
207
+
208
+ ### ADR-4 代码走「结构摘要」而不是「正文倒出」
209
+
210
+ 用户材料里的代码若按文本摄取,一个上万行的仓库会挤爆上下文且对写作无益。
211
+ `src/ingest/code.ts` 只提取**结构信号**:语言、文件/行数/代码行/注释行、顶层声明与行号、
212
+ 依赖清单推断的技术栈指纹、以及被跳过的大文件清单。产物是 `00-管理/材料/<目录>-代码结构.md`,
213
+ 直接服务「系统实现」章的骨架、工作量证据与答辩索引。
214
+
215
+ ### ADR-5 只在运行时依赖宿主的两处能力
216
+
217
+ 运行期 import 宿主包只有两处:`schemastery`(schema)与 `dsh-tools` 的 `defineTool`
218
+ (离线退回 `src/shared/define-tool.ts` 的等价实现)。其余宿主能力(`ctx.fs`/`ctx.tools`/
219
+ `ctx.commands`/`ctx.on`/`ctx.provide`/`ctx.effect`)都经 `ctx` 注入。
220
+ **理由**:把编译期的类型耦合压到最小,让仓库在只有 `typescript` 的环境里 `tsc` 全绿、`node --test` 全绿。
221
+
222
+ ### ADR-6 原创性自查只做「诚实度量 + 改写处方」
223
+
224
+ 本地、确定性、可复现(shingle 指纹 + 倒排剪枝 + 最长公共片段定位),报告写明估算口径;
225
+ **不接入**知网/维普等收费系统;处方明确「必须保留」:数字、单位、术语、公式、引用标记、代码标识符——
226
+ 为降重改数据是学术不端。与 `thesis_stylecheck` 同源:两者同时命中的段落优先**整段重写**。
227
+
228
+ ### ADR-7 答辩幻灯以 Markdown 为唯一真相
229
+
230
+ `07-答辩/PPT.md`(Marp 兼容)可 git diff、可复用、不依赖 Office;`.pptx` 是派生产物。
231
+ 转换链路探测外部引擎(marp → npx marp-cli → pandoc)→ 成功则产出 →
232
+ 失败/缺失则写「转换说明」给出可复制命令与兜底路径,**绝不假装成功**
233
+ (退出码 0 但产物 0 字节也判失败)。
234
+
235
+ ### ADR-8 跨会话事实用全局库 + key 命名空间
236
+
237
+ 装配发生在进程启动、拿不到会话 cwd;而事实里跨课题复用的内容(写作风格偏好、导师沟通习惯、
238
+ 学校通用规范)本就该跨项目活着。约定 `user.*` / `school.*` / `thesis.<slug>.*`,
239
+ 技能明文规定「不要把进度与一次性实验数字写进事实」。
240
+
241
+ ### ADR-9 技能随插件发布并复制进论文仓库
242
+
243
+ 项目级技能目录 `<论文仓库>/.dsh/skills`(rank 100)优先级高于用户级(400);
244
+ `thesis_init` 把 `skills/**` 复制过去,使方法论与论文同版本、同 git 历史、可离线迁移。
245
+ 技能名必须等于目录名、frontmatter 不得带 BOM(带 BOM 时 DSH 的解析返回 undefined,技能被静默忽略)。
246
+
247
+ ### ADR-10 目录结构只在 paper 模块内成形
248
+
249
+ 论文工作区的九阶段目录(`00-管理` … `08-合规`)由 `paper/lib/layout.ts` 唯一产生;
250
+ 其它模块只往既有目录写产物(`00-管理/材料清单.md`、`08-合规/降重报告.md`、`07-答辩/PPT.md`),
251
+ **不新增顶层阶段目录**。
252
+
253
+ ### ADR-11 读不出来 ≠ 不存在
254
+
255
+ 工作区里的追问答案、进度台账、文献库、检索记录、决定日志都是学生的资产,且不可再生。
256
+ 所有读路径必须区分「确认不存在(ENOENT / FS_NOT_FOUND)」与「读失败」:
257
+ 前者可回退到默认值,后者**必须抛错并保持原文件不动**。
258
+ 把读失败当成「还没建过」然后用默认值覆盖,是本插件最严重的一类缺陷——
259
+ 用户连「发生了什么」都不会知道。相关工具集中在 `src/shared/fs-errors.ts`。
260
+
261
+ ### ADR-12 子进程的成功判据是「真的成功了」
262
+
263
+ `spawnSync` 在子进程从未启动(如受限环境 `EPERM`)、被信号杀死或被 timeout 掐断时
264
+ 返回 `status: null`。因此成功判据只能是 `status === 0`;并且默认用 `stdio: 'ignore'`
265
+ (某些受限环境里管道 stdio 直接被拒),需要输出时才 `capture`。
266
+ 统一实现在 `src/shared/spawn.ts`,并给 pandoc 之类的调用配了超时。
267
+
268
+ ---
269
+
270
+ ## 7. 数据与产物
271
+
272
+ | 产物 | 位置 | 产生者 |
273
+ |---|---|---|
274
+ | 意图规格(唯一真相) | `00-管理/意图规格.md` | `thesis_intake` |
275
+ | 材料清单 + 逐文件摘要 | `00-管理/材料清单.md`、`00-管理/材料/*.md` | `thesis_ingest` |
276
+ | 进度台账 / 决定日志 / 时间线 | `00-管理/` | `thesis_init` / `thesis_progress` / `thesis_decide` |
277
+ | 文献库与检索审计 | `02-文献/refs.bib`、`检索记录.md`、`笔记/` | `thesis_lit_*` |
278
+ | 章节与产出 | `06-论文/章节/*.md`、`产出/论文.docx` | 写作 + `thesis_build` |
279
+ | 合规报告 | `08-合规/`(引用/格式/AI 味/降重/复测) | `thesis_check` / `thesis_stylecheck` / `thesis_originality` |
280
+ | 答辩材料 | `07-答辩/答辩素材.md`、`预答辩问题库.md`、`PPT.md` | `thesis_defense` / `thesis_slides` |
281
+ | 插件状态 | `<cwd>/.paper/`(追问状态、代码演练状态) | `intake/` / `codewalk/` |
282
+ | 跨会话事实 | `$DSH_HOME/paper-memory.db` | `fact_*` |
283
+
284
+ ---
285
+
286
+ ## 8. 九阶段流水线与人工关卡
287
+
288
+ | 阶段 | 产出物 | 验收标准 | 人工关卡 |
289
+ |---|---|---|---|
290
+ | 1 选题 | 选题确认书 | 课题明确、工作量合理、答辩友好 | **G1** |
291
+ | 2 开题 | 开题报告 + 任务书 | 导师认可;结构与规范达标 | **G3** |
292
+ | 3 文献调研 | 文献库 + 笔记 + 综述素材 | 15-30 篇真实文献;每篇有笔记 | — |
293
+ | 4 系统设计 | 需求/设计/选型文档 | 方案可落地;选型有论证 | — |
294
+ | 5 系统实现 | 可运行系统 + git 提交 | 功能真实可跑 | — |
295
+ | 6 系统测试 | 测试报告 + 真实结果 | 结果可复现;零伪造 | — |
296
+ | 7 论文撰写 | 七章正文 | 逐章人工验收 | **G2**(×7 章) |
297
+ | 8 定稿与合规 | 论文.docx + 检查报告 | 格式/引用/自查全部通过 | **G4** |
298
+ | 9 答辩 | 幻灯 + 演练记录 | 能讲清设计与实现 | — |
299
+
300
+ 关卡由 `thesis_progress` 在工具层强制:阶段入口关卡未通过时该阶段任务拒绝推进;
301
+ 通过关卡前其关联任务必须先完成。**闸门不是提示语,是拒绝。**
302
+
303
+ 另有两道横切闸门:写作意图闸门(`agent/pre-step`,用户要开写但要求没谈清时注入追问指令,
304
+ 用户说「直接写」即放行)与不可逆操作闸门(`tools/pre-execute`,破坏性命令以 ask 决策提请拍板,
305
+ 是唯一不可被提示词绕过的一道)。
306
+
307
+ ---
308
+
309
+ ## 9. 质量与测试策略(证据分层)
310
+
311
+ | 层 | 命令 | 内容 |
312
+ |---|---|---|
313
+ | 纯逻辑与契约 | `npm run test:sandbox` | 430 条:相似度、归一化、处方、问题排序、状态机、幻灯渲染、OOXML/PDF 解析、记忆 SQL、代码结构摘要;装配契约(21 工具 / 9 命令 / 2 服务 / 4 类监听);`definePaperTool` 的 DSL→JSON Schema 编译 |
314
+ | **真实场景端到端** | `npm run test:e2e` | 65 条断言,见 §9.1 |
315
+ | **真实宿主** | `npm run test:host` | 24 项:真实 cordis + dsh-tools 装配、工具 schema 被真实注册表接受、真实执行工具、宿主拒绝缺参、**闸门在真实 waterfall 上真的注入**、卸载后工具注销 |
316
+ | **真实引擎装载** | `npm run test:host-load` | 11 项:真实 `dsh` 引擎解析并校验本插件 |
317
+ | 对外表面审计 | `npm run audit` | 工具/命令/技能契约一致 + 技能命名/BOM 检查,见 §9.3 |
318
+ | 真实网络(可选) | `npm run test:net` | 真实学术 API 检索 → 收录 → 笔记 |
319
+
320
+ `npm run verify` = build + typecheck + 单元/契约 + 审计 + 端到端,是主线不变的守门命令。
321
+
322
+ ### 9.1 真实场景端到端基准
323
+
324
+ 夹具 `tests/e2e/fixtures/jiangzhou-thesis/`(一所虚构学校的真实形态材料):
325
+
326
+ | 夹具 | 作用 |
327
+ |---|---|
328
+ | `学校论文规范.md` | 字数/查重阈值/引用格式/AI 政策/答辩形式 → 驱动追问与格式检查 |
329
+ | `实验数据-检索性能.csv` | 真实运行数据(20 次)→ 驱动第六、七章与图表编号检查 |
330
+ | `系统源码摘要.md` | 代码结构 → 驱动第五章与答辩素材 |
331
+ | `导师要求.txt` | 导师口径 → 驱动意图规格与决定日志 |
332
+
333
+ 一条命令、**全程离线**跑完 11 环并逐环断言:建库 → 摄取(清单+摘要)→ 追问(含「必答未齐拒绝 done」
334
+ 负路径)→ 决定留痕 → 七章写作与逐章评审 → G1/G2 闸门(含负路径)→ 全文检查 →
335
+ 写作风格自查 → docx 构建 → 原创性自查(scan → verify)→ 幻灯(页数/时长窗口)→ 答辩素材。
336
+
337
+ 其中 docx 的校验是**独立 ZIP 解析**:自读中央目录、`inflateRawSync` 解出 `word/document.xml`,
338
+ 按 UTF-8 断言真实正文与「不含待补/TODO 残留」——而不是只看文件签名。
339
+
340
+ ### 9.2 失败路径与鲁棒性
341
+
342
+ 负路径是必测项,且**最严重的缺陷类型是「静默假装成功」**:
343
+ 转换器缺失却报成功、抽取失败却返回空正文、读失败却用默认值覆盖。
344
+ `tests/robustness.test.ts` 专测数据安全与边界,断言一律成对:
345
+ 「工具抛错」+「原文件零改动(或零写盘)」。
346
+
347
+ ### 9.3 审计为什么必须有
348
+
349
+ 对外名字(工具名、命令名、技能名)是**契约**:学生与宿主都按名字调用,改名而不改文档
350
+ 就是文档骗人,改名而不改测试就是契约失守。这类漂移只靠人工看必然漏,
351
+ 故 `scripts/audit-surface.mjs` 把它们固定成断言:**注册集必须恰好等于契约集**,
352
+ 多一个少一个都失败;技能 frontmatter 的 `name` 必须等于目录名(DSH 按目录名发现技能);
353
+ `SKILL.md` 不得带 BOM(带 BOM 时宿主解析 frontmatter 返回 undefined,**整个技能被静默忽略**——
354
+ 文件明明在、技能却不存在,是最难排查的一类故障)。
355
+
356
+ **脚本会自己腐坏,所以它有测试**:审计脚本自身一旦写错(正则不匹配、路径算错、
357
+ 例外开得太宽),就会给出虚假的绿色。因此它的每条规则要么能被现有测试独立覆盖
358
+ (装配契约由 `tests/composition.test.ts` 断言),要么口径收得足够窄、宁少勿假。
359
+ 审计脚本不再承担「零前身残留」这类**过渡期脚手架**职责:脚手架是给重构过程用的,
360
+ 重构结束后继续留着,只会留下一条永远为假的例外和一份没人再读的词表。
361
+
362
+ ---
363
+
364
+ ## 10. 已知边界(诚实清单)
365
+
366
+ 1. **PDF 抽取是尽力而为**:扫描版(无文本层)、对象流/加密 PDF 可能抽不到文字;
367
+ 工具返回 `ok:false` + 原因,绝不编造内容;低抽取率会带 `lowConfidence` 标记。
368
+ 2. **旧二进制 Office 格式(.doc/.xls/.ppt)不支持**,明确提示另存为新格式。
369
+ 3. **查重不接收费系统**:报告的重复率是本地估算,与学校检测结果不可等同;口径与参数写进报告。
370
+ 4. **幻灯依赖外部转换器**:本机无 marp/pandoc 时只能拿到 Markdown + 转换指引(幻灯文字已是最终稿)。
371
+ 5. **代码演练内置语言矩阵只覆盖 Go/TS/Python/Rust**,其余语言需在配置里补 `gates`。
372
+ 6. **子进程不可取消**:pandoc/marp/git 走 `spawnSync`,有超时上限,但 `exec.signal` 不进入子进程。
373
+ 7. **受限环境下管道 stdio 被拒**:某些沙箱里 `stdio: 'pipe'` 会 `EPERM`,故默认 `stdio: 'ignore'`。
374
+ 8. **宿主契约以本地 shim 声明**:真实签名核对见 [docs/host-api.md](./docs/host-api.md),
375
+ 运行时行为由端到端基准与真实宿主冒烟兜底。
376
+ 9. **真实 `dsh` 引擎的装载验证需要写 `$DSH_HOME/profiles/<name>/cordis.yml`**(引擎在
377
+ `--dump-config` 前就会写它)。受限沙箱下该写入会被拒,`npm run test:host-load` 因此需要放宽文件权限;
378
+ `npm run test:host`(真实 cordis,不碰 profile)不需要。
379
+ 10. **意图规格是「一次到位」的努力而非保证**:已知的返工源会被问完,未知风险仍会在阶段推进中暴露,
380
+ 此时应回到 `thesis_intake` 补问并把答案写回规格。
381
+
382
+ ---
383
+
384
+ ## 11. 反目标(明确不做)
385
+
386
+ 1. **不做多插件拆分**——单一插件 = 一次安装、一个配置、一套技能、模块间共享上下文。
387
+ 2. **不引入运行时第三方依赖**——离线可构建、可评审、供应链风险为零。
388
+ 3. **不自研 pptx 生成器**——Markdown 为唯一真相,转换交给外部引擎,缺失时给可执行指引。
389
+ 4. **不接收费查重系统**——只做本地确定性度量,口径写进报告。
390
+ 5. **不保留旧工具名别名**——别名会让两套叙事长期共存,比改名本身更伤人。
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Paloma966
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE.md ADDED
@@ -0,0 +1,10 @@
1
+ # 来源与许可声明(NOTICE)
2
+
3
+ 本仓库的全部代码与文档均为作者本人(Paloma966)的原创作品,其中一部分由作者此前
4
+ 在其它宿主环境下的同题材项目整理、合并、重写而来。**没有使用任何第三方代码**,
5
+ 因此这里没有需要致谢的外部贡献者;本文件存在的唯一目的,是如实说明这一点。
6
+
7
+ ## 许可
8
+
9
+ MIT,以本仓库根目录的 [`LICENSE`](./LICENSE) 为准。被合并整理的早期作品同为该作者所有、
10
+ 同为 MIT 许可,合并这件事本身不改变许可。