graphlin 0.1.3 → 0.2.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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +12 -3
- package/docs/decision-service.md +393 -0
- package/docs/extension-authoring.md +553 -0
- package/docs/model-api.md +293 -0
- package/docs/usage.md +472 -0
- package/docs/visualizer-views.md +240 -0
- package/node_modules/@vscode/tree-sitter-wasm/LICENSE +21 -0
- package/node_modules/@vscode/tree-sitter-wasm/README.md +36 -0
- package/node_modules/@vscode/tree-sitter-wasm/SECURITY.md +41 -0
- package/node_modules/@vscode/tree-sitter-wasm/cgmanifest.json +16 -0
- package/node_modules/@vscode/tree-sitter-wasm/package.json +42 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-bash.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-c-sharp.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-cpp.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-css.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-go.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-ini.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-java.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-javascript.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-php.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-powershell.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-python.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-regex.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-ruby.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-rust.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-tsx.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-typescript.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.js +4075 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/web-tree-sitter.d.ts +1027 -0
- package/package.json +78 -9
- package/plugin.json +4 -2
- package/runtime/architecture/analysis.mjs +344 -0
- package/runtime/architecture/controller.mjs +209 -0
- package/runtime/architecture/evidence.mjs +108 -0
- package/runtime/architecture/profile.mjs +56 -0
- package/runtime/core/evidence.mjs +43 -9
- package/runtime/core/graph.mjs +11 -6
- package/runtime/core/privacy.mjs +1 -0
- package/runtime/daemon/auth.mjs +7 -3
- package/runtime/daemon/diagnostics.mjs +1 -1
- package/runtime/daemon/extension-api.mjs +203 -0
- package/runtime/daemon/lineage.mjs +70 -0
- package/runtime/daemon/manager.mjs +9 -6
- package/runtime/daemon/model-api.mjs +728 -0
- package/runtime/daemon/model-persistence.mjs +220 -0
- package/runtime/daemon/server.mjs +81 -14
- package/runtime/daemon/settings.mjs +11 -3
- package/runtime/decisions/broker.mjs +349 -0
- package/runtime/decisions/contracts.mjs +179 -0
- package/runtime/decisions/evaluation.mjs +305 -0
- package/runtime/decisions/faults.mjs +32 -0
- package/runtime/decisions/index.mjs +818 -0
- package/runtime/decisions/profiles.mjs +93 -0
- package/runtime/decisions/questions.mjs +268 -0
- package/runtime/discovery/index.mjs +2 -0
- package/runtime/discovery/inventory.mjs +160 -0
- package/runtime/discovery/parser.mjs +40 -0
- package/runtime/discovery/structure.mjs +232 -0
- package/runtime/extensions/contracts.mjs +59 -0
- package/runtime/extensions/frame.mjs +64 -0
- package/runtime/extensions/index.mjs +9 -0
- package/runtime/extensions/manifest.mjs +95 -0
- package/runtime/extensions/packages.mjs +222 -0
- package/runtime/extensions/profiles.mjs +36 -0
- package/runtime/extensions/projection.mjs +130 -0
- package/runtime/extensions/registry.mjs +285 -0
- package/runtime/extensions/scene.mjs +105 -0
- package/runtime/extensions/sdk.d.ts +205 -0
- package/runtime/extensions/sdk.mjs +88 -0
- package/runtime/jev/index.mjs +13 -777
- package/runtime/jev/provider.mjs +101 -0
- package/runtime/jev/questions.mjs +16 -258
- package/runtime/jev/wire.mjs +17 -25
- package/runtime/model/changes.mjs +42 -0
- package/runtime/model/history.mjs +124 -0
- package/runtime/model/index.mjs +2 -0
- package/runtime/model/project-model.mjs +1020 -0
- package/runtime/model/records.mjs +240 -0
- package/runtime/pipeline.mjs +267 -55
- package/runtime/platform.mjs +254 -0
- package/runtime/visualizers/blocks.mjs +5 -0
- package/runtime/visualizers/c4.mjs +154 -0
- package/runtime/visualizers/changes.mjs +24 -0
- package/runtime/visualizers/code.mjs +5 -0
- package/runtime/visualizers/index.mjs +23 -0
- package/runtime/visualizers/structure.mjs +120 -0
- package/runtime/visualizers/timeline.mjs +66 -0
- package/runtime/web/app.js +225 -63
- package/runtime/web/extension-frame.js +128 -0
- package/runtime/web/index.html +38 -1
- package/runtime/web/model-client.js +162 -0
- package/runtime/web/platform.js +445 -0
- package/runtime/web/scene.js +111 -0
- package/runtime/web/style.css +51 -0
- package/schemas/graph.schema.json +4 -1
- package/scripts/arguments.mjs +5 -1
- package/scripts/build-packages.mjs +6 -2
- package/scripts/control.mjs +1 -1
- package/scripts/daemon.mjs +2 -1
- package/scripts/extensions.mjs +44 -0
- package/scripts/graphlin.mjs +23 -3
- package/scripts/onboarding.mjs +10 -3
- package/scripts/validate-packages.mjs +54 -8
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { opaque, plain, integer } from '../core/common.mjs';
|
|
2
|
+
import { excluded, safeText } from '../core/privacy.mjs';
|
|
3
|
+
|
|
4
|
+
export const DEFAULT_LIMITS = Object.freeze({
|
|
5
|
+
entities: 20_000, relations: 40_000, artifacts: 10_000, interpretations: 512,
|
|
6
|
+
imports: 20_000, scopes: 1_024, activity: 2_048, sessions: 64, checkpoints: 8,
|
|
7
|
+
bytes: 48 * 1024 * 1024, softBytes: 32 * 1024 * 1024,
|
|
8
|
+
checkpointBytes: 32 * 1024 * 1024, refs: 16,
|
|
9
|
+
});
|
|
10
|
+
export const id = value => typeof value === 'string' &&
|
|
11
|
+
/^[A-Za-z0-9][A-Za-z0-9_.:-]{0,159}$/.test(value) && safeText(value, 160) ? value : null;
|
|
12
|
+
export const token = (value, fallback = 'unknown') => typeof value === 'string' &&
|
|
13
|
+
/^[a-z][a-z0-9_.-]{0,63}$/.test(value) && safeText(value, 64) ? value : fallback;
|
|
14
|
+
export const label = (value, fallback = 'Unknown') => typeof value === 'string' &&
|
|
15
|
+
safeText(value, 240) && !/[\r\n<>]/.test(value) && !/^(?:\/|[a-z]+:)/i.test(value) ? value : fallback;
|
|
16
|
+
export const validity = value => ['current', 'stale', 'retracted'].includes(value) ? value : 'stale';
|
|
17
|
+
export const classification = value => ['accepted', 'tentative', 'unknown', 'stale', 'pending', 'abstained'].includes(value)
|
|
18
|
+
? value : 'unknown';
|
|
19
|
+
export const basis = value => ['metadata', 'parsed', 'lexical', 'decision', 'legacy'].includes(value) ? value : 'legacy';
|
|
20
|
+
export const interpretationNamespace = value => typeof value === 'string' &&
|
|
21
|
+
/^[a-z][a-z0-9_-]*(?:[.:][a-z0-9_-]+)+$/.test(value) && safeText(value, 80) ? value : null;
|
|
22
|
+
export const byteSize = value => Buffer.byteLength(JSON.stringify(value));
|
|
23
|
+
export const key = (prefix, ...parts) => opaque(prefix, ...parts);
|
|
24
|
+
const version = value => typeof value === 'string' && value.length <= 256 &&
|
|
25
|
+
/^[@A-Za-z0-9][A-Za-z0-9_.@+/-]*$/.test(value) && safeText(value, 256) ? value : null;
|
|
26
|
+
|
|
27
|
+
export function relativePath(value, policy = {}) {
|
|
28
|
+
if (typeof value !== 'string' || value.length > 512 || !value ||
|
|
29
|
+
/[\\:\0\r\n<>%]/.test(value) || value.split('/').some(p => !p || p === '.' || p === '..') ||
|
|
30
|
+
!safeText(value, 512) || excluded(value, policy)) return null;
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function currentPolicy(provider) {
|
|
35
|
+
const value = (typeof provider === 'function' ? provider() : provider) ?? {};
|
|
36
|
+
return {
|
|
37
|
+
readSource: value.readSource === true || value.transmitSource === true,
|
|
38
|
+
displayEvidence: value.displayEvidence !== false,
|
|
39
|
+
persistEvidence: value.persistEvidence === true,
|
|
40
|
+
excludePaths: Array.isArray(value.excludePaths) ? value.excludePaths : [],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function lineageRecord(value) {
|
|
45
|
+
if (!plain(value) || !id(value.id)) return null;
|
|
46
|
+
const branch = label(value.branch, '');
|
|
47
|
+
return {
|
|
48
|
+
id: value.id, status: token(value.status),
|
|
49
|
+
...(branch ? { branch } : {}),
|
|
50
|
+
...(typeof value.head === 'string' && /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(value.head) ? { head: value.head } : {}),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function references(values, max = DEFAULT_LIMITS.refs) {
|
|
55
|
+
if (!Array.isArray(values) || values.length > max) return null;
|
|
56
|
+
const result = [];
|
|
57
|
+
for (const value of values) {
|
|
58
|
+
if (!plain(value) || !id(value.artifactId) || !integer(value.generation, 1) ||
|
|
59
|
+
typeof value.hash !== 'string' || !/^[a-f0-9]{64}$/.test(value.hash)) return null;
|
|
60
|
+
const ref = { artifactId: value.artifactId, hash: value.hash, generation: value.generation };
|
|
61
|
+
if (integer(value.startLine, 1, 10_000_000) && integer(value.endLine, value.startLine, 10_000_000)) {
|
|
62
|
+
ref.startLine = value.startLine;
|
|
63
|
+
ref.endLine = value.endLine;
|
|
64
|
+
}
|
|
65
|
+
if (id(value.eventId)) ref.eventId = value.eventId;
|
|
66
|
+
if (id(value.extractor)) ref.extractor = value.extractor;
|
|
67
|
+
if (version(value.extractorVersion)) ref.extractorVersion = value.extractorVersion;
|
|
68
|
+
if (version(value.identityVersion)) ref.identityVersion = value.identityVersion;
|
|
69
|
+
// Intent references cannot be promoted to deterministic source support.
|
|
70
|
+
if (value.sourceClass === 'public_intent') ref.sourceClass = 'public_intent';
|
|
71
|
+
result.push(ref);
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function entityRecord(value, maxRefs) {
|
|
77
|
+
if (!plain(value) || !id(value.id)) return null;
|
|
78
|
+
const sourceRefs = references(value.sourceRefs ?? [], maxRefs);
|
|
79
|
+
if (!sourceRefs) return null;
|
|
80
|
+
const entity = {
|
|
81
|
+
id: value.id, label: label(value.label), kind: token(value.kind),
|
|
82
|
+
parentId: id(value.parentId), sourceRefs, basis: basis(value.basis),
|
|
83
|
+
validity: validity(value.validity), classification: classification(value.classification),
|
|
84
|
+
};
|
|
85
|
+
if (id(value.artifactId)) entity.artifactId = value.artifactId;
|
|
86
|
+
if (value.qualifiedName) entity.qualifiedName = label(value.qualifiedName);
|
|
87
|
+
if (id(value.sessionId)) entity.sessionId = value.sessionId;
|
|
88
|
+
if (id(value.legacyId)) entity.legacyId = value.legacyId;
|
|
89
|
+
if (relativePath(value.relativePath)) entity.relativePath = value.relativePath;
|
|
90
|
+
if (integer(value.knownAtSequence)) entity.knownAtSequence = value.knownAtSequence;
|
|
91
|
+
if (integer(value.createdAtSequence, 1)) entity.createdAtSequence = value.createdAtSequence;
|
|
92
|
+
if (value.ownership === 'unresolved') entity.ownership = 'unresolved';
|
|
93
|
+
return entity;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function relationRecord(value, maxRefs) {
|
|
97
|
+
if (!plain(value) || !id(value.id) || !id(value.source) || !id(value.target)) return null;
|
|
98
|
+
const sourceRefs = references(value.sourceRefs ?? [], maxRefs);
|
|
99
|
+
if (!sourceRefs) return null;
|
|
100
|
+
return {
|
|
101
|
+
id: value.id, source: value.source, target: value.target, kind: token(value.kind),
|
|
102
|
+
basis: basis(value.basis), validity: validity(value.validity), sourceRefs,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function interpretationRecord(value, maxRefs) {
|
|
107
|
+
if (!plain(value) || !id(value.id) || !interpretationNamespace(value.namespace)) return null;
|
|
108
|
+
const sourceRefs = references(value.sourceRefs ?? [], maxRefs);
|
|
109
|
+
if (!sourceRefs || !Array.isArray(value.entityIds) || value.entityIds.length > 256 ||
|
|
110
|
+
value.entityIds.some(value => !id(value))) return null;
|
|
111
|
+
return {
|
|
112
|
+
id: value.id, namespace: value.namespace, kind: token(value.kind),
|
|
113
|
+
label: label(value.label), entityIds: [...new Set(value.entityIds)],
|
|
114
|
+
basis: 'decision', validity: validity(value.validity),
|
|
115
|
+
classification: classification(value.classification),
|
|
116
|
+
support: ['supported', 'tentative', 'unknown', 'contradicted'].includes(value.support) ? value.support : 'unknown',
|
|
117
|
+
sourceRefs, version: id(String(value.version ?? '1')) ?? '1',
|
|
118
|
+
...(id(value.sessionId) ? { sessionId: value.sessionId } : {}),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function certificate(value) {
|
|
123
|
+
if (!plain(value) || !id(value.artifactId) || !id(value.scopeId) ||
|
|
124
|
+
!integer(value.generation, 1) || !/^[a-f0-9]{64}$/.test(value.hash)) return null;
|
|
125
|
+
const ranges = Array.isArray(value.coveredRanges) ? value.coveredRanges.slice(0, 128).flatMap(range => {
|
|
126
|
+
const startLine = Array.isArray(range) ? range[0] : range?.startLine;
|
|
127
|
+
const endLine = Array.isArray(range) ? range[1] : range?.endLine;
|
|
128
|
+
return integer(startLine, 1, 10_000_000) && integer(endLine, startLine, 10_000_000) ? [{ startLine, endLine }] : [];
|
|
129
|
+
}) : [];
|
|
130
|
+
const omissions = Array.isArray(value.omissions) ? value.omissions.slice(0, 32).map(v => token(v, 'unspecified')) : ['unspecified'];
|
|
131
|
+
const validVersions = version(String(value.version ?? '')) && version(String(value.identityVersion ?? '')) && id(value.extractor);
|
|
132
|
+
return {
|
|
133
|
+
artifactId: value.artifactId, scopeId: value.scopeId, hash: value.hash, generation: value.generation,
|
|
134
|
+
complete: value.complete === true && omissions.length === 0 && !!validVersions && ranges.length > 0 &&
|
|
135
|
+
value.coveredRanges.length === ranges.length && value.capability === 'parsed',
|
|
136
|
+
extractor: id(value.extractor) ?? 'unknown', version: version(String(value.version ?? '')) ?? 'unknown',
|
|
137
|
+
identityVersion: version(String(value.identityVersion ?? '')) ?? 'unknown',
|
|
138
|
+
coveredRanges: ranges, omissions, capability: token(value.capability),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function activityRecord(value, sequence, now) {
|
|
143
|
+
if (!plain(value)) return null;
|
|
144
|
+
const at = time(value.at ?? value.timestamp, now);
|
|
145
|
+
const record = {
|
|
146
|
+
id: id(value.id) ?? key('activity', sequence, at),
|
|
147
|
+
kind: token(value.kind, 'capture.gap'), sequence, knownAtSequence: sequence,
|
|
148
|
+
at, recordedAt: time(now, now),
|
|
149
|
+
outcome: ['pending', 'succeeded', 'failed', 'interrupted', 'denied', 'unresolved', 'observed'].includes(value.outcome)
|
|
150
|
+
? value.outcome : 'unresolved',
|
|
151
|
+
toolCategory: token(value.toolCategory, 'other'),
|
|
152
|
+
attribution: ['observed', 'correlated', 'unknown'].includes(value.attribution) ? value.attribution : 'unknown',
|
|
153
|
+
};
|
|
154
|
+
for (const field of ['sessionId', 'agentId', 'toolCallId']) if (id(value[field])) record[field] = value[field];
|
|
155
|
+
for (const field of ['entityIds', 'artifactIds']) {
|
|
156
|
+
record[field] = Array.isArray(value[field]) ? [...new Set(value[field].slice(0, 256).filter(id))] : [];
|
|
157
|
+
}
|
|
158
|
+
const sourceRefs = references(value.sourceRefs ?? []);
|
|
159
|
+
record.sourceRefs = sourceRefs ?? [];
|
|
160
|
+
// Creation is accepted only as an explicit successful observation with source
|
|
161
|
+
// version correlation. A write attempt or a new file in inventory is not one.
|
|
162
|
+
record.creation = value.creation === true && record.outcome === 'succeeded' &&
|
|
163
|
+
record.kind !== 'tool.requested' && record.sourceRefs.length > 0 &&
|
|
164
|
+
record.sourceRefs.every(ref => ref.sourceClass !== 'public_intent');
|
|
165
|
+
return record;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function time(value, fallback = 0) {
|
|
169
|
+
const number = typeof value === 'string' ? Date.parse(value) : value;
|
|
170
|
+
const safe = Number.isFinite(number) && number >= 0 && number <= 8_640_000_000_000_000 ? number : fallback;
|
|
171
|
+
return new Date(Number.isFinite(safe) ? safe : 0).toISOString();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Projection is an allowlist, including for restored state and old checkpoints. */
|
|
175
|
+
export function projectSnapshot(state, policy, { persistent = false, sessionId, scopeId } = {}) {
|
|
176
|
+
const sourceLabels = policy.readSource && policy.displayEvidence && (!persistent || policy.persistEvidence);
|
|
177
|
+
const blockedArtifacts = new Set((state.coverage.artifacts ?? []).filter(value =>
|
|
178
|
+
value.relativePath && !relativePath(value.relativePath, policy)).map(value => value.id));
|
|
179
|
+
let entities = state.entities.map(value => entityRecord(value)).filter(Boolean).map(entity => {
|
|
180
|
+
const path = relativePath(entity.relativePath, policy);
|
|
181
|
+
const metadata = path && (entity.basis === 'metadata' || ['file', 'module'].includes(entity.kind));
|
|
182
|
+
if (metadata) entity.label = path.split('/').at(-1);
|
|
183
|
+
if (!sourceLabels || blockedArtifacts.has(entity.artifactId) || entity.relativePath && !path) {
|
|
184
|
+
if (!metadata) {
|
|
185
|
+
entity.label = entity.kind === 'project' ? 'Project' : token(entity.kind, 'entity');
|
|
186
|
+
}
|
|
187
|
+
delete entity.qualifiedName;
|
|
188
|
+
}
|
|
189
|
+
if (entity.basis === 'metadata' && !path && entity.kind !== 'project') entity.label = entity.kind;
|
|
190
|
+
if (!path) delete entity.relativePath;
|
|
191
|
+
return entity;
|
|
192
|
+
});
|
|
193
|
+
if (scopeId) {
|
|
194
|
+
const children = new Map();
|
|
195
|
+
for (const entity of entities) {
|
|
196
|
+
if (!children.has(entity.parentId)) children.set(entity.parentId, []);
|
|
197
|
+
children.get(entity.parentId).push(entity.id);
|
|
198
|
+
}
|
|
199
|
+
const selected = new Set(), pending = [scopeId];
|
|
200
|
+
while (pending.length) {
|
|
201
|
+
const next = pending.pop();
|
|
202
|
+
if (selected.has(next)) continue;
|
|
203
|
+
selected.add(next);
|
|
204
|
+
pending.push(...(children.get(next) ?? []));
|
|
205
|
+
}
|
|
206
|
+
const byId = new Map(entities.map(entity => [entity.id, entity]));
|
|
207
|
+
let parent = byId.get(scopeId)?.parentId;
|
|
208
|
+
while (parent && !selected.has(parent)) { selected.add(parent); parent = byId.get(parent)?.parentId; }
|
|
209
|
+
entities = entities.filter(entity => selected.has(entity.id));
|
|
210
|
+
}
|
|
211
|
+
const entityIds = new Set(entities.map(entity => entity.id));
|
|
212
|
+
const relations = state.relations.map(value => relationRecord(value)).filter(value =>
|
|
213
|
+
value && entityIds.has(value.source) && entityIds.has(value.target));
|
|
214
|
+
const interpretations = state.interpretations.map(value => interpretationRecord(value)).filter(value =>
|
|
215
|
+
value && value.entityIds.every(entityId => entityIds.has(entityId))).map(value =>
|
|
216
|
+
sourceLabels && !value.sourceRefs.some(ref => blockedArtifacts.has(ref.artifactId)) ? value : { ...value, label: 'Interpretation' });
|
|
217
|
+
const activity = state.activity.filter(value => !sessionId || value.sessionId === sessionId).map(value => {
|
|
218
|
+
const record = activityRecord(value, value.sequence, Date.parse(value.recordedAt));
|
|
219
|
+
record.entityIds = record.entityIds.filter(value => entityIds.has(value));
|
|
220
|
+
return record;
|
|
221
|
+
});
|
|
222
|
+
const coverage = structuredClone(state.coverage);
|
|
223
|
+
coverage.scopes = (coverage.scopes ?? []).map(scope => {
|
|
224
|
+
const path = relativePath(scope.relativePath, policy);
|
|
225
|
+
return { ...scope, label: path ?? 'Scope', ...(path ? { relativePath: path } : { relativePath: undefined }) };
|
|
226
|
+
});
|
|
227
|
+
coverage.files = (coverage.files ?? []).map(file => {
|
|
228
|
+
const path = relativePath(file.relativePath, policy);
|
|
229
|
+
return { ...file, relativePath: path ?? undefined, root: relativePath(file.root, policy) ?? undefined };
|
|
230
|
+
});
|
|
231
|
+
coverage.artifacts = (coverage.artifacts ?? []).map(artifact => ({
|
|
232
|
+
...artifact, relativePath: relativePath(artifact.relativePath, policy) ?? undefined,
|
|
233
|
+
}));
|
|
234
|
+
return {
|
|
235
|
+
schemaVersion: 2, projectId: state.projectId, revision: state.revision, sequence: state.sequence,
|
|
236
|
+
entities, relations, interpretations, activity, coverage,
|
|
237
|
+
sessions: state.sessions.filter(value => !sessionId || value.id === sessionId).map(value => ({ ...value })),
|
|
238
|
+
checkpoints: state.checkpoints.map(value => ({ ...value, label: sourceLabels ? label(value.label, 'Checkpoint') : 'Checkpoint' })),
|
|
239
|
+
};
|
|
240
|
+
}
|