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
@@ -0,0 +1,572 @@
1
+ /**
2
+ * 论文工作区布局与全部模板文件内容(DESIGN.md §5 的落地)。
3
+ *
4
+ * thesis_init 按此生成目录树;模板内容与技能包(plugin/skills/)保持一致。
5
+ * 本模块只依赖 Node 内置能力。
6
+ */
7
+ import { defaultState, defaultTimeline, renderLedger, renderTimeline } from "./ledger.js";
8
+ const HEADER_NOTE = '> 本文件由 thesis_init 生成;内容模板由 dsh-thesis 技能包指导填写。';
9
+ export function buildLayout(opts) {
10
+ const files = [];
11
+ // ------------------------------------------------------------------ 根
12
+ files.push({
13
+ path: 'README.md',
14
+ content: `# ${opts.title}
15
+
16
+ ${HEADER_NOTE}
17
+
18
+ ## 这是什么
19
+
20
+ 本仓库是毕业设计(计算机类)的完整工作区:选题、开题、文献、设计、实现、
21
+ 论文、合规、答辩,全程留痕。
22
+
23
+ - 进度状态:见 \`00-管理/进度台账.md\`(由 \`thesis_progress\` 工具维护)
24
+ - 关键决定:见 \`00-管理/决定日志.md\`
25
+ - 流程地图:见 \`00-管理/流程地图.md\`
26
+
27
+ ## 目录速览
28
+
29
+ | 目录 | 内容 |
30
+ |---|---|
31
+ | 00-管理 | 流程地图、选题、时间线、台账、决定日志 |
32
+ | 01-开题 | 开题报告、任务书 |
33
+ | 02-文献 | 文献库 refs.bib、检索记录、笔记 |
34
+ | 03-设计 | 需求分析、系统设计、技术选型论证 |
35
+ | 04-实现 | 真实代码 |
36
+ | 05-实验测试 | 测试计划与真实运行结果 |
37
+ | 06-论文 | 大纲、七章正文、图表、学校模板、产出 |
38
+ | 07-答辩 | PPT 大纲、问答演练 |
39
+ | 08-合规 | 格式/引用检查报告、自查报告 |
40
+
41
+ ## 使用方式
42
+
43
+ 在 DSH Web 界面中与本工作区配合使用:AI 会加载 \`.dsh/skills/\` 下的技能包,
44
+ 按流程地图推进,并通过 \`thesis_progress\` / \`thesis_decide\` 工具维护台账与决定日志。
45
+ `,
46
+ });
47
+ files.push({
48
+ path: '.gitignore',
49
+ content: `# 依赖与构建产物
50
+ node_modules/
51
+ dist/
52
+ build/
53
+ __pycache__/
54
+ *.pyc
55
+
56
+ # 系统文件
57
+ .DS_Store
58
+ Thumbs.db
59
+
60
+ # 论文编译中间产物
61
+ *.aux
62
+ *.log
63
+ *.out
64
+ *.toc
65
+
66
+ # 文献检索缓存(临时候选,由 thesis_lit_search 维护)
67
+ 02-文献/.lit-cache.json
68
+ `,
69
+ });
70
+ // ---------------------------------------------------------------- 00-管理
71
+ files.push({
72
+ path: '00-管理/流程地图.md',
73
+ content: `# 毕业设计流程地图
74
+
75
+ ${HEADER_NOTE}
76
+
77
+ 九阶段全景。每个阶段:产出物 → 验收标准 → 下一站。详细方法论见技能包
78
+ \`thesis-pipeline\` / \`thesis-opener\` 等。
79
+
80
+ | 阶段 | 产出物 | 验收标准 | 人工关卡 |
81
+ |---|---|---|---|
82
+ | 1 选题 | 选题确认书 | 课题明确、工作量合理、答辩友好 | **G1** |
83
+ | 2 开题 | 开题报告 + 任务书 | 导师认可;报告结构与规范达标 | **G3** |
84
+ | 3 文献调研 | 文献库 + 笔记 + 综述素材 | 15-30 篇真实文献;每篇有笔记 | — |
85
+ | 4 系统设计 | 需求/设计/选型文档 | 方案可落地;选型有论证 | — |
86
+ | 5 系统实现 | 可运行系统 + git 提交 | 功能真实可跑;中期检查通过 | — |
87
+ | 6 系统测试 | 测试报告 + 真实结果 | 结果可复现;零伪造 | — |
88
+ | 7 论文撰写 | 七章正文 | 逐章人工验收 | **G2**(×7 章) |
89
+ | 8 定稿与合规 | 论文.docx + 检查报告 | 格式/引用/自查全部通过 | **G4** |
90
+ | 9 答辩 | PPT + 演练记录 | 能讲清设计与实现 | — |
91
+
92
+ **红线**(违反即学术不端,永不允许):
93
+
94
+ 1. 不得编造文献(每条引用必须来自真实检索,见 02-文献/检索记录.md)
95
+ 2. 不得伪造数据/截图/运行结果(05-实验测试/结果 必须可在 04-实现 上复现)
96
+ 3. 学校明文限制 AI 使用时,正文必须经过人工关卡(G1-G4)后提交
97
+
98
+ **每阶段结束的动作**:更新进度台账(\`thesis_progress\`)→ 关键决定写入决定日志
99
+ (\`thesis_decide\`)→ git 提交。
100
+ `,
101
+ });
102
+ files.push({
103
+ path: '00-管理/选题/备选课题.md',
104
+ content: `# 备选课题
105
+
106
+ ${HEADER_NOTE}
107
+
108
+ 选题工作坊产出:每个备选课题按"选题四要素"评估(兴趣 / 可行性 / 工作量 / 答辩友好度),
109
+ 每项 1-5 分。评估由 \`thesis-opener\` 技能指导完成。
110
+
111
+ ## 备选 A:<课题名>
112
+
113
+ - 一句话描述:
114
+ - 要解决的问题:
115
+ - 大致技术路线:
116
+ - 评估:
117
+ - 兴趣:?/5
118
+ - 可行性(你的基础 + AI 辅助可达成):?/5
119
+ - 工作量(与毕设周期匹配):?/5
120
+ - 答辩友好度(能讲清、有演示、有数据):?/5
121
+ - 风险与对策:
122
+
123
+ ## 备选 B:<课题名>
124
+
125
+ (同上)
126
+
127
+ ## 备选 C:<课题名>
128
+
129
+ (同上)
130
+
131
+ ## 结论
132
+
133
+ 最终选择:<备选>。理由见《选题确认书》与决定日志。
134
+ `,
135
+ });
136
+ files.push({
137
+ path: '00-管理/选题/选题确认书.md',
138
+ content: `# 选题确认书
139
+
140
+ ${HEADER_NOTE}
141
+
142
+ > 关卡 **G1** 的产物。本文件由用户书面确认后,G1 才能标记通过。
143
+
144
+ - 学生:<姓名>
145
+ - 课题:<课题名>
146
+ - 日期:${opts.date}
147
+
148
+ ## 1. 课题动机
149
+
150
+ <为什么做这个课题:课程/兴趣/实际问题,2-3 句>
151
+
152
+ ## 2. 要解决的问题
153
+
154
+ <用一句"用户/系统痛点 + 本课题的解法"来表述>
155
+
156
+ ## 3. 技术路线概述
157
+
158
+ <用什么技术栈、大致分几步实现:一句话总览 + 3-5 个步骤>
159
+
160
+ ## 4. 工作量评估
161
+
162
+ <功能范围:核心功能与可选功能;与毕设周期是否匹配>
163
+
164
+ ## 5. 风险与对策
165
+
166
+ <最大风险是什么;如果做不出来,退路是什么>
167
+
168
+ ## 6. 用户确认
169
+
170
+ - [ ] 我已理解上述课题内容与工作量,同意以此为毕业设计课题。
171
+ - 确认人:________ 日期:________
172
+ `,
173
+ });
174
+ files.push({
175
+ path: '00-管理/时间线.md',
176
+ content: renderTimeline(defaultTimeline()),
177
+ });
178
+ files.push({
179
+ path: '00-管理/进度台账.md',
180
+ content: renderLedger({ ...defaultState(), title: opts.title }),
181
+ });
182
+ files.push({
183
+ path: '00-管理/决定日志.md',
184
+ content: `# 决定日志
185
+
186
+ ${HEADER_NOTE}
187
+
188
+ > 每个关键决定的留痕:内容、理由、备选。答辩时它是"我为什么这么写"的证据。
189
+ > 由 \`thesis_decide\` 工具或 /thesis-decide 命令追加。
190
+
191
+ (暂无决定)
192
+ `,
193
+ });
194
+ // ---------------------------------------------------------------- 01-开题
195
+ files.push({
196
+ path: '01-开题/开题报告.md',
197
+ content: `# 开题报告
198
+
199
+ ${HEADER_NOTE}
200
+
201
+ > 结构遵循 \`thesis-opener\` 技能;完稿后由 \`thesis_build\` 产出 docx。
202
+ > 提交前需通过关卡 **G3**。
203
+
204
+ ## 1 课题背景与意义
205
+
206
+ <行业/领域背景 → 现有问题 → 本课题意义(建议 600-800 字)>
207
+
208
+ ## 2 国内外研究现状
209
+
210
+ <按主题组织的文献综述,引用真实文献 [1][2](建议 800-1200 字)>
211
+
212
+ ## 3 研究内容与目标
213
+
214
+ <3-5 条具体研究内容,每条一句目标(建议 400-600 字)>
215
+
216
+ ## 4 技术路线与方案
217
+
218
+ <总体方案图(可用 Mermaid)+ 分步说明 + 关键技术点(建议 600-800 字)>
219
+
220
+ ## 5 进度安排
221
+
222
+ <表格:阶段 / 时间 / 产出(与 00-管理/时间线.md 一致)>
223
+
224
+ ## 6 参考文献
225
+
226
+ <GB/T 7714 格式,全部来自 02-文献/refs.bib,此处手工同步或由构建工具自动生成>
227
+ `,
228
+ });
229
+ files.push({
230
+ path: '01-开题/任务书.md',
231
+ content: `# 任务书
232
+
233
+ ${HEADER_NOTE}
234
+
235
+ > 各校模板不同;拿到学校模板后放 06-论文/assets/学校模板/,按模板重写本文件。
236
+
237
+ - 课题名称:
238
+ - 学生:
239
+ - 指导教师:
240
+
241
+ ## 一、设计(研究)内容
242
+
243
+ ## 二、主要技术指标或要求
244
+
245
+ ## 三、进度安排
246
+
247
+ ## 四、主要参考文献
248
+ `,
249
+ });
250
+ // ---------------------------------------------------------------- 02-文献
251
+ files.push({
252
+ path: '02-文献/refs.bib',
253
+ content: `% 文献库(BibTeX)。
254
+ % 红线:本文件只收录真实检索到的文献(由 thesis_lit_search/save 写入)。
255
+ % 每条必须含 DOI 或 URL。引用格式遵循 GB/T 7714-2015(顺序编码制)。
256
+ `,
257
+ });
258
+ files.push({
259
+ path: '02-文献/检索记录.md',
260
+ content: `# 文献检索记录
261
+
262
+ ${HEADER_NOTE}
263
+
264
+ > 每次检索留痕:哪个库、什么关键词、命中多少、筛掉哪些、为什么。
265
+ > 这是"零假文献"的审计证据。
266
+
267
+ | 日期 | 数据库 | 关键词 | 命中 | 收录 | 备注 |
268
+ |---|---|---|---|---|---|
269
+ | ${opts.date} | (待检索) | — | — | — | — |
270
+ `,
271
+ });
272
+ files.push({ path: '02-文献/笔记/.gitkeep', content: '' });
273
+ // ---------------------------------------------------------------- 03-设计
274
+ files.push({
275
+ path: '03-设计/需求分析.md',
276
+ content: `# 需求分析
277
+
278
+ ${HEADER_NOTE}
279
+
280
+ > 规范见 \`thesis-eng-design\` 技能。功能需求编号 FR-x,非功能 NFR-x。
281
+
282
+ ## 1 系统概述
283
+
284
+ <一句话:系统给谁用、解决什么问题>
285
+
286
+ ## 2 功能需求
287
+
288
+ | 编号 | 功能 | 说明 | 优先级 |
289
+ |---|---|---|---|
290
+ | FR-1 | | | 高 |
291
+
292
+ ## 3 非功能需求
293
+
294
+ | 编号 | 类别 | 要求 |
295
+ |---|---|---|
296
+ | NFR-1 | 性能 | |
297
+ | NFR-2 | 安全 | |
298
+ | NFR-3 | 易用性 | |
299
+
300
+ ## 4 用例描述
301
+
302
+ <核心用例:参与者 → 操作 → 系统响应>
303
+ `,
304
+ });
305
+ files.push({
306
+ path: '03-设计/系统设计.md',
307
+ content: `# 系统设计
308
+
309
+ ${HEADER_NOTE}
310
+
311
+ ## 1 总体架构
312
+
313
+ <架构图:可用 Mermaid(flowchart/architecture)>
314
+
315
+ ## 2 模块划分
316
+
317
+ | 模块 | 职责 | 对外接口 |
318
+ |---|---|---|
319
+
320
+ ## 3 数据库设计
321
+
322
+ <ER 图 + 关键表结构>
323
+
324
+ ## 4 接口设计
325
+
326
+ <API/接口列表:路径、方法、参数、返回>
327
+ `,
328
+ });
329
+ files.push({
330
+ path: '03-设计/技术选型论证.md',
331
+ content: `# 技术选型论证
332
+
333
+ ${HEADER_NOTE}
334
+
335
+ > 答辩高频问题:"为什么选这个技术?" 每个选型按下面模板论证并写入决定日志。
336
+
337
+ | 选型项 | 选择 | 理由 | 备选 | 弃用备选的原因 |
338
+ |---|---|---|---|---|
339
+ | 后端框架 | | | | |
340
+ | 前端 | | | | |
341
+ | 数据库 | | | | |
342
+ | 部署 | | | | |
343
+ `,
344
+ });
345
+ // ---------------------------------------------------------------- 04-实现
346
+ files.push({
347
+ path: '04-实现/.gitkeep',
348
+ content: '',
349
+ });
350
+ // ---------------------------------------------------------- 05-实验测试
351
+ files.push({
352
+ path: '05-实验测试/测试计划.md',
353
+ content: `# 测试计划
354
+
355
+ ${HEADER_NOTE}
356
+
357
+ | 用例 ID | 对应需求 | 步骤 | 预期结果 |
358
+ |---|---|---|---|
359
+ | TC-1 | FR-1 | | |
360
+
361
+ > 红线:所有结果必须真实运行获得,截图/数据存入 结果/ 目录并注明复现步骤。
362
+ `,
363
+ });
364
+ files.push({ path: '05-实验测试/结果/.gitkeep', content: '' });
365
+ // ---------------------------------------------------------------- 06-论文
366
+ files.push({
367
+ path: '06-论文/大纲.md',
368
+ content: `# 论文大纲
369
+
370
+ ${HEADER_NOTE}
371
+
372
+ 七章标准结构(计算机类毕设通用;以学校模板为准)。字数目标为常见要求
373
+ (总计约 1.5-2 万字),最终以学校文件为准。
374
+
375
+ | 章 | 内容 | 字数目标 |
376
+ |---|---|---|
377
+ | 1 绪论 | 背景、意义、国内外现状、本文工作与组织结构 | 2000-2500 |
378
+ | 2 相关技术 | 用到的关键技术介绍(结合文献笔记) | 1500-2500 |
379
+ | 3 需求分析 | 功能/非功能需求、用例 | 1500-2000 |
380
+ | 4 系统设计 | 架构、模块、数据库、接口 | 2500-3500 |
381
+ | 5 系统实现 | 关键模块实现细节(结合真实代码) | 3000-4000 |
382
+ | 6 系统测试 | 测试环境、用例、真实结果与分析 | 2000-3000 |
383
+ | 7 总结与展望 | 工作总结、不足与改进方向 | 800-1200 |
384
+ `,
385
+ });
386
+ for (const [i, meta] of CHAPTER_META.entries()) {
387
+ files.push({
388
+ path: `06-论文/章节/${meta.file}.md`,
389
+ content: chapterTemplate(i + 1, meta),
390
+ });
391
+ }
392
+ files.push({ path: '06-论文/图表/.gitkeep', content: '' });
393
+ files.push({
394
+ path: '06-论文/assets/学校模板/README.md',
395
+ content: `# 学校模板与规范
396
+
397
+ ${HEADER_NOTE}
398
+
399
+ > 把学校发的所有规范文件放这里:论文模板(docx)、格式要求、字数要求、
400
+ > 引用规范、查重要求。\`thesis_build\` 与 \`thesis_check\` 以这里的文件为准。
401
+ > 尚未拿到时,构建工具会使用内置过渡模板并显式标注"非学校模板"。
402
+
403
+ 获取渠道建议:教务处网站、学院通知、学长学姐。
404
+ `,
405
+ });
406
+ files.push({ path: '06-论文/产出/.gitkeep', content: '' });
407
+ // ---------------------------------------------------------------- 07-答辩
408
+ files.push({
409
+ path: '07-答辩/PPT大纲.md',
410
+ content: `# 答辩 PPT 大纲
411
+
412
+ ${HEADER_NOTE}
413
+
414
+ > 标准 10-12 页,规范见 \`thesis-defense\` 技能。
415
+
416
+ 1. 封面(课题/学生/导师)
417
+ 2. 目录
418
+ 3. 课题背景与意义
419
+ 4. 国内外现状(1 页,图为主)
420
+ 5. 需求分析(用例/功能点)
421
+ 6. 系统总体设计(架构图)
422
+ 7. 关键实现(2-3 页:核心模块 + 代码/界面截图)
423
+ 8. 系统测试(真实数据图)
424
+ 9. 总结与展望
425
+ 10. 致谢/问答页
426
+ `,
427
+ });
428
+ files.push({
429
+ path: '07-答辩/问答演练.md',
430
+ content: `# 问答演练
431
+
432
+ ${HEADER_NOTE}
433
+
434
+ > 预答辩问题库由 \`thesis_defense\` 工具根据论文与代码生成;
435
+ > 每次演练记录一问一答,重点练习"你的系统怎么实现的"。
436
+
437
+ (待演练)
438
+ `,
439
+ });
440
+ // ---------------------------------------------------------------- 08-合规
441
+ files.push({
442
+ path: '08-合规/自查报告.md',
443
+ content: `# 提交前自查报告
444
+
445
+ ${HEADER_NOTE}
446
+
447
+ > 关卡 **G4** 的产物。\`thesis_check\` 与 \`thesis_stylecheck\` 的输出汇总于此,
448
+ > 用户确认已阅读后 G4 方可标记通过。
449
+
450
+ ## 1 引用检查
451
+
452
+ <来自 thesis_check:每条引用 ↔ refs.bib 双向一致;全部真实可查>
453
+
454
+ ## 2 格式检查
455
+
456
+ <来自 thesis_check:模板/图表编号/字数/术语一致性>
457
+
458
+ ## 3 查重前自查
459
+
460
+ <重复风险段落清单与降重动作>
461
+
462
+ ## 4 AI 味自查
463
+
464
+ <来自 thesis_stylecheck:需人工改写段落清单与处理记录>
465
+
466
+ ## 5 用户确认
467
+
468
+ - [ ] 我已阅读本报告并完成相应修改。
469
+ - 确认人:________ 日期:________
470
+ `,
471
+ });
472
+ files.push({ path: '08-合规/格式检查报告/.gitkeep', content: '' });
473
+ files.push({ path: '08-合规/引用检查报告/.gitkeep', content: '' });
474
+ return files;
475
+ }
476
+ export const CHAPTER_META = [
477
+ {
478
+ file: '01-绪论',
479
+ title: '绪论',
480
+ words: '2000-2500',
481
+ outline: ['1.1 研究背景与意义', '1.2 国内外研究现状', '1.3 本文主要工作', '1.4 论文组织结构'],
482
+ checklist: ['背景→问题→意义的逻辑链完整', '研究现状按主题组织且每条引用真实', '本文工作与后文章节一一对应'],
483
+ },
484
+ {
485
+ file: '02-相关技术',
486
+ title: '相关技术',
487
+ words: '1500-2500',
488
+ outline: ['2.1 <核心技术一>', '2.2 <核心技术二>', '2.3 <核心技术三>', '2.4 本章小结'],
489
+ checklist: ['只介绍本系统真正用到的技术', '每项技术结合文献笔记说明', '与第四章设计形成呼应(不是技术手册摘抄)'],
490
+ },
491
+ {
492
+ file: '03-需求分析',
493
+ title: '需求分析',
494
+ words: '1500-2000',
495
+ outline: ['3.1 系统概述', '3.2 功能需求', '3.3 非功能需求', '3.4 用例分析'],
496
+ checklist: ['需求编号 FR/NFR 与 03-设计/需求分析.md 一致', '每条功能需求在第五章有对应实现、第六章有对应测试'],
497
+ },
498
+ {
499
+ file: '04-系统设计',
500
+ title: '系统设计',
501
+ words: '2500-3500',
502
+ outline: ['4.1 总体架构设计', '4.2 模块设计', '4.3 数据库设计', '4.4 接口设计', '4.5 本章小结'],
503
+ checklist: ['有架构图且与真实代码一致', '每个模块职责单一、接口清晰', '技术选型有论证(引用技术选型论证.md)'],
504
+ },
505
+ {
506
+ file: '05-系统实现',
507
+ title: '系统实现',
508
+ words: '3000-4000',
509
+ outline: ['5.1 开发环境', '5.2 <模块一>实现', '5.3 <模块二>实现', '5.4 <模块三>实现', '5.5 本章小结'],
510
+ checklist: ['代码片段来自真实代码(04-实现),可复现', '每张界面截图来自真实运行', '关键实现细节讲清"为什么这么写"'],
511
+ },
512
+ {
513
+ file: '06-系统测试',
514
+ title: '系统测试',
515
+ words: '2000-3000',
516
+ outline: ['6.1 测试环境', '6.2 测试用例设计', '6.3 测试结果与分析', '6.4 本章小结'],
517
+ checklist: ['用例编号与测试计划一致', '结果全部真实(05-实验测试/结果)', '对失败用例有分析与修复记录'],
518
+ },
519
+ {
520
+ file: '07-总结与展望',
521
+ title: '总结与展望',
522
+ words: '800-1200',
523
+ outline: ['7.1 工作总结', '7.2 不足与展望'],
524
+ checklist: ['总结与绪论"本文主要工作"呼应', '不足诚实、展望具体(不是空话)'],
525
+ },
526
+ ];
527
+ export function chapterTemplate(n, meta) {
528
+ return `# 第 ${n} 章 ${meta.title}
529
+
530
+ > 字数目标:${meta.words} 字(以学校要求为准)
531
+ > 写作规范:\`thesis-writing\` 技能;引用规范:\`thesis-citation\` 技能
532
+ > 本章通过关卡 G2 验收后,用 \`thesis_progress\` 标记。
533
+
534
+ ## 大纲
535
+
536
+ ${meta.outline.map(x => `- ${x}`).join('\n')}
537
+
538
+ ## 正文
539
+
540
+ (写作要求:基于真实素材——文献笔记、03-设计文档、04-实现代码、05-实验测试结果——逐段撰写;写完后执行 G2 验收)
541
+
542
+ ## 本章 G2 验收清单
543
+
544
+ ${meta.checklist.map(x => `- [ ] ${x}`).join('\n')}
545
+ - [ ] 用户已阅读本章并完成修改,书面确认验收
546
+ `;
547
+ }
548
+ /** 章节文件列表(供工具与测试使用)。 */
549
+ export const CHAPTER_FILES = CHAPTER_META.map(m => m.file);
550
+ /** 按文件名(带或不带 .md 后缀)查找章节元数据。 */
551
+ export function chapterMetaFor(file) {
552
+ const name = file.endsWith('.md') ? file.slice(0, -3) : file;
553
+ const index = CHAPTER_META.findIndex(m => m.file === name);
554
+ if (index === -1)
555
+ return undefined;
556
+ return { meta: CHAPTER_META[index], chapterNo: index + 1 };
557
+ }
558
+ function cjkCount(text) {
559
+ return (text.match(/[\u4e00-\u9fff]/g) ?? []).length;
560
+ }
561
+ /**
562
+ * 章节"已撰写"判定(确定性):
563
+ * - 勾选过至少一项 G2 清单(- [x]),或
564
+ * - 正文 CJK 字数比模板脚手架多 100 字以上(模板只含大纲与写作要求)。
565
+ * 供 thesis_build / thesis_check / thesis_stylecheck 共用,
566
+ * 避免把未动笔的脚手架当正文处理。
567
+ */
568
+ export function isWrittenChapter(text, metaNo, meta) {
569
+ if (/^\s*- \[x\]/m.test(text))
570
+ return true;
571
+ return cjkCount(text) > cjkCount(chapterTemplate(metaNo, meta)) + 100;
572
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * 进度台账、时间线、决定日志的数据模型与读写逻辑。
3
+ *
4
+ * 设计要点(见 DESIGN.md §5):
5
+ * - 台账的机器真相是一个 JSON 状态块,藏在 Markdown 的 `<!-- thesis:state -->`
6
+ * HTML 注释里;表格等人类可读部分由 renderLedger 每次重绘,两者永不失步。
7
+ * - 关卡闸门(G1/G2/G3/G4)在工具层强制执行,不是"靠 AI 自觉":
8
+ * 未通过某阶段的 gateIn,该阶段任务不允许进入 doing/done。
9
+ *
10
+ * 本模块只依赖 Node 内置能力,可在任何环境独立测试。
11
+ */
12
+ export type TaskStatus = 'todo' | 'doing' | 'done';
13
+ export interface Task {
14
+ /** 稳定任务 ID,如 T1.1。 */
15
+ readonly id: string;
16
+ readonly title: string;
17
+ readonly stage: number;
18
+ status: TaskStatus;
19
+ /** 关联的人工关卡(如 G1);该任务 done 是关卡通过的前提之一。 */
20
+ readonly gate?: string;
21
+ note?: string;
22
+ }
23
+ export type GateStatus = 'pending' | 'passed';
24
+ export interface GateState {
25
+ status: GateStatus;
26
+ /** 通过日期(ISO 日期字符串)。 */
27
+ date?: string;
28
+ note?: string;
29
+ /** G2 专用:各章验收状态。 */
30
+ chapters?: Record<string, GateStatus>;
31
+ }
32
+ export interface ThesisState {
33
+ title?: string;
34
+ currentStage: number;
35
+ updatedAt: string;
36
+ gates: Record<string, GateState>;
37
+ tasks: Task[];
38
+ }
39
+ export interface StageMeta {
40
+ readonly id: number;
41
+ readonly name: string;
42
+ /** 进入该阶段前必须已通过的关卡。 */
43
+ readonly gateIn?: string;
44
+ /** 离开该阶段前必须已通过的关卡。 */
45
+ readonly gateOut?: string;
46
+ }
47
+ export interface Milestone {
48
+ readonly id: string;
49
+ readonly name: string;
50
+ readonly due?: string;
51
+ status: 'pending' | 'done';
52
+ readonly dependsOn: readonly string[];
53
+ }
54
+ export interface TimelineState {
55
+ milestones: Milestone[];
56
+ }
57
+ export interface DecisionEntry {
58
+ readonly date: string;
59
+ readonly title: string;
60
+ readonly content: string;
61
+ readonly reason?: string;
62
+ readonly alternatives?: string;
63
+ }
64
+ export declare const STAGES: readonly StageMeta[];
65
+ export declare const GATE_NAMES: Readonly<Record<string, string>>;
66
+ /** G2 覆盖的论文七章(与 layout.ts 的章节模板一致)。 */
67
+ export declare const CHAPTERS: readonly string[];
68
+ export declare function defaultTasks(): Task[];
69
+ export declare function defaultState(now?: Date): ThesisState;
70
+ export declare function stageMeta(id: number): StageMeta | undefined;
71
+ export declare function gatePassed(state: ThesisState, gate: string): boolean;
72
+ export interface LedgerParse {
73
+ readonly state: ThesisState;
74
+ readonly found: boolean;
75
+ }
76
+ /** 从台账 Markdown 提取 JSON 状态块;缺失时返回 found:false 与默认状态。 */
77
+ export declare function parseLedger(md: string): LedgerParse;
78
+ export declare function stateToJson(state: ThesisState): string;
79
+ export interface GateCheck {
80
+ readonly ok: boolean;
81
+ readonly reason: string;
82
+ }
83
+ /**
84
+ * 把任务推进到 toStatus 是否被允许。
85
+ * 规则:任务所在阶段有 gateIn 时,该关卡必须已通过;关联 gate 的任务
86
+ * 必须先完成(done)才能把该关卡标记通过(由 applyGate 检查)。
87
+ */
88
+ export declare function canUpdateTask(state: ThesisState, task: Task, toStatus: TaskStatus): GateCheck;
89
+ /**
90
+ * 重算 currentStage:第一个"仍有待办任务且入口关卡已通过(或没有入口关卡)"的阶段。
91
+ * 阶段出口关卡未通过时不会越过该阶段进入下一阶段。
92
+ */
93
+ export declare function recomputeStage(state: ThesisState): void;
94
+ export declare function applyTaskUpdate(state: ThesisState, taskId: string, toStatus: TaskStatus, note?: string, now?: Date): GateCheck & {
95
+ task?: Task;
96
+ };
97
+ export declare function applyGate(state: ThesisState, gate: string, pass: boolean, opts?: {
98
+ chapter?: string;
99
+ note?: string;
100
+ now?: Date;
101
+ }): GateCheck;
102
+ export declare function renderLedger(state: ThesisState): string;
103
+ export declare function renderReport(state: ThesisState): string;
104
+ export declare function defaultTimeline(): TimelineState;
105
+ export declare function parseTimeline(md: string): {
106
+ state: TimelineState;
107
+ found: boolean;
108
+ };
109
+ export declare function renderTimeline(t: TimelineState): string;
110
+ export declare function renderDecisionEntry(entry: DecisionEntry): string;
111
+ export declare function appendDecision(md: string, entry: DecisionEntry): string;
112
+ export declare function countDecisions(md: string): number;