dsh-data-domain-knowledge 0.1.0-alpha.9 → 0.1.1-alpha.2

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 (438) hide show
  1. package/README.md +118 -567
  2. package/cordis.patch.yml +5 -418
  3. package/eval/README.md +19 -8
  4. package/eval/benchmark-extraction-format.mjs +20 -0
  5. package/eval/evaluate-retrieval.mjs +17 -8
  6. package/eval/queries.example.jsonl +1 -0
  7. package/lib/client.js +4181 -3239
  8. package/lib/contract-envelope.d.ts +91 -0
  9. package/lib/contract-envelope.js +106 -0
  10. package/lib/contract-layout.d.ts +130 -0
  11. package/lib/contract-layout.js +138 -0
  12. package/lib/contract-refs.d.ts +39 -0
  13. package/lib/contract-refs.js +9 -0
  14. package/lib/contract-version.d.ts +311 -0
  15. package/lib/contract-version.js +270 -0
  16. package/lib/contract-wire.d.ts +147 -0
  17. package/lib/contract-wire.js +99 -0
  18. package/lib/contracts.d.ts +12 -0
  19. package/lib/contracts.js +12 -0
  20. package/lib/doc-page.js +2 -2
  21. package/lib/pages.js +3329 -1296
  22. package/lib/types/agent-behavior-rules.d.ts +10 -0
  23. package/lib/types/agent-behavior-rules.d.ts.map +1 -0
  24. package/lib/types/agent-behavior-rules.js +28 -0
  25. package/lib/types/agent-behavior-rules.js.map +1 -0
  26. package/lib/types/axis-registry.d.ts +37 -5
  27. package/lib/types/axis-registry.d.ts.map +1 -1
  28. package/lib/types/axis-registry.js +234 -26
  29. package/lib/types/axis-registry.js.map +1 -1
  30. package/lib/types/card-organize.d.ts +27 -12
  31. package/lib/types/card-organize.d.ts.map +1 -1
  32. package/lib/types/card-organize.js +58 -73
  33. package/lib/types/card-organize.js.map +1 -1
  34. package/lib/types/compiler/embedding-identity.d.ts +3 -0
  35. package/lib/types/compiler/embedding-identity.d.ts.map +1 -0
  36. package/lib/types/compiler/embedding-identity.js +24 -0
  37. package/lib/types/compiler/embedding-identity.js.map +1 -0
  38. package/lib/types/compiler/snapshot.d.ts +16 -0
  39. package/lib/types/compiler/snapshot.d.ts.map +1 -0
  40. package/lib/types/compiler/snapshot.js +2 -0
  41. package/lib/types/compiler/snapshot.js.map +1 -0
  42. package/lib/types/config-schema.d.ts +6 -3
  43. package/lib/types/config-schema.d.ts.map +1 -1
  44. package/lib/types/config-schema.js +6 -2
  45. package/lib/types/config-schema.js.map +1 -1
  46. package/lib/types/convert/host.d.ts +6 -5
  47. package/lib/types/convert/host.d.ts.map +1 -1
  48. package/lib/types/convert/host.js +58 -18
  49. package/lib/types/convert/host.js.map +1 -1
  50. package/lib/types/convert/ingest.d.ts +10 -1
  51. package/lib/types/convert/ingest.d.ts.map +1 -1
  52. package/lib/types/convert/ingest.js +68 -9
  53. package/lib/types/convert/ingest.js.map +1 -1
  54. package/lib/types/derive-contract.d.ts +3 -0
  55. package/lib/types/derive-contract.d.ts.map +1 -0
  56. package/lib/types/derive-contract.js +15 -0
  57. package/lib/types/derive-contract.js.map +1 -0
  58. package/lib/types/diagnosis/cards.d.ts +7 -3
  59. package/lib/types/diagnosis/cards.d.ts.map +1 -1
  60. package/lib/types/diagnosis/cards.js +13 -8
  61. package/lib/types/diagnosis/cards.js.map +1 -1
  62. package/lib/types/diagnosis/run.d.ts +4 -13
  63. package/lib/types/diagnosis/run.d.ts.map +1 -1
  64. package/lib/types/diagnosis/run.js +26 -16
  65. package/lib/types/diagnosis/run.js.map +1 -1
  66. package/lib/types/diagnosis/schema.js +2 -2
  67. package/lib/types/diagnosis/schema.js.map +1 -1
  68. package/lib/types/diagnosis/seed-source.d.ts +1 -1
  69. package/lib/types/diagnosis/seed-source.d.ts.map +1 -1
  70. package/lib/types/diagnosis/seed-source.js +5 -4
  71. package/lib/types/diagnosis/seed-source.js.map +1 -1
  72. package/lib/types/diagnosis/seed.d.ts +4 -4
  73. package/lib/types/diagnosis/seed.d.ts.map +1 -1
  74. package/lib/types/diagnosis/seed.js +6 -8
  75. package/lib/types/diagnosis/seed.js.map +1 -1
  76. package/lib/types/diagnosis/store.d.ts +24 -18
  77. package/lib/types/diagnosis/store.d.ts.map +1 -1
  78. package/lib/types/diagnosis/store.js +130 -65
  79. package/lib/types/diagnosis/store.js.map +1 -1
  80. package/lib/types/diagnosis/types.d.ts +47 -15
  81. package/lib/types/diagnosis/types.d.ts.map +1 -1
  82. package/lib/types/diagnosis/types.js.map +1 -1
  83. package/lib/types/environment/dsh-python.d.ts +77 -0
  84. package/lib/types/environment/dsh-python.d.ts.map +1 -0
  85. package/lib/types/environment/dsh-python.js +139 -0
  86. package/lib/types/environment/dsh-python.js.map +1 -0
  87. package/lib/types/environment/install.d.ts +15 -0
  88. package/lib/types/environment/install.d.ts.map +1 -0
  89. package/lib/types/environment/install.js +297 -0
  90. package/lib/types/environment/install.js.map +1 -0
  91. package/lib/types/environment/manifest.d.ts +208 -0
  92. package/lib/types/environment/manifest.d.ts.map +1 -0
  93. package/lib/types/environment/manifest.js +26 -0
  94. package/lib/types/environment/manifest.js.map +1 -0
  95. package/lib/types/environment/model-catalog.d.ts +223 -0
  96. package/lib/types/environment/model-catalog.d.ts.map +1 -0
  97. package/lib/types/environment/model-catalog.js +129 -0
  98. package/lib/types/environment/model-catalog.js.map +1 -0
  99. package/lib/types/environment/process.d.ts +10 -0
  100. package/lib/types/environment/process.d.ts.map +1 -0
  101. package/lib/types/environment/process.js +54 -0
  102. package/lib/types/environment/process.js.map +1 -0
  103. package/lib/types/environment/selection.d.ts +9 -0
  104. package/lib/types/environment/selection.d.ts.map +1 -0
  105. package/lib/types/environment/selection.js +29 -0
  106. package/lib/types/environment/selection.js.map +1 -0
  107. package/lib/types/environment/service.d.ts +64 -0
  108. package/lib/types/environment/service.d.ts.map +1 -0
  109. package/lib/types/environment/service.js +424 -0
  110. package/lib/types/environment/service.js.map +1 -0
  111. package/lib/types/environment/types.d.ts +56 -0
  112. package/lib/types/environment/types.d.ts.map +1 -0
  113. package/lib/types/environment/types.js +2 -0
  114. package/lib/types/environment/types.js.map +1 -0
  115. package/lib/types/events.d.ts +76 -0
  116. package/lib/types/events.d.ts.map +1 -0
  117. package/lib/types/events.js +52 -0
  118. package/lib/types/events.js.map +1 -0
  119. package/lib/types/extract-contract.d.ts +3 -0
  120. package/lib/types/extract-contract.d.ts.map +1 -0
  121. package/lib/types/extract-contract.js +41 -0
  122. package/lib/types/extract-contract.js.map +1 -0
  123. package/lib/types/extract-model.d.ts +5 -0
  124. package/lib/types/extract-model.d.ts.map +1 -1
  125. package/lib/types/extract-model.js.map +1 -1
  126. package/lib/types/extract-table-contract.d.ts +3 -0
  127. package/lib/types/extract-table-contract.d.ts.map +1 -0
  128. package/lib/types/extract-table-contract.js +27 -0
  129. package/lib/types/extract-table-contract.js.map +1 -0
  130. package/lib/types/extract-table.d.ts +8 -0
  131. package/lib/types/extract-table.d.ts.map +1 -0
  132. package/lib/types/extract-table.js +158 -0
  133. package/lib/types/extract-table.js.map +1 -0
  134. package/lib/types/extraction-runs.d.ts +30 -6
  135. package/lib/types/extraction-runs.d.ts.map +1 -1
  136. package/lib/types/extraction-runs.js +69 -8
  137. package/lib/types/extraction-runs.js.map +1 -1
  138. package/lib/types/fs-atomic.d.ts +0 -7
  139. package/lib/types/fs-atomic.d.ts.map +1 -1
  140. package/lib/types/fs-atomic.js +17 -2
  141. package/lib/types/fs-atomic.js.map +1 -1
  142. package/lib/types/images.d.ts +26 -0
  143. package/lib/types/images.d.ts.map +1 -0
  144. package/lib/types/images.js +196 -0
  145. package/lib/types/images.js.map +1 -0
  146. package/lib/types/index.d.ts +2 -2
  147. package/lib/types/index.d.ts.map +1 -1
  148. package/lib/types/index.js +598 -209
  149. package/lib/types/index.js.map +1 -1
  150. package/lib/types/intent/engine.d.ts +12 -4
  151. package/lib/types/intent/engine.d.ts.map +1 -1
  152. package/lib/types/intent/engine.js +43 -5
  153. package/lib/types/intent/engine.js.map +1 -1
  154. package/lib/types/intent/host.d.ts +5 -8
  155. package/lib/types/intent/host.d.ts.map +1 -1
  156. package/lib/types/intent/host.js +56 -11
  157. package/lib/types/intent/host.js.map +1 -1
  158. package/lib/types/intent/scope.d.ts +25 -0
  159. package/lib/types/intent/scope.d.ts.map +1 -0
  160. package/lib/types/intent/scope.js +116 -0
  161. package/lib/types/intent/scope.js.map +1 -0
  162. package/lib/types/intent/tools.d.ts +24 -20
  163. package/lib/types/intent/tools.d.ts.map +1 -1
  164. package/lib/types/intent/tools.js +65 -23
  165. package/lib/types/intent/tools.js.map +1 -1
  166. package/lib/types/intent/types.d.ts +11 -4
  167. package/lib/types/intent/types.d.ts.map +1 -1
  168. package/lib/types/knowledge-bases.d.ts +11 -5
  169. package/lib/types/knowledge-bases.d.ts.map +1 -1
  170. package/lib/types/knowledge-bases.js +52 -20
  171. package/lib/types/knowledge-bases.js.map +1 -1
  172. package/lib/types/knowledge-contract.d.ts +32 -0
  173. package/lib/types/knowledge-contract.d.ts.map +1 -0
  174. package/lib/types/knowledge-contract.js +116 -0
  175. package/lib/types/knowledge-contract.js.map +1 -0
  176. package/lib/types/knowledge.d.ts +31 -9
  177. package/lib/types/knowledge.d.ts.map +1 -1
  178. package/lib/types/knowledge.js +137 -60
  179. package/lib/types/knowledge.js.map +1 -1
  180. package/lib/types/layout.d.ts +10 -29
  181. package/lib/types/layout.d.ts.map +1 -1
  182. package/lib/types/layout.js +17 -36
  183. package/lib/types/layout.js.map +1 -1
  184. package/lib/types/materialize-snapshot.d.ts +49 -0
  185. package/lib/types/materialize-snapshot.d.ts.map +1 -0
  186. package/lib/types/materialize-snapshot.js +2 -0
  187. package/lib/types/materialize-snapshot.js.map +1 -0
  188. package/lib/types/migrate.d.ts +11 -0
  189. package/lib/types/migrate.d.ts.map +1 -1
  190. package/lib/types/migrate.js +83 -2
  191. package/lib/types/migrate.js.map +1 -1
  192. package/lib/types/model-text.d.ts +58 -1
  193. package/lib/types/model-text.d.ts.map +1 -1
  194. package/lib/types/model-text.js +85 -30
  195. package/lib/types/model-text.js.map +1 -1
  196. package/lib/types/oplog.d.ts.map +1 -1
  197. package/lib/types/oplog.js +7 -0
  198. package/lib/types/oplog.js.map +1 -1
  199. package/lib/types/organize-contract.d.ts +18 -0
  200. package/lib/types/organize-contract.d.ts.map +1 -0
  201. package/lib/types/organize-contract.js +82 -0
  202. package/lib/types/organize-contract.js.map +1 -0
  203. package/lib/types/pipeline/engine.d.ts +66 -0
  204. package/lib/types/pipeline/engine.d.ts.map +1 -0
  205. package/lib/types/pipeline/engine.js +352 -0
  206. package/lib/types/pipeline/engine.js.map +1 -0
  207. package/lib/types/pipeline/store.d.ts +73 -0
  208. package/lib/types/pipeline/store.d.ts.map +1 -0
  209. package/lib/types/pipeline/store.js +143 -0
  210. package/lib/types/pipeline/store.js.map +1 -0
  211. package/lib/types/pipeline/types.d.ts +102 -0
  212. package/lib/types/pipeline/types.d.ts.map +1 -0
  213. package/lib/types/pipeline/types.js +5 -0
  214. package/lib/types/pipeline/types.js.map +1 -0
  215. package/lib/types/present.d.ts +2 -0
  216. package/lib/types/present.d.ts.map +1 -1
  217. package/lib/types/present.js +9 -4
  218. package/lib/types/present.js.map +1 -1
  219. package/lib/types/preset-ids.d.ts +4 -0
  220. package/lib/types/preset-ids.d.ts.map +1 -0
  221. package/lib/types/preset-ids.js +6 -0
  222. package/lib/types/preset-ids.js.map +1 -0
  223. package/lib/types/query-analysis.d.ts +13 -1
  224. package/lib/types/query-analysis.d.ts.map +1 -1
  225. package/lib/types/query-analysis.js +62 -6
  226. package/lib/types/query-analysis.js.map +1 -1
  227. package/lib/types/recall-rank.d.ts +3 -3
  228. package/lib/types/recall-rank.d.ts.map +1 -1
  229. package/lib/types/recall-rank.js +4 -4
  230. package/lib/types/recall-rank.js.map +1 -1
  231. package/lib/types/retention.d.ts +39 -0
  232. package/lib/types/retention.d.ts.map +1 -0
  233. package/lib/types/retention.js +42 -0
  234. package/lib/types/retention.js.map +1 -0
  235. package/lib/types/retrieval/vector-index.d.ts +32 -0
  236. package/lib/types/retrieval/vector-index.d.ts.map +1 -0
  237. package/lib/types/retrieval/vector-index.js +15 -0
  238. package/lib/types/retrieval/vector-index.js.map +1 -0
  239. package/lib/types/retrieval/visibility.d.ts +6 -0
  240. package/lib/types/retrieval/visibility.d.ts.map +1 -0
  241. package/lib/types/retrieval/visibility.js +11 -0
  242. package/lib/types/retrieval/visibility.js.map +1 -0
  243. package/lib/types/runtime.d.ts +272 -27
  244. package/lib/types/runtime.d.ts.map +1 -1
  245. package/lib/types/runtime.js +2751 -537
  246. package/lib/types/runtime.js.map +1 -1
  247. package/lib/types/settings-schema.d.ts +17 -15
  248. package/lib/types/settings-schema.d.ts.map +1 -1
  249. package/lib/types/settings-schema.js +50 -47
  250. package/lib/types/settings-schema.js.map +1 -1
  251. package/lib/types/settings-volatile.d.ts +4 -4
  252. package/lib/types/settings-volatile.js +4 -4
  253. package/lib/types/source-evidence.d.ts +14 -0
  254. package/lib/types/source-evidence.d.ts.map +1 -0
  255. package/lib/types/source-evidence.js +36 -0
  256. package/lib/types/source-evidence.js.map +1 -0
  257. package/lib/types/store/axis-references.d.ts +5 -0
  258. package/lib/types/store/axis-references.d.ts.map +1 -0
  259. package/lib/types/store/axis-references.js +106 -0
  260. package/lib/types/store/axis-references.js.map +1 -0
  261. package/lib/types/store/derived.d.ts +12 -1
  262. package/lib/types/store/derived.d.ts.map +1 -1
  263. package/lib/types/store/derived.js +71 -12
  264. package/lib/types/store/derived.js.map +1 -1
  265. package/lib/types/store/knowledge-db.d.ts +31 -1
  266. package/lib/types/store/knowledge-db.d.ts.map +1 -1
  267. package/lib/types/store/knowledge-db.js +252 -18
  268. package/lib/types/store/knowledge-db.js.map +1 -1
  269. package/lib/types/store/migrate.d.ts.map +1 -1
  270. package/lib/types/store/migrate.js +17 -6
  271. package/lib/types/store/migrate.js.map +1 -1
  272. package/lib/types/trajectory-types.d.ts +172 -0
  273. package/lib/types/trajectory-types.d.ts.map +1 -0
  274. package/lib/types/trajectory-types.js +36 -0
  275. package/lib/types/trajectory-types.js.map +1 -0
  276. package/lib/types/types.d.ts +59 -27
  277. package/lib/types/types.d.ts.map +1 -1
  278. package/lib/types/types.js +6 -15
  279. package/lib/types/types.js.map +1 -1
  280. package/lib/types/wiki-finalize.d.ts +16 -0
  281. package/lib/types/wiki-finalize.d.ts.map +1 -1
  282. package/lib/types/wiki-finalize.js +26 -0
  283. package/lib/types/wiki-finalize.js.map +1 -1
  284. package/lib/types/wiki-materialize.d.ts +4 -0
  285. package/lib/types/wiki-materialize.d.ts.map +1 -1
  286. package/lib/types/wiki-materialize.js +21 -7
  287. package/lib/types/wiki-materialize.js.map +1 -1
  288. package/lib/types/wiki-trial-types.d.ts +87 -0
  289. package/lib/types/wiki-trial-types.d.ts.map +1 -1
  290. package/lib/types/wiki-trial-types.js +0 -16
  291. package/lib/types/wiki-trial-types.js.map +1 -1
  292. package/lib/types/wiki-trial.d.ts +40 -16
  293. package/lib/types/wiki-trial.d.ts.map +1 -1
  294. package/lib/types/wiki-trial.js +337 -224
  295. package/lib/types/wiki-trial.js.map +1 -1
  296. package/package.json +29 -20
  297. package/python/prepare-models.py +19 -0
  298. package/python/requirements.txt +8 -6
  299. package/scripts/doctor.mjs +13 -19
  300. package/scripts/environment.mjs +29 -0
  301. package/scripts/setup-embedding.sh +15 -5
  302. package/src/agent-behavior-rules.ts +37 -0
  303. package/src/axis-registry.ts +234 -27
  304. package/src/card-organize.ts +69 -75
  305. package/src/client/AgentBehaviorRulesCard.tsx +65 -0
  306. package/src/client/AttributionEventGuide.tsx +41 -39
  307. package/src/client/AxisRegistrySection.tsx +204 -164
  308. package/src/client/CompileDialogs.tsx +44 -29
  309. package/src/client/DeleteDocumentDialog.tsx +36 -5
  310. package/src/client/DirectoryPicker.tsx +0 -10
  311. package/src/client/EnvironmentSetup.tsx +243 -0
  312. package/src/client/ExpansionGraph.tsx +13 -7
  313. package/src/client/ExtractionTasksPage.tsx +578 -0
  314. package/src/client/GuideArchitectureCanvas.tsx +470 -0
  315. package/src/client/ImportFilesDialog.tsx +2 -13
  316. package/src/client/IntentLogic.tsx +2 -2
  317. package/src/client/IntentTab.tsx +118 -47
  318. package/src/client/KnowledgeBaseTab.tsx +277 -197
  319. package/src/client/KnowledgeLayerSection.tsx +24 -6
  320. package/src/client/KnowledgePanel.tsx +58 -93
  321. package/src/client/KnowledgeSettingsDrawer.tsx +90 -0
  322. package/src/client/ListPager.tsx +15 -5
  323. package/src/client/MaterializeTrajectoryView.tsx +124 -0
  324. package/src/client/NodeSettings.tsx +210 -89
  325. package/src/client/NormalizeTrajectoryView.tsx +136 -0
  326. package/src/client/PipelineNotice.tsx +26 -0
  327. package/src/client/PreviewSections.tsx +118 -51
  328. package/src/client/RecallPanel.tsx +89 -85
  329. package/src/client/TabGuide.tsx +159 -184
  330. package/src/client/TrialReportView.tsx +391 -214
  331. package/src/client/TypeDefinitionDrawer.tsx +150 -23
  332. package/src/client/WikiCardPreview.tsx +62 -16
  333. package/src/client/WikiFlowPanel.tsx +4 -4
  334. package/src/client/arch/NodeLogicPanel.tsx +3 -4
  335. package/src/client/arch/model.ts +6 -9
  336. package/src/client/architecture.tsx +23 -33
  337. package/src/client/attribution/AttributionGraph.tsx +10 -6
  338. package/src/client/attribution/AttributionTab.tsx +136 -84
  339. package/src/client/attribution/CaseView.tsx +3 -1
  340. package/src/client/attribution/EventView.tsx +108 -0
  341. package/src/client/attribution/RunView.tsx +2 -2
  342. package/src/client/attribution/StageChrome.tsx +34 -3
  343. package/src/client/attribution/ViewSwitch.tsx +20 -5
  344. package/src/client/attribution/graph-options.ts +47 -39
  345. package/src/client/attribution/model.ts +17 -10
  346. package/src/client/config-scope.ts +3 -3
  347. package/src/client/graph/palette.ts +165 -0
  348. package/src/client/index.ts +49 -42
  349. package/src/client/pages.css +459 -135
  350. package/src/client/pages.tsx +37 -9
  351. package/src/client/problem-domains.ts +1 -1
  352. package/src/client/session-remote.ts +9 -0
  353. package/src/client/styles.css +205 -62
  354. package/src/client/wiki-trial.ts +44 -3
  355. package/src/compiler/embedding-identity.ts +21 -0
  356. package/src/compiler/snapshot.ts +17 -0
  357. package/src/config-schema.ts +8 -3
  358. package/src/convert/host.ts +56 -21
  359. package/src/convert/ingest.ts +74 -10
  360. package/src/derive-contract.ts +14 -0
  361. package/src/diagnosis/cards.ts +13 -8
  362. package/src/diagnosis/run.ts +27 -17
  363. package/src/diagnosis/schema.ts +2 -2
  364. package/src/diagnosis/seed-source.ts +5 -4
  365. package/src/diagnosis/seed.ts +6 -8
  366. package/src/diagnosis/store.ts +138 -69
  367. package/src/diagnosis/types.ts +34 -15
  368. package/src/environment/dsh-python.ts +156 -0
  369. package/src/environment/install.ts +244 -0
  370. package/src/environment/manifest.ts +28 -0
  371. package/src/environment/model-catalog.ts +147 -0
  372. package/src/environment/process.ts +54 -0
  373. package/src/environment/selection.ts +29 -0
  374. package/src/environment/service.ts +348 -0
  375. package/src/environment/types.ts +45 -0
  376. package/src/events.ts +108 -0
  377. package/src/extract-contract.ts +42 -0
  378. package/src/extract-model.ts +10 -1
  379. package/src/extract-table-contract.ts +26 -0
  380. package/src/extract-table.ts +132 -0
  381. package/src/extraction-runs.ts +70 -11
  382. package/src/fs-atomic.ts +19 -2
  383. package/src/images.ts +203 -0
  384. package/src/index.ts +553 -205
  385. package/src/intent/README.md +8 -6
  386. package/src/intent/engine.ts +44 -6
  387. package/src/intent/host.ts +59 -18
  388. package/src/intent/scope.ts +125 -0
  389. package/src/intent/tools.ts +70 -28
  390. package/src/intent/types.ts +11 -4
  391. package/src/knowledge-bases.ts +56 -20
  392. package/src/knowledge-contract.ts +114 -0
  393. package/src/knowledge.ts +138 -69
  394. package/src/layout.ts +17 -37
  395. package/src/materialize-snapshot.ts +46 -0
  396. package/src/migrate.ts +75 -2
  397. package/src/model-text.ts +109 -4
  398. package/src/oplog.ts +7 -0
  399. package/src/organize-contract.ts +83 -0
  400. package/src/pipeline/engine.ts +323 -0
  401. package/src/pipeline/store.ts +147 -0
  402. package/src/pipeline/types.ts +93 -0
  403. package/src/present.ts +10 -4
  404. package/src/preset-ids.ts +6 -0
  405. package/src/python/embedding_worker.py +66 -2
  406. package/src/query-analysis.ts +68 -8
  407. package/src/recall-rank.ts +5 -5
  408. package/src/retention.ts +76 -0
  409. package/src/retrieval/vector-index.ts +45 -0
  410. package/src/retrieval/visibility.ts +14 -0
  411. package/src/runtime.ts +2708 -567
  412. package/src/settings-schema.ts +11 -8
  413. package/src/settings-volatile.ts +4 -4
  414. package/src/source-evidence.ts +37 -0
  415. package/src/store/axis-references.ts +96 -0
  416. package/src/store/derived.ts +70 -12
  417. package/src/store/knowledge-db.ts +248 -17
  418. package/src/store/migrate.ts +16 -6
  419. package/src/trajectory-types.ts +142 -0
  420. package/src/types.ts +61 -35
  421. package/src/wiki-finalize.ts +28 -0
  422. package/src/wiki-materialize.ts +25 -6
  423. package/src/wiki-trial-types.ts +83 -1
  424. package/src/wiki-trial.ts +357 -185
  425. package/lib/types/intent/preset-tools.d.ts +0 -37
  426. package/lib/types/intent/preset-tools.d.ts.map +0 -1
  427. package/lib/types/intent/preset-tools.js +0 -45
  428. package/lib/types/intent/preset-tools.js.map +0 -1
  429. package/preset/tita-data-agent/agent.cordis.yml +0 -394
  430. package/preset/tita-data-agent/preset.yml +0 -3
  431. package/scripts/install-agent-preset.mjs +0 -92
  432. package/scripts/sync-agent-preset.mjs +0 -188
  433. package/src/client/AgentPresetCard.tsx +0 -247
  434. package/src/client/agent-preset.ts +0 -121
  435. package/src/client/convert/ConvertPanel.tsx +0 -583
  436. package/src/client/convert/styles.css +0 -138
  437. package/src/client/convert/styles.ts +0 -49
  438. package/src/intent/preset-tools.ts +0 -48
@@ -5,12 +5,12 @@ import {
5
5
  import type { ReactNode } from 'react'
6
6
  import { Badge, Button, Input, cn } from '@tita-agent/ui/components'
7
7
  import {
8
- EDGE_LEGEND, type GraphLayout,
8
+ EDGE_KIND_LABEL, EDGE_LEGEND, type GraphLayout,
9
9
  } from './graph-options.ts'
10
10
  import {
11
11
  CHECK_COST_BANDS, FAILURE_REASON_STYLE, FILTERABLE_KINDS, LANES, NODE_KIND_LABEL,
12
12
  PROBLEM_CLASSES, PROBLEM_CLASS_LABEL,
13
- type AttributionNode, type AttributionNodeKind, type AttributionStats, type FailureReason,
13
+ type AttributionEdge, type AttributionNode, type AttributionNodeKind, type AttributionStats, type FailureReason,
14
14
  type LaneId, type ProblemClassId,
15
15
  } from './model.ts'
16
16
 
@@ -512,7 +512,16 @@ function Stat({ label, value, tone }: { label: string; value: number; tone?: 'wa
512
512
 
513
513
  /* ─────────────────────────────────────────────── 画布右侧:选中节点详情 ── */
514
514
 
515
- export function NodeDetailCard({ node, onClear }: { node: AttributionNode; onClear?: () => void }): ReactNode {
515
+ export function NodeDetailCard({ node, nodes = [], edges = [], onSelect, onClear }: {
516
+ node: AttributionNode
517
+ nodes?: readonly AttributionNode[]
518
+ edges?: readonly AttributionEdge[]
519
+ onSelect?: (id: string) => void
520
+ onClear?: () => void
521
+ }): ReactNode {
522
+ const byId = new Map(nodes.map(item => [item.id, item]))
523
+ const related = edges.filter(edge => edge.source === node.id || edge.target === node.id)
524
+
516
525
  return <ChromePanel className="flex flex-col gap-1.5 p-2">
517
526
  <div className="flex items-start justify-between gap-2">
518
527
  <span className="text-[11.5px] font-semibold leading-snug">{node.title}</span>
@@ -534,6 +543,28 @@ export function NodeDetailCard({ node, onClear }: { node: AttributionNode; onCle
534
543
  </p>}
535
544
  {node.discriminator && <p className="text-[10px] leading-snug text-tita-ink-muted">判据:{node.discriminator}</p>}
536
545
  {node.why && <p className="text-[10px] leading-snug text-tita-ink-muted">为什么算数:{node.why}</p>}
546
+ {related.length > 0 && <section className="flex flex-col gap-0.5 border-t border-tita-line pt-1.5" aria-label="关联关系">
547
+ <p className="text-[9.5px] font-semibold text-tita-ink-muted">关联关系 · {related.length}</p>
548
+ {related.slice(0, 5).map(edge => {
549
+ const outgoing = edge.source === node.id
550
+ const otherId = outgoing ? edge.target : edge.source
551
+ const other = byId.get(otherId)
552
+ const relation = EDGE_KIND_LABEL[edge.kind] ?? edge.kind
553
+ return <Button
554
+ key={edge.id}
555
+ size="sm"
556
+ variant="ghost"
557
+ className="h-auto min-h-0 w-full justify-start gap-1 rounded px-1 py-1 text-left text-[9.5px] leading-snug"
558
+ disabled={!other || !onSelect}
559
+ title={other?.title ?? otherId}
560
+ onClick={() => { if (other) onSelect?.(other.id) }}
561
+ >
562
+ <span className="shrink-0 text-tita-ink-faint">{outgoing ? `${relation} →` : `← ${relation}`}</span>
563
+ <span className="min-w-0 truncate text-tita-ink">{other?.title ?? otherId}</span>
564
+ </Button>
565
+ })}
566
+ {related.length > 5 && <p className="px-1 text-[9px] text-tita-ink-faint">另有 {related.length - 5} 条关系,可在图中查看</p>}
567
+ </section>}
537
568
  {onClear && <button
538
569
  type="button"
539
570
  onClick={onClear}
@@ -20,6 +20,20 @@ export interface ViewSwitchItem<T extends string> {
20
20
  * 而分段的轨道 + 会滑动的白色胶囊把「同一组、选一个」直接画了出来 ——
21
21
  * 位置本身就是状态,不需要读颜色。
22
22
  *
23
+ * ## 语义是 `group` + `aria-pressed`,不是 tablist
24
+ *
25
+ * 它原来是 `role="tablist"` / `role="tab"` / `aria-selected` / roving `tabIndex`。
26
+ * 那是**冒充**:这一组只换内容,被换掉的那一块渲染在树的别处(调用方自己的
27
+ * `stage`/`subView` 分支),没有 `tabpanel`、没有 `aria-controls`、也没有 id。
28
+ * 读屏会念出「选项卡,4 个中的第 2 个」,然后按 tab 语义去找一个不存在的面板 ——
29
+ * 那不是「少写了一层」,那是把一句假话说给不会看到的用户听。
30
+ *
31
+ * 要把它改成真的 tab 就得让被换的内容成为这一组的 `tabpanel` 并互相对上 id:那要求
32
+ * 调用方把舞台搬进这个组件,或者把 id 一路传出去。**这一组承载的是「同一个视图的几种
33
+ * 画法」,不是「几个并列的内容面板」** —— 所以诚实的做法是退掉 tab 语义:一组
34
+ * 互斥按钮(`group` + `aria-pressed`),键盘用方向键在同一组里走。这一层没有丢
35
+ * 可达性,丢掉的是一句假的角色声明。
36
+ *
23
37
  * 滑块的位移用纯 CSS 算:轨道是 `auto-cols-fr` 的等宽栅格,滑块宽度取
24
38
  * `(100% - 内边距) / 页数`,位移取 `index × 100%`(百分比是相对滑块自身宽度)。
25
39
  * 这样**不需要测量 DOM**,也就不存在「测量时机不对导致滑块错位」这一类 bug ——
@@ -54,20 +68,20 @@ export function ViewSwitch<T extends string>({ items, value, onChange, ariaLabel
54
68
  if (!target) return
55
69
  onChange(target.id)
56
70
  // 焦点必须跟着走,否则键盘用户的下一次左右键会从旧位置继续算。
57
- const nodes = event.currentTarget.querySelectorAll<HTMLElement>('[role="tab"]')
71
+ const nodes = event.currentTarget.querySelectorAll<HTMLElement>('button')
58
72
  nodes[next]?.focus()
59
73
  }
60
74
 
61
75
  return <div className={cn('flex min-w-0 flex-col gap-1', className)}>
62
76
  <div
63
- role="tablist"
77
+ role="group"
64
78
  aria-label={ariaLabel}
65
79
  onKeyDown={onKeyDown}
66
80
  // 轨道刻意与面板自己的标签条(`.tita-tabsList`)用同一组颜色与圆角:
67
81
  // 同屏出现两个分段控件时,它们要么明显是同一套,要么明显是两套 —— 差一点点最难看。
68
82
  className="relative inline-grid grid-flow-col auto-cols-fr self-start rounded-[9px] border border-tita-line bg-tita-surface-muted p-[3px]"
69
83
  >
70
- {/* 滑块:装饰性元素,语义由 `aria-selected` 承载。 */}
84
+ {/* 滑块:装饰性元素,语义由 `aria-pressed` 承载。 */}
71
85
  <span
72
86
  aria-hidden="true"
73
87
  className="pointer-events-none absolute bottom-[3px] left-[3px] top-[3px] rounded-[7px] bg-tita-surface shadow-[0_1px_3px_rgb(15_23_42_/_0.16),inset_0_0_0_1px_var(--tita-primary-shadow)] transition-transform duration-200 ease-[cubic-bezier(0.22,0.61,0.36,1)]"
@@ -79,8 +93,9 @@ export function ViewSwitch<T extends string>({ items, value, onChange, ariaLabel
79
93
  return <button
80
94
  key={item.id}
81
95
  type="button"
82
- role="tab"
83
- aria-selected={on}
96
+ aria-pressed={on}
97
+ // 整个控件是一个 tab 停靠点,组内用方向键走 —— 与 shadcn 的 Tabs 同一条纪律,
98
+ // 只是角色换成了诚实的 `group`。
84
99
  tabIndex={on ? 0 : -1}
85
100
  data-state={on ? 'active' : 'inactive'}
86
101
  onClick={() => onChange(item.id)}
@@ -5,6 +5,11 @@ import {
5
5
  visibleEdges, visibleNodes,
6
6
  type AttributionEdge, type AttributionGraphData, type AttributionNode, type AttributionEdgeKind,
7
7
  } from './model.ts'
8
+ import {
9
+ BADGE_AUTO_INK, BADGE_GAP_STROKE, BADGE_INK, BADGE_MANUAL_INK, BADGE_PLATE, BADGE_PLATE_STROKE,
10
+ BADGE_PROBLEM_INK, BADGE_PROBLEM_STROKE, EDGE_COUNT_INK, EDGE_STROKE, EDGE_ZOMBIE_INK,
11
+ GAP_STROKE, LABEL_PLATE, SELECTION_RING, ZOMBIE_STROKE,
12
+ } from '../graph/palette.ts'
8
13
 
9
14
  /**
10
15
  * 我的模型 → G6 v5 的数据与配置。
@@ -47,19 +52,19 @@ const FONT = '"PingFang SC","Hiragino Sans GB","Microsoft YaHei",system-ui,sans-
47
52
 
48
53
  /** 十种边各自的外观。层内边实线、跨层边点线,`refutes` 一律红色虚线(一等公民)。 */
49
54
  const EDGE_STYLE: Record<AttributionEdgeKind, { stroke: string; lineWidth: number; lineDash?: number[] }> = {
50
- may_be_caused_by: { stroke: '#93b4f8', lineWidth: 1.6 },
51
- verified_by: { stroke: '#6b54cf', lineWidth: 1.3 },
52
- categorized_as: { stroke: '#c9b8ff', lineWidth: 1.2, lineDash: [5, 4] },
55
+ may_be_caused_by: { stroke: EDGE_STROKE.may_be_caused_by, lineWidth: 1.6 },
56
+ verified_by: { stroke: EDGE_STROKE.verified_by, lineWidth: 1.3 },
57
+ categorized_as: { stroke: EDGE_STROKE.categorized_as, lineWidth: 1.2, lineDash: [5, 4] },
53
58
  // `queries`(检查点 → 资产)与 `indexed_from`(资产 → 假设)是两条边,两端与回答的
54
59
  // 问题都不同,所以外观也要能分开:同色同线型的话,图上分不清「这条假设落在哪张表上」
55
60
  // 与「这条检查要去查哪张表」。
56
- queries: { stroke: '#9ec2ff', lineWidth: 1.3, lineDash: [1, 3] },
57
- produces: { stroke: '#b96d14', lineWidth: 1.2, lineDash: [2, 3] },
58
- supports: { stroke: '#12875f', lineWidth: 1.4 },
59
- refutes: { stroke: '#b42318', lineWidth: 1.6, lineDash: [5, 4] },
60
- confirmed_as: { stroke: '#0f766e', lineWidth: 1.6 },
61
- instance_of: { stroke: '#b96d14', lineWidth: 1.2, lineDash: [2, 3] },
62
- indexed_from: { stroke: '#9ec2ff', lineWidth: 1.2, lineDash: [2, 3] },
61
+ queries: { stroke: EDGE_STROKE.queries, lineWidth: 1.3, lineDash: [1, 3] },
62
+ produces: { stroke: EDGE_STROKE.produces, lineWidth: 1.2, lineDash: [2, 3] },
63
+ supports: { stroke: EDGE_STROKE.supports, lineWidth: 1.4 },
64
+ refutes: { stroke: EDGE_STROKE.refutes, lineWidth: 1.6, lineDash: [5, 4] },
65
+ confirmed_as: { stroke: EDGE_STROKE.confirmed_as, lineWidth: 1.6 },
66
+ instance_of: { stroke: EDGE_STROKE.instance_of, lineWidth: 1.2, lineDash: [2, 3] },
67
+ indexed_from: { stroke: EDGE_STROKE.indexed_from, lineWidth: 1.2, lineDash: [2, 3] },
63
68
  }
64
69
 
65
70
  /** 边的中文读法。**十种必须全有** —— 图例是通过遍历这个表生成的,漏一种就是漏一段语义。 */
@@ -90,15 +95,17 @@ export const EDGE_LEGEND: Array<{ kind: AttributionEdgeKind; label: string; stro
90
95
  ...EDGE_STYLE[kind],
91
96
  }))
92
97
 
93
- const ZOMBIE_STYLE = { stroke: '#9aa4b2', lineWidth: 1.2, lineDash: [5, 4] }
94
- const GAP_STROKE = '#b42318'
98
+ // 画布侧的颜色全部来自 `graph/palette.ts`:canvas 读不到 CSS 变量(那条理由写在那个
99
+ // 模块头上),所以值只能以字面量给,但**只给一份**。三处各写一份的代价是同一个
100
+ // 「中性文字」在三处慢慢漂成三个灰度,而没有任何一处能看出它们本该相同。
101
+ const ZOMBIE_STYLE = { stroke: ZOMBIE_STROKE, lineWidth: 1.2, lineDash: [5, 4] }
95
102
 
96
103
  const BADGE_BASE = {
97
- fill: '#748091',
104
+ fill: BADGE_INK,
98
105
  fontSize: 9,
99
106
  fontFamily: FONT,
100
- backgroundFill: '#ffffff',
101
- backgroundStroke: '#e5e9f0',
107
+ backgroundFill: BADGE_PLATE,
108
+ backgroundStroke: BADGE_PLATE_STROKE,
102
109
  backgroundLineWidth: 1,
103
110
  backgroundRadius: 6,
104
111
  // 动线视角里徽标画在**胶囊内部**(见 `laneNodeStyleFor`),所以它越矮越好:
@@ -162,8 +169,8 @@ export function nodeStyleFor(
162
169
  lineDash: isGap ? [4, 3] : undefined,
163
170
  zIndex: node.layer === 'instance' ? 0 : 1,
164
171
  // 圆里放 id(直径由复用次数决定,中文标题塞不进);胶囊放标题。
165
- // 案例例外:它的标题来自案例卡片、不含 id,而案例要靠 id 才能在复盘里被指认 ——
166
- // 所以由画布把 id 拼回去,标题本身保持单一份来源。
172
+ // Case 是排查 SourceRaw 的只读投影,不是 WikiCard。视图用症状标题;画布补上稳定的
173
+ // Case id,方便在复盘里指认这次排查。
167
174
  labelText: shape === 'circle' ? node.id : node.kind === 'case' ? `${node.id} ${node.title}` : node.title,
168
175
  labelPlacement: 'center',
169
176
  labelFill: palette.text,
@@ -179,12 +186,12 @@ export function nodeStyleFor(
179
186
  if (shape === 'rect') style.radius = 8
180
187
 
181
188
  const badges: Array<Record<string, unknown>> = []
182
- const gapBadge = { ...BADGE_BASE, text: '空区 · 无检查', placement: 'top', offsetY: -10, fill: GAP_STROKE, backgroundStroke: '#f0b7ad' }
189
+ const gapBadge = { ...BADGE_BASE, text: '空区 · 无检查', placement: 'top', offsetY: -10, fill: GAP_STROKE, backgroundStroke: BADGE_GAP_STROKE }
183
190
  if (node.kind === 'symptom') {
184
191
  // 问题侧的层次必须能在**画布上**读到,而不是只能靠筛选器猜。
185
192
  // 用文字徽标而不是颜色:颜色通道已经被失败模式占满(见 model.ts 的 PROBLEM_CLASS_ORDER)。
186
193
  const problem = problemBadgeOf(node)
187
- if (problem) badges.push({ ...BADGE_BASE, text: problem, placement: 'bottom', offsetY: 12, fill: '#96580f', backgroundStroke: '#f2ddb8' })
194
+ if (problem) badges.push({ ...BADGE_BASE, text: problem, placement: 'bottom', offsetY: 12, fill: BADGE_PROBLEM_INK, backgroundStroke: BADGE_PROBLEM_STROKE })
188
195
  } else if (node.kind === 'hypothesis') {
189
196
  badges.push({ ...BADGE_BASE, text: node.title, placement: 'bottom', offsetY: 12, fill: palette.text, backgroundStroke: palette.stroke })
190
197
  // 空区徽标必须和「复用 N」**互斥地**占用顶部位置,而不是写成 else-if ——
@@ -192,7 +199,7 @@ export function nodeStyleFor(
192
199
  // 而空区恰恰总是假设节点。
193
200
  badges.push(isGap ? gapBadge : { ...BADGE_BASE, text: `复用 ${node.reuseCount ?? 0}`, placement: 'top', offsetY: -10 })
194
201
  } else if (node.kind === 'check_point') {
195
- badges.push({ ...BADGE_BASE, text: `${node.costMinutes ?? '?'} min · ${node.automation === 'auto' ? '自动' : '人工'}`, placement: 'bottom', offsetY: 10, fill: node.automation === 'auto' ? '#12875f' : '#b96d14' })
202
+ badges.push({ ...BADGE_BASE, text: `${node.costMinutes ?? '?'} min · ${node.automation === 'auto' ? '自动' : '人工'}`, placement: 'bottom', offsetY: 10, fill: node.automation === 'auto' ? BADGE_AUTO_INK : BADGE_MANUAL_INK })
196
203
  } else if (isGap) {
197
204
  badges.push(gapBadge)
198
205
  }
@@ -269,18 +276,18 @@ export function laneNodeStyleFor(node: AttributionNode, gapIds: ReadonlySet<stri
269
276
  // 都堆上去的话,44px 高的胶囊会被三个徽标切成碎片。
270
277
  if (node.kind === 'symptom') {
271
278
  const problem = problemBadgeOf(node)
272
- if (problem) badges.push({ ...BADGE_BASE, text: problem, placement: 'bottom', offsetY: BADGE_GAP, fill: '#96580f', backgroundStroke: '#f2ddb8' })
279
+ if (problem) badges.push({ ...BADGE_BASE, text: problem, placement: 'bottom', offsetY: BADGE_GAP, fill: BADGE_PROBLEM_INK, backgroundStroke: BADGE_PROBLEM_STROKE })
273
280
  } else if (node.kind === 'hypothesis') {
274
281
  badges.push(isGap
275
- ? { ...BADGE_BASE, text: '空区 · 无检查点', placement: 'bottom', offsetY: BADGE_GAP, fill: GAP_STROKE, backgroundStroke: '#f0b7ad' }
282
+ ? { ...BADGE_BASE, text: '空区 · 无检查点', placement: 'bottom', offsetY: BADGE_GAP, fill: GAP_STROKE, backgroundStroke: BADGE_GAP_STROKE }
276
283
  : { ...BADGE_BASE, text: `复用 ${node.reuseCount ?? 0}`, placement: 'bottom', offsetY: BADGE_GAP, fill: palette.text, backgroundStroke: palette.stroke })
277
284
  } else if (node.kind === 'check_point') {
278
- badges.push({ ...BADGE_BASE, text: `${node.costMinutes ?? '?'} min · ${node.automation === 'auto' ? '自动' : '人工'}`, placement: 'bottom', offsetY: BADGE_GAP, fill: node.automation === 'auto' ? '#12875f' : '#b96d14' })
285
+ badges.push({ ...BADGE_BASE, text: `${node.costMinutes ?? '?'} min · ${node.automation === 'auto' ? '自动' : '人工'}`, placement: 'bottom', offsetY: BADGE_GAP, fill: node.automation === 'auto' ? BADGE_AUTO_INK : BADGE_MANUAL_INK })
279
286
  } else if (node.kind === 'evidence') {
280
287
  const verdict = node.verdict === 'refutes' ? '否定' : node.verdict === 'supports' ? '支持' : '给不出结论'
281
- badges.push({ ...BADGE_BASE, text: verdict, placement: 'bottom', offsetY: BADGE_GAP, fill: node.verdict === 'refutes' ? GAP_STROKE : '#12875f' })
288
+ badges.push({ ...BADGE_BASE, text: verdict, placement: 'bottom', offsetY: BADGE_GAP, fill: node.verdict === 'refutes' ? GAP_STROKE : BADGE_AUTO_INK })
282
289
  } else if (isGap) {
283
- badges.push({ ...BADGE_BASE, text: '空区 · 无检查点', placement: 'bottom', offsetY: BADGE_GAP, fill: GAP_STROKE, backgroundStroke: '#f0b7ad' })
290
+ badges.push({ ...BADGE_BASE, text: '空区 · 无检查点', placement: 'bottom', offsetY: BADGE_GAP, fill: GAP_STROKE, backgroundStroke: BADGE_GAP_STROKE })
284
291
  }
285
292
  if (badges.length > 0) style.badges = badges
286
293
  if (options.dimmed) {
@@ -305,7 +312,8 @@ export function edgeStyleFor(edge: AttributionEdge, options: { labels?: boolean
305
312
  const base = zombie ? ZOMBIE_STYLE : EDGE_STYLE[edge.kind]
306
313
  const style: Record<string, unknown> = {
307
314
  ...base,
308
- endArrow: edge.kind === 'instance_of' || edge.kind === 'indexed_from',
315
+ // 归因图的边都是有向关系。全量关系视图必须保留箭头,否则只能靠节点距离猜方向。
316
+ endArrow: true,
309
317
  endArrowType: 'triangle',
310
318
  endArrowSize: 6,
311
319
  zIndex: 0,
@@ -313,7 +321,7 @@ export function edgeStyleFor(edge: AttributionEdge, options: { labels?: boolean
313
321
  labelAutoRotate: false,
314
322
  labelFontFamily: FONT,
315
323
  labelBackground: true,
316
- labelBackgroundFill: '#f6f8fb',
324
+ labelBackgroundFill: LABEL_PLATE,
317
325
  labelBackgroundRadius: 4,
318
326
  labelPadding: [2, 4, 2, 4],
319
327
  }
@@ -323,11 +331,11 @@ export function edgeStyleFor(edge: AttributionEdge, options: { labels?: boolean
323
331
  if (zombie) {
324
332
  style.labelText = `僵尸边 ${edge.staleDays} 天未走`
325
333
  style.labelFontSize = 9
326
- style.labelFill = '#9aa4b2'
334
+ style.labelFill = EDGE_ZOMBIE_INK
327
335
  } else if (edge.count !== undefined) {
328
336
  style.labelText = `${edge.count} 例`
329
337
  style.labelFontSize = 9
330
- style.labelFill = '#b96d14'
338
+ style.labelFill = EDGE_COUNT_INK
331
339
  }
332
340
  return style
333
341
  }
@@ -688,16 +696,16 @@ const ROW_NODE_GAP = 8
688
696
  const EMPTY_ROW_HEIGHT = 24
689
697
 
690
698
  /**
691
- * 布局种类。**只有两种,而且默认是动线。**
699
+ * 布局种类。**只有两种,默认显示关系全景。**
692
700
  *
693
- * `line`(动线)是默认读法:五段泳道,位置完全由段位与段内排序决定(§7.7)。
694
- * 它回答的是值班同学打开这一栏真正要问的那句 ——「下一步查什么、这条链断在哪」。
695
- * `force`(关系)是自由读法:浮动节点、可拖拽,关系靠聚簇与距离表达。
696
- * 它回答「这张图长什么样、哪块密哪里空」,那是维护者的问题。
701
+ * `force`(关系)是默认读法:浮动节点、可拖拽,关系靠聚簇、方向箭头与距离表达。
702
+ * 它回答「有哪些现象、原因、检查点,它们如何连接」。
703
+ * `line`(动线)是五段泳道,位置完全由段位与段内排序决定(§7.7)。
704
+ * 它回答值班同学「下一步查什么、这条链断在哪」。
697
705
  *
698
706
  * **v1.4 撤销了「分层」(`layered`)。** 原来留它是因为「方向本身是语义」——
699
- * 而动线就是这件事的语义版:分层只按入度分列,动线按这五个阶段分列,且每段带段头
700
- * 与计数。两个都能画方向时,留那个说得清「这一段是什么」的(§7.2)。
707
+ * 两种布局都能画方向;分层只按入度分列,而动线按这五个阶段分列,且每段带段头与计数。
708
+ * 因此保留更能表达排查阶段的动线作为按步骤阅读方式(§7.2)。
701
709
  */
702
710
  export type GraphLayout = 'line' | 'force'
703
711
 
@@ -875,8 +883,8 @@ export function buildGraphOptions(
875
883
  layout: layoutOf(layout, rankdir),
876
884
  node: {
877
885
  state: {
878
- selected: { lineWidth: 3, stroke: '#2563eb' },
879
- active: { lineWidth: 2.6, stroke: '#2563eb' },
886
+ selected: { lineWidth: 3, stroke: SELECTION_RING },
887
+ active: { lineWidth: 2.6, stroke: SELECTION_RING },
880
888
  // 「其余节点透明度降到 0.35」(§7.4 第 9 条)。状态的样式值走 `var()` 共享
881
889
  // 令牌,`DIM_OPACITY` 是它的数值孪生 —— 节点数据在纯函数里算出来时也要用同一
882
890
  // 个数(node:test 里读不到 CSS),两处不同步就会一半亮一半暗。
@@ -888,7 +896,7 @@ export function buildGraphOptions(
888
896
  type: line ? 'polyline' : 'quadratic',
889
897
  style: line ? { radius: 6 } : { curveOffset: 22 },
890
898
  state: {
891
- selected: { lineWidth: 2.4, stroke: '#2563eb' },
899
+ selected: { lineWidth: 2.4, stroke: SELECTION_RING },
892
900
  dim: { strokeOpacity: DIM_OPACITY, labelOpacity: DIM_OPACITY },
893
901
  },
894
902
  },
@@ -8,11 +8,15 @@ import type {
8
8
  AttributionEdge, AttributionEdgeKind, AttributionGraphData, AttributionNode, AttributionNodeKind,
9
9
  AttributionStats, FailureReason, NodeLayer,
10
10
  } from '../../diagnosis/types.js'
11
+ import {
12
+ FAILURE_REASON_FILL, FAILURE_REASON_STROKE, FAILURE_REASON_TEXT,
13
+ NEUTRAL_NODE, NODE_CHECK_POINT, NODE_REFERENCE_FILL, NODE_REFERENCE_STROKE, NODE_REFERENCE_TEXT, NODE_SYMPTOM,
14
+ } from '../graph/palette.ts'
11
15
 
12
16
  export { ZOMBIE_EDGE_DAYS, PROBLEM_CLASSES, PROBLEM_CLASS_LABEL, problemClassIds, problemSubclassOf }
13
17
  export type {
14
18
  AssetType,
15
- AttributionEdge, AttributionGraphData, AttributionNode, AttributionNodeKind,
19
+ AttributionEdge, AttributionEvent, AttributionGraphData, AttributionNode, AttributionNodeKind,
16
20
  AttributionEdgeKind, AttributionStats, FailureReason, NodeLayer,
17
21
  AttributionCase, CaseSection, CasePathStep,
18
22
  } from '../../diagnosis/types.js'
@@ -35,13 +39,16 @@ export const LAYER_TONES: Record<NodeLayer, 'blue' | 'violet' | 'amber'> = {
35
39
  /**
36
40
  * 失败原因 → 颜色。分类在图谱视图里是**着色**而不是分区,所以它只影响一眼扫过的
37
41
  * 分组感,不影响节点位置 —— 位置由布局按边的方向决定。
42
+ *
43
+ * 五个色值来自 `graph/palette.ts`(画布色只有那一份)。这里只是把它们按
44
+ * `FailureReason` 装配起来,标签留在本地 —— 标签是文案,不是调色板。
38
45
  */
39
46
  export const FAILURE_REASON_STYLE: Record<FailureReason, { label: string; fill: string; stroke: string; text: string }> = {
40
- 'upstream-missing': { label: '上游未产出', fill: '#eef4ff', stroke: '#2563eb', text: '#1d4ed8' },
41
- 'spec-change': { label: '口径变更', fill: '#f3f0ff', stroke: '#6b54cf', text: '#5b45be' },
42
- 'data-processing': { label: '数据处理', fill: '#eafaf2', stroke: '#12875f', text: '#0f6b4d' },
43
- consumption: { label: '消费与展示', fill: '#fff7ea', stroke: '#b96d14', text: '#96580f' },
44
- permission: { label: '权限与过滤', fill: '#fdecea', stroke: '#b42318', text: '#98200f' },
47
+ 'upstream-missing': { label: '上游未产出', fill: FAILURE_REASON_FILL['upstream-missing'], stroke: FAILURE_REASON_STROKE['upstream-missing'], text: FAILURE_REASON_TEXT['upstream-missing'] },
48
+ 'spec-change': { label: '口径变更', fill: FAILURE_REASON_FILL['spec-change'], stroke: FAILURE_REASON_STROKE['spec-change'], text: FAILURE_REASON_TEXT['spec-change'] },
49
+ 'data-processing': { label: '数据处理', fill: FAILURE_REASON_FILL['data-processing'], stroke: FAILURE_REASON_STROKE['data-processing'], text: FAILURE_REASON_TEXT['data-processing'] },
50
+ consumption: { label: '消费与展示', fill: FAILURE_REASON_FILL.consumption, stroke: FAILURE_REASON_STROKE.consumption, text: FAILURE_REASON_TEXT.consumption },
51
+ permission: { label: '权限与过滤', fill: FAILURE_REASON_FILL.permission, stroke: FAILURE_REASON_STROKE.permission, text: FAILURE_REASON_TEXT.permission },
45
52
  }
46
53
 
47
54
  /**
@@ -76,7 +83,7 @@ export function symptomCountByProblemClass(nodes: AttributionNode[]): Record<Pro
76
83
  }
77
84
 
78
85
  /** 无失败模式的节点(现象、资产、检查)用中性色。 */
79
- export const NEUTRAL_STYLE = { fill: '#ffffff', stroke: '#d6dce6', text: '#748091' }
86
+ export const NEUTRAL_STYLE = { fill: NEUTRAL_NODE.fill, stroke: NEUTRAL_NODE.stroke, text: NEUTRAL_NODE.text }
80
87
 
81
88
  export const NODE_KIND_LABEL: Record<AttributionNodeKind, string> = {
82
89
  symptom: '现象',
@@ -564,9 +571,9 @@ export function nodeShapeOf(node: AttributionNode): 'circle' | 'rect' {
564
571
  /** 节点的取色:假设跟着失败模式走,其余走层色。 */
565
572
  export function nodeStyleOf(node: AttributionNode): { fill: string; stroke: string; text: string } {
566
573
  if (node.failureReason) return FAILURE_REASON_STYLE[node.failureReason]
567
- if (node.layer === 'reference') return { fill: '#eef4ff', stroke: '#9ec2ff', text: '#1d4ed8' }
568
- if (node.kind === 'symptom') return { fill: '#fff7ea', stroke: '#b96d14', text: '#96580f' }
569
- if (node.kind === 'check_point') return { fill: '#f5f1ff', stroke: '#c9b8ff', text: '#5b45be' }
574
+ if (node.layer === 'reference') return { fill: NODE_REFERENCE_FILL, stroke: NODE_REFERENCE_STROKE, text: NODE_REFERENCE_TEXT }
575
+ if (node.kind === 'symptom') return { fill: NODE_SYMPTOM.fill, stroke: NODE_SYMPTOM.stroke, text: NODE_SYMPTOM.text }
576
+ if (node.kind === 'check_point') return { fill: NODE_CHECK_POINT.fill, stroke: NODE_CHECK_POINT.stroke, text: NODE_CHECK_POINT.text }
570
577
  return NEUTRAL_STYLE
571
578
  }
572
579
 
@@ -6,8 +6,8 @@
6
6
  *
7
7
  * 0.1.7 删掉了 `ctx.settingsScope.bind({ namespace })` 这套客户端设置 API,换成
8
8
  * `ctx.configForms.get(entryId)`:**设置不再是按命名空间分的独立文档,而是一个
9
- * 插件 entry 自己的 config**。本插件把两块设置合并进同一个 entry(`knowledge` /
10
- * `convert` 两个组),但下层的编辑器(`NodeSettings`、`KnowledgeBaseTab`
9
+ * 插件 entry 自己的 config**。本插件把设置合并进同一个 entry(`knowledge` /
10
+ * `convert` / `behaviorRules` 三个组),但下层的编辑器(`NodeSettings`、`KnowledgeBaseTab`
11
11
  * …)是按「一个平铺的设置组」写的,它们读 `snapshot.value.recallTopK`、
12
12
  * 写 `scope.set('recallTopK', 20)`。
13
13
  *
@@ -20,7 +20,7 @@
20
20
  *
21
21
  * `ConfigForm.set(field, …)` 的契约是「**命名空间 section 里的标量字段**」——只认
22
22
  * 顶层的键。分组之后的字段都在第二层,所以一律走按路径寻址的 `mutate`。`group`
23
- * 省略时(`agent-preset-registry` 那条 DSH 自己的 entry)路径就只有字段名本身,
23
+ * 省略分组时路径只有字段名本身,
24
24
  * 与 `set` 等价。
25
25
  *
26
26
  * @module
@@ -0,0 +1,165 @@
1
+ /**
2
+ * 画布上用的**颜色字面量**,只有这一份。
3
+ *
4
+ * ## 为什么是字面量,不是 CSS 变量
5
+ *
6
+ * G6 的 canvas 渲染器读不到 CSS 自定义属性:`var(--tita-primary)` 会被 `parseColor`
7
+ * 解析成全透明黑 —— 表现是「节点边框凭空消失」,而且不报错。所以这些值必须以
8
+ * `#rrggbb` 的形式交给画布。
9
+ *
10
+ * ## 为什么集中到一个模块
11
+ *
12
+ * 它们原来是三份互不相干的字面量:`attribution/graph-options.ts`(边与徽标)、
13
+ * `attribution/model.ts`(节点取色)、`ExpansionGraph.tsx`(扩展图的圆点)。三份各自
14
+ * 演化,于是同一个「中性文字」在三处的灰度不同,而**没有任何一处能看出它们本该相同**。
15
+ * 现在三处都从这里取,改一次就三处一起改。
16
+ *
17
+ * ## 必须守住的对比度
18
+ *
19
+ * 画布没有 CSS 的兜底,所以这里的值**由测量决定**,不是由手感决定。背景按
20
+ * `--tita-surface` = `#ffffff` 算(深浅主题下画布底色都由外层容器给,浅色是默认):
21
+ *
22
+ * - 标签墨色(`LABEL_INK` / `LABEL_FAINT` / `BADGE_INK`):≥ 4.5:1(正文级)。
23
+ * 它们画的是 9–11px 的字,比大字号更需要余量。
24
+ * - 静音描边(`OUTLINE_MUTED`):≥ 3:1(非文字 UI 的门槛)。
25
+ * - 引用层描边(`NODE_REFERENCE_STROKE`)与它的底色(`NODE_REFERENCE_FILL`)之间:
26
+ * ≥ 3:1。这一对原来只有 1.64:1 —— 边和填充几乎同色,节点看起来是一块平色。
27
+ * - 命中色(`HIT_FILL`):≥ 3:1;它同时是圆点填充和它的描边。
28
+ *
29
+ * 改动任何一个值之前先算一遍:`(L1 + 0.05) / (L2 + 0.05)`,`L` 是 WCAG 的相对亮度。
30
+ * 这条注释留在文件里的理由很具体 —— 「颜色慢慢漂到不达标」这件事没有编译期检查,
31
+ * 只有某个人真的去量。2026-10-18 量过一轮,下面每个值都过了。
32
+ */
33
+
34
+ /* ─────────────────────────────────────────────────────────── 画布底色上的文字与描边 */
35
+
36
+ /** 画布主文字色(节点标题、命中圆点的标签)。白底 7.7:1。 */
37
+ export const LABEL_INK = '#101828'
38
+
39
+ /** 次级文字色(扩展图里「预算外」邻居的标签、边的计数标签底色)。白底 4.9:1。 */
40
+ export const LABEL_FAINT = '#667085'
41
+
42
+ /** 静音描边:预算外的邻居、僵尸边。白底 5.0:1(原 `#98a2b3` 只有 2.58:1,不达标)。 */
43
+ export const OUTLINE_MUTED = '#667085'
44
+
45
+ /** 滑块式的圆角底:边标签垫在它上面。它是**底色**不是文字,所以浅。 */
46
+ export const LABEL_PLATE = '#f6f8fb'
47
+
48
+ /* ───────────────────────────────────────────────────────────── 扩展图的命中 / 邻居 */
49
+
50
+ /** 命中卡片:填充与描边同色(它是一个实心点,不是带框的卡片)。白底 5.4:1。 */
51
+ export const HIT_FILL = '#4868b2'
52
+
53
+ /** 预算内邻居:白底 + 命中色描边,靠描边区分「这是邻居」。 */
54
+ export const NEIGHBOR_FILL = '#ffffff'
55
+
56
+ /** 节点被选中的那一圈。白底 5.2:1。 */
57
+ export const SELECTION_RING = '#2563eb'
58
+
59
+ /* ───────────────────────────────────────────────────────────────────── 节点的取色 */
60
+
61
+ /** 中性节点(没有分类、没有失败模式的那一类):白底、浅描边、静音文字。 */
62
+ export const NEUTRAL_NODE = { fill: '#ffffff', stroke: '#d6dce6', text: LABEL_FAINT }
63
+
64
+ /**
65
+ * 引用层节点:**底色与描边必须分得开**。
66
+ *
67
+ * 原来是 `#eef4ff` 配 `#9ec2ff`(1.64:1),几乎是一块平色;描边提到 `#2563eb`
68
+ * 之后是 4.68:1,白底上也有 5.17:1。
69
+ */
70
+ export const NODE_REFERENCE_FILL = '#eef4ff'
71
+ export const NODE_REFERENCE_STROKE = '#2563eb'
72
+ export const NODE_REFERENCE_TEXT = '#1d4ed8'
73
+
74
+ /** 现象节点:琥珀。 */
75
+ export const NODE_SYMPTOM = { fill: '#fff7ea', stroke: '#b96d14', text: '#96580f' }
76
+
77
+ /** 检查点节点:紫。 */
78
+ export const NODE_CHECK_POINT = { fill: '#f5f1ff', stroke: '#c9b8ff', text: '#5b45be' }
79
+
80
+ /** 空区假设:描边是虚线,颜色与失败原因里的红同一档(它要人来看一眼)。 */
81
+ export const GAP_STROKE = '#b42318'
82
+
83
+ /** 僵尸边(90 天没走过):灰、虚线。与 `OUTLINE_MUTED` 分开命名是因为它还会变淡。 */
84
+ export const ZOMBIE_STROKE = '#9aa4b2'
85
+
86
+ /** 失败模式的取色。与 `model.ts` 的 `FAILURE_REASON_LABEL` 一一对应,顺序也一致。 */
87
+ export const FAILURE_REASON_FILL = {
88
+ 'upstream-missing': '#eef4ff',
89
+ 'spec-change': '#f3f0ff',
90
+ 'data-processing': '#eafaf2',
91
+ consumption: '#fff7ea',
92
+ permission: '#fdecea',
93
+ } as const
94
+
95
+ export const FAILURE_REASON_STROKE = {
96
+ 'upstream-missing': '#2563eb',
97
+ 'spec-change': '#6b54cf',
98
+ 'data-processing': '#12875f',
99
+ consumption: '#b96d14',
100
+ permission: '#b42318',
101
+ } as const
102
+
103
+ export const FAILURE_REASON_TEXT = {
104
+ 'upstream-missing': '#1d4ed8',
105
+ 'spec-change': '#5b45be',
106
+ 'data-processing': '#0f6b4d',
107
+ consumption: '#96580f',
108
+ permission: '#98200f',
109
+ } as const
110
+
111
+ /* ─────────────────────────────────────────────────────────────────────────── 边 */
112
+
113
+ /**
114
+ * 十二种边各自的外观色。
115
+ *
116
+ * 这里只有**颜色**;线宽与线型留在 `graph-options.ts` 的 `EDGE_STYLE` 里 —— 那些是
117
+ * 几何,不是调色板的一部分。名字与 `AttributionEdgeKind` 逐字相同,漏一种在类型上
118
+ * 就报错。
119
+ */
120
+ export const EDGE_STROKE = {
121
+ may_be_caused_by: '#93b4f8',
122
+ verified_by: '#6b54cf',
123
+ categorized_as: '#c9b8ff',
124
+ queries: '#9ec2ff',
125
+ produces: '#b96d14',
126
+ supports: '#12875f',
127
+ refutes: '#b42318',
128
+ confirmed_as: '#0f766e',
129
+ instance_of: '#b96d14',
130
+ /**
131
+ * 反查索引。原来是 `#9ec2ff`(白底 1.8:1)—— 与「要去查」那条边的颜色完全相同,
132
+ * 两条语义不同的边在画布上分不出来。现在深一档(4.68:1),与引用层节点描边同色:
133
+ * 它画的正是「这张表被哪条假设引用」。
134
+ */
135
+ indexed_from: '#2563eb',
136
+ } as const
137
+
138
+ /* ─────────────────────────────────────────────────────────────────────────── 徽标 */
139
+
140
+ /**
141
+ * 节点徽标(挂在节点上沿 / 下沿的小字牌)。
142
+ *
143
+ * `fontSize: 9` 是最小可读档,所以它的墨色必须比正文更保守:`#748091` 在白底上
144
+ * 只有 4.01:1(不达 4.5),换成 `#475467`(7.7:1)。
145
+ */
146
+ export const BADGE_INK = '#475467'
147
+ export const BADGE_PLATE = '#ffffff'
148
+ export const BADGE_PLATE_STROKE = '#e5e9f0'
149
+
150
+ /** 空区徽标的红:与 `GAP_STROKE` 同色,浅红描边把它从白底上托起来。 */
151
+ export const BADGE_GAP_STROKE = '#f0b7ad'
152
+
153
+ /** 问题分类徽标:琥珀文字 + 浅琥珀描边。 */
154
+ export const BADGE_PROBLEM_INK = '#96580f'
155
+ export const BADGE_PROBLEM_STROKE = '#f2ddb8'
156
+
157
+ /** 「N min · 自动 / 人工」徽标:自动走绿、人工走琥珀(同一档语义色)。 */
158
+ export const BADGE_AUTO_INK = '#12875f'
159
+ export const BADGE_MANUAL_INK = '#b96d14'
160
+
161
+ /** 边上的「N 例」计数标签:琥珀。 */
162
+ export const EDGE_COUNT_INK = '#b96d14'
163
+
164
+ /** 边上的「僵尸边 N 天未走」标签:静音灰。 */
165
+ export const EDGE_ZOMBIE_INK = '#9aa4b2'