@chengxianglibra/dsh-data-analysis 0.1.1 → 0.2.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 (303) hide show
  1. package/README.md +139 -53
  2. package/cordis.patch.yml +1 -1
  3. package/lib/bin/environment.js +9 -7
  4. package/lib/bin/presentation-lint.js +21 -0
  5. package/lib/bridges.js +2 -2
  6. package/lib/client/credentials/changes.js +74 -0
  7. package/lib/client/credentials/create-datasource.js +171 -0
  8. package/lib/client/credentials/credential-draft.js +42 -0
  9. package/lib/client/credentials/defaults.js +11 -0
  10. package/lib/client/credentials/descriptions.js +46 -0
  11. package/lib/client/credentials/install.js +319 -0
  12. package/lib/client/credentials/model.js +766 -0
  13. package/lib/client/credentials/report-publishing.js +96 -0
  14. package/lib/client/credentials/styles.js +21 -0
  15. package/lib/client/i18n/context.js +22 -0
  16. package/lib/client/i18n/copy.js +57 -0
  17. package/lib/client/i18n/credentials.js +475 -0
  18. package/lib/client/i18n/host.js +27 -0
  19. package/lib/client/i18n/navigation.js +41 -0
  20. package/lib/client/i18n/presentation.js +577 -0
  21. package/lib/client/i18n/python.js +36 -0
  22. package/lib/client/i18n/semantic.js +441 -0
  23. package/lib/client/input-context.js +21 -0
  24. package/lib/client/python-tool/card.js +35 -0
  25. package/lib/client/python-tool/execution-error.js +35 -0
  26. package/lib/client/python-tool/install.js +9 -0
  27. package/lib/client/python-tool/model.js +101 -0
  28. package/lib/client/right-tabs/install.js +535 -0
  29. package/lib/client/right-tabs/live-delivery.js +58 -0
  30. package/lib/client/right-tabs/navigation.js +47 -0
  31. package/lib/client/right-tabs/page.js +178 -0
  32. package/lib/client/right-tabs/styles.js +11 -0
  33. package/lib/client/rpc.js +5 -0
  34. package/lib/client/semantic-reference.js +10 -0
  35. package/lib/client/workspace-header-action.js +24 -0
  36. package/lib/client/workspace-shortcuts.js +26 -0
  37. package/lib/client.js +1250 -730
  38. package/lib/compatibility.js +2 -2
  39. package/lib/datasource/authoring.js +109 -0
  40. package/lib/datasource/bridge-programs.js +42 -27
  41. package/lib/datasource/bridge.js +144 -9
  42. package/lib/datasource/changes-contract.js +41 -0
  43. package/lib/datasource/changes.js +49 -0
  44. package/lib/datasource/configure.js +39 -0
  45. package/lib/datasource/defaults.js +25 -0
  46. package/lib/datasource/index.js +4 -2
  47. package/lib/datasource/python-options.js +21 -0
  48. package/lib/datasource/python.js +206 -0
  49. package/lib/datasource/resolver-program.js +112 -0
  50. package/lib/datasource/rpc.js +150 -0
  51. package/lib/datasource/service.js +962 -0
  52. package/lib/datasource/shell-env.js +2 -333
  53. package/lib/datasource/test.js +25 -51
  54. package/lib/disclosure/activation.js +19 -7
  55. package/lib/disclosure/execution-guidance.js +52 -0
  56. package/lib/disclosure/help.js +4 -1
  57. package/lib/environment/binding.js +54 -9
  58. package/lib/environment/runtime.js +120 -108
  59. package/lib/environment/subprocess.js +6 -1
  60. package/lib/environment/summary.js +3 -3
  61. package/lib/environment/workspace.js +23 -1
  62. package/lib/index.js +1 -1
  63. package/lib/lifecycle.js +33 -0
  64. package/lib/plugin-agents.js +154 -0
  65. package/lib/plugin.js +172 -133
  66. package/lib/presentation/asset.js +34 -0
  67. package/lib/presentation/assets/portable.js +606 -0
  68. package/lib/presentation/assets/static.js +1216 -0
  69. package/lib/presentation/build/index.js +72 -0
  70. package/lib/presentation/commit.js +163 -0
  71. package/lib/presentation/contracts/asset-path.js +9 -0
  72. package/lib/presentation/contracts/catalog.js +62 -0
  73. package/lib/presentation/contracts/charts.js +453 -0
  74. package/lib/presentation/contracts/editing.js +58 -0
  75. package/lib/presentation/contracts/index.js +663 -0
  76. package/lib/presentation/contracts/interaction.js +62 -0
  77. package/lib/presentation/contracts/types.js +15 -0
  78. package/lib/presentation/contracts/values.js +28 -0
  79. package/lib/presentation/delivery.js +71 -0
  80. package/lib/presentation/export-html.js +214 -0
  81. package/lib/presentation/files.js +82 -0
  82. package/lib/presentation/index.js +6 -0
  83. package/lib/presentation/lint.js +46 -0
  84. package/lib/presentation/projection/files.js +85 -0
  85. package/lib/presentation/projection/index.js +196 -0
  86. package/lib/presentation/projection/program.js +137 -0
  87. package/lib/presentation/projection/sql-code.js +79 -0
  88. package/lib/presentation/receipt.js +34 -0
  89. package/lib/presentation/reports.js +219 -0
  90. package/lib/presentation/rpc.js +186 -0
  91. package/lib/presentation/tool.js +118 -0
  92. package/lib/python-execution-contracts.js +1 -0
  93. package/lib/python-execution.js +232 -0
  94. package/lib/report-publishing/adapters.js +111 -0
  95. package/lib/report-publishing/config.js +69 -0
  96. package/lib/report-publishing/service.js +180 -0
  97. package/lib/rpc.js +49 -0
  98. package/lib/semantic-browser/contracts.js +97 -0
  99. package/lib/semantic-browser/definition.js +64 -0
  100. package/lib/semantic-browser/program.js +129 -0
  101. package/lib/semantic-browser/service.js +106 -0
  102. package/lib/semantic-reference/bridge.js +127 -0
  103. package/lib/semantic-reference/contracts.js +127 -0
  104. package/lib/semantic-reference/environment.js +56 -0
  105. package/lib/semantic-reference/index.js +3 -0
  106. package/lib/semantic-reference/labels.js +16 -0
  107. package/lib/semantic-reference/rpc.js +143 -0
  108. package/lib/semantic-reference/search.js +95 -0
  109. package/lib/semantic-reference/usage.js +152 -0
  110. package/lib/tool-lifecycle.js +22 -0
  111. package/lib/types/bridges.d.ts +2 -2
  112. package/lib/types/client/credentials/changes.d.ts +9 -0
  113. package/lib/types/client/credentials/create-datasource.d.ts +7 -0
  114. package/lib/types/client/credentials/credential-draft.d.ts +14 -0
  115. package/lib/types/client/credentials/defaults.d.ts +2 -0
  116. package/lib/types/client/credentials/descriptions.d.ts +1 -0
  117. package/lib/types/client/credentials/install.d.ts +19 -0
  118. package/lib/types/client/credentials/model.d.ts +79 -0
  119. package/lib/types/client/credentials/report-publishing.d.ts +5 -0
  120. package/lib/types/client/credentials/styles.d.ts +1 -0
  121. package/lib/types/client/i18n/context.d.ts +17 -0
  122. package/lib/types/client/i18n/copy.d.ts +806 -0
  123. package/lib/types/client/i18n/credentials.d.ts +475 -0
  124. package/lib/types/client/i18n/host.d.ts +16 -0
  125. package/lib/types/client/i18n/navigation.d.ts +41 -0
  126. package/lib/types/client/i18n/presentation.d.ts +577 -0
  127. package/lib/types/client/i18n/python.d.ts +19 -0
  128. package/lib/types/client/i18n/semantic.d.ts +441 -0
  129. package/lib/types/client/input-context.d.ts +19 -0
  130. package/lib/types/client/presentation/ask-dsh.d.ts +5 -0
  131. package/lib/types/client/presentation/catalog-model.d.ts +24 -0
  132. package/lib/types/client/presentation/catalog.d.ts +20 -0
  133. package/lib/types/client/presentation/chart-explorer.d.ts +12 -0
  134. package/lib/types/client/presentation/chart-geometry.d.ts +30 -0
  135. package/lib/types/client/presentation/chart-renderer.d.ts +10 -0
  136. package/lib/types/client/presentation/chart-specials.d.ts +10 -0
  137. package/lib/types/client/presentation/chart-styles.d.ts +1 -0
  138. package/lib/types/client/presentation/chart-tooltip.d.ts +13 -0
  139. package/lib/types/client/presentation/chart-view.d.ts +23 -0
  140. package/lib/types/client/presentation/context-reference.d.ts +12 -0
  141. package/lib/types/client/presentation/copy-context.d.ts +5 -0
  142. package/lib/types/client/presentation/delivery-model.d.ts +75 -0
  143. package/lib/types/client/presentation/delivery.d.ts +78 -0
  144. package/lib/types/client/presentation/download.d.ts +2 -0
  145. package/lib/types/client/presentation/editor-controls.d.ts +12 -0
  146. package/lib/types/client/presentation/export-menu.d.ts +26 -0
  147. package/lib/types/client/presentation/export-view.d.ts +63 -0
  148. package/lib/types/client/presentation/global-filters.d.ts +6 -0
  149. package/lib/types/client/presentation/host-entry.d.ts +18 -0
  150. package/lib/types/client/presentation/icons.d.ts +4 -0
  151. package/lib/types/client/presentation/markdown.d.ts +5 -0
  152. package/lib/types/client/presentation/model.d.ts +61 -0
  153. package/lib/types/client/presentation/reader.d.ts +24 -0
  154. package/lib/types/client/presentation/reference-source.d.ts +9 -0
  155. package/lib/types/client/presentation/source-code-model.d.ts +17 -0
  156. package/lib/types/client/presentation/source-code.d.ts +6 -0
  157. package/lib/types/client/presentation/source-dialog.d.ts +12 -0
  158. package/lib/types/client/presentation/source-facts.d.ts +20 -0
  159. package/lib/types/client/presentation/source-format.d.ts +5 -0
  160. package/lib/types/client/presentation/source-highlight.d.ts +7 -0
  161. package/lib/types/client/presentation/sources.d.ts +13 -0
  162. package/lib/types/client/presentation/styles.d.ts +1 -0
  163. package/lib/types/client/presentation/table.d.ts +16 -0
  164. package/lib/types/client/presentation/use-element-width.d.ts +5 -0
  165. package/lib/types/client/python-tool/card.d.ts +2 -0
  166. package/lib/types/client/python-tool/execution-error.d.ts +3 -0
  167. package/lib/types/client/python-tool/install.d.ts +2 -0
  168. package/lib/types/client/python-tool/model.d.ts +20 -0
  169. package/lib/types/client/right-tabs/install.d.ts +18 -0
  170. package/lib/types/client/right-tabs/live-delivery.d.ts +8 -0
  171. package/lib/types/client/right-tabs/navigation.d.ts +17 -0
  172. package/lib/types/client/right-tabs/page.d.ts +36 -0
  173. package/lib/types/client/right-tabs/styles.d.ts +2 -0
  174. package/lib/types/client/rpc.d.ts +3 -0
  175. package/lib/types/client/semantic-reference.d.ts +4 -0
  176. package/lib/types/client/workspace-header-action.d.ts +7 -0
  177. package/lib/types/client/workspace-shortcuts.d.ts +15 -0
  178. package/lib/types/client.d.ts +9 -124
  179. package/lib/types/compatibility.d.ts +3 -3
  180. package/lib/types/datasource/authoring.d.ts +35 -0
  181. package/lib/types/datasource/bridge.d.ts +43 -4
  182. package/lib/types/datasource/changes-contract.d.ts +18 -0
  183. package/lib/types/datasource/changes.d.ts +15 -0
  184. package/lib/types/datasource/configure.d.ts +7 -0
  185. package/lib/types/datasource/defaults.d.ts +7 -0
  186. package/lib/types/datasource/index.d.ts +8 -5
  187. package/lib/types/datasource/python-options.d.ts +9 -0
  188. package/lib/types/datasource/python.d.ts +19 -0
  189. package/lib/types/datasource/resolver-program.d.ts +6 -0
  190. package/lib/types/datasource/rpc.d.ts +5 -0
  191. package/lib/types/datasource/service.d.ts +155 -0
  192. package/lib/types/datasource/shell-env.d.ts +0 -29
  193. package/lib/types/datasource/test.d.ts +6 -29
  194. package/lib/types/disclosure/activation.d.ts +2 -1
  195. package/lib/types/disclosure/execution-guidance.d.ts +6 -0
  196. package/lib/types/disclosure/help.d.ts +1 -1
  197. package/lib/types/environment/binding.d.ts +5 -1
  198. package/lib/types/environment/errors.d.ts +1 -1
  199. package/lib/types/environment/runtime.d.ts +5 -5
  200. package/lib/types/environment/types.d.ts +15 -3
  201. package/lib/types/environment/workspace.d.ts +1 -0
  202. package/lib/types/index.d.ts +1 -1
  203. package/lib/types/lifecycle.d.ts +8 -0
  204. package/lib/types/plugin-agents.d.ts +27 -0
  205. package/lib/types/plugin.d.ts +14 -24
  206. package/lib/types/presentation/asset.d.ts +6 -0
  207. package/lib/types/presentation/build/index.d.ts +16 -0
  208. package/lib/types/presentation/commit.d.ts +4 -0
  209. package/lib/types/presentation/contracts/asset-path.d.ts +2 -0
  210. package/lib/types/presentation/contracts/catalog.d.ts +27 -0
  211. package/lib/types/presentation/contracts/charts.d.ts +11 -0
  212. package/lib/types/presentation/contracts/editing.d.ts +8 -0
  213. package/lib/types/presentation/contracts/index.d.ts +11 -0
  214. package/lib/types/presentation/contracts/interaction.d.ts +8 -0
  215. package/lib/types/presentation/contracts/types.d.ts +255 -0
  216. package/lib/types/presentation/contracts/values.d.ts +9 -0
  217. package/lib/types/presentation/delivery.d.ts +3 -0
  218. package/lib/types/presentation/export-html.d.ts +13 -0
  219. package/lib/types/presentation/files.d.ts +7 -0
  220. package/lib/types/presentation/index.d.ts +6 -0
  221. package/lib/types/presentation/lint.d.ts +13 -0
  222. package/lib/types/presentation/projection/files.d.ts +2 -0
  223. package/lib/types/presentation/projection/index.d.ts +20 -0
  224. package/lib/types/presentation/projection/program.d.ts +2 -0
  225. package/lib/types/presentation/projection/sql-code.d.ts +2 -0
  226. package/lib/types/presentation/receipt.d.ts +14 -0
  227. package/lib/types/presentation/reports.d.ts +10 -0
  228. package/lib/types/presentation/rpc.d.ts +25 -0
  229. package/lib/types/presentation/tool.d.ts +12 -0
  230. package/lib/types/python-execution-contracts.d.ts +10 -0
  231. package/lib/types/python-execution.d.ts +10 -0
  232. package/lib/types/report-publishing/adapters.d.ts +6 -0
  233. package/lib/types/report-publishing/config.d.ts +22 -0
  234. package/lib/types/report-publishing/service.d.ts +68 -0
  235. package/lib/types/rpc.d.ts +3 -0
  236. package/lib/types/semantic-browser/contracts.d.ts +47 -0
  237. package/lib/types/semantic-browser/definition.d.ts +20 -0
  238. package/lib/types/semantic-browser/program.d.ts +2 -0
  239. package/lib/types/semantic-browser/service.d.ts +26 -0
  240. package/lib/types/semantic-reference/bridge.d.ts +12 -0
  241. package/lib/types/semantic-reference/contracts.d.ts +54 -0
  242. package/lib/types/semantic-reference/environment.d.ts +22 -0
  243. package/lib/types/semantic-reference/index.d.ts +3 -0
  244. package/lib/types/semantic-reference/labels.d.ts +16 -0
  245. package/lib/types/semantic-reference/rpc.d.ts +15 -0
  246. package/lib/types/semantic-reference/search.d.ts +10 -0
  247. package/lib/types/semantic-reference/usage.d.ts +43 -0
  248. package/lib/types/tool-lifecycle.d.ts +4 -0
  249. package/lib/types/workspace-identity.d.ts +6 -0
  250. package/lib/workspace-identity.js +9 -0
  251. package/package.json +99 -53
  252. package/python/presentation-kit/dist/dsh_data_analysis_presentation_kit-1.1.0-py3-none-any.whl +0 -0
  253. package/skills/dsh-data-analysis-files/SKILL.md +32 -0
  254. package/skills/dsh-data-analysis-files/references/examples.md +93 -0
  255. package/skills/dsh-data-analysis-presentation/SKILL.md +28 -0
  256. package/skills/dsh-data-analysis-presentation/references/chart-examples.md +18 -0
  257. package/skills/dsh-data-analysis-presentation/references/charts.md +55 -0
  258. package/skills/dsh-data-analysis-presentation/references/examples/artifact.draft.json +36 -0
  259. package/skills/dsh-data-analysis-presentation/references/examples/charts-bins.dataset.json +33 -0
  260. package/skills/dsh-data-analysis-presentation/references/examples/charts-boxes.dataset.json +45 -0
  261. package/skills/dsh-data-analysis-presentation/references/examples/charts-composition.dataset.json +33 -0
  262. package/skills/dsh-data-analysis-presentation/references/examples/charts-funnel.dataset.json +27 -0
  263. package/skills/dsh-data-analysis-presentation/references/examples/charts-precision.dataset.json +21 -0
  264. package/skills/dsh-data-analysis-presentation/references/examples/charts-series.dataset.json +58 -0
  265. package/skills/dsh-data-analysis-presentation/references/examples/charts-shares.dataset.json +33 -0
  266. package/skills/dsh-data-analysis-presentation/references/examples/charts-waterfall.dataset.json +44 -0
  267. package/skills/dsh-data-analysis-presentation/references/examples/charts.draft.json +393 -0
  268. package/skills/dsh-data-analysis-presentation/references/examples/comparison-selected.dataset.json +24 -0
  269. package/skills/dsh-data-analysis-presentation/references/examples/comparison-summary.dataset.json +22 -0
  270. package/skills/dsh-data-analysis-presentation/references/examples/comparison.dataset.json +18 -0
  271. package/skills/dsh-data-analysis-presentation/references/examples/comparison.draft.json +80 -0
  272. package/skills/dsh-data-analysis-presentation/references/examples/computed-sources.draft.json +42 -0
  273. package/skills/dsh-data-analysis-presentation/references/examples/computed.dataset.json +12 -0
  274. package/skills/dsh-data-analysis-presentation/references/examples/computed.draft.json +58 -0
  275. package/skills/dsh-data-analysis-presentation/references/examples/interaction-detail.dataset.json +30 -0
  276. package/skills/dsh-data-analysis-presentation/references/examples/interaction-summary.dataset.json +22 -0
  277. package/skills/dsh-data-analysis-presentation/references/examples/interaction.draft.json +279 -0
  278. package/skills/dsh-data-analysis-presentation/references/examples/source-only.draft.json +27 -0
  279. package/skills/dsh-data-analysis-presentation/references/examples/write-charts.py +73 -0
  280. package/skills/dsh-data-analysis-presentation/references/examples/write-comparison.py +42 -0
  281. package/skills/dsh-data-analysis-presentation/references/examples/write-computed.py +21 -0
  282. package/skills/dsh-data-analysis-presentation/references/examples/write-interaction.py +33 -0
  283. package/skills/dsh-data-analysis-presentation/references/examples.md +44 -0
  284. package/skills/dsh-data-analysis-presentation/references/export-html.md +7 -0
  285. package/skills/dsh-data-analysis-presentation/references/interaction.md +56 -0
  286. package/skills/dsh-data-analysis-presentation/references/narrative.md +37 -0
  287. package/skills/dsh-data-analysis-presentation/references/publishing.md +3 -0
  288. package/skills/dsh-data-analysis-presentation/references/schema.md +162 -0
  289. package/lib/datasource/access.js +0 -60
  290. package/lib/datasource/credentials.js +0 -24
  291. package/lib/evidence/bridge-program.js +0 -153
  292. package/lib/evidence/bridge.js +0 -166
  293. package/lib/evidence/index.js +0 -2
  294. package/lib/evidence/sources.js +0 -263
  295. package/lib/types/datasource/access.d.ts +0 -27
  296. package/lib/types/evidence/bridge.d.ts +0 -40
  297. package/lib/types/evidence/index.d.ts +0 -4
  298. package/lib/types/evidence/sources.d.ts +0 -57
  299. package/python/report-kit/dist/dsh_data_analysis_report_kit-3.0.0-py3-none-any.whl +0 -0
  300. package/skills/dsh-data-analysis-report/SKILL.md +0 -57
  301. package/skills/dsh-data-analysis-report/assets/marivo-artifact.js +0 -113
  302. package/skills/dsh-data-analysis-report/assets/marivo-session-dag.js +0 -1201
  303. package/skills/dsh-data-analysis-report/assets/report-data.js +0 -449
@@ -0,0 +1,162 @@
1
+ # 草稿 schema 与文件边界
2
+
3
+ 这是插件的 presentation v1 写入契约。所有对象只接受列出的字段;不要把生成文档或 receipt 当作草稿。Marivo 的分析 API 与 semantic schema 以 bound Runtime 的 Skill 和 live Help 为准。
4
+
5
+ ## 报告语言与版本
6
+
7
+ 报告展示语言由 Draft 的 `locale` 决定,Document 使用 `schemaVersion: 3` 并原样保留语言。系统语言仅控制插件操作界面。保存、重开、打印和离线 HTML 均保持报告语言;用户要求改语言时更新完整 Draft,并按既有并发保存契约生成新 Build。旧 Draft v1、Document v2 或缺少语言的报告不受支持,必须重新生成;不修改已有不可变 Build。
8
+
9
+ ## 顶层与引用
10
+
11
+ 顶层必须有 `schemaVersion: 2`、`locale: "zh-CN" | "en-US"`、非空 `title`、`datasets`、`sources`、`blocks`。即使没有 dataset 或来源,也保留空数组;至少一个 block。datasets、sources、blocks 各自的 `id` 不重复,所有引用必须存在。
12
+
13
+ | 对象 | 必填字段 | 可选字段 |
14
+ | --- | --- | --- |
15
+ | 声明来源 | `id`, `ref: {sessionId, artifactRef}` | `ref.findingId` |
16
+ | Artifact dataset | `id`, `kind: "artifact"`, `sourceId`, `rowLimit` | `columns: string[]`, `codeRefs` |
17
+ | computed dataset | `id`, `kind: "computed"`, `path`, `sourceIds: string[]` | `codeRefs` |
18
+
19
+ `sessionId` 使用 Artifact 所属 Marivo Session 的实际 `session.id`,`artifactRef` 使用实际 `artifact.ref`。保存并传递这两个公开属性;`session.name`、显示名称、日志标题和 DSH Session ID 都不能替代持久身份。`sourceId` 和 `sourceIds` 指向草稿 `sources[].id`。computed 可声明零个或多个来源,声明不建立 Marivo lineage,也不验证转换。Artifact dataset 要求可恢复保存数据;computed 的声明来源不可用时仍可展示数据,并标明 unavailable。
20
+
21
+ `draft_path` 与 computed 的 `path` 均相对于当前绑定 Workspace 根目录,**不是相对于草稿文件目录**。使用根目录内的 JSON 文件;不使用绝对路径、`..`、`.` 路径段、反斜杠、空路径段或通向 Workspace 外的符号链接。不从其他项目、解释器或数据源补齐失败的引用。
22
+
23
+ ## 从报告 cell 引用继续
24
+
25
+ Ask DSH 与离线复制提供所属 Workspace、Report ID、实际显示的 Build ID、Cell ID,以及
26
+ 相对于该 Workspace 的固定 Build `presentation.json` 路径。先用普通文件读取该路径,核对身份,
27
+ 再按 `blocks[].id` 定位 cell;正文、数据、单位、精确值、比较和来源限制均从文件读取,不依赖旧对话。
28
+ `Workspace`、`Cell` 和 `Prepared view` 的字段值使用 JSON 字符串编码;先按 JSON 解码再精确匹配,
29
+ 保留 ID 中的换行、引号和反斜杠,不取首行、不做 trim。`Report title` 仅为辅助标题,不参与身份匹配。
30
+ 文件较长时按读取工具的分页提示继续;单行被截断时使用已有 Workspace 文件能力定向读取 JSON 字段,
31
+ 不将截断内容当成完整文档。路径属于原 Workspace,单独分享 HTML 不授予访问原文件的能力。
32
+
33
+ 引用的 Filters 按 filter ID 与 option ID 匹配该 Build 的 `interaction.slices`,从对应 dataset 的
34
+ `rowIndices` 取已有数据。Prepared view 按目标 chart 的 `preparedViews[].id` 读取;若附有
35
+ Current chart view override,则替换显示配置,再应用 Hidden series。Table sort 只改变显示顺序;
36
+ 表格引用包含全部筛选结果,不限当前分页。未附覆盖时沿用保存配置。这些均为临时显示状态,不能宣称已保存。
37
+
38
+ 解释时以引用 Build 为准,不能静默换成 current。修改时还需按下面的报告更新契约读取 current,
39
+ 比较引用与当前内容,保留已有编辑;有歧义时澄清具体修改目标,不能只替换 expected ID 重试。
40
+ 临时探索状态只有在用户要求保存或据此修改时才进入修改范围。目标 Workspace 或文件不可访问时明确说明,
41
+ 不猜测其他报告、不通过重新查询或执行分析补齐。
42
+
43
+ ## 报告更新
44
+
45
+ 新建报告调用 `marivo_present({ draft_path })`。修改已有报告时使用:
46
+
47
+ ```text
48
+ marivo_present({ draft_path, report_id, expected_build_id })
49
+ ```
50
+
51
+ `report_id` 与 `expected_build_id` 是 Tool 参数,必须成对提供,不能放进 Draft。
52
+ 取实际 receipt 的 `reportId`、`buildId`;目标必须属于当前绑定 Workspace。更新前通过普通文件读取
53
+ `.dsh-data-analysis/presentations/<reportId>/current.json` 中的 receipt,再读取该 receipt 指向的
54
+ `presentation.json`,确认修改所基于的内容和 buildId。文件读取不替代 Tool 的身份与摘要校验。
55
+ 基于原始 Draft 合并需要保留的已保存编辑;生成文档包含投影快照,不能直接作为 Draft 提交。
56
+
57
+ 这是完整 Draft 重建,会重新读取声明的已有数据和来源、替换报告全部内容;省略的内容不会自动合并。
58
+ 更新成功保持 reportId,创建不可变新 buildId 并原子推进 current,返回本次提交的精确 receipt。
59
+ 宿主原卡片重开读取 current,已打开阅读器与固定文件链接保持各自快照。
60
+
61
+ `invalid-report-update-target` 表示两个参数没有成对提供;非法身份、目标缺失或损坏均拒绝更新,不回退新建。
62
+ `report-save-conflict` 表示当前版本已变化:读取 current 及其文档,核对用户编辑并重新形成 Draft,
63
+ 再以该已读取版本提交;不能只替换 expected ID 重试。响应丢失时也先读取 current 核对内容,避免重复提交。
64
+ 已有 Report 之间不自动合并,历史 Build 不覆盖或清理。
65
+
66
+ ## 生成代码
67
+
68
+ `marivo_python` 成功执行后自动保存该次提交的 Python 原文,并在结果中返回 `codeRef: {executionId, sha256}`。
69
+ 需要在 cell 的“代码”Tab 查看生成脚本时,把实际返回的引用放进对应 dataset 的 `codeRefs` 数组;最多 32 项。
70
+ 例如 `codeRefs: [result.codeRef]`。一次执行生成多个数据集时,各 dataset 可以引用同一个 `codeRef`;跨多次执行时按生成顺序列出需要的引用。
71
+ 不手填 UUID、摘要或脚本路径,不把内联代码写进草稿,也不修改执行记录文件。
72
+
73
+ 记录证明该脚本曾成功执行;dataset 与执行的关联由作者声明,不证明每个数据值来自该脚本或计算正确。
74
+ 记录保存失败时,执行结果会带 `codeCaptureError`,已有执行结果仍然有效;省略缺失的引用并说明代码不可用,不为修复展示自动重放分析。
75
+ 明确引用的记录丢失、摘要不匹配或属于其他 Workspace 时,报告构建失败;核对引用,不替换成当前脚本文件。
76
+
77
+ Artifact 的实际执行 SQL 由投影程序从该 Artifact 及其上游生产记录读取,无需在草稿重复提供。
78
+ 没有查询、记录不可读取或超出读取预算时保留明确说明。`md.raw_sql()` 等未持久化为这些 Artifact 生产记录的 SQL 不会自动补出。
79
+ Python / SQL 原文随报告快照保存,不做字面量脱敏;reader 只显示文本,不执行它们。Python 记录的是本次提交代码,导入模块及外部文件的内容不会自动打包。
80
+
81
+ ## 五类 block
82
+
83
+ | kind | 必填字段(除 `id`、`kind`) | 可选字段 |
84
+ | --- | --- | --- |
85
+ | `markdown` | `text` | 无 |
86
+ | `metric` | `datasetId`, `columnId`, `rowIndex`, `label` | `description`, `comparisons`;动态行见下文 |
87
+ | `chart` | `datasetId`, `chart`, `x`, `y: string[]`, `numericMode: "exact" \| "approximate"` | 按类型声明 `bindings`;`options`、`preparedViews`,见[图形配置](charts.md) |
88
+ | `table` | `datasetId` | `columns: string[]` |
89
+ | `source` | 非空 `sourceIds: string[]` | 无 |
90
+
91
+ metric 选取一个现有行列交叉值,`rowIndex` 从 0 开始;它不求和、不筛选、不计算 delta。chart 的 `x` 是已有列 ID,`y` 是一个或多个数值列 ID。table 的 `columns` 控制展示选择和顺序。需要聚合、比率或排序来回答问题时先完成分析,不能让 reader 推断。
92
+
93
+ blocks 数组决定阅读顺序,reader 自行适配布局;schema 没有 `layout`、`theme` 或 chart `title` 字段。图前说明用 markdown block,图例和坐标标签来自 dataset 列。Markdown 支持正文、标题、列表、引用、代码和链接;HTML 作为文字,图片不加载,不接受作者 JavaScript 或任意 renderer 配置。
94
+
95
+ 文本跟随内容区宽度,相邻 metric 自动换行且单卡有宽度上限。连续 chart 在容器足够宽时最多并排两列,
96
+ 窄容器恢复原顺序单列;Markdown、table、source 和固定/筛选分区边界都会断开图表组。
97
+ 需要并排比较时连续放置 chart,共同说明放在这组图前;不要使用空白 block 占位或假定固定行列位置。
98
+ 无脚本和打印使用单列精确数据表。
99
+
100
+ ## computed typed JSON
101
+
102
+ 优先让 `write_dataset` 处理 DataFrame 类型。手工提供纯数据 JSON 时必须满足下列契约,不能使用普通 records 数组或 JavaScript 注册脚本。
103
+
104
+ | 字段 | 含义 |
105
+ | --- | --- |
106
+ | `schemaVersion` | `1` |
107
+ | `columns` | 非空数组;每列有 `id`, `label`, `type`, `nullable`;`id` 用于字段绑定,`label` 为独立展示名;可选 `unit` |
108
+ | `rows` | 行数组,每行与 columns 等宽;null 仅用于 nullable 列 |
109
+ | `rowCount` | 截断前的总行数,非负安全整数 |
110
+ | `limit` | 1–5000;写出行数必须等于 `min(rowCount, limit)` |
111
+ | `truncated` | 必须等于 `rowCount > rows.length` |
112
+
113
+ 列类型只接受 `string`、`boolean`、`float64`、`int64`、`decimal`、`date`、`datetime`。`int64` 是有符号 64 位范围内的精确整数字符串;更大整数用 `decimal`。`decimal` 用精确字符串保留尾零。`float64` 必须有限,整数值必须是 JS 安全整数。日期用 `YYYY-MM-DD`;datetime 用带 `Z` 或显式 UTC offset 的 ISO 字符串,最多微秒精度。不要猜时区或把已舍入的数据标成精确值。
114
+
115
+ 中文报告用 `write_dataset(frame, path, labels={"base_0831": "基期(08月31日)", "cur_0907": "本期(09月07日)"})` 设置表头、图例和 tooltip 展示名,Draft 仍绑定原始列 ID。允许部分映射,未映射列沿用列名;label 可重复,须为非空字符串且最多 256 UTF-16 code units,不含 NUL 或非法 Unicode。未知映射键和非法 label 报错,最终字节预算包含 label,失败不覆盖已有文件。
116
+
117
+ Python helper 要求 `.json` 目标的父目录已存在,默认 `row_limit=5000`,返回 `path`、`bytes`、`row_count`、`written_rows`、`limit`、`truncated`。None、pandas 缺失值写为 null;无法表示的混合类型、无时区 datetime 和超精度值会报错。DataFrame index、attrs、来源和转换代码不会写入文件。
118
+
119
+ ## 有界预算与诊断
120
+
121
+ 一份草稿最多 256 KiB、16 个 datasets、64 个 sources、64 个 blocks。每个 dataset 最多 2 MiB、64 列、5000 行、100000 个单元格;文本字段最多 32768 UTF-16 code units,title 最多 512。helper 会按行与单元格预算缩减有效 limit 并报告截断;字节或文本超限直接失败。生成文档与 HTML 还分别受 4 MiB、8 MiB 限制。
122
+
123
+ 错误中的 JSON pointer 定位需要修复的字段。列不存在时核对实际输出;metric 行不存在时改为现有值或空结果说明;`numeric_precision` 按[数值绘图规则](charts.md)处理;预算超限时选择问题需要的列和有界数据,并保留范围说明。不要删掉 unavailable 或截断提示来冒充完整结果。
124
+
125
+ ## 可选全局筛选
126
+
127
+ Draft 与生成 Document 可声明 `interaction`;省略时不生成筛选器。字段及动态 metric 的互斥绑定见 [全局筛选与动态指标](interaction.md)。
128
+
129
+
130
+ ## 草稿静态预检
131
+
132
+ 在 Workspace 根目录运行 `dsh-data-analysis-presentation-lint analysis/presentation.draft.json`,
133
+ 或通过 `--project-root PATH` 显式指定 Workspace。CLI 复用 present 的草稿与 TypedDataset 校验及文件边界,
134
+ 检查草稿结构和引用的 computed JSON;不启动 Runtime、不执行分析、不生成报告文件。
135
+ 输出 JSON 的 `ok` 仅表示这些静态检查通过;`deferredChecks` 列出仍由 `marivo_present` 完成的
136
+ Artifact 可用性与数据、codeRefs、投影后文档与渲染检查。退出码为 0(通过)、1(校验失败)、2(参数错误)。
137
+ 草稿结构通过后逐份检查 computed 文件,每份保留首个错误,修正后可再次预检。
138
+
139
+ int64 单元格必须是精确整数字符串,例如 `"42"`;JSON number `42` 也不接受。
140
+ 诊断保留 JSON pointer,并显示 `column query_count type=int64`、原因与修复建议。
141
+ 超过 JS 安全整数范围的 number 可能已舍入,不能转成字符串来恢复精度;应从原始精确数据重写,
142
+ 或使用绑定 Runtime 中的 `write_dataset`。预检通过不等于成功交付,仍需 present 的成功 receipt。
143
+
144
+
145
+ ## KPI 比较卡片
146
+
147
+ `metric` 支持简短标题、主值、可选 `description`(周期或口径)以及 1–4 条 `comparisons`。
148
+ 每条包含唯一 `label`(如“同比 · 去年同期”“环比 · 上月”“较目标”),并至少绑定一个
149
+ `referenceColumnId`(参考值)、`deltaColumnId`(绝对变化)或 `relativeColumnId`(变化率)。
150
+ 所有引用均为同一 dataset、同一选中行的数值列;动态 KPI 的比较值也随 slice 一起切换。
151
+
152
+ ```json
153
+ {"id":"queries","kind":"metric","datasetId":"summary","columnId":"current","rowIndex":0,"label":"查询量","description":"全天 0–23h","comparisons":[{"label":"较上周一","referenceColumnId":"baseline","deltaColumnId":"delta_current_minus_baseline","sentiment":"neutral"}]}
154
+ ```
155
+
156
+ 分析端预先计算 current − baseline 与变化率,声明分母及比较周期。百分比用已乘 100 的值
157
+ 配 `unit: "%"`,百分点差用 delta 列配 `unit: "百分点"`。基准为零而变化率无定义时保存 nullable
158
+ `null`,不要伪造 0%。reader 不从日期、主值或参考值计算比较,也不自动重缩放。
159
+ `sentiment` 可为 `higher-is-better`、`lower-is-better` 或默认 `neutral`;例如失败率越低越好。
160
+ 箭头取已准备的 delta 符号(缺失则取 relative 符号),零显示“持平”,两者缺失显示“变化不可用”;
161
+ 作者须保证两个变化字段方向一致。颜色表达业务好坏,文字与箭头表达涨跌,不将上涨自动判为利好。
162
+ 不要把基准、变化率塞进标题或拆成独立 KPI;无比较时原有单值卡片仍有效。
@@ -1,60 +0,0 @@
1
- import { defineTool } from '@deepseek-ai/dsh-tools';
2
- import { resolveMarivoDatasourceBridge, } from "./bridge.js";
3
- import { inspectMarivoDatasourceCredentials } from "./credentials.js";
4
- export const MARIVO_DATASOURCE_ACCESS_TOOL_NAME = 'marivo_datasource_access';
5
- function datasourceName(value) {
6
- if (typeof value !== 'string' || value.trim() === '' || value.length > 256) {
7
- throw new TypeError('marivo_datasource_access name must be a non-empty string of at most 256 characters');
8
- }
9
- return value;
10
- }
11
- function renderValue(value) {
12
- if (value.status === 'needs-credentials')
13
- return JSON.stringify(value);
14
- return [
15
- `Marivo datasource ${value.name} foreground Shell access is ready for up to ${value.shell_lease.max_uses} executions within ${value.shell_lease.expires_in_ms} ms.`,
16
- 'Copy every line of the matching prelude verbatim before each foreground analysis command.',
17
- 'The first line beginning with "# dsh-marivo-credential-lease:" is a required control marker; do not remove or move it.',
18
- 'Use run_in_background=false (or omit it). If a datasource credential environment variable is missing, reacquire access; never read DSH credential files or ~/.marivo/secrets.toml.',
19
- `bash prelude:\n${value.shell_lease.bash_prelude}`,
20
- `pwsh prelude:\n${value.shell_lease.pwsh_prelude}`,
21
- ].join('\n');
22
- }
23
- /** Build the scoped datasource access Tool without performing a connection test. */
24
- export function createMarivoDatasourceAccessTool(bridgeSource, credentials, options) {
25
- return defineTool({
26
- name: MARIVO_DATASOURCE_ACCESS_TOOL_NAME,
27
- description: 'Acquire bounded foreground Shell access for one configured Marivo datasource without testing its connection.',
28
- parameters: {
29
- name: {
30
- type: 'string',
31
- required: true,
32
- description: 'Configured Marivo datasource name.',
33
- },
34
- },
35
- output: {
36
- schema: { type: 'json' },
37
- render: (_args, value) => [
38
- { type: 'text', text: renderValue(value) },
39
- ],
40
- },
41
- async execute(args, exec) {
42
- const name = datasourceName(args.name);
43
- const bridge = await resolveMarivoDatasourceBridge(bridgeSource);
44
- options.revokeShellLease(bridge, name);
45
- const described = await bridge.describe(name, exec.signal);
46
- const missing = await inspectMarivoDatasourceCredentials(described.refs, credentials, exec.signal);
47
- if (missing.length > 0) {
48
- return { status: 'needs-credentials', name: described.name, refs: missing };
49
- }
50
- return {
51
- status: 'ok',
52
- name: described.name,
53
- shell_lease: options.issueShellLease(bridge, described.name, described.refs),
54
- };
55
- },
56
- });
57
- }
58
- export function registerMarivoDatasourceAccessTool(ctx, bridgeSource, credentials, options) {
59
- return ctx.tools.register(createMarivoDatasourceAccessTool(bridgeSource, credentials, options));
60
- }
@@ -1,24 +0,0 @@
1
- import { credentialRef } from '@deepseek-ai/dsh-credentials';
2
- import { MarivoEnvironmentError } from "../environment/index.js";
3
- import { assertMarivoCredentialReferences, marivoCredentialStorageRef } from "./shell-env.js";
4
- /** Resolve mapped credentials once and optionally project values into an operation overlay. */
5
- export async function inspectMarivoDatasourceCredentials(refs, credentials, signal, accept) {
6
- const uniqueRefs = [...new Set(refs)];
7
- assertMarivoCredentialReferences(uniqueRefs);
8
- const missing = [];
9
- for (const ref of uniqueRefs) {
10
- signal.throwIfAborted();
11
- let resolved;
12
- try {
13
- resolved = await credentials.resolve(credentialRef(marivoCredentialStorageRef(ref)));
14
- }
15
- catch {
16
- throw new MarivoEnvironmentError('datasource-credential-resolve-failed', 'A mapped Marivo datasource credential could not be resolved', { ref });
17
- }
18
- if (resolved === undefined)
19
- missing.push(ref);
20
- else
21
- accept?.(ref, resolved.value);
22
- }
23
- return missing;
24
- }
@@ -1,153 +0,0 @@
1
- export const MARIVO_EVIDENCE_FINDINGS_PROGRAM = String.raw `
2
- import json
3
- import sys
4
- import marivo.analysis as mv
5
- from marivo.analysis.errors import ArtifactNotFoundError, FindingNotFoundError
6
-
7
-
8
- session_id = sys.argv[1]
9
- selections = json.loads(sys.argv[2])
10
- try:
11
- session = mv.session.resume(session_id, use_datasources=False)
12
- except Exception as exc:
13
- print(json.dumps({
14
- "kind": "evidence-session-read-failed",
15
- "exception_type": type(exc).__name__,
16
- }, sort_keys=True), file=sys.stderr)
17
- raise SystemExit(70)
18
-
19
-
20
- def revalidation_projection(artifact):
21
- try:
22
- result = session.revalidate(artifact.ref)
23
- except ArtifactNotFoundError:
24
- return {
25
- "status": "unavailable",
26
- "semantic_status": None,
27
- "evidence_status": None,
28
- "dependency_status": None,
29
- }
30
- return {
31
- "status": result.status,
32
- "semantic_status": result.semantic_status,
33
- "evidence_status": result.evidence_status,
34
- "dependency_status": result.dependency_status,
35
- }
36
-
37
-
38
- sources = []
39
- for selection in selections:
40
- artifact_ref = selection["artifactRef"]
41
- finding_id = selection["findingId"]
42
- locator = f"marivo://session/{session.id}/artifact/{artifact_ref}/finding/{finding_id}"
43
- try:
44
- artifact = session.artifact(artifact_ref)
45
- except Exception:
46
- sources.append({
47
- "status": "missing",
48
- "title": f"Missing Marivo Finding {finding_id}",
49
- "locator": locator,
50
- "excerpt": None,
51
- "truncated": False,
52
- "finding_id": finding_id,
53
- "finding_type": None,
54
- "epistemic_kind": None,
55
- "artifact_ref": artifact_ref,
56
- "session_id": session.id,
57
- "canonical_item_key": None,
58
- "committed_at": None,
59
- "source_refs": [],
60
- "revalidation": None,
61
- })
62
- continue
63
- except Exception:
64
- sources.append({
65
- "status": "unsupported",
66
- "title": f"Unavailable Marivo Finding {finding_id}",
67
- "locator": locator,
68
- "excerpt": None,
69
- "truncated": False,
70
- "finding_id": finding_id,
71
- "finding_type": None,
72
- "epistemic_kind": None,
73
- "artifact_ref": artifact_ref,
74
- "session_id": session.id,
75
- "canonical_item_key": None,
76
- "committed_at": None,
77
- "source_refs": [],
78
- "revalidation": None,
79
- })
80
- continue
81
-
82
- revalidation = revalidation_projection(artifact)
83
- try:
84
- finding = artifact.finding(finding_id)
85
- except FindingNotFoundError:
86
- sources.append({
87
- "status": "missing",
88
- "title": f"Missing Marivo Finding {finding_id}",
89
- "locator": locator,
90
- "excerpt": None,
91
- "truncated": False,
92
- "finding_id": finding_id,
93
- "finding_type": None,
94
- "epistemic_kind": None,
95
- "artifact_ref": artifact.ref,
96
- "session_id": session.id,
97
- "canonical_item_key": None,
98
- "committed_at": None,
99
- "source_refs": [],
100
- "revalidation": revalidation,
101
- })
102
- continue
103
- except Exception:
104
- sources.append({
105
- "status": "unsupported",
106
- "title": f"Unavailable Marivo Finding {finding_id}",
107
- "locator": locator,
108
- "excerpt": None,
109
- "truncated": False,
110
- "finding_id": finding_id,
111
- "finding_type": None,
112
- "epistemic_kind": None,
113
- "artifact_ref": artifact.ref,
114
- "session_id": session.id,
115
- "canonical_item_key": None,
116
- "committed_at": None,
117
- "source_refs": [],
118
- "revalidation": revalidation,
119
- })
120
- continue
121
-
122
- if finding.session_id != session.id or finding.artifact_ref != artifact.ref:
123
- print(json.dumps({"kind": "evidence-identity-mismatch"}, sort_keys=True), file=sys.stderr)
124
- raise SystemExit(70)
125
-
126
- try:
127
- excerpt = finding.render(max_output_bytes=4096)
128
- status = "available"
129
- except Exception:
130
- excerpt = None
131
- status = "unsupported"
132
- sources.append({
133
- "status": status,
134
- "title": f"{finding.finding_type} Finding: {finding.canonical_item_key}",
135
- "locator": locator,
136
- "excerpt": excerpt,
137
- "truncated": excerpt is not None and "output truncated at " in excerpt,
138
- "finding_id": finding.finding_id,
139
- "finding_type": finding.finding_type,
140
- "epistemic_kind": finding.epistemic_kind,
141
- "artifact_ref": finding.artifact_ref,
142
- "session_id": finding.session_id,
143
- "canonical_item_key": finding.canonical_item_key,
144
- "committed_at": finding.committed_at.isoformat(),
145
- "source_refs": list(finding.source_refs),
146
- "revalidation": revalidation,
147
- })
148
-
149
- print(json.dumps({
150
- "session_id": session.id,
151
- "sources": sources,
152
- }, sort_keys=True))
153
- `.trim();
@@ -1,166 +0,0 @@
1
- import { MarivoEnvironmentError } from "../environment/errors.js";
2
- import { resolveMarivoBridgeSource } from "../environment/source.js";
3
- import { MARIVO_EVIDENCE_FINDINGS_PROGRAM } from "./bridge-program.js";
4
- const EVIDENCE_LIMITS = Object.freeze({
5
- timeoutMs: 30_000,
6
- stdoutMaxBytes: 1_048_576,
7
- stderrMaxBytes: 65_536,
8
- });
9
- function nonEmptyString(value, field, maxChars = 2_048) {
10
- if (typeof value !== 'string' || value.trim() === '' || value.length > maxChars) {
11
- throw new TypeError(`${field} must be a bounded non-empty string`);
12
- }
13
- return value;
14
- }
15
- function boundedText(value, field, maxBytes = 4_096) {
16
- const result = nonEmptyString(value, field, maxBytes);
17
- if (Buffer.byteLength(result, 'utf8') > maxBytes) {
18
- throw new TypeError(`${field} must be at most ${maxBytes} UTF-8 bytes`);
19
- }
20
- return result;
21
- }
22
- function nullableString(value, field, maxChars = 2_048) {
23
- return value === null ? null : nonEmptyString(value, field, maxChars);
24
- }
25
- function parseRevalidation(value) {
26
- if (value === null)
27
- return null;
28
- const item = jsonObject(value);
29
- if (item === undefined)
30
- throw new TypeError('revalidation must be an object or null');
31
- exactKeys(item, ['status', 'semantic_status', 'evidence_status', 'dependency_status'], 'revalidation');
32
- return {
33
- status: nonEmptyString(item.status, 'revalidation.status', 128),
34
- semanticStatus: nullableString(item.semantic_status, 'revalidation.semantic_status', 128),
35
- evidenceStatus: nullableString(item.evidence_status, 'revalidation.evidence_status', 128),
36
- dependencyStatus: nullableString(item.dependency_status, 'revalidation.dependency_status', 128),
37
- };
38
- }
39
- function jsonObject(value) {
40
- return typeof value === 'object' && value !== null && !Array.isArray(value)
41
- ? value
42
- : undefined;
43
- }
44
- function exactKeys(value, keys, field) {
45
- const expected = new Set(keys);
46
- if (Object.keys(value).some((key) => !expected.has(key)) || keys.some((key) => !(key in value))) {
47
- throw new TypeError(`${field} must contain exactly the expected fields`);
48
- }
49
- }
50
- function parseFinding(value) {
51
- const item = jsonObject(value);
52
- if (item === undefined)
53
- throw new TypeError('finding must be an object');
54
- exactKeys(item, [
55
- 'finding_id',
56
- 'status',
57
- 'title',
58
- 'locator',
59
- 'excerpt',
60
- 'truncated',
61
- 'finding_type',
62
- 'epistemic_kind',
63
- 'artifact_ref',
64
- 'session_id',
65
- 'canonical_item_key',
66
- 'committed_at',
67
- 'source_refs',
68
- 'revalidation',
69
- ], 'finding');
70
- if (!['available', 'missing', 'unsupported'].includes(String(item.status))) {
71
- throw new TypeError('status must be available, missing, or unsupported');
72
- }
73
- if (typeof item.truncated !== 'boolean')
74
- throw new TypeError('truncated must be boolean');
75
- if (!Array.isArray(item.source_refs) || item.source_refs.length > 100) {
76
- throw new TypeError('source_refs must be a bounded array');
77
- }
78
- const parsed = {
79
- status: item.status,
80
- title: boundedText(item.title, 'title', 2_048),
81
- locator: boundedText(item.locator, 'locator', 2_048),
82
- excerpt: item.excerpt === null ? null : boundedText(item.excerpt, 'excerpt'),
83
- truncated: item.truncated,
84
- findingId: nonEmptyString(item.finding_id, 'finding_id'),
85
- findingType: nullableString(item.finding_type, 'finding_type'),
86
- epistemicKind: nullableString(item.epistemic_kind, 'epistemic_kind'),
87
- artifactRef: nonEmptyString(item.artifact_ref, 'artifact_ref'),
88
- sessionId: nonEmptyString(item.session_id, 'finding session_id'),
89
- canonicalItemKey: nullableString(item.canonical_item_key, 'canonical_item_key'),
90
- committedAt: nullableString(item.committed_at, 'committed_at'),
91
- sourceRefs: item.source_refs.map((ref, index) => nonEmptyString(ref, `source_refs[${index}]`, 2_048)),
92
- revalidation: parseRevalidation(item.revalidation),
93
- };
94
- if ((parsed.status === 'available' &&
95
- (parsed.excerpt === null ||
96
- parsed.findingType === null ||
97
- parsed.epistemicKind === null ||
98
- parsed.canonicalItemKey === null ||
99
- parsed.committedAt === null)) ||
100
- (parsed.status === 'missing' &&
101
- (parsed.excerpt !== null ||
102
- parsed.truncated ||
103
- parsed.findingType !== null ||
104
- parsed.epistemicKind !== null ||
105
- parsed.canonicalItemKey !== null ||
106
- parsed.committedAt !== null)) ||
107
- (parsed.status === 'unsupported' && parsed.excerpt !== null) ||
108
- (parsed.truncated && parsed.excerpt === null)) {
109
- throw new TypeError('finding status fields are inconsistent');
110
- }
111
- return parsed;
112
- }
113
- function parseFindingsPayload(stdout, expectedSessionId, expectedSelections) {
114
- try {
115
- const root = jsonObject(JSON.parse(stdout.toString('utf8')));
116
- if (root !== undefined)
117
- exactKeys(root, ['session_id', 'sources'], 'root');
118
- if (root === undefined ||
119
- root.session_id !== expectedSessionId ||
120
- !Array.isArray(root.sources)) {
121
- throw new TypeError('root fields are invalid');
122
- }
123
- const findings = root.sources.map(parseFinding);
124
- if (findings.length !== expectedSelections.length)
125
- throw new TypeError('finding count differs');
126
- for (let index = 0; index < findings.length; index++) {
127
- const finding = findings[index];
128
- const selection = expectedSelections[index];
129
- if (finding === undefined ||
130
- selection === undefined ||
131
- finding.findingId !== selection.findingId ||
132
- finding.artifactRef !== selection.artifactRef ||
133
- finding.sessionId !== expectedSessionId) {
134
- throw new TypeError('finding identity or order differs');
135
- }
136
- }
137
- return findings;
138
- }
139
- catch (cause) {
140
- throw new MarivoEnvironmentError('subprocess-output-invalid', 'Marivo Evidence reader returned an invalid Finding payload', { stdoutBytes: stdout.byteLength }, { cause });
141
- }
142
- }
143
- /** Identity-checked adapter for exact persisted Marivo Findings. */
144
- export class MarivoEvidenceBridge {
145
- binding;
146
- #runner;
147
- constructor(runner) {
148
- this.#runner = runner;
149
- this.binding = runner.binding;
150
- }
151
- async findings(sessionId, selections, signal) {
152
- const result = await this.#runner.runChecked({
153
- program: MARIVO_EVIDENCE_FINDINGS_PROGRAM,
154
- args: [sessionId, JSON.stringify(selections)],
155
- limits: EVIDENCE_LIMITS,
156
- signal,
157
- });
158
- if (result.exitCode !== 0) {
159
- throw new MarivoEnvironmentError('subprocess-failed', `Marivo Evidence read failed with exit code ${String(result.exitCode)}`, { exitCode: result.exitCode, stderr: result.stderr.toString('utf8').slice(0, 2_000) });
160
- }
161
- return parseFindingsPayload(result.stdout, sessionId, selections);
162
- }
163
- }
164
- export function resolveMarivoEvidenceBridge(source) {
165
- return resolveMarivoBridgeSource(source);
166
- }
@@ -1,2 +0,0 @@
1
- export { MarivoEvidenceBridge, resolveMarivoEvidenceBridge, } from "./bridge.js";
2
- export { createMarivoEvidenceSourcesTool, evidenceSourcesMeta, installMarivoEvidenceSourcesCodeDelivery, MARIVO_EVIDENCE_SOURCES_DURABLE_CONTENT_KIND, MARIVO_EVIDENCE_SOURCES_MAX_PER_CALL, MARIVO_EVIDENCE_SOURCES_META_KIND, MARIVO_EVIDENCE_SOURCES_META_VERSION, MARIVO_EVIDENCE_SOURCES_TOOL_NAME, registerMarivoEvidenceSourcesTool, } from "./sources.js";