@kaelio/ktx 0.1.0-rc.6 → 0.1.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.
- package/assets/python/{kaelio_ktx-0.1.0rc6-py3-none-any.whl → kaelio_ktx-0.1.0-py3-none-any.whl} +0 -0
- package/assets/python/manifest.json +4 -4
- package/dist/commands/mcp-commands.js +11 -3
- package/dist/commands/mcp-commands.test.js +30 -1
- package/dist/ingest.test.js +2 -26
- package/dist/next-steps.js +1 -1
- package/dist/next-steps.test.js +2 -0
- package/dist/runtime-requirements.d.ts +1 -2
- package/dist/runtime-requirements.js +0 -7
- package/dist/runtime-requirements.test.js +2 -2
- package/dist/setup-agents.d.ts +11 -3
- package/dist/setup-agents.js +397 -134
- package/dist/setup-agents.test.js +359 -61
- package/dist/setup-runtime.d.ts +0 -1
- package/dist/setup-runtime.js +0 -1
- package/dist/setup-runtime.test.js +7 -13
- package/dist/setup.d.ts +3 -0
- package/dist/setup.js +51 -25
- package/dist/setup.test.js +112 -16
- package/node_modules/@ktx/connector-clickhouse/dist/package-exports.test.js +1 -1
- package/node_modules/@ktx/context/dist/core/git.service.d.ts +0 -1
- package/node_modules/@ktx/context/dist/core/git.service.js +0 -12
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/historic-sql.adapter.d.ts +1 -2
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/historic-sql.adapter.js +0 -18
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/local-ingest-acceptance.test.js +6 -6
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/post-processor.d.ts +4 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/post-processor.js +38 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/post-processor.test.js +63 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/projection.d.ts +0 -5
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/projection.js +0 -48
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/projection.test.js +0 -83
- package/node_modules/@ktx/context/dist/ingest/index.d.ts +2 -1
- package/node_modules/@ktx/context/dist/ingest/index.js +1 -0
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.d.ts +0 -2
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.isolated-diff.test.js +0 -166
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.js +45 -235
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.test.js +38 -193
- package/node_modules/@ktx/context/dist/ingest/local-bundle-ingest.test.js +3 -22
- package/node_modules/@ktx/context/dist/ingest/local-bundle-runtime.js +4 -0
- package/node_modules/@ktx/context/dist/ingest/local-ingest.js +7 -0
- package/node_modules/@ktx/context/dist/ingest/memory-flow/schema.d.ts +4 -4
- package/node_modules/@ktx/context/dist/ingest/memory-flow/schema.js +1 -1
- package/node_modules/@ktx/context/dist/ingest/memory-flow/types.d.ts +1 -1
- package/node_modules/@ktx/context/dist/ingest/ports.d.ts +20 -1
- package/node_modules/@ktx/context/dist/ingest/report-snapshot.d.ts +2 -73
- package/node_modules/@ktx/context/dist/ingest/report-snapshot.js +0 -27
- package/node_modules/@ktx/context/dist/ingest/reports.d.ts +5 -23
- package/node_modules/@ktx/context/dist/ingest/reports.js +24 -7
- package/node_modules/@ktx/context/dist/ingest/types.d.ts +0 -33
- package/node_modules/@ktx/context/dist/package-exports.test.js +1 -2
- package/package.json +4 -4
- package/node_modules/@ktx/context/dist/ingest/finalization-scope.d.ts +0 -22
- package/node_modules/@ktx/context/dist/ingest/finalization-scope.js +0 -95
- package/node_modules/@ktx/context/dist/ingest/finalization-scope.test.js +0 -114
- /package/node_modules/@ktx/context/dist/ingest/{finalization-scope.test.d.ts → adapters/historic-sql/post-processor.test.d.ts} +0 -0
|
@@ -29,31 +29,13 @@ export interface IngestReportToolTranscriptSummary {
|
|
|
29
29
|
errorCount: number;
|
|
30
30
|
toolNames: string[];
|
|
31
31
|
}
|
|
32
|
-
export interface
|
|
33
|
-
artifactKind: 'sl' | 'wiki';
|
|
34
|
-
key: string;
|
|
35
|
-
direction: 'missing_from_adapter_declaration' | 'extra_in_adapter_declaration';
|
|
36
|
-
}
|
|
37
|
-
export interface IngestReportFinalizationProvenanceExclusion {
|
|
38
|
-
action: MemoryAction;
|
|
39
|
-
reason: 'missing_raw_paths' | 'raw_path_not_defensible';
|
|
40
|
-
invalidRawPaths?: string[];
|
|
41
|
-
}
|
|
42
|
-
export interface IngestReportFinalizationOutcome {
|
|
32
|
+
export interface IngestReportPostProcessorOutcome {
|
|
43
33
|
sourceKey: string;
|
|
44
|
-
status: 'success' | 'failed'
|
|
45
|
-
commitSha: string | null;
|
|
46
|
-
touchedPaths: string[];
|
|
47
|
-
declaredTouchedSources: TouchedSlSource[];
|
|
48
|
-
derivedTouchedSources: TouchedSlSource[];
|
|
49
|
-
declaredChangedWikiPageKeys: string[];
|
|
50
|
-
derivedChangedWikiPageKeys: string[];
|
|
51
|
-
mismatches: IngestReportFinalizationMismatch[];
|
|
34
|
+
status: 'success' | 'failed';
|
|
52
35
|
result?: unknown;
|
|
53
36
|
errors: string[];
|
|
54
37
|
warnings: string[];
|
|
55
|
-
|
|
56
|
-
provenanceExclusions: IngestReportFinalizationProvenanceExclusion[];
|
|
38
|
+
touchedSources: TouchedSlSource[];
|
|
57
39
|
}
|
|
58
40
|
export interface IngestReportFailure {
|
|
59
41
|
phase: string;
|
|
@@ -97,7 +79,7 @@ export interface IngestReportBody {
|
|
|
97
79
|
overrideOf: string | null;
|
|
98
80
|
provenanceRows: IngestReportProvenanceDetail[];
|
|
99
81
|
toolTranscripts: IngestReportToolTranscriptSummary[];
|
|
100
|
-
|
|
82
|
+
postProcessor?: IngestReportPostProcessorOutcome;
|
|
101
83
|
wikiSlRefRepairs?: WikiSlRefRepair[];
|
|
102
84
|
wikiSlRefRepairWarnings?: string[];
|
|
103
85
|
memoryFlow?: MemoryFlowReplayInput;
|
|
@@ -115,6 +97,6 @@ export interface IngestSavedMemoryCounts {
|
|
|
115
97
|
wikiCount: number;
|
|
116
98
|
slCount: number;
|
|
117
99
|
}
|
|
118
|
-
export declare function
|
|
100
|
+
export declare function postProcessorSavedMemoryCounts(postProcessor: IngestReportPostProcessorOutcome | undefined): IngestSavedMemoryCounts;
|
|
119
101
|
export declare function savedMemoryCountsForReport(report: IngestReportSnapshot): IngestSavedMemoryCounts;
|
|
120
102
|
export declare function buildStageIndexFromReportBody(jobId: string, connectionId: string, body: IngestReportBody): StageIndex;
|
|
@@ -1,19 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
1
|
+
function numericResultField(result, field) {
|
|
2
|
+
const value = result[field];
|
|
3
|
+
return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : 0;
|
|
4
|
+
}
|
|
5
|
+
export function postProcessorSavedMemoryCounts(postProcessor) {
|
|
6
|
+
if (!postProcessor || postProcessor.sourceKey !== 'historic-sql') {
|
|
7
|
+
return { wikiCount: 0, slCount: 0 };
|
|
8
|
+
}
|
|
9
|
+
const result = postProcessor.result;
|
|
10
|
+
if (!result || typeof result !== 'object' || Array.isArray(result)) {
|
|
11
|
+
return { wikiCount: 0, slCount: 0 };
|
|
12
|
+
}
|
|
13
|
+
const record = result;
|
|
3
14
|
return {
|
|
4
|
-
wikiCount:
|
|
5
|
-
|
|
15
|
+
wikiCount: numericResultField(record, 'patternPagesWritten') +
|
|
16
|
+
numericResultField(record, 'stalePatternPagesMarked') +
|
|
17
|
+
numericResultField(record, 'archivedPatternPages'),
|
|
18
|
+
slCount: numericResultField(record, 'tableUsageMerged') + numericResultField(record, 'staleTablesMarked'),
|
|
6
19
|
};
|
|
7
20
|
}
|
|
8
21
|
export function savedMemoryCountsForReport(report) {
|
|
9
22
|
const workUnitActions = report.body.workUnits.flatMap((workUnit) => workUnit.actions);
|
|
10
23
|
const reconciliationActions = report.body.reconciliationActions ?? [];
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
return {
|
|
24
|
+
const actions = [...workUnitActions, ...reconciliationActions];
|
|
25
|
+
const directCounts = {
|
|
14
26
|
wikiCount: actions.filter((action) => action.target === 'wiki').length,
|
|
15
27
|
slCount: actions.filter((action) => action.target === 'sl').length,
|
|
16
28
|
};
|
|
29
|
+
const postProcessorCounts = postProcessorSavedMemoryCounts(report.body.postProcessor);
|
|
30
|
+
return {
|
|
31
|
+
wikiCount: directCounts.wikiCount + postProcessorCounts.wikiCount,
|
|
32
|
+
slCount: directCounts.slCount + postProcessorCounts.slCount,
|
|
33
|
+
};
|
|
17
34
|
}
|
|
18
35
|
export function buildStageIndexFromReportBody(jobId, connectionId, body) {
|
|
19
36
|
return {
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import type { KtxEmbeddingPort } from '../core/embedding.js';
|
|
2
|
-
import type { MemoryAction } from '../memory/index.js';
|
|
3
2
|
import type { SemanticLayerService } from '../sl/index.js';
|
|
4
|
-
import type { TouchedSlSource } from '../tools/index.js';
|
|
5
3
|
import type { MemoryFlowEventSink } from './memory-flow/types.js';
|
|
6
|
-
import type { StageIndex } from './stages/stage-index.types.js';
|
|
7
|
-
import type { WorkUnitOutcome } from './stages/stage-3-work-units.js';
|
|
8
4
|
export type IngestTrigger = 'upload' | 'scheduled_pull' | 'manual_resync' | 'manual_override';
|
|
9
5
|
export interface DiffSet {
|
|
10
6
|
added: string[];
|
|
@@ -103,34 +99,6 @@ export interface ProjectionResult {
|
|
|
103
99
|
changedWikiPageKeys: string[];
|
|
104
100
|
result?: unknown;
|
|
105
101
|
}
|
|
106
|
-
export interface FinalizationOverrideReplay {
|
|
107
|
-
priorJobId: string;
|
|
108
|
-
priorRunId: string;
|
|
109
|
-
priorSyncId: string;
|
|
110
|
-
evictionRawPaths: string[];
|
|
111
|
-
}
|
|
112
|
-
export interface DeterministicFinalizationContext {
|
|
113
|
-
connectionId: string;
|
|
114
|
-
sourceKey: string;
|
|
115
|
-
syncId: string;
|
|
116
|
-
jobId: string;
|
|
117
|
-
runId: string;
|
|
118
|
-
stagedDir: string;
|
|
119
|
-
workdir: string;
|
|
120
|
-
parseArtifacts?: unknown;
|
|
121
|
-
stageIndex: StageIndex;
|
|
122
|
-
workUnitOutcomes: WorkUnitOutcome[];
|
|
123
|
-
reconciliationActions: MemoryAction[];
|
|
124
|
-
overrideReplay?: FinalizationOverrideReplay;
|
|
125
|
-
}
|
|
126
|
-
export interface FinalizationResult {
|
|
127
|
-
warnings: string[];
|
|
128
|
-
errors: string[];
|
|
129
|
-
touchedSources: TouchedSlSource[];
|
|
130
|
-
changedWikiPageKeys: string[];
|
|
131
|
-
actions?: MemoryAction[];
|
|
132
|
-
result?: unknown;
|
|
133
|
-
}
|
|
134
102
|
export interface SourceAdapter {
|
|
135
103
|
readonly source: string;
|
|
136
104
|
readonly skillNames: string[];
|
|
@@ -145,7 +113,6 @@ export interface SourceAdapter {
|
|
|
145
113
|
chunk(stagedDir: string, diffSet?: DiffSet): Promise<ChunkResult>;
|
|
146
114
|
clusterWorkUnits?(ctx: ClusterWorkUnitsContext): Promise<WorkUnit[]>;
|
|
147
115
|
project?(ctx: DeterministicProjectionContext): Promise<ProjectionResult>;
|
|
148
|
-
finalize?(ctx: DeterministicFinalizationContext): Promise<FinalizationResult>;
|
|
149
116
|
describeScope?(stagedDir: string): Promise<ScopeDescriptor>;
|
|
150
117
|
onPullSucceeded?(ctx: {
|
|
151
118
|
connectionId: string;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
const scanTypeExportCoverage = {};
|
|
3
|
-
const ingestFinalizationTypeExportCoverage = {};
|
|
4
3
|
describe('@ktx/context package exports', () => {
|
|
5
4
|
it('exports package entry points used by host adapters', async () => {
|
|
6
5
|
const core = await import('./core/index.js');
|
|
@@ -32,7 +31,6 @@ describe('@ktx/context package exports', () => {
|
|
|
32
31
|
expect(connections.notionConnectionToPullConfig).toBeTypeOf('function');
|
|
33
32
|
expect(scan).toBeDefined();
|
|
34
33
|
expect(scanTypeExportCoverage).toEqual({});
|
|
35
|
-
expect(ingestFinalizationTypeExportCoverage).toEqual({});
|
|
36
34
|
expect(scan.createKtxConnectorCapabilities).toBeTypeOf('function');
|
|
37
35
|
expect(`liveDatabaseSnapshotToKtx${'SchemaSnapshot'}` in scan).toBe(false);
|
|
38
36
|
expect(scan.normalizeKtxNativeType).toBeTypeOf('function');
|
|
@@ -233,6 +231,7 @@ describe('@ktx/context package exports', () => {
|
|
|
233
231
|
expect(ingest.historicSqlEvidenceEnvelopeSchema).toBeDefined();
|
|
234
232
|
expect(ingest.historicSqlEvidencePath).toBeTypeOf('function');
|
|
235
233
|
expect(ingest.createEmitHistoricSqlEvidenceTool).toBeTypeOf('function');
|
|
234
|
+
expect(ingest.HistoricSqlProjectionPostProcessor).toBeTypeOf('function');
|
|
236
235
|
expect(ingest.SqliteContextEvidenceStore).toBeTypeOf('function');
|
|
237
236
|
expect(ingest.SqliteBundleIngestStore).toBeTypeOf('function');
|
|
238
237
|
expect(ingest.CuratorPaginationService).toBeTypeOf('function');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaelio/ktx",
|
|
3
|
-
"version": "0.1.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Standalone KTX context layer for database agents",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -71,10 +71,10 @@
|
|
|
71
71
|
"license": "Apache-2.0",
|
|
72
72
|
"repository": {
|
|
73
73
|
"type": "git",
|
|
74
|
-
"url": "
|
|
74
|
+
"url": "https://github.com/Kaelio/ktx"
|
|
75
75
|
},
|
|
76
76
|
"bugs": {
|
|
77
|
-
"url": "https://github.com/
|
|
77
|
+
"url": "https://github.com/Kaelio/ktx/issues"
|
|
78
78
|
},
|
|
79
|
-
"homepage": "https://github.com/
|
|
79
|
+
"homepage": "https://github.com/Kaelio/ktx#readme"
|
|
80
80
|
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { SemanticLayerSource } from '../sl/index.js';
|
|
2
|
-
import type { TouchedSlSource } from '../tools/index.js';
|
|
3
|
-
import type { IngestReportFinalizationMismatch } from './reports.js';
|
|
4
|
-
interface DeriveTouchedSourcesInput {
|
|
5
|
-
changedPaths: string[];
|
|
6
|
-
beforeSourcesByConnection: Map<string, SemanticLayerSource[]>;
|
|
7
|
-
afterSourcesByConnection: Map<string, SemanticLayerSource[]>;
|
|
8
|
-
}
|
|
9
|
-
interface DeriveTouchedSourcesResult {
|
|
10
|
-
touchedSources: TouchedSlSource[];
|
|
11
|
-
unresolvedPaths: string[];
|
|
12
|
-
}
|
|
13
|
-
interface CompareFinalizationDeclarationsInput {
|
|
14
|
-
declaredTouchedSources: TouchedSlSource[];
|
|
15
|
-
derivedTouchedSources: TouchedSlSource[];
|
|
16
|
-
declaredChangedWikiPageKeys: string[];
|
|
17
|
-
derivedChangedWikiPageKeys: string[];
|
|
18
|
-
}
|
|
19
|
-
export declare function deriveFinalizationWikiPageKeys(paths: string[]): string[];
|
|
20
|
-
export declare function deriveFinalizationTouchedSources(input: DeriveTouchedSourcesInput): Promise<DeriveTouchedSourcesResult>;
|
|
21
|
-
export declare function compareFinalizationDeclarations(input: CompareFinalizationDeclarationsInput): IngestReportFinalizationMismatch[];
|
|
22
|
-
export {};
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
function uniqueSorted(values) {
|
|
2
|
-
return [...new Set(values.filter((value) => value.length > 0))].sort();
|
|
3
|
-
}
|
|
4
|
-
function touchedKey(source) {
|
|
5
|
-
return `${source.connectionId}:${source.sourceName}`;
|
|
6
|
-
}
|
|
7
|
-
function stableJson(value) {
|
|
8
|
-
if (Array.isArray(value)) {
|
|
9
|
-
return `[${value.map((entry) => stableJson(entry)).join(',')}]`;
|
|
10
|
-
}
|
|
11
|
-
if (value && typeof value === 'object') {
|
|
12
|
-
const record = value;
|
|
13
|
-
return `{${Object.keys(record)
|
|
14
|
-
.sort()
|
|
15
|
-
.map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`)
|
|
16
|
-
.join(',')}}`;
|
|
17
|
-
}
|
|
18
|
-
return JSON.stringify(value);
|
|
19
|
-
}
|
|
20
|
-
function changedSourceNames(beforeSources, afterSources) {
|
|
21
|
-
const before = new Map(beforeSources.map((source) => [source.name, stableJson(source)]));
|
|
22
|
-
const after = new Map(afterSources.map((source) => [source.name, stableJson(source)]));
|
|
23
|
-
return uniqueSorted(uniqueSorted([...before.keys(), ...after.keys()]).filter((sourceName) => before.get(sourceName) !== after.get(sourceName)));
|
|
24
|
-
}
|
|
25
|
-
export function deriveFinalizationWikiPageKeys(paths) {
|
|
26
|
-
return uniqueSorted(paths
|
|
27
|
-
.filter((path) => path.startsWith('wiki/global/') && path.endsWith('.md'))
|
|
28
|
-
.filter((path) => !path.slice('wiki/global/'.length, -'.md'.length).includes('/'))
|
|
29
|
-
.map((path) => path.slice('wiki/global/'.length, -'.md'.length)));
|
|
30
|
-
}
|
|
31
|
-
export async function deriveFinalizationTouchedSources(input) {
|
|
32
|
-
const touched = new Map();
|
|
33
|
-
const unresolvedPaths = [];
|
|
34
|
-
for (const path of input.changedPaths) {
|
|
35
|
-
if (!path.startsWith('semantic-layer/') || !(path.endsWith('.yaml') || path.endsWith('.yml'))) {
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
const parts = path.split('/');
|
|
39
|
-
const connectionId = parts[1] ?? '';
|
|
40
|
-
if (!connectionId) {
|
|
41
|
-
unresolvedPaths.push(path);
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
if (parts[2] !== '_schema') {
|
|
45
|
-
const fileName = parts.at(-1) ?? '';
|
|
46
|
-
const sourceName = fileName.replace(/\.ya?ml$/, '');
|
|
47
|
-
if (!sourceName) {
|
|
48
|
-
unresolvedPaths.push(path);
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
touched.set(`${connectionId}:${sourceName}`, { connectionId, sourceName });
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
const changedNames = changedSourceNames(input.beforeSourcesByConnection.get(connectionId) ?? [], input.afterSourcesByConnection.get(connectionId) ?? []);
|
|
55
|
-
if (changedNames.length === 0) {
|
|
56
|
-
unresolvedPaths.push(path);
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
for (const sourceName of changedNames) {
|
|
60
|
-
touched.set(`${connectionId}:${sourceName}`, { connectionId, sourceName });
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return {
|
|
64
|
-
touchedSources: [...touched.values()].sort((left, right) => touchedKey(left).localeCompare(touchedKey(right))),
|
|
65
|
-
unresolvedPaths: uniqueSorted(unresolvedPaths),
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
export function compareFinalizationDeclarations(input) {
|
|
69
|
-
const mismatches = [];
|
|
70
|
-
const declaredSl = new Set(input.declaredTouchedSources.map(touchedKey));
|
|
71
|
-
const derivedSl = new Set(input.derivedTouchedSources.map(touchedKey));
|
|
72
|
-
const declaredWiki = new Set(input.declaredChangedWikiPageKeys);
|
|
73
|
-
const derivedWiki = new Set(input.derivedChangedWikiPageKeys);
|
|
74
|
-
for (const key of [...derivedSl].sort()) {
|
|
75
|
-
if (!declaredSl.has(key)) {
|
|
76
|
-
mismatches.push({ artifactKind: 'sl', key, direction: 'missing_from_adapter_declaration' });
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
for (const key of [...declaredSl].sort()) {
|
|
80
|
-
if (!derivedSl.has(key)) {
|
|
81
|
-
mismatches.push({ artifactKind: 'sl', key, direction: 'extra_in_adapter_declaration' });
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
for (const key of [...derivedWiki].sort()) {
|
|
85
|
-
if (!declaredWiki.has(key)) {
|
|
86
|
-
mismatches.push({ artifactKind: 'wiki', key, direction: 'missing_from_adapter_declaration' });
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
for (const key of [...declaredWiki].sort()) {
|
|
90
|
-
if (!derivedWiki.has(key)) {
|
|
91
|
-
mismatches.push({ artifactKind: 'wiki', key, direction: 'extra_in_adapter_declaration' });
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return mismatches;
|
|
95
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { compareFinalizationDeclarations, deriveFinalizationTouchedSources, deriveFinalizationWikiPageKeys, } from './finalization-scope.js';
|
|
3
|
-
describe('deriveFinalizationWikiPageKeys', () => {
|
|
4
|
-
it('maps changed global wiki markdown paths to page keys', () => {
|
|
5
|
-
expect(deriveFinalizationWikiPageKeys([
|
|
6
|
-
'wiki/global/historic-sql-orders.md',
|
|
7
|
-
'wiki/global/nested/page.md',
|
|
8
|
-
'README.md',
|
|
9
|
-
])).toEqual(['historic-sql-orders']);
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
describe('deriveFinalizationTouchedSources', () => {
|
|
13
|
-
it('maps standalone semantic-layer files directly', async () => {
|
|
14
|
-
const result = await deriveFinalizationTouchedSources({
|
|
15
|
-
changedPaths: ['semantic-layer/warehouse/orders.yaml'],
|
|
16
|
-
beforeSourcesByConnection: new Map(),
|
|
17
|
-
afterSourcesByConnection: new Map(),
|
|
18
|
-
});
|
|
19
|
-
expect(result).toEqual({
|
|
20
|
-
touchedSources: [{ connectionId: 'warehouse', sourceName: 'orders' }],
|
|
21
|
-
unresolvedPaths: [],
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
it('resolves aggregate _schema changes by comparing loaded source snapshots', async () => {
|
|
25
|
-
const beforeSourcesByConnection = new Map([
|
|
26
|
-
[
|
|
27
|
-
'warehouse',
|
|
28
|
-
[
|
|
29
|
-
{
|
|
30
|
-
name: 'orders',
|
|
31
|
-
grain: ['order_id'],
|
|
32
|
-
columns: [{ name: 'order_id', type: 'string' }],
|
|
33
|
-
joins: [],
|
|
34
|
-
measures: [],
|
|
35
|
-
usage: {
|
|
36
|
-
narrative: 'old',
|
|
37
|
-
frequencyTier: 'low',
|
|
38
|
-
commonFilters: [],
|
|
39
|
-
commonJoins: [],
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
],
|
|
43
|
-
],
|
|
44
|
-
]);
|
|
45
|
-
const afterSourcesByConnection = new Map([
|
|
46
|
-
[
|
|
47
|
-
'warehouse',
|
|
48
|
-
[
|
|
49
|
-
{
|
|
50
|
-
name: 'orders',
|
|
51
|
-
grain: ['order_id'],
|
|
52
|
-
columns: [{ name: 'order_id', type: 'string' }],
|
|
53
|
-
joins: [],
|
|
54
|
-
measures: [],
|
|
55
|
-
usage: {
|
|
56
|
-
narrative: 'new',
|
|
57
|
-
frequencyTier: 'high',
|
|
58
|
-
commonFilters: [],
|
|
59
|
-
commonJoins: [],
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
],
|
|
63
|
-
],
|
|
64
|
-
]);
|
|
65
|
-
const result = await deriveFinalizationTouchedSources({
|
|
66
|
-
changedPaths: ['semantic-layer/warehouse/_schema/public.yaml'],
|
|
67
|
-
beforeSourcesByConnection,
|
|
68
|
-
afterSourcesByConnection,
|
|
69
|
-
});
|
|
70
|
-
expect(result).toEqual({
|
|
71
|
-
touchedSources: [{ connectionId: 'warehouse', sourceName: 'orders' }],
|
|
72
|
-
unresolvedPaths: [],
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
it('flags aggregate _schema changes that cannot be resolved to logical sources', async () => {
|
|
76
|
-
const beforeSourcesByConnection = new Map([['warehouse', []]]);
|
|
77
|
-
const afterSourcesByConnection = new Map([['warehouse', []]]);
|
|
78
|
-
const result = await deriveFinalizationTouchedSources({
|
|
79
|
-
changedPaths: ['semantic-layer/warehouse/_schema/public.yaml'],
|
|
80
|
-
beforeSourcesByConnection,
|
|
81
|
-
afterSourcesByConnection,
|
|
82
|
-
});
|
|
83
|
-
expect(result).toEqual({
|
|
84
|
-
touchedSources: [],
|
|
85
|
-
unresolvedPaths: ['semantic-layer/warehouse/_schema/public.yaml'],
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
describe('compareFinalizationDeclarations', () => {
|
|
90
|
-
it('reports missing and extra adapter declarations', () => {
|
|
91
|
-
expect(compareFinalizationDeclarations({
|
|
92
|
-
declaredTouchedSources: [{ connectionId: 'warehouse', sourceName: 'orders' }],
|
|
93
|
-
derivedTouchedSources: [{ connectionId: 'warehouse', sourceName: 'customers' }],
|
|
94
|
-
declaredChangedWikiPageKeys: ['orders'],
|
|
95
|
-
derivedChangedWikiPageKeys: ['orders', 'patterns'],
|
|
96
|
-
})).toEqual([
|
|
97
|
-
{
|
|
98
|
-
artifactKind: 'sl',
|
|
99
|
-
key: 'warehouse:customers',
|
|
100
|
-
direction: 'missing_from_adapter_declaration',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
artifactKind: 'sl',
|
|
104
|
-
key: 'warehouse:orders',
|
|
105
|
-
direction: 'extra_in_adapter_declaration',
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
artifactKind: 'wiki',
|
|
109
|
-
key: 'patterns',
|
|
110
|
-
direction: 'missing_from_adapter_declaration',
|
|
111
|
-
},
|
|
112
|
-
]);
|
|
113
|
-
});
|
|
114
|
-
});
|