dsh-data-quality 0.2.0 → 0.3.1
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.
- package/CHANGELOG.md +14 -0
- package/README.es.md +51 -5
- package/README.hi.md +51 -5
- package/README.md +43 -3
- package/README.pt.md +51 -5
- package/README.zh.md +51 -5
- package/SECURITY.md +39 -0
- package/SUMMARY.md +147 -0
- package/lib/index.js +224 -25
- package/lib/types/events.d.ts +10 -10
- package/lib/types/events.js +10 -10
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +2 -0
- package/lib/types/index.js.map +1 -1
- package/lib/types/profile.d.ts +2 -0
- package/lib/types/profile.d.ts.map +1 -1
- package/lib/types/profile.js +2 -0
- package/lib/types/profile.js.map +1 -1
- package/lib/types/report-html.d.ts +41 -0
- package/lib/types/report-html.d.ts.map +1 -0
- package/lib/types/report-html.js +192 -0
- package/lib/types/report-html.js.map +1 -0
- package/lib/types/tools/profile-report-schema.d.ts +4 -0
- package/lib/types/tools/profile-report-schema.d.ts.map +1 -1
- package/lib/types/tools/profile-report-schema.js +1 -0
- package/lib/types/tools/profile-report-schema.js.map +1 -1
- package/lib/types/tools/report.d.ts.map +1 -1
- package/lib/types/tools/report.js +28 -2
- package/lib/types/tools/report.js.map +1 -1
- package/lib/types/version.d.ts +8 -1
- package/lib/types/version.d.ts.map +1 -1
- package/lib/types/version.js +8 -1
- package/lib/types/version.js.map +1 -1
- package/package.json +9 -2
- package/src/events.ts +11 -11
- package/src/index.ts +2 -0
- package/src/profile.ts +4 -0
- package/src/report-html.ts +208 -0
- package/src/tools/profile-report-schema.ts +1 -0
- package/src/tools/report.ts +31 -2
- package/src/version.ts +9 -1
package/SUMMARY.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# dsh-data-quality — Completion Summary
|
|
2
|
+
|
|
3
|
+
Standalone DeepSeek Harness plugin repository (`dsh-data-quality`): deterministic TypeScript data profiling / cleaning / verification for the agent harness, built as the full three-layer capability seam (Service Definition / local Provider / three model tool Consumers) with durable report storage and adaptive session events.
|
|
4
|
+
|
|
5
|
+
## Deliverables
|
|
6
|
+
|
|
7
|
+
### Capability seam
|
|
8
|
+
|
|
9
|
+
- **`ctx.dataQuality` Service Definition** (`src/service.ts`) — `DataQualityService extends Service`, registered under `dataQuality`. Exposes the frozen cross-plugin contract:
|
|
10
|
+
- `verifyCitations(request: CitationCheckRequest): Promise<CitationCheckResult>` — the byte-stable cross-plugin contract (§6.2 of the plugin spec), change only with an ecosystem migration.
|
|
11
|
+
- `profileDataset`, `cleanDataset`, `verifyDataset` — the internal report pipeline used by the tools.
|
|
12
|
+
- **Local deterministic Provider** (`src/provider-local.ts`) — no I/O in the engines, no clock (injected `now` / `freshness`), no RNG; TypeScript `private` fields only (ECMA `#` fields throw on cordis' proxied service receiver).
|
|
13
|
+
- **Consumers** (`src/tools/*.ts`) — `data_profile`, `data_clean`, `data_verify` `defineTool`s; all computation via the service; `workspaceOf(exec)` mirrors the official fs tools' session-cwd rule.
|
|
14
|
+
|
|
15
|
+
### Engines (pure, deterministic)
|
|
16
|
+
|
|
17
|
+
- `src/dataset.ts` — workspace-confined path resolution, size/row guards, hand-rolled CSV/TSV/JSON/JSONL parsers, deterministic systematic sampling, strict scalar parsers (`Cell = JsonValue`).
|
|
18
|
+
- `src/profile.ts` — row/column counts, inferred types, missing rates, unique counts, numeric distribution (min/max/mean/median/p25/p75), IQR outlier counts, mixed-type suspicion notes, duplicate-row counts, text rendering.
|
|
19
|
+
- `src/clean.ts` — six rule kinds, exactly the spec's list: `dedupe` (column group), `fill-missing` (constant/mean/median/forward), `coerce-type` (number/date/boolean with failure counts), `normalize-unit` (万/亿-style factor map), `trim`, `map-values` (enum mapping with `else: keep|missing`).
|
|
20
|
+
- `src/verify.ts` — seven rule kinds, exactly the spec's list: `not-null`, `unique`, `range`, `regex`, `enum`, `cross-column`, `freshness` (date column vs `asOf`, default injected clock) — plus `checkCitations`/`parseLocator`/`walkLocator` and the four verification states (`verified` / `mismatch` / `not-found` / `unverifiable`).
|
|
21
|
+
|
|
22
|
+
### Integration surfaces
|
|
23
|
+
|
|
24
|
+
- `src/store.ts` — `data_quality` storage domain (zod record schema, version 1, table `reports`), deterministic report key `YYYYMMDDHHmmssSSS-<kind>-<8-hex-sha256>`.
|
|
25
|
+
- `src/events.ts` — `data-quality/profile|clean|verify` in the `SessionEventMap` declaration merge. Adaptive append gate: known vocabulary → plain append; unknown vocabulary → probe the unbound `append` source for an `ignorable` marker and only then append with `{ ignorable: true }`; otherwise skip (the storage-domain report is always the durable copy). This is required because the rc.6 `Session.append` has no `ignorable` flag and no plugin event-registration surface exists, so an unknown appended type makes the persistence coordinator refuse the session log on restore.
|
|
26
|
+
- `src/config.ts` — Schemastery schema + explicit `resolveConfig` (no hidden `?? default`); numeric bounds fail loud at mount.
|
|
27
|
+
|
|
28
|
+
### Model tools (per plugin contract)
|
|
29
|
+
|
|
30
|
+
| Tool | Input | Output |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| `data_profile` | dataset path, sample? | row/column counts, per-column cards (type, missing, unique, numeric stats, notes), duplicate rows, reportKey |
|
|
33
|
+
| `data_clean` | dataset path, rules[], output path (optional, workspace-confined) | cleaned rows, per-rule audit log (affected rows), reportKey |
|
|
34
|
+
| `data_verify` | dataset path, rules[], evidence cap | verdict `passed`, per-rule pass/fail with evidence rows, reportKey |
|
|
35
|
+
|
|
36
|
+
## Configuration (cordis.yml `config`)
|
|
37
|
+
|
|
38
|
+
| Key | Default | Notes |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| `enabled` | `true` | master switch |
|
|
41
|
+
| `maxRows` | `200000` | row guard, fail loud |
|
|
42
|
+
| `maxFileSizeMB` | `64` | file size guard, fail loud |
|
|
43
|
+
| `defaultTolerance` | `1e-9` | numeric comparison relative tolerance |
|
|
44
|
+
| `evidenceRowLimit` | `20` | evidence rows per failed verify rule |
|
|
45
|
+
| `allowedExtensions` | `.csv .tsv .json .jsonl` | dataset file extensions |
|
|
46
|
+
| `workspaceRoot` | `''` | service-level citation checks resolve here; tools resolve in the session workspace |
|
|
47
|
+
| `storeReports` | `true` | persist reports to the `data_quality` storage domain |
|
|
48
|
+
|
|
49
|
+
All knobs are documented in the five-language README configuration tables and mirrored in `cordis.patch.yml` with inline comments.
|
|
50
|
+
|
|
51
|
+
## Acceptance
|
|
52
|
+
|
|
53
|
+
### Gate chain — re-run green on the final tree (2026-08-20)
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
pnpm run typecheck PASS tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit
|
|
57
|
+
pnpm run typecheck:ci PASS tsc -p tsconfig.ci.json --noEmit (published 0.1.0-rc.6 peers)
|
|
58
|
+
pnpm test PASS 112 tests / 8 files (clean 22, verify 28, dataset 25, plugin 10, citations 9, profile 8, events 6, config 4)
|
|
59
|
+
pnpm run build PASS lib/index.js 82.82 kB; fix-dts rewrote 11 files / 37 specifiers
|
|
60
|
+
pnpm run verify:self-contained PASS all dependency specs resolve from the registry
|
|
61
|
+
pnpm run verify:artifacts PASS syntax + ESM import + plugin face + no .ts leftovers + bundle patch present
|
|
62
|
+
pnpm run verify:readme-sync PASS all 5 READMEs share section structure and config keys
|
|
63
|
+
pnpm run pack:check PASS dsh-data-quality-0.1.0.tgz (lib/index.js + lib/types + cordis.patch.yml + READMEs + src)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`pnpm run test:coverage` thresholds (statements 90 / branches 80 / functions 90 / lines 90) pass.
|
|
67
|
+
|
|
68
|
+
### Real composition smokes
|
|
69
|
+
|
|
70
|
+
1. **Loader runner** (`node scripts/loader-runner.mjs .tmp/loader-smoke/cordis.yml fixtures`) — boots a real `Context` + vendored Loader with the Include builtin against the real storage seam (dsh-storage + dsh-storage-json + dsh-storage-domain), dsh-system-prompt, dsh-tools, and the BUILT `lib/index.js` bundle with `workspaceRoot` = fixtures dir. Keyless three-tool chain over the dirty fixture:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
DSH_LOADER_RESULT {"tools":["data_profile","data_clean","data_verify"],"profileRows":10,"profileColumns":6,"cleanOutputRows":8,"verifyPassed":false,"citationStatus":"verified"}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
profile 10 rows / 6 columns; clean (trim → dedupe → normalize-unit → coerce-type) drops 2 duplicate rows (8 out); verify `passed:false` is the correct verdict (the fixture's missing `holding_value` on FUND005 fails `range` — evidence flows); `verifyCitations` resolves a cited value from the CSV → `verified`.
|
|
77
|
+
|
|
78
|
+
2. **dsh-test-drive isolated install matrix (preferred path, run 2026-08-20)** — programmatic drive of the dsh-test-drive pipeline (`D:\deepseek-harness\Project\Plugins\dsh-test-drive\`, real `LocalSubprocessRuntime` → real `dsh` CLI + pnpm) against this checkout:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
verdict: pass
|
|
82
|
+
install pass dsh plugin add <checkout> ok (exit 0, allowBuildsNeeded: false)
|
|
83
|
+
config pass patchEffective: true, layers: ["dsh-data-quality"], full bundle patch visible in --dump-config
|
|
84
|
+
smoke boot-ok booted without loader failures; MISSING_CREDENTIAL (no API key) proves the tree mounted
|
|
85
|
+
capability skipped disabled by config and no per-drive spec (requires DEEPSEEK_API_KEY)
|
|
86
|
+
uninstall pass dsh plugin remove ok (exit 0)
|
|
87
|
+
cleanup pass owned temp root quarantined and removed
|
|
88
|
+
isolation hostHomeTouched: false, tempDshHome/tempWorkspace/tempStore: true
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
3. **Real dsh CLI temp-profile install** (earlier session, recorded here): `dsh plugin --profile dq add @deepseek-ai/dsh-base@0.1.0-rc.6 @deepseek-ai/dsh-headless@0.1.0-rc.6 ./dsh-data-quality-0.1.0.tgz` → install succeeds; `--dump-config` shows the bundle patch merging the storage rows + `dsh-data-quality` row; keyless headless exits with `MISSING_CREDENTIAL` (a pending service would hang to timeout instead); `dsh plugin remove` reverts cleanly.
|
|
92
|
+
|
|
93
|
+
## Commit history (13 commits, `main`)
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
d5e1c7b docs: record v0.1.0 release status
|
|
97
|
+
d9201d2 chore(release): 0.1.0
|
|
98
|
+
f2f95b7 fix: release script stamps a first release whose version is already set
|
|
99
|
+
3261e77 chore: keep loader-runner output byproduct untracked
|
|
100
|
+
433f9d4 docs: completion summary
|
|
101
|
+
6f9c4e5 docs: five-language READMEs and repo policy files
|
|
102
|
+
90ae5ed ci: ci/compat/release workflow trio
|
|
103
|
+
daca96f build: self-contained prepare/verify/release scripts and loader-runner smoke
|
|
104
|
+
8ad596d test: real-service vitest suite (112 specs) plus dirty-data fixtures
|
|
105
|
+
2048c6e feat: data_profile/data_clean/data_verify tools and plugin entry with fail-loud config
|
|
106
|
+
be634cd feat: ctx.dataQuality seam (frozen verifyCitations contract, local provider, storage domain, adaptive session events)
|
|
107
|
+
0be188f feat: deterministic dataset layer and pure engines (profile/clean/verify)
|
|
108
|
+
d6af7b6 chore: project scaffold (package manifest, tsconfig trio, build/test config)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Deviations from the plugin spec (vetted, intentional)
|
|
112
|
+
|
|
113
|
+
1. **Session events are adaptive, not unconditional.** The spec requires a `SessionEventMap` merge for model-visible content; that merge exists (`src/events.ts`). On rc.6 hosts the append surface has no `ignorable` flag and no plugin event-registration surface, so appending an unknown `data-quality/*` type would make the persistence coordinator refuse the session log on restore. The gate appends only when the host knows the vocabulary or supports the ignorable marker, and fails safe to skipping; the storage-domain report remains the durable record. (The original SUMMARY predated this refinement; the current code is authoritative.)
|
|
114
|
+
2. **Rule names match the spec verbatim.** The six clean rules (`dedupe`, `fill-missing`, `coerce-type`, `normalize-unit`, `trim`, `map-values`) and seven verify rules (`not-null`, `unique`, `range`, `regex`, `enum`, `cross-column`, `freshness`) use the spec's kebab-case names. An earlier SUMMARY draft described an intermediate snake_case rule set; the shipped code never shipped those names.
|
|
115
|
+
3. **Render shape is text, not a table.** The spec suggests a "generic + table render"; the tools use `generic` tools with a human-readable text summary in `output.render` (tables are ill-suited to the variable-width evidence rows). Semantics unchanged: canonical JSON in `output.schema`, human text in `output.render`.
|
|
116
|
+
4. **`workspaceRoot` added for the service plane.** Tool calls always resolve inside the session workspace (spec). `verifyCitations` has no session, so a `workspaceRoot` config (default: process launch directory) anchors service-level checks; it is fixed at provider construction.
|
|
117
|
+
5. **Extra config keys `enabled` / `storeReports`.** Both default on and are settable from cordis.yml — additions to, not replacements of, the spec's five keys.
|
|
118
|
+
6. **`MAX_CELL_TEXT` (120 chars) is a display-safety invariant**, not a tunable; documented in AGENTS.md.
|
|
119
|
+
7. **Push/publish did not happen in the development session.** The spec forbids push and publish here; `d9201d2`/`d5e1c7b` record the release session's stamp/status work, and the remote (`PerryLink/dsh-data-quality`) plus npm (`dsh-data-quality@0.1.0`, published 2026-08-19T13:54Z) were populated by that release session.
|
|
120
|
+
|
|
121
|
+
## Repo & release state
|
|
122
|
+
|
|
123
|
+
- 13 conventional commits on `main`, tag `v0.1.0`, working tree clean. Remote: `github.com/PerryLink/dsh-data-quality` (pushed by the release session).
|
|
124
|
+
- npm registry: `dsh-data-quality@0.1.0` published 2026-08-19T13:54Z (`latest` = 0.1.0); the earlier "npm publish skipped (no NPM_TOKEN)" note is superseded — the release session closed that gap.
|
|
125
|
+
- `dsh-data-quality-0.1.0.tgz` is gitignored and reproducible via `pnpm pack`.
|
|
126
|
+
|
|
127
|
+
## Known limitations & follow-up suggestions
|
|
128
|
+
|
|
129
|
+
- **Session events are best-effort on pre-rc.7 hosts**: on a host whose append lacks the `ignorable` marker, `data-quality/*` events are skipped rather than risking log-restore refusal; the storage-domain report remains the durable record. Revisit when the harness exposes a real plugin event-registration surface.
|
|
130
|
+
- **No fuzzy/LLM-based cleaning**: rule semantics are strictly deterministic by design; a future `data_clean` rule kind could delegate fuzzy matching to an LLM tool as an opt-in.
|
|
131
|
+
- **`workspaceRoot` is process-start-time**: the provider caches the resolved root at construction; a runtime configuration change requires remounting the plugin.
|
|
132
|
+
- **Numeric parsing is strict**: locale-formatted numbers (`"1,234.56"`) and currency strings are text until `coerce-type`/`normalize-unit` run.
|
|
133
|
+
- **Cross-column date comparison uses epoch fallback**: strings that do not parse as numbers fall back to `Date.parse`; unparseable pairs fall back to strict string equality (only for `==` / `!=`).
|
|
134
|
+
- **Evidence rows are truncated** by `MAX_CELL_TEXT` (120 chars).
|
|
135
|
+
|
|
136
|
+
## Project overview suggestion
|
|
137
|
+
|
|
138
|
+
Add one row to the Project/Plugins overview roster: `dsh-data-quality` — `ctx.dataQuality` three-layer seam (deterministic profiling/cleaning/verification) with `data_profile` / `data_clean` / `data_verify` tools; v0.1.0 on npm since 2026-08-19.
|
|
139
|
+
|
|
140
|
+
## Release-session handoff (PHASE2 §0.3 chain) — execution status
|
|
141
|
+
|
|
142
|
+
The chain was executed (2026-08-20) as far as the session's capabilities allow:
|
|
143
|
+
|
|
144
|
+
1. **Community feedback check** — DONE: GitHub API audit shows `PerryLink/dsh-data-quality` has 0 open/0 closed issues, 0 stars; no feedback to fold in before the next release.
|
|
145
|
+
2. **Standard item B (community engineering)** — DONE: all 8 GitHub topics are set (`dsh`, `dsh-plugin`, `deepseek-harness`, `cordis`, `data-quality`, `data-cleaning`, `data-profiling`, `data-verification` — mirror of `package.json` keywords); five-language READMEs pass `verify:readme-sync`; `THIRD_PARTY_NOTICES.md` current. The Project/Plugins overview (`D:\deepseek-harness\Project\Plugins\README.md`) now lists `dsh-data-quality` under "已发布 GitHub + npm" (30 projects / 13 published).
|
|
146
|
+
3. **Standard item A (ecosystem delivery)** — npm closed (`dsh-data-quality@0.1.0`, 2026-08-19T13:54Z). Ecosystem catalog submission is BLOCKED: community catalogs exist (`awesome-dsh-plugins/awesome-dsh-plugins` et al., none listing this plugin yet) but submitting requires GitHub write credentials — no `gh` CLI and no `GH_TOKEN`/`GITHUB_TOKEN` in this session; a release session with credentials should open the catalog PR.
|
|
147
|
+
4. **Standard item C (publish upload)** — CLOSED for 0.1.0: tag `v0.1.0`, GitHub Release (2026-08-19T13:45Z), npm publish (2026-08-19T13:54Z). `main` synced to origin (`d669a19`). For the next version: `node scripts/release.mjs <x.y.z>` (stamps CHANGELOG, re-runs the gate, commits + tags, never pushes), then push — `release.yml` publishes to npm with provenance and creates the GitHub Release from the stamped CHANGELOG section (needs the `NPM_TOKEN` secret configured on the repo).
|
package/lib/index.js
CHANGED
|
@@ -1165,6 +1165,22 @@ function computeAccuracy(stats, table, declaredSchema) {
|
|
|
1165
1165
|
};
|
|
1166
1166
|
}
|
|
1167
1167
|
//#endregion
|
|
1168
|
+
//#region src/version.ts
|
|
1169
|
+
/**
|
|
1170
|
+
* Plugin version, kept in one place so `scripts/release.mjs` can stamp it and
|
|
1171
|
+
* reports can name their generator.
|
|
1172
|
+
* @module dsh-data-quality/version
|
|
1173
|
+
*/
|
|
1174
|
+
/** The package version reported in persisted reports. */
|
|
1175
|
+
const VERSION = "0.3.1";
|
|
1176
|
+
/**
|
|
1177
|
+
* Version of the persisted report schema. Bump it whenever a report's
|
|
1178
|
+
* canonical shape changes in a way old consumers cannot read (the durable
|
|
1179
|
+
* `data_quality` records keep their own `schemaVersion` so a future reader
|
|
1180
|
+
* can detect and reject an incompatible record instead of misreading it).
|
|
1181
|
+
*/
|
|
1182
|
+
const REPORT_SCHEMA_VERSION = 1;
|
|
1183
|
+
//#endregion
|
|
1168
1184
|
//#region src/profile.ts
|
|
1169
1185
|
/**
|
|
1170
1186
|
* Deterministic dataset profiling: per-column type inference, missingness,
|
|
@@ -1345,6 +1361,7 @@ function profileTable(table, options) {
|
|
|
1345
1361
|
signal: options.signal
|
|
1346
1362
|
});
|
|
1347
1363
|
return {
|
|
1364
|
+
schemaVersion: 1,
|
|
1348
1365
|
dataset: options.dataset,
|
|
1349
1366
|
rowCount: table.rows.length,
|
|
1350
1367
|
sampled: profiled.length !== table.rows.length,
|
|
@@ -1983,14 +2000,14 @@ function checkCitations(root, citations, defaultTolerance) {
|
|
|
1983
2000
|
*
|
|
1984
2001
|
* - Hosts whose known-type set already covers the vocabulary (a future harness
|
|
1985
2002
|
* that adopts these events) append plainly.
|
|
1986
|
-
* - Hosts with an `ignorable` append option (
|
|
1987
|
-
*
|
|
1988
|
-
* marker, so builds that do not know the type skip the event on restore.
|
|
2003
|
+
* - Hosts with an `ignorable` append option (pre-0.1.2 rc builds) append with
|
|
2004
|
+
* the marker, so builds that do not know the type skip the event on restore.
|
|
1989
2005
|
* - 0.1.0-rc.6 and 0.1.0-rc.8 hosts have neither a registration surface nor an
|
|
1990
2006
|
* `ignorable` append option (rc.8's `Session.append` accepts surface metadata
|
|
1991
|
-
* only, never the marker)
|
|
1992
|
-
*
|
|
1993
|
-
* skipped and the storage-domain report remains the
|
|
2007
|
+
* only, never the marker), and 0.1.2-alpha.1 removed the `ignorable` envelope
|
|
2008
|
+
* entirely (42dc2a46c2) and fails closed on unknown types at read; on all of
|
|
2009
|
+
* them the append is skipped and the storage-domain report remains the
|
|
2010
|
+
* durable copy.
|
|
1994
2011
|
* @module dsh-data-quality/events
|
|
1995
2012
|
*/
|
|
1996
2013
|
/** The event type vocabulary this plugin appends. */
|
|
@@ -2003,10 +2020,10 @@ const DATA_QUALITY_EVENT_TYPES = [
|
|
|
2003
2020
|
* Append one `data-quality/*` event when the host can carry it safely; skip
|
|
2004
2021
|
* silently otherwise (the storage-domain report is always the durable copy).
|
|
2005
2022
|
* The `ignorable` probe reads the UNBOUND method's source (a `.bind()` result
|
|
2006
|
-
* reports `[native code]`): the rc.6
|
|
2007
|
-
* handling while
|
|
2008
|
-
* survive minification, so the probe fails safe (skips)
|
|
2009
|
-
* a log.
|
|
2023
|
+
* reports `[native code]`): the rc.6/rc.8 builds and 0.1.2-alpha.1 contain no
|
|
2024
|
+
* `ignorable` handling while pre-0.1.2 master builds referenced the flag by
|
|
2025
|
+
* name; property names survive minification, so the probe fails safe (skips)
|
|
2026
|
+
* rather than corrupting a log.
|
|
2010
2027
|
* @param session - the calling session.
|
|
2011
2028
|
* @param type - the event type.
|
|
2012
2029
|
* @param data - the payload.
|
|
@@ -2540,6 +2557,10 @@ const COLUMN_PROFILE_SCHEMA = {
|
|
|
2540
2557
|
const PROFILE_REPORT_SCHEMA = {
|
|
2541
2558
|
type: "object",
|
|
2542
2559
|
properties: {
|
|
2560
|
+
schemaVersion: {
|
|
2561
|
+
type: "number",
|
|
2562
|
+
required: true
|
|
2563
|
+
},
|
|
2543
2564
|
dataset: {
|
|
2544
2565
|
type: "string",
|
|
2545
2566
|
required: true
|
|
@@ -3537,6 +3558,168 @@ function defineVerifyTool(service) {
|
|
|
3537
3558
|
});
|
|
3538
3559
|
}
|
|
3539
3560
|
//#endregion
|
|
3561
|
+
//#region src/report-html.ts
|
|
3562
|
+
/** Escape text for safe embedding in an HTML document. */
|
|
3563
|
+
function escapeHtml(text) {
|
|
3564
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
3565
|
+
}
|
|
3566
|
+
/** Render a 0..1 rate as a percentage string, or `—` when undetermined. */
|
|
3567
|
+
function pct(score) {
|
|
3568
|
+
return score === null ? "—" : `${(score * 100).toFixed(1)}%`;
|
|
3569
|
+
}
|
|
3570
|
+
/** The shared document shell: inline CSS + inline JS, no external requests. */
|
|
3571
|
+
function shell(title, body, script) {
|
|
3572
|
+
return [
|
|
3573
|
+
"<!doctype html>",
|
|
3574
|
+
"<html lang=\"en\">",
|
|
3575
|
+
"<head>",
|
|
3576
|
+
"<meta charset=\"utf-8\">",
|
|
3577
|
+
`<title>${escapeHtml(title)}</title>`,
|
|
3578
|
+
"<style>",
|
|
3579
|
+
" :root { --ink: #1a1f2e; --muted: #6b7280; --line: #e5e7eb; --accent: #0f766e; --fail: #b91c1c; --warn: #b45309; --pass: #15803d; }",
|
|
3580
|
+
" * { box-sizing: border-box; }",
|
|
3581
|
+
" body { margin: 0; padding: 24px; font: 14px/1.5 ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif; color: var(--ink); background: #f8fafc; }",
|
|
3582
|
+
" header { margin-bottom: 20px; }",
|
|
3583
|
+
" h1 { font-size: 20px; margin: 0 0 4px; }",
|
|
3584
|
+
" .meta { color: var(--muted); font-size: 12px; }",
|
|
3585
|
+
" section { background: #fff; border: 1px solid var(--line); border-radius: 8px; padding: 16px 20px; margin-bottom: 16px; }",
|
|
3586
|
+
" h2 { font-size: 15px; margin: 0 0 12px; }",
|
|
3587
|
+
" table { border-collapse: collapse; width: 100%; font-size: 13px; }",
|
|
3588
|
+
" th, td { text-align: left; padding: 6px 10px; border-top: 1px solid var(--line); vertical-align: top; }",
|
|
3589
|
+
" th { color: var(--muted); font-weight: 600; }",
|
|
3590
|
+
" .score-cell { font-variant-numeric: tabular-nums; }",
|
|
3591
|
+
" .dim-fail { color: var(--fail); font-weight: 600; }",
|
|
3592
|
+
" .dim-warn { color: var(--warn); }",
|
|
3593
|
+
" .dim-pass { color: var(--pass); }",
|
|
3594
|
+
" .dim-undetermined { color: var(--muted); }",
|
|
3595
|
+
" button { cursor: pointer; font: inherit; }",
|
|
3596
|
+
"</style>",
|
|
3597
|
+
"</head>",
|
|
3598
|
+
"<body>",
|
|
3599
|
+
body,
|
|
3600
|
+
"<script>",
|
|
3601
|
+
script,
|
|
3602
|
+
"<\/script>",
|
|
3603
|
+
"</body>",
|
|
3604
|
+
"</html>",
|
|
3605
|
+
""
|
|
3606
|
+
].join("\n");
|
|
3607
|
+
}
|
|
3608
|
+
/** The DAMA six-dimension scorecard section. */
|
|
3609
|
+
function scorecardSection(report) {
|
|
3610
|
+
const rows = report.scorecard.dimensions.map((dimension) => {
|
|
3611
|
+
const cls = dimension.score === null ? "dim-undetermined" : dimension.score >= .9 ? "dim-pass" : dimension.score >= .7 ? "dim-warn" : "dim-fail";
|
|
3612
|
+
return `<tr><td>${escapeHtml(dimension.name)}</td><td class="score-cell ${cls}">${pct(dimension.score)}</td><td>${escapeHtml(dimension.note)}</td></tr>`;
|
|
3613
|
+
}).join("\n");
|
|
3614
|
+
const overall = report.scorecard.overall;
|
|
3615
|
+
const weighted = report.scorecard.weightedOverall;
|
|
3616
|
+
return [
|
|
3617
|
+
"<section>",
|
|
3618
|
+
"<h2>DAMA six-dimension quality scorecard</h2>",
|
|
3619
|
+
"<table>",
|
|
3620
|
+
"<thead><tr><th>Dimension</th><th>Score</th><th>Note</th></tr></thead>",
|
|
3621
|
+
"<tbody>",
|
|
3622
|
+
rows,
|
|
3623
|
+
"</tbody>",
|
|
3624
|
+
"</table>",
|
|
3625
|
+
`<p class="meta" id="summary-text">overall ${pct(overall)} · weighted ${pct(weighted)}</p>`,
|
|
3626
|
+
"</section>"
|
|
3627
|
+
].join("\n");
|
|
3628
|
+
}
|
|
3629
|
+
/** The per-column profile summary table. */
|
|
3630
|
+
function columnsSection(report) {
|
|
3631
|
+
return [
|
|
3632
|
+
"<section>",
|
|
3633
|
+
"<h2>Column profile</h2>",
|
|
3634
|
+
"<table>",
|
|
3635
|
+
"<thead><tr><th>Column</th><th>Type</th><th>Missing</th><th>Missing rate</th><th>Unique</th><th>Numeric distribution</th><th>Top values</th><th>Notes</th></tr></thead>",
|
|
3636
|
+
"<tbody>",
|
|
3637
|
+
report.columns.map((column) => {
|
|
3638
|
+
const numeric = column.numeric;
|
|
3639
|
+
const numericCell = numeric === void 0 ? "—" : `min ${numeric.min} · p25 ${numeric.p25} · median ${numeric.median} · p75 ${numeric.p75} · max ${numeric.max} · mean ${numeric.mean}${numeric.outliers > 0 ? ` · ${numeric.outliers} IQR outliers` : ""}`;
|
|
3640
|
+
const top = column.topValues === void 0 ? "—" : column.topValues.map((entry) => `${escapeHtml(entry.value)} ×${entry.count}`).join(", ");
|
|
3641
|
+
const notes = column.notes.length === 0 ? "" : `<p class="meta">${column.notes.map(escapeHtml).join("; ")}</p>`;
|
|
3642
|
+
return [
|
|
3643
|
+
"<tr>",
|
|
3644
|
+
`<td>${escapeHtml(column.name)}</td>`,
|
|
3645
|
+
`<td>${escapeHtml(column.inferredType)}</td>`,
|
|
3646
|
+
`<td class="score-cell">${column.missing}</td>`,
|
|
3647
|
+
`<td class="score-cell">${(column.missingRate * 100).toFixed(1)}%</td>`,
|
|
3648
|
+
`<td class="score-cell">${column.unique}</td>`,
|
|
3649
|
+
`<td>${numericCell}</td>`,
|
|
3650
|
+
`<td>${top}</td>`,
|
|
3651
|
+
`<td>${notes}</td>`,
|
|
3652
|
+
"</tr>"
|
|
3653
|
+
].join("");
|
|
3654
|
+
}).join("\n"),
|
|
3655
|
+
"</tbody>",
|
|
3656
|
+
"</table>",
|
|
3657
|
+
"</section>"
|
|
3658
|
+
].join("\n");
|
|
3659
|
+
}
|
|
3660
|
+
/**
|
|
3661
|
+
* Render a profile report as a self-contained offline HTML document.
|
|
3662
|
+
* @param report - the profile report (already persisted/returned by data_profile).
|
|
3663
|
+
* @returns the complete single-file HTML.
|
|
3664
|
+
*/
|
|
3665
|
+
function renderProfileHtml(report) {
|
|
3666
|
+
const body = [
|
|
3667
|
+
"<header>",
|
|
3668
|
+
`<h1>Data profile: ${escapeHtml(report.dataset)}</h1>`,
|
|
3669
|
+
`<p class="meta">${report.rowCount} rows × ${report.columnCount} columns · generated ${new Date(report.generatedAt).toISOString()} · schema v1 · report ${report.reportKey ?? "(unpersisted)"}</p>`,
|
|
3670
|
+
"<button id=\"copy-summary\" type=\"button\">Copy summary</button>",
|
|
3671
|
+
"</header>",
|
|
3672
|
+
scorecardSection(report),
|
|
3673
|
+
columnsSection(report)
|
|
3674
|
+
].join("\n");
|
|
3675
|
+
const script = [
|
|
3676
|
+
"const button = document.getElementById('copy-summary');",
|
|
3677
|
+
"if (button) {",
|
|
3678
|
+
" button.addEventListener(\"click\", () => {",
|
|
3679
|
+
" const text = document.getElementById(\"summary-text\");",
|
|
3680
|
+
" if (text && navigator.clipboard) navigator.clipboard.writeText(text.textContent || \"\");",
|
|
3681
|
+
" });",
|
|
3682
|
+
"}"
|
|
3683
|
+
].join("\n");
|
|
3684
|
+
return shell(`Data profile: ${report.dataset}`, body, script);
|
|
3685
|
+
}
|
|
3686
|
+
/** The per-rule cleaning summary table (for clean/clean-diff reports). */
|
|
3687
|
+
function cleaningSection(report) {
|
|
3688
|
+
const rows = report.logs.map((log) => {
|
|
3689
|
+
return `<tr><td>${escapeHtml(log.rule)}</td><td class="score-cell">${log.affectedRows}</td><td>${escapeHtml(log.detail)}</td></tr>`;
|
|
3690
|
+
}).join("\n");
|
|
3691
|
+
const removed = report.inputRows - report.outputRows;
|
|
3692
|
+
return [
|
|
3693
|
+
"<section>",
|
|
3694
|
+
"<h2>Cleaning summary</h2>",
|
|
3695
|
+
`<p class="meta" id="summary-text">input ${report.inputRows} rows · output ${report.outputRows} rows · removed ${removed} rows</p>`,
|
|
3696
|
+
"<table>",
|
|
3697
|
+
"<thead><tr><th>Rule</th><th>Affected rows</th><th>Detail</th></tr></thead>",
|
|
3698
|
+
"<tbody>",
|
|
3699
|
+
rows,
|
|
3700
|
+
"</tbody>",
|
|
3701
|
+
"</table>",
|
|
3702
|
+
"</section>"
|
|
3703
|
+
].join("\n");
|
|
3704
|
+
}
|
|
3705
|
+
/**
|
|
3706
|
+
* Render a clean report as a self-contained offline HTML document (the
|
|
3707
|
+
* per-rule cleaning summary table).
|
|
3708
|
+
* @param report - the clean report (logs + input/output row counts).
|
|
3709
|
+
* @param dataset - the dataset label for the document title.
|
|
3710
|
+
* @returns the complete single-file HTML.
|
|
3711
|
+
*/
|
|
3712
|
+
function renderCleanHtml(report, dataset) {
|
|
3713
|
+
const body = [
|
|
3714
|
+
"<header>",
|
|
3715
|
+
`<h1>Cleaning report: ${escapeHtml(dataset)}</h1>`,
|
|
3716
|
+
`<p class="meta">schema v1</p>`,
|
|
3717
|
+
"</header>",
|
|
3718
|
+
cleaningSection(report)
|
|
3719
|
+
].join("\n");
|
|
3720
|
+
return shell(`Cleaning report: ${dataset}`, body, "// no interactive behavior needed; everything renders without external requests\n");
|
|
3721
|
+
}
|
|
3722
|
+
//#endregion
|
|
3540
3723
|
//#region src/tools/report.ts
|
|
3541
3724
|
/**
|
|
3542
3725
|
* The `data_report` model tool: read persisted profile/clean-diff reports
|
|
@@ -3552,6 +3735,12 @@ const REPORT_KINDS = [
|
|
|
3552
3735
|
"verify",
|
|
3553
3736
|
"citations"
|
|
3554
3737
|
];
|
|
3738
|
+
/** Render one stored report as a self-contained HTML document (profile/clean only). */
|
|
3739
|
+
function renderRecordHtml(record) {
|
|
3740
|
+
if (record.kind === "profile") return renderProfileHtml(record.report);
|
|
3741
|
+
if (record.kind === "clean" || record.kind === "clean-diff") return renderCleanHtml(record.report, record.dataset);
|
|
3742
|
+
throw new Error(`data_report html format does not support kind "${record.kind}" (profile/clean only)`);
|
|
3743
|
+
}
|
|
3555
3744
|
/** Project a stored report into the canonical value (the stored report is already lossless JSON). */
|
|
3556
3745
|
function toView(record) {
|
|
3557
3746
|
return {
|
|
@@ -3592,6 +3781,11 @@ function defineReportTool(service) {
|
|
|
3592
3781
|
type: "string",
|
|
3593
3782
|
enum: [...REPORT_KINDS],
|
|
3594
3783
|
description: "Report kind to list (profile/clean/clean-diff/verify/citations)."
|
|
3784
|
+
},
|
|
3785
|
+
format: {
|
|
3786
|
+
type: "string",
|
|
3787
|
+
enum: ["json", "html"],
|
|
3788
|
+
description: "Output format. json (default) returns the report envelope(s); html renders one report as a self-contained offline HTML document (requires key; profile/clean only)."
|
|
3595
3789
|
}
|
|
3596
3790
|
},
|
|
3597
3791
|
output: {
|
|
@@ -3633,25 +3827,39 @@ function defineReportTool(service) {
|
|
|
3633
3827
|
additionalProperties: false
|
|
3634
3828
|
},
|
|
3635
3829
|
required: true
|
|
3830
|
+
},
|
|
3831
|
+
html: {
|
|
3832
|
+
type: "string",
|
|
3833
|
+
description: "Self-contained offline HTML (present only when format: html)."
|
|
3636
3834
|
}
|
|
3637
3835
|
},
|
|
3638
3836
|
additionalProperties: false
|
|
3639
3837
|
},
|
|
3640
|
-
render: (_args, value) =>
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3838
|
+
render: (_args, value) => {
|
|
3839
|
+
const view = value;
|
|
3840
|
+
if (view.html !== void 0) return [{
|
|
3841
|
+
type: "text",
|
|
3842
|
+
text: view.html
|
|
3843
|
+
}];
|
|
3844
|
+
return [{
|
|
3845
|
+
type: "text",
|
|
3846
|
+
text: renderReportText(view)
|
|
3847
|
+
}];
|
|
3848
|
+
}
|
|
3644
3849
|
},
|
|
3645
3850
|
async execute(args, _exec) {
|
|
3646
3851
|
const hasKey = args.key !== void 0;
|
|
3647
3852
|
if (hasKey === (args.kind !== void 0)) throw new Error("data_report needs exactly one of key/kind");
|
|
3853
|
+
const format = args.format ?? "json";
|
|
3648
3854
|
if (hasKey) {
|
|
3649
3855
|
const record = await service.getReport(args.key);
|
|
3650
3856
|
return {
|
|
3651
3857
|
key: args.key,
|
|
3652
|
-
records: [toView(record)]
|
|
3858
|
+
records: [toView(record)],
|
|
3859
|
+
...format === "html" ? { html: renderRecordHtml(record) } : {}
|
|
3653
3860
|
};
|
|
3654
3861
|
}
|
|
3862
|
+
if (format === "html") throw new Error("data_report html format requires key (exactly one report)");
|
|
3655
3863
|
const records = await service.listReports(args.kind);
|
|
3656
3864
|
return {
|
|
3657
3865
|
kind: args.kind,
|
|
@@ -3661,15 +3869,6 @@ function defineReportTool(service) {
|
|
|
3661
3869
|
});
|
|
3662
3870
|
}
|
|
3663
3871
|
//#endregion
|
|
3664
|
-
//#region src/version.ts
|
|
3665
|
-
/**
|
|
3666
|
-
* Plugin version, kept in one place so `scripts/release.mjs` can stamp it and
|
|
3667
|
-
* reports can name their generator.
|
|
3668
|
-
* @module dsh-data-quality/version
|
|
3669
|
-
*/
|
|
3670
|
-
/** The package version reported in persisted reports. */
|
|
3671
|
-
const VERSION = "0.2.0";
|
|
3672
|
-
//#endregion
|
|
3673
3872
|
//#region src/index.ts
|
|
3674
3873
|
const name = "data-quality";
|
|
3675
3874
|
/** The four model tools and the durable report domain. */
|
|
@@ -3723,4 +3922,4 @@ async function apply(ctx, config = {}) {
|
|
|
3723
3922
|
}
|
|
3724
3923
|
}
|
|
3725
3924
|
//#endregion
|
|
3726
|
-
export { Config, DATA_QUALITY_EVENT_TYPES, DataQualityService, DatasetError, INDUSTRY_PRESETS, INDUSTRY_PRESET_IDS, LocalDataQualityService, MAX_CELL_TEXT, VERSION, VerifyExpectationError, appendDataQualityEvent, apply, applyCleanRules, checkCitations, computeCleanContract, computeCleanProfileDiff, computeScorecard, countDuplicateRows, dataQualityDomainSpec, dateFormatOf, detectDuplicateRows, detectEncoding, inject, isMissing, isValidReportKey, loadDocument, loadTable, name, numericProfile, parseBoolean, parseDate, parseDateCell, parseDelimited, parseJsonTable, parseLocator, parseNumeric, profileTable, readDatasetFile, renderProfileText, renderVerifyText, reportKeyOf, reportRecordSchema, resolveConfig, resolveIndustryPreset, resolveWorkspacePath, sampleRows, serializeDelimited, truncateCell, truncateRow, verifyExpectations, verifyTable };
|
|
3925
|
+
export { Config, DATA_QUALITY_EVENT_TYPES, DataQualityService, DatasetError, INDUSTRY_PRESETS, INDUSTRY_PRESET_IDS, LocalDataQualityService, MAX_CELL_TEXT, REPORT_SCHEMA_VERSION, VERSION, VerifyExpectationError, appendDataQualityEvent, apply, applyCleanRules, checkCitations, computeCleanContract, computeCleanProfileDiff, computeScorecard, countDuplicateRows, dataQualityDomainSpec, dateFormatOf, detectDuplicateRows, detectEncoding, inject, isMissing, isValidReportKey, loadDocument, loadTable, name, numericProfile, parseBoolean, parseDate, parseDateCell, parseDelimited, parseJsonTable, parseLocator, parseNumeric, profileTable, readDatasetFile, renderCleanHtml, renderProfileHtml, renderProfileText, renderVerifyText, reportKeyOf, reportRecordSchema, resolveConfig, resolveIndustryPreset, resolveWorkspacePath, sampleRows, serializeDelimited, truncateCell, truncateRow, verifyExpectations, verifyTable };
|
package/lib/types/events.d.ts
CHANGED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
*
|
|
6
6
|
* - Hosts whose known-type set already covers the vocabulary (a future harness
|
|
7
7
|
* that adopts these events) append plainly.
|
|
8
|
-
* - Hosts with an `ignorable` append option (
|
|
9
|
-
*
|
|
10
|
-
* marker, so builds that do not know the type skip the event on restore.
|
|
8
|
+
* - Hosts with an `ignorable` append option (pre-0.1.2 rc builds) append with
|
|
9
|
+
* the marker, so builds that do not know the type skip the event on restore.
|
|
11
10
|
* - 0.1.0-rc.6 and 0.1.0-rc.8 hosts have neither a registration surface nor an
|
|
12
11
|
* `ignorable` append option (rc.8's `Session.append` accepts surface metadata
|
|
13
|
-
* only, never the marker)
|
|
14
|
-
*
|
|
15
|
-
* skipped and the storage-domain report remains the
|
|
12
|
+
* only, never the marker), and 0.1.2-alpha.1 removed the `ignorable` envelope
|
|
13
|
+
* entirely (42dc2a46c2) and fails closed on unknown types at read; on all of
|
|
14
|
+
* them the append is skipped and the storage-domain report remains the
|
|
15
|
+
* durable copy.
|
|
16
16
|
* @module dsh-data-quality/events
|
|
17
17
|
*/
|
|
18
18
|
import { type Session } from '@deepseek-ai/dsh-session';
|
|
@@ -65,10 +65,10 @@ export type DataQualityEventType = (typeof DATA_QUALITY_EVENT_TYPES)[number];
|
|
|
65
65
|
* Append one `data-quality/*` event when the host can carry it safely; skip
|
|
66
66
|
* silently otherwise (the storage-domain report is always the durable copy).
|
|
67
67
|
* The `ignorable` probe reads the UNBOUND method's source (a `.bind()` result
|
|
68
|
-
* reports `[native code]`): the rc.6
|
|
69
|
-
* handling while
|
|
70
|
-
* survive minification, so the probe fails safe (skips)
|
|
71
|
-
* a log.
|
|
68
|
+
* reports `[native code]`): the rc.6/rc.8 builds and 0.1.2-alpha.1 contain no
|
|
69
|
+
* `ignorable` handling while pre-0.1.2 master builds referenced the flag by
|
|
70
|
+
* name; property names survive minification, so the probe fails safe (skips)
|
|
71
|
+
* rather than corrupting a log.
|
|
72
72
|
* @param session - the calling session.
|
|
73
73
|
* @param type - the event type.
|
|
74
74
|
* @param data - the payload.
|
package/lib/types/events.js
CHANGED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
*
|
|
6
6
|
* - Hosts whose known-type set already covers the vocabulary (a future harness
|
|
7
7
|
* that adopts these events) append plainly.
|
|
8
|
-
* - Hosts with an `ignorable` append option (
|
|
9
|
-
*
|
|
10
|
-
* marker, so builds that do not know the type skip the event on restore.
|
|
8
|
+
* - Hosts with an `ignorable` append option (pre-0.1.2 rc builds) append with
|
|
9
|
+
* the marker, so builds that do not know the type skip the event on restore.
|
|
11
10
|
* - 0.1.0-rc.6 and 0.1.0-rc.8 hosts have neither a registration surface nor an
|
|
12
11
|
* `ignorable` append option (rc.8's `Session.append` accepts surface metadata
|
|
13
|
-
* only, never the marker)
|
|
14
|
-
*
|
|
15
|
-
* skipped and the storage-domain report remains the
|
|
12
|
+
* only, never the marker), and 0.1.2-alpha.1 removed the `ignorable` envelope
|
|
13
|
+
* entirely (42dc2a46c2) and fails closed on unknown types at read; on all of
|
|
14
|
+
* them the append is skipped and the storage-domain report remains the
|
|
15
|
+
* durable copy.
|
|
16
16
|
* @module dsh-data-quality/events
|
|
17
17
|
*/
|
|
18
18
|
import { KNOWN_SESSION_EVENT_TYPES } from '@deepseek-ai/dsh-session';
|
|
@@ -22,10 +22,10 @@ export const DATA_QUALITY_EVENT_TYPES = ['data-quality/profile', 'data-quality/c
|
|
|
22
22
|
* Append one `data-quality/*` event when the host can carry it safely; skip
|
|
23
23
|
* silently otherwise (the storage-domain report is always the durable copy).
|
|
24
24
|
* The `ignorable` probe reads the UNBOUND method's source (a `.bind()` result
|
|
25
|
-
* reports `[native code]`): the rc.6
|
|
26
|
-
* handling while
|
|
27
|
-
* survive minification, so the probe fails safe (skips)
|
|
28
|
-
* a log.
|
|
25
|
+
* reports `[native code]`): the rc.6/rc.8 builds and 0.1.2-alpha.1 contain no
|
|
26
|
+
* `ignorable` handling while pre-0.1.2 master builds referenced the flag by
|
|
27
|
+
* name; property names survive minification, so the probe fails safe (skips)
|
|
28
|
+
* rather than corrupting a log.
|
|
29
29
|
* @param session - the calling session.
|
|
30
30
|
* @param type - the event type.
|
|
31
31
|
* @param data - the payload.
|
package/lib/types/index.d.ts
CHANGED
|
@@ -37,6 +37,8 @@ export { DatasetError, loadTable, loadDocument, readDatasetFile, detectEncoding,
|
|
|
37
37
|
export { dataQualityDomainSpec, reportKeyOf, reportRecordSchema, isValidReportKey, type ReportRecord, type ReportStore, type StoredReport } from './store.js';
|
|
38
38
|
export { DATA_QUALITY_EVENT_TYPES, appendDataQualityEvent, type DataQualityEventData, type DataQualityEventType } from './events.js';
|
|
39
39
|
export { MAX_CELL_TEXT, truncateCell, truncateRow } from './present.js';
|
|
40
|
+
export { renderProfileHtml, renderCleanHtml, type CleanReportHtml } from './report-html.js';
|
|
41
|
+
export { REPORT_SCHEMA_VERSION } from './version.js';
|
|
40
42
|
/**
|
|
41
43
|
* Mount the seam: resolve config (fail loud), open the report domain, publish
|
|
42
44
|
* `ctx.dataQuality`, and register the three tools. With `enabled: false` the
|
package/lib/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,EAAE,MAAM,EAAiB,MAAM,aAAa,CAAA;AASnD,eAAO,MAAM,IAAI,iBAAiB,CAAA;AAClC,0DAA0D;AAC1D,eAAO,MAAM,MAAM,UAA6B,CAAA;AAEhD,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACnD,YAAY,EAAE,MAAM,IAAI,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAChG,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EACL,kBAAkB,EAClB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,uBAAuB,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAChF,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACtE,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,KAAK,oBAAoB,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC/H,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAClH,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1J,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACtG,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AACvH,OAAO,EAAE,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,KAAK,kBAAkB,EAAE,KAAK,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAClI,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAChH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAChE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EACL,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,eAAe,EACf,cAAc,EACd,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,SAAS,EACT,YAAY,EACZ,SAAS,EACT,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,KAAK,KAAK,EACV,KAAK,GAAG,EACR,KAAK,IAAI,EACT,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAA;AAC7J,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,KAAK,oBAAoB,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACpI,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/lib/types/index.js
CHANGED
|
@@ -39,6 +39,8 @@ export { DatasetError, loadTable, loadDocument, readDatasetFile, detectEncoding,
|
|
|
39
39
|
export { dataQualityDomainSpec, reportKeyOf, reportRecordSchema, isValidReportKey } from "./store.js";
|
|
40
40
|
export { DATA_QUALITY_EVENT_TYPES, appendDataQualityEvent } from "./events.js";
|
|
41
41
|
export { MAX_CELL_TEXT, truncateCell, truncateRow } from "./present.js";
|
|
42
|
+
export { renderProfileHtml, renderCleanHtml } from "./report-html.js";
|
|
43
|
+
export { REPORT_SCHEMA_VERSION } from "./version.js";
|
|
42
44
|
/**
|
|
43
45
|
* Mount the seam: resolve config (fail loud), open the report domain, publish
|
|
44
46
|
* `ctx.dataQuality`, and register the three tools. With `enabled: false` the
|
package/lib/types/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,OAAO,EAAU,aAAa,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAoB,MAAM,YAAY,CAAA;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,CAAC,MAAM,IAAI,GAAG,cAAc,CAAA;AAClC,0DAA0D;AAC1D,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;AAEhD,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEnD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EACL,kBAAkB,GAOnB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,uBAAuB,EAAqB,MAAM,qBAAqB,CAAA;AAEhF,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAoD,MAAM,eAAe,CAAA;AAG/H,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACtG,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AACvH,OAAO,EAAE,gBAAgB,EAAmF,MAAM,gBAAgB,CAAA;AAClI,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,qBAAqB,EAAuB,MAAM,cAAc,CAAA;AAChH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAChE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EACL,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,eAAe,EACf,cAAc,EACd,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,SAAS,EACT,YAAY,EACZ,SAAS,EACT,aAAa,EACb,YAAY,EACZ,YAAY,GAQb,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,kBAAkB,EAAE,gBAAgB,EAA0D,MAAM,YAAY,CAAA;AAC7J,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAwD,MAAM,aAAa,CAAA;AACpI,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/lib/types/profile.d.ts
CHANGED
|
@@ -55,6 +55,8 @@ export interface DuplicateDetection {
|
|
|
55
55
|
}
|
|
56
56
|
/** The full profile report (also the persisted and tool-returned value). */
|
|
57
57
|
export interface ProfileReport {
|
|
58
|
+
/** The persisted-report schema version (see {@link REPORT_SCHEMA_VERSION}). */
|
|
59
|
+
readonly schemaVersion: number;
|
|
58
60
|
readonly dataset: string;
|
|
59
61
|
readonly rowCount: number;
|
|
60
62
|
/** Whether column cards describe a systematic sample rather than every row. */
|