@unrdf/knowledge-engine 5.0.1 → 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/package.json +23 -17
- package/src/ai-enhanced-search.mjs +371 -0
- package/src/anomaly-detector.mjs +226 -0
- package/src/artifact-generator.mjs +252 -0
- package/src/browser.mjs +1 -1
- package/src/chatman/disruption-arithmetic.mjs +140 -0
- package/src/chatman/market-dynamics.mjs +140 -0
- package/src/chatman/organizational-dynamics.mjs +140 -0
- package/src/chatman/strategic-dynamics.mjs +140 -0
- package/src/chatman-config-loader.mjs +282 -0
- package/src/chatman-engine.mjs +435 -0
- package/src/chatman-operator.mjs +343 -0
- package/src/dark-field-detector.mjs +332 -0
- package/src/formation-theorems.mjs +345 -0
- package/src/index.mjs +20 -2
- package/src/knowledge-hook-manager.mjs +1 -1
- package/src/lockchain-writer-browser.mjs +2 -2
- package/src/observability.mjs +40 -4
- package/src/query-optimizer.mjs +1 -1
- package/src/resolution-layer.mjs +1 -1
- package/src/transaction.mjs +11 -9
- package/README.md +0 -84
- package/src/browser-shims.mjs +0 -343
- package/src/canonicalize.mjs +0 -414
- package/src/condition-cache.mjs +0 -109
- package/src/condition-evaluator.mjs +0 -722
- package/src/dark-matter-core.mjs +0 -742
- package/src/define-hook.mjs +0 -213
- package/src/effect-sandbox-browser.mjs +0 -283
- package/src/effect-sandbox-worker.mjs +0 -170
- package/src/effect-sandbox.mjs +0 -517
- package/src/engines/index.mjs +0 -11
- package/src/engines/rdf-engine.mjs +0 -299
- package/src/file-resolver.mjs +0 -387
- package/src/hook-executor-batching.mjs +0 -277
- package/src/hook-executor.mjs +0 -870
- package/src/hook-management.mjs +0 -150
- package/src/ken-parliment.mjs +0 -119
- package/src/ken.mjs +0 -149
- package/src/knowledge-engine/builtin-rules.mjs +0 -190
- package/src/knowledge-engine/inference-engine.mjs +0 -418
- package/src/knowledge-engine/knowledge-engine.mjs +0 -317
- package/src/knowledge-engine/pattern-dsl.mjs +0 -142
- package/src/knowledge-engine/pattern-matcher.mjs +0 -215
- package/src/knowledge-engine/rules.mjs +0 -184
- package/src/knowledge-engine.mjs +0 -319
- package/src/knowledge-hook-engine.mjs +0 -360
- package/src/knowledge-substrate-core.mjs +0 -927
- package/src/lite.mjs +0 -222
- package/src/lockchain-writer.mjs +0 -602
- package/src/monitoring/andon-signals.mjs +0 -775
- package/src/parse.mjs +0 -290
- package/src/performance-optimizer.mjs +0 -678
- package/src/policy-pack.mjs +0 -572
- package/src/query-cache.mjs +0 -116
- package/src/query.mjs +0 -306
- package/src/reason.mjs +0 -350
- package/src/schemas.mjs +0 -1063
- package/src/security/error-sanitizer.mjs +0 -257
- package/src/security/path-validator.mjs +0 -194
- package/src/security/sandbox-restrictions.mjs +0 -331
- package/src/security-validator.mjs +0 -389
- package/src/store-cache.mjs +0 -137
- package/src/telemetry.mjs +0 -167
- package/src/utils/adaptive-monitor.mjs +0 -746
- package/src/utils/circuit-breaker.mjs +0 -513
- package/src/utils/edge-case-handler.mjs +0 -503
- package/src/utils/memory-manager.mjs +0 -498
- package/src/utils/ring-buffer.mjs +0 -282
- package/src/validate.mjs +0 -319
- package/src/validators/index.mjs +0 -338
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Chatman Operator - μ Closure Operator Implementation
|
|
3
|
+
* @module knowledge-engine/chatman-operator
|
|
4
|
+
*
|
|
5
|
+
* @description
|
|
6
|
+
* Implements the μ (mu) closure operator from the Chatman Equation.
|
|
7
|
+
* The μ operator calculates the closure of observable patterns to reveal
|
|
8
|
+
* the complete artifact space including invisible dark field components.
|
|
9
|
+
*
|
|
10
|
+
* Core Formula: A = μ(O)
|
|
11
|
+
* Where:
|
|
12
|
+
* - A = Complete artifact space (100%)
|
|
13
|
+
* - μ = Closure operator
|
|
14
|
+
* - O = Observable patterns (~5%)
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { randomUUID } from 'crypto';
|
|
18
|
+
import { z } from 'zod';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Observable pattern schema
|
|
22
|
+
*/
|
|
23
|
+
export const ObservablePatternSchema = z.object({
|
|
24
|
+
id: z.string().uuid().optional(),
|
|
25
|
+
type: z.enum(['market', 'organizational', 'strategic', 'disruption']),
|
|
26
|
+
patterns: z.array(z.string()).min(1),
|
|
27
|
+
visibility: z.number().min(0).max(1).default(0.05),
|
|
28
|
+
metadata: z.record(z.unknown()).optional(),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Closure result schema
|
|
33
|
+
*/
|
|
34
|
+
export const ClosureResultSchema = z.object({
|
|
35
|
+
observable: ObservablePatternSchema,
|
|
36
|
+
darkField: z.object({
|
|
37
|
+
patterns: z.array(z.string()),
|
|
38
|
+
visibility: z.number(),
|
|
39
|
+
coverage: z.number(),
|
|
40
|
+
}),
|
|
41
|
+
completeness: z.number().min(0).max(1),
|
|
42
|
+
timestamp: z.number(),
|
|
43
|
+
operatorId: z.string().uuid(),
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Chatman μ operator - Calculates closure of observable patterns
|
|
48
|
+
*/
|
|
49
|
+
export class ChatmanOperator {
|
|
50
|
+
/**
|
|
51
|
+
* Create a new Chatman operator
|
|
52
|
+
* @param {Object} [options] - Operator options
|
|
53
|
+
* @param {number} [options.observableRatio=0.05] - Observable to dark field ratio (5% default)
|
|
54
|
+
* @param {number} [options.closureThreshold=0.95] - Minimum completeness threshold
|
|
55
|
+
* @param {Function} [options.tracer] - OTEL tracer function
|
|
56
|
+
*/
|
|
57
|
+
constructor(options = {}) {
|
|
58
|
+
this.observableRatio = options.observableRatio ?? 0.05;
|
|
59
|
+
this.closureThreshold = options.closureThreshold ?? 0.95;
|
|
60
|
+
this.tracer = options.tracer;
|
|
61
|
+
this.operatorId = randomUUID();
|
|
62
|
+
this.metrics = {
|
|
63
|
+
closureOperations: 0,
|
|
64
|
+
averageCompleteness: 0,
|
|
65
|
+
totalDarkFieldRevealed: 0,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Apply μ operator to observable patterns to compute closure
|
|
71
|
+
* @param {Object} observable - Observable pattern
|
|
72
|
+
* @returns {Promise<Object>} Closure result
|
|
73
|
+
*/
|
|
74
|
+
async apply(observable) {
|
|
75
|
+
const span = this.tracer?.startSpan?.('chatman.operator.apply');
|
|
76
|
+
const startTime = Date.now();
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
// Validate input
|
|
80
|
+
const validated = ObservablePatternSchema.parse(observable);
|
|
81
|
+
if (!validated.id) {
|
|
82
|
+
validated.id = randomUUID();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
span?.setAttribute?.('pattern.type', validated.type);
|
|
86
|
+
span?.setAttribute?.('pattern.count', validated.patterns.length);
|
|
87
|
+
|
|
88
|
+
// Calculate dark field using closure operator
|
|
89
|
+
const darkField = this._calculateDarkField(validated);
|
|
90
|
+
|
|
91
|
+
// Compute completeness metric
|
|
92
|
+
const completeness = this._computeCompleteness(validated, darkField);
|
|
93
|
+
|
|
94
|
+
span?.setAttribute?.('completeness', completeness);
|
|
95
|
+
span?.setAttribute?.('dark_field_size', darkField.patterns.length);
|
|
96
|
+
|
|
97
|
+
const result = {
|
|
98
|
+
observable: validated,
|
|
99
|
+
darkField,
|
|
100
|
+
completeness,
|
|
101
|
+
timestamp: Date.now(),
|
|
102
|
+
operatorId: this.operatorId,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Update metrics
|
|
106
|
+
this.metrics.closureOperations++;
|
|
107
|
+
this.metrics.averageCompleteness =
|
|
108
|
+
(this.metrics.averageCompleteness * (this.metrics.closureOperations - 1) +
|
|
109
|
+
completeness) /
|
|
110
|
+
this.metrics.closureOperations;
|
|
111
|
+
this.metrics.totalDarkFieldRevealed += darkField.patterns.length;
|
|
112
|
+
|
|
113
|
+
span?.addEvent?.('closure_computed', {
|
|
114
|
+
'closure.completeness': completeness,
|
|
115
|
+
'closure.duration_ms': Date.now() - startTime,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
return ClosureResultSchema.parse(result);
|
|
119
|
+
} catch (error) {
|
|
120
|
+
span?.recordException?.(error);
|
|
121
|
+
span?.setStatus?.({ code: 2, message: error.message }); // ERROR
|
|
122
|
+
throw error;
|
|
123
|
+
} finally {
|
|
124
|
+
span?.end?.();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Calculate dark field patterns from observable patterns
|
|
130
|
+
* @param {Object} observable - Observable pattern
|
|
131
|
+
* @returns {Object} Dark field
|
|
132
|
+
* @private
|
|
133
|
+
*/
|
|
134
|
+
_calculateDarkField(observable) {
|
|
135
|
+
const observableCount = observable.patterns.length;
|
|
136
|
+
|
|
137
|
+
// μ(O) = O ∪ DarkField
|
|
138
|
+
// where |DarkField| ≈ |O| * (1/observableRatio - 1)
|
|
139
|
+
const darkFieldMultiplier = 1 / this.observableRatio - 1;
|
|
140
|
+
const darkFieldSize = Math.floor(observableCount * darkFieldMultiplier);
|
|
141
|
+
|
|
142
|
+
// Generate dark field patterns based on observable type
|
|
143
|
+
const darkFieldPatterns = this._generateDarkFieldPatterns(
|
|
144
|
+
observable.type,
|
|
145
|
+
observable.patterns,
|
|
146
|
+
darkFieldSize
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
patterns: darkFieldPatterns,
|
|
151
|
+
visibility: 1 - this.observableRatio,
|
|
152
|
+
coverage: darkFieldSize / (darkFieldSize + observableCount),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Generate dark field patterns based on type and observables
|
|
158
|
+
* @param {string} type - Pattern type
|
|
159
|
+
* @param {Array<string>} observablePatterns - Observable patterns
|
|
160
|
+
* @param {number} targetSize - Target dark field size
|
|
161
|
+
* @returns {Array<string>} Dark field patterns
|
|
162
|
+
* @private
|
|
163
|
+
*/
|
|
164
|
+
_generateDarkFieldPatterns(type, observablePatterns, targetSize) {
|
|
165
|
+
const darkField = [];
|
|
166
|
+
const generators = {
|
|
167
|
+
market: this._generateMarketDarkField.bind(this),
|
|
168
|
+
organizational: this._generateOrganizationalDarkField.bind(this),
|
|
169
|
+
strategic: this._generateStrategicDarkField.bind(this),
|
|
170
|
+
disruption: this._generateDisruptionDarkField.bind(this),
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const generator = generators[type] || generators.market;
|
|
174
|
+
return generator(observablePatterns, targetSize);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Generate market dynamics dark field
|
|
179
|
+
* @param {Array<string>} patterns - Observable patterns
|
|
180
|
+
* @param {number} size - Target size
|
|
181
|
+
* @returns {Array<string>} Dark field patterns
|
|
182
|
+
* @private
|
|
183
|
+
*/
|
|
184
|
+
_generateMarketDarkField(patterns, size) {
|
|
185
|
+
const darkField = [];
|
|
186
|
+
const dimensions = [
|
|
187
|
+
'hidden_customer_needs',
|
|
188
|
+
'latent_market_segments',
|
|
189
|
+
'unspoken_value_drivers',
|
|
190
|
+
'invisible_competition',
|
|
191
|
+
'emergent_demand_patterns',
|
|
192
|
+
'tacit_buying_criteria',
|
|
193
|
+
'underground_distribution_channels',
|
|
194
|
+
'implicit_price_expectations',
|
|
195
|
+
];
|
|
196
|
+
|
|
197
|
+
for (let i = 0; i < size; i++) {
|
|
198
|
+
const dimension = dimensions[i % dimensions.length];
|
|
199
|
+
const patternIndex = i % patterns.length;
|
|
200
|
+
darkField.push(`${dimension}:derived_from:${patterns[patternIndex]}`);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return darkField;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Generate organizational dynamics dark field
|
|
208
|
+
* @param {Array<string>} patterns - Observable patterns
|
|
209
|
+
* @param {number} size - Target size
|
|
210
|
+
* @returns {Array<string>} Dark field patterns
|
|
211
|
+
* @private
|
|
212
|
+
*/
|
|
213
|
+
_generateOrganizationalDarkField(patterns, size) {
|
|
214
|
+
const darkField = [];
|
|
215
|
+
const dimensions = [
|
|
216
|
+
'informal_power_structures',
|
|
217
|
+
'tacit_knowledge_networks',
|
|
218
|
+
'hidden_resource_flows',
|
|
219
|
+
'implicit_decision_criteria',
|
|
220
|
+
'unwritten_cultural_norms',
|
|
221
|
+
'latent_capability_reserves',
|
|
222
|
+
'invisible_coordination_mechanisms',
|
|
223
|
+
'emergent_collaboration_patterns',
|
|
224
|
+
];
|
|
225
|
+
|
|
226
|
+
for (let i = 0; i < size; i++) {
|
|
227
|
+
const dimension = dimensions[i % dimensions.length];
|
|
228
|
+
const patternIndex = i % patterns.length;
|
|
229
|
+
darkField.push(`${dimension}:derived_from:${patterns[patternIndex]}`);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return darkField;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Generate strategic dynamics dark field
|
|
237
|
+
* @param {Array<string>} patterns - Observable patterns
|
|
238
|
+
* @param {number} size - Target size
|
|
239
|
+
* @returns {Array<string>} Dark field patterns
|
|
240
|
+
* @private
|
|
241
|
+
*/
|
|
242
|
+
_generateStrategicDarkField(patterns, size) {
|
|
243
|
+
const darkField = [];
|
|
244
|
+
const dimensions = [
|
|
245
|
+
'latent_strategic_options',
|
|
246
|
+
'hidden_competitive_advantages',
|
|
247
|
+
'implicit_strategic_assumptions',
|
|
248
|
+
'emergent_industry_shifts',
|
|
249
|
+
'tacit_success_factors',
|
|
250
|
+
'invisible_threat_vectors',
|
|
251
|
+
'unrecognized_opportunities',
|
|
252
|
+
'hidden_ecosystem_dependencies',
|
|
253
|
+
];
|
|
254
|
+
|
|
255
|
+
for (let i = 0; i < size; i++) {
|
|
256
|
+
const dimension = dimensions[i % dimensions.length];
|
|
257
|
+
const patternIndex = i % patterns.length;
|
|
258
|
+
darkField.push(`${dimension}:derived_from:${patterns[patternIndex]}`);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return darkField;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Generate disruption arithmetic dark field
|
|
266
|
+
* @param {Array<string>} patterns - Observable patterns
|
|
267
|
+
* @param {number} size - Target size
|
|
268
|
+
* @returns {Array<string>} Dark field patterns
|
|
269
|
+
* @private
|
|
270
|
+
*/
|
|
271
|
+
_generateDisruptionDarkField(patterns, size) {
|
|
272
|
+
const darkField = [];
|
|
273
|
+
const dimensions = [
|
|
274
|
+
'latent_disruption_vectors',
|
|
275
|
+
'hidden_innovation_barriers',
|
|
276
|
+
'implicit_adoption_triggers',
|
|
277
|
+
'emergent_technology_convergence',
|
|
278
|
+
'tacit_resistance_patterns',
|
|
279
|
+
'invisible_tipping_points',
|
|
280
|
+
'unrecognized_substitutes',
|
|
281
|
+
'hidden_value_chain_vulnerabilities',
|
|
282
|
+
];
|
|
283
|
+
|
|
284
|
+
for (let i = 0; i < size; i++) {
|
|
285
|
+
const dimension = dimensions[i % dimensions.length];
|
|
286
|
+
const patternIndex = i % patterns.length;
|
|
287
|
+
darkField.push(`${dimension}:derived_from:${patterns[patternIndex]}`);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return darkField;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Compute completeness of closure
|
|
295
|
+
* @param {Object} observable - Observable pattern
|
|
296
|
+
* @param {Object} darkField - Dark field
|
|
297
|
+
* @returns {number} Completeness ratio [0, 1]
|
|
298
|
+
* @private
|
|
299
|
+
*/
|
|
300
|
+
_computeCompleteness(observable, darkField) {
|
|
301
|
+
const totalPatterns = observable.patterns.length + darkField.patterns.length;
|
|
302
|
+
const coverageScore = darkField.patterns.length / totalPatterns;
|
|
303
|
+
|
|
304
|
+
// Completeness is high when dark field coverage approaches (1 - observableRatio)
|
|
305
|
+
const targetCoverage = 1 - this.observableRatio;
|
|
306
|
+
const completeness = Math.min(1, coverageScore / targetCoverage);
|
|
307
|
+
|
|
308
|
+
return completeness;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Get operator metrics
|
|
313
|
+
* @returns {Object} Metrics
|
|
314
|
+
*/
|
|
315
|
+
getMetrics() {
|
|
316
|
+
return {
|
|
317
|
+
...this.metrics,
|
|
318
|
+
operatorId: this.operatorId,
|
|
319
|
+
observableRatio: this.observableRatio,
|
|
320
|
+
closureThreshold: this.closureThreshold,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Reset operator metrics
|
|
326
|
+
*/
|
|
327
|
+
resetMetrics() {
|
|
328
|
+
this.metrics = {
|
|
329
|
+
closureOperations: 0,
|
|
330
|
+
averageCompleteness: 0,
|
|
331
|
+
totalDarkFieldRevealed: 0,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Create a Chatman operator instance
|
|
338
|
+
* @param {Object} [options] - Operator options
|
|
339
|
+
* @returns {ChatmanOperator} Operator instance
|
|
340
|
+
*/
|
|
341
|
+
export function createChatmanOperator(options = {}) {
|
|
342
|
+
return new ChatmanOperator(options);
|
|
343
|
+
}
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Dark Field Detector - 95% Invisible Field Detection
|
|
3
|
+
* @module knowledge-engine/dark-field-detector
|
|
4
|
+
*
|
|
5
|
+
* @description
|
|
6
|
+
* Detects and analyzes the dark field (invisible ~95%) of organizational,
|
|
7
|
+
* market, strategic, and disruption patterns using the Chatman Equation.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { randomUUID } from 'crypto';
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Detection result schema
|
|
15
|
+
*/
|
|
16
|
+
export const DetectionResultSchema = z.object({
|
|
17
|
+
id: z.string().uuid(),
|
|
18
|
+
type: z.enum(['market', 'organizational', 'strategic', 'disruption']),
|
|
19
|
+
observableSize: z.number().int().nonnegative(),
|
|
20
|
+
darkFieldSize: z.number().int().nonnegative(),
|
|
21
|
+
darkFieldRatio: z.number().min(0).max(1),
|
|
22
|
+
patterns: z.array(
|
|
23
|
+
z.object({
|
|
24
|
+
dimension: z.string(),
|
|
25
|
+
confidence: z.number().min(0).max(1),
|
|
26
|
+
derivedFrom: z.array(z.string()),
|
|
27
|
+
})
|
|
28
|
+
),
|
|
29
|
+
detectedAt: z.number(),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Detection options schema
|
|
34
|
+
*/
|
|
35
|
+
export const DetectionOptionsSchema = z.object({
|
|
36
|
+
minConfidence: z.number().min(0).max(1).default(0.7),
|
|
37
|
+
maxPatterns: z.number().int().positive().default(100),
|
|
38
|
+
targetRatio: z.number().min(0).max(1).default(0.95),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Dark field detector for Chatman Equation
|
|
43
|
+
*/
|
|
44
|
+
export class DarkFieldDetector {
|
|
45
|
+
/**
|
|
46
|
+
* Create a new dark field detector
|
|
47
|
+
* @param {Object} [options] - Detector options
|
|
48
|
+
* @param {Function} [options.tracer] - OTEL tracer function
|
|
49
|
+
* @param {number} [options.targetRatio=0.95] - Target dark field ratio
|
|
50
|
+
*/
|
|
51
|
+
constructor(options = {}) {
|
|
52
|
+
this.tracer = options.tracer;
|
|
53
|
+
this.targetRatio = options.targetRatio ?? 0.95;
|
|
54
|
+
this.metrics = {
|
|
55
|
+
detectionsPerformed: 0,
|
|
56
|
+
averageDarkFieldRatio: 0,
|
|
57
|
+
totalPatternsDetected: 0,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Detect dark field patterns from observable data
|
|
63
|
+
* @param {Object} observable - Observable pattern data
|
|
64
|
+
* @param {Object} [options] - Detection options
|
|
65
|
+
* @returns {Promise<Object>} Detection result
|
|
66
|
+
*/
|
|
67
|
+
async detect(observable, options = {}) {
|
|
68
|
+
const span = this.tracer?.startSpan?.('chatman.darkfield.detect');
|
|
69
|
+
const startTime = Date.now();
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
const opts = DetectionOptionsSchema.parse(options);
|
|
73
|
+
|
|
74
|
+
span?.setAttribute?.('observable.type', observable.type);
|
|
75
|
+
span?.setAttribute?.('observable.size', observable.patterns.length);
|
|
76
|
+
span?.setAttribute?.('target_ratio', opts.targetRatio);
|
|
77
|
+
|
|
78
|
+
// Calculate expected dark field size
|
|
79
|
+
const observableSize = observable.patterns.length;
|
|
80
|
+
const darkFieldSize = this._calculateDarkFieldSize(observableSize, opts.targetRatio);
|
|
81
|
+
|
|
82
|
+
// Detect dark field patterns
|
|
83
|
+
const patterns = this._detectPatterns(observable, darkFieldSize, opts);
|
|
84
|
+
|
|
85
|
+
const darkFieldRatio = darkFieldSize / (darkFieldSize + observableSize);
|
|
86
|
+
|
|
87
|
+
const result = {
|
|
88
|
+
id: randomUUID(),
|
|
89
|
+
type: observable.type,
|
|
90
|
+
observableSize,
|
|
91
|
+
darkFieldSize,
|
|
92
|
+
darkFieldRatio,
|
|
93
|
+
patterns,
|
|
94
|
+
detectedAt: Date.now(),
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Update metrics
|
|
98
|
+
this.metrics.detectionsPerformed++;
|
|
99
|
+
this.metrics.averageDarkFieldRatio =
|
|
100
|
+
(this.metrics.averageDarkFieldRatio * (this.metrics.detectionsPerformed - 1) +
|
|
101
|
+
darkFieldRatio) /
|
|
102
|
+
this.metrics.detectionsPerformed;
|
|
103
|
+
this.metrics.totalPatternsDetected += patterns.length;
|
|
104
|
+
|
|
105
|
+
span?.addEvent?.('detection_completed', {
|
|
106
|
+
'detection.id': result.id,
|
|
107
|
+
'detection.dark_field_size': darkFieldSize,
|
|
108
|
+
'detection.ratio': darkFieldRatio,
|
|
109
|
+
'detection.pattern_count': patterns.length,
|
|
110
|
+
'detection.duration_ms': Date.now() - startTime,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return DetectionResultSchema.parse(result);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
span?.recordException?.(error);
|
|
116
|
+
span?.setStatus?.({ code: 2, message: error.message });
|
|
117
|
+
throw error;
|
|
118
|
+
} finally {
|
|
119
|
+
span?.end?.();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Calculate dark field size from observable size and target ratio
|
|
125
|
+
* @param {number} observableSize - Number of observable patterns
|
|
126
|
+
* @param {number} targetRatio - Target dark field ratio
|
|
127
|
+
* @returns {number} Dark field size
|
|
128
|
+
* @private
|
|
129
|
+
*/
|
|
130
|
+
_calculateDarkFieldSize(observableSize, targetRatio) {
|
|
131
|
+
// targetRatio = darkField / (darkField + observable)
|
|
132
|
+
// darkField = observable * targetRatio / (1 - targetRatio)
|
|
133
|
+
return Math.floor((observableSize * targetRatio) / (1 - targetRatio));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Detect dark field patterns
|
|
138
|
+
* @param {Object} observable - Observable pattern
|
|
139
|
+
* @param {number} targetSize - Target dark field size
|
|
140
|
+
* @param {Object} options - Detection options
|
|
141
|
+
* @returns {Array<Object>} Detected patterns
|
|
142
|
+
* @private
|
|
143
|
+
*/
|
|
144
|
+
_detectPatterns(observable, targetSize, options) {
|
|
145
|
+
const detectors = {
|
|
146
|
+
market: this._detectMarketDarkField.bind(this),
|
|
147
|
+
organizational: this._detectOrganizationalDarkField.bind(this),
|
|
148
|
+
strategic: this._detectStrategicDarkField.bind(this),
|
|
149
|
+
disruption: this._detectDisruptionDarkField.bind(this),
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const detector = detectors[observable.type] || detectors.market;
|
|
153
|
+
return detector(observable.patterns, targetSize, options);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Detect market dark field patterns
|
|
158
|
+
* @param {Array<string>} observablePatterns - Observable patterns
|
|
159
|
+
* @param {number} targetSize - Target size
|
|
160
|
+
* @param {Object} options - Options
|
|
161
|
+
* @returns {Array<Object>} Detected patterns
|
|
162
|
+
* @private
|
|
163
|
+
*/
|
|
164
|
+
_detectMarketDarkField(observablePatterns, targetSize, options) {
|
|
165
|
+
const dimensions = [
|
|
166
|
+
'hidden_customer_needs',
|
|
167
|
+
'latent_market_segments',
|
|
168
|
+
'unspoken_value_drivers',
|
|
169
|
+
'invisible_competition',
|
|
170
|
+
'emergent_demand_patterns',
|
|
171
|
+
];
|
|
172
|
+
|
|
173
|
+
return this._generateDetectedPatterns(
|
|
174
|
+
dimensions,
|
|
175
|
+
observablePatterns,
|
|
176
|
+
targetSize,
|
|
177
|
+
options
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Detect organizational dark field patterns
|
|
183
|
+
* @param {Array<string>} observablePatterns - Observable patterns
|
|
184
|
+
* @param {number} targetSize - Target size
|
|
185
|
+
* @param {Object} options - Options
|
|
186
|
+
* @returns {Array<Object>} Detected patterns
|
|
187
|
+
* @private
|
|
188
|
+
*/
|
|
189
|
+
_detectOrganizationalDarkField(observablePatterns, targetSize, options) {
|
|
190
|
+
const dimensions = [
|
|
191
|
+
'informal_power_structures',
|
|
192
|
+
'tacit_knowledge_networks',
|
|
193
|
+
'hidden_resource_flows',
|
|
194
|
+
'implicit_decision_criteria',
|
|
195
|
+
'unwritten_cultural_norms',
|
|
196
|
+
];
|
|
197
|
+
|
|
198
|
+
return this._generateDetectedPatterns(
|
|
199
|
+
dimensions,
|
|
200
|
+
observablePatterns,
|
|
201
|
+
targetSize,
|
|
202
|
+
options
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Detect strategic dark field patterns
|
|
208
|
+
* @param {Array<string>} observablePatterns - Observable patterns
|
|
209
|
+
* @param {number} targetSize - Target size
|
|
210
|
+
* @param {Object} options - Options
|
|
211
|
+
* @returns {Array<Object>} Detected patterns
|
|
212
|
+
* @private
|
|
213
|
+
*/
|
|
214
|
+
_detectStrategicDarkField(observablePatterns, targetSize, options) {
|
|
215
|
+
const dimensions = [
|
|
216
|
+
'latent_strategic_options',
|
|
217
|
+
'hidden_competitive_advantages',
|
|
218
|
+
'implicit_strategic_assumptions',
|
|
219
|
+
'emergent_industry_shifts',
|
|
220
|
+
'tacit_success_factors',
|
|
221
|
+
];
|
|
222
|
+
|
|
223
|
+
return this._generateDetectedPatterns(
|
|
224
|
+
dimensions,
|
|
225
|
+
observablePatterns,
|
|
226
|
+
targetSize,
|
|
227
|
+
options
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Detect disruption dark field patterns
|
|
233
|
+
* @param {Array<string>} observablePatterns - Observable patterns
|
|
234
|
+
* @param {number} targetSize - Target size
|
|
235
|
+
* @param {Object} options - Options
|
|
236
|
+
* @returns {Array<Object>} Detected patterns
|
|
237
|
+
* @private
|
|
238
|
+
*/
|
|
239
|
+
_detectDisruptionDarkField(observablePatterns, targetSize, options) {
|
|
240
|
+
const dimensions = [
|
|
241
|
+
'latent_disruption_vectors',
|
|
242
|
+
'hidden_innovation_barriers',
|
|
243
|
+
'implicit_adoption_triggers',
|
|
244
|
+
'emergent_technology_convergence',
|
|
245
|
+
'tacit_resistance_patterns',
|
|
246
|
+
];
|
|
247
|
+
|
|
248
|
+
return this._generateDetectedPatterns(
|
|
249
|
+
dimensions,
|
|
250
|
+
observablePatterns,
|
|
251
|
+
targetSize,
|
|
252
|
+
options
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Generate detected patterns from dimensions
|
|
258
|
+
* @param {Array<string>} dimensions - Pattern dimensions
|
|
259
|
+
* @param {Array<string>} observablePatterns - Observable patterns
|
|
260
|
+
* @param {number} targetSize - Target size
|
|
261
|
+
* @param {Object} options - Options
|
|
262
|
+
* @returns {Array<Object>} Detected patterns
|
|
263
|
+
* @private
|
|
264
|
+
*/
|
|
265
|
+
_generateDetectedPatterns(dimensions, observablePatterns, targetSize, options) {
|
|
266
|
+
const patterns = [];
|
|
267
|
+
const maxPatterns = Math.min(targetSize, options.maxPatterns);
|
|
268
|
+
|
|
269
|
+
for (let i = 0; i < maxPatterns; i++) {
|
|
270
|
+
const dimension = dimensions[i % dimensions.length];
|
|
271
|
+
const patternIndex = i % observablePatterns.length;
|
|
272
|
+
const confidence = this._calculateConfidence(i, maxPatterns, options.minConfidence);
|
|
273
|
+
|
|
274
|
+
if (confidence >= options.minConfidence) {
|
|
275
|
+
patterns.push({
|
|
276
|
+
dimension,
|
|
277
|
+
confidence,
|
|
278
|
+
derivedFrom: [observablePatterns[patternIndex]],
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return patterns;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Calculate confidence score for pattern
|
|
288
|
+
* @param {number} index - Pattern index
|
|
289
|
+
* @param {number} total - Total patterns
|
|
290
|
+
* @param {number} minConfidence - Minimum confidence
|
|
291
|
+
* @returns {number} Confidence score
|
|
292
|
+
* @private
|
|
293
|
+
*/
|
|
294
|
+
_calculateConfidence(index, total, minConfidence) {
|
|
295
|
+
// Confidence decreases slightly as we generate more patterns
|
|
296
|
+
const decay = 0.1;
|
|
297
|
+
const baseConfidence = 0.95;
|
|
298
|
+
const confidence = baseConfidence - (index / total) * decay;
|
|
299
|
+
return Math.max(minConfidence, confidence);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Get detector metrics
|
|
304
|
+
* @returns {Object} Metrics
|
|
305
|
+
*/
|
|
306
|
+
getMetrics() {
|
|
307
|
+
return {
|
|
308
|
+
...this.metrics,
|
|
309
|
+
targetRatio: this.targetRatio,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Reset detector metrics
|
|
315
|
+
*/
|
|
316
|
+
resetMetrics() {
|
|
317
|
+
this.metrics = {
|
|
318
|
+
detectionsPerformed: 0,
|
|
319
|
+
averageDarkFieldRatio: 0,
|
|
320
|
+
totalPatternsDetected: 0,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Create a dark field detector instance
|
|
327
|
+
* @param {Object} [options] - Detector options
|
|
328
|
+
* @returns {DarkFieldDetector} Detector instance
|
|
329
|
+
*/
|
|
330
|
+
export function createDarkFieldDetector(options = {}) {
|
|
331
|
+
return new DarkFieldDetector(options);
|
|
332
|
+
}
|