dsh-data-domain-knowledge 0.1.0-alpha.2 → 0.1.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/README.md +147 -19
  2. package/cordis.patch.yml +25 -10
  3. package/lib/client.js +6400 -3326
  4. package/lib/doc-page.js +7761 -0
  5. package/lib/types/convert/host.d.ts.map +1 -1
  6. package/lib/types/convert/host.js +63 -11
  7. package/lib/types/convert/host.js.map +1 -1
  8. package/lib/types/convert/ingest.d.ts +7 -4
  9. package/lib/types/convert/ingest.d.ts.map +1 -1
  10. package/lib/types/convert/ingest.js +52 -14
  11. package/lib/types/convert/ingest.js.map +1 -1
  12. package/lib/types/convert/types.d.ts +2 -2
  13. package/lib/types/convert/types.d.ts.map +1 -1
  14. package/lib/types/convert/types.js +2 -2
  15. package/lib/types/convert/types.js.map +1 -1
  16. package/lib/types/diagnosis/cards.d.ts +8 -7
  17. package/lib/types/diagnosis/cards.d.ts.map +1 -1
  18. package/lib/types/diagnosis/cards.js +119 -49
  19. package/lib/types/diagnosis/cards.js.map +1 -1
  20. package/lib/types/diagnosis/run.d.ts +57 -0
  21. package/lib/types/diagnosis/run.d.ts.map +1 -0
  22. package/lib/types/diagnosis/run.js +245 -0
  23. package/lib/types/diagnosis/run.js.map +1 -0
  24. package/lib/types/diagnosis/schema.d.ts +25 -2
  25. package/lib/types/diagnosis/schema.d.ts.map +1 -1
  26. package/lib/types/diagnosis/schema.js +64 -25
  27. package/lib/types/diagnosis/schema.js.map +1 -1
  28. package/lib/types/diagnosis/seed-source.d.ts +17 -2
  29. package/lib/types/diagnosis/seed-source.d.ts.map +1 -1
  30. package/lib/types/diagnosis/seed-source.js +19 -2
  31. package/lib/types/diagnosis/seed-source.js.map +1 -1
  32. package/lib/types/diagnosis/seed.d.ts +32 -42
  33. package/lib/types/diagnosis/seed.d.ts.map +1 -1
  34. package/lib/types/diagnosis/seed.js +187 -51
  35. package/lib/types/diagnosis/seed.js.map +1 -1
  36. package/lib/types/diagnosis/store.d.ts +95 -25
  37. package/lib/types/diagnosis/store.d.ts.map +1 -1
  38. package/lib/types/diagnosis/store.js +297 -166
  39. package/lib/types/diagnosis/store.js.map +1 -1
  40. package/lib/types/diagnosis/types.d.ts +168 -16
  41. package/lib/types/diagnosis/types.d.ts.map +1 -1
  42. package/lib/types/diagnosis/types.js +1 -1
  43. package/lib/types/diagnosis/types.js.map +1 -1
  44. package/lib/types/document-page.d.ts +39 -0
  45. package/lib/types/document-page.d.ts.map +1 -0
  46. package/lib/types/document-page.js +43 -0
  47. package/lib/types/document-page.js.map +1 -0
  48. package/lib/types/extract-model.d.ts +67 -27
  49. package/lib/types/extract-model.d.ts.map +1 -1
  50. package/lib/types/extract-model.js +225 -97
  51. package/lib/types/extract-model.js.map +1 -1
  52. package/lib/types/extract.d.ts +16 -0
  53. package/lib/types/extract.d.ts.map +1 -1
  54. package/lib/types/extract.js +19 -2
  55. package/lib/types/extract.js.map +1 -1
  56. package/lib/types/fs-atomic.d.ts +11 -0
  57. package/lib/types/fs-atomic.d.ts.map +1 -0
  58. package/lib/types/fs-atomic.js +41 -0
  59. package/lib/types/fs-atomic.js.map +1 -0
  60. package/lib/types/index.d.ts.map +1 -1
  61. package/lib/types/index.js +466 -63
  62. package/lib/types/index.js.map +1 -1
  63. package/lib/types/intent/types.js +1 -1
  64. package/lib/types/intent/types.js.map +1 -1
  65. package/lib/types/knowledge-bases.d.ts +23 -12
  66. package/lib/types/knowledge-bases.d.ts.map +1 -1
  67. package/lib/types/knowledge-bases.js +37 -44
  68. package/lib/types/knowledge-bases.js.map +1 -1
  69. package/lib/types/layout.d.ts +3 -3
  70. package/lib/types/layout.d.ts.map +1 -1
  71. package/lib/types/layout.js +4 -4
  72. package/lib/types/layout.js.map +1 -1
  73. package/lib/types/migrate.d.ts +1 -1
  74. package/lib/types/migrate.js +2 -2
  75. package/lib/types/migrate.js.map +1 -1
  76. package/lib/types/model-text.d.ts +99 -0
  77. package/lib/types/model-text.d.ts.map +1 -0
  78. package/lib/types/model-text.js +103 -0
  79. package/lib/types/model-text.js.map +1 -0
  80. package/lib/types/present.d.ts +239 -0
  81. package/lib/types/present.d.ts.map +1 -0
  82. package/lib/types/present.js +255 -0
  83. package/lib/types/present.js.map +1 -0
  84. package/lib/types/recall-rank.d.ts +37 -0
  85. package/lib/types/recall-rank.d.ts.map +1 -1
  86. package/lib/types/recall-rank.js +41 -1
  87. package/lib/types/recall-rank.js.map +1 -1
  88. package/lib/types/runtime.d.ts +564 -31
  89. package/lib/types/runtime.d.ts.map +1 -1
  90. package/lib/types/runtime.js +2645 -292
  91. package/lib/types/runtime.js.map +1 -1
  92. package/lib/types/settings-schema.d.ts +4 -2
  93. package/lib/types/settings-schema.d.ts.map +1 -1
  94. package/lib/types/settings-schema.js +2 -0
  95. package/lib/types/settings-schema.js.map +1 -1
  96. package/lib/types/source-images.d.ts +118 -0
  97. package/lib/types/source-images.d.ts.map +1 -0
  98. package/lib/types/source-images.js +288 -0
  99. package/lib/types/source-images.js.map +1 -0
  100. package/lib/types/types.d.ts +356 -28
  101. package/lib/types/types.d.ts.map +1 -1
  102. package/lib/types/types.js +112 -18
  103. package/lib/types/types.js.map +1 -1
  104. package/lib/types/wiki-finalize.d.ts +140 -0
  105. package/lib/types/wiki-finalize.d.ts.map +1 -0
  106. package/lib/types/wiki-finalize.js +269 -0
  107. package/lib/types/wiki-finalize.js.map +1 -0
  108. package/lib/types/wiki-types.d.ts +10 -2
  109. package/lib/types/wiki-types.d.ts.map +1 -1
  110. package/lib/types/wiki-types.js +27 -30
  111. package/lib/types/wiki-types.js.map +1 -1
  112. package/package.json +4 -3
  113. package/preset/tita-data-agent/agent.cordis.yml +25 -10
  114. package/src/client/DirectoryPicker.tsx +12 -12
  115. package/src/client/DrawerSection.tsx +18 -0
  116. package/src/client/InfoHint.tsx +21 -8
  117. package/src/client/IntentTab.tsx +20 -26
  118. package/src/client/KnowledgeBaseTab.tsx +458 -158
  119. package/src/client/KnowledgePanel.tsx +44 -10
  120. package/src/client/KnowledgeStepRail.tsx +3 -0
  121. package/src/client/KnowledgeToolRow.tsx +331 -0
  122. package/src/client/NodeSettings.tsx +20 -22
  123. package/src/client/PreviewSections.tsx +178 -43
  124. package/src/client/RecallPanel.tsx +418 -127
  125. package/src/client/TypeDefinitionDrawer.tsx +154 -54
  126. package/src/client/WikiCardReview.tsx +266 -0
  127. package/src/client/WikiFlowCard.tsx +57 -95
  128. package/src/client/WikiTypeEditor.tsx +197 -95
  129. package/src/client/arch/AgentArchitectureGraph.tsx +30 -14
  130. package/src/client/arch/NodeLogicPanel.tsx +6 -3
  131. package/src/client/arch/model.ts +164 -26
  132. package/src/client/architecture.css +25 -10
  133. package/src/client/architecture.tsx +66 -41
  134. package/src/client/asset-images.ts +125 -0
  135. package/src/client/attribution/AttributionGraph.tsx +481 -34
  136. package/src/client/attribution/AttributionTab.tsx +501 -106
  137. package/src/client/attribution/CaseView.tsx +9 -14
  138. package/src/client/attribution/GraphStage.tsx +25 -18
  139. package/src/client/attribution/RunView.tsx +27 -9
  140. package/src/client/attribution/StageChrome.tsx +280 -140
  141. package/src/client/attribution/graph-options.ts +611 -47
  142. package/src/client/attribution/model.ts +559 -30
  143. package/src/client/convert/ConvertPanel.tsx +36 -4
  144. package/src/client/doc-page.css +134 -0
  145. package/src/client/doc-page.tsx +242 -0
  146. package/src/client/index.ts +18 -0
  147. package/src/client/panel-state.ts +105 -0
  148. package/src/client/problem-domains.ts +1 -1
  149. package/src/client/request.ts +36 -0
  150. package/src/client/styles.css +397 -54
  151. package/src/client/useFitScale.ts +15 -2
  152. package/src/client/wiki-type-groups.ts +86 -0
  153. package/src/convert/host.ts +68 -9
  154. package/src/convert/ingest.ts +61 -18
  155. package/src/convert/types.ts +2 -2
  156. package/src/diagnosis/cards.ts +120 -50
  157. package/src/diagnosis/run.ts +251 -0
  158. package/src/diagnosis/schema.ts +67 -26
  159. package/src/diagnosis/seed-source.ts +29 -4
  160. package/src/diagnosis/seed.ts +187 -85
  161. package/src/diagnosis/store.ts +310 -173
  162. package/src/diagnosis/types.ts +181 -16
  163. package/src/document-page.ts +51 -0
  164. package/src/extract-model.ts +254 -99
  165. package/src/extract.ts +35 -3
  166. package/src/fs-atomic.ts +41 -0
  167. package/src/index.ts +499 -62
  168. package/src/intent/types.ts +1 -1
  169. package/src/knowledge-bases.ts +50 -49
  170. package/src/layout.ts +4 -4
  171. package/src/migrate.ts +2 -2
  172. package/src/model-text.ts +126 -0
  173. package/src/present.ts +367 -0
  174. package/src/recall-rank.ts +57 -2
  175. package/src/runtime.ts +2802 -293
  176. package/src/settings-schema.ts +2 -0
  177. package/src/source-images.ts +326 -0
  178. package/src/types.ts +446 -45
  179. package/src/wiki-finalize.ts +310 -0
  180. package/src/wiki-types.ts +28 -32
@@ -16,13 +16,16 @@ import { PROBLEM_CLASS_LABEL, problemClassIds, problemSubclassOf } from './probl
16
16
  * 序和枚举一旦写进散文,归并算法就再也读不到它们了。
17
17
  * 3. **校验必须分三层报错**:格式 / 引用完整性 / 语义。混成同一个「校验失败」,
18
18
  * 人就学不会怎么写卡片。
19
+ *
20
+ * 两处更名(0021 v1.1 / v1.2):`check` → **`check_point`**(检查点)、
21
+ * `failure-mode` → **`failure_reason`**(失败原因)。kind 用下划线,卡片类型用连字符。
19
22
  */
20
23
 
21
24
  export type DiagnosisEntityType =
22
25
  | 'diagnosis/symptom'
23
26
  | 'diagnosis/hypothesis'
24
- | 'diagnosis/check'
25
- | 'diagnosis/failure-mode'
27
+ | 'diagnosis/check-point'
28
+ | 'diagnosis/failure-reason'
26
29
  | 'diagnosis/case'
27
30
 
28
31
  export interface DiagnosisFieldSpec {
@@ -53,11 +56,29 @@ export interface DiagnosisEntitySpec {
53
56
  export const DIAGNOSIS_ENTITY_TYPES: DiagnosisEntityType[] = [
54
57
  'diagnosis/symptom',
55
58
  'diagnosis/hypothesis',
56
- 'diagnosis/check',
57
- 'diagnosis/failure-mode',
59
+ 'diagnosis/check-point',
60
+ 'diagnosis/failure-reason',
58
61
  'diagnosis/case',
59
62
  ]
60
63
 
64
+ /**
65
+ * 改名之前的两个 `entity_type`,以及它们对应的新名字。
66
+ *
67
+ * 留着这张表是为了**存量卡片不静默消失**:磁盘上还叫 `diagnosis/check` 的卡片,
68
+ * 如果读的时候直接判为「未知类型」,后果是这张卡片既不进 wikiNotes、也不上图,
69
+ * 而且没有任何报错。所以读取端按别名认,写入端做一次性迁移(见
70
+ * `runtime.migrateLegacyDiagnosisCards`)。
71
+ */
72
+ export const LEGACY_ENTITY_TYPES: Record<string, DiagnosisEntityType> = {
73
+ 'diagnosis/check': 'diagnosis/check-point',
74
+ 'diagnosis/failure-mode': 'diagnosis/failure-reason',
75
+ }
76
+
77
+ /** 卡片里那个旧字段名 → 新字段名。`failure_mode` 改叫 `failure_reason`。 */
78
+ export const LEGACY_BLOCK_FIELDS: Record<string, string> = {
79
+ failure_mode: 'failure_reason',
80
+ }
81
+
61
82
  /** 不是 wiki 卡片、但仍属于同一张图的节点类型。校验不按卡片规则要求它们。 */
62
83
  export const NON_CARD_KINDS: AttributionNodeKind[] = ['asset', 'evidence', 'cause', 'unknown']
63
84
 
@@ -76,11 +97,11 @@ export const DIAGNOSIS_ENTITIES: DiagnosisEntitySpec[] = [
76
97
  entityType: 'diagnosis/symptom',
77
98
  kind: 'symptom',
78
99
  layer: 'type',
79
- label: '现象类型',
100
+ label: '现象',
80
101
  fields: [
81
102
  { name: 'observable', note: '可观测口径:指标 + 维度 + 时间窗' },
82
103
  { name: 'entry_when', note: '什么条件下适用' },
83
- { name: 'problem_class', note: '问题大类:mandatory,取值只能来自 §4.5 的四个大类' },
104
+ { name: 'problem_class', note: '问题大类:必填,取值只能来自 §4.5 的四个大类' },
84
105
  { name: 'problem_subclass', note: '问题子类:必须属于所选大类;它同时决定 §5.1 的 shape / time_pattern' },
85
106
  ],
86
107
  sections: ['观测口径', '典型信号', '不适用的情况', '关联假设'],
@@ -93,34 +114,35 @@ export const DIAGNOSIS_ENTITIES: DiagnosisEntitySpec[] = [
93
114
  fields: [
94
115
  { name: 'discriminator', note: '**一句可判真假的话** —— 它同时是查重的比对对象' },
95
116
  { name: 'not_when', note: '**反例边界**:什么情况下这个假设不成立。refutes 边在文档层的表达' },
96
- { name: 'failure_mode', note: '切面:upstream-missing | spec-change | data-processing | consumption | permission' },
97
- { name: 'verified_by', note: '引用的检查 id 列表' },
98
- { name: 'assets', note: '关联资产(表 / 指标 / 任务)' },
117
+ { name: 'failure_reason', note: '切面:upstream-missing | spec-change | data-processing | consumption | permission' },
118
+ { name: 'verified_by', note: '引用的检查点 id 列表' },
119
+ { name: 'assets', note: '这条假设**落在**哪些对象上(反向索引入口)。可写成 `"dwd_ord_di"`,或 `{ id, type }` 顺带声明种类' },
99
120
  { name: 'stats', system: true, note: 'prior / last_hit_at / refutes_count / case_count' },
100
121
  ],
101
122
  sections: ['判据', '反例边界', '典型信号', '关联检查', '案例索引'],
102
123
  },
103
124
  {
104
- entityType: 'diagnosis/check',
105
- kind: 'check',
125
+ entityType: 'diagnosis/check-point',
126
+ kind: 'check_point',
106
127
  layer: 'type',
107
- label: '检查',
128
+ label: '检查点',
108
129
  fields: [
109
130
  { name: 'cost_minutes', note: '耗时(分钟),优先分的分母' },
110
131
  { name: 'automation', note: 'auto | manual' },
111
132
  { name: 'owner', note: '执行人或角色' },
112
133
  { name: 'verdict_true', note: '**看到什么算真**' },
113
134
  { name: 'verdict_false', note: '**看到什么算假** —— 只写「算真」就无法否定假设' },
114
- { name: 'runbook', note: '怎么跑:SQL / 工具 / 找谁' },
135
+ { name: 'runbook', note: '怎么跑:SQL / 工具 / 找谁。**可复用的查询模板**写这里' },
115
136
  { name: 'side_effect', note: '是否有副作用(只读 / 会写)' },
137
+ { name: 'assets', note: '**查询依据**:这条检查要去查哪些对象(表 / 指标 / 任务 / 链路)。可写成 `"dwd_ord_di"`,或 `{ id, type }` 顺带声明种类' },
116
138
  ],
117
139
  sections: ['怎么跑', '判定阈值', '有结论与无结论的区分'],
118
140
  },
119
141
  {
120
- entityType: 'diagnosis/failure-mode',
121
- kind: 'failure-mode',
142
+ entityType: 'diagnosis/failure-reason',
143
+ kind: 'failure_reason',
122
144
  layer: 'type',
123
- label: '失败模式(切面)',
145
+ label: '失败原因',
124
146
  fields: [
125
147
  { name: 'code', note: '稳定编码' },
126
148
  { name: 'label', note: '界面词' },
@@ -135,7 +157,7 @@ export const DIAGNOSIS_ENTITIES: DiagnosisEntitySpec[] = [
135
157
  label: '案例',
136
158
  fields: [
137
159
  { name: 'symptom', note: '入口现象 id' },
138
- { name: 'path', note: '**有序**节点序列:现象 → 假设 → 检查 → 证据 → 根因' },
160
+ { name: 'path', note: '**有序**节点序列:现象 → 假设 → 检查点 → 证据 → 根因' },
139
161
  { name: 'duration_minutes', note: '总耗时' },
140
162
  { name: 'misleading_edges', note: '误导边:节点 + 浪费的分钟数 + 为什么' },
141
163
  { name: 'root_cause', note: '根因一句话' },
@@ -146,7 +168,7 @@ export const DIAGNOSIS_ENTITIES: DiagnosisEntitySpec[] = [
146
168
  },
147
169
  ]
148
170
 
149
- /** 语义校验用的判据:check 的标题必须**可执行**。 */
171
+ /** 语义校验用的判据:检查点的标题必须**可执行**。 */
150
172
  const VAGUE_CHECK_TITLES = /^(检查|看看|排查|确认)?\s*(一下)?\s*(数据质量|是不是|有没有问题|上游|下游)/
151
173
 
152
174
  export type DiagnosisIssueLevel = 'format' | 'reference' | 'semantic'
@@ -171,6 +193,9 @@ export function specOf(kind: AttributionNodeKind): DiagnosisEntitySpec | undefin
171
193
  *
172
194
  * 分开报错不是洁癖:**格式错说明卡片没填完,引用错说明图断了,语义错说明这条知识
173
195
  * 本身没用**。三者对应的动作完全不同(补字段 / 修边 / 重写),混在一起就只能靠猜。
196
+ *
197
+ * 它同时是**提议阶段与确认阶段的前置**(0021 §6.5):两道都跑,是因为这两次修改
198
+ * 来自不同的人。
174
199
  */
175
200
  export function validateDiagnosis(graph: AttributionGraphData): DiagnosisIssue[] {
176
201
  const issues: DiagnosisIssue[] = []
@@ -185,7 +210,7 @@ export function validateDiagnosis(graph: AttributionGraphData): DiagnosisIssue[]
185
210
  if (node.kind === 'hypothesis') {
186
211
  if (!node.discriminator?.trim()) issues.push(fieldIssue(node, 'discriminator', '假设必须有一句可判真假的判据'))
187
212
  if (!node.notWhen?.trim()) issues.push(fieldIssue(node, 'notWhen', '假设必须写明反例边界 —— 否则查重会把相似情形并成一条'))
188
- if (!node.failureMode) issues.push(fieldIssue(node, 'failureMode', '假设必须归属一个失败模式切面'))
213
+ if (!node.failureReason) issues.push(fieldIssue(node, 'failureReason', '假设必须归属一个失败原因切面'))
189
214
  }
190
215
  if (node.kind === 'symptom') {
191
216
  // 问题侧的分类是**必填**:留空的后果不是「少个字段」,而是这个现象在按问题筛选时
@@ -207,12 +232,22 @@ export function validateDiagnosis(graph: AttributionGraphData): DiagnosisIssue[]
207
232
  // 分类字段只属于现象。假设上挂问题大类,会把「问题」和「原因」两根轴搅在一起。
208
233
  issues.push(fieldIssue(node, 'problemClass', '问题分类只能写在现象(symptom)上,不能挂在原因侧'))
209
234
  }
210
- if (node.kind === 'check') {
235
+ if (node.kind === 'check_point') {
211
236
  for (const [field, value] of [['costMinutes', node.costMinutes], ['automation', node.automation], ['owner', node.owner], ['verdictTrue', node.verdictTrue], ['verdictFalse', node.verdictFalse]] as const) {
212
- if (value === undefined || value === '') issues.push(fieldIssue(node, field, `检查缺少 ${field} —— 缺了它这一步就无法被自动化或复核`))
237
+ if (value === undefined || value === '') issues.push(fieldIssue(node, field, `检查点缺少 ${field} —— 缺了它这一步就无法被自动化或复核`))
213
238
  }
239
+ // `assets[]` 是 v1.3 的必填:缺了它,这条检查**不知道去哪查**,
240
+ // 也就没法生成查询、判断影响面。
241
+ if (!node.assets || node.assets.length === 0) {
242
+ issues.push(fieldIssue(node, 'assets', '检查点必须写明查询依据(assets[])—— 缺了它这条检查不知道去哪查'))
243
+ }
244
+ }
245
+ if (node.kind === 'evidence') {
246
+ if (!node.query?.trim()) issues.push(fieldIssue(node, 'query', '证据必须记下这次实际跑的查询'))
247
+ if (!node.verdict) issues.push(fieldIssue(node, 'verdict', '证据必须给出结论:supports / refutes / inconclusive'))
248
+ if (!node.why?.trim()) issues.push(fieldIssue(node, 'why', '证据必须说明「为什么这个结果算数或不算数」—— 采信与剔除都得能说理由'))
214
249
  }
215
- // `case` 节点只是图上的桩:案例的正文与路径住在 `cases.json` 里,由
250
+ // `case` 节点只是图上的桩:案例的正文与路径住在案例卡片里,由
216
251
  // DiagnosisSnapshot.cases 校验,不在节点上重复要求。
217
252
  }
218
253
 
@@ -225,18 +260,18 @@ export function validateDiagnosis(graph: AttributionGraphData): DiagnosisIssue[]
225
260
  if (node.kind !== 'hypothesis') continue
226
261
  const hasCheck = graph.edges.some(edge => edge.kind === 'verified_by' && edge.source === node.id)
227
262
  // 空区不是错,是**待办**:它是一条信息(这张图哪里还没建完),所以只提示不报错。
228
- if (!hasCheck) issues.push({ level: 'semantic', entityId: node.id, message: '空区:有假设但没有任何检查,拿不出成本,因此进不了排序' })
263
+ if (!hasCheck) issues.push({ level: 'semantic', entityId: node.id, message: '空区:有假设但没有任何检查点,拿不出成本,因此进不了排序' })
229
264
  }
230
265
 
231
266
  // ── 第三层:语义 ──────────────────────────────────────────────────────────
232
267
  for (const node of graph.nodes) {
233
- if (node.kind !== 'check') continue
268
+ if (node.kind !== 'check_point') continue
234
269
  if (VAGUE_CHECK_TITLES.test(node.title.trim())) {
235
270
  issues.push({
236
271
  level: 'semantic',
237
272
  entityId: node.id,
238
273
  field: 'title',
239
- message: `检查标题不可执行:「${node.title}」。必须能回答「谁、用什么、多久、看到什么算真、看到什么算假」`,
274
+ message: `检查点标题不可执行:「${node.title}」。必须能回答「谁、用什么、多久、看到什么算真、看到什么算假」`,
240
275
  })
241
276
  }
242
277
  }
@@ -244,7 +279,13 @@ export function validateDiagnosis(graph: AttributionGraphData): DiagnosisIssue[]
244
279
  return issues
245
280
  }
246
281
 
247
- /** 空的模板卡:新人写卡片时看的是它,不是 schema。 */
282
+ /**
283
+ * 空的模板卡:新人写卡片时看的是它,不是 schema。
284
+ *
285
+ * 模板卡**由类型定义派生、不再落成磁盘文件**(0021 §6.6):模板是类型定义的一种
286
+ * 呈现,定义搬进设置,模板跟着走 —— 否则会出现「设置里改了、磁盘上那份没改」的
287
+ * 第二真源。
288
+ */
248
289
  export function templateCard(spec: DiagnosisEntitySpec): string {
249
290
  const front = [
250
291
  `entity_type: ${spec.entityType}`,
@@ -2,7 +2,7 @@
2
2
  * Seed 的**原始材料**:一份排查手册 + 三篇复盘。
3
3
  *
4
4
  * 这一层存在的理由,正是 v0.7 修掉的那处架构缺口:排查思路如果只以 TypeScript 字面量存在,
5
- * 它就**不是 wiki 内容** —— 不会进 `01_source_truth`、不会被编译、永远召不回来。
5
+ * 它就**不是 wiki 内容** —— 不会进 `01_source_raw`、不会被编译、永远召不回来。
6
6
  * 所以 seed 也走完整条动线:
7
7
  *
8
8
  * ```
@@ -12,14 +12,22 @@
12
12
  * 手册与复盘是**人写的散文**(就是下面这些字面量),卡片是从它们编译出来的结构化提取。
13
13
  * 两者内容会有重叠 —— 那是正常的:卡片是散文的投影,不是它的替代品。
14
14
  */
15
- import { SEED_CASES } from './seed.js'
15
+ import { SEED_CASES, SEED_RUNS } from './seed.js'
16
+ import { renderRunSource } from './run.js'
16
17
 
17
18
  export interface SeedSource {
18
19
  /** 稳定 id,用作 `external_id`,迁移与重跑都靠它幂等。 */
19
20
  id: string
20
21
  title: string
21
- /** 来源分类。排查手册与复盘都属于既有的 `question`(「问题排查文档」)。 */
22
- sourceType: 'question'
22
+ /**
23
+ * 来源分类。**两种**:
24
+ * - `question`:人写的手册与复盘(卡片 `source_refs` 指向这里);
25
+ * - `agent_diagnosis_case`:Agent 跑出来的三次排查记录(v1.1 新增的来源分类)。
26
+ *
27
+ * 边界裁决是「谁写的、是不是已经归纳过」:同一件事可以有两条来源,
28
+ * 一个回答「结论是什么」,一个回答「当时怎么走的」。
29
+ */
30
+ sourceType: 'question' | 'agent_diagnosis_case'
23
31
  content: string
24
32
  }
25
33
 
@@ -99,9 +107,26 @@ export function seedCaseSources(): SeedSource[] {
99
107
  }))
100
108
  }
101
109
 
110
+ /**
111
+ * 三次排查的**过程记录**。
112
+ *
113
+ * 它们不由散文手写,而是从 `SEED_RUNS` **渲染**出来(`renderRunSource`)——
114
+ * 这正是运行时那条路径:一次排查结束 → 一条 `agent_diagnosis_case` 的 SourceRaw。
115
+ * 示例走同一条路,所以它同时也是这条路的回归夹具。
116
+ */
117
+ export function seedRunSources(): SeedSource[] {
118
+ return SEED_RUNS.map(record => ({
119
+ id: record.runId,
120
+ title: `AI 诊断日志 · ${record.symptomId} · ${record.runId}`,
121
+ sourceType: 'agent_diagnosis_case' as const,
122
+ content: renderRunSource(record),
123
+ }))
124
+ }
125
+
102
126
  export function seedSources(): SeedSource[] {
103
127
  return [
104
128
  { id: 'handbook', title: '日报指标异常排查手册(内部版)', sourceType: 'question', content: SEED_HANDBOOK },
105
129
  ...seedCaseSources(),
130
+ ...seedRunSources(),
106
131
  ]
107
132
  }