@camstack/addon-post-analysis 1.2.653 → 1.2.654

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.
Files changed (16) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/{clip-model-registry-BrazZJvr.mjs → clip-model-registry-BX6j2lnF.mjs} +997 -147
  3. package/dist/{clip-model-registry-Bz1uQvQ8.js → clip-model-registry-CFQBxtE2.js} +997 -147
  4. package/dist/embedding-encoder/index.js +1 -1
  5. package/dist/embedding-encoder/index.mjs +1 -1
  6. package/dist/pipeline-analytics/_stub.js +2 -2
  7. package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-D6DnF6Vk.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-Vag6rhEh.mjs} +2 -2
  8. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BUwWKfHC.mjs +26 -0
  9. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DXQUFp7P.mjs +26 -0
  10. package/dist/pipeline-analytics/{hostInit-DtrcY1yz.mjs → hostInit-CnvnZsmk.mjs} +2 -2
  11. package/dist/pipeline-analytics/index.js +164 -10
  12. package/dist/pipeline-analytics/index.mjs +164 -10
  13. package/dist/pipeline-analytics/remoteEntry.js +1 -1
  14. package/package.json +1 -1
  15. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BKMr4IqL.mjs +0 -26
  16. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CtNyIYsM.mjs +0 -26
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_clip_model_registry = require("../clip-model-registry-Bz1uQvQ8.js");
5
+ const require_clip_model_registry = require("../clip-model-registry-CFQBxtE2.js");
6
6
  let node_fs = require("node:fs");
7
7
  node_fs = require_clip_model_registry.__toESM(node_fs, 1);
8
8
  let node_path = require("node:path");
@@ -54723,6 +54723,12 @@ var FrameState = class {
54723
54723
  * per 5 minutes, not one per governor round (the wedge re-sights all
54724
54724
  * night; ~300 identical lines would bury the log it exists to serve). */
54725
54725
  packageOversizeLogAt = /* @__PURE__ */ new Map();
54726
+ /**
54727
+ * The newest frame the package path held per camera — the picture a parcel
54728
+ * promoted from a raw look is stored from (`package-still-capture.ts`). The
54729
+ * scene path concludes without a frame of its own, so it reads this.
54730
+ */
54731
+ packageLookFrames = /* @__PURE__ */ new Map();
54726
54732
  /** Reasons logged on the previous package look — episode helper for drops. */
54727
54733
  packageLookDropReasons = /* @__PURE__ */ new Map();
54728
54734
  };
@@ -59027,6 +59033,89 @@ function sweepOne(deps, deviceId) {
59027
59033
  if (outcome.departed.length > 0 || outcome.departedWithoutActivity.length > 0 || outcome.expired.length > 0) deps.onOutcome(deviceId, outcome, deps.now);
59028
59034
  }
59029
59035
  //#endregion
59036
+ //#region src/pipeline-analytics/pipeline/package/package-still-capture.ts
59037
+ /** A held look frame older than this is not the parcel's picture any more. */
59038
+ var PACKAGE_LOOK_FRAME_MAX_AGE_MS = 15e3;
59039
+ async function jpegOf(reply) {
59040
+ if (reply.tier === "ram-fullframe") return "preview-only";
59041
+ if (reply.jpegBytes !== void 0 && reply.jpegBytes.byteLength > 0) return reply.jpegBytes;
59042
+ if (reply.bytes !== void 0 && reply.bytes.length === reply.width * reply.height * 3) return encodeRgbCropToJpeg(reply.bytes, reply.width, reply.height);
59043
+ return "empty-frame";
59044
+ }
59045
+ /**
59046
+ * The entry carrying its still's `keyFrameMediaId`, or the entry unchanged when
59047
+ * it already had one or none could be stored (said, with the reason).
59048
+ */
59049
+ async function withParcelStill(input) {
59050
+ const { entry, logger } = input;
59051
+ if (entry.keyFrameMediaId !== void 0) return entry;
59052
+ const miss = (reason, detail) => {
59053
+ logger.warn("package still NOT stored — the delivery ships without a picture of the parcel", {
59054
+ tags: { deviceId: entry.deviceId },
59055
+ meta: {
59056
+ entryId: entry.id,
59057
+ reason,
59058
+ ...detail !== void 0 ? { error: detail } : {}
59059
+ }
59060
+ });
59061
+ return entry;
59062
+ };
59063
+ if (input.handle === null) return miss("no-frame-handle");
59064
+ if (input.writer === null) return miss("no-media-store");
59065
+ try {
59066
+ const reply = await input.query({
59067
+ handle: input.handle,
59068
+ bbox: {
59069
+ x: 0,
59070
+ y: 0,
59071
+ w: entry.frameWidth,
59072
+ h: entry.frameHeight
59073
+ },
59074
+ acceptJpegBytes: true,
59075
+ encodeJpeg: true,
59076
+ pin: require_clip_model_registry.nodePin(input.handle.nodeId)
59077
+ });
59078
+ if (reply === null) return miss("native-miss");
59079
+ const jpeg = await jpegOf(reply);
59080
+ if (typeof jpeg === "string") return miss(jpeg);
59081
+ const keyFrameMediaId = await input.writer.putReplacing({
59082
+ deviceId: entry.deviceId,
59083
+ ownerKind: "track",
59084
+ ownerId: entry.id,
59085
+ kind: "keyFrame",
59086
+ timestamp: input.timestamp,
59087
+ data: Buffer.from(jpeg),
59088
+ subjectBox: {
59089
+ x: entry.bbox.x,
59090
+ y: entry.bbox.y,
59091
+ w: entry.bbox.w,
59092
+ h: entry.bbox.h,
59093
+ frameWidth: entry.frameWidth,
59094
+ frameHeight: entry.frameHeight
59095
+ }
59096
+ });
59097
+ return {
59098
+ ...entry,
59099
+ keyFrameMediaId
59100
+ };
59101
+ } catch (err) {
59102
+ return miss("write-failed", require_clip_model_registry.errMsg(err));
59103
+ }
59104
+ }
59105
+ /**
59106
+ * One promotion, in the order that matters: the still is stored FIRST, then the
59107
+ * detector emits `delivered` — the notification centre reads the still when the
59108
+ * event arrives, so a picture written after it is a picture nobody sees.
59109
+ */
59110
+ async function promoteWithStill(input) {
59111
+ const entry = await withParcelStill(input);
59112
+ await input.detector.onStationaryChange({
59113
+ phase: "appeared",
59114
+ entry,
59115
+ timestamp: input.entry.becameStationaryAt
59116
+ });
59117
+ }
59118
+ //#endregion
59030
59119
  //#region src/pipeline-analytics/pipeline/person-over-vehicle.ts
59031
59120
  /**
59032
59121
  * How much of the PERSON box must sit inside a vehicle box to be counted.
@@ -70516,7 +70605,12 @@ Object.freeze({
70516
70605
  "listSupportedEntityKinds"
70517
70606
  ],
70518
70607
  "device-extension": ["listSlots", "listSources"],
70519
- "device-provider": ["discoverDevices", "getDevices"],
70608
+ "device-provider": [
70609
+ "classifyDiscoveryHits",
70610
+ "discoverDevices",
70611
+ "getDevices",
70612
+ "getDiscoveryModes"
70613
+ ],
70520
70614
  "device-removal-hook": ["listDeviceData"],
70521
70615
  "failure-contribution": ["list"],
70522
70616
  "llm": [
@@ -97314,6 +97408,15 @@ var NcSystemStateLedger = class {
97314
97408
  closeLegacyStreamKeys() {
97315
97409
  this.closeWhere("legacy-stream-keys", (row) => row.key.startsWith("stream:") && !DEVICE_STREAM_KEY.test(row.key), "legacy-stream-key");
97316
97410
  }
97411
+ /**
97412
+ * Is this device switched off RIGHT NOW (an open `device-disabled` row)?
97413
+ * D62: the switch outranks the device's liveness and its streams — a device
97414
+ * somebody turned off is reported off, never as offline. `false` while the
97415
+ * store has never answered (unknown is never "disabled").
97416
+ */
97417
+ isDeviceDisabled(deviceId) {
97418
+ return (this.openRows() ?? []).some((row) => row.kind === "device-disabled" && row.deviceId === deviceId);
97419
+ }
97317
97420
  /** The open rows, or `null` while the store has never answered. */
97318
97421
  openRows() {
97319
97422
  return this.deps.rows.answered() ? this.deps.rows.all() : null;
@@ -97820,6 +97923,7 @@ function readRaw(section, ports, nowMs) {
97820
97923
  reason: UNREAD_STATE
97821
97924
  };
97822
97925
  const items = [];
97926
+ const switchedOff = new Set(state.flatMap((row) => row.kind === "device-disabled" && row.deviceId !== void 0 ? [row.deviceId] : []));
97823
97927
  if (section === "device-state" || section === "nodes") {
97824
97928
  const liveness = ports.liveness();
97825
97929
  if (liveness === null) return {
@@ -97829,10 +97933,14 @@ function readRaw(section, ports, nowMs) {
97829
97933
  for (const row of liveness) {
97830
97934
  if (row.state !== "offline" || nowMs - row.updatedAt < ports.livenessHoldoffMs) continue;
97831
97935
  const item = livenessItem(row, ports.lookup);
97832
- if (item !== null && item.section === section) items.push(item);
97936
+ if (item === null || item.section !== section) continue;
97937
+ const id = item.subject.deviceId;
97938
+ if (id !== void 0 && switchedOff.has(id)) continue;
97939
+ items.push(item);
97833
97940
  }
97834
97941
  }
97835
97942
  for (const row of state) {
97943
+ if (row.kind === "stream-offline" && row.deviceId !== void 0 && switchedOff.has(row.deviceId)) continue;
97836
97944
  const item = stateItem(row, ports.lookup, ports.nodes);
97837
97945
  if (item.section === section) items.push(item);
97838
97946
  }
@@ -101997,16 +102105,37 @@ function onSystemEvent(host, event) {
101997
102105
  return;
101998
102106
  }
101999
102107
  if (isDeviceLivenessKind(observation.kind)) {
102108
+ if (dropSwitchedOff(host, system)) return;
102000
102109
  holdoff.arm(observation.subject, incoming);
102001
102110
  return;
102002
102111
  }
102003
102112
  } else if (system !== void 0 && (system.kind.startsWith("device-") || system.kind.startsWith("stream-"))) {
102004
102113
  if (host.lastSystemLiveness.get(system.subject) === system.kind) return;
102005
102114
  host.lastSystemLiveness.set(system.subject, system.kind);
102115
+ if (dropSwitchedOff(host, system)) return;
102006
102116
  }
102007
102117
  host.consumeEvent(incoming);
102008
102118
  }
102009
102119
  /**
102120
+ * D62: a device the operator switched off is reported off, never offline. Its
102121
+ * `device-offline` / `stream-offline` is dropped (and said) while an open
102122
+ * `device-disabled` row exists — the broker of a disabled device stopping is
102123
+ * the switch working, not an outage. The memory of the flip is already kept.
102124
+ */
102125
+ function dropSwitchedOff(host, system) {
102126
+ if (system === void 0 || system.deviceId === void 0) return false;
102127
+ if (system.kind !== "device-offline" && system.kind !== "stream-offline") return false;
102128
+ if (!host.stateSummary.ledger.isDeviceDisabled(system.deviceId)) return false;
102129
+ host.logger.debug("offline not notified — the device is switched off (D62)", {
102130
+ tags: { deviceId: system.deviceId },
102131
+ meta: {
102132
+ kind: system.kind,
102133
+ subject: system.subject
102134
+ }
102135
+ });
102136
+ return true;
102137
+ }
102138
+ /**
102010
102139
  * Arm a node liveness flip. An OFFLINE of a node that announced an update is
102011
102140
  * held for the whole planned-update window and worded as such if it is still
102012
102141
  * sent; the node's return inside the window is logged and sends nothing (the
@@ -113197,7 +113326,10 @@ var PackageDropDetector = class {
113197
113326
  }
113198
113327
  if (outcome.kind === "yes") {
113199
113328
  this.reportLlmSilence(this.llmSilence.noteAnswered(entry.deviceId), tags);
113200
- return { packageLlmVerdict: outcome.verdict };
113329
+ return {
113330
+ packageLlmVerdict: outcome.verdict,
113331
+ confirmElapsedMs: latencyMs
113332
+ };
113201
113333
  }
113202
113334
  this.dropUncertain(entry, tags, outcome.reason, latencyMs);
113203
113335
  return null;
@@ -113389,10 +113521,12 @@ var PackageDropDetector = class {
113389
113521
  }
113390
113522
  const llm = await this.llmFields(entry, rules, hitZones, tags);
113391
113523
  if (llm === null) return;
113524
+ const { confirmElapsedMs, ...llmRowFields } = llm;
113525
+ const rowTimestamp = timestamp + (confirmElapsedMs ?? 0);
113392
113526
  const draft = {
113393
113527
  kind: "object",
113394
113528
  deviceId: entry.deviceId,
113395
- timestamp,
113529
+ timestamp: rowTimestamp,
113396
113530
  source: "pipeline",
113397
113531
  idempotencyKey,
113398
113532
  trackId: entry.sourceTrackId ?? entry.id,
@@ -113411,7 +113545,7 @@ var PackageDropDetector = class {
113411
113545
  frameHeight: entry.frameHeight,
113412
113546
  ...entry.keyFrameMediaId !== void 0 ? { mediaId: entry.keyFrameMediaId } : {},
113413
113547
  importance: PACKAGE_IMPORTANCE,
113414
- ...llm
113548
+ ...llmRowFields
113415
113549
  };
113416
113550
  const rowId = await this.deps.events.insertObject(draft);
113417
113551
  if (rowId === null) {
@@ -113442,7 +113576,7 @@ var PackageDropDetector = class {
113442
113576
  w: entry.bbox.w,
113443
113577
  h: entry.bbox.h
113444
113578
  },
113445
- timestamp
113579
+ timestamp: rowTimestamp
113446
113580
  });
113447
113581
  this.deps.logger.info("package delivered — all 5 gates passed", {
113448
113582
  tags: { deviceId: entry.deviceId },
@@ -113453,6 +113587,7 @@ var PackageDropDetector = class {
113453
113587
  zoneIds: hitZones,
113454
113588
  dwellMs,
113455
113589
  areaFrac: Number(minAreaFrac.toFixed(5)),
113590
+ ...confirmElapsedMs !== void 0 ? { footageAnchorShiftMs: confirmElapsedMs } : {},
113456
113591
  ...entry.confidence !== void 0 ? { confidence: entry.confidence } : {}
113457
113592
  }
113458
113593
  });
@@ -123984,6 +124119,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
123984
124119
  this.frameState.lastNonPackageActivityAt.delete(data.deviceId);
123985
124120
  this.frameState.packageCollectors.forgetDevice(data.deviceId);
123986
124121
  this.frameState.packageOversizeLogAt.delete(data.deviceId);
124122
+ this.frameState.packageLookFrames.delete(data.deviceId);
123987
124123
  this.frameState.packageLookDropReasons.delete(data.deviceId);
123988
124124
  this.overlayState.clearDevice(data.deviceId);
123989
124125
  this.frameState.overlaySynthesisWarnAt.delete(data.deviceId);
@@ -124007,6 +124143,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
124007
124143
  this.frameState.lastNonPackageActivityAt.delete(deviceId);
124008
124144
  this.frameState.packageCollectors.forgetDevice(deviceId);
124009
124145
  this.frameState.packageOversizeLogAt.delete(deviceId);
124146
+ this.frameState.packageLookFrames.delete(deviceId);
124010
124147
  this.frameState.packageLookDropReasons.delete(deviceId);
124011
124148
  this.overlayState.clearDevice(deviceId);
124012
124149
  this.frameState.overlaySynthesisWarnAt.delete(deviceId);
@@ -126989,6 +127126,10 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
126989
127126
  runPackageStillness(input) {
126990
127127
  if (this.packageDropDetector === null) return;
126991
127128
  const tags = { deviceId: input.deviceId };
127129
+ if (input.frameHandle !== null) this.frameState.packageLookFrames.set(input.deviceId, {
127130
+ handle: input.frameHandle,
127131
+ at: input.timestamp
127132
+ });
126992
127133
  for (const t of input.tracked) {
126993
127134
  if (input.packageClasses.has(t.className)) continue;
126994
127135
  if (!isDelivererInPackageZone(t.zones, input.packageZoneIds)) continue;
@@ -127222,10 +127363,23 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_clip_m
127222
127363
  ...entry.confidence !== void 0 ? { confidence: entry.confidence } : {}
127223
127364
  }
127224
127365
  });
127225
- this.packageDropDetector.onStationaryChange({
127226
- phase: "appeared",
127366
+ const lookFrame = this.frameState.packageLookFrames.get(input.deviceId);
127367
+ promoteWithStill({
127227
127368
  entry,
127228
- timestamp: entry.becameStationaryAt
127369
+ handle: lookFrame !== void 0 && input.timestamp - lookFrame.at <= PACKAGE_LOOK_FRAME_MAX_AGE_MS ? lookFrame.handle : null,
127370
+ timestamp: lookFrame?.at ?? input.timestamp,
127371
+ query: (request) => this.queryPackageSceneCrop(request),
127372
+ writer: this.mediaStore,
127373
+ logger: this.ctx.logger,
127374
+ detector: this.packageDropDetector
127375
+ }).catch((err) => {
127376
+ this.ctx.logger.warn("package promotion failed", {
127377
+ tags,
127378
+ meta: {
127379
+ entryId: entry.id,
127380
+ error: err instanceof Error ? err.message : String(err)
127381
+ }
127382
+ });
127229
127383
  });
127230
127384
  }
127231
127385
  for (const entry of outcome.departed) {
@@ -1,4 +1,4 @@
1
- import { $ as MediaFileKindEnum, $i as BaseAddon, $n as cloneAlarmSettings, $r as paintHex, $t as OpsLogEntrySchema, A as DeclaredDevices, Aa as unknown, Ai as storageOccupancyCapability, An as TrackSideSchema, Ar as isAudioClassName, At as NcAlarmSensorsInputSchema, B as FULL_IMAGE_BBOX, Bi as systemEventSummarySplitOf, Bn as applyModeDelaysEdits, Br as isRootSuppliableStepId, Bt as NcRuleUpdateInputSchema, C as ClearTrackRelationResultSchema, Ca as partialRecord, Ci as ruleGroupingApplies, Cn as TimelapseRuleInputSchema, Cr as failureContributionCapability, Ct as NC_SNOOZE_MAX_MINUTES, D as DEFAULT_TIMELAPSE_PREVIEW_TEXT, Da as templateLiteral, Di as sensorRaisedOf, Dn as TrackPuritySchema, Dr as isAlertEpisodeOpen, Dt as NC_TEMPLATE_VARS, E as DEFAULT_EVENT_COLOR, Ea as string, Ei as secureActuationFor, En as TrackPlacementSchema, Er as isAlarmControllableCap, Et as NC_TAXONOMY, F as EVENT_DENSITY_BATCH_MAX, Fi as syncActiveAlarmProfileSettings, Fn as alarmPanelCapability, Fr as isEventOwnerType, Ft as NcRuleActionSchema, G as ListTrackRelationsResultSchema, Gi as withSystemEventClasses, Gn as audioMetricsCapability, Gr as kebabToCamel, Gt as NcSnoozeSuppressedSchema, H as LABEL_SUPPLY_MACRO, Hi as templateVarsFor, Hn as applySecureOnArmEdit, Hr as isSystemDelivery, Ht as NcSharedSequenceSchema, I as EVENT_KIND_BY_CAP, Ii as systemEventDeliveryProblems, In as alertEpisodeId, Ir as isKnownTemplateVar, It as NcRuleInputSchema, J as MAX_BIRTH_DECISION_RECORDS, Ji as canonicalHash, Jn as buildSubjectPath, Jr as memoizePinnedFfmpeg, Jt as NcTaxonomySchema, K as LockStateSchema, Ki as zoneAnalyticsCapability, Kn as audioModeOf, Kr as linkedStepOf, Kt as NcStateSummarySectionIdSchema, L as EVENT_OWNER_TYPES, Li as systemEventFamilyProblems, Ln as alertEpisodeKind, Lr as isLabelSupplyStepId, Lt as NcRulePatchSchema, M as EMBEDDING_MODEL_FAILED, Mi as subjectPathSampleFromBox, Mn as activateAlarmProfile, Mr as isDetectionMacroClass, Mt as NcAlarmSettingsPatchSchema, N as EMBEDDING_REQUIREMENTS_FAILED, Ni as subjectPathSvgPoints, Nn as addonWidgetsSourceCapability, Nr as isDrawableSubjectPath, Nt as NcConditionDescriptorSchema, O as DETECTION_MACRO_CLASSES, Oa as tuple, Oi as servedTemplateVars, On as TrackRelationKindSchema, Or as isAlertEpisodeSeverity, Ot as NcAlarmConfigSchema, P as EMBEDDING_REQUIREMENTS_UNAVAILABLE, Pi as summarizeReview, Pn as alarmDeviceSecureOnArm, Pr as isEventKindLabelKey, Pt as NcConditionsSchema, Q as MOTION_CLOSE_AFTER_MS, Qi as errMsg, Qn as classifyRetrainReview, Qr as occupancyScope, Qt as OPS_LOG_DEFAULT_LIMIT, R as EXPORT_DENSE_MAX_RANGES, Ri as systemEventFilterApplies, Rn as alertEpisodePayload, Rr as isMediaOwnerType, Rt as NcRuleSchema, S as ClearTrackRelationInputSchema, Sa as object, Si as ruleDeviceCompatCapQueries, Sn as TRACK_RELATIONS_DEFAULT_LIMIT, Sr as faceGalleryCapability, St as NC_SENSOR_TRANSITION_KINDS, T as DEFAULT_DETAIL_CROP_CONVENTION, Ta as strictObject, Ti as sceneMonitorCapability, Tn as TimelapseRuleSchema, Tr as gifFromMp4Args, Tt as NC_SYSTEM_EVENT_KIND_GROUP_SPECS, U as LabelAttributionSchema, Ui as vectorDimFromBase64, Un as armRemovalReconcile, Ur as isSystemEventSummaryRule, Ut as NcSnoozeInputSchema, V as FailureCounters, Vi as templateCarriesSummary, Vn as applyNonBlockingEdit, Vr as isScheduleActive, Vt as NcScheduleSchema, W as ListTrackRelationsInputSchema, Wi as viewerLinkBaseOf, Wn as assertTimelapseCadences, Wr as isVectorIndexDimConflict, Wt as NcSnoozeSchema, X as MAX_TRACK_PURITIES, Xi as isSourceCap, Xn as bundledCamstack, Xr as normalizeNcMediaPolicy, Xt as NcTemplatePreviewSchema, Y as MAX_BIRTH_LATENCY_PROXY_MS, Yi as evaluateSensorEdge, Yn as buildViewerLink, Yr as ncMediaPolicyError, Yt as NcTemplatePreviewInputSchema, Z as MAX_TRACK_RELATIONS, Zi as DeviceType, Zn as calendarEventLocalSpan, Zr as notificationRulesCapability, Zt as NcTemplateVarDescriptorSchema, _ as BIRTH_DECISION_DEFAULT_LIMIT, _a as boolean, _n as SceneMonitorSchema, _t as NC_CONSUMABLE_SYSTEM_EVENT_KINDS, a as CLIP_EMBEDDING_STEP_ID, aa as createEvent, ai as plateGalleryCapability, an as RetrainDismissedSchema, ar as deleteAlarmProfile, at as NC_ALARM_NOTIFY_FIELDS, b as BucketAccumulator, ba as looseObject, bi as ruleAutoTriggersAlarm, bn as SetTrackRelationInputSchema, br as eventKindLabel, bt as NC_GROUPING_MAX_SEC, c as readClusterModelPinStrict, ca as defineRecordKinds, ci as readMotionTriggeredBy, cn as SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX, cr as deriveRecordingMode, ct as NC_AUDIO_CONFIRM_HITS_DEFAULT, d as APPEARANCE_BLOCKS, da as nodePin, di as resolveClipSearchMinScore, dn as SCENE_DEFAULT_CHECK_INTERVAL_SEC, dr as deviceAttentionKind, dt as NC_CLIP_PRE_ROLL_DEFAULT_SEC, ea as CAP_ADVANCE_FIELDS, ei as paletteResultSchema, en as PackageLlmVerdictSchema, er as consumableFormOf, et as MotionTriggeredBySchema, f as APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT, fi as resolveDeliveryParams, fn as SCENE_DEFAULT_OBSERVATION_SPACING_SEC, fr as deviceRemovalHookCapability, ft as NC_CLIP_RETENTION_MAX_SEC, g as ArchivedDebugNoteSchema, ga as array, gi as resolveNcMediaImage, gn as SCENE_RESET_RECAPTURES, gt as NC_CONSUMABLE_LOW_PERCENT_DEFAULT, h as AlarmArmModeSchema, ha as _enum, hi as resolveModeNotifyPolicy, hn as SCENE_DIVERGED, hr as embeddingRefusalOf, ht as NC_CONFIRM_DEFAULT_TIMEOUT_MS, ia as RECORD_QUERY_MAX, ii as pipelineAnalyticsCapability, in as RebuildObjectEmbeddingsRefusalSchema, ir as createAlarmProfile, it as NC_ALARM_DELAY_MAX_SEC, j as DetectionSourceSchema, ja as EventCategory, ji as subKindsOf, jn as TrackSourceSchema, jr as isDefaultAlarmProfileId, jt as NcAlarmSensorsSchema, k as DETECTION_PIPELINE_CAP_NAME, ka as union, ki as startMoverUnderClearance, kn as TrackRelationSchema, kr as isAppLinkBase, kt as NcAlarmPostTriggeredActionSchema, l as resolveClusterModelPin, la as hydrateSchema, li as readTimelapseGeneratedAt, ln as SCENE_CONFIRM_DEFAULT_TIMEOUT_MS, lr as describeSystemEventDeliveryProblem, lt as NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT, m as AUDIO_MACRO_LABELS, ma as ZodObject, mi as resolveModeDelays, mn as SCENE_DEFAULT_UNCOVERED_POLICY, mt as NC_CONFIRM_DEFAULT_MAX_IMAGE_PX, na as InvalidRecordError, nn as RECORDING_EXPORT_MAX_READ_BYTES, nr as coreBlockIdFromAddonId, nt as NC_ALARM_DEFAULT_TRIGGERED_DURATION_SEC, o as CLUSTER_MODEL_OWNER_ADDON_ID, oa as customAction, oi as projectSubjectPath, on as RetrainOriginSchema, or as deriveDetailCropRect, ot as NC_ALARM_SYSTEM_EVENT_KINDS, p as ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT, pa as sleep$1, pi as resolveLocationMode, pn as SCENE_DEFAULT_QUIET_SECONDS, pt as NC_CONDITION_CATALOG, q as MAX_ARCHIVED_DEBUG_NOTES, qi as DEFAULT_FIRST_SIGHTING_FRESHNESS_MS, qn as buildEventKindDescriptor, qr as mayWriteToLocation, qt as NcSystemEventKindSchema, ra as RECORD_MAX_DATA_BYTES, ri as pickFaceRescoreIntervalMinutes, rn as RECORDING_SOURCE_CAMSTACK_ADDON, rr as cosineSimilarity$1, rt as NC_ALARM_DELAY_FIELDS, s as FACE_EMBEDDING_STEP_ID, sa as defineCustomActions, si as readDeviceStateFrom, sn as RetrainStatusSchema, sr as derivePostTriggeredAction, st as NC_ALARM_TRIGGERED_MAX_SEC, t as BUILTIN_CLIP_MODELS, ta as CamProfileSchema, ti as parseAlertEpisodePayload, tr as consumableLowPercentOf, tt as NC_ALARM_DEFAULT_PROFILE_ID, u as APPEARANCE_BIN_COUNT, ua as isDeviceScopedCap, ui as renameAlarmProfile, un as SCENE_DEFAULT_ANCHOR_THRESHOLD, ur as describeSystemEventFamilyProblem, ut as NC_CLIP_POST_ROLL_DEFAULT_SEC, v as BaseDevice, va as discriminatedUnion, vi as retrainRevisionConflictMessage, vn as SetTrackPurityInputSchema, vr as encodeVectorBase64, vt as NC_DEFAULT_SNOOZE_MINUTES, w as CoverStateSchema, wa as record, wi as ruleKindOf, wn as TimelapseRulePatchSchema, wr as gifDeriveSpeed, wt as NC_STATE_SUMMARY_SECTION_IDS, x as COCO_TO_MACRO, xa as number, xi as ruleBelongsToAlarm$1, xn as TIMELAPSE_DENSE_FLOOR_SEC, xr as evictionPolicyOfLocation, xt as NC_GROUPING_MIN_SEC, y as BirthDecisionRecordSchema, ya as literal, yi as rootSupplyServes, yn as SetTrackPurityResultSchema, yr as ensureAlarmProfiles, yt as NC_GROUPING_DEFAULT_SEC, z as FIRST_LEVEL_MACRO_CLASSES, zi as systemEventSummaryScheduleOf, zn as applyBlockingEdit, zr as isRetiredClearKey, zt as NcRuleTargetSchema } from "../clip-model-registry-BrazZJvr.mjs";
1
+ import { $ as MediaFileKindEnum, $i as BaseAddon, $n as cloneAlarmSettings, $r as paintHex, $t as OpsLogEntrySchema, A as DeclaredDevices, Aa as unknown, Ai as storageOccupancyCapability, An as TrackSideSchema, Ar as isAudioClassName, At as NcAlarmSensorsInputSchema, B as FULL_IMAGE_BBOX, Bi as systemEventSummarySplitOf, Bn as applyModeDelaysEdits, Br as isRootSuppliableStepId, Bt as NcRuleUpdateInputSchema, C as ClearTrackRelationResultSchema, Ca as partialRecord, Ci as ruleGroupingApplies, Cn as TimelapseRuleInputSchema, Cr as failureContributionCapability, Ct as NC_SNOOZE_MAX_MINUTES, D as DEFAULT_TIMELAPSE_PREVIEW_TEXT, Da as templateLiteral, Di as sensorRaisedOf, Dn as TrackPuritySchema, Dr as isAlertEpisodeOpen, Dt as NC_TEMPLATE_VARS, E as DEFAULT_EVENT_COLOR, Ea as string, Ei as secureActuationFor, En as TrackPlacementSchema, Er as isAlarmControllableCap, Et as NC_TAXONOMY, F as EVENT_DENSITY_BATCH_MAX, Fi as syncActiveAlarmProfileSettings, Fn as alarmPanelCapability, Fr as isEventOwnerType, Ft as NcRuleActionSchema, G as ListTrackRelationsResultSchema, Gi as withSystemEventClasses, Gn as audioMetricsCapability, Gr as kebabToCamel, Gt as NcSnoozeSuppressedSchema, H as LABEL_SUPPLY_MACRO, Hi as templateVarsFor, Hn as applySecureOnArmEdit, Hr as isSystemDelivery, Ht as NcSharedSequenceSchema, I as EVENT_KIND_BY_CAP, Ii as systemEventDeliveryProblems, In as alertEpisodeId, Ir as isKnownTemplateVar, It as NcRuleInputSchema, J as MAX_BIRTH_DECISION_RECORDS, Ji as canonicalHash, Jn as buildSubjectPath, Jr as memoizePinnedFfmpeg, Jt as NcTaxonomySchema, K as LockStateSchema, Ki as zoneAnalyticsCapability, Kn as audioModeOf, Kr as linkedStepOf, Kt as NcStateSummarySectionIdSchema, L as EVENT_OWNER_TYPES, Li as systemEventFamilyProblems, Ln as alertEpisodeKind, Lr as isLabelSupplyStepId, Lt as NcRulePatchSchema, M as EMBEDDING_MODEL_FAILED, Mi as subjectPathSampleFromBox, Mn as activateAlarmProfile, Mr as isDetectionMacroClass, Mt as NcAlarmSettingsPatchSchema, N as EMBEDDING_REQUIREMENTS_FAILED, Ni as subjectPathSvgPoints, Nn as addonWidgetsSourceCapability, Nr as isDrawableSubjectPath, Nt as NcConditionDescriptorSchema, O as DETECTION_MACRO_CLASSES, Oa as tuple, Oi as servedTemplateVars, On as TrackRelationKindSchema, Or as isAlertEpisodeSeverity, Ot as NcAlarmConfigSchema, P as EMBEDDING_REQUIREMENTS_UNAVAILABLE, Pi as summarizeReview, Pn as alarmDeviceSecureOnArm, Pr as isEventKindLabelKey, Pt as NcConditionsSchema, Q as MOTION_CLOSE_AFTER_MS, Qi as errMsg, Qn as classifyRetrainReview, Qr as occupancyScope, Qt as OPS_LOG_DEFAULT_LIMIT, R as EXPORT_DENSE_MAX_RANGES, Ri as systemEventFilterApplies, Rn as alertEpisodePayload, Rr as isMediaOwnerType, Rt as NcRuleSchema, S as ClearTrackRelationInputSchema, Sa as object, Si as ruleDeviceCompatCapQueries, Sn as TRACK_RELATIONS_DEFAULT_LIMIT, Sr as faceGalleryCapability, St as NC_SENSOR_TRANSITION_KINDS, T as DEFAULT_DETAIL_CROP_CONVENTION, Ta as strictObject, Ti as sceneMonitorCapability, Tn as TimelapseRuleSchema, Tr as gifFromMp4Args, Tt as NC_SYSTEM_EVENT_KIND_GROUP_SPECS, U as LabelAttributionSchema, Ui as vectorDimFromBase64, Un as armRemovalReconcile, Ur as isSystemEventSummaryRule, Ut as NcSnoozeInputSchema, V as FailureCounters, Vi as templateCarriesSummary, Vn as applyNonBlockingEdit, Vr as isScheduleActive, Vt as NcScheduleSchema, W as ListTrackRelationsInputSchema, Wi as viewerLinkBaseOf, Wn as assertTimelapseCadences, Wr as isVectorIndexDimConflict, Wt as NcSnoozeSchema, X as MAX_TRACK_PURITIES, Xi as isSourceCap, Xn as bundledCamstack, Xr as normalizeNcMediaPolicy, Xt as NcTemplatePreviewSchema, Y as MAX_BIRTH_LATENCY_PROXY_MS, Yi as evaluateSensorEdge, Yn as buildViewerLink, Yr as ncMediaPolicyError, Yt as NcTemplatePreviewInputSchema, Z as MAX_TRACK_RELATIONS, Zi as DeviceType, Zn as calendarEventLocalSpan, Zr as notificationRulesCapability, Zt as NcTemplateVarDescriptorSchema, _ as BIRTH_DECISION_DEFAULT_LIMIT, _a as boolean, _n as SceneMonitorSchema, _t as NC_CONSUMABLE_SYSTEM_EVENT_KINDS, a as CLIP_EMBEDDING_STEP_ID, aa as createEvent, ai as plateGalleryCapability, an as RetrainDismissedSchema, ar as deleteAlarmProfile, at as NC_ALARM_NOTIFY_FIELDS, b as BucketAccumulator, ba as looseObject, bi as ruleAutoTriggersAlarm, bn as SetTrackRelationInputSchema, br as eventKindLabel, bt as NC_GROUPING_MAX_SEC, c as readClusterModelPinStrict, ca as defineRecordKinds, ci as readMotionTriggeredBy, cn as SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX, cr as deriveRecordingMode, ct as NC_AUDIO_CONFIRM_HITS_DEFAULT, d as APPEARANCE_BLOCKS, da as nodePin, di as resolveClipSearchMinScore, dn as SCENE_DEFAULT_CHECK_INTERVAL_SEC, dr as deviceAttentionKind, dt as NC_CLIP_PRE_ROLL_DEFAULT_SEC, ea as CAP_ADVANCE_FIELDS, ei as paletteResultSchema, en as PackageLlmVerdictSchema, er as consumableFormOf, et as MotionTriggeredBySchema, f as APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT, fi as resolveDeliveryParams, fn as SCENE_DEFAULT_OBSERVATION_SPACING_SEC, fr as deviceRemovalHookCapability, ft as NC_CLIP_RETENTION_MAX_SEC, g as ArchivedDebugNoteSchema, ga as array, gi as resolveNcMediaImage, gn as SCENE_RESET_RECAPTURES, gt as NC_CONSUMABLE_LOW_PERCENT_DEFAULT, h as AlarmArmModeSchema, ha as _enum, hi as resolveModeNotifyPolicy, hn as SCENE_DIVERGED, hr as embeddingRefusalOf, ht as NC_CONFIRM_DEFAULT_TIMEOUT_MS, ia as RECORD_QUERY_MAX, ii as pipelineAnalyticsCapability, in as RebuildObjectEmbeddingsRefusalSchema, ir as createAlarmProfile, it as NC_ALARM_DELAY_MAX_SEC, j as DetectionSourceSchema, ja as EventCategory, ji as subKindsOf, jn as TrackSourceSchema, jr as isDefaultAlarmProfileId, jt as NcAlarmSensorsSchema, k as DETECTION_PIPELINE_CAP_NAME, ka as union, ki as startMoverUnderClearance, kn as TrackRelationSchema, kr as isAppLinkBase, kt as NcAlarmPostTriggeredActionSchema, l as resolveClusterModelPin, la as hydrateSchema, li as readTimelapseGeneratedAt, ln as SCENE_CONFIRM_DEFAULT_TIMEOUT_MS, lr as describeSystemEventDeliveryProblem, lt as NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT, m as AUDIO_MACRO_LABELS, ma as ZodObject, mi as resolveModeDelays, mn as SCENE_DEFAULT_UNCOVERED_POLICY, mt as NC_CONFIRM_DEFAULT_MAX_IMAGE_PX, na as InvalidRecordError, nn as RECORDING_EXPORT_MAX_READ_BYTES, nr as coreBlockIdFromAddonId, nt as NC_ALARM_DEFAULT_TRIGGERED_DURATION_SEC, o as CLUSTER_MODEL_OWNER_ADDON_ID, oa as customAction, oi as projectSubjectPath, on as RetrainOriginSchema, or as deriveDetailCropRect, ot as NC_ALARM_SYSTEM_EVENT_KINDS, p as ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT, pa as sleep$1, pi as resolveLocationMode, pn as SCENE_DEFAULT_QUIET_SECONDS, pt as NC_CONDITION_CATALOG, q as MAX_ARCHIVED_DEBUG_NOTES, qi as DEFAULT_FIRST_SIGHTING_FRESHNESS_MS, qn as buildEventKindDescriptor, qr as mayWriteToLocation, qt as NcSystemEventKindSchema, ra as RECORD_MAX_DATA_BYTES, ri as pickFaceRescoreIntervalMinutes, rn as RECORDING_SOURCE_CAMSTACK_ADDON, rr as cosineSimilarity$1, rt as NC_ALARM_DELAY_FIELDS, s as FACE_EMBEDDING_STEP_ID, sa as defineCustomActions, si as readDeviceStateFrom, sn as RetrainStatusSchema, sr as derivePostTriggeredAction, st as NC_ALARM_TRIGGERED_MAX_SEC, t as BUILTIN_CLIP_MODELS, ta as CamProfileSchema, ti as parseAlertEpisodePayload, tr as consumableLowPercentOf, tt as NC_ALARM_DEFAULT_PROFILE_ID, u as APPEARANCE_BIN_COUNT, ua as isDeviceScopedCap, ui as renameAlarmProfile, un as SCENE_DEFAULT_ANCHOR_THRESHOLD, ur as describeSystemEventFamilyProblem, ut as NC_CLIP_POST_ROLL_DEFAULT_SEC, v as BaseDevice, va as discriminatedUnion, vi as retrainRevisionConflictMessage, vn as SetTrackPurityInputSchema, vr as encodeVectorBase64, vt as NC_DEFAULT_SNOOZE_MINUTES, w as CoverStateSchema, wa as record, wi as ruleKindOf, wn as TimelapseRulePatchSchema, wr as gifDeriveSpeed, wt as NC_STATE_SUMMARY_SECTION_IDS, x as COCO_TO_MACRO, xa as number, xi as ruleBelongsToAlarm$1, xn as TIMELAPSE_DENSE_FLOOR_SEC, xr as evictionPolicyOfLocation, xt as NC_GROUPING_MIN_SEC, y as BirthDecisionRecordSchema, ya as literal, yi as rootSupplyServes, yn as SetTrackPurityResultSchema, yr as ensureAlarmProfiles, yt as NC_GROUPING_DEFAULT_SEC, z as FIRST_LEVEL_MACRO_CLASSES, zi as systemEventSummaryScheduleOf, zn as applyBlockingEdit, zr as isRetiredClearKey, zt as NcRuleTargetSchema } from "../clip-model-registry-BX6j2lnF.mjs";
2
2
  import { t as __exportAll } from "../embedding-encoder/index.mjs";
3
3
  import * as fs$1 from "node:fs";
4
4
  import { createWriteStream, promises } from "node:fs";
@@ -54628,6 +54628,12 @@ var FrameState = class {
54628
54628
  * per 5 minutes, not one per governor round (the wedge re-sights all
54629
54629
  * night; ~300 identical lines would bury the log it exists to serve). */
54630
54630
  packageOversizeLogAt = /* @__PURE__ */ new Map();
54631
+ /**
54632
+ * The newest frame the package path held per camera — the picture a parcel
54633
+ * promoted from a raw look is stored from (`package-still-capture.ts`). The
54634
+ * scene path concludes without a frame of its own, so it reads this.
54635
+ */
54636
+ packageLookFrames = /* @__PURE__ */ new Map();
54631
54637
  /** Reasons logged on the previous package look — episode helper for drops. */
54632
54638
  packageLookDropReasons = /* @__PURE__ */ new Map();
54633
54639
  };
@@ -58932,6 +58938,89 @@ function sweepOne(deps, deviceId) {
58932
58938
  if (outcome.departed.length > 0 || outcome.departedWithoutActivity.length > 0 || outcome.expired.length > 0) deps.onOutcome(deviceId, outcome, deps.now);
58933
58939
  }
58934
58940
  //#endregion
58941
+ //#region src/pipeline-analytics/pipeline/package/package-still-capture.ts
58942
+ /** A held look frame older than this is not the parcel's picture any more. */
58943
+ var PACKAGE_LOOK_FRAME_MAX_AGE_MS = 15e3;
58944
+ async function jpegOf(reply) {
58945
+ if (reply.tier === "ram-fullframe") return "preview-only";
58946
+ if (reply.jpegBytes !== void 0 && reply.jpegBytes.byteLength > 0) return reply.jpegBytes;
58947
+ if (reply.bytes !== void 0 && reply.bytes.length === reply.width * reply.height * 3) return encodeRgbCropToJpeg(reply.bytes, reply.width, reply.height);
58948
+ return "empty-frame";
58949
+ }
58950
+ /**
58951
+ * The entry carrying its still's `keyFrameMediaId`, or the entry unchanged when
58952
+ * it already had one or none could be stored (said, with the reason).
58953
+ */
58954
+ async function withParcelStill(input) {
58955
+ const { entry, logger } = input;
58956
+ if (entry.keyFrameMediaId !== void 0) return entry;
58957
+ const miss = (reason, detail) => {
58958
+ logger.warn("package still NOT stored — the delivery ships without a picture of the parcel", {
58959
+ tags: { deviceId: entry.deviceId },
58960
+ meta: {
58961
+ entryId: entry.id,
58962
+ reason,
58963
+ ...detail !== void 0 ? { error: detail } : {}
58964
+ }
58965
+ });
58966
+ return entry;
58967
+ };
58968
+ if (input.handle === null) return miss("no-frame-handle");
58969
+ if (input.writer === null) return miss("no-media-store");
58970
+ try {
58971
+ const reply = await input.query({
58972
+ handle: input.handle,
58973
+ bbox: {
58974
+ x: 0,
58975
+ y: 0,
58976
+ w: entry.frameWidth,
58977
+ h: entry.frameHeight
58978
+ },
58979
+ acceptJpegBytes: true,
58980
+ encodeJpeg: true,
58981
+ pin: nodePin(input.handle.nodeId)
58982
+ });
58983
+ if (reply === null) return miss("native-miss");
58984
+ const jpeg = await jpegOf(reply);
58985
+ if (typeof jpeg === "string") return miss(jpeg);
58986
+ const keyFrameMediaId = await input.writer.putReplacing({
58987
+ deviceId: entry.deviceId,
58988
+ ownerKind: "track",
58989
+ ownerId: entry.id,
58990
+ kind: "keyFrame",
58991
+ timestamp: input.timestamp,
58992
+ data: Buffer.from(jpeg),
58993
+ subjectBox: {
58994
+ x: entry.bbox.x,
58995
+ y: entry.bbox.y,
58996
+ w: entry.bbox.w,
58997
+ h: entry.bbox.h,
58998
+ frameWidth: entry.frameWidth,
58999
+ frameHeight: entry.frameHeight
59000
+ }
59001
+ });
59002
+ return {
59003
+ ...entry,
59004
+ keyFrameMediaId
59005
+ };
59006
+ } catch (err) {
59007
+ return miss("write-failed", errMsg(err));
59008
+ }
59009
+ }
59010
+ /**
59011
+ * One promotion, in the order that matters: the still is stored FIRST, then the
59012
+ * detector emits `delivered` — the notification centre reads the still when the
59013
+ * event arrives, so a picture written after it is a picture nobody sees.
59014
+ */
59015
+ async function promoteWithStill(input) {
59016
+ const entry = await withParcelStill(input);
59017
+ await input.detector.onStationaryChange({
59018
+ phase: "appeared",
59019
+ entry,
59020
+ timestamp: input.entry.becameStationaryAt
59021
+ });
59022
+ }
59023
+ //#endregion
58935
59024
  //#region src/pipeline-analytics/pipeline/person-over-vehicle.ts
58936
59025
  /**
58937
59026
  * How much of the PERSON box must sit inside a vehicle box to be counted.
@@ -70421,7 +70510,12 @@ Object.freeze({
70421
70510
  "listSupportedEntityKinds"
70422
70511
  ],
70423
70512
  "device-extension": ["listSlots", "listSources"],
70424
- "device-provider": ["discoverDevices", "getDevices"],
70513
+ "device-provider": [
70514
+ "classifyDiscoveryHits",
70515
+ "discoverDevices",
70516
+ "getDevices",
70517
+ "getDiscoveryModes"
70518
+ ],
70425
70519
  "device-removal-hook": ["listDeviceData"],
70426
70520
  "failure-contribution": ["list"],
70427
70521
  "llm": [
@@ -97219,6 +97313,15 @@ var NcSystemStateLedger = class {
97219
97313
  closeLegacyStreamKeys() {
97220
97314
  this.closeWhere("legacy-stream-keys", (row) => row.key.startsWith("stream:") && !DEVICE_STREAM_KEY.test(row.key), "legacy-stream-key");
97221
97315
  }
97316
+ /**
97317
+ * Is this device switched off RIGHT NOW (an open `device-disabled` row)?
97318
+ * D62: the switch outranks the device's liveness and its streams — a device
97319
+ * somebody turned off is reported off, never as offline. `false` while the
97320
+ * store has never answered (unknown is never "disabled").
97321
+ */
97322
+ isDeviceDisabled(deviceId) {
97323
+ return (this.openRows() ?? []).some((row) => row.kind === "device-disabled" && row.deviceId === deviceId);
97324
+ }
97222
97325
  /** The open rows, or `null` while the store has never answered. */
97223
97326
  openRows() {
97224
97327
  return this.deps.rows.answered() ? this.deps.rows.all() : null;
@@ -97725,6 +97828,7 @@ function readRaw(section, ports, nowMs) {
97725
97828
  reason: UNREAD_STATE
97726
97829
  };
97727
97830
  const items = [];
97831
+ const switchedOff = new Set(state.flatMap((row) => row.kind === "device-disabled" && row.deviceId !== void 0 ? [row.deviceId] : []));
97728
97832
  if (section === "device-state" || section === "nodes") {
97729
97833
  const liveness = ports.liveness();
97730
97834
  if (liveness === null) return {
@@ -97734,10 +97838,14 @@ function readRaw(section, ports, nowMs) {
97734
97838
  for (const row of liveness) {
97735
97839
  if (row.state !== "offline" || nowMs - row.updatedAt < ports.livenessHoldoffMs) continue;
97736
97840
  const item = livenessItem(row, ports.lookup);
97737
- if (item !== null && item.section === section) items.push(item);
97841
+ if (item === null || item.section !== section) continue;
97842
+ const id = item.subject.deviceId;
97843
+ if (id !== void 0 && switchedOff.has(id)) continue;
97844
+ items.push(item);
97738
97845
  }
97739
97846
  }
97740
97847
  for (const row of state) {
97848
+ if (row.kind === "stream-offline" && row.deviceId !== void 0 && switchedOff.has(row.deviceId)) continue;
97741
97849
  const item = stateItem(row, ports.lookup, ports.nodes);
97742
97850
  if (item.section === section) items.push(item);
97743
97851
  }
@@ -101902,16 +102010,37 @@ function onSystemEvent(host, event) {
101902
102010
  return;
101903
102011
  }
101904
102012
  if (isDeviceLivenessKind(observation.kind)) {
102013
+ if (dropSwitchedOff(host, system)) return;
101905
102014
  holdoff.arm(observation.subject, incoming);
101906
102015
  return;
101907
102016
  }
101908
102017
  } else if (system !== void 0 && (system.kind.startsWith("device-") || system.kind.startsWith("stream-"))) {
101909
102018
  if (host.lastSystemLiveness.get(system.subject) === system.kind) return;
101910
102019
  host.lastSystemLiveness.set(system.subject, system.kind);
102020
+ if (dropSwitchedOff(host, system)) return;
101911
102021
  }
101912
102022
  host.consumeEvent(incoming);
101913
102023
  }
101914
102024
  /**
102025
+ * D62: a device the operator switched off is reported off, never offline. Its
102026
+ * `device-offline` / `stream-offline` is dropped (and said) while an open
102027
+ * `device-disabled` row exists — the broker of a disabled device stopping is
102028
+ * the switch working, not an outage. The memory of the flip is already kept.
102029
+ */
102030
+ function dropSwitchedOff(host, system) {
102031
+ if (system === void 0 || system.deviceId === void 0) return false;
102032
+ if (system.kind !== "device-offline" && system.kind !== "stream-offline") return false;
102033
+ if (!host.stateSummary.ledger.isDeviceDisabled(system.deviceId)) return false;
102034
+ host.logger.debug("offline not notified — the device is switched off (D62)", {
102035
+ tags: { deviceId: system.deviceId },
102036
+ meta: {
102037
+ kind: system.kind,
102038
+ subject: system.subject
102039
+ }
102040
+ });
102041
+ return true;
102042
+ }
102043
+ /**
101915
102044
  * Arm a node liveness flip. An OFFLINE of a node that announced an update is
101916
102045
  * held for the whole planned-update window and worded as such if it is still
101917
102046
  * sent; the node's return inside the window is logged and sends nothing (the
@@ -113102,7 +113231,10 @@ var PackageDropDetector = class {
113102
113231
  }
113103
113232
  if (outcome.kind === "yes") {
113104
113233
  this.reportLlmSilence(this.llmSilence.noteAnswered(entry.deviceId), tags);
113105
- return { packageLlmVerdict: outcome.verdict };
113234
+ return {
113235
+ packageLlmVerdict: outcome.verdict,
113236
+ confirmElapsedMs: latencyMs
113237
+ };
113106
113238
  }
113107
113239
  this.dropUncertain(entry, tags, outcome.reason, latencyMs);
113108
113240
  return null;
@@ -113294,10 +113426,12 @@ var PackageDropDetector = class {
113294
113426
  }
113295
113427
  const llm = await this.llmFields(entry, rules, hitZones, tags);
113296
113428
  if (llm === null) return;
113429
+ const { confirmElapsedMs, ...llmRowFields } = llm;
113430
+ const rowTimestamp = timestamp + (confirmElapsedMs ?? 0);
113297
113431
  const draft = {
113298
113432
  kind: "object",
113299
113433
  deviceId: entry.deviceId,
113300
- timestamp,
113434
+ timestamp: rowTimestamp,
113301
113435
  source: "pipeline",
113302
113436
  idempotencyKey,
113303
113437
  trackId: entry.sourceTrackId ?? entry.id,
@@ -113316,7 +113450,7 @@ var PackageDropDetector = class {
113316
113450
  frameHeight: entry.frameHeight,
113317
113451
  ...entry.keyFrameMediaId !== void 0 ? { mediaId: entry.keyFrameMediaId } : {},
113318
113452
  importance: PACKAGE_IMPORTANCE,
113319
- ...llm
113453
+ ...llmRowFields
113320
113454
  };
113321
113455
  const rowId = await this.deps.events.insertObject(draft);
113322
113456
  if (rowId === null) {
@@ -113347,7 +113481,7 @@ var PackageDropDetector = class {
113347
113481
  w: entry.bbox.w,
113348
113482
  h: entry.bbox.h
113349
113483
  },
113350
- timestamp
113484
+ timestamp: rowTimestamp
113351
113485
  });
113352
113486
  this.deps.logger.info("package delivered — all 5 gates passed", {
113353
113487
  tags: { deviceId: entry.deviceId },
@@ -113358,6 +113492,7 @@ var PackageDropDetector = class {
113358
113492
  zoneIds: hitZones,
113359
113493
  dwellMs,
113360
113494
  areaFrac: Number(minAreaFrac.toFixed(5)),
113495
+ ...confirmElapsedMs !== void 0 ? { footageAnchorShiftMs: confirmElapsedMs } : {},
113361
113496
  ...entry.confidence !== void 0 ? { confidence: entry.confidence } : {}
113362
113497
  }
113363
113498
  });
@@ -123889,6 +124024,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
123889
124024
  this.frameState.lastNonPackageActivityAt.delete(data.deviceId);
123890
124025
  this.frameState.packageCollectors.forgetDevice(data.deviceId);
123891
124026
  this.frameState.packageOversizeLogAt.delete(data.deviceId);
124027
+ this.frameState.packageLookFrames.delete(data.deviceId);
123892
124028
  this.frameState.packageLookDropReasons.delete(data.deviceId);
123893
124029
  this.overlayState.clearDevice(data.deviceId);
123894
124030
  this.frameState.overlaySynthesisWarnAt.delete(data.deviceId);
@@ -123912,6 +124048,7 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
123912
124048
  this.frameState.lastNonPackageActivityAt.delete(deviceId);
123913
124049
  this.frameState.packageCollectors.forgetDevice(deviceId);
123914
124050
  this.frameState.packageOversizeLogAt.delete(deviceId);
124051
+ this.frameState.packageLookFrames.delete(deviceId);
123915
124052
  this.frameState.packageLookDropReasons.delete(deviceId);
123916
124053
  this.overlayState.clearDevice(deviceId);
123917
124054
  this.frameState.overlaySynthesisWarnAt.delete(deviceId);
@@ -126894,6 +127031,10 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
126894
127031
  runPackageStillness(input) {
126895
127032
  if (this.packageDropDetector === null) return;
126896
127033
  const tags = { deviceId: input.deviceId };
127034
+ if (input.frameHandle !== null) this.frameState.packageLookFrames.set(input.deviceId, {
127035
+ handle: input.frameHandle,
127036
+ at: input.timestamp
127037
+ });
126897
127038
  for (const t of input.tracked) {
126898
127039
  if (input.packageClasses.has(t.className)) continue;
126899
127040
  if (!isDelivererInPackageZone(t.zones, input.packageZoneIds)) continue;
@@ -127127,10 +127268,23 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
127127
127268
  ...entry.confidence !== void 0 ? { confidence: entry.confidence } : {}
127128
127269
  }
127129
127270
  });
127130
- this.packageDropDetector.onStationaryChange({
127131
- phase: "appeared",
127271
+ const lookFrame = this.frameState.packageLookFrames.get(input.deviceId);
127272
+ promoteWithStill({
127132
127273
  entry,
127133
- timestamp: entry.becameStationaryAt
127274
+ handle: lookFrame !== void 0 && input.timestamp - lookFrame.at <= PACKAGE_LOOK_FRAME_MAX_AGE_MS ? lookFrame.handle : null,
127275
+ timestamp: lookFrame?.at ?? input.timestamp,
127276
+ query: (request) => this.queryPackageSceneCrop(request),
127277
+ writer: this.mediaStore,
127278
+ logger: this.ctx.logger,
127279
+ detector: this.packageDropDetector
127280
+ }).catch((err) => {
127281
+ this.ctx.logger.warn("package promotion failed", {
127282
+ tags,
127283
+ meta: {
127284
+ entryId: entry.id,
127285
+ error: err instanceof Error ? err.message : String(err)
127286
+ }
127287
+ });
127134
127288
  });
127135
127289
  }
127136
127290
  for (const entry of outcome.departed) {
@@ -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-D6DnF6Vk.mjs")).catch((e) => {
33
+ return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-Vag6rhEh.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.653",
3
+ "version": "1.2.654",
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",