@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
@@ -1,449 +0,0 @@
1
- ;((scope) => {
2
- const datasets = new Map()
3
- const recordViews = new Map()
4
- const DATASET_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/
5
- const TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/
6
- const ARTIFACT_ROLES = new Set(['time', 'dimension', 'value', 'measure', 'unknown'])
7
- const ISSUE_CATEGORIES = new Set([
8
- 'data_quality',
9
- 'comparability',
10
- 'evidence_availability',
11
- 'candidate_resolution',
12
- ])
13
-
14
- class ReportDataError extends Error {
15
- constructor(code, path, message) {
16
- super(`${path}: ${message}`)
17
- this.name = 'ReportDataError'
18
- this.code = code
19
- this.path = path
20
- }
21
- }
22
-
23
- function fail(path, message, code = 'dataset-invalid') {
24
- throw new ReportDataError(code, path, message)
25
- }
26
-
27
- function isObject(value) {
28
- return typeof value === 'object' && value !== null && !Array.isArray(value)
29
- }
30
-
31
- function object(value, path) {
32
- if (!isObject(value)) fail(path, 'must be an object')
33
- return value
34
- }
35
-
36
- function exactKeys(value, path, required, optional = []) {
37
- const keys = Object.keys(value)
38
- const allowed = new Set([...required, ...optional])
39
- for (const key of required) {
40
- if (!Object.hasOwn(value, key)) fail(`${path}.${key}`, 'is required')
41
- }
42
- for (const key of keys) {
43
- if (!allowed.has(key)) fail(`${path}.${key}`, 'is not allowed')
44
- }
45
- }
46
-
47
- function string(value, path, { nullable = false, maxLength = 2048 } = {}) {
48
- if (nullable && value === null) return
49
- if (typeof value !== 'string' || value.length === 0 || value.length > maxLength) {
50
- fail(path, `must be a non-empty string of at most ${maxLength} characters`)
51
- }
52
- }
53
-
54
- function integer(value, path, { nullable = false, maximum = Number.MAX_SAFE_INTEGER } = {}) {
55
- if (nullable && value === null) return
56
- if (!Number.isSafeInteger(value) || value < 0 || value > maximum) {
57
- fail(path, `must be an integer between 0 and ${maximum}`)
58
- }
59
- }
60
-
61
- function number(value, path, { nullable = false } = {}) {
62
- if (nullable && value === null) return
63
- if (typeof value !== 'number' || !Number.isFinite(value)) fail(path, 'must be a finite number')
64
- }
65
-
66
- function timestamp(value, path) {
67
- if (
68
- typeof value !== 'string' ||
69
- !TIMESTAMP.test(value) ||
70
- !Number.isFinite(Date.parse(value))
71
- ) {
72
- fail(path, 'must be an RFC 3339 timestamp')
73
- }
74
- }
75
-
76
- function stringArray(value, path, maximum = 100) {
77
- if (!Array.isArray(value) || value.length > maximum) {
78
- fail(path, `must be an array with at most ${maximum} items`)
79
- }
80
- value.forEach((item, index) => {
81
- string(item, `${path}[${index}]`)
82
- })
83
- }
84
-
85
- function validateRepair(value, path, nullable) {
86
- if (nullable && value === null) return
87
- const repair = object(value, path)
88
- exactKeys(repair, path, ['kind', 'action', 'help_target'])
89
- if (
90
- !['retry', 'inspect', 'user_choice', 'semantic_authoring', 'environment'].includes(
91
- repair.kind,
92
- )
93
- ) {
94
- fail(`${path}.kind`, 'is unsupported')
95
- }
96
- string(repair.action, `${path}.action`)
97
- string(repair.help_target, `${path}.help_target`)
98
- }
99
-
100
- function validateIssue(value, path, allowEvidenceRule = false) {
101
- const issue = object(value, path)
102
- string(issue.category, `${path}.category`)
103
- if (allowEvidenceRule && issue.category === 'evidence_rule') {
104
- exactKeys(issue, path, ['category', 'kind', 'severity', 'expected', 'received', 'repair'])
105
- string(issue.kind, `${path}.kind`)
106
- if (!['warning', 'blocking'].includes(issue.severity))
107
- fail(`${path}.severity`, 'is unsupported')
108
- string(issue.expected, `${path}.expected`)
109
- string(issue.received, `${path}.received`)
110
- validateRepair(issue.repair, `${path}.repair`, false)
111
- return
112
- }
113
- if (!ISSUE_CATEGORIES.has(issue.category)) fail(`${path}.category`, 'is unsupported')
114
- if (issue.category === 'data_quality') {
115
- exactKeys(issue, path, ['category', 'kind', 'severity', 'check_id', 'expectation', 'repair'])
116
- string(issue.check_id, `${path}.check_id`)
117
- string(issue.expectation, `${path}.expectation`)
118
- } else if (issue.category === 'comparability') {
119
- exactKeys(issue, path, [
120
- 'category',
121
- 'kind',
122
- 'severity',
123
- 'incompatible_fields',
124
- 'approximation_details',
125
- 'repair',
126
- ])
127
- stringArray(issue.incompatible_fields, `${path}.incompatible_fields`)
128
- stringArray(issue.approximation_details, `${path}.approximation_details`)
129
- } else if (issue.category === 'evidence_availability') {
130
- exactKeys(issue, path, [
131
- 'category',
132
- 'kind',
133
- 'severity',
134
- 'failed_stage',
135
- 'findings_available',
136
- 'stable_error_category',
137
- 'repair',
138
- ])
139
- if (!['extract', 'digest', 'store'].includes(issue.failed_stage)) {
140
- fail(`${path}.failed_stage`, 'is unsupported')
141
- }
142
- if (typeof issue.findings_available !== 'boolean') {
143
- fail(`${path}.findings_available`, 'must be boolean')
144
- }
145
- string(issue.stable_error_category, `${path}.stable_error_category`)
146
- } else {
147
- exactKeys(issue, path, ['category', 'kind', 'severity', 'historical', 'repair'])
148
- if (issue.severity !== 'warning') fail(`${path}.severity`, 'must be warning')
149
- if (typeof issue.historical !== 'boolean') fail(`${path}.historical`, 'must be boolean')
150
- }
151
- string(issue.kind, `${path}.kind`)
152
- if (!['warning', 'blocking'].includes(issue.severity))
153
- fail(`${path}.severity`, 'is unsupported')
154
- validateRepair(issue.repair, `${path}.repair`, issue.category !== 'candidate_resolution')
155
- }
156
-
157
- function validateQuality(value, path) {
158
- if (value === null) return
159
- const quality = object(value, path)
160
- const fields = [
161
- 'coverage',
162
- 'null_rate',
163
- 'sample_size',
164
- 'sample_coverage_min',
165
- 'sample_coverage_avg',
166
- 'sample_coverage_partial_buckets',
167
- 'zero_denominator_rows',
168
- 'evaluated_check_count',
169
- 'failed_check_count',
170
- 'warning_check_count',
171
- ]
172
- exactKeys(quality, path, fields)
173
- for (const field of ['coverage', 'null_rate', 'sample_coverage_min', 'sample_coverage_avg']) {
174
- number(quality[field], `${path}.${field}`, { nullable: true })
175
- }
176
- for (const field of fields
177
- .slice(2)
178
- .filter((field) => !['sample_coverage_min', 'sample_coverage_avg'].includes(field))) {
179
- integer(quality[field], `${path}.${field}`, { nullable: true })
180
- }
181
- }
182
-
183
- function validateRevalidation(value, path) {
184
- const revalidation = object(value, path)
185
- string(revalidation.status, `${path}.status`)
186
- if (revalidation.status === 'not_checked') {
187
- exactKeys(revalidation, path, ['status'])
188
- return
189
- }
190
- if (revalidation.status !== 'checked') fail(`${path}.status`, 'is unsupported')
191
- exactKeys(revalidation, path, [
192
- 'status',
193
- 'result',
194
- 'semantic_status',
195
- 'evidence_status',
196
- 'dependency_status',
197
- 'checked_at',
198
- 'issues',
199
- 'issues_omitted',
200
- ])
201
- if (!['admissible', 'stale', 'indeterminate'].includes(revalidation.result)) {
202
- fail(`${path}.result`, 'is unsupported')
203
- }
204
- if (!['current', 'stale', 'indeterminate'].includes(revalidation.semantic_status)) {
205
- fail(`${path}.semantic_status`, 'is unsupported')
206
- }
207
- if (!['complete', 'partial', 'unavailable'].includes(revalidation.evidence_status)) {
208
- fail(`${path}.evidence_status`, 'is unsupported')
209
- }
210
- if (!['admissible', 'stale', 'indeterminate'].includes(revalidation.dependency_status)) {
211
- fail(`${path}.dependency_status`, 'is unsupported')
212
- }
213
- timestamp(revalidation.checked_at, `${path}.checked_at`)
214
- if (!Array.isArray(revalidation.issues) || revalidation.issues.length > 100) {
215
- fail(`${path}.issues`, 'must contain at most 100 issues')
216
- }
217
- revalidation.issues.forEach((issue, index) => {
218
- validateIssue(issue, `${path}.issues[${index}]`, true)
219
- })
220
- integer(revalidation.issues_omitted, `${path}.issues_omitted`)
221
- }
222
-
223
- function validateSource(value, path, table) {
224
- const source = object(value, path)
225
- string(source.kind, `${path}.kind`)
226
- if (source.kind === 'computed') {
227
- exactKeys(source, path, ['kind'])
228
- if (Object.hasOwn(table, 'semantic_shape')) {
229
- fail('$.table.semantic_shape', 'is not allowed for a computed dataset')
230
- }
231
- return 'computed'
232
- }
233
- if (source.kind !== 'marivo_artifact') fail(`${path}.kind`, 'is unsupported')
234
- exactKeys(source, path, [
235
- 'kind',
236
- 'detail',
237
- 'artifact',
238
- 'quality_summary',
239
- 'issues',
240
- 'issues_omitted',
241
- 'lineage',
242
- 'revalidation',
243
- ])
244
- if (!['reader', 'audit'].includes(source.detail)) fail(`${path}.detail`, 'is unsupported')
245
- const artifact = object(source.artifact, `${path}.artifact`)
246
- exactKeys(artifact, `${path}.artifact`, [
247
- 'session_id',
248
- 'ref',
249
- 'kind',
250
- 'artifact_schema_version',
251
- 'content_hash',
252
- 'created_at',
253
- 'row_count',
254
- 'evidence_status',
255
- 'finding_count',
256
- ])
257
- for (const field of ['session_id', 'ref', 'kind', 'artifact_schema_version']) {
258
- string(artifact[field], `${path}.artifact.${field}`)
259
- }
260
- string(artifact.content_hash, `${path}.artifact.content_hash`, { nullable: true })
261
- timestamp(artifact.created_at, `${path}.artifact.created_at`)
262
- integer(artifact.row_count, `${path}.artifact.row_count`)
263
- integer(artifact.finding_count, `${path}.artifact.finding_count`)
264
- if (!['complete', 'partial', 'unavailable'].includes(artifact.evidence_status)) {
265
- fail(`${path}.artifact.evidence_status`, 'is unsupported')
266
- }
267
- validateQuality(source.quality_summary, `${path}.quality_summary`)
268
- if (!Array.isArray(source.issues) || source.issues.length > 100) {
269
- fail(`${path}.issues`, 'must contain at most 100 issues')
270
- }
271
- source.issues.forEach((issue, index) => {
272
- validateIssue(issue, `${path}.issues[${index}]`)
273
- })
274
- integer(source.issues_omitted, `${path}.issues_omitted`)
275
- const lineage = object(source.lineage, `${path}.lineage`)
276
- exactKeys(lineage, `${path}.lineage`, [
277
- 'external_inputs',
278
- 'external_inputs_omitted',
279
- 'steps',
280
- 'steps_omitted',
281
- ])
282
- stringArray(lineage.external_inputs, `${path}.lineage.external_inputs`)
283
- integer(lineage.external_inputs_omitted, `${path}.lineage.external_inputs_omitted`)
284
- if (!Array.isArray(lineage.steps) || lineage.steps.length > 100) {
285
- fail(`${path}.lineage.steps`, 'must contain at most 100 steps')
286
- }
287
- lineage.steps.forEach((candidate, index) => {
288
- const stepPath = `${path}.lineage.steps[${index}]`
289
- const step = object(candidate, stepPath)
290
- exactKeys(step, stepPath, [
291
- 'intent',
292
- 'job_ref',
293
- 'inputs',
294
- 'params_digest',
295
- 'analysis_purpose',
296
- ])
297
- string(step.intent, `${stepPath}.intent`)
298
- string(step.job_ref, `${stepPath}.job_ref`)
299
- stringArray(step.inputs, `${stepPath}.inputs`)
300
- string(step.params_digest, `${stepPath}.params_digest`)
301
- string(step.analysis_purpose, `${stepPath}.analysis_purpose`, { nullable: true })
302
- })
303
- integer(lineage.steps_omitted, `${path}.lineage.steps_omitted`)
304
- validateRevalidation(source.revalidation, `${path}.revalidation`)
305
- if (!Object.hasOwn(table, 'semantic_shape')) {
306
- fail('$.table.semantic_shape', 'is required for an Artifact dataset')
307
- }
308
- string(table.semantic_shape, '$.table.semantic_shape', { nullable: true })
309
- if (artifact.row_count !== table.total_rows) {
310
- fail(`${path}.artifact.row_count`, 'must equal $.table.total_rows')
311
- }
312
- return 'marivo_artifact'
313
- }
314
-
315
- function validateDataset(value, registrationId) {
316
- const dataset = object(value, '$')
317
- exactKeys(dataset, '$', ['schema', 'dataset_id', 'emitted_at', 'source', 'table'])
318
- if (dataset.schema !== 'dsh-data-analysis-dataset/v2') fail('$.schema', 'is unsupported')
319
- if (typeof dataset.dataset_id !== 'string' || !DATASET_ID.test(dataset.dataset_id)) {
320
- fail('$.dataset_id', 'is invalid')
321
- }
322
- if (dataset.dataset_id !== registrationId) {
323
- fail('$.dataset_id', 'must match the registered id', 'dataset-id-mismatch')
324
- }
325
- timestamp(dataset.emitted_at, '$.emitted_at')
326
- const table = object(dataset.table, '$.table')
327
- exactKeys(
328
- table,
329
- '$.table',
330
- ['total_rows', 'written_rows', 'omitted_rows', 'columns', 'rows'],
331
- ['semantic_shape'],
332
- )
333
- integer(table.total_rows, '$.table.total_rows')
334
- integer(table.written_rows, '$.table.written_rows', { maximum: 100000 })
335
- integer(table.omitted_rows, '$.table.omitted_rows')
336
- if (table.total_rows !== table.written_rows + table.omitted_rows) {
337
- fail('$.table.total_rows', 'must equal written_rows + omitted_rows')
338
- }
339
- if (!Array.isArray(table.columns) || table.columns.length > 100) {
340
- fail('$.table.columns', 'must contain at most 100 columns')
341
- }
342
- const sourceKind = validateSource(dataset.source, '$.source', table)
343
- const names = new Set()
344
- table.columns.forEach((candidate, index) => {
345
- const columnPath = `$.table.columns[${index}]`
346
- const column = object(candidate, columnPath)
347
- const computedKeys = ['name', 'dtype', 'contains_null']
348
- const artifactKeys = [...computedKeys, 'artifact_dtype', 'nullable', 'role']
349
- exactKeys(column, columnPath, sourceKind === 'computed' ? computedKeys : artifactKeys)
350
- string(column.name, `${columnPath}.name`)
351
- string(column.dtype, `${columnPath}.dtype`)
352
- if (names.has(column.name)) fail(`${columnPath}.name`, 'must be unique')
353
- names.add(column.name)
354
- if (typeof column.contains_null !== 'boolean')
355
- fail(`${columnPath}.contains_null`, 'must be boolean')
356
- if (sourceKind === 'marivo_artifact') {
357
- string(column.artifact_dtype, `${columnPath}.artifact_dtype`)
358
- if (typeof column.nullable !== 'boolean') fail(`${columnPath}.nullable`, 'must be boolean')
359
- if (!ARTIFACT_ROLES.has(column.role)) fail(`${columnPath}.role`, 'is unsupported')
360
- }
361
- })
362
- if (!Array.isArray(table.rows) || table.rows.length > 100000) {
363
- fail('$.table.rows', 'must contain at most 100000 rows')
364
- }
365
- if (table.rows.length !== table.written_rows) {
366
- fail('$.table.written_rows', 'must equal rows.length')
367
- }
368
- table.rows.forEach((row, rowIndex) => {
369
- const rowPath = `$.table.rows[${rowIndex}]`
370
- if (!Array.isArray(row) || row.length !== table.columns.length) {
371
- fail(rowPath, `must contain exactly ${table.columns.length} cells`)
372
- }
373
- row.forEach((cell, cellIndex) => {
374
- if (!['string', 'number', 'boolean'].includes(typeof cell) && cell !== null) {
375
- fail(`${rowPath}[${cellIndex}]`, 'must be a JSON scalar')
376
- }
377
- if (typeof cell === 'number' && !Number.isFinite(cell)) {
378
- fail(`${rowPath}[${cellIndex}]`, 'must be finite')
379
- }
380
- })
381
- })
382
- return dataset
383
- }
384
-
385
- function deepFreeze(value, seen = new WeakSet()) {
386
- if (!isObject(value) && !Array.isArray(value)) return value
387
- if (seen.has(value)) return value
388
- seen.add(value)
389
- for (const child of Object.values(value)) deepFreeze(child, seen)
390
- return Object.freeze(value)
391
- }
392
-
393
- function validateId(id) {
394
- if (typeof id !== 'string' || !DATASET_ID.test(id)) {
395
- fail('$id', 'is invalid', 'dataset-id-invalid')
396
- }
397
- }
398
-
399
- function register(id, dataset) {
400
- validateId(id)
401
- if (datasets.has(id)) fail('$id', 'is already registered', 'dataset-id-duplicate')
402
- datasets.set(id, deepFreeze(validateDataset(dataset, id)))
403
- }
404
-
405
- function get(id) {
406
- validateId(id)
407
- const dataset = datasets.get(id)
408
- if (!dataset) fail('$id', 'is not registered', 'dataset-not-found')
409
- return dataset
410
- }
411
-
412
- function records(id) {
413
- if (recordViews.has(id)) return recordViews.get(id)
414
- const dataset = get(id)
415
- const names = dataset.table.columns.map((column) => column.name)
416
- const recordsForId = dataset.table.rows.map((row) => {
417
- const record = {}
418
- names.forEach((name, index) => {
419
- Object.defineProperty(record, name, {
420
- configurable: false,
421
- enumerable: true,
422
- value: row[index],
423
- writable: false,
424
- })
425
- })
426
- return Object.freeze(record)
427
- })
428
- const frozen = Object.freeze(recordsForId)
429
- recordViews.set(id, frozen)
430
- return frozen
431
- }
432
-
433
- function has(id) {
434
- validateId(id)
435
- return datasets.has(id)
436
- }
437
-
438
- function list() {
439
- return Object.freeze([...datasets.keys()])
440
- }
441
-
442
- const api = Object.freeze({ get, has, list, records, register })
443
- Object.defineProperty(scope, 'ReportData', {
444
- configurable: false,
445
- enumerable: true,
446
- value: api,
447
- writable: false,
448
- })
449
- })(globalThis)