@unrdf/kgc-probe 26.4.2
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/README.md +414 -0
- package/package.json +81 -0
- package/src/agents/index.mjs +1402 -0
- package/src/artifact.mjs +405 -0
- package/src/cli.mjs +932 -0
- package/src/config.mjs +115 -0
- package/src/guards.mjs +1213 -0
- package/src/index.mjs +347 -0
- package/src/merge.mjs +196 -0
- package/src/observation.mjs +193 -0
- package/src/orchestrator.mjs +315 -0
- package/src/probe.mjs +58 -0
- package/src/probes/CONCURRENCY-PROBE.md +256 -0
- package/src/probes/README.md +275 -0
- package/src/probes/concurrency.mjs +1175 -0
- package/src/probes/filesystem.mjs +731 -0
- package/src/probes/filesystem.test.mjs +244 -0
- package/src/probes/network.mjs +503 -0
- package/src/probes/performance.mjs +816 -0
- package/src/probes/persistence.mjs +785 -0
- package/src/probes/runtime.mjs +589 -0
- package/src/probes/tooling.mjs +454 -0
- package/src/probes/tooling.test.mjs +372 -0
- package/src/probes/verify-execution.mjs +131 -0
- package/src/probes/verify-guards.mjs +73 -0
- package/src/probes/wasm.mjs +715 -0
- package/src/receipt.mjs +197 -0
- package/src/receipts/index.mjs +813 -0
- package/src/reporter.example.mjs +223 -0
- package/src/reporter.mjs +555 -0
- package/src/reporters/markdown.mjs +355 -0
- package/src/reporters/rdf.mjs +383 -0
- package/src/storage/index.mjs +827 -0
- package/src/types.mjs +1028 -0
- package/src/utils/errors.mjs +397 -0
- package/src/utils/index.mjs +32 -0
- package/src/utils/logger.mjs +236 -0
- package/src/vocabulary.ttl +169 -0
package/src/index.mjs
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview KGC Probe - Public API
|
|
3
|
+
*
|
|
4
|
+
* High-level entry points for:
|
|
5
|
+
* - Creating probe orchestrator instances
|
|
6
|
+
* - Registering guards and agents
|
|
7
|
+
* - Running scans and merging results
|
|
8
|
+
* - Validating artifacts
|
|
9
|
+
* - KGC Markdown document validation (frontmatter, blocks, receipts)
|
|
10
|
+
*
|
|
11
|
+
* @module @unrdf/kgc-probe
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// ORCHESTRATOR
|
|
16
|
+
// ============================================================================
|
|
17
|
+
|
|
18
|
+
export { createProbeOrchestrator, ProbeOrchestrator } from './orchestrator.mjs';
|
|
19
|
+
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// GUARDS REGISTRY
|
|
22
|
+
// ============================================================================
|
|
23
|
+
|
|
24
|
+
export { createGuardRegistry, GuardRegistry, PATTERNS } from './guards.mjs';
|
|
25
|
+
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// OBSERVATION VALIDATOR
|
|
28
|
+
// ============================================================================
|
|
29
|
+
|
|
30
|
+
export { createObservationValidator, ObservationValidator } from './artifact.mjs';
|
|
31
|
+
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// AGENTS (Factory Functions for 10 probe agents)
|
|
34
|
+
// ============================================================================
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
// Registry
|
|
38
|
+
createAgentRegistry,
|
|
39
|
+
AgentRegistry,
|
|
40
|
+
Agent,
|
|
41
|
+
|
|
42
|
+
// 10 Domain Agents
|
|
43
|
+
OrchestratorAgent,
|
|
44
|
+
RuntimeAgent,
|
|
45
|
+
FilesystemAgent,
|
|
46
|
+
WasmAgent,
|
|
47
|
+
PerformanceAgent,
|
|
48
|
+
NetworkAgent,
|
|
49
|
+
ToolingAgent,
|
|
50
|
+
StorageAgent,
|
|
51
|
+
ConcurrencyAgent,
|
|
52
|
+
SystemAgent,
|
|
53
|
+
|
|
54
|
+
// Factory functions
|
|
55
|
+
createOrchestratorAgent,
|
|
56
|
+
createRuntimeAgent,
|
|
57
|
+
createFilesystemAgent,
|
|
58
|
+
createWasmAgent,
|
|
59
|
+
createPerformanceAgent,
|
|
60
|
+
createNetworkAgent,
|
|
61
|
+
createToolingAgent,
|
|
62
|
+
createStorageAgent,
|
|
63
|
+
createConcurrencyAgent,
|
|
64
|
+
createSystemAgent,
|
|
65
|
+
|
|
66
|
+
// Backward compatibility
|
|
67
|
+
CompletionAgent,
|
|
68
|
+
ConsistencyAgent,
|
|
69
|
+
ConformanceAgent,
|
|
70
|
+
CoverageAgent,
|
|
71
|
+
CachingAgent,
|
|
72
|
+
CompletenessAgent,
|
|
73
|
+
CoherenceAgent,
|
|
74
|
+
ClusteringAgent,
|
|
75
|
+
ClassificationAgent,
|
|
76
|
+
CollaborationAgent,
|
|
77
|
+
createCompletionAgent,
|
|
78
|
+
createConsistencyAgent,
|
|
79
|
+
createConformanceAgent,
|
|
80
|
+
createCoverageAgent,
|
|
81
|
+
createCachingAgent,
|
|
82
|
+
createCompletenessAgent,
|
|
83
|
+
createCoherenceAgent,
|
|
84
|
+
createClusteringAgent,
|
|
85
|
+
createClassificationAgent,
|
|
86
|
+
createCollaborationAgent
|
|
87
|
+
} from './agents/index.mjs';
|
|
88
|
+
|
|
89
|
+
// ============================================================================
|
|
90
|
+
// STORAGE BACKENDS
|
|
91
|
+
// ============================================================================
|
|
92
|
+
|
|
93
|
+
export {
|
|
94
|
+
MemoryStorage,
|
|
95
|
+
FileStorage,
|
|
96
|
+
DatabaseStorage,
|
|
97
|
+
createMemoryStorage,
|
|
98
|
+
createFileStorage,
|
|
99
|
+
createDatabaseStorage,
|
|
100
|
+
createStorage
|
|
101
|
+
} from './storage/index.mjs';
|
|
102
|
+
|
|
103
|
+
// ============================================================================
|
|
104
|
+
// RECEIPTS
|
|
105
|
+
// ============================================================================
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
// Constants
|
|
109
|
+
HASH_ALGORITHM,
|
|
110
|
+
RECEIPT_VERSION,
|
|
111
|
+
RECEIPT_TYPES,
|
|
112
|
+
|
|
113
|
+
// Hash utilities
|
|
114
|
+
computeHash,
|
|
115
|
+
computeChainHash,
|
|
116
|
+
deterministicSerialize,
|
|
117
|
+
|
|
118
|
+
// Merkle
|
|
119
|
+
buildMerkleTree,
|
|
120
|
+
verifyMerkleRoot,
|
|
121
|
+
|
|
122
|
+
// Receipt creation
|
|
123
|
+
createObservationReceipt,
|
|
124
|
+
createMergeReceipt,
|
|
125
|
+
createVerificationReceipt,
|
|
126
|
+
|
|
127
|
+
// Verification
|
|
128
|
+
verifyObservationReceipt,
|
|
129
|
+
verifyMergeReceipt,
|
|
130
|
+
verifyVerificationReceipt,
|
|
131
|
+
|
|
132
|
+
// Confidence
|
|
133
|
+
calculateConfidenceScore,
|
|
134
|
+
getFailedChecks,
|
|
135
|
+
summarizeVerification,
|
|
136
|
+
|
|
137
|
+
// Chain builder
|
|
138
|
+
ReceiptChainBuilder,
|
|
139
|
+
createReceiptChainBuilder
|
|
140
|
+
} from './receipts/index.mjs';
|
|
141
|
+
|
|
142
|
+
// ============================================================================
|
|
143
|
+
// ARTIFACT OPERATIONS
|
|
144
|
+
// ============================================================================
|
|
145
|
+
|
|
146
|
+
export {
|
|
147
|
+
mergeShards,
|
|
148
|
+
diffArtifacts,
|
|
149
|
+
verifyArtifact,
|
|
150
|
+
serializeArtifact,
|
|
151
|
+
deserializeArtifact,
|
|
152
|
+
hashObservations,
|
|
153
|
+
computeArtifactSummary
|
|
154
|
+
} from './artifact.mjs';
|
|
155
|
+
|
|
156
|
+
// ============================================================================
|
|
157
|
+
// CONVENIENCE: FULL SCAN
|
|
158
|
+
// ============================================================================
|
|
159
|
+
|
|
160
|
+
export { runProbe } from './probe.mjs';
|
|
161
|
+
|
|
162
|
+
// ============================================================================
|
|
163
|
+
// ZOD SCHEMAS (All schemas from SPARC specification)
|
|
164
|
+
// ============================================================================
|
|
165
|
+
|
|
166
|
+
export {
|
|
167
|
+
// Constants & Regexes
|
|
168
|
+
SHA256_REGEX,
|
|
169
|
+
UUID_V4_REGEX,
|
|
170
|
+
SEMVER_REGEX,
|
|
171
|
+
|
|
172
|
+
// KGC Markdown Frontmatter Schemas (Domain 1)
|
|
173
|
+
SourceSchema,
|
|
174
|
+
BoundsSchema,
|
|
175
|
+
AuthorSchema,
|
|
176
|
+
DiatasisViewSchema,
|
|
177
|
+
FrontmatterSchema,
|
|
178
|
+
|
|
179
|
+
// Block Metadata Schemas (Domain 2)
|
|
180
|
+
BlockTypeSchema,
|
|
181
|
+
OutputFormatSchema,
|
|
182
|
+
DeterminismLevelSchema,
|
|
183
|
+
BlockMetadataSchema,
|
|
184
|
+
QueryTypeSchema,
|
|
185
|
+
ResultBoundsSchema,
|
|
186
|
+
QueryMetadataSchema,
|
|
187
|
+
ExtractionTypeSchema,
|
|
188
|
+
ExtractMetadataSchema,
|
|
189
|
+
RenderMetadataSchema,
|
|
190
|
+
ProofTypeSchema,
|
|
191
|
+
ProofMetadataSchema,
|
|
192
|
+
|
|
193
|
+
// Receipt Schemas (Domain 3)
|
|
194
|
+
DecisionSchema,
|
|
195
|
+
MerkleProofSchema,
|
|
196
|
+
ReceiptSchema,
|
|
197
|
+
|
|
198
|
+
// Dynamic Section Schemas (Domain 4)
|
|
199
|
+
DynamicSectionSchema,
|
|
200
|
+
|
|
201
|
+
// Error Schemas (Domain 10)
|
|
202
|
+
ErrorSeveritySchema,
|
|
203
|
+
ErrorTypeSchema,
|
|
204
|
+
ProbeErrorSchema,
|
|
205
|
+
ProbeWarningSchema,
|
|
206
|
+
|
|
207
|
+
// Probe Report Schemas
|
|
208
|
+
DomainResultSchema,
|
|
209
|
+
ProbeReportSchema,
|
|
210
|
+
|
|
211
|
+
// Observation & Artifact Schemas
|
|
212
|
+
ObservationSchema,
|
|
213
|
+
ObservationType,
|
|
214
|
+
ArtifactSummarySchema,
|
|
215
|
+
ArtifactSchema,
|
|
216
|
+
ArtifactType,
|
|
217
|
+
|
|
218
|
+
// Configuration Schemas
|
|
219
|
+
ProbeConfigSchema,
|
|
220
|
+
GuardConfigSchema,
|
|
221
|
+
StorageConfigSchema,
|
|
222
|
+
|
|
223
|
+
// Agent & Guard Schemas
|
|
224
|
+
AgentSchema,
|
|
225
|
+
GuardViolationSchema,
|
|
226
|
+
GuardViolationType,
|
|
227
|
+
|
|
228
|
+
// Diff & Result Schemas
|
|
229
|
+
DiffResultSchema,
|
|
230
|
+
DiffResultType,
|
|
231
|
+
ScanResultSchema,
|
|
232
|
+
ScanResultType
|
|
233
|
+
} from './types.mjs';
|
|
234
|
+
|
|
235
|
+
// ============================================================================
|
|
236
|
+
// FACTORY FUNCTIONS (25 factories per SPARC specification)
|
|
237
|
+
// ============================================================================
|
|
238
|
+
|
|
239
|
+
export {
|
|
240
|
+
// Frontmatter & Sources
|
|
241
|
+
createFrontmatter,
|
|
242
|
+
createBounds,
|
|
243
|
+
createSource,
|
|
244
|
+
createAuthor,
|
|
245
|
+
|
|
246
|
+
// Block Metadata
|
|
247
|
+
createBlockMetadata,
|
|
248
|
+
createQueryMetadata,
|
|
249
|
+
createExtractMetadata,
|
|
250
|
+
createRenderMetadata,
|
|
251
|
+
createProofMetadata,
|
|
252
|
+
|
|
253
|
+
// Receipts & Proofs
|
|
254
|
+
createReceipt,
|
|
255
|
+
createMerkleProof,
|
|
256
|
+
|
|
257
|
+
// Observations
|
|
258
|
+
createObservation,
|
|
259
|
+
|
|
260
|
+
// Dynamic Sections
|
|
261
|
+
createDynamicSection,
|
|
262
|
+
|
|
263
|
+
// Errors & Warnings
|
|
264
|
+
createProbeError,
|
|
265
|
+
createProbeWarning,
|
|
266
|
+
|
|
267
|
+
// Reports & Results
|
|
268
|
+
createDomainResult,
|
|
269
|
+
createProbeReport,
|
|
270
|
+
|
|
271
|
+
// Configuration
|
|
272
|
+
createProbeConfig
|
|
273
|
+
} from './types.mjs';
|
|
274
|
+
|
|
275
|
+
// ============================================================================
|
|
276
|
+
// VALIDATION FUNCTIONS
|
|
277
|
+
// ============================================================================
|
|
278
|
+
|
|
279
|
+
export {
|
|
280
|
+
validateObservation,
|
|
281
|
+
validateArtifact,
|
|
282
|
+
validateProbeConfig,
|
|
283
|
+
validateFrontmatter,
|
|
284
|
+
validateReceipt,
|
|
285
|
+
tryValidateObservation,
|
|
286
|
+
tryValidateFrontmatter,
|
|
287
|
+
tryValidateReceipt
|
|
288
|
+
} from './types.mjs';
|
|
289
|
+
|
|
290
|
+
// ============================================================================
|
|
291
|
+
// CLI COMMANDS
|
|
292
|
+
// ============================================================================
|
|
293
|
+
|
|
294
|
+
export {
|
|
295
|
+
scanCommand,
|
|
296
|
+
mergeCommand,
|
|
297
|
+
diffCommand,
|
|
298
|
+
reportCommand,
|
|
299
|
+
verifyCommand,
|
|
300
|
+
probeExtension,
|
|
301
|
+
ScanArgsSchema,
|
|
302
|
+
MergeArgsSchema,
|
|
303
|
+
DiffArgsSchema,
|
|
304
|
+
ReportArgsSchema,
|
|
305
|
+
VerifyArgsSchema
|
|
306
|
+
} from './cli.mjs';
|
|
307
|
+
|
|
308
|
+
// ============================================================================
|
|
309
|
+
// UTILITIES (Logger, Errors)
|
|
310
|
+
// ============================================================================
|
|
311
|
+
|
|
312
|
+
export {
|
|
313
|
+
Logger,
|
|
314
|
+
createLogger,
|
|
315
|
+
defaultLogger,
|
|
316
|
+
LOG_LEVELS
|
|
317
|
+
} from './utils/logger.mjs';
|
|
318
|
+
|
|
319
|
+
export {
|
|
320
|
+
ProbeError,
|
|
321
|
+
GuardViolationError,
|
|
322
|
+
ValidationError,
|
|
323
|
+
MergeConflictError,
|
|
324
|
+
ReceiptError,
|
|
325
|
+
ArtifactNotFoundError,
|
|
326
|
+
TimeoutError,
|
|
327
|
+
AgentError,
|
|
328
|
+
StorageError,
|
|
329
|
+
ConfigurationError,
|
|
330
|
+
ErrorCodes,
|
|
331
|
+
isProbeError,
|
|
332
|
+
wrapError
|
|
333
|
+
} from './utils/errors.mjs';
|
|
334
|
+
|
|
335
|
+
// ============================================================================
|
|
336
|
+
// DEFAULT EXPORT (Package Metadata)
|
|
337
|
+
// ============================================================================
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Package metadata
|
|
341
|
+
* @type {Object}
|
|
342
|
+
*/
|
|
343
|
+
export default {
|
|
344
|
+
name: '@unrdf/kgc-probe',
|
|
345
|
+
version: '1.0.0',
|
|
346
|
+
description: 'KGC Probe - Automated knowledge graph integrity scanning with 10 agents and artifact validation'
|
|
347
|
+
};
|
package/src/merge.mjs
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Deterministic merge logic for KGC Probe observations
|
|
4
|
+
*
|
|
5
|
+
* Merges observations from multiple agents with stable, deterministic ordering.
|
|
6
|
+
* Guarantees: Same input → same output hash (critical for receipt verification).
|
|
7
|
+
*
|
|
8
|
+
* Design principles:
|
|
9
|
+
* - Deterministic: Stable sort order, canonical representation
|
|
10
|
+
* - Composable: Works with any observation source
|
|
11
|
+
* - Verifiable: Produces consistent hashes
|
|
12
|
+
* - Fast: O(n log n) merge with minimal overhead
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Severity order for stable sorting (highest priority first)
|
|
17
|
+
*/
|
|
18
|
+
const SEVERITY_ORDER = {
|
|
19
|
+
fatal: 0,
|
|
20
|
+
error: 1,
|
|
21
|
+
warn: 2,
|
|
22
|
+
info: 3,
|
|
23
|
+
debug: 4,
|
|
24
|
+
trace: 5
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Merge observations from multiple sources with deterministic ordering
|
|
29
|
+
*
|
|
30
|
+
* Stable sort order:
|
|
31
|
+
* 1. Category (alphabetical)
|
|
32
|
+
* 2. Severity (fatal > error > warn > info > debug > trace)
|
|
33
|
+
* 3. File path (alphabetical)
|
|
34
|
+
* 4. Line number (ascending)
|
|
35
|
+
* 5. Agent ID (alphabetical)
|
|
36
|
+
* 6. Timestamp (ascending)
|
|
37
|
+
*
|
|
38
|
+
* @param {import('./observation.mjs').Observation[]} observations - Observations to merge
|
|
39
|
+
* @returns {import('./observation.mjs').Observation[]} - Sorted observations
|
|
40
|
+
*/
|
|
41
|
+
export function mergeObservations(observations) {
|
|
42
|
+
// Stable sort (creates new array)
|
|
43
|
+
return observations.slice().sort((a, b) => {
|
|
44
|
+
// 1. Category (alphabetical)
|
|
45
|
+
if (a.category !== b.category) {
|
|
46
|
+
return a.category.localeCompare(b.category);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 2. Severity (fatal > error > warn > info > debug > trace)
|
|
50
|
+
if (a.severity !== b.severity) {
|
|
51
|
+
return SEVERITY_ORDER[a.severity] - SEVERITY_ORDER[b.severity];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 3. File path (alphabetical)
|
|
55
|
+
const aFile = a.location?.file || '';
|
|
56
|
+
const bFile = b.location?.file || '';
|
|
57
|
+
if (aFile !== bFile) {
|
|
58
|
+
return aFile.localeCompare(bFile);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 4. Line number (ascending)
|
|
62
|
+
const aLine = a.location?.line || 0;
|
|
63
|
+
const bLine = b.location?.line || 0;
|
|
64
|
+
if (aLine !== bLine) {
|
|
65
|
+
return aLine - bLine;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 5. Agent ID (alphabetical)
|
|
69
|
+
if (a.metadata.agentId !== b.metadata.agentId) {
|
|
70
|
+
return a.metadata.agentId.localeCompare(b.metadata.agentId);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 6. Timestamp (ascending)
|
|
74
|
+
return a.metadata.timestamp.localeCompare(b.metadata.timestamp);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Merge observations from multiple agent shards
|
|
80
|
+
*
|
|
81
|
+
* @param {Map<string, import('./observation.mjs').Observation[]>} shards - Agent ID → observations
|
|
82
|
+
* @returns {import('./observation.mjs').Observation[]} - Merged and sorted observations
|
|
83
|
+
*/
|
|
84
|
+
export function mergeShards(shards) {
|
|
85
|
+
const allObservations = [];
|
|
86
|
+
|
|
87
|
+
for (const [agentId, observations] of shards.entries()) {
|
|
88
|
+
allObservations.push(...observations);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return mergeObservations(allObservations);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Deduplicate observations by content hash
|
|
96
|
+
*
|
|
97
|
+
* Useful when multiple agents might emit identical observations.
|
|
98
|
+
*
|
|
99
|
+
* @param {import('./observation.mjs').Observation[]} observations
|
|
100
|
+
* @returns {import('./observation.mjs').Observation[]}
|
|
101
|
+
*/
|
|
102
|
+
export function deduplicateObservations(observations) {
|
|
103
|
+
const seen = new Set();
|
|
104
|
+
const unique = [];
|
|
105
|
+
|
|
106
|
+
for (const obs of observations) {
|
|
107
|
+
// Create deterministic content key
|
|
108
|
+
const key = JSON.stringify({
|
|
109
|
+
category: obs.category,
|
|
110
|
+
severity: obs.severity,
|
|
111
|
+
message: obs.message,
|
|
112
|
+
location: obs.location,
|
|
113
|
+
data: obs.data,
|
|
114
|
+
tags: obs.tags.slice().sort()
|
|
115
|
+
}, Object.keys(obs).sort());
|
|
116
|
+
|
|
117
|
+
if (!seen.has(key)) {
|
|
118
|
+
seen.add(key);
|
|
119
|
+
unique.push(obs);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return unique;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Group observations by category
|
|
128
|
+
*
|
|
129
|
+
* @param {import('./observation.mjs').Observation[]} observations
|
|
130
|
+
* @returns {Map<string, import('./observation.mjs').Observation[]>}
|
|
131
|
+
*/
|
|
132
|
+
export function groupByCategory(observations) {
|
|
133
|
+
const groups = new Map();
|
|
134
|
+
|
|
135
|
+
for (const obs of observations) {
|
|
136
|
+
if (!groups.has(obs.category)) {
|
|
137
|
+
groups.set(obs.category, []);
|
|
138
|
+
}
|
|
139
|
+
groups.get(obs.category).push(obs);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return groups;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Group observations by severity
|
|
147
|
+
*
|
|
148
|
+
* @param {import('./observation.mjs').Observation[]} observations
|
|
149
|
+
* @returns {Map<string, import('./observation.mjs').Observation[]>}
|
|
150
|
+
*/
|
|
151
|
+
export function groupBySeverity(observations) {
|
|
152
|
+
const groups = new Map();
|
|
153
|
+
|
|
154
|
+
for (const obs of observations) {
|
|
155
|
+
if (!groups.has(obs.severity)) {
|
|
156
|
+
groups.set(obs.severity, []);
|
|
157
|
+
}
|
|
158
|
+
groups.get(obs.severity).push(obs);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return groups;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Filter observations by category
|
|
166
|
+
*
|
|
167
|
+
* @param {import('./observation.mjs').Observation[]} observations
|
|
168
|
+
* @param {string[]} categories - Categories to include
|
|
169
|
+
* @returns {import('./observation.mjs').Observation[]}
|
|
170
|
+
*/
|
|
171
|
+
export function filterByCategory(observations, categories) {
|
|
172
|
+
const categorySet = new Set(categories);
|
|
173
|
+
return observations.filter(obs => categorySet.has(obs.category));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Filter observations by severity (minimum level)
|
|
178
|
+
*
|
|
179
|
+
* @param {import('./observation.mjs').Observation[]} observations
|
|
180
|
+
* @param {string} minSeverity - Minimum severity level
|
|
181
|
+
* @returns {import('./observation.mjs').Observation[]}
|
|
182
|
+
*/
|
|
183
|
+
export function filterBySeverity(observations, minSeverity) {
|
|
184
|
+
const minLevel = SEVERITY_ORDER[minSeverity];
|
|
185
|
+
return observations.filter(obs => SEVERITY_ORDER[obs.severity] <= minLevel);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export default {
|
|
189
|
+
mergeObservations,
|
|
190
|
+
mergeShards,
|
|
191
|
+
deduplicateObservations,
|
|
192
|
+
groupByCategory,
|
|
193
|
+
groupBySeverity,
|
|
194
|
+
filterByCategory,
|
|
195
|
+
filterBySeverity
|
|
196
|
+
};
|