@odla-ai/kg 0.3.0 → 0.4.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/dist/chunk-T6SYIVST.js +376 -0
- package/dist/chunk-T6SYIVST.js.map +1 -0
- package/dist/index.cjs +410 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +330 -5
- package/dist/index.d.ts +330 -5
- package/dist/index.js +249 -38
- package/dist/index.js.map +1 -1
- package/dist/lenses-C7Q7Gvnx.d.cts +123 -0
- package/dist/lenses-C7Q7Gvnx.d.ts +123 -0
- package/dist/temporal/index.cjs +134 -617
- package/dist/temporal/index.cjs.map +1 -1
- package/dist/temporal/index.d.cts +23 -447
- package/dist/temporal/index.d.ts +23 -447
- package/dist/temporal/index.js +28 -780
- package/dist/temporal/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-V3N2GRYU.js +0 -73
- package/dist/chunk-V3N2GRYU.js.map +0 -1
- package/dist/sources-nJyD0JUP.d.cts +0 -256
- package/dist/sources-nJyD0JUP.d.ts +0 -256
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import '@odla-ai/
|
|
1
|
+
import { b as GraphNode, G as GraphFragment } from '../lenses-C7Q7Gvnx.cjs';
|
|
2
|
+
export { W as WeightedPair, X as XY, d as blendPairs, f as composeTargets, g as directTargets, h as geoPairs, p as projectBridges, r as reifiedBridgeTargets, t as timePairs } from '../lenses-C7Q7Gvnx.cjs';
|
|
3
|
+
import '@odla-ai/db';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* FNV-1a 32-bit hash of a string. Used to derive a per-identity PRNG seed
|
|
@@ -76,209 +76,6 @@ declare function indexGraph(fragment: GraphFragment): GraphIndex;
|
|
|
76
76
|
*/
|
|
77
77
|
declare function resolvePath(g: GraphIndex, start: NodeRef, labels: readonly string[]): NodeRef[];
|
|
78
78
|
|
|
79
|
-
/**
|
|
80
|
-
* Where an event's geography lives: walk `path` (forward edge labels) from the
|
|
81
|
-
* event node, then read `attr` off the landing node — or, with no `attr`, use
|
|
82
|
-
* the landing node's key (e.g. a `region` entity slug). With no `path`, the
|
|
83
|
-
* event node itself is the landing node.
|
|
84
|
-
*/
|
|
85
|
-
interface GeoSpec {
|
|
86
|
-
path?: readonly string[];
|
|
87
|
-
attr?: string;
|
|
88
|
-
}
|
|
89
|
-
/** How to turn one entity type into temporal events. */
|
|
90
|
-
interface EventSpec {
|
|
91
|
-
/** Event entity type, e.g. `"funding_round"` or `"signal"`. */
|
|
92
|
-
type: string;
|
|
93
|
-
/** Attr holding the event date (parsed with `parseDateMs`; undated nodes are skipped). */
|
|
94
|
-
dateAttr: string;
|
|
95
|
-
/** Attr holding a magnitude, parsed with `parseAmount`; unparseable → weight 1. */
|
|
96
|
-
weightAttr?: string;
|
|
97
|
-
/** Override hook for weights the attr grammar can't express. */
|
|
98
|
-
weightOf?: (attrs: Record<string, Value>) => number | undefined;
|
|
99
|
-
/** Edge-label paths from the event node to its participant entities. */
|
|
100
|
-
attach?: readonly (readonly string[])[];
|
|
101
|
-
/** Geography of the event (choropleth/hotspot keying). */
|
|
102
|
-
geo?: GeoSpec;
|
|
103
|
-
/** Destination geography — only for flow-shaped events (money moving A→B). */
|
|
104
|
-
geoTo?: GeoSpec;
|
|
105
|
-
}
|
|
106
|
-
/** The extraction contract: one spec per event entity type. */
|
|
107
|
-
interface TemporalConfig {
|
|
108
|
-
events: EventSpec[];
|
|
109
|
-
}
|
|
110
|
-
/** One timestamped event extracted from the graph. */
|
|
111
|
-
interface TemporalEvent {
|
|
112
|
-
/** Epoch ms (UTC). */
|
|
113
|
-
t: number;
|
|
114
|
-
/** The spec's entity type. */
|
|
115
|
-
kind: string;
|
|
116
|
-
/** The event node itself. */
|
|
117
|
-
node: NodeRef;
|
|
118
|
-
/** Attached participant entities, deduped, sorted by id. */
|
|
119
|
-
refs: NodeRef[];
|
|
120
|
-
/** Magnitude (defaults to 1). */
|
|
121
|
-
weight: number;
|
|
122
|
-
/** Source geography key, when resolvable. */
|
|
123
|
-
geo?: string;
|
|
124
|
-
/** Destination geography key, when resolvable (flow events). */
|
|
125
|
-
geoTo?: string;
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Parse a human money/quantity string to a number: `"$12.5M"` → 12500000,
|
|
129
|
-
* `"12,500,000"` → 12500000, `"500k"` → 500000, numbers pass through.
|
|
130
|
-
* Returns undefined for anything else (never NaN).
|
|
131
|
-
*/
|
|
132
|
-
declare function parseAmount(v: unknown): number | undefined;
|
|
133
|
-
/**
|
|
134
|
-
* Extract the event stream: for every spec, every node of that type with a
|
|
135
|
-
* parseable date becomes one event. Sorted by time, tie-broken by node id —
|
|
136
|
-
* the ordering is total and reproducible.
|
|
137
|
-
*/
|
|
138
|
-
declare function extractEvents(fragment: GraphFragment, config: TemporalConfig): TemporalEvent[];
|
|
139
|
-
|
|
140
|
-
/** One named series, index-aligned with its SeriesSet's buckets. */
|
|
141
|
-
interface Series {
|
|
142
|
-
key: string;
|
|
143
|
-
values: number[];
|
|
144
|
-
}
|
|
145
|
-
/** A grain, its buckets, and every series over them (sorted by key). */
|
|
146
|
-
interface SeriesSet {
|
|
147
|
-
grain: TimeGrain;
|
|
148
|
-
buckets: TimeBucket[];
|
|
149
|
-
series: Series[];
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* How to key events into series: `"kind"` (event type), `"geo"` (source
|
|
153
|
-
* geography; geo-less events are dropped), `"ref"` (fan one event into one
|
|
154
|
-
* increment per attached participant, keyed by node id), or a custom function
|
|
155
|
-
* returning zero or more keys per event.
|
|
156
|
-
*/
|
|
157
|
-
type SeriesKeyer = "kind" | "geo" | "ref" | ((e: TemporalEvent) => string | readonly string[] | undefined);
|
|
158
|
-
/** The series keys one event contributes to under a keyer (used by rollup and by hotspot contributor attachment). */
|
|
159
|
-
declare function seriesKeys(e: TemporalEvent, by: SeriesKeyer): readonly string[];
|
|
160
|
-
/**
|
|
161
|
-
* Roll events up into bucketed series. The bucket range spans `from`..`to`
|
|
162
|
-
* when given (zero-padded even where nothing happened — burst baselines need
|
|
163
|
-
* the quiet buckets), else the events' own time span. Events outside the
|
|
164
|
-
* range are ignored.
|
|
165
|
-
*/
|
|
166
|
-
declare function rollup(events: readonly TemporalEvent[], opts: {
|
|
167
|
-
grain: TimeGrain;
|
|
168
|
-
by?: SeriesKeyer;
|
|
169
|
-
measure?: "count" | "weight";
|
|
170
|
-
from?: number;
|
|
171
|
-
to?: number;
|
|
172
|
-
}): SeriesSet;
|
|
173
|
-
/** Per-bucket sum across every series in the set (the "all" line). */
|
|
174
|
-
declare function totals(set: SeriesSet): Series;
|
|
175
|
-
|
|
176
|
-
/** Tuning for {@link burstScores}/{@link detectBursts}. */
|
|
177
|
-
interface BurstOptions {
|
|
178
|
-
/** Trailing buckets forming the baseline (excluding the scored bucket). Default 6. */
|
|
179
|
-
window?: number;
|
|
180
|
-
/** z needed to OPEN a burst run. Default 2. */
|
|
181
|
-
zEnter?: number;
|
|
182
|
-
/** z needed to EXTEND an open run (hysteresis). Default 1. */
|
|
183
|
-
zExit?: number;
|
|
184
|
-
/** Minimum trailing buckets before scoring (cold start → z 0). Default 3. */
|
|
185
|
-
minBaseline?: number;
|
|
186
|
-
/**
|
|
187
|
-
* Floor on the baseline sigma. sqrt(mean) is always applied (Poisson-
|
|
188
|
-
* consistent for counts); this guards the all-zero baseline. Default 1.
|
|
189
|
-
*/
|
|
190
|
-
minSigma?: number;
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Per-bucket burst z-scores for one series: (value − trailing mean) /
|
|
194
|
-
* max(trailing stdev, sqrt(mean), minSigma). Cold-start buckets score 0.
|
|
195
|
-
*/
|
|
196
|
-
declare function burstScores(values: readonly number[], opts?: BurstOptions): number[];
|
|
197
|
-
/** One detected burst: a maximal hysteresis run within one series. */
|
|
198
|
-
interface Burst {
|
|
199
|
-
seriesKey: string;
|
|
200
|
-
/** Bucket indexes, inclusive. */
|
|
201
|
-
start: number;
|
|
202
|
-
end: number;
|
|
203
|
-
/** Highest z in the run. */
|
|
204
|
-
peak: number;
|
|
205
|
-
/** Σ max(0, z) over the run — rewards both height and duration. */
|
|
206
|
-
score: number;
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* All bursts across a SeriesSet, ranked score desc (ties: earlier start,
|
|
210
|
-
* then series key). A run opens at z ≥ zEnter and extends while z ≥ zExit.
|
|
211
|
-
*/
|
|
212
|
-
declare function detectBursts(set: SeriesSet, opts?: BurstOptions): Burst[];
|
|
213
|
-
/** A burst plus its bucket keys and top contributing events — a ranked lead. */
|
|
214
|
-
interface Hotspot extends Burst {
|
|
215
|
-
bucketKeys: string[];
|
|
216
|
-
contributors: TemporalEvent[];
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* Detect, rank, and enrich bursts into explorable leads. `by` must be the
|
|
220
|
-
* same keyer the SeriesSet was rolled up with — it re-derives each event's
|
|
221
|
-
* series keys to attach contributors (top per-lead by weight, then time).
|
|
222
|
-
*/
|
|
223
|
-
declare function rankHotspots(set: SeriesSet, events: readonly TemporalEvent[], opts?: BurstOptions & {
|
|
224
|
-
by?: SeriesKeyer;
|
|
225
|
-
top?: number;
|
|
226
|
-
contributorsPer?: number;
|
|
227
|
-
}): Hotspot[];
|
|
228
|
-
|
|
229
|
-
/** One dated undirected edge (canonical order: a < b). */
|
|
230
|
-
interface TimelineEdge {
|
|
231
|
-
a: NodeId;
|
|
232
|
-
b: NodeId;
|
|
233
|
-
t: number;
|
|
234
|
-
kind: string;
|
|
235
|
-
weight: number;
|
|
236
|
-
}
|
|
237
|
-
/** The replayable structure built once from the event stream. */
|
|
238
|
-
interface Timeline {
|
|
239
|
-
events: TemporalEvent[];
|
|
240
|
-
/** Every node ever seen, sorted by id. */
|
|
241
|
-
nodes: NodeId[];
|
|
242
|
-
/** Dated edges, time-ordered. */
|
|
243
|
-
edges: TimelineEdge[];
|
|
244
|
-
/** Node id → first time it appeared. */
|
|
245
|
-
firstSeen: Map<NodeId, number>;
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Build the timeline. `"entities"` (default) projects each event onto its
|
|
249
|
-
* participants — every ref pair co-occurring in one event becomes an edge
|
|
250
|
-
* (companies↔investors↔people), and event nodes vanish. `"full"` keeps the
|
|
251
|
-
* event node and links it to each ref (bipartite).
|
|
252
|
-
*/
|
|
253
|
-
declare function buildTimeline(events: readonly TemporalEvent[], opts?: {
|
|
254
|
-
mode?: "entities" | "full";
|
|
255
|
-
}): Timeline;
|
|
256
|
-
/** The graph as it stood at time `t`. */
|
|
257
|
-
interface Snapshot {
|
|
258
|
-
t: number;
|
|
259
|
-
/** Nodes first seen at or before t, sorted. */
|
|
260
|
-
nodes: NodeId[];
|
|
261
|
-
/** Aggregated undirected edges (weight = co-occurrence count). */
|
|
262
|
-
edges: Array<{
|
|
263
|
-
a: NodeId;
|
|
264
|
-
b: NodeId;
|
|
265
|
-
weight: number;
|
|
266
|
-
}>;
|
|
267
|
-
/** Node id → its latest event time ≤ t (drives recency glow). */
|
|
268
|
-
activity: Map<NodeId, number>;
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Materialize the graph at `t`: cumulative by default, or only edges within
|
|
272
|
-
* the trailing `window` ms when given (rolling co-activity).
|
|
273
|
-
*/
|
|
274
|
-
declare function snapshotAt(timeline: Timeline, t: number, opts?: {
|
|
275
|
-
window?: number;
|
|
276
|
-
}): Snapshot;
|
|
277
|
-
/** One snapshot per bucket, each taken at the bucket's inclusive end. */
|
|
278
|
-
declare function snapshotSeries(timeline: Timeline, buckets: readonly TimeBucket[], opts?: {
|
|
279
|
-
window?: number;
|
|
280
|
-
}): Snapshot[];
|
|
281
|
-
|
|
282
79
|
/**
|
|
283
80
|
* Asynchronous label propagation with deterministic (seeded) tie-breaking:
|
|
284
81
|
* - labels start as each node's own id;
|
|
@@ -302,252 +99,31 @@ declare function labelPropagation(nodes: readonly NodeId[], edges: ReadonlyArray
|
|
|
302
99
|
maxRounds?: number;
|
|
303
100
|
}): Map<NodeId, string>;
|
|
304
101
|
|
|
305
|
-
/** One
|
|
306
|
-
interface
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
interface ClusterFrame {
|
|
312
|
-
t: number;
|
|
313
|
-
clusters: Cluster[];
|
|
314
|
-
}
|
|
315
|
-
/** A structural change between consecutive frames. */
|
|
316
|
-
type ClusterChange = {
|
|
317
|
-
kind: "birth";
|
|
318
|
-
t: number;
|
|
319
|
-
id: string;
|
|
320
|
-
} | {
|
|
321
|
-
kind: "death";
|
|
322
|
-
t: number;
|
|
323
|
-
id: string;
|
|
324
|
-
} | {
|
|
325
|
-
kind: "merge";
|
|
326
|
-
t: number;
|
|
327
|
-
into: string;
|
|
328
|
-
from: string[];
|
|
329
|
-
} | {
|
|
330
|
-
kind: "split";
|
|
331
|
-
t: number;
|
|
332
|
-
from: string;
|
|
333
|
-
into: string[];
|
|
334
|
-
};
|
|
335
|
-
/**
|
|
336
|
-
* Thread stable cluster ids through per-frame label maps. A current cluster
|
|
337
|
-
* inherits the id of its best-Jaccard predecessor at ≥ minJaccard (ties:
|
|
338
|
-
* more shared members, then smaller id); when several current clusters claim
|
|
339
|
-
* one predecessor the best keeps the id and the rest record a split; a
|
|
340
|
-
* current cluster absorbing ≥2 predecessors records a merge. Unmatched
|
|
341
|
-
* current clusters are births (id = "c:" + smallest member); vanished ids
|
|
342
|
-
* are deaths.
|
|
343
|
-
*/
|
|
344
|
-
declare function trackClusters(frames: ReadonlyArray<{
|
|
345
|
-
t: number;
|
|
346
|
-
labels: Map<NodeId, string>;
|
|
347
|
-
}>, opts?: {
|
|
348
|
-
minJaccard?: number;
|
|
349
|
-
}): {
|
|
350
|
-
frames: ClusterFrame[];
|
|
351
|
-
changes: ClusterChange[];
|
|
352
|
-
};
|
|
353
|
-
|
|
354
|
-
/** A unit-square position (scale to pixels at draw time). */
|
|
355
|
-
interface XY {
|
|
356
|
-
x: number;
|
|
357
|
-
y: number;
|
|
358
|
-
}
|
|
359
|
-
/** Tuning for {@link forceLayout}. */
|
|
360
|
-
interface LayoutOptions {
|
|
361
|
-
/** Force iterations. Default 300 (cold); use fewer for warm refinement. */
|
|
362
|
-
iterations?: number;
|
|
363
|
-
/** Seed mixed into every node's hash-derived initial position. Default 1. */
|
|
364
|
-
seed?: number;
|
|
365
|
-
/**
|
|
366
|
-
* Repulsion multiplier. Default 0.1 — measured on a real ~800-node OSINT
|
|
367
|
-
* graph as the point where nothing pins to the clamped boundary.
|
|
368
|
-
*/
|
|
369
|
-
repulsion?: number;
|
|
370
|
-
/** Pull toward the center, proportional to distance. Default 0.5. */
|
|
371
|
-
gravity?: number;
|
|
372
|
-
/** Warm-start positions (nodes present here start where they were). */
|
|
373
|
-
positions?: ReadonlyMap<NodeId, XY>;
|
|
102
|
+
/** One node's brokerage: normalized score + the communities it connects. */
|
|
103
|
+
interface Bridging {
|
|
104
|
+
/** 0..1, 1 = the frame's strongest connector. */
|
|
105
|
+
score: number;
|
|
106
|
+
/** Communities this node touches through its edges (own community first). */
|
|
107
|
+
groups: string[];
|
|
374
108
|
}
|
|
375
109
|
/**
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
380
|
-
*
|
|
110
|
+
* Score every node's brokerage against a community partition. Edges inside a
|
|
111
|
+
* community contribute nothing; an edge to a foreign community contributes
|
|
112
|
+
* its weight, and the total is multiplied by the number of DISTINCT foreign
|
|
113
|
+
* communities — a node wiring three groups together outranks one with the
|
|
114
|
+
* same raw weight into a single neighbor group. Scores are normalized to
|
|
115
|
+
* the frame's max (empty/one-community frames → all zeros).
|
|
381
116
|
*/
|
|
382
|
-
declare function
|
|
117
|
+
declare function bridgingScores(edges: ReadonlyArray<{
|
|
383
118
|
a: NodeId;
|
|
384
119
|
b: NodeId;
|
|
385
120
|
weight?: number;
|
|
386
|
-
}>,
|
|
387
|
-
/**
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
* `warmIterations` — existing nodes drift instead of re-scrambling, so
|
|
391
|
-
* inter-frame motion means something.
|
|
392
|
-
*/
|
|
393
|
-
declare function layoutSequence(snapshots: readonly Snapshot[], opts?: LayoutOptions & {
|
|
394
|
-
warmIterations?: number;
|
|
395
|
-
}): Map<NodeId, XY>[];
|
|
396
|
-
|
|
397
|
-
/** Tuning for {@link buildTemporalReport}. */
|
|
398
|
-
interface ReportOptions {
|
|
399
|
-
/** Analysis anchor (epoch ms). Default: the latest event time. Inject for determinism. */
|
|
400
|
-
now?: number;
|
|
401
|
-
/** Weekly cluster/lead window. Default 155 days (~22 frames). */
|
|
402
|
-
windowDays?: number;
|
|
403
|
-
/** Monthly density-series span. Default 12 months. */
|
|
404
|
-
monthlyMonths?: number;
|
|
405
|
-
/** Ranked leads kept. Default 8. */
|
|
406
|
-
topLeads?: number;
|
|
407
|
-
/** Contributing events per lead. Default 3. */
|
|
408
|
-
contributorsPer?: number;
|
|
409
|
-
/** Trailing weeks of cluster changes kept. Default 4. */
|
|
410
|
-
changeWeeks?: number;
|
|
411
|
-
/** Burst detector tuning. Default `{ window: 6 }`. */
|
|
412
|
-
burst?: BurstOptions;
|
|
413
|
-
}
|
|
414
|
-
/** One ranked hotspot lead: a bursting entity plus its evidence. */
|
|
415
|
-
interface ReportLead {
|
|
416
|
-
key: string;
|
|
417
|
-
type: string;
|
|
418
|
-
name: string;
|
|
419
|
-
city?: string;
|
|
420
|
-
sector?: string;
|
|
121
|
+
}>, labels: Map<NodeId, string>): Map<NodeId, Bridging>;
|
|
122
|
+
/** The frame's strongest connectors, ranked (ties: id order). */
|
|
123
|
+
declare function topBridges(bridging: Map<NodeId, Bridging>, n?: number): Array<{
|
|
124
|
+
id: NodeId;
|
|
421
125
|
score: number;
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
contributors: Array<{
|
|
425
|
-
kind: string;
|
|
426
|
-
key: string;
|
|
427
|
-
title: string;
|
|
428
|
-
date: string;
|
|
429
|
-
}>;
|
|
430
|
-
}
|
|
431
|
-
/** One cluster-evolution change, name-resolved for display. */
|
|
432
|
-
interface ReportClusterChange {
|
|
433
|
-
week: string;
|
|
434
|
-
kind: "birth" | "death" | "merge" | "split";
|
|
435
|
-
ids: string[];
|
|
436
|
-
names: string[];
|
|
437
|
-
}
|
|
438
|
-
/** The cached/served analysis product — everything JSON-native and bounded (≲20KB). */
|
|
439
|
-
interface TemporalReport {
|
|
440
|
-
generatedAt: string;
|
|
441
|
-
window: {
|
|
442
|
-
from: string;
|
|
443
|
-
to: string;
|
|
444
|
-
weeks: string[];
|
|
445
|
-
};
|
|
446
|
-
totals: {
|
|
447
|
-
events: number;
|
|
448
|
-
nodes: number;
|
|
449
|
-
edges: number;
|
|
450
|
-
};
|
|
451
|
-
series: Array<{
|
|
452
|
-
kind: string;
|
|
453
|
-
months: string[];
|
|
454
|
-
values: number[];
|
|
455
|
-
}>;
|
|
456
|
-
leads: ReportLead[];
|
|
457
|
-
clusters: {
|
|
458
|
-
frames: Array<{
|
|
459
|
-
week: string;
|
|
460
|
-
count: number;
|
|
461
|
-
top: Array<{
|
|
462
|
-
id: string;
|
|
463
|
-
size: number;
|
|
464
|
-
label: string;
|
|
465
|
-
}>;
|
|
466
|
-
}>;
|
|
467
|
-
changes: ReportClusterChange[];
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
/** Build the full temporal report for a graph fragment. Empty input → zeroed report. */
|
|
471
|
-
declare function buildTemporalReport(fragment: GraphFragment, config: TemporalConfig, opts?: ReportOptions): TemporalReport;
|
|
472
|
-
|
|
473
|
-
/** True when the report has anything worth narrating (any lead or recent cluster change). */
|
|
474
|
-
declare function shouldNarrate(report: TemporalReport): boolean;
|
|
475
|
-
/**
|
|
476
|
-
* The deterministic materials block handed to the narrative LLM call:
|
|
477
|
-
* window/totals header, top leads with evidence, cluster changes, and
|
|
478
|
-
* per-kind monthly density lines. No prose, no interpretation.
|
|
479
|
-
*/
|
|
480
|
-
declare function buildNarrationMaterials(report: TemporalReport, opts?: {
|
|
481
|
-
topLeads?: number;
|
|
482
|
-
}): string;
|
|
483
|
-
/** First-line `# title` heuristic shared with the digest workflow. */
|
|
484
|
-
declare function splitTitleBody(text: string, fallbackTitle: string): {
|
|
485
|
-
title: string;
|
|
486
|
-
body: string;
|
|
487
|
-
};
|
|
488
|
-
|
|
489
|
-
/**
|
|
490
|
-
* Burst score per natural key for one entity type, from a report's leads:
|
|
491
|
-
* `{ leads: [{key: "company:acme", score: 7.3}] }` → `{ acme: 7.3 }`.
|
|
492
|
-
*/
|
|
493
|
-
declare function leadScores(report: Pick<TemporalReport, "leads">, type?: string): Record<string, number>;
|
|
494
|
-
/** One selected enrichment target. */
|
|
495
|
-
interface EnrichmentCandidate {
|
|
496
|
-
slug: string;
|
|
497
|
-
name: string;
|
|
498
|
-
score: number;
|
|
499
|
-
}
|
|
500
|
-
/**
|
|
501
|
-
* Rank enrichment candidates: burst score descending, ties keep the input
|
|
502
|
-
* (creation) order. Cooling rows are skipped at selection. Complete rows are
|
|
503
|
-
* skipped UNLESS they carry a burst score — a bursting complete company
|
|
504
|
-
* deserves a re-check. With no scores this reproduces the legacy behavior
|
|
505
|
-
* exactly (input order, incomplete rows only).
|
|
506
|
-
*/
|
|
507
|
-
declare function rankEnrichmentCandidates(rows: ReadonlyArray<Record<string, unknown>>, opts: {
|
|
508
|
-
limit: number;
|
|
509
|
-
scores?: Record<string, number>;
|
|
510
|
-
cooling?: ReadonlySet<string>;
|
|
511
|
-
isComplete?: (row: Record<string, unknown>) => boolean;
|
|
512
|
-
}): EnrichmentCandidate[];
|
|
513
|
-
/**
|
|
514
|
-
* Replace the synthesized burst-sweep source with a fresh one derived from
|
|
515
|
-
* the report's top company leads (or remove it when there are none).
|
|
516
|
-
* Hand-authored entries — anything without `origin: "burst"` — are returned
|
|
517
|
-
* untouched, in order. Queries follow
|
|
518
|
-
* `"<name>" <city|sector|startup> funding OR expansion OR hiring news`.
|
|
519
|
-
*/
|
|
520
|
-
declare function synthesizeBurstSources(existing: readonly SourceEntry[], report: Pick<TemporalReport, "leads">, opts?: {
|
|
521
|
-
max?: number;
|
|
522
|
-
cadenceHours?: number;
|
|
523
|
-
}): SourceEntry[];
|
|
524
|
-
|
|
525
|
-
/** One aggregated movement between two geography keys within a bucket. */
|
|
526
|
-
interface Flow {
|
|
527
|
-
from: string;
|
|
528
|
-
to: string;
|
|
529
|
-
/** Summed event weights (e.g. dollars). */
|
|
530
|
-
weight: number;
|
|
531
|
-
/** Number of contributing events. */
|
|
532
|
-
count: number;
|
|
533
|
-
}
|
|
534
|
-
/** All flows for one time bucket, sorted weight-desc then from/to. */
|
|
535
|
-
interface FlowFrame {
|
|
536
|
-
bucket: TimeBucket;
|
|
537
|
-
flows: Flow[];
|
|
538
|
-
}
|
|
539
|
-
/**
|
|
540
|
-
* Aggregate flow events into per-bucket frames over `from`..`to` (default:
|
|
541
|
-
* the events' span). With `cumulative`, each frame includes everything up to
|
|
542
|
-
* and including its bucket — replay-style accumulation.
|
|
543
|
-
*/
|
|
544
|
-
declare function flowFrames(events: readonly TemporalEvent[], opts: {
|
|
545
|
-
grain: TimeGrain;
|
|
546
|
-
from?: number;
|
|
547
|
-
to?: number;
|
|
548
|
-
cumulative?: boolean;
|
|
549
|
-
}): FlowFrame[];
|
|
550
|
-
/** The frame's top-n flows by weight (already the frame's sort order). */
|
|
551
|
-
declare function topFlows(frame: FlowFrame, n: number): Flow[];
|
|
126
|
+
groups: string[];
|
|
127
|
+
}>;
|
|
552
128
|
|
|
553
|
-
export { type
|
|
129
|
+
export { type Bridging, type GraphIndex, type NodeId, type NodeRef, type TimeBucket, type TimeGrain, bridgingScores, bucketFor, bucketKey, bucketRange, byNodeId, hash32, indexGraph, labelPropagation, mulberry32, nodeId, parseDateMs, resolvePath, shuffle, topBridges };
|