@camstack/addon-post-analysis 1.2.212 → 1.2.213
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/{dist-GQbzNwJB.mjs → dist-CT2SouNJ.mjs} +42 -1
- package/dist/{dist-IE6UOohI.js → dist-DA1sJKXM.js} +42 -1
- package/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-utVZjlcV.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-CxVox7bu.mjs} +3 -3
- package/dist/pipeline-analytics/{hostInit-BL9mWOe9.mjs → hostInit-BSVhT9bi.mjs} +3 -3
- package/dist/pipeline-analytics/index.js +88 -9
- package/dist/pipeline-analytics/index.mjs +88 -9
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +1 -1
|
@@ -22483,6 +22483,22 @@ var occupancyRecheckFramesField = {
|
|
|
22483
22483
|
step: 1
|
|
22484
22484
|
};
|
|
22485
22485
|
/**
|
|
22486
|
+
* Frames one PRE-ROLL catch-up burst may send to inference at session open.
|
|
22487
|
+
*
|
|
22488
|
+
* The default of 12 over a ~4 s retained window is one frame per ~333 ms of
|
|
22489
|
+
* footage, and costs ~480 ms of ONE inference permit at the 40 ms/frame this
|
|
22490
|
+
* fleet measures — one-shot, and only ever taken while a permit would still be
|
|
22491
|
+
* spare for live. `0` turns the burst off entirely (the history is still
|
|
22492
|
+
* decoded, because that is how the dial reaches a decodable GOP, and is then
|
|
22493
|
+
* discarded — the pre-D411 behaviour).
|
|
22494
|
+
*/
|
|
22495
|
+
var preRollInferenceFramesField = {
|
|
22496
|
+
min: 0,
|
|
22497
|
+
max: 30,
|
|
22498
|
+
default: 12,
|
|
22499
|
+
step: 1
|
|
22500
|
+
};
|
|
22501
|
+
/**
|
|
22486
22502
|
* Source enum for motion signals fed to the runner. Extensible — add
|
|
22487
22503
|
* new variants here when new motion-trigger paths are wired in
|
|
22488
22504
|
* (`wasm-cross-camera`, `event-bus-relay`, etc.). The runner uses
|
|
@@ -22723,6 +22739,31 @@ var RunnerCameraConfigSchema = object({
|
|
|
22723
22739
|
* to every occupancy rule until something moved in front of it. The churn is
|
|
22724
22740
|
* now paid on the interval instead — see `occupancyRecheckSecField`.
|
|
22725
22741
|
*/
|
|
22742
|
+
/**
|
|
22743
|
+
* Infer the session's PRE-ROLL — the retained history the restreamer replays
|
|
22744
|
+
* at session open — instead of decoding it and throwing it away.
|
|
22745
|
+
*
|
|
22746
|
+
* DEFAULT `true`, and the default is the argument. This is not a new
|
|
22747
|
+
* capability being offered cautiously: the pre-roll is ALREADY requested,
|
|
22748
|
+
* already served, already decoded and already paid for on every on-motion
|
|
22749
|
+
* detection session that asks for history. What shipped was a last-moment
|
|
22750
|
+
* discard — `FrameSlot`'s throttle compares wall clocks, and ~4 s of media
|
|
22751
|
+
* arriving inside a few hundred ms of wall clock looks to it like one frame's
|
|
22752
|
+
* worth. Device 617, 2026-09-08: a re-run of the SAME model over the stored
|
|
22753
|
+
* recording scored the subject `vehicle 0.5669` — above the 0.50 floor —
|
|
22754
|
+
* 1.68 s BEFORE the live track was born, on a frame that was in the pre-roll,
|
|
22755
|
+
* was decoded, and was freed.
|
|
22756
|
+
*
|
|
22757
|
+
* Shipping that as opt-in would ship the bug: an operator cannot discover a
|
|
22758
|
+
* setting whose absence looks exactly like a camera that noticed the cyclist
|
|
22759
|
+
* late. What makes ON safe is not a switch but the BOUND —
|
|
22760
|
+
* `preRollInferenceFrames`, a wall-clock ceiling, and a lane that never takes
|
|
22761
|
+
* the last inference permit — so the switch exists for the camera where the
|
|
22762
|
+
* history is worthless (a doorbell whose subject is always already at the
|
|
22763
|
+
* door), not as a hedge against the feature.
|
|
22764
|
+
*/
|
|
22765
|
+
preRollInferenceEnabled: boolean().default(true),
|
|
22766
|
+
preRollInferenceFrames: number().min(preRollInferenceFramesField.min).max(preRollInferenceFramesField.max).default(preRollInferenceFramesField.default),
|
|
22726
22767
|
occupancyRecheckEnabled: boolean().default(true),
|
|
22727
22768
|
occupancyRecheckSec: number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
|
|
22728
22769
|
occupancyRecheckFrames: number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
|
|
@@ -22751,7 +22792,7 @@ var RunnerCameraConfigSchema = object({
|
|
|
22751
22792
|
*/
|
|
22752
22793
|
inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
|
|
22753
22794
|
});
|
|
22754
|
-
motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
|
|
22795
|
+
motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, preRollInferenceFramesField.min, preRollInferenceFramesField.max, preRollInferenceFramesField.step, preRollInferenceFramesField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
|
|
22755
22796
|
/**
|
|
22756
22797
|
* Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
|
|
22757
22798
|
* load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
|
|
@@ -22514,6 +22514,22 @@ var occupancyRecheckFramesField = {
|
|
|
22514
22514
|
step: 1
|
|
22515
22515
|
};
|
|
22516
22516
|
/**
|
|
22517
|
+
* Frames one PRE-ROLL catch-up burst may send to inference at session open.
|
|
22518
|
+
*
|
|
22519
|
+
* The default of 12 over a ~4 s retained window is one frame per ~333 ms of
|
|
22520
|
+
* footage, and costs ~480 ms of ONE inference permit at the 40 ms/frame this
|
|
22521
|
+
* fleet measures — one-shot, and only ever taken while a permit would still be
|
|
22522
|
+
* spare for live. `0` turns the burst off entirely (the history is still
|
|
22523
|
+
* decoded, because that is how the dial reaches a decodable GOP, and is then
|
|
22524
|
+
* discarded — the pre-D411 behaviour).
|
|
22525
|
+
*/
|
|
22526
|
+
var preRollInferenceFramesField = {
|
|
22527
|
+
min: 0,
|
|
22528
|
+
max: 30,
|
|
22529
|
+
default: 12,
|
|
22530
|
+
step: 1
|
|
22531
|
+
};
|
|
22532
|
+
/**
|
|
22517
22533
|
* Source enum for motion signals fed to the runner. Extensible — add
|
|
22518
22534
|
* new variants here when new motion-trigger paths are wired in
|
|
22519
22535
|
* (`wasm-cross-camera`, `event-bus-relay`, etc.). The runner uses
|
|
@@ -22754,6 +22770,31 @@ var RunnerCameraConfigSchema = object({
|
|
|
22754
22770
|
* to every occupancy rule until something moved in front of it. The churn is
|
|
22755
22771
|
* now paid on the interval instead — see `occupancyRecheckSecField`.
|
|
22756
22772
|
*/
|
|
22773
|
+
/**
|
|
22774
|
+
* Infer the session's PRE-ROLL — the retained history the restreamer replays
|
|
22775
|
+
* at session open — instead of decoding it and throwing it away.
|
|
22776
|
+
*
|
|
22777
|
+
* DEFAULT `true`, and the default is the argument. This is not a new
|
|
22778
|
+
* capability being offered cautiously: the pre-roll is ALREADY requested,
|
|
22779
|
+
* already served, already decoded and already paid for on every on-motion
|
|
22780
|
+
* detection session that asks for history. What shipped was a last-moment
|
|
22781
|
+
* discard — `FrameSlot`'s throttle compares wall clocks, and ~4 s of media
|
|
22782
|
+
* arriving inside a few hundred ms of wall clock looks to it like one frame's
|
|
22783
|
+
* worth. Device 617, 2026-09-08: a re-run of the SAME model over the stored
|
|
22784
|
+
* recording scored the subject `vehicle 0.5669` — above the 0.50 floor —
|
|
22785
|
+
* 1.68 s BEFORE the live track was born, on a frame that was in the pre-roll,
|
|
22786
|
+
* was decoded, and was freed.
|
|
22787
|
+
*
|
|
22788
|
+
* Shipping that as opt-in would ship the bug: an operator cannot discover a
|
|
22789
|
+
* setting whose absence looks exactly like a camera that noticed the cyclist
|
|
22790
|
+
* late. What makes ON safe is not a switch but the BOUND —
|
|
22791
|
+
* `preRollInferenceFrames`, a wall-clock ceiling, and a lane that never takes
|
|
22792
|
+
* the last inference permit — so the switch exists for the camera where the
|
|
22793
|
+
* history is worthless (a doorbell whose subject is always already at the
|
|
22794
|
+
* door), not as a hedge against the feature.
|
|
22795
|
+
*/
|
|
22796
|
+
preRollInferenceEnabled: boolean().default(true),
|
|
22797
|
+
preRollInferenceFrames: number().min(preRollInferenceFramesField.min).max(preRollInferenceFramesField.max).default(preRollInferenceFramesField.default),
|
|
22757
22798
|
occupancyRecheckEnabled: boolean().default(true),
|
|
22758
22799
|
occupancyRecheckSec: number().min(occupancyRecheckSecField.min).max(occupancyRecheckSecField.max).default(occupancyRecheckSecField.default),
|
|
22759
22800
|
occupancyRecheckFrames: number().min(occupancyRecheckFramesField.min).max(occupancyRecheckFramesField.max).default(occupancyRecheckFramesField.default),
|
|
@@ -22782,7 +22823,7 @@ var RunnerCameraConfigSchema = object({
|
|
|
22782
22823
|
*/
|
|
22783
22824
|
inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
|
|
22784
22825
|
});
|
|
22785
|
-
motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
|
|
22826
|
+
motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, preRollInferenceFramesField.min, preRollInferenceFramesField.max, preRollInferenceFramesField.step, preRollInferenceFramesField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
|
|
22786
22827
|
/**
|
|
22787
22828
|
* Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
|
|
22788
22829
|
* load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
|
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
5
|
+
const require_dist = require("../dist-DA1sJKXM.js");
|
|
6
6
|
let node_fs = require("node:fs");
|
|
7
7
|
node_fs = require_dist.__toESM(node_fs);
|
|
8
8
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { At as resolvePoolMemoryPolicy, B as PoolMemoryWatchdog, Ct as parseProcStatus, gt as hfModelUrl, ut as embeddingEncoderCapability, zt as BaseAddon } from "../dist-
|
|
1
|
+
import { At as resolvePoolMemoryPolicy, B as PoolMemoryWatchdog, Ct as parseProcStatus, gt as hfModelUrl, ut as embeddingEncoderCapability, zt as BaseAddon } from "../dist-CT2SouNJ.mjs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import * as fs from "node:fs";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -3,7 +3,7 @@ import "./dist-CYZr2fwk.mjs";
|
|
|
3
3
|
var e = {
|
|
4
4
|
"@camstack/sdk": {
|
|
5
5
|
name: "@camstack/sdk",
|
|
6
|
-
version: "1.2.
|
|
6
|
+
version: "1.2.92",
|
|
7
7
|
scope: ["default"],
|
|
8
8
|
loaded: !1,
|
|
9
9
|
from: "addon_pipeline_analytics_widgets",
|
|
@@ -18,7 +18,7 @@ var e = {
|
|
|
18
18
|
},
|
|
19
19
|
"@camstack/types": {
|
|
20
20
|
name: "@camstack/types",
|
|
21
|
-
version: "1.2.
|
|
21
|
+
version: "1.2.172",
|
|
22
22
|
scope: ["default"],
|
|
23
23
|
loaded: !1,
|
|
24
24
|
from: "addon_pipeline_analytics_widgets",
|
|
@@ -33,7 +33,7 @@ var e = {
|
|
|
33
33
|
},
|
|
34
34
|
"@camstack/ui-library": {
|
|
35
35
|
name: "@camstack/ui-library",
|
|
36
|
-
version: "1.2.
|
|
36
|
+
version: "1.2.140",
|
|
37
37
|
scope: ["default"],
|
|
38
38
|
loaded: !1,
|
|
39
39
|
from: "addon_pipeline_analytics_widgets",
|
|
@@ -36,7 +36,7 @@ async function r() {
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"@camstack/types": {
|
|
39
|
-
version: "1.2.
|
|
39
|
+
version: "1.2.172",
|
|
40
40
|
scope: "default",
|
|
41
41
|
shareConfig: {
|
|
42
42
|
singleton: !0,
|
|
@@ -45,7 +45,7 @@ async function r() {
|
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
47
|
"@camstack/sdk": {
|
|
48
|
-
version: "1.2.
|
|
48
|
+
version: "1.2.92",
|
|
49
49
|
scope: "default",
|
|
50
50
|
shareConfig: {
|
|
51
51
|
singleton: !0,
|
|
@@ -81,7 +81,7 @@ async function r() {
|
|
|
81
81
|
}
|
|
82
82
|
},
|
|
83
83
|
"@camstack/ui-library": {
|
|
84
|
-
version: "1.2.
|
|
84
|
+
version: "1.2.140",
|
|
85
85
|
scope: "default",
|
|
86
86
|
shareConfig: {
|
|
87
87
|
singleton: !0,
|
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
5
|
+
const require_dist = require("../dist-DA1sJKXM.js");
|
|
6
6
|
let node_fs = require("node:fs");
|
|
7
7
|
node_fs = require_dist.__toESM(node_fs, 1);
|
|
8
8
|
let node_path = require("node:path");
|
|
@@ -34861,6 +34861,9 @@ var DEFAULT_TRACKER_CONFIG = {
|
|
|
34861
34861
|
var PERSON_CLASS = "person";
|
|
34862
34862
|
var ANIMAL_CLASS = "animal";
|
|
34863
34863
|
var MAX_PATH_LENGTH = 300;
|
|
34864
|
+
/** No stationary-held detections on this frame — the default for every caller
|
|
34865
|
+
* that has no gate (replay, tests, the non-pipeline planes). */
|
|
34866
|
+
var EMPTY_INDEX_SET = /* @__PURE__ */ new Set();
|
|
34864
34867
|
function clamp$1(value, min, max) {
|
|
34865
34868
|
return Math.max(min, Math.min(max, value));
|
|
34866
34869
|
}
|
|
@@ -35480,13 +35483,15 @@ var SortTracker = class SortTracker {
|
|
|
35480
35483
|
* gates) so the two-tier ByteTrack association stays a single implementation.
|
|
35481
35484
|
* Mutates `used` / `matchedTracks` / `matched` in place.
|
|
35482
35485
|
*/
|
|
35483
|
-
greedyAssociate(detections, candidateIdxs, iouThreshold, timestamp, used, matchedTracks, matched) {
|
|
35486
|
+
greedyAssociate(detections, candidateIdxs, iouThreshold, timestamp, used, matchedTracks, matched, continuationOnly) {
|
|
35484
35487
|
const pairs = [];
|
|
35485
35488
|
for (const track of this.tracks) {
|
|
35486
35489
|
if (matchedTracks.has(track)) continue;
|
|
35487
35490
|
const pbox = this.predicted(track, timestamp);
|
|
35491
|
+
const confirmed = this.isConfirmedForEmit(track);
|
|
35488
35492
|
for (const di of candidateIdxs) {
|
|
35489
35493
|
if (used.has(di)) continue;
|
|
35494
|
+
if (!confirmed && continuationOnly.has(di)) continue;
|
|
35490
35495
|
const det = detections[di];
|
|
35491
35496
|
if (!this.associable(track.class, det)) continue;
|
|
35492
35497
|
const score = iou$3(pbox, det.bbox);
|
|
@@ -35507,6 +35512,7 @@ var SortTracker = class SortTracker {
|
|
|
35507
35512
|
}
|
|
35508
35513
|
update(detections, timestamp, frameContext) {
|
|
35509
35514
|
const frameArea = frameContext ? frameContext.frameWidth * frameContext.frameHeight : 0;
|
|
35515
|
+
const continuationOnly = frameContext?.continuationOnly ?? EMPTY_INDEX_SET;
|
|
35510
35516
|
const resurrectedScene = /* @__PURE__ */ new Map();
|
|
35511
35517
|
if (this.config.maxTrackLifetimeMs > 0) {
|
|
35512
35518
|
const alive = [];
|
|
@@ -35543,12 +35549,12 @@ var SortTracker = class SortTracker {
|
|
|
35543
35549
|
for (let di = 0; di < detections.length; di++) if (this.config.byteTrackEnabled && detections[di].score < this.config.byteTrackHighThreshold) lowIdxs.push(di);
|
|
35544
35550
|
else highIdxs.push(di);
|
|
35545
35551
|
const lowSet = new Set(lowIdxs);
|
|
35546
|
-
this.greedyAssociate(detections, highIdxs, this.config.iouThreshold, timestamp, used, matchedTracks, matched);
|
|
35552
|
+
this.greedyAssociate(detections, highIdxs, this.config.iouThreshold, timestamp, used, matchedTracks, matched, continuationOnly);
|
|
35547
35553
|
const rescuePairs = [];
|
|
35548
35554
|
for (const track of this.tracks) {
|
|
35549
35555
|
if (matchedTracks.has(track)) continue;
|
|
35550
35556
|
for (let di = 0; di < detections.length; di++) {
|
|
35551
|
-
if (used.has(di) || lowSet.has(di)) continue;
|
|
35557
|
+
if (used.has(di) || lowSet.has(di) || continuationOnly.has(di)) continue;
|
|
35552
35558
|
const det = detections[di];
|
|
35553
35559
|
const gate = this.looseMatch(track, det, timestamp);
|
|
35554
35560
|
if (gate === null) continue;
|
|
@@ -35570,7 +35576,7 @@ var SortTracker = class SortTracker {
|
|
|
35570
35576
|
used.add(pair.detIdx);
|
|
35571
35577
|
this.reportBind("rescue", pair.gate, pair.track, det, timestamp);
|
|
35572
35578
|
}
|
|
35573
|
-
if (this.config.byteTrackEnabled && lowIdxs.length > 0) this.greedyAssociate(detections, lowIdxs, this.config.byteTrackLowIouThreshold, timestamp, used, matchedTracks, matched);
|
|
35579
|
+
if (this.config.byteTrackEnabled && lowIdxs.length > 0) this.greedyAssociate(detections, lowIdxs, this.config.byteTrackLowIouThreshold, timestamp, used, matchedTracks, matched, continuationOnly);
|
|
35574
35580
|
for (const [track, det] of matched) {
|
|
35575
35581
|
if (track.class !== det.class) this.reportRefusal("cross-class-absorbed", det, { against: track });
|
|
35576
35582
|
const prevCenter = bboxCentroid({
|
|
@@ -35626,7 +35632,7 @@ var SortTracker = class SortTracker {
|
|
|
35626
35632
|
} else surviving.push(track);
|
|
35627
35633
|
}
|
|
35628
35634
|
for (let di = 0; di < detections.length; di++) {
|
|
35629
|
-
if (used.has(di)) continue;
|
|
35635
|
+
if (used.has(di) || continuationOnly.has(di)) continue;
|
|
35630
35636
|
const det = detections[di];
|
|
35631
35637
|
let best;
|
|
35632
35638
|
let bestScore = -1;
|
|
@@ -35694,6 +35700,11 @@ var SortTracker = class SortTracker {
|
|
|
35694
35700
|
});
|
|
35695
35701
|
for (const di of unmatchedIdx) {
|
|
35696
35702
|
const det = detections[di];
|
|
35703
|
+
if (continuationOnly.has(di)) {
|
|
35704
|
+
this.reportRefusal("stationary-hold", det);
|
|
35705
|
+
used.add(di);
|
|
35706
|
+
continue;
|
|
35707
|
+
}
|
|
35697
35708
|
if (!this.meetsClassScoreFloor(det)) {
|
|
35698
35709
|
this.reportRefusal("score-floor", det, {
|
|
35699
35710
|
threshold: this.config.classMinScores[det.class] ?? 0,
|
|
@@ -36432,14 +36443,28 @@ var FrameProcessor = class {
|
|
|
36432
36443
|
timestamp
|
|
36433
36444
|
}) : {
|
|
36434
36445
|
suppressedIndices: /* @__PURE__ */ new Set(),
|
|
36446
|
+
continuableIndices: /* @__PURE__ */ new Set(),
|
|
36435
36447
|
confirmed: [],
|
|
36436
36448
|
woken: []
|
|
36437
36449
|
};
|
|
36438
|
-
const trackerInput =
|
|
36450
|
+
const trackerInput = [];
|
|
36451
|
+
const continuationOnly = /* @__PURE__ */ new Set();
|
|
36452
|
+
const continuableBoxes = /* @__PURE__ */ new Set();
|
|
36453
|
+
for (let i = 0; i < filteredDetections.length; i++) {
|
|
36454
|
+
const det = filteredDetections[i];
|
|
36455
|
+
if (gate.suppressedIndices.has(i)) {
|
|
36456
|
+
if (!gate.continuableIndices.has(i)) continue;
|
|
36457
|
+
continuationOnly.add(trackerInput.length);
|
|
36458
|
+
continuableBoxes.add(det.bbox);
|
|
36459
|
+
}
|
|
36460
|
+
trackerInput.push(det);
|
|
36461
|
+
}
|
|
36439
36462
|
const trackedDetections = this.tracker.update(trackerInput, timestamp, {
|
|
36440
36463
|
frameWidth,
|
|
36441
|
-
frameHeight
|
|
36464
|
+
frameHeight,
|
|
36465
|
+
continuationOnly
|
|
36442
36466
|
});
|
|
36467
|
+
const stationaryContinued = continuableBoxes.size === 0 ? 0 : trackedDetections.filter((t) => t.matchedThisFrame !== false && continuableBoxes.has(t.bbox)).length;
|
|
36443
36468
|
const riderFolds = foldByVehicleBbox.size === 0 ? EMPTY_RIDER_FOLDS : [...foldByVehicleBbox].map(([bbox, fold]) => {
|
|
36444
36469
|
const td = trackedDetections.find((t) => t.bbox === bbox && t.matchedThisFrame !== false);
|
|
36445
36470
|
return td !== void 0 ? {
|
|
@@ -36643,6 +36668,7 @@ var FrameProcessor = class {
|
|
|
36643
36668
|
rawTrackedDetections: trackedDetections,
|
|
36644
36669
|
stationaryConfirmed: gate.confirmed,
|
|
36645
36670
|
stationaryWoken: gate.woken,
|
|
36671
|
+
stationaryContinued,
|
|
36646
36672
|
riderFolds
|
|
36647
36673
|
};
|
|
36648
36674
|
}
|
|
@@ -54989,6 +55015,31 @@ function thumbnailWouldShowParkedNotSubject(input) {
|
|
|
54989
55015
|
* dropped, against every entry that did NOT wake this frame. Woken entries are
|
|
54990
55016
|
* excluded so a departure still releases its object — a car that drives away is
|
|
54991
55017
|
* noticed on the frame its second read lands, exactly as before.
|
|
55018
|
+
*
|
|
55019
|
+
* ## A weak hold may CONTINUE a track; only a strong read is the object (D410)
|
|
55020
|
+
*
|
|
55021
|
+
* D275 predicted that a moving vehicle overlapping a parked one "loses a frame
|
|
55022
|
+
* or two while it passes" and coasts through on `maxAge`. Measured on device
|
|
55023
|
+
* 617 on 2026-09-08 it lost the whole pass: the parked cars sit at the frame
|
|
55024
|
+
* edge, so a car driving across their front is held on every frame from the
|
|
55025
|
+
* first overlap to the moment it leaves the frame, and the tracker — which had
|
|
55026
|
+
* followed it for 5–10 frames — coasts `maxMissedMs` on nothing and drops it.
|
|
55027
|
+
* Four operator-marked tracks, 1.7–3.5 s old, died on exactly that geometry;
|
|
55028
|
+
* the sweep for the window reported `reach: 0`, so the hold was pass 1's: the
|
|
55029
|
+
* mover occludes the parked car, the detector reports one vehicle box, and it
|
|
55030
|
+
* is the entry's best match.
|
|
55031
|
+
*
|
|
55032
|
+
* The hold is right — that box covers the parked spot and must not OPEN a
|
|
55033
|
+
* track, which is the whole of the operator's requirement — but it is not the
|
|
55034
|
+
* parked car: a strong read (IoU ≥ `suppressIou`) is the parked object unmoved,
|
|
55035
|
+
* and everything below it is a box that merely overlaps the spot (swallow,
|
|
55036
|
+
* jitter, departing). So `suppressedIndices` still names every box that may
|
|
55037
|
+
* not spawn, and `continuableIndices` names the weak subset the tracker may use
|
|
55038
|
+
* to CONTINUE a track it has already confirmed — through its strict
|
|
55039
|
+
* predicted-box association only, never a rescue or a resurrection. The reach
|
|
55040
|
+
* pass reports strength the same way. Nothing about confirmation, anchoring or
|
|
55041
|
+
* departure changes: a weak hold confirms and never re-anchors, exactly as
|
|
55042
|
+
* before.
|
|
54992
55043
|
*/
|
|
54993
55044
|
function partitionDetectionsAgainstRegistry(input) {
|
|
54994
55045
|
const { entries, detections, config, now } = input;
|
|
@@ -54996,6 +55047,7 @@ function partitionDetectionsAgainstRegistry(input) {
|
|
|
54996
55047
|
const departure = input.departure ?? DEFAULT_DEPARTURE_CONFIG;
|
|
54997
55048
|
const warmUp = input.warmUp ?? false;
|
|
54998
55049
|
const suppressed = /* @__PURE__ */ new Set();
|
|
55050
|
+
const continuable = /* @__PURE__ */ new Set();
|
|
54999
55051
|
const confirmed = [];
|
|
55000
55052
|
const woken = [];
|
|
55001
55053
|
const strikeChanges = [];
|
|
@@ -55035,6 +55087,7 @@ function partitionDetectionsAgainstRegistry(input) {
|
|
|
55035
55087
|
}
|
|
55036
55088
|
if (holdIdx >= 0) {
|
|
55037
55089
|
suppressed.add(holdIdx);
|
|
55090
|
+
if (!strong) continuable.add(holdIdx);
|
|
55038
55091
|
confirmed.push({
|
|
55039
55092
|
entryId: entry.id,
|
|
55040
55093
|
className: entry.className,
|
|
@@ -55074,6 +55127,7 @@ function partitionDetectionsAgainstRegistry(input) {
|
|
|
55074
55127
|
if (warmUp) {
|
|
55075
55128
|
warmUpDepartureReads += 1;
|
|
55076
55129
|
suppressed.add(bestIdx);
|
|
55130
|
+
continuable.add(bestIdx);
|
|
55077
55131
|
continue;
|
|
55078
55132
|
}
|
|
55079
55133
|
if (strike === void 0) {
|
|
@@ -55086,6 +55140,7 @@ function partitionDetectionsAgainstRegistry(input) {
|
|
|
55086
55140
|
reason: "armed"
|
|
55087
55141
|
});
|
|
55088
55142
|
suppressed.add(bestIdx);
|
|
55143
|
+
continuable.add(bestIdx);
|
|
55089
55144
|
continue;
|
|
55090
55145
|
}
|
|
55091
55146
|
if (strikeAgeMs >= departure.confirmMinGapMs) {
|
|
@@ -55106,6 +55161,7 @@ function partitionDetectionsAgainstRegistry(input) {
|
|
|
55106
55161
|
reason: "held"
|
|
55107
55162
|
});
|
|
55108
55163
|
suppressed.add(bestIdx);
|
|
55164
|
+
continuable.add(bestIdx);
|
|
55109
55165
|
}
|
|
55110
55166
|
const wokenIds = woken.length === 0 ? EMPTY_IDS : new Set(woken.map((w) => w.entryId));
|
|
55111
55167
|
let reachSuppressedCount = 0;
|
|
@@ -55116,14 +55172,17 @@ function partitionDetectionsAgainstRegistry(input) {
|
|
|
55116
55172
|
for (let ei = 0; ei < entries.length; ei++) {
|
|
55117
55173
|
const entry = entries[ei];
|
|
55118
55174
|
if (entryClasses[ei] !== detClass || wokenIds.has(entry.id)) continue;
|
|
55119
|
-
|
|
55175
|
+
const held = parkedEntryHoldsDetection(entry, det.bbox, config);
|
|
55176
|
+
if (!held.holds) continue;
|
|
55120
55177
|
suppressed.add(di);
|
|
55178
|
+
if (!held.strong) continuable.add(di);
|
|
55121
55179
|
reachSuppressedCount += 1;
|
|
55122
55180
|
break;
|
|
55123
55181
|
}
|
|
55124
55182
|
}
|
|
55125
55183
|
return {
|
|
55126
55184
|
suppressedIndices: suppressed,
|
|
55185
|
+
continuableIndices: continuable,
|
|
55127
55186
|
confirmed,
|
|
55128
55187
|
woken,
|
|
55129
55188
|
strikeChanges,
|
|
@@ -56747,6 +56806,10 @@ var StationaryObjectRegistry = class {
|
|
|
56747
56806
|
*/
|
|
56748
56807
|
suppressedSinceSweep = /* @__PURE__ */ new Map();
|
|
56749
56808
|
reachSuppressedSinceSweep = /* @__PURE__ */ new Map();
|
|
56809
|
+
/** Weak holds handed to the tracker as continuable (D410), per device. */
|
|
56810
|
+
continuableSinceSweep = /* @__PURE__ */ new Map();
|
|
56811
|
+
/** Of those, the ones the tracker reports actually continued a track. */
|
|
56812
|
+
continuedSinceSweep = /* @__PURE__ */ new Map();
|
|
56750
56813
|
constructor(deps) {
|
|
56751
56814
|
this.logger = deps.logger;
|
|
56752
56815
|
this.ledger = new DurableLedger({
|
|
@@ -56830,6 +56893,7 @@ var StationaryObjectRegistry = class {
|
|
|
56830
56893
|
const entries = this.list(deviceId);
|
|
56831
56894
|
if (entries.length === 0) return {
|
|
56832
56895
|
suppressedIndices: /* @__PURE__ */ new Set(),
|
|
56896
|
+
continuableIndices: /* @__PURE__ */ new Set(),
|
|
56833
56897
|
confirmed: [],
|
|
56834
56898
|
woken: [],
|
|
56835
56899
|
reachSuppressedCount: 0
|
|
@@ -56850,14 +56914,23 @@ var StationaryObjectRegistry = class {
|
|
|
56850
56914
|
if (result.suppressedIndices.size > 0) {
|
|
56851
56915
|
this.suppressedSinceSweep.set(deviceId, (this.suppressedSinceSweep.get(deviceId) ?? 0) + result.suppressedIndices.size);
|
|
56852
56916
|
if (result.reachSuppressedCount > 0) this.reachSuppressedSinceSweep.set(deviceId, (this.reachSuppressedSinceSweep.get(deviceId) ?? 0) + result.reachSuppressedCount);
|
|
56917
|
+
if (result.continuableIndices.size > 0) this.continuableSinceSweep.set(deviceId, (this.continuableSinceSweep.get(deviceId) ?? 0) + result.continuableIndices.size);
|
|
56853
56918
|
}
|
|
56854
56919
|
return {
|
|
56855
56920
|
suppressedIndices: result.suppressedIndices,
|
|
56921
|
+
continuableIndices: result.continuableIndices,
|
|
56856
56922
|
confirmed: result.confirmed,
|
|
56857
56923
|
woken: result.woken,
|
|
56858
56924
|
reachSuppressedCount: result.reachSuppressedCount
|
|
56859
56925
|
};
|
|
56860
56926
|
}
|
|
56927
|
+
/** The tracker's answer to {@link StationaryFrameFilterResult.continuableIndices}:
|
|
56928
|
+
* how many of this frame's weak holds continued a confirmed track (D410).
|
|
56929
|
+
* Counted here so the sweep line can report it beside `continuable`. */
|
|
56930
|
+
noteContinued(deviceId, count) {
|
|
56931
|
+
if (count <= 0) return;
|
|
56932
|
+
this.continuedSinceSweep.set(deviceId, (this.continuedSinceSweep.get(deviceId) ?? 0) + count);
|
|
56933
|
+
}
|
|
56861
56934
|
/** Pending departure strikes for a device — the read-only diagnostic's whole
|
|
56862
56935
|
* reason to exist. Ordered oldest first so "what has been waiting" reads
|
|
56863
56936
|
* straight off the top. */
|
|
@@ -56996,6 +57069,8 @@ var StationaryObjectRegistry = class {
|
|
|
56996
57069
|
absorbed,
|
|
56997
57070
|
suppressed,
|
|
56998
57071
|
reach: this.reachSuppressedSinceSweep.get(deviceId) ?? 0,
|
|
57072
|
+
continuable: this.continuableSinceSweep.get(deviceId) ?? 0,
|
|
57073
|
+
continued: this.continuedSinceSweep.get(deviceId) ?? 0,
|
|
56999
57074
|
entries: this.count(deviceId)
|
|
57000
57075
|
}
|
|
57001
57076
|
});
|
|
@@ -57003,6 +57078,8 @@ var StationaryObjectRegistry = class {
|
|
|
57003
57078
|
this.absorbedSinceSweep.clear();
|
|
57004
57079
|
this.suppressedSinceSweep.clear();
|
|
57005
57080
|
this.reachSuppressedSinceSweep.clear();
|
|
57081
|
+
this.continuableSinceSweep.clear();
|
|
57082
|
+
this.continuedSinceSweep.clear();
|
|
57006
57083
|
for (const [deviceId, counters] of this.strikeCountersByDevice) this.logger.info("stationary departure strikes", {
|
|
57007
57084
|
tags: { deviceId },
|
|
57008
57085
|
meta: {
|
|
@@ -73573,6 +73650,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_dist.B
|
|
|
73573
73650
|
woken: result.stationaryWoken,
|
|
73574
73651
|
timestamp: result.timestamp
|
|
73575
73652
|
});
|
|
73653
|
+
if (this.stationaryRegistry && result.stationaryContinued > 0) this.stationaryRegistry.noteContinued(deviceId, result.stationaryContinued);
|
|
73576
73654
|
const stationaryViews = this.stationaryRegistry?.listViews(deviceId) ?? [];
|
|
73577
73655
|
const stationaryAsTracked = stationaryViews.map((v) => ({
|
|
73578
73656
|
trackId: `stationary:${v.id}`,
|
|
@@ -76943,6 +77021,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_dist.B
|
|
|
76943
77021
|
const s = this.stationarySettingsFromCache(deviceId);
|
|
76944
77022
|
if (!s.enabled) return {
|
|
76945
77023
|
suppressedIndices: /* @__PURE__ */ new Set(),
|
|
77024
|
+
continuableIndices: /* @__PURE__ */ new Set(),
|
|
76946
77025
|
confirmed: [],
|
|
76947
77026
|
woken: []
|
|
76948
77027
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as VISIT_MERGE_GAP_MS, $t as object, A as NcRulePatchSchema, Bt as CamProfileSchema, C as NC_ALARM_SYSTEM_EVENT_KINDS, D as NC_TAXONOMY, Dt as readDeviceStateFrom, Et as plateGalleryCapability, F as NcSnoozeSchema, Ft as vectorDimFromBase64, G as SCENE_DEFAULT_UNCOVERED_POLICY, Gt as nodePin, H as RetrainStatusSchema, Ht as createEvent, I as NcSnoozeSuppressedSchema, It as videoclipsCapability, J as TIMELAPSE_DENSE_FLOOR_SEC, Jt as array, K as SCENE_DIVERGED, Kt as sleep$1, L as NcSystemEventKindSchema, Lt as zoneAnalyticsCapability, M as NcRuleTargetSchema, Mt as storageOccupancyCapability, N as NcScheduleSchema, Nt as subKindsOf, O as NcConditionDescriptorSchema, Ot as readTimelapseGeneratedAt, P as NcSnoozeInputSchema, Pt as systemEventFilterApplies, Q as TrackSourceSchema, Qt as number, R as NcTaxonomySchema, Rt as errMsg$1, S as MediaFileKindEnum, St as notificationRulesCapability, T as NC_DEFAULT_SNOOZE_MINUTES, Tt as pipelineAnalyticsCapability, Ut as hydrateSchema, V as RECORDING_EXPORT_MAX_READ_BYTES, Vt as DeviceType, W as SCENE_DEFAULT_ANCHOR_THRESHOLD, Wt as isDeviceScopedCap, X as TimelapseRulePatchSchema, Xt as discriminatedUnion, Y as TimelapseRuleInputSchema, Yt as boolean, Z as TimelapseRuleSchema, Zt as literal, _ as LabelAttributionSchema, _t as isDetectionMacroClass, a as CLUSTER_MODEL_SCOPED_STEPS, at as buildEventKindDescriptor, b as MAX_BIRTH_DECISION_RECORDS, bt as kebabToCamel, ct as defineCustomActions, dt as encodeVectorBase64, en as partialRecord, et as addonWidgetsSourceCapability, f as DeclaredDevices, ft as evaluateSensorEdge, g as FailureCounters, h as FULL_IMAGE_BBOX, ht as failureContributionCapability, i as BirthDecisionRecordSchema, in as EventCategory, it as audioModeOf, j as NcRuleSchema, jt as sceneMonitorCapability, k as NcRuleInputSchema, kt as resolveLocationMode, lt as deriveRecordingMode, m as EVENT_PAD_MS, mt as faceGalleryCapability, n as ArchivedDebugNoteSchema, nn as string, nt as assertTimelapseCadences, o as COCO_TO_MACRO, ot as cosineSimilarity$1, p as EVENT_KIND_BY_CAP, pt as evictionPolicyOfLocation, q as SceneMonitorSchema, qt as _enum, r as BaseDevice, rn as unknown, rt as audioMetricsCapability, s as DEFAULT_EVENT_COLOR, st as customAction, t as AUDIO_MACRO_LABELS, tn as record, tt as alarmPanelCapability, u as DETECTION_MACRO_CLASSES, v as MACRO_LABELS, vt as isScheduleActive, w as NC_CONDITION_CATALOG, wt as pickClusterStepModels, xt as mayWriteToLocation, y as MAX_ARCHIVED_DEBUG_NOTES, yt as isSourceCap, z as OpsLogEntrySchema, zt as BaseAddon } from "../dist-
|
|
1
|
+
import { $ as VISIT_MERGE_GAP_MS, $t as object, A as NcRulePatchSchema, Bt as CamProfileSchema, C as NC_ALARM_SYSTEM_EVENT_KINDS, D as NC_TAXONOMY, Dt as readDeviceStateFrom, Et as plateGalleryCapability, F as NcSnoozeSchema, Ft as vectorDimFromBase64, G as SCENE_DEFAULT_UNCOVERED_POLICY, Gt as nodePin, H as RetrainStatusSchema, Ht as createEvent, I as NcSnoozeSuppressedSchema, It as videoclipsCapability, J as TIMELAPSE_DENSE_FLOOR_SEC, Jt as array, K as SCENE_DIVERGED, Kt as sleep$1, L as NcSystemEventKindSchema, Lt as zoneAnalyticsCapability, M as NcRuleTargetSchema, Mt as storageOccupancyCapability, N as NcScheduleSchema, Nt as subKindsOf, O as NcConditionDescriptorSchema, Ot as readTimelapseGeneratedAt, P as NcSnoozeInputSchema, Pt as systemEventFilterApplies, Q as TrackSourceSchema, Qt as number, R as NcTaxonomySchema, Rt as errMsg$1, S as MediaFileKindEnum, St as notificationRulesCapability, T as NC_DEFAULT_SNOOZE_MINUTES, Tt as pipelineAnalyticsCapability, Ut as hydrateSchema, V as RECORDING_EXPORT_MAX_READ_BYTES, Vt as DeviceType, W as SCENE_DEFAULT_ANCHOR_THRESHOLD, Wt as isDeviceScopedCap, X as TimelapseRulePatchSchema, Xt as discriminatedUnion, Y as TimelapseRuleInputSchema, Yt as boolean, Z as TimelapseRuleSchema, Zt as literal, _ as LabelAttributionSchema, _t as isDetectionMacroClass, a as CLUSTER_MODEL_SCOPED_STEPS, at as buildEventKindDescriptor, b as MAX_BIRTH_DECISION_RECORDS, bt as kebabToCamel, ct as defineCustomActions, dt as encodeVectorBase64, en as partialRecord, et as addonWidgetsSourceCapability, f as DeclaredDevices, ft as evaluateSensorEdge, g as FailureCounters, h as FULL_IMAGE_BBOX, ht as failureContributionCapability, i as BirthDecisionRecordSchema, in as EventCategory, it as audioModeOf, j as NcRuleSchema, jt as sceneMonitorCapability, k as NcRuleInputSchema, kt as resolveLocationMode, lt as deriveRecordingMode, m as EVENT_PAD_MS, mt as faceGalleryCapability, n as ArchivedDebugNoteSchema, nn as string, nt as assertTimelapseCadences, o as COCO_TO_MACRO, ot as cosineSimilarity$1, p as EVENT_KIND_BY_CAP, pt as evictionPolicyOfLocation, q as SceneMonitorSchema, qt as _enum, r as BaseDevice, rn as unknown, rt as audioMetricsCapability, s as DEFAULT_EVENT_COLOR, st as customAction, t as AUDIO_MACRO_LABELS, tn as record, tt as alarmPanelCapability, u as DETECTION_MACRO_CLASSES, v as MACRO_LABELS, vt as isScheduleActive, w as NC_CONDITION_CATALOG, wt as pickClusterStepModels, xt as mayWriteToLocation, y as MAX_ARCHIVED_DEBUG_NOTES, yt as isSourceCap, z as OpsLogEntrySchema, zt as BaseAddon } from "../dist-CT2SouNJ.mjs";
|
|
2
2
|
import { t as __exportAll } from "../embedding-encoder/index.mjs";
|
|
3
3
|
import * as fs from "node:fs";
|
|
4
4
|
import { promises } from "node:fs";
|
|
@@ -34836,6 +34836,9 @@ var DEFAULT_TRACKER_CONFIG = {
|
|
|
34836
34836
|
var PERSON_CLASS = "person";
|
|
34837
34837
|
var ANIMAL_CLASS = "animal";
|
|
34838
34838
|
var MAX_PATH_LENGTH = 300;
|
|
34839
|
+
/** No stationary-held detections on this frame — the default for every caller
|
|
34840
|
+
* that has no gate (replay, tests, the non-pipeline planes). */
|
|
34841
|
+
var EMPTY_INDEX_SET = /* @__PURE__ */ new Set();
|
|
34839
34842
|
function clamp$1(value, min, max) {
|
|
34840
34843
|
return Math.max(min, Math.min(max, value));
|
|
34841
34844
|
}
|
|
@@ -35455,13 +35458,15 @@ var SortTracker = class SortTracker {
|
|
|
35455
35458
|
* gates) so the two-tier ByteTrack association stays a single implementation.
|
|
35456
35459
|
* Mutates `used` / `matchedTracks` / `matched` in place.
|
|
35457
35460
|
*/
|
|
35458
|
-
greedyAssociate(detections, candidateIdxs, iouThreshold, timestamp, used, matchedTracks, matched) {
|
|
35461
|
+
greedyAssociate(detections, candidateIdxs, iouThreshold, timestamp, used, matchedTracks, matched, continuationOnly) {
|
|
35459
35462
|
const pairs = [];
|
|
35460
35463
|
for (const track of this.tracks) {
|
|
35461
35464
|
if (matchedTracks.has(track)) continue;
|
|
35462
35465
|
const pbox = this.predicted(track, timestamp);
|
|
35466
|
+
const confirmed = this.isConfirmedForEmit(track);
|
|
35463
35467
|
for (const di of candidateIdxs) {
|
|
35464
35468
|
if (used.has(di)) continue;
|
|
35469
|
+
if (!confirmed && continuationOnly.has(di)) continue;
|
|
35465
35470
|
const det = detections[di];
|
|
35466
35471
|
if (!this.associable(track.class, det)) continue;
|
|
35467
35472
|
const score = iou$3(pbox, det.bbox);
|
|
@@ -35482,6 +35487,7 @@ var SortTracker = class SortTracker {
|
|
|
35482
35487
|
}
|
|
35483
35488
|
update(detections, timestamp, frameContext) {
|
|
35484
35489
|
const frameArea = frameContext ? frameContext.frameWidth * frameContext.frameHeight : 0;
|
|
35490
|
+
const continuationOnly = frameContext?.continuationOnly ?? EMPTY_INDEX_SET;
|
|
35485
35491
|
const resurrectedScene = /* @__PURE__ */ new Map();
|
|
35486
35492
|
if (this.config.maxTrackLifetimeMs > 0) {
|
|
35487
35493
|
const alive = [];
|
|
@@ -35518,12 +35524,12 @@ var SortTracker = class SortTracker {
|
|
|
35518
35524
|
for (let di = 0; di < detections.length; di++) if (this.config.byteTrackEnabled && detections[di].score < this.config.byteTrackHighThreshold) lowIdxs.push(di);
|
|
35519
35525
|
else highIdxs.push(di);
|
|
35520
35526
|
const lowSet = new Set(lowIdxs);
|
|
35521
|
-
this.greedyAssociate(detections, highIdxs, this.config.iouThreshold, timestamp, used, matchedTracks, matched);
|
|
35527
|
+
this.greedyAssociate(detections, highIdxs, this.config.iouThreshold, timestamp, used, matchedTracks, matched, continuationOnly);
|
|
35522
35528
|
const rescuePairs = [];
|
|
35523
35529
|
for (const track of this.tracks) {
|
|
35524
35530
|
if (matchedTracks.has(track)) continue;
|
|
35525
35531
|
for (let di = 0; di < detections.length; di++) {
|
|
35526
|
-
if (used.has(di) || lowSet.has(di)) continue;
|
|
35532
|
+
if (used.has(di) || lowSet.has(di) || continuationOnly.has(di)) continue;
|
|
35527
35533
|
const det = detections[di];
|
|
35528
35534
|
const gate = this.looseMatch(track, det, timestamp);
|
|
35529
35535
|
if (gate === null) continue;
|
|
@@ -35545,7 +35551,7 @@ var SortTracker = class SortTracker {
|
|
|
35545
35551
|
used.add(pair.detIdx);
|
|
35546
35552
|
this.reportBind("rescue", pair.gate, pair.track, det, timestamp);
|
|
35547
35553
|
}
|
|
35548
|
-
if (this.config.byteTrackEnabled && lowIdxs.length > 0) this.greedyAssociate(detections, lowIdxs, this.config.byteTrackLowIouThreshold, timestamp, used, matchedTracks, matched);
|
|
35554
|
+
if (this.config.byteTrackEnabled && lowIdxs.length > 0) this.greedyAssociate(detections, lowIdxs, this.config.byteTrackLowIouThreshold, timestamp, used, matchedTracks, matched, continuationOnly);
|
|
35549
35555
|
for (const [track, det] of matched) {
|
|
35550
35556
|
if (track.class !== det.class) this.reportRefusal("cross-class-absorbed", det, { against: track });
|
|
35551
35557
|
const prevCenter = bboxCentroid({
|
|
@@ -35601,7 +35607,7 @@ var SortTracker = class SortTracker {
|
|
|
35601
35607
|
} else surviving.push(track);
|
|
35602
35608
|
}
|
|
35603
35609
|
for (let di = 0; di < detections.length; di++) {
|
|
35604
|
-
if (used.has(di)) continue;
|
|
35610
|
+
if (used.has(di) || continuationOnly.has(di)) continue;
|
|
35605
35611
|
const det = detections[di];
|
|
35606
35612
|
let best;
|
|
35607
35613
|
let bestScore = -1;
|
|
@@ -35669,6 +35675,11 @@ var SortTracker = class SortTracker {
|
|
|
35669
35675
|
});
|
|
35670
35676
|
for (const di of unmatchedIdx) {
|
|
35671
35677
|
const det = detections[di];
|
|
35678
|
+
if (continuationOnly.has(di)) {
|
|
35679
|
+
this.reportRefusal("stationary-hold", det);
|
|
35680
|
+
used.add(di);
|
|
35681
|
+
continue;
|
|
35682
|
+
}
|
|
35672
35683
|
if (!this.meetsClassScoreFloor(det)) {
|
|
35673
35684
|
this.reportRefusal("score-floor", det, {
|
|
35674
35685
|
threshold: this.config.classMinScores[det.class] ?? 0,
|
|
@@ -36407,14 +36418,28 @@ var FrameProcessor = class {
|
|
|
36407
36418
|
timestamp
|
|
36408
36419
|
}) : {
|
|
36409
36420
|
suppressedIndices: /* @__PURE__ */ new Set(),
|
|
36421
|
+
continuableIndices: /* @__PURE__ */ new Set(),
|
|
36410
36422
|
confirmed: [],
|
|
36411
36423
|
woken: []
|
|
36412
36424
|
};
|
|
36413
|
-
const trackerInput =
|
|
36425
|
+
const trackerInput = [];
|
|
36426
|
+
const continuationOnly = /* @__PURE__ */ new Set();
|
|
36427
|
+
const continuableBoxes = /* @__PURE__ */ new Set();
|
|
36428
|
+
for (let i = 0; i < filteredDetections.length; i++) {
|
|
36429
|
+
const det = filteredDetections[i];
|
|
36430
|
+
if (gate.suppressedIndices.has(i)) {
|
|
36431
|
+
if (!gate.continuableIndices.has(i)) continue;
|
|
36432
|
+
continuationOnly.add(trackerInput.length);
|
|
36433
|
+
continuableBoxes.add(det.bbox);
|
|
36434
|
+
}
|
|
36435
|
+
trackerInput.push(det);
|
|
36436
|
+
}
|
|
36414
36437
|
const trackedDetections = this.tracker.update(trackerInput, timestamp, {
|
|
36415
36438
|
frameWidth,
|
|
36416
|
-
frameHeight
|
|
36439
|
+
frameHeight,
|
|
36440
|
+
continuationOnly
|
|
36417
36441
|
});
|
|
36442
|
+
const stationaryContinued = continuableBoxes.size === 0 ? 0 : trackedDetections.filter((t) => t.matchedThisFrame !== false && continuableBoxes.has(t.bbox)).length;
|
|
36418
36443
|
const riderFolds = foldByVehicleBbox.size === 0 ? EMPTY_RIDER_FOLDS : [...foldByVehicleBbox].map(([bbox, fold]) => {
|
|
36419
36444
|
const td = trackedDetections.find((t) => t.bbox === bbox && t.matchedThisFrame !== false);
|
|
36420
36445
|
return td !== void 0 ? {
|
|
@@ -36618,6 +36643,7 @@ var FrameProcessor = class {
|
|
|
36618
36643
|
rawTrackedDetections: trackedDetections,
|
|
36619
36644
|
stationaryConfirmed: gate.confirmed,
|
|
36620
36645
|
stationaryWoken: gate.woken,
|
|
36646
|
+
stationaryContinued,
|
|
36621
36647
|
riderFolds
|
|
36622
36648
|
};
|
|
36623
36649
|
}
|
|
@@ -54915,6 +54941,31 @@ function thumbnailWouldShowParkedNotSubject(input) {
|
|
|
54915
54941
|
* dropped, against every entry that did NOT wake this frame. Woken entries are
|
|
54916
54942
|
* excluded so a departure still releases its object — a car that drives away is
|
|
54917
54943
|
* noticed on the frame its second read lands, exactly as before.
|
|
54944
|
+
*
|
|
54945
|
+
* ## A weak hold may CONTINUE a track; only a strong read is the object (D410)
|
|
54946
|
+
*
|
|
54947
|
+
* D275 predicted that a moving vehicle overlapping a parked one "loses a frame
|
|
54948
|
+
* or two while it passes" and coasts through on `maxAge`. Measured on device
|
|
54949
|
+
* 617 on 2026-09-08 it lost the whole pass: the parked cars sit at the frame
|
|
54950
|
+
* edge, so a car driving across their front is held on every frame from the
|
|
54951
|
+
* first overlap to the moment it leaves the frame, and the tracker — which had
|
|
54952
|
+
* followed it for 5–10 frames — coasts `maxMissedMs` on nothing and drops it.
|
|
54953
|
+
* Four operator-marked tracks, 1.7–3.5 s old, died on exactly that geometry;
|
|
54954
|
+
* the sweep for the window reported `reach: 0`, so the hold was pass 1's: the
|
|
54955
|
+
* mover occludes the parked car, the detector reports one vehicle box, and it
|
|
54956
|
+
* is the entry's best match.
|
|
54957
|
+
*
|
|
54958
|
+
* The hold is right — that box covers the parked spot and must not OPEN a
|
|
54959
|
+
* track, which is the whole of the operator's requirement — but it is not the
|
|
54960
|
+
* parked car: a strong read (IoU ≥ `suppressIou`) is the parked object unmoved,
|
|
54961
|
+
* and everything below it is a box that merely overlaps the spot (swallow,
|
|
54962
|
+
* jitter, departing). So `suppressedIndices` still names every box that may
|
|
54963
|
+
* not spawn, and `continuableIndices` names the weak subset the tracker may use
|
|
54964
|
+
* to CONTINUE a track it has already confirmed — through its strict
|
|
54965
|
+
* predicted-box association only, never a rescue or a resurrection. The reach
|
|
54966
|
+
* pass reports strength the same way. Nothing about confirmation, anchoring or
|
|
54967
|
+
* departure changes: a weak hold confirms and never re-anchors, exactly as
|
|
54968
|
+
* before.
|
|
54918
54969
|
*/
|
|
54919
54970
|
function partitionDetectionsAgainstRegistry(input) {
|
|
54920
54971
|
const { entries, detections, config, now } = input;
|
|
@@ -54922,6 +54973,7 @@ function partitionDetectionsAgainstRegistry(input) {
|
|
|
54922
54973
|
const departure = input.departure ?? DEFAULT_DEPARTURE_CONFIG;
|
|
54923
54974
|
const warmUp = input.warmUp ?? false;
|
|
54924
54975
|
const suppressed = /* @__PURE__ */ new Set();
|
|
54976
|
+
const continuable = /* @__PURE__ */ new Set();
|
|
54925
54977
|
const confirmed = [];
|
|
54926
54978
|
const woken = [];
|
|
54927
54979
|
const strikeChanges = [];
|
|
@@ -54961,6 +55013,7 @@ function partitionDetectionsAgainstRegistry(input) {
|
|
|
54961
55013
|
}
|
|
54962
55014
|
if (holdIdx >= 0) {
|
|
54963
55015
|
suppressed.add(holdIdx);
|
|
55016
|
+
if (!strong) continuable.add(holdIdx);
|
|
54964
55017
|
confirmed.push({
|
|
54965
55018
|
entryId: entry.id,
|
|
54966
55019
|
className: entry.className,
|
|
@@ -55000,6 +55053,7 @@ function partitionDetectionsAgainstRegistry(input) {
|
|
|
55000
55053
|
if (warmUp) {
|
|
55001
55054
|
warmUpDepartureReads += 1;
|
|
55002
55055
|
suppressed.add(bestIdx);
|
|
55056
|
+
continuable.add(bestIdx);
|
|
55003
55057
|
continue;
|
|
55004
55058
|
}
|
|
55005
55059
|
if (strike === void 0) {
|
|
@@ -55012,6 +55066,7 @@ function partitionDetectionsAgainstRegistry(input) {
|
|
|
55012
55066
|
reason: "armed"
|
|
55013
55067
|
});
|
|
55014
55068
|
suppressed.add(bestIdx);
|
|
55069
|
+
continuable.add(bestIdx);
|
|
55015
55070
|
continue;
|
|
55016
55071
|
}
|
|
55017
55072
|
if (strikeAgeMs >= departure.confirmMinGapMs) {
|
|
@@ -55032,6 +55087,7 @@ function partitionDetectionsAgainstRegistry(input) {
|
|
|
55032
55087
|
reason: "held"
|
|
55033
55088
|
});
|
|
55034
55089
|
suppressed.add(bestIdx);
|
|
55090
|
+
continuable.add(bestIdx);
|
|
55035
55091
|
}
|
|
55036
55092
|
const wokenIds = woken.length === 0 ? EMPTY_IDS : new Set(woken.map((w) => w.entryId));
|
|
55037
55093
|
let reachSuppressedCount = 0;
|
|
@@ -55042,14 +55098,17 @@ function partitionDetectionsAgainstRegistry(input) {
|
|
|
55042
55098
|
for (let ei = 0; ei < entries.length; ei++) {
|
|
55043
55099
|
const entry = entries[ei];
|
|
55044
55100
|
if (entryClasses[ei] !== detClass || wokenIds.has(entry.id)) continue;
|
|
55045
|
-
|
|
55101
|
+
const held = parkedEntryHoldsDetection(entry, det.bbox, config);
|
|
55102
|
+
if (!held.holds) continue;
|
|
55046
55103
|
suppressed.add(di);
|
|
55104
|
+
if (!held.strong) continuable.add(di);
|
|
55047
55105
|
reachSuppressedCount += 1;
|
|
55048
55106
|
break;
|
|
55049
55107
|
}
|
|
55050
55108
|
}
|
|
55051
55109
|
return {
|
|
55052
55110
|
suppressedIndices: suppressed,
|
|
55111
|
+
continuableIndices: continuable,
|
|
55053
55112
|
confirmed,
|
|
55054
55113
|
woken,
|
|
55055
55114
|
strikeChanges,
|
|
@@ -56673,6 +56732,10 @@ var StationaryObjectRegistry = class {
|
|
|
56673
56732
|
*/
|
|
56674
56733
|
suppressedSinceSweep = /* @__PURE__ */ new Map();
|
|
56675
56734
|
reachSuppressedSinceSweep = /* @__PURE__ */ new Map();
|
|
56735
|
+
/** Weak holds handed to the tracker as continuable (D410), per device. */
|
|
56736
|
+
continuableSinceSweep = /* @__PURE__ */ new Map();
|
|
56737
|
+
/** Of those, the ones the tracker reports actually continued a track. */
|
|
56738
|
+
continuedSinceSweep = /* @__PURE__ */ new Map();
|
|
56676
56739
|
constructor(deps) {
|
|
56677
56740
|
this.logger = deps.logger;
|
|
56678
56741
|
this.ledger = new DurableLedger({
|
|
@@ -56756,6 +56819,7 @@ var StationaryObjectRegistry = class {
|
|
|
56756
56819
|
const entries = this.list(deviceId);
|
|
56757
56820
|
if (entries.length === 0) return {
|
|
56758
56821
|
suppressedIndices: /* @__PURE__ */ new Set(),
|
|
56822
|
+
continuableIndices: /* @__PURE__ */ new Set(),
|
|
56759
56823
|
confirmed: [],
|
|
56760
56824
|
woken: [],
|
|
56761
56825
|
reachSuppressedCount: 0
|
|
@@ -56776,14 +56840,23 @@ var StationaryObjectRegistry = class {
|
|
|
56776
56840
|
if (result.suppressedIndices.size > 0) {
|
|
56777
56841
|
this.suppressedSinceSweep.set(deviceId, (this.suppressedSinceSweep.get(deviceId) ?? 0) + result.suppressedIndices.size);
|
|
56778
56842
|
if (result.reachSuppressedCount > 0) this.reachSuppressedSinceSweep.set(deviceId, (this.reachSuppressedSinceSweep.get(deviceId) ?? 0) + result.reachSuppressedCount);
|
|
56843
|
+
if (result.continuableIndices.size > 0) this.continuableSinceSweep.set(deviceId, (this.continuableSinceSweep.get(deviceId) ?? 0) + result.continuableIndices.size);
|
|
56779
56844
|
}
|
|
56780
56845
|
return {
|
|
56781
56846
|
suppressedIndices: result.suppressedIndices,
|
|
56847
|
+
continuableIndices: result.continuableIndices,
|
|
56782
56848
|
confirmed: result.confirmed,
|
|
56783
56849
|
woken: result.woken,
|
|
56784
56850
|
reachSuppressedCount: result.reachSuppressedCount
|
|
56785
56851
|
};
|
|
56786
56852
|
}
|
|
56853
|
+
/** The tracker's answer to {@link StationaryFrameFilterResult.continuableIndices}:
|
|
56854
|
+
* how many of this frame's weak holds continued a confirmed track (D410).
|
|
56855
|
+
* Counted here so the sweep line can report it beside `continuable`. */
|
|
56856
|
+
noteContinued(deviceId, count) {
|
|
56857
|
+
if (count <= 0) return;
|
|
56858
|
+
this.continuedSinceSweep.set(deviceId, (this.continuedSinceSweep.get(deviceId) ?? 0) + count);
|
|
56859
|
+
}
|
|
56787
56860
|
/** Pending departure strikes for a device — the read-only diagnostic's whole
|
|
56788
56861
|
* reason to exist. Ordered oldest first so "what has been waiting" reads
|
|
56789
56862
|
* straight off the top. */
|
|
@@ -56922,6 +56995,8 @@ var StationaryObjectRegistry = class {
|
|
|
56922
56995
|
absorbed,
|
|
56923
56996
|
suppressed,
|
|
56924
56997
|
reach: this.reachSuppressedSinceSweep.get(deviceId) ?? 0,
|
|
56998
|
+
continuable: this.continuableSinceSweep.get(deviceId) ?? 0,
|
|
56999
|
+
continued: this.continuedSinceSweep.get(deviceId) ?? 0,
|
|
56925
57000
|
entries: this.count(deviceId)
|
|
56926
57001
|
}
|
|
56927
57002
|
});
|
|
@@ -56929,6 +57004,8 @@ var StationaryObjectRegistry = class {
|
|
|
56929
57004
|
this.absorbedSinceSweep.clear();
|
|
56930
57005
|
this.suppressedSinceSweep.clear();
|
|
56931
57006
|
this.reachSuppressedSinceSweep.clear();
|
|
57007
|
+
this.continuableSinceSweep.clear();
|
|
57008
|
+
this.continuedSinceSweep.clear();
|
|
56932
57009
|
for (const [deviceId, counters] of this.strikeCountersByDevice) this.logger.info("stationary departure strikes", {
|
|
56933
57010
|
tags: { deviceId },
|
|
56934
57011
|
meta: {
|
|
@@ -73499,6 +73576,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
73499
73576
|
woken: result.stationaryWoken,
|
|
73500
73577
|
timestamp: result.timestamp
|
|
73501
73578
|
});
|
|
73579
|
+
if (this.stationaryRegistry && result.stationaryContinued > 0) this.stationaryRegistry.noteContinued(deviceId, result.stationaryContinued);
|
|
73502
73580
|
const stationaryViews = this.stationaryRegistry?.listViews(deviceId) ?? [];
|
|
73503
73581
|
const stationaryAsTracked = stationaryViews.map((v) => ({
|
|
73504
73582
|
trackId: `stationary:${v.id}`,
|
|
@@ -76869,6 +76947,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
76869
76947
|
const s = this.stationarySettingsFromCache(deviceId);
|
|
76870
76948
|
if (!s.enabled) return {
|
|
76871
76949
|
suppressedIndices: /* @__PURE__ */ new Set(),
|
|
76950
|
+
continuableIndices: /* @__PURE__ */ new Set(),
|
|
76872
76951
|
confirmed: [],
|
|
76873
76952
|
woken: []
|
|
76874
76953
|
};
|
|
@@ -30,7 +30,7 @@ async function d(e) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
async function f() {
|
|
33
|
-
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-
|
|
33
|
+
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-CxVox7bu.mjs")).catch((e) => {
|
|
34
34
|
throw l = void 0, e;
|
|
35
35
|
}), l;
|
|
36
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-post-analysis",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.213",
|
|
4
4
|
"description": "Post-Analysis bundle — enrichment, embedding-encoder, pipeline-analytics. Multi-entry npm package shipping addons that consume pipeline output.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|