@trillboards/edge-sdk 0.2.53 → 0.2.55
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/deploy/macos/README.md +4 -4
- package/deploy/macos/bench-local-vlm.sh +140 -0
- package/deploy/macos/build-macos-pkg.sh +3 -2
- package/deploy/windows/README.md +7 -5
- package/deploy/windows/bundle-windows-installer.ps1 +1 -3
- package/deploy/windows/e2e/test-local-sense.ps1 +97 -6
- package/dist/AudienceAnalyzeClient.d.ts +12 -1
- package/dist/AudienceAnalyzeClient.d.ts.map +1 -1
- package/dist/AudienceAnalyzeClient.js +1 -0
- package/dist/AudienceAnalyzeClient.js.map +1 -1
- package/dist/ChannelProber.d.ts +22 -0
- package/dist/ChannelProber.d.ts.map +1 -1
- package/dist/ChannelProber.js +47 -3
- package/dist/ChannelProber.js.map +1 -1
- package/dist/CloudSensingManager.d.ts.map +1 -1
- package/dist/CloudSensingManager.js +8 -1
- package/dist/CloudSensingManager.js.map +1 -1
- package/dist/EdgeAgent.js +1 -1
- package/dist/OnvifClient.d.ts +135 -3
- package/dist/OnvifClient.d.ts.map +1 -1
- package/dist/OnvifClient.js +303 -11
- package/dist/OnvifClient.js.map +1 -1
- package/dist/diagnose.d.ts +1 -1
- package/dist/diagnose.js +1 -1
- package/dist/localVlmBench.d.ts +102 -0
- package/dist/localVlmBench.d.ts.map +1 -1
- package/dist/localVlmBench.js +129 -0
- package/dist/localVlmBench.js.map +1 -1
- package/dist/sensingCatchRate.d.ts +83 -0
- package/dist/sensingCatchRate.d.ts.map +1 -1
- package/dist/sensingCatchRate.js +63 -2
- package/dist/sensingCatchRate.js.map +1 -1
- package/package.json +1 -1
package/dist/localVlmBench.d.ts
CHANGED
|
@@ -104,6 +104,108 @@ export declare function interleaveArms(arms: BenchArm[], rounds: number): Planne
|
|
|
104
104
|
* 0 s/frame reads as "infinitely fast" and a NaN silently poisons a table.
|
|
105
105
|
*/
|
|
106
106
|
export declare function median(values: number[]): number | null;
|
|
107
|
+
/** The machine a measurement came off. Read from `os`, never asserted. */
|
|
108
|
+
export interface MachineDescriptor {
|
|
109
|
+
platform: string;
|
|
110
|
+
arch: string;
|
|
111
|
+
release: string;
|
|
112
|
+
cpuModel: string;
|
|
113
|
+
cores: number;
|
|
114
|
+
memGb: number;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Minimal `os` surface this needs. Injectable ONLY so the unit tests can drive
|
|
118
|
+
* a Windows/Linux descriptor from a Mac — production always passes the real
|
|
119
|
+
* `os` module.
|
|
120
|
+
*/
|
|
121
|
+
export interface OsLike {
|
|
122
|
+
platform(): string;
|
|
123
|
+
arch(): string;
|
|
124
|
+
release(): string;
|
|
125
|
+
cpus(): Array<{
|
|
126
|
+
model?: string;
|
|
127
|
+
}>;
|
|
128
|
+
totalmem(): number;
|
|
129
|
+
}
|
|
130
|
+
export declare function describeMachine(osLike: OsLike): MachineDescriptor;
|
|
131
|
+
/**
|
|
132
|
+
* A STABLE slug for "machines of this kind" — the join key between a measured
|
|
133
|
+
* row and a box we might sell. Deliberately excludes OS version and hostname:
|
|
134
|
+
* two runs of the same silicon a point release apart are the same machine
|
|
135
|
+
* class, and a hostname would make every CI runner its own class (a matrix with
|
|
136
|
+
* 200 one-row classes measures nothing).
|
|
137
|
+
*/
|
|
138
|
+
export declare function machineClassId(m: MachineDescriptor): string;
|
|
139
|
+
/**
|
|
140
|
+
* Analyses per hour one serve sustains at a given per-frame cost.
|
|
141
|
+
*
|
|
142
|
+
* `litert-lm serve` admits ONE request at a time, so this is the machine's
|
|
143
|
+
* whole sensing capacity — not a per-camera figure. `null` (never 0, never
|
|
144
|
+
* Infinity) for a non-positive input, because a fabricated capacity is how a
|
|
145
|
+
* machine that measured nothing ends up in a spec sheet.
|
|
146
|
+
*/
|
|
147
|
+
export declare function analysesPerHour(secondsPerFrame: number): number | null;
|
|
148
|
+
/**
|
|
149
|
+
* How many cameras this per-frame cost serves, if every camera must be looked
|
|
150
|
+
* at once per `cadenceSeconds`. FLOOR, not round: 3.8 cameras is 3 cameras and
|
|
151
|
+
* one that misses its cadence.
|
|
152
|
+
*/
|
|
153
|
+
export declare function camerasAtCadence(secondsPerFrame: number, cadenceSeconds: number): number | null;
|
|
154
|
+
/**
|
|
155
|
+
* The throughput floor a box must clear to serve `cameras` at `cadenceSeconds`.
|
|
156
|
+
*
|
|
157
|
+
* This is NOT a new capacity model — it is `connectorCadence`'s, solved for the
|
|
158
|
+
* machine instead of for the interval. That file derives
|
|
159
|
+
*
|
|
160
|
+
* H >= N x ANALYZE / SHARE
|
|
161
|
+
*
|
|
162
|
+
* (N feeds, one admission slot, SHARE of it reserved for the still-scene
|
|
163
|
+
* heartbeat so the rest stays free for motion-triggered alerts). Fix H at the
|
|
164
|
+
* interval the product must resolve and it becomes a statement about hardware:
|
|
165
|
+
*
|
|
166
|
+
* ANALYZE <= H x SHARE / N
|
|
167
|
+
*/
|
|
168
|
+
export interface HardwareFloor {
|
|
169
|
+
cameras: number;
|
|
170
|
+
cadenceSeconds: number;
|
|
171
|
+
/** Fraction of the single admission slot the still-scene floor may consume. */
|
|
172
|
+
slotShare: number;
|
|
173
|
+
/** The per-frame budget. A machine slower than this cannot make the cadence. */
|
|
174
|
+
maxSecondsPerFrame: number;
|
|
175
|
+
/** The same statement in the unit the capacity plan quotes. */
|
|
176
|
+
minAnalysesPerHour: number;
|
|
177
|
+
}
|
|
178
|
+
export declare function floorFor(cameras: number, cadenceSeconds: number, slotShare?: number): HardwareFloor | null;
|
|
179
|
+
export interface FloorVerdict {
|
|
180
|
+
clears: boolean;
|
|
181
|
+
secondsPerFrame: number;
|
|
182
|
+
camerasSupported: number;
|
|
183
|
+
analysesPerHour: number;
|
|
184
|
+
/** >1 = headroom, <1 = short. Reported so "barely" and "10x" are distinguishable. */
|
|
185
|
+
headroom: number;
|
|
186
|
+
reason: string;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Does this measured per-frame cost clear the floor? A machine with NO measured
|
|
190
|
+
* number does not "fail" — it returns null, because unmeasured and too-slow are
|
|
191
|
+
* different facts and collapsing them is exactly how windows-latest spent two
|
|
192
|
+
* months looking like a slow box instead of an unmeasured one.
|
|
193
|
+
*/
|
|
194
|
+
export declare function gradeAgainstFloor(secondsPerFrame: number | null, floor: HardwareFloor): FloorVerdict | null;
|
|
195
|
+
/**
|
|
196
|
+
* A time budget for a whole bench run, so a run that cannot finish still
|
|
197
|
+
* REPORTS what it measured. The Windows lane's entire history is runs that
|
|
198
|
+
* measured frames and then died at the job cap having written nothing: a
|
|
199
|
+
* partial matrix is a datapoint, a killed process is not.
|
|
200
|
+
*/
|
|
201
|
+
export declare function budgetRemaining(startedAtMs: number, budgetMs: number, nowMs: number): number;
|
|
202
|
+
/**
|
|
203
|
+
* Should the runner attempt one more frame? Refuses when the time left is less
|
|
204
|
+
* than what the last frames actually cost — starting a frame we cannot finish
|
|
205
|
+
* both wastes the remaining budget and records a DEADLINE as if it were a
|
|
206
|
+
* machine's speed.
|
|
207
|
+
*/
|
|
208
|
+
export declare function shouldAttemptAnother(remainingMs: number, observedFrameMs: number[], fallbackFrameMs: number): boolean;
|
|
107
209
|
/**
|
|
108
210
|
* Nearest-rank percentile of a sample. `null` on empty, for the same reason
|
|
109
211
|
* `median` returns null.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localVlmBench.d.ts","sourceRoot":"","sources":["../src/localVlmBench.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,OAAO,EAGL,KAAK,mBAAmB,EACxB,KAAK,YAAY,EAClB,MAAM,wBAAwB,CAAC;AAEhC,uFAAuF;AACvF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,oBAAyB,GAAG,gBAAgB,CAQrF;AASD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,EAAE,CAwBV;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACrE;AAaD;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,UAAU,CAUZ;AAED,8DAA8D;AAC9D,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IACpC,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE,CAU7E;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAMtD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQrE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,0BAA0B,KAAK,CAAC"}
|
|
1
|
+
{"version":3,"file":"localVlmBench.d.ts","sourceRoot":"","sources":["../src/localVlmBench.ts"],"names":[],"mappings":"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"}
|
package/dist/localVlmBench.js
CHANGED
|
@@ -6,6 +6,14 @@ exports.validateAgainstContract = validateAgainstContract;
|
|
|
6
6
|
exports.scoreFields = scoreFields;
|
|
7
7
|
exports.interleaveArms = interleaveArms;
|
|
8
8
|
exports.median = median;
|
|
9
|
+
exports.describeMachine = describeMachine;
|
|
10
|
+
exports.machineClassId = machineClassId;
|
|
11
|
+
exports.analysesPerHour = analysesPerHour;
|
|
12
|
+
exports.camerasAtCadence = camerasAtCadence;
|
|
13
|
+
exports.floorFor = floorFor;
|
|
14
|
+
exports.gradeAgainstFloor = gradeAgainstFloor;
|
|
15
|
+
exports.budgetRemaining = budgetRemaining;
|
|
16
|
+
exports.shouldAttemptAnother = shouldAttemptAnother;
|
|
9
17
|
exports.percentile = percentile;
|
|
10
18
|
/**
|
|
11
19
|
* localVlmBench — the reusable, unit-tested pieces of the LIVE on-device VLM
|
|
@@ -170,6 +178,127 @@ function median(values) {
|
|
|
170
178
|
const mid = Math.floor(sorted.length / 2);
|
|
171
179
|
return sorted.length % 2 === 1 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
|
|
172
180
|
}
|
|
181
|
+
/** Trim the vendor noise x86 CPU strings carry ('(R)', '(TM)', 'CPU @ 2.60GHz'). */
|
|
182
|
+
function normaliseCpuModel(raw) {
|
|
183
|
+
return String(raw || 'unknown')
|
|
184
|
+
.replace(/\((R|TM|r|tm)\)/g, '')
|
|
185
|
+
.replace(/\bCPU\b/g, '')
|
|
186
|
+
.replace(/@\s*[\d.]+\s*GHz/i, '')
|
|
187
|
+
.replace(/\s+/g, ' ')
|
|
188
|
+
.trim() || 'unknown';
|
|
189
|
+
}
|
|
190
|
+
function describeMachine(osLike) {
|
|
191
|
+
const cpus = osLike.cpus() || [];
|
|
192
|
+
return {
|
|
193
|
+
platform: osLike.platform(),
|
|
194
|
+
arch: osLike.arch(),
|
|
195
|
+
release: osLike.release(),
|
|
196
|
+
cpuModel: normaliseCpuModel(cpus[0] && cpus[0].model ? cpus[0].model : 'unknown'),
|
|
197
|
+
cores: cpus.length,
|
|
198
|
+
memGb: Math.round((osLike.totalmem() / 1024 ** 3) * 10) / 10,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* A STABLE slug for "machines of this kind" — the join key between a measured
|
|
203
|
+
* row and a box we might sell. Deliberately excludes OS version and hostname:
|
|
204
|
+
* two runs of the same silicon a point release apart are the same machine
|
|
205
|
+
* class, and a hostname would make every CI runner its own class (a matrix with
|
|
206
|
+
* 200 one-row classes measures nothing).
|
|
207
|
+
*/
|
|
208
|
+
function machineClassId(m) {
|
|
209
|
+
const cpu = String(m.cpuModel || 'unknown').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
210
|
+
return `${m.platform}-${m.arch}-${cpu}-${m.cores}c-${Math.round(m.memGb)}g`;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Analyses per hour one serve sustains at a given per-frame cost.
|
|
214
|
+
*
|
|
215
|
+
* `litert-lm serve` admits ONE request at a time, so this is the machine's
|
|
216
|
+
* whole sensing capacity — not a per-camera figure. `null` (never 0, never
|
|
217
|
+
* Infinity) for a non-positive input, because a fabricated capacity is how a
|
|
218
|
+
* machine that measured nothing ends up in a spec sheet.
|
|
219
|
+
*/
|
|
220
|
+
function analysesPerHour(secondsPerFrame) {
|
|
221
|
+
if (!Number.isFinite(secondsPerFrame) || secondsPerFrame <= 0)
|
|
222
|
+
return null;
|
|
223
|
+
return Number((3600 / secondsPerFrame).toFixed(1));
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* How many cameras this per-frame cost serves, if every camera must be looked
|
|
227
|
+
* at once per `cadenceSeconds`. FLOOR, not round: 3.8 cameras is 3 cameras and
|
|
228
|
+
* one that misses its cadence.
|
|
229
|
+
*/
|
|
230
|
+
function camerasAtCadence(secondsPerFrame, cadenceSeconds) {
|
|
231
|
+
if (!Number.isFinite(secondsPerFrame) || secondsPerFrame <= 0)
|
|
232
|
+
return null;
|
|
233
|
+
if (!Number.isFinite(cadenceSeconds) || cadenceSeconds <= 0)
|
|
234
|
+
return null;
|
|
235
|
+
return Math.floor(cadenceSeconds / secondsPerFrame);
|
|
236
|
+
}
|
|
237
|
+
function floorFor(cameras, cadenceSeconds, slotShare = 1) {
|
|
238
|
+
if (!Number.isFinite(cameras) || cameras <= 0)
|
|
239
|
+
return null;
|
|
240
|
+
if (!Number.isFinite(cadenceSeconds) || cadenceSeconds <= 0)
|
|
241
|
+
return null;
|
|
242
|
+
if (!Number.isFinite(slotShare) || slotShare <= 0 || slotShare > 1)
|
|
243
|
+
return null;
|
|
244
|
+
const budget = cadenceSeconds * slotShare;
|
|
245
|
+
return {
|
|
246
|
+
cameras,
|
|
247
|
+
cadenceSeconds,
|
|
248
|
+
slotShare,
|
|
249
|
+
maxSecondsPerFrame: Number((budget / cameras).toFixed(2)),
|
|
250
|
+
minAnalysesPerHour: Number(((cameras * 3600) / budget).toFixed(1)),
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Does this measured per-frame cost clear the floor? A machine with NO measured
|
|
255
|
+
* number does not "fail" — it returns null, because unmeasured and too-slow are
|
|
256
|
+
* different facts and collapsing them is exactly how windows-latest spent two
|
|
257
|
+
* months looking like a slow box instead of an unmeasured one.
|
|
258
|
+
*/
|
|
259
|
+
function gradeAgainstFloor(secondsPerFrame, floor) {
|
|
260
|
+
if (secondsPerFrame === null || !Number.isFinite(secondsPerFrame) || secondsPerFrame <= 0)
|
|
261
|
+
return null;
|
|
262
|
+
const cameras = camerasAtCadence(secondsPerFrame, floor.cadenceSeconds * floor.slotShare);
|
|
263
|
+
const perHour = analysesPerHour(secondsPerFrame);
|
|
264
|
+
const clears = secondsPerFrame <= floor.maxSecondsPerFrame;
|
|
265
|
+
return {
|
|
266
|
+
clears,
|
|
267
|
+
secondsPerFrame,
|
|
268
|
+
camerasSupported: cameras,
|
|
269
|
+
analysesPerHour: perHour,
|
|
270
|
+
headroom: Number((floor.maxSecondsPerFrame / secondsPerFrame).toFixed(2)),
|
|
271
|
+
reason: clears
|
|
272
|
+
? `${secondsPerFrame}s/frame <= ${floor.maxSecondsPerFrame}s budget: serves ${cameras} cameras at a ${floor.cadenceSeconds}s cadence (target ${floor.cameras})`
|
|
273
|
+
: `${secondsPerFrame}s/frame EXCEEDS the ${floor.maxSecondsPerFrame}s budget: serves ${cameras} camera(s) at a ${floor.cadenceSeconds}s cadence, not ${floor.cameras}`,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* A time budget for a whole bench run, so a run that cannot finish still
|
|
278
|
+
* REPORTS what it measured. The Windows lane's entire history is runs that
|
|
279
|
+
* measured frames and then died at the job cap having written nothing: a
|
|
280
|
+
* partial matrix is a datapoint, a killed process is not.
|
|
281
|
+
*/
|
|
282
|
+
function budgetRemaining(startedAtMs, budgetMs, nowMs) {
|
|
283
|
+
if (!Number.isFinite(budgetMs) || budgetMs <= 0)
|
|
284
|
+
return Number.POSITIVE_INFINITY;
|
|
285
|
+
return budgetMs - (nowMs - startedAtMs);
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Should the runner attempt one more frame? Refuses when the time left is less
|
|
289
|
+
* than what the last frames actually cost — starting a frame we cannot finish
|
|
290
|
+
* both wastes the remaining budget and records a DEADLINE as if it were a
|
|
291
|
+
* machine's speed.
|
|
292
|
+
*/
|
|
293
|
+
function shouldAttemptAnother(remainingMs, observedFrameMs, fallbackFrameMs) {
|
|
294
|
+
if (remainingMs === Number.POSITIVE_INFINITY)
|
|
295
|
+
return true;
|
|
296
|
+
if (remainingMs <= 0)
|
|
297
|
+
return false;
|
|
298
|
+
const worst = (observedFrameMs || []).filter((n) => Number.isFinite(n) && n > 0);
|
|
299
|
+
const need = worst.length ? Math.max(...worst) : fallbackFrameMs;
|
|
300
|
+
return remainingMs >= need;
|
|
301
|
+
}
|
|
173
302
|
/**
|
|
174
303
|
* Nearest-rank percentile of a sample. `null` on empty, for the same reason
|
|
175
304
|
* `median` returns null.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localVlmBench.js","sourceRoot":"","sources":["../src/localVlmBench.ts"],"names":[],"mappings":";;;AAkEA,4CAQC;AAeD,0DA2BC;AA0BD,kCAaC;AAqBD,wCAUC;AAMD,wBAMC;
|
|
1
|
+
{"version":3,"file":"localVlmBench.js","sourceRoot":"","sources":["../src/localVlmBench.ts"],"names":[],"mappings":"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"}
|
|
@@ -212,6 +212,56 @@ export interface SamplerConfig {
|
|
|
212
212
|
* a machine we do not ship.
|
|
213
213
|
*/
|
|
214
214
|
feedPhaseModel: 'uniform' | 'staggered';
|
|
215
|
+
/**
|
|
216
|
+
* Floor between two MOTION-triggered analyses of ONE feed, seconds — the
|
|
217
|
+
* `rate_limited` branch of `MotionGate.evaluate`, whose shipped value is
|
|
218
|
+
* `MIN_ANALYZE_INTERVAL_MS` (30 s).
|
|
219
|
+
*
|
|
220
|
+
* DEFAULT 0 (off), which is what every committed baseline was measured under,
|
|
221
|
+
* so this cannot silently move a pinned number.
|
|
222
|
+
*
|
|
223
|
+
* It was safe to omit while the only question was CATCH RATE: an event needs
|
|
224
|
+
* one analysis to be caught, and the first one is never rate-limited. It stops
|
|
225
|
+
* being safe the moment the question is CORROBORATION, because then the
|
|
226
|
+
* quantity of interest is how many analyses land inside one event, and this is
|
|
227
|
+
* the constraint that bounds it. A replay without it reports corroboration the
|
|
228
|
+
* shipped connector cannot deliver.
|
|
229
|
+
*
|
|
230
|
+
* The heartbeat is deliberately NOT subject to it: `heartbeatDue` returns from
|
|
231
|
+
* `MotionGate.evaluate` above the rate-limit branch, which is what lets a
|
|
232
|
+
* starved still feed keep qualifying.
|
|
233
|
+
*/
|
|
234
|
+
minAnalyzeIntervalS: number;
|
|
235
|
+
/**
|
|
236
|
+
* Does an event with ongoing movement present a change to the gate on EVERY
|
|
237
|
+
* look, or only once?
|
|
238
|
+
*
|
|
239
|
+
* DEFAULT false — present once — which is the model every committed baseline
|
|
240
|
+
* uses, and it is the right one for catch rate: it refuses to invent analysis
|
|
241
|
+
* demand, and a second look at an event already analysed cannot catch it
|
|
242
|
+
* twice.
|
|
243
|
+
*
|
|
244
|
+
* For corroboration it is the wrong model and would understate the answer to
|
|
245
|
+
* zero. The detector is a frame-to-frame differ, so a person who is still
|
|
246
|
+
* MOVING changes the signature on every look and re-presents; the shipped
|
|
247
|
+
* `stationary` branch suppresses only a signature that has not changed since
|
|
248
|
+
* the last landed analysis. Turning this on together with
|
|
249
|
+
* `minAnalyzeIntervalS` is what reproduces the real thing: a moving event is
|
|
250
|
+
* re-analysed at the analyze floor, a still one only at the heartbeat.
|
|
251
|
+
*/
|
|
252
|
+
motionRepresents: boolean;
|
|
253
|
+
/**
|
|
254
|
+
* How many analyses must land inside one event, within `confirmWindowS`,
|
|
255
|
+
* before the alert layer will speak for it — the replay's mirror of
|
|
256
|
+
* `sensing_routes.confirm_samples`.
|
|
257
|
+
*
|
|
258
|
+
* DEFAULT 1, i.e. no corroboration required, which makes `confirmRate` 1
|
|
259
|
+
* wherever the event was analysed at all and leaves `confirmedCatchRate`
|
|
260
|
+
* identical to `catchRate`. The committed baseline is unmoved.
|
|
261
|
+
*/
|
|
262
|
+
confirmSamples: number;
|
|
263
|
+
/** Window those analyses must fall inside, seconds. Mirrors `confirm_window_seconds`. */
|
|
264
|
+
confirmWindowS: number;
|
|
215
265
|
}
|
|
216
266
|
export declare const DEFAULT_SAMPLER: Readonly<SamplerConfig>;
|
|
217
267
|
/** Per-event replay outcome. */
|
|
@@ -237,6 +287,19 @@ export interface EventOutcome {
|
|
|
237
287
|
* model_wrong — it reached the model and the model read it wrong.
|
|
238
288
|
*/
|
|
239
289
|
lostTo: 'never_looked' | 'gate_dropped' | 'slot_starved' | 'buffer_expired' | 'model_wrong' | null;
|
|
290
|
+
/**
|
|
291
|
+
* How many analyses landed inside this event. 0 or 1 for almost everything
|
|
292
|
+
* unless `motionRepresents` is on — see that field for why the default model
|
|
293
|
+
* deliberately caps it at one.
|
|
294
|
+
*/
|
|
295
|
+
analyses: number;
|
|
296
|
+
/**
|
|
297
|
+
* Were `confirmSamples` of those analyses inside one `confirmWindowS` window?
|
|
298
|
+
* This is the ALERT layer's question, not the sensing layer's: an event can be
|
|
299
|
+
* caught (the model read one frame right) and still be unconfirmable, which is
|
|
300
|
+
* exactly the trade the corroboration gate makes.
|
|
301
|
+
*/
|
|
302
|
+
confirmed: boolean;
|
|
240
303
|
/** Seconds from event start to the analysis landing. `null` if never. */
|
|
241
304
|
latencyS: number | null;
|
|
242
305
|
}
|
|
@@ -271,6 +334,24 @@ export interface ShapeReport {
|
|
|
271
334
|
shapeId: string;
|
|
272
335
|
group: ShapeGroup;
|
|
273
336
|
events: number;
|
|
337
|
+
/**
|
|
338
|
+
* Of the events the model DID read correctly, the fraction that also produced
|
|
339
|
+
* `confirmSamples` readings inside one window — i.e. the share of real catches
|
|
340
|
+
* the corroboration gate is willing to speak for.
|
|
341
|
+
*
|
|
342
|
+
* This is the cost side of the gate, and it is reported as its own number
|
|
343
|
+
* rather than folded into the catch rate because they are different claims:
|
|
344
|
+
* catch rate is what the CONNECTOR sensed, this is what the ALERT layer will
|
|
345
|
+
* say out loud. A gate that suppressed everything would leave catch rate
|
|
346
|
+
* untouched and drive this to 0.
|
|
347
|
+
*/
|
|
348
|
+
confirmRate: number;
|
|
349
|
+
/**
|
|
350
|
+
* `catchRate x confirmRate` — the fraction of events that both got read right
|
|
351
|
+
* AND could be corroborated. THE alert-layer number, and the one to compare
|
|
352
|
+
* against the pre-gate catch rate.
|
|
353
|
+
*/
|
|
354
|
+
confirmedCatchRate: number;
|
|
274
355
|
/** Fraction of events where a look landed inside. The ceiling. */
|
|
275
356
|
lookRate: number;
|
|
276
357
|
/** Fraction of events the model was actually asked about. */
|
|
@@ -335,6 +416,8 @@ export declare function reportByGroup(reports: readonly ShapeReport[]): Array<{
|
|
|
335
416
|
falseTriggerRate: number | null;
|
|
336
417
|
admissionFalseTriggerRate: number;
|
|
337
418
|
lookRate: number;
|
|
419
|
+
confirmRate: number;
|
|
420
|
+
confirmedCatchRate: number;
|
|
338
421
|
}>;
|
|
339
422
|
/**
|
|
340
423
|
* The look cadence a shape needs to reach `target`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sensingCatchRate.d.ts","sourceRoot":"","sources":["../src/sensingCatchRate.ts"],"names":[],"mappings":"AAqEA;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,CAAC;AAErE,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAAwD,CAAC;AAEvG;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,yEAAyE;IACzE,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,KAAK,EAAE,UAAU,CAAC;IAClB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,UAAU,EAAE,kBAAkB,GAAG,gBAAgB,GAAG,eAAe,GAAG,oBAAoB,CAAC;IAC3F;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EAuElD,CAAC;AAIH,yEAAyE;AACzE,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAE1D;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,aAAa,CAAC,YAAY,CAAC,GACtC,aAAa,GAAG,IAAI,CAOtB;AAMD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIxE;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMhG;AAMD,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,eAAe,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;;;;;;;;;;;;;;;OAiBG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;;;;OASG;IACH,oBAAoB,EAAE,OAAO,CAAC;IAC9B,kDAAkD;IAClD,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,cAAc,EAAE,SAAS,GAAG,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"sensingCatchRate.d.ts","sourceRoot":"","sources":["../src/sensingCatchRate.ts"],"names":[],"mappings":"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"}
|
package/dist/sensingCatchRate.js
CHANGED
|
@@ -231,6 +231,12 @@ exports.DEFAULT_SAMPLER = Object.freeze({
|
|
|
231
231
|
analyzeJitterS: 0,
|
|
232
232
|
fairShareAcrossFeeds: false,
|
|
233
233
|
fairShareMaxHoldS: 5,
|
|
234
|
+
// All four default to "today's model", so DEFAULT_SAMPLER is byte-identical
|
|
235
|
+
// in behaviour to the one every committed baseline was measured under.
|
|
236
|
+
minAnalyzeIntervalS: 0,
|
|
237
|
+
motionRepresents: false,
|
|
238
|
+
confirmSamples: 1,
|
|
239
|
+
confirmWindowS: 90,
|
|
234
240
|
feedPhaseModel: 'uniform',
|
|
235
241
|
});
|
|
236
242
|
/**
|
|
@@ -321,7 +327,10 @@ function replay(events, config = {}, { durationS, seed = 1 }) {
|
|
|
321
327
|
}
|
|
322
328
|
return false;
|
|
323
329
|
};
|
|
324
|
-
const analyzedEvents = new Map(); // eventId -> analysis land time
|
|
330
|
+
const analyzedEvents = new Map(); // eventId -> FIRST analysis land time
|
|
331
|
+
// eventId -> every analysis land time, in order. The corroboration question is
|
|
332
|
+
// "how many readings, how far apart", so a count alone cannot answer it.
|
|
333
|
+
const analysisTimes = new Map();
|
|
325
334
|
let idleAnalyses = 0;
|
|
326
335
|
let analyses = 0;
|
|
327
336
|
let looks = 0;
|
|
@@ -367,6 +376,11 @@ function replay(events, config = {}, { durationS, seed = 1 }) {
|
|
|
367
376
|
if (frame.eventId) {
|
|
368
377
|
if (!analyzedEvents.has(frame.eventId))
|
|
369
378
|
analyzedEvents.set(frame.eventId, t);
|
|
379
|
+
const times = analysisTimes.get(frame.eventId);
|
|
380
|
+
if (times)
|
|
381
|
+
times.push(t);
|
|
382
|
+
else
|
|
383
|
+
analysisTimes.set(frame.eventId, [t]);
|
|
370
384
|
}
|
|
371
385
|
else {
|
|
372
386
|
idleAnalyses += 1;
|
|
@@ -421,7 +435,11 @@ function replay(events, config = {}, { durationS, seed = 1 }) {
|
|
|
421
435
|
// `motion` only on the look that catches the CHANGE. A still-scene event
|
|
422
436
|
// never presents one at all and is reachable ONLY by the heartbeat — the
|
|
423
437
|
// leaking-cooler case connectorCadence.ts is written about.
|
|
424
|
-
|
|
438
|
+
// `motionRepresents` on: a still-MOVING event changes the differ's signature
|
|
439
|
+
// every look, so it presents a change every look. Off (the default): one
|
|
440
|
+
// presentation per event, which is what the committed baselines model.
|
|
441
|
+
const presentsChange = Boolean(active && active.producesMotion
|
|
442
|
+
&& (cfg.motionRepresents || !changePresented.has(active.id)));
|
|
425
443
|
// The gate can MISS a change it looked at. `gateRecall < 1` draws for that,
|
|
426
444
|
// and the draw is short-circuited at 1 so the shipped baseline consumes the
|
|
427
445
|
// same random stream it always did — a config that only isolates a layer
|
|
@@ -435,6 +453,16 @@ function replay(events, config = {}, { durationS, seed = 1 }) {
|
|
|
435
453
|
const motion = gateSaw;
|
|
436
454
|
if (!motion && !heartbeatDue)
|
|
437
455
|
continue; // no_motion / stationary -> dropped
|
|
456
|
+
// `rate_limited`. Sits BELOW `heartbeatDue` in MotionGate.evaluate — a due
|
|
457
|
+
// heartbeat returns before this branch is reached — so it throttles motion
|
|
458
|
+
// only. This is the constraint that decides whether corroboration is
|
|
459
|
+
// physically available to a shape: at the shipped 30 s floor, an event
|
|
460
|
+
// shorter than 30 s can never produce a second reading, however fast we look.
|
|
461
|
+
if (motion && !heartbeatDue && cfg.minAnalyzeIntervalS > 0) {
|
|
462
|
+
const lastLanded = lastAnalyzedAt.get(feed);
|
|
463
|
+
if (lastLanded !== undefined && t - lastLanded < cfg.minAnalyzeIntervalS)
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
438
466
|
const frame = {
|
|
439
467
|
eventId: active ? active.id : null,
|
|
440
468
|
feed,
|
|
@@ -458,10 +486,26 @@ function replay(events, config = {}, { durationS, seed = 1 }) {
|
|
|
458
486
|
pump(durationS);
|
|
459
487
|
// Content layer. One draw per caught event, from the same seeded stream, so
|
|
460
488
|
// the whole result is reproducible from `seed` alone.
|
|
489
|
+
/**
|
|
490
|
+
* Were `need` of these land times inside one `windowS` window? A forward scan
|
|
491
|
+
* rather than a count, because N readings spread over an hour are not
|
|
492
|
+
* corroboration — the evaluator prunes to the window before it counts, and a
|
|
493
|
+
* replay that only counted would promise agreement Redis will never see.
|
|
494
|
+
*/
|
|
495
|
+
const withinWindow = (times, need, windowS) => {
|
|
496
|
+
if (need <= 1)
|
|
497
|
+
return times.length >= 1;
|
|
498
|
+
for (let i = 0; i + need - 1 < times.length; i += 1) {
|
|
499
|
+
if (times[i + need - 1] - times[i] <= windowS)
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
return false;
|
|
503
|
+
};
|
|
461
504
|
const outcomes = events.map((e) => {
|
|
462
505
|
const looked = everLooked.has(e.id);
|
|
463
506
|
const landedAt = analyzedEvents.get(e.id);
|
|
464
507
|
const analyzed = landedAt !== undefined;
|
|
508
|
+
const times = analysisTimes.get(e.id) || [];
|
|
465
509
|
let lostTo = null;
|
|
466
510
|
let caught = false;
|
|
467
511
|
if (!looked)
|
|
@@ -492,6 +536,8 @@ function replay(events, config = {}, { durationS, seed = 1 }) {
|
|
|
492
536
|
caught,
|
|
493
537
|
lostTo,
|
|
494
538
|
latencyS: analyzed ? landedAt - e.startS : null,
|
|
539
|
+
analyses: times.length,
|
|
540
|
+
confirmed: analyzed && withinWindow(times, cfg.confirmSamples, cfg.confirmWindowS),
|
|
495
541
|
};
|
|
496
542
|
});
|
|
497
543
|
let falseTriggers = 0;
|
|
@@ -531,11 +577,17 @@ function reportByShape(result, { contentScored = false } = {}) {
|
|
|
531
577
|
if (!outs || outs.length === 0)
|
|
532
578
|
continue;
|
|
533
579
|
const caught = outs.filter((o) => o.caught).length;
|
|
580
|
+
const confirmedCaught = outs.filter((o) => o.caught && o.confirmed).length;
|
|
534
581
|
const totalFires = caught + result.falseTriggers;
|
|
535
582
|
reports.push({
|
|
536
583
|
shapeId: shape.id,
|
|
537
584
|
group: shape.group,
|
|
538
585
|
events: outs.length,
|
|
586
|
+
// Denominator is CAUGHT events, not all events: this measures what the
|
|
587
|
+
// gate costs on the catches we actually had, so a shape the connector
|
|
588
|
+
// never sensed cannot flatter it.
|
|
589
|
+
confirmRate: caught > 0 ? confirmedCaught / caught : 0,
|
|
590
|
+
confirmedCatchRate: confirmedCaught / outs.length,
|
|
539
591
|
lookRate: outs.filter((o) => o.looked).length / outs.length,
|
|
540
592
|
analyzeRate: outs.filter((o) => o.analyzed).length / outs.length,
|
|
541
593
|
catchRate: caught / outs.length,
|
|
@@ -580,6 +632,15 @@ function reportByGroup(reports) {
|
|
|
580
632
|
: rows.reduce((a, r) => a + r.falseTriggerRate * r.events, 0) / events,
|
|
581
633
|
admissionFalseTriggerRate: rows.reduce((a, r) => a + r.admissionFalseTriggerRate * r.events, 0) / events,
|
|
582
634
|
lookRate: rows.reduce((a, r) => a + r.lookRate * r.events, 0) / events,
|
|
635
|
+
// Event-weighted like every other rollup here. Derived from the
|
|
636
|
+
// confirmed-catch and catch totals rather than averaging the per-shape
|
|
637
|
+
// confirmRate, because that ratio's denominator differs per shape.
|
|
638
|
+
confirmedCatchRate: rows.reduce((a, r) => a + r.confirmedCatchRate * r.events, 0) / events,
|
|
639
|
+
confirmRate: (() => {
|
|
640
|
+
const caughtTotal = rows.reduce((a, r) => a + r.catchRate * r.events, 0);
|
|
641
|
+
const confirmedTotal = rows.reduce((a, r) => a + r.confirmedCatchRate * r.events, 0);
|
|
642
|
+
return caughtTotal > 0 ? confirmedTotal / caughtTotal : 0;
|
|
643
|
+
})(),
|
|
583
644
|
});
|
|
584
645
|
}
|
|
585
646
|
return out;
|