@duckcodeailabs/dql-core 1.6.20 → 1.6.22
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/dist/apps/dashboard-document.d.ts +41 -0
- package/dist/apps/dashboard-document.d.ts.map +1 -1
- package/dist/apps/dashboard-document.js +109 -0
- package/dist/apps/dashboard-document.js.map +1 -1
- package/dist/apps/index.d.ts +1 -1
- package/dist/apps/index.d.ts.map +1 -1
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js.map +1 -1
- package/dist/contracts/registry.d.ts +25 -1
- package/dist/contracts/registry.d.ts.map +1 -1
- package/dist/contracts/registry.js +104 -12
- package/dist/contracts/registry.js.map +1 -1
- package/dist/contracts/types.d.ts +55 -0
- package/dist/contracts/types.d.ts.map +1 -1
- package/dist/contracts/types.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lineage/builder.d.ts.map +1 -1
- package/dist/lineage/builder.js +12 -0
- package/dist/lineage/builder.js.map +1 -1
- package/dist/lineage/column-lineage.d.ts +27 -0
- package/dist/lineage/column-lineage.d.ts.map +1 -1
- package/dist/lineage/column-lineage.js +147 -0
- package/dist/lineage/column-lineage.js.map +1 -1
- package/dist/lineage/derivation.d.ts +111 -0
- package/dist/lineage/derivation.d.ts.map +1 -0
- package/dist/lineage/derivation.js +177 -0
- package/dist/lineage/derivation.js.map +1 -0
- package/dist/lineage/impact.d.ts +127 -0
- package/dist/lineage/impact.d.ts.map +1 -0
- package/dist/lineage/impact.js +305 -0
- package/dist/lineage/impact.js.map +1 -0
- package/dist/lineage/index.d.ts +3 -1
- package/dist/lineage/index.d.ts.map +1 -1
- package/dist/lineage/index.js +3 -1
- package/dist/lineage/index.js.map +1 -1
- package/dist/manifest/builder.d.ts +16 -0
- package/dist/manifest/builder.d.ts.map +1 -1
- package/dist/manifest/builder.js +141 -11
- package/dist/manifest/builder.js.map +1 -1
- package/dist/manifest/dbt-freshness.d.ts +65 -0
- package/dist/manifest/dbt-freshness.d.ts.map +1 -0
- package/dist/manifest/dbt-freshness.js +264 -0
- package/dist/manifest/dbt-freshness.js.map +1 -0
- package/dist/manifest/domain-writer.d.ts +66 -0
- package/dist/manifest/domain-writer.d.ts.map +1 -0
- package/dist/manifest/domain-writer.js +114 -0
- package/dist/manifest/domain-writer.js.map +1 -0
- package/dist/manifest/index.d.ts +4 -1
- package/dist/manifest/index.d.ts.map +1 -1
- package/dist/manifest/index.js +3 -0
- package/dist/manifest/index.js.map +1 -1
- package/dist/manifest/output-drift.d.ts +31 -0
- package/dist/manifest/output-drift.d.ts.map +1 -0
- package/dist/manifest/output-drift.js +97 -0
- package/dist/manifest/output-drift.js.map +1 -0
- package/dist/manifest/types.d.ts +156 -1
- package/dist/manifest/types.d.ts.map +1 -1
- package/dist/parser/parser.d.ts.map +1 -1
- package/dist/parser/parser.js +8 -0
- package/dist/parser/parser.js.map +1 -1
- package/dist/semantic/analyzer.d.ts +8 -0
- package/dist/semantic/analyzer.d.ts.map +1 -1
- package/dist/semantic/analyzer.js +8 -0
- package/dist/semantic/analyzer.js.map +1 -1
- package/dist/semantic/conflicts.d.ts +33 -0
- package/dist/semantic/conflicts.d.ts.map +1 -0
- package/dist/semantic/conflicts.js +270 -0
- package/dist/semantic/conflicts.js.map +1 -0
- package/dist/semantic/index.d.ts +1 -1
- package/dist/semantic/index.d.ts.map +1 -1
- package/dist/semantic/index.js +1 -1
- package/dist/semantic/index.js.map +1 -1
- package/dist/trust/index.d.ts +3 -0
- package/dist/trust/index.d.ts.map +1 -0
- package/dist/trust/index.js +2 -0
- package/dist/trust/index.js.map +1 -0
- package/dist/trust/labels.d.ts +122 -0
- package/dist/trust/labels.d.ts.map +1 -0
- package/dist/trust/labels.js +185 -0
- package/dist/trust/labels.js.map +1 -0
- package/package.json +5 -1
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Show your work" — consumer-facing derivation walk.
|
|
3
|
+
*
|
|
4
|
+
* A derivation walk is the plain-language story of how a single certified (or
|
|
5
|
+
* generated) answer was produced: the value, the governed block that owns it,
|
|
6
|
+
* the business terms and metrics/dimensions it draws on, the dbt model/source
|
|
7
|
+
* it ultimately reads from, and the freshness/owner/review state that makes it
|
|
8
|
+
* trustworthy.
|
|
9
|
+
*
|
|
10
|
+
* It is NOT the raw author lineage graph. It deliberately hides depth: a flat,
|
|
11
|
+
* ordered list of steps the UI can reveal one level at a time. The structured
|
|
12
|
+
* payload is assembled entirely from data that already exists —
|
|
13
|
+
* `queryBusiness360` (businessDefinition / businessComposition /
|
|
14
|
+
* technicalSources / consumers / gaps / evidence) plus the answer's source
|
|
15
|
+
* block governance fields — so no lineage is rebuilt and no schema changes.
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_MAX_PER_KIND = 3;
|
|
18
|
+
/**
|
|
19
|
+
* Assemble a consumer-facing derivation walk from an already-computed
|
|
20
|
+
* `queryBusiness360` result plus the answer's source block. Pure and
|
|
21
|
+
* synchronous — safe to call from a browser bundle.
|
|
22
|
+
*/
|
|
23
|
+
export function buildDerivationWalk(input) {
|
|
24
|
+
const { business360, block, value, generated = false } = input;
|
|
25
|
+
const maxPerKind = input.maxPerKind ?? DEFAULT_MAX_PER_KIND;
|
|
26
|
+
const focus = business360.focus;
|
|
27
|
+
const steps = [];
|
|
28
|
+
// 1) Value — the thing the consumer actually asked about.
|
|
29
|
+
if (value) {
|
|
30
|
+
steps.push({
|
|
31
|
+
kind: 'value',
|
|
32
|
+
name: value,
|
|
33
|
+
detail: focus.name ? `Reported by ${focus.name}.` : undefined,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
// 2) Block / business asset that owns the answer.
|
|
37
|
+
const blockOwner = block?.owner ?? focus.owner;
|
|
38
|
+
const blockStatus = (block?.status ?? focus.status);
|
|
39
|
+
const reviewCadence = block?.reviewCadence ?? metadataString(focus.metadata, 'reviewCadence');
|
|
40
|
+
steps.push({
|
|
41
|
+
kind: 'block',
|
|
42
|
+
name: focus.name,
|
|
43
|
+
owner: blockOwner,
|
|
44
|
+
status: blockStatus,
|
|
45
|
+
detail: blockDetail({
|
|
46
|
+
reviewCadence,
|
|
47
|
+
businessOutcome: block?.businessOutcome ?? metadataString(focus.metadata, 'businessOutcome'),
|
|
48
|
+
decisionUse: block?.decisionUse,
|
|
49
|
+
}),
|
|
50
|
+
});
|
|
51
|
+
// 3) Business terms that define the language of the answer.
|
|
52
|
+
const termAssets = uniqueByName([
|
|
53
|
+
...business360.businessDefinition.terms,
|
|
54
|
+
...business360.businessDefinition.definedByTerms,
|
|
55
|
+
]);
|
|
56
|
+
for (const term of termAssets.slice(0, maxPerKind)) {
|
|
57
|
+
if (term.id === focus.id)
|
|
58
|
+
continue;
|
|
59
|
+
steps.push({
|
|
60
|
+
kind: 'term',
|
|
61
|
+
name: term.name,
|
|
62
|
+
owner: term.owner,
|
|
63
|
+
detail: 'Business term this answer is defined in.',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// 4) Metrics / dimensions referenced by the block (semantic layer).
|
|
67
|
+
for (const metric of dedupeNames(block?.metricRefs).slice(0, maxPerKind)) {
|
|
68
|
+
steps.push({ kind: 'metric', name: metric, detail: 'Governed metric used in the calculation.' });
|
|
69
|
+
}
|
|
70
|
+
for (const dimension of dedupeNames(block?.dimensionRefs).slice(0, maxPerKind)) {
|
|
71
|
+
steps.push({ kind: 'dimension', name: dimension, detail: 'Dimension used to slice the value.' });
|
|
72
|
+
}
|
|
73
|
+
// 5) dbt models / sources — the technical floor of the trust chain.
|
|
74
|
+
for (const model of business360.technicalSources.dbtModels.slice(0, maxPerKind)) {
|
|
75
|
+
steps.push({
|
|
76
|
+
kind: 'model',
|
|
77
|
+
name: model.name,
|
|
78
|
+
detail: 'dbt model the certified SQL builds on.',
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
const sourceAssets = uniqueByName([
|
|
82
|
+
...business360.technicalSources.dbtSources,
|
|
83
|
+
...business360.technicalSources.sourceTables,
|
|
84
|
+
]);
|
|
85
|
+
for (const source of sourceAssets.slice(0, maxPerKind)) {
|
|
86
|
+
steps.push({
|
|
87
|
+
kind: 'source',
|
|
88
|
+
name: source.name,
|
|
89
|
+
detail: 'Raw source table the data originates from.',
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const caveats = dedupeNames(block?.caveats ?? metadataStringArray(focus.metadata, 'caveats'));
|
|
93
|
+
return {
|
|
94
|
+
value,
|
|
95
|
+
summary: buildSummary({ focus, blockOwner, reviewCadence, generated, sourceAssets }),
|
|
96
|
+
steps,
|
|
97
|
+
trustLabel: input.trustLabel ?? (generated ? 'review_required' : undefined),
|
|
98
|
+
// Explicit `freshness` input wins; otherwise derive a marker from the
|
|
99
|
+
// block's upstream data health, then fall back to any focus metadata.
|
|
100
|
+
freshness: input.freshness ??
|
|
101
|
+
freshnessFromDataState(block?.dataState, block?.dataStateDetail) ??
|
|
102
|
+
metadataString(focus.metadata, 'freshness'),
|
|
103
|
+
caveats: caveats.length > 0 ? caveats : undefined,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Render a derivation-walk freshness marker from a block's `dataState`. Returns
|
|
108
|
+
* `undefined` for `fresh`/`unknown`/missing so a healthy or un-instrumented
|
|
109
|
+
* block shows no freshness downgrade.
|
|
110
|
+
*/
|
|
111
|
+
function freshnessFromDataState(dataState, detail) {
|
|
112
|
+
switch (dataState) {
|
|
113
|
+
case 'failed':
|
|
114
|
+
return detail ? `upstream failed — ${detail}` : 'upstream failed';
|
|
115
|
+
case 'stale':
|
|
116
|
+
return detail ? `stale data — ${detail}` : 'stale data';
|
|
117
|
+
default:
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function blockDetail(input) {
|
|
122
|
+
const parts = [];
|
|
123
|
+
if (input.businessOutcome)
|
|
124
|
+
parts.push(input.businessOutcome);
|
|
125
|
+
else if (input.decisionUse)
|
|
126
|
+
parts.push(`Supports: ${input.decisionUse}.`);
|
|
127
|
+
if (input.reviewCadence)
|
|
128
|
+
parts.push(`Reviewed ${input.reviewCadence}.`);
|
|
129
|
+
return parts.length > 0 ? parts.join(' ') : undefined;
|
|
130
|
+
}
|
|
131
|
+
function buildSummary(input) {
|
|
132
|
+
const ownerPhrase = input.blockOwner ? ` owned by ${input.blockOwner}` : '';
|
|
133
|
+
const sourcePhrase = input.sourceAssets.length > 0
|
|
134
|
+
? ` It traces back to ${input.sourceAssets[0].name}.`
|
|
135
|
+
: '';
|
|
136
|
+
if (input.generated) {
|
|
137
|
+
return `This value was generated from ${input.focus.name}${ownerPhrase} and still needs analyst review before it can be certified.${sourcePhrase}`;
|
|
138
|
+
}
|
|
139
|
+
const cadencePhrase = input.reviewCadence ? `, reviewed ${input.reviewCadence}` : '';
|
|
140
|
+
return `This value comes from the certified ${input.focus.name}${ownerPhrase}${cadencePhrase}.${sourcePhrase}`;
|
|
141
|
+
}
|
|
142
|
+
function metadataString(metadata, key) {
|
|
143
|
+
const value = metadata?.[key];
|
|
144
|
+
return typeof value === 'string' && value.trim().length > 0 ? value : undefined;
|
|
145
|
+
}
|
|
146
|
+
function metadataStringArray(metadata, key) {
|
|
147
|
+
const value = metadata?.[key];
|
|
148
|
+
return Array.isArray(value)
|
|
149
|
+
? value.filter((item) => typeof item === 'string' && item.trim().length > 0)
|
|
150
|
+
: [];
|
|
151
|
+
}
|
|
152
|
+
function dedupeNames(values) {
|
|
153
|
+
if (!values)
|
|
154
|
+
return [];
|
|
155
|
+
const seen = new Set();
|
|
156
|
+
const out = [];
|
|
157
|
+
for (const value of values) {
|
|
158
|
+
const trimmed = typeof value === 'string' ? value.trim() : '';
|
|
159
|
+
if (!trimmed || seen.has(trimmed.toLowerCase()))
|
|
160
|
+
continue;
|
|
161
|
+
seen.add(trimmed.toLowerCase());
|
|
162
|
+
out.push(trimmed);
|
|
163
|
+
}
|
|
164
|
+
return out;
|
|
165
|
+
}
|
|
166
|
+
function uniqueByName(assets) {
|
|
167
|
+
const seen = new Set();
|
|
168
|
+
const out = [];
|
|
169
|
+
for (const asset of assets) {
|
|
170
|
+
if (seen.has(asset.id))
|
|
171
|
+
continue;
|
|
172
|
+
seen.add(asset.id);
|
|
173
|
+
out.push(asset);
|
|
174
|
+
}
|
|
175
|
+
return out;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=derivation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derivation.js","sourceRoot":"","sources":["../../src/lineage/derivation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Impact analysis + re-certification gating for DQL's answer layer.
|
|
3
|
+
*
|
|
4
|
+
* DQL composition is unbounded freeform `ref()`. The safety net: when a block
|
|
5
|
+
* changes, you must know what downstream *certified* work it invalidates.
|
|
6
|
+
*
|
|
7
|
+
* Given changed block name(s) — from `dql diff` or explicit input — this module:
|
|
8
|
+
* 1. walks the dependency DAG **downstream** to the full transitive set,
|
|
9
|
+
* 2. flags the cross-domain edges that get invalidated,
|
|
10
|
+
* 3. computes the resulting `domainTrust` delta,
|
|
11
|
+
* 4. produces a **required re-cert** list (certified downstream depending on
|
|
12
|
+
* a changed block's semantics).
|
|
13
|
+
*
|
|
14
|
+
* It also classifies whether a given block change is *semantic* (affects what
|
|
15
|
+
* the block computes) or purely cosmetic (description/owner/tag/viz only).
|
|
16
|
+
* The classification is **conservative**: when unsure, treat the change as
|
|
17
|
+
* semantic so re-cert is required rather than silently skipped.
|
|
18
|
+
*
|
|
19
|
+
* This is the LOCAL engine. It does not manage org-wide workflow, approvals,
|
|
20
|
+
* audit, or auto-re-certification — that is the cloud product.
|
|
21
|
+
*/
|
|
22
|
+
import type { LineageGraph } from './lineage-graph.js';
|
|
23
|
+
import type { DiffChange } from '../format/diff.js';
|
|
24
|
+
/** Reason a changed block was (or was not) classified as a semantic change. */
|
|
25
|
+
export type SemanticVerdict = 'semantic' | 'non-semantic';
|
|
26
|
+
export interface ChangedBlock {
|
|
27
|
+
/** Block name (matches `block:<name>` in the lineage graph). */
|
|
28
|
+
name: string;
|
|
29
|
+
/** Whether the change affects what the block computes. */
|
|
30
|
+
verdict: SemanticVerdict;
|
|
31
|
+
/** Field paths that changed (for block-changed diffs). */
|
|
32
|
+
changedFields: string[];
|
|
33
|
+
/** True when the block was added or removed (always semantic). */
|
|
34
|
+
structural: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Classify a single block-level `DiffChange` as semantic or non-semantic.
|
|
38
|
+
*
|
|
39
|
+
* - Added/removed blocks are always semantic (structural).
|
|
40
|
+
* - A changed block is non-semantic only when **every** changed field is in
|
|
41
|
+
* {@link NON_SEMANTIC_BLOCK_FIELDS}. A single unrecognized or semantic field
|
|
42
|
+
* makes the whole change semantic (conservative default).
|
|
43
|
+
*/
|
|
44
|
+
export declare function classifyBlockChange(change: DiffChange): ChangedBlock | null;
|
|
45
|
+
/**
|
|
46
|
+
* Extract the set of changed blocks from a diff report's changes, classifying
|
|
47
|
+
* each as semantic or non-semantic. Non-block changes (dashboards, workbooks,
|
|
48
|
+
* cells, notebooks) are ignored here — impact is keyed off block identity.
|
|
49
|
+
*/
|
|
50
|
+
export declare function changedBlocksFromDiff(changes: DiffChange[]): ChangedBlock[];
|
|
51
|
+
export interface ImpactedNode {
|
|
52
|
+
id: string;
|
|
53
|
+
type: string;
|
|
54
|
+
name: string;
|
|
55
|
+
domain?: string;
|
|
56
|
+
status?: string;
|
|
57
|
+
owner?: string;
|
|
58
|
+
}
|
|
59
|
+
export interface CrossDomainImpact {
|
|
60
|
+
from: string;
|
|
61
|
+
to: string;
|
|
62
|
+
/** Invalidated boundary edges: source feeds a target in another domain. */
|
|
63
|
+
edges: Array<{
|
|
64
|
+
source: string;
|
|
65
|
+
target: string;
|
|
66
|
+
}>;
|
|
67
|
+
}
|
|
68
|
+
export interface DomainTrustDelta {
|
|
69
|
+
domain: string;
|
|
70
|
+
/** Certified count before vs. after re-cert demotions. */
|
|
71
|
+
certifiedBefore: number;
|
|
72
|
+
certifiedAfter: number;
|
|
73
|
+
total: number;
|
|
74
|
+
trustBefore: number;
|
|
75
|
+
trustAfter: number;
|
|
76
|
+
/** trustAfter - trustBefore (≤ 0). */
|
|
77
|
+
delta: number;
|
|
78
|
+
}
|
|
79
|
+
export interface RecertItem {
|
|
80
|
+
id: string;
|
|
81
|
+
name: string;
|
|
82
|
+
domain?: string;
|
|
83
|
+
owner?: string;
|
|
84
|
+
/** The changed block(s) whose semantics this artifact transitively depends on. */
|
|
85
|
+
invalidatedBy: string[];
|
|
86
|
+
}
|
|
87
|
+
export interface ImpactReport {
|
|
88
|
+
/** Changed blocks that were analyzed (semantic + non-semantic). */
|
|
89
|
+
changedBlocks: ChangedBlock[];
|
|
90
|
+
/** Changed blocks with a semantic verdict — only these propagate impact. */
|
|
91
|
+
semanticChanges: string[];
|
|
92
|
+
/** Full transitive downstream set across all semantic changes (excludes domain nodes). */
|
|
93
|
+
downstream: ImpactedNode[];
|
|
94
|
+
/** Cross-domain edges inside the invalidated zone, grouped by from→to. */
|
|
95
|
+
crossDomainImpacts: CrossDomainImpact[];
|
|
96
|
+
/** Certified artifacts that must be re-certified. */
|
|
97
|
+
requiresRecert: RecertItem[];
|
|
98
|
+
/** Per-domain trust delta caused by demoting the re-cert set. */
|
|
99
|
+
domainTrustDelta: DomainTrustDelta[];
|
|
100
|
+
/** True when certified downstream is invalidated and not already pending re-cert. */
|
|
101
|
+
hasCertifiedInvalidation: boolean;
|
|
102
|
+
}
|
|
103
|
+
export interface ComputeImpactOptions {
|
|
104
|
+
/**
|
|
105
|
+
* When true (default), a re-cert is only required for downstream nodes still
|
|
106
|
+
* marked `certified`. Nodes already `pending_recertification` are reported in
|
|
107
|
+
* the downstream set but do not, on their own, trip the gate — they are
|
|
108
|
+
* already flagged. Set false to also count `pending_recertification`.
|
|
109
|
+
*/
|
|
110
|
+
ignoreAlreadyPending?: boolean;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Compute the impact of a set of changed blocks against a lineage graph.
|
|
114
|
+
*
|
|
115
|
+
* Only blocks with a **semantic** verdict propagate downstream impact; a purely
|
|
116
|
+
* cosmetic change (description/owner/tag only) produces an empty downstream set
|
|
117
|
+
* and never trips the re-cert gate.
|
|
118
|
+
*/
|
|
119
|
+
export declare function computeImpact(graph: LineageGraph, changedBlocks: ChangedBlock[], options?: ComputeImpactOptions): ImpactReport;
|
|
120
|
+
/**
|
|
121
|
+
* One-shot helper: classify a diff's block changes and compute the impact
|
|
122
|
+
* report in a single call.
|
|
123
|
+
*/
|
|
124
|
+
export declare function computeImpactFromDiff(graph: LineageGraph, changes: DiffChange[], options?: ComputeImpactOptions): ImpactReport;
|
|
125
|
+
/** Render an impact report as human-readable text for the CLI. */
|
|
126
|
+
export declare function renderImpactText(report: ImpactReport): string;
|
|
127
|
+
//# sourceMappingURL=impact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"impact.d.ts","sourceRoot":"","sources":["../../src/lineage/impact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Impact analysis + re-certification gating for DQL's answer layer.
|
|
3
|
+
*
|
|
4
|
+
* DQL composition is unbounded freeform `ref()`. The safety net: when a block
|
|
5
|
+
* changes, you must know what downstream *certified* work it invalidates.
|
|
6
|
+
*
|
|
7
|
+
* Given changed block name(s) — from `dql diff` or explicit input — this module:
|
|
8
|
+
* 1. walks the dependency DAG **downstream** to the full transitive set,
|
|
9
|
+
* 2. flags the cross-domain edges that get invalidated,
|
|
10
|
+
* 3. computes the resulting `domainTrust` delta,
|
|
11
|
+
* 4. produces a **required re-cert** list (certified downstream depending on
|
|
12
|
+
* a changed block's semantics).
|
|
13
|
+
*
|
|
14
|
+
* It also classifies whether a given block change is *semantic* (affects what
|
|
15
|
+
* the block computes) or purely cosmetic (description/owner/tag/viz only).
|
|
16
|
+
* The classification is **conservative**: when unsure, treat the change as
|
|
17
|
+
* semantic so re-cert is required rather than silently skipped.
|
|
18
|
+
*
|
|
19
|
+
* This is the LOCAL engine. It does not manage org-wide workflow, approvals,
|
|
20
|
+
* audit, or auto-re-certification — that is the cloud product.
|
|
21
|
+
*/
|
|
22
|
+
import { getDomainTrustOverview } from './domain-lineage.js';
|
|
23
|
+
// ---- Semantic-change classification ----
|
|
24
|
+
/**
|
|
25
|
+
* Block-diff field paths that are **non-semantic**: they describe or annotate
|
|
26
|
+
* the block but do not change what it computes. A change confined entirely to
|
|
27
|
+
* these fields does not invalidate certification.
|
|
28
|
+
*
|
|
29
|
+
* Everything else (query, params, metric refs, tests, domain, type, business
|
|
30
|
+
* rules, visualization, …) is treated as semantic. This is deliberately a
|
|
31
|
+
* deny-list of known-cosmetic fields rather than an allow-list of semantic
|
|
32
|
+
* ones, so an unrecognized/new field defaults to "semantic" → needs re-cert.
|
|
33
|
+
*/
|
|
34
|
+
const NON_SEMANTIC_BLOCK_FIELDS = new Set([
|
|
35
|
+
'description',
|
|
36
|
+
'owner',
|
|
37
|
+
'tags',
|
|
38
|
+
'businessOutcome',
|
|
39
|
+
'businessOwner',
|
|
40
|
+
'decisionUse',
|
|
41
|
+
'reviewCadence',
|
|
42
|
+
'caveats',
|
|
43
|
+
]);
|
|
44
|
+
/**
|
|
45
|
+
* Classify a single block-level `DiffChange` as semantic or non-semantic.
|
|
46
|
+
*
|
|
47
|
+
* - Added/removed blocks are always semantic (structural).
|
|
48
|
+
* - A changed block is non-semantic only when **every** changed field is in
|
|
49
|
+
* {@link NON_SEMANTIC_BLOCK_FIELDS}. A single unrecognized or semantic field
|
|
50
|
+
* makes the whole change semantic (conservative default).
|
|
51
|
+
*/
|
|
52
|
+
export function classifyBlockChange(change) {
|
|
53
|
+
switch (change.kind) {
|
|
54
|
+
case 'block-added':
|
|
55
|
+
case 'block-removed':
|
|
56
|
+
return { name: change.name, verdict: 'semantic', changedFields: [], structural: true };
|
|
57
|
+
case 'block-changed': {
|
|
58
|
+
const fields = change.fields.map((f) => f.path);
|
|
59
|
+
const allCosmetic = fields.length > 0 && fields.every((p) => isNonSemanticField(p));
|
|
60
|
+
return {
|
|
61
|
+
name: change.name,
|
|
62
|
+
verdict: allCosmetic ? 'non-semantic' : 'semantic',
|
|
63
|
+
changedFields: fields,
|
|
64
|
+
structural: false,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
default:
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** A field path is non-semantic when its leading segment is a known cosmetic field. */
|
|
72
|
+
function isNonSemanticField(path) {
|
|
73
|
+
// `tags`, `description`, … are top-level; `params.region`, `tests[..]`,
|
|
74
|
+
// `visualization.title`, `query` are semantic. Only the exact known cosmetic
|
|
75
|
+
// field names count as non-semantic.
|
|
76
|
+
return NON_SEMANTIC_BLOCK_FIELDS.has(path);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Extract the set of changed blocks from a diff report's changes, classifying
|
|
80
|
+
* each as semantic or non-semantic. Non-block changes (dashboards, workbooks,
|
|
81
|
+
* cells, notebooks) are ignored here — impact is keyed off block identity.
|
|
82
|
+
*/
|
|
83
|
+
export function changedBlocksFromDiff(changes) {
|
|
84
|
+
const out = [];
|
|
85
|
+
for (const change of changes) {
|
|
86
|
+
const classified = classifyBlockChange(change);
|
|
87
|
+
if (classified)
|
|
88
|
+
out.push(classified);
|
|
89
|
+
}
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Compute the impact of a set of changed blocks against a lineage graph.
|
|
94
|
+
*
|
|
95
|
+
* Only blocks with a **semantic** verdict propagate downstream impact; a purely
|
|
96
|
+
* cosmetic change (description/owner/tag only) produces an empty downstream set
|
|
97
|
+
* and never trips the re-cert gate.
|
|
98
|
+
*/
|
|
99
|
+
export function computeImpact(graph, changedBlocks, options = {}) {
|
|
100
|
+
const ignoreAlreadyPending = options.ignoreAlreadyPending ?? true;
|
|
101
|
+
const semantic = changedBlocks.filter((b) => b.verdict === 'semantic');
|
|
102
|
+
const semanticNames = semantic.map((b) => b.name);
|
|
103
|
+
// Resolve each changed block to its graph node id. A changed block may not
|
|
104
|
+
// exist in the graph (e.g. removed, or never compiled) — skip those for the
|
|
105
|
+
// downstream walk but keep them in the report.
|
|
106
|
+
const sourceIds = [];
|
|
107
|
+
const sourceNameById = new Map();
|
|
108
|
+
for (const block of semantic) {
|
|
109
|
+
const id = `block:${block.name}`;
|
|
110
|
+
if (graph.getNode(id)) {
|
|
111
|
+
sourceIds.push(id);
|
|
112
|
+
sourceNameById.set(id, block.name);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Full transitive downstream union. Track which changed block(s) reach each
|
|
116
|
+
// downstream node so the re-cert list can attribute invalidations precisely.
|
|
117
|
+
const downstreamById = new Map();
|
|
118
|
+
const reachedBy = new Map();
|
|
119
|
+
for (const id of sourceIds) {
|
|
120
|
+
const blockName = sourceNameById.get(id);
|
|
121
|
+
for (const node of graph.descendants(id)) {
|
|
122
|
+
if (node.type === 'domain')
|
|
123
|
+
continue;
|
|
124
|
+
downstreamById.set(node.id, node);
|
|
125
|
+
const set = reachedBy.get(node.id) ?? new Set();
|
|
126
|
+
set.add(blockName);
|
|
127
|
+
reachedBy.set(node.id, set);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const downstream = [...downstreamById.values()]
|
|
131
|
+
.map(toImpactedNode)
|
|
132
|
+
.sort((a, b) => a.id.localeCompare(b.id));
|
|
133
|
+
// Cross-domain edges fully contained in the invalidated zone (source = a
|
|
134
|
+
// changed block or a downstream node; target = a downstream node).
|
|
135
|
+
const zoneIds = new Set([...sourceIds, ...downstreamById.keys()]);
|
|
136
|
+
const crossDomainImpacts = collectCrossDomainImpacts(graph, zoneIds);
|
|
137
|
+
// Re-cert list: certified downstream nodes invalidated by a semantic change.
|
|
138
|
+
const requiresRecert = [];
|
|
139
|
+
for (const node of downstreamById.values()) {
|
|
140
|
+
if (node.status !== 'certified') {
|
|
141
|
+
if (!(node.status === 'pending_recertification' && !ignoreAlreadyPending))
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
requiresRecert.push({
|
|
145
|
+
id: node.id,
|
|
146
|
+
name: node.name,
|
|
147
|
+
domain: node.domain,
|
|
148
|
+
owner: node.owner,
|
|
149
|
+
invalidatedBy: [...(reachedBy.get(node.id) ?? new Set())].sort(),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
requiresRecert.sort((a, b) => a.id.localeCompare(b.id));
|
|
153
|
+
const domainTrustDelta = computeDomainTrustDelta(graph, requiresRecert);
|
|
154
|
+
return {
|
|
155
|
+
changedBlocks,
|
|
156
|
+
semanticChanges: semanticNames,
|
|
157
|
+
downstream,
|
|
158
|
+
crossDomainImpacts,
|
|
159
|
+
requiresRecert,
|
|
160
|
+
domainTrustDelta,
|
|
161
|
+
hasCertifiedInvalidation: requiresRecert.length > 0,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function toImpactedNode(node) {
|
|
165
|
+
return {
|
|
166
|
+
id: node.id,
|
|
167
|
+
type: node.type,
|
|
168
|
+
name: node.name,
|
|
169
|
+
domain: node.domain,
|
|
170
|
+
status: node.status,
|
|
171
|
+
owner: node.owner,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Collect cross-domain edges whose source and target both lie inside the
|
|
176
|
+
* invalidated zone, grouped by `from → to` domain pair.
|
|
177
|
+
*/
|
|
178
|
+
function collectCrossDomainImpacts(graph, zoneIds) {
|
|
179
|
+
const byPair = new Map();
|
|
180
|
+
for (const edge of graph.getCrossDomainEdges()) {
|
|
181
|
+
if (!zoneIds.has(edge.source) || !zoneIds.has(edge.target))
|
|
182
|
+
continue;
|
|
183
|
+
const from = edge.sourceDomain ?? graph.getNode(edge.source)?.domain ?? '(unknown)';
|
|
184
|
+
const to = edge.targetDomain ?? graph.getNode(edge.target)?.domain ?? '(unknown)';
|
|
185
|
+
const key = `${from}→${to}`;
|
|
186
|
+
let impact = byPair.get(key);
|
|
187
|
+
if (!impact) {
|
|
188
|
+
impact = { from, to, edges: [] };
|
|
189
|
+
byPair.set(key, impact);
|
|
190
|
+
}
|
|
191
|
+
impact.edges.push({ source: edge.source, target: edge.target });
|
|
192
|
+
}
|
|
193
|
+
return [...byPair.values()].sort((a, b) => `${a.from}→${a.to}`.localeCompare(`${b.from}→${b.to}`));
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Compute the per-domain `domainTrust` delta that results from demoting every
|
|
197
|
+
* re-cert artifact out of `certified`. The "before" view uses the live graph;
|
|
198
|
+
* the "after" view recomputes trust as if each re-cert block were no longer
|
|
199
|
+
* certified (it would become `pending_recertification`).
|
|
200
|
+
*
|
|
201
|
+
* Only block-typed re-cert items affect trust scores, mirroring
|
|
202
|
+
* {@link getDomainTrustOverview} which counts blocks only.
|
|
203
|
+
*/
|
|
204
|
+
function computeDomainTrustDelta(graph, requiresRecert) {
|
|
205
|
+
// Map domain → set of block names losing certified status.
|
|
206
|
+
const demotedByDomain = new Map();
|
|
207
|
+
const affectedDomains = new Set();
|
|
208
|
+
for (const item of requiresRecert) {
|
|
209
|
+
const node = graph.getNode(item.id);
|
|
210
|
+
if (!node || node.type !== 'block')
|
|
211
|
+
continue;
|
|
212
|
+
const domain = node.domain ?? '(unassigned)';
|
|
213
|
+
demotedByDomain.set(domain, (demotedByDomain.get(domain) ?? 0) + 1);
|
|
214
|
+
affectedDomains.add(domain);
|
|
215
|
+
}
|
|
216
|
+
const deltas = [];
|
|
217
|
+
for (const domain of affectedDomains) {
|
|
218
|
+
const overview = getDomainTrustOverview(graph, domain);
|
|
219
|
+
const total = overview.totalBlocks;
|
|
220
|
+
const certifiedBefore = overview.certified;
|
|
221
|
+
const demoted = demotedByDomain.get(domain) ?? 0;
|
|
222
|
+
const certifiedAfter = Math.max(0, certifiedBefore - demoted);
|
|
223
|
+
const trustBefore = total > 0 ? certifiedBefore / total : 0;
|
|
224
|
+
const trustAfter = total > 0 ? certifiedAfter / total : 0;
|
|
225
|
+
deltas.push({
|
|
226
|
+
domain,
|
|
227
|
+
certifiedBefore,
|
|
228
|
+
certifiedAfter,
|
|
229
|
+
total,
|
|
230
|
+
trustBefore,
|
|
231
|
+
trustAfter,
|
|
232
|
+
delta: trustAfter - trustBefore,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
return deltas.sort((a, b) => a.domain.localeCompare(b.domain));
|
|
236
|
+
}
|
|
237
|
+
// ---- Convenience: full report from a diff ----
|
|
238
|
+
/**
|
|
239
|
+
* One-shot helper: classify a diff's block changes and compute the impact
|
|
240
|
+
* report in a single call.
|
|
241
|
+
*/
|
|
242
|
+
export function computeImpactFromDiff(graph, changes, options) {
|
|
243
|
+
return computeImpact(graph, changedBlocksFromDiff(changes), options);
|
|
244
|
+
}
|
|
245
|
+
// ---- Text rendering ----
|
|
246
|
+
/** Render an impact report as human-readable text for the CLI. */
|
|
247
|
+
export function renderImpactText(report) {
|
|
248
|
+
const lines = [];
|
|
249
|
+
lines.push(' Impact Analysis');
|
|
250
|
+
lines.push(' ' + '='.repeat(50));
|
|
251
|
+
if (report.changedBlocks.length === 0) {
|
|
252
|
+
lines.push('');
|
|
253
|
+
lines.push(' No block changes detected.');
|
|
254
|
+
return lines.join('\n');
|
|
255
|
+
}
|
|
256
|
+
lines.push('');
|
|
257
|
+
lines.push(' Changed blocks:');
|
|
258
|
+
for (const block of report.changedBlocks) {
|
|
259
|
+
const tag = block.structural
|
|
260
|
+
? '(structural)'
|
|
261
|
+
: block.verdict === 'non-semantic'
|
|
262
|
+
? '(non-semantic — no re-cert)'
|
|
263
|
+
: '(semantic)';
|
|
264
|
+
lines.push(` ${block.name} ${tag}`);
|
|
265
|
+
}
|
|
266
|
+
lines.push('');
|
|
267
|
+
lines.push(` Transitive downstream affected: ${report.downstream.length}`);
|
|
268
|
+
for (const node of report.downstream) {
|
|
269
|
+
const badge = node.status === 'certified' ? ' [certified]' : node.status ? ` [${node.status}]` : '';
|
|
270
|
+
const domain = node.domain ? ` (${node.domain})` : '';
|
|
271
|
+
lines.push(` - ${node.type}:${node.name}${domain}${badge}`);
|
|
272
|
+
}
|
|
273
|
+
if (report.crossDomainImpacts.length > 0) {
|
|
274
|
+
lines.push('');
|
|
275
|
+
lines.push(' Cross-domain edges invalidated:');
|
|
276
|
+
for (const impact of report.crossDomainImpacts) {
|
|
277
|
+
lines.push(` ${impact.from} -> ${impact.to} (${impact.edges.length} edge(s))`);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
if (report.domainTrustDelta.length > 0) {
|
|
281
|
+
lines.push('');
|
|
282
|
+
lines.push(' domainTrust delta:');
|
|
283
|
+
for (const d of report.domainTrustDelta) {
|
|
284
|
+
const before = (d.trustBefore * 100).toFixed(0);
|
|
285
|
+
const after = (d.trustAfter * 100).toFixed(0);
|
|
286
|
+
const pts = (d.delta * 100).toFixed(0);
|
|
287
|
+
lines.push(` ${d.domain}: ${d.certifiedBefore}/${d.total} -> ${d.certifiedAfter}/${d.total} certified ` +
|
|
288
|
+
`(${before}% -> ${after}%, ${pts} pts)`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
lines.push('');
|
|
292
|
+
if (report.requiresRecert.length > 0) {
|
|
293
|
+
lines.push(` Requires re-certification (${report.requiresRecert.length}):`);
|
|
294
|
+
for (const item of report.requiresRecert) {
|
|
295
|
+
const owner = item.owner ? ` — ${item.owner}` : '';
|
|
296
|
+
lines.push(` ! ${item.name}${item.domain ? ` (${item.domain})` : ''}${owner}`);
|
|
297
|
+
lines.push(` invalidated by: ${item.invalidatedBy.join(', ')}`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
lines.push(' No certified downstream invalidated. Re-cert not required.');
|
|
302
|
+
}
|
|
303
|
+
return lines.join('\n');
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=impact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"impact.js","sourceRoot":"","sources":["../../src/lineage/impact.ts"],"names":[],"mappings":"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"}
|
package/dist/lineage/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export { analyzeSqlReferences, extractTablesFromSql, type SqlColumnReference, type SqlParseResult, type SqlReferenceAnalysis, } from './sql-parser.js';
|
|
2
|
-
export { extractColumnLineage, type ColumnLineageEntry, type ColumnLineageResult, type ColumnSource, } from './column-lineage.js';
|
|
2
|
+
export { extractColumnLineage, extractRefColumnUsage, type ColumnLineageEntry, type ColumnLineageResult, type ColumnSource, type RefColumnUsage, } from './column-lineage.js';
|
|
3
3
|
export { resolveDependencies, getUpstream, getDownstream, type BlockDependencyInfo, type DependencyResolutionResult, } from './dependency-resolver.js';
|
|
4
4
|
export { LineageGraph, getLayerForNodeType, type LineageNode, type LineageEdge, type LineageNodeType, type LineageEdgeType, type LineageLayer, type LineageGraphJSON, } from './lineage-graph.js';
|
|
5
5
|
export { buildLineageGraph, type LineageBlockInput, type LineageMetricInput, type LineageDimensionInput, type LineageDbtModelInput, type LineageDashboardInput, type LineageBusinessViewInput, type LineageTermInput, type LineageBuilderOptions, } from './builder.js';
|
|
6
6
|
export { queryLineage, queryBusiness360, queryCompleteLineagePaths, type LineageQuery, type LineageQueryResult, type Business360Asset, type Business360BlockContract, type Business360Edge, type Business360Gap, type Business360Options, type Business360Reusability, type Business360Result, type Business360ResultV2, type LineagePath, type CompletePathResult, type CompletePathOptions, } from './query.js';
|
|
7
7
|
export { buildTrustChain, analyzeImpact, detectDomainFlows, getDomainTrustOverview, type TrustChain, type TrustChainNode, type ImpactAnalysis, type DomainImpact, type DomainFlow, } from './domain-lineage.js';
|
|
8
|
+
export { buildDerivationWalk, type DerivationWalk, type DerivationStep, type DerivationStepKind, type DerivationFocusBlock, type BuildDerivationWalkInput, } from './derivation.js';
|
|
9
|
+
export { classifyBlockChange, changedBlocksFromDiff, computeImpact, computeImpactFromDiff, renderImpactText, type ChangedBlock, type SemanticVerdict, type ImpactReport, type ImpactedNode, type CrossDomainImpact, type DomainTrustDelta, type RecertItem, type ComputeImpactOptions, } from './impact.js';
|
|
8
10
|
//# sourceMappingURL=index.d.ts.map
|