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
@@ -1,7 +1,7 @@
1
1
  import { ChevronDown, CircleDot, FileText, TriangleAlert } from '@tita-data-agent/ui/icons'
2
2
  import type { ReactNode } from 'react'
3
3
  import { Badge, Button, Card, cn } from '@tita-data-agent/ui/components'
4
- import { SEED_CASES } from '../../diagnosis/seed.js'
4
+ import type { AttributionCase } from './model.ts'
5
5
 
6
6
  /**
7
7
  * 案例视图:**wiki 定义 + 排查节点**。
@@ -13,21 +13,26 @@ import { SEED_CASES } from '../../diagnosis/seed.js'
13
13
  * 所以这里不做「文档里嵌一张图」那种合成视图,而是把两段并排放在同一张卡里 ——
14
14
  * 读者能同时看到叙述和结构,而两者的数据源仍然各自独立。
15
15
  *
16
+ * 案例**由调用方传入**(服务端的 `/diagnosis/graph` 给的那一份)。这一层原来直接
17
+ * import `SEED_CASES`,于是不管你的库里有没有案例,这一页画的都是内置示例。
18
+ *
16
19
  * 红色底边与绿色底没有共享的 Tailwind 工具类(工具类只在 packages/ui 构建时按用到的类
17
20
  * 生成,而插件不能改 packages/ui),所以这两处走行内 `style`,取值仍是共享令牌。
18
21
  */
19
22
  /** 被否定的一步 / 误导段共用的红色底与边(见文件头)。 */
20
23
  const REFUTED_WASH = { borderColor: 'var(--ddk-danger-line)', background: 'var(--ddk-danger-tint)' }
21
24
 
22
- export function CaseView({ activeId, onActiveChange }: {
25
+ export function CaseView({ cases, activeId, onActiveChange }: {
26
+ cases: AttributionCase[]
23
27
  activeId: string
24
28
  onActiveChange: (id: string) => void
25
29
  }): ReactNode {
26
- const active = SEED_CASES.find(item => item.id === activeId) ?? SEED_CASES[0]!
30
+ const active = cases.find(item => item.id === activeId) ?? cases[0]
31
+ if (!active) return <p className="text-[11px] text-tita-ink-muted">这个知识库还没有排查案例。</p>
27
32
 
28
33
  return <div className="flex flex-col gap-3">
29
34
  <div className="flex flex-wrap gap-1.5">
30
- {SEED_CASES.map(item => <Button
35
+ {cases.map(item => <Button
31
36
  key={item.id}
32
37
  variant={item.id === active.id ? 'default' : 'outline'}
33
38
  size="sm"
@@ -88,15 +93,5 @@ export function CaseView({ activeId, onActiveChange }: {
88
93
  </footer>
89
94
  </Card>
90
95
 
91
- <details className="group rounded-lg border border-tita-line bg-tita-surface p-2.5">
92
- <summary className="flex cursor-pointer list-none items-center gap-1.5 text-[11.5px] font-medium">
93
- <ChevronDown size={13} className="transition-transform group-open:rotate-180" />
94
- 为什么案例要分「wiki 段」和「节点段」两段
95
- </summary>
96
- <p className="mt-1.5 text-[10.5px] leading-relaxed text-tita-ink-muted">
97
- wiki 段是给人读、给向量召回的散文;节点段是给归并与剪枝读的结构。把「序」和「枚举」写进散文,
98
- 归并算法就再也读不到它们了 —— 这也是案例不能只存成一篇文档的原因。
99
- </p>
100
- </details>
101
96
  </div>
102
97
  }
@@ -10,19 +10,24 @@ export interface GraphStageProps {
10
10
  /**
11
11
  * 覆盖层(案例 / 排查视图)。
12
12
  *
13
- * 给了它,画布**不卸载**,只是被盖住。理由是位置记忆:力导向图被拖动过之后,
13
+ * 给了它,画布**不卸载**,只是被盖住。理由是位置记忆:被拖动过之后,
14
14
  * 切到案例再切回来应该还是原来的形状;卸载重建会让每次切页都把图重新吹散。
15
15
  */
16
16
  layer?: ReactNode
17
- /** 左上:布局切换 + 类型切面。 */
17
+ /** 画布左上:操作(按动线顺序的四组切面)。 */
18
18
  topLeft?: ReactNode
19
- /** 右上:图例 + 全屏。 */
19
+ /** 画布右上:读法(图例 · 全景 / 聚焦 · 保留 1 跳邻居 · 全屏,四个同排)。 */
20
20
  topRight?: ReactNode
21
- /** 底部中间:其余筛选。 */
21
+ /** 画布底中:文本搜索 + 命中数。 */
22
22
  bottomCenter?: ReactNode
23
- /** 右下:统计。 */
24
- bottomRight?: ReactNode
25
- /** 右侧副栏,贴在顶部那一行之下(图例正文、选中节点详情)。 */
23
+ /**
24
+ * 画布左下:读数(统计 + 数据来源)。
25
+ *
26
+ * v1.4 从右下搬来(0021 §7.1):左列因此形成「上面改、下面读」的一列,
27
+ * 右下让给图例与选中节点详情的展开正文。
28
+ */
29
+ bottomLeft?: ReactNode
30
+ /** 画布右侧副栏,贴在右上那一行之下(图例正文、选中节点详情)。 */
26
31
  side?: ReactNode
27
32
  className?: string
28
33
  }
@@ -32,19 +37,20 @@ export interface GraphStageProps {
32
37
  *
33
38
  * **它存在的唯一理由是「图谱占满内容区」。** 改版前,筛选、统计、图例都是图谱的
34
39
  * 兄弟节点,从上到下堆成一列 —— 在 380px 宽的右栏里,图谱被自己的控件挤到只剩
35
- * 一半高度。改版后所有这些控件变成**浮在画布上的四条边**(左上 / 右上 / 底中 /
36
- * 右下),画布本身吃掉整块面积。这是「打开就是一张大图」在结构上的实现方式:
37
- * 不是把图放大,而是把其它东西从它的高度里拿走。
40
+ * 一半高度。改版后所有这些控件变成**浮在画布上的四条边**(左上操作 / 右上读法 /
41
+ * 左下读数 / 底中搜索),画布本身吃掉整块面积。这是「打开就是一张大图」在结构上的
42
+ * 实现方式:不是把图放大,而是把其它东西从它的高度里拿走。
38
43
  *
39
44
  * 两套排布分开写,而不是用一套 `absolute` 加条件:
40
45
  * - **画布模式**(无明显层):四条边浮在画布上,画布铺满,节点在浮层下面继续延展。
41
46
  * - **内容模式**(案例 / 排查):内容要滚动,浮层浮在滚动内容上会遮住正文,
42
47
  * 所以顶部控件改为正常流里的一行,内容占满其余高度。
43
48
  *
44
- * 浮层容器整体 `pointer-events-none`、只给面板本身打开命中 —— 否则四条边的
45
- * 空档会把画布的拖拽和滚轮缩放吞掉。
49
+ * 浮层容器整体 `pointer-events-none`、只给面板本身打开命中(§7.4 第 10 条)——
50
+ * 否则四条边的空档会把画布的拖拽和滚轮缩放吞掉。左右两条因此可以同处一行:
51
+ * 它们之间的空档不属于任何一条,事件直接落到画布上。
46
52
  */
47
- export function GraphStage({ mode, canvas, layer, topLeft, topRight, bottomCenter, bottomRight, side, className }: GraphStageProps): ReactNode {
53
+ export function GraphStage({ mode, canvas, layer, topLeft, topRight, bottomCenter, bottomLeft, side, className }: GraphStageProps): ReactNode {
48
54
  const frame = cn(
49
55
  'relative min-h-0 w-full flex-1 overflow-hidden rounded-xl border border-tita-line bg-tita-surface',
50
56
  className,
@@ -65,9 +71,10 @@ export function GraphStage({ mode, canvas, layer, topLeft, topRight, bottomCente
65
71
 
66
72
  return <div className={frame}>
67
73
  <div className="absolute inset-0">{canvas}</div>
68
- <div className="pointer-events-none relative flex h-full flex-col gap-1.5 p-2">
74
+ {/* 四条浮层容器的这一层不吃事件,事件只在各自的面板上被接住。 */}
75
+ <div className="pointer-events-none absolute inset-0 flex flex-col gap-1.5 p-2">
69
76
  <div className="flex items-start gap-1.5">
70
- {topLeft && <div className="pointer-events-auto min-w-0 max-w-full">{topLeft}</div>}
77
+ {topLeft && <div className="pointer-events-auto min-w-0 max-w-[calc(100%-128px)]">{topLeft}</div>}
71
78
  {topRight && <div className="pointer-events-auto ml-auto shrink-0">{topRight}</div>}
72
79
  </div>
73
80
  {side && <div className={cn(
@@ -78,9 +85,9 @@ export function GraphStage({ mode, canvas, layer, topLeft, topRight, bottomCente
78
85
  )}>
79
86
  {side}
80
87
  </div>}
81
- <div className="mt-auto flex flex-col gap-1.5">
82
- {bottomCenter && <div className="pointer-events-auto mx-auto w-full">{bottomCenter}</div>}
83
- {bottomRight && <div className="pointer-events-auto ml-auto">{bottomRight}</div>}
88
+ <div className="mt-auto flex items-end gap-1.5">
89
+ {bottomLeft && <div className="pointer-events-auto min-w-0 shrink">{bottomLeft}</div>}
90
+ {bottomCenter && <div className="pointer-events-auto mx-auto w-full min-w-0">{bottomCenter}</div>}
84
91
  </div>
85
92
  </div>
86
93
  </div>
@@ -3,9 +3,8 @@ import { useMemo, type ReactNode } from 'react'
3
3
  import { Badge, Button, Card, cn } from '@tita-data-agent/ui/components'
4
4
  import {
5
5
  candidatesOf, problemBadgeOf, PROBLEM_CLASS_LABEL, SAMPLE_SIZE,
6
- type AttributionGraphData, type AttributionNode,
6
+ type AttributionCase, type AttributionGraphData, type AttributionNode,
7
7
  } from './model.ts'
8
- import { SEED_CASES } from '../../diagnosis/seed.js'
9
8
 
10
9
  /**
11
10
  * 本文件里凡是没有共享 Tailwind 工具类的颜色(tone 墨色、强调环、红色底边)都走行内
@@ -19,8 +18,10 @@ import { SEED_CASES } from '../../diagnosis/seed.js'
19
18
  *
20
19
  * 排序与优先分全部来自 `candidatesOf()`,界面不自己再算一遍「哪个该先查」。
21
20
  */
22
- export function RunView({ data, symptoms, symptomId, onSymptomChange, onSelectNode }: {
21
+ export function RunView({ data, cases, symptoms, symptomId, onSymptomChange, onSelectNode }: {
23
22
  data: AttributionGraphData
23
+ /** 案例清单(服务端那一份)。用来回答「这次排序把哪几个案例的路径算进去了」。 */
24
+ cases: AttributionCase[]
24
25
  /** 可选的现象清单。**必须能切**:不同现象共享同一批假设,候选排序也各不相同。 */
25
26
  symptoms: AttributionNode[]
26
27
  symptomId: string
@@ -32,7 +33,7 @@ export function RunView({ data, symptoms, symptomId, onSymptomChange, onSelectNo
32
33
 
33
34
  /** 来源归因:这次排序把哪些案例的路径算进去了。锚定风险靠它显式可见。 */
34
35
  const sourcesOf = (hypothesisId: string): string[] =>
35
- SEED_CASES.filter(item => item.path.some(step => step.nodeId === hypothesisId) || item.misleading?.nodeId === hypothesisId)
36
+ cases.filter(item => item.path.some(step => step.nodeId === hypothesisId) || item.misleading?.nodeId === hypothesisId)
36
37
  .map(item => item.id.replace('CASE-', '#'))
37
38
 
38
39
  const gapCandidate = candidates.find(candidate => candidate.gap)
@@ -54,7 +55,7 @@ export function RunView({ data, symptoms, symptomId, onSymptomChange, onSelectNo
54
55
  <div className="min-w-0">
55
56
  <h3 className="text-[12.5px] font-semibold">{symptom?.title ?? symptomId}</h3>
56
57
  <p className="mt-0.5 text-[10.5px] leading-snug text-tita-ink-muted">
57
- 优先分 = 根因占比 ÷ 检查成本 · 样本量 {SAMPLE_SIZE} 次(近 30 天)
58
+ 优先分 = 根因占比 ÷ 检查成本 · 分母取示例样本量 {SAMPLE_SIZE}(`prior` 尚未由系统回填)
58
59
  </p>
59
60
  </div>
60
61
  <Badge tone="blue">{candidates.length + (gapCandidate ? 1 : 0)} 个候选</Badge>
@@ -93,7 +94,7 @@ export function RunView({ data, symptoms, symptomId, onSymptomChange, onSelectNo
93
94
 
94
95
  {/* 来源归因:把「这次排序被谁影响」摊开,否则锚定是无声的。 */}
95
96
  <p className="text-[10px] text-tita-ink-faint">
96
- 来源:{sourcesOf(candidate.hypothesis.id).join(' · ') || '切面先验'} · 切面 {candidate.hypothesis.failureMode ?? '未标注'}
97
+ 来源:{sourcesOf(candidate.hypothesis.id).join(' · ') || '切面先验'} · 切面 {candidate.hypothesis.failureReason ?? '未标注'}
97
98
  </p>
98
99
 
99
100
  <div className="flex flex-col gap-1">
@@ -132,10 +133,18 @@ export function RunView({ data, symptoms, symptomId, onSymptomChange, onSelectNo
132
133
  <div className="flex items-center gap-2">
133
134
  <CircleHelp size={14} className="shrink-0" style={{ color: 'var(--tita-tone-amber)' }} />
134
135
  <span className="flex-1 text-[12px] font-semibold">未归类(假设空间之外)</span>
135
- <Button size="sm">登记新假设</Button>
136
+ <Badge tone="warning">待实现</Badge>
136
137
  </div>
137
138
  <p className="text-[10.5px] leading-snug text-tita-ink-muted">
138
- 近 30 天 8 次 · 占比 20% —— 它是重量抽象的触发器,不是兜底话术。
139
+ 它是**登记新假设**的触发器,不是兜底话术:候选剪空时不该返回空列表,
140
+ 而应该在这里落一条「这个现象我们还没有对应的假设」。
141
+ </p>
142
+ {/* 这里原来写「近 30 天 8 次 · 占比 20%」—— 那是编出来的数字,与产品第一条
143
+ 品牌承诺(不编造数字、未实现必须标出)直接冲突。真实计数要等 `unknown`
144
+ 节点与它的统计落地之后才有;在那之前如实标「待实现」,不填占位数字。 */}
145
+ <p className="text-[10px] leading-snug text-tita-ink-faint">
146
+ 登记入口在「知识库 → Wiki」的待办区:Agent 用 <b>propose_wiki_cards</b> 提一条
147
+ 假设草案,人确认之后才落卡(未确认的提议不上图)。这一屏目前只读。
139
148
  </p>
140
149
  </Card>
141
150
 
@@ -163,7 +172,16 @@ export function RunView({ data, symptoms, symptomId, onSymptomChange, onSelectNo
163
172
  <TriangleAlert size={10} className="mr-1 inline align-[-1px]" />
164
173
  被否定,记为误导边 —— 否定也是要写回的内容。
165
174
  </p>
166
- <Button className="w-full" size="sm">写回图谱(记录本次路径)</Button>
175
+ {/*
176
+ 写回**不从这一屏发起**。这一屏渲染的是一份已有的知识(案例路径 + 候选集),
177
+ 不是一次进行中的排查 —— 没有「本次跑了哪些检查点、看到什么」的现场状态,
178
+ 按一个按钮只能编出一份路径来,而那正好是这个产品最不该做的事。
179
+ 真实的写回发生在排查进行时:Agent 调 `POST /diagnosis/run` 落一条
180
+ `agent_diagnosis_case` 的 SourceRaw,顺手提一张案例卡片等人确认。
181
+ */}
182
+ <Button className="w-full" size="sm" disabled title="写回发生在排查进行时:Agent 用 POST /diagnosis/run 落一条诊断日志并提议案例卡片。这一屏是只读的复盘视图。">
183
+ 写回由排查进行时完成(这一屏只读)
184
+ </Button>
167
185
  </Card>
168
186
  </div>
169
187
  }