@camstack/addon-post-analysis 1.2.622 → 1.2.624

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 (15) hide show
  1. package/THIRD_PARTY_MODELS.md +2 -2
  2. package/dist/{clip-model-registry-EDTOCKN9.mjs → clip-model-registry-BpS_EthX.mjs} +181 -71
  3. package/dist/{clip-model-registry-MHJ9BSUV.js → clip-model-registry-WENnCB-u.js} +192 -70
  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-DAyVukQp.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-B3M-0LC0.mjs} +3 -3
  8. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DBuMgPh6.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-CssYIiFD.mjs → _virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-B1HZu0i3.mjs} +1 -1
  10. package/dist/pipeline-analytics/{hostInit-C4-dCKYR.mjs → hostInit-BqU6Q1wQ.mjs} +3 -3
  11. package/dist/pipeline-analytics/index.js +335 -86
  12. package/dist/pipeline-analytics/index.mjs +335 -86
  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-CTvx3PDS.mjs +0 -26
@@ -1,4 +1,4 @@
1
- import { $ as MediaFileKindEnum, $i as hydrateSchema, $n as cosineSimilarity$1, $r as projectSubjectPath, $t as OpsLogEntrySchema, A as DeclaredDevices, Ai as systemEventFilterApplies, An as activateAlarmProfile, Ar as isEventOwnerType, At as NcAlarmSensorsInputSchema, B as FULL_IMAGE_BBOX, Bi as canonicalHash, Bn as applySecureOnArmEdit, Br as kebabToCamel, Bt as NcRuleUpdateInputSchema, C as ClearTrackRelationResultSchema, Ci as subKindsOf, Cn as TimelapseRulePatchSchema, Cr as isAlertEpisodeSeverity, Ct as NC_SNOOZE_MAX_MINUTES, D as DEFAULT_TIMELAPSE_PREVIEW_TEXT, Di as syncActiveAlarmProfileSettings, Dn as TrackRelationSchema, Dr as isDetectionMacroClass, Dt as NC_TEMPLATE_VARS, E as DEFAULT_EVENT_COLOR, Ei as summarizeReview, En as TrackRelationKindSchema, Er as isDefaultAlarmProfileId, Et as NC_TAXONOMY, F as EVENT_DENSITY_BATCH_MAX, Fi as vectorDimFromBase64, Fn as alertEpisodeKind, Fr as isRootSuppliableStepId, Ft as NcRuleActionSchema, G as ListTrackRelationsResultSchema, Gi as BaseAddon, Gn as buildEventKindDescriptor, Gr as normalizeNcMediaPolicy, Gt as NcSnoozeSuppressedSchema, H as LABEL_SUPPLY_MACRO, Hi as isSourceCap, Hn as assertTimelapseCadences, Hr as mayWriteToLocation, Ht as NcSharedSequenceSchema, I as EVENT_KIND_BY_CAP, Ii as viewerLinkBaseOf, In as alertEpisodePayload, Ir as isScheduleActive, It as NcRuleInputSchema, J as MAX_BIRTH_DECISION_RECORDS, Ji as RECORD_QUERY_MAX, Jn as calendarEventLocalSpan, Jr as parseAlertEpisodePayload, Jt as NcTaxonomySchema, K as LockStateSchema, Ki as CamProfileSchema, Kn as buildSubjectPath, Kr as notificationRulesCapability, Kt as NcStateSummarySectionIdSchema, L as EVENT_OWNER_TYPES, Li as withSystemEventClasses, Ln as applyBlockingEdit, Lr as isSystemDelivery, Lt as NcRulePatchSchema, M as EMBEDDING_MODEL_FAILED, Mi as systemEventSummarySplitOf, Mn as alarmDeviceSecureOnArm, Mr as isLabelSupplyStepId, Mt as NcAlarmSettingsPatchSchema, N as EMBEDDING_REQUIREMENTS_FAILED, Ni as templateCarriesSummary, Nn as alarmPanelCapability, Nr as isMediaOwnerType, Nt as NcConditionDescriptorSchema, O as DETECTION_MACRO_CLASSES, Oi as systemEventDeliveryProblems, On as TrackSideSchema, Or as isDrawableSubjectPath, Ot as NcAlarmConfigSchema, P as EMBEDDING_REQUIREMENTS_UNAVAILABLE, Pi as templateVarsFor, Pn as alertEpisodeId, Pr as isRetiredClearKey, Pt as NcConditionsSchema, Q as MOTION_CLOSE_AFTER_MS, Qi as defineRecordKinds, Qn as coreBlockIdFromAddonId, Qr as plateGalleryCapability, Qt as OPS_LOG_DEFAULT_LIMIT, R as EXPORT_DENSE_MAX_RANGES, Ri as zoneAnalyticsCapability, Rn as applyModeDelaysEdits, Rr as isSystemEventSummaryRule, Rt as NcRuleSchema, S as ClearTrackRelationInputSchema, Si as storageOccupancyCapability, Sn as TimelapseRuleInputSchema, Sr as isAlertEpisodeOpen, St as NC_SENSOR_TRANSITION_KINDS, T as DEFAULT_DETAIL_CROP_CONVENTION, Ti as subjectPathSvgPoints, Tn as TrackPuritySchema, Tr as isAudioClassName, Tt as NC_TANK_SYSTEM_EVENT_KINDS, U as LabelAttributionSchema, Ui as DeviceType, Un as audioMetricsCapability, Ur as memoizePinnedFfmpeg, Ut as NcSnoozeInputSchema, V as FailureCounters, Vi as evaluateSensorEdge, Vn as armRemovalReconcile, Vr as linkedStepOf, Vt as NcScheduleSchema, W as ListTrackRelationsInputSchema, Wi as errMsg, Wn as audioModeOf, Wr as ncMediaPolicyError, Wt as NcSnoozeSchema, X as MAX_TRACK_PURITIES, Xi as customAction, Xn as cloneAlarmSettings, Xr as pickFaceRescoreIntervalMinutes, Xt as NcTemplatePreviewSchema, Y as MAX_BIRTH_LATENCY_PROXY_MS, Yi as createEvent, Yn as classifyRetrainReview, Yt as NcTemplatePreviewInputSchema, Z as MAX_TRACK_RELATIONS, Zi as defineCustomActions, Zn as consumableLowPercentOf, Zr as pipelineAnalyticsCapability, Zt as NcTemplateVarDescriptorSchema, _ as BIRTH_DECISION_DEFAULT_LIMIT, _a as templateLiteral, _i as sceneMonitorCapability, _n as SetTrackPurityInputSchema, _r as faceGalleryCapability, _t as NC_CONSUMABLE_SYSTEM_EVENT_KINDS, a as CLIP_EMBEDDING_STEP_ID, aa as _enum, ai as resolveLocationMode, an as RetrainOriginSchema, ar as describeSystemEventDeliveryProblem, at as NC_ALARM_NOTIFY_FIELDS, b as BucketAccumulator, ba as unknown, bi as servedTemplateVars, bn as TIMELAPSE_DENSE_FLOOR_SEC, br as gifFromMp4Args, bt as NC_GROUPING_MAX_SEC, c as readClusterModelPinStrict, ca as discriminatedUnion, ci as resolveNcMediaImage, cn as SCENE_CONFIRM_DEFAULT_TIMEOUT_MS, ct as NC_AUDIO_CONFIRM_HITS_DEFAULT, d as APPEARANCE_BLOCKS, da as number, di as rootSupplyServes, dn as SCENE_DEFAULT_OBSERVATION_SPACING_SEC, dt as NC_CLIP_PRE_ROLL_DEFAULT_SEC, ea as isDeviceScopedCap, ei as readDeviceStateFrom, er as createAlarmProfile, et as MotionTriggeredBySchema, f as APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT, fa as object, fi as ruleAutoTriggersAlarm, fn as SCENE_DEFAULT_QUIET_SECONDS, ft as NC_CLIP_RETENTION_MAX_SEC, g as ArchivedDebugNoteSchema, ga as string, gi as ruleKindOf, gn as SceneMonitorSchema, gr as evictionPolicyOfLocation, gt as NC_CONSUMABLE_LOW_PERCENT_DEFAULT, h as AlarmArmModeSchema, ha as strictObject, hi as ruleGroupingApplies, hn as SCENE_RESET_RECAPTURES, hr as eventKindLabel, ht as NC_CONFIRM_DEFAULT_TIMEOUT_MS, ia as ZodObject, ii as resolveClipSearchMinScore, in as RetrainDismissedSchema, ir as deriveRecordingMode, it as NC_ALARM_DELAY_MAX_SEC, j as DetectionSourceSchema, ji as systemEventSummaryScheduleOf, jn as addonWidgetsSourceCapability, jr as isKnownTemplateVar, jt as NcAlarmSensorsSchema, k as DETECTION_PIPELINE_CAP_NAME, ki as systemEventFamilyProblems, kn as TrackSourceSchema, kr as isEventKindLabelKey, kt as NcAlarmPostTriggeredActionSchema, l as resolveClusterModelPin, la as literal, ln as SCENE_DEFAULT_ANCHOR_THRESHOLD, lt as NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT, m as AUDIO_MACRO_LABELS, ma as record, mi as ruleDeviceCompatCapQueries, mn as SCENE_DIVERGED, mr as ensureAlarmProfiles, mt as NC_CONFIRM_DEFAULT_MAX_IMAGE_PX, ni as readTimelapseGeneratedAt, nn as RECORDING_SOURCE_CAMSTACK_ADDON, nr as deriveDetailCropRect, nt as NC_ALARM_DEFAULT_TRIGGERED_DURATION_SEC, o as CLUSTER_MODEL_OWNER_ADDON_ID, oa as array, oi as resolveModeDelays, on as RetrainStatusSchema, or as describeSystemEventFamilyProblem, ot as NC_ALARM_SYSTEM_EVENT_KINDS, p as ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT, pa as partialRecord, pi as ruleBelongsToAlarm$1, pn as SCENE_DEFAULT_UNCOVERED_POLICY, pr as encodeVectorBase64, pt as NC_CONDITION_CATALOG, q as MAX_ARCHIVED_DEBUG_NOTES, qi as RECORD_MAX_DATA_BYTES, qn as buildViewerLink, qr as occupancyScope, qt as NcSystemEventKindSchema, ra as sleep$1, ri as renameAlarmProfile, rn as RebuildObjectEmbeddingsRefusalSchema, rr as derivePostTriggeredAction, rt as NC_ALARM_DELAY_FIELDS, s as FACE_EMBEDDING_STEP_ID, sa as boolean, si as resolveModeNotifyPolicy, sn as SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX, sr as deviceRemovalHookCapability, st as NC_ALARM_TRIGGERED_MAX_SEC, t as BUILTIN_CLIP_MODELS, ta as nodePin, ti as readMotionTriggeredBy, tn as RECORDING_EXPORT_MAX_READ_BYTES, tr as deleteAlarmProfile, tt as NC_ALARM_DEFAULT_PROFILE_ID, u as APPEARANCE_BIN_COUNT, ua as looseObject, ui as retrainRevisionConflictMessage, un as SCENE_DEFAULT_CHECK_INTERVAL_SEC, ur as embeddingRefusalOf, ut as NC_CLIP_POST_ROLL_DEFAULT_SEC, v as BaseDevice, va as tuple, vi as secureActuationFor, vn as SetTrackPurityResultSchema, vr as failureContributionCapability, vt as NC_DEFAULT_SNOOZE_MINUTES, w as CoverStateSchema, wi as subjectPathSampleFromBox, wn as TimelapseRuleSchema, wr as isAppLinkBase, wt as NC_SYSTEM_EVENT_KIND_GROUP_SPECS, x as COCO_TO_MACRO, xa as EventCategory, xi as startMoverUnderClearance, xn as TRACK_RELATIONS_DEFAULT_LIMIT, xr as isAlarmControllableCap, xt as NC_GROUPING_MIN_SEC, y as BirthDecisionRecordSchema, ya as union, yi as sensorRaisedOf, yn as SetTrackRelationInputSchema, yr as gifDeriveSpeed, yt as NC_GROUPING_DEFAULT_SEC, z as FIRST_LEVEL_MACRO_CLASSES, zi as DEFAULT_FIRST_SIGHTING_FRESHNESS_MS, zn as applyNonBlockingEdit, zr as isVectorIndexDimConflict, zt as NcRuleTargetSchema } from "../clip-model-registry-EDTOCKN9.mjs";
1
+ import { $ as MediaFileKindEnum, $i as defineCustomActions, $n as cosineSimilarity$1, $r as plateGalleryCapability, $t as OpsLogEntrySchema, A as DeclaredDevices, Ai as systemEventFamilyProblems, An as activateAlarmProfile, Ar as isEventKindLabelKey, At as NcAlarmSensorsInputSchema, B as FULL_IMAGE_BBOX, Bi as DEFAULT_FIRST_SIGHTING_FRESHNESS_MS, Bn as applySecureOnArmEdit, Br as isVectorIndexDimConflict, Bt as NcRuleUpdateInputSchema, C as ClearTrackRelationResultSchema, Ca as EventCategory, Ci as storageOccupancyCapability, Cn as TimelapseRulePatchSchema, Cr as isAlertEpisodeOpen, Ct as NC_SNOOZE_MAX_MINUTES, D as DEFAULT_TIMELAPSE_PREVIEW_TEXT, Di as summarizeReview, Dn as TrackRelationSchema, Dr as isDefaultAlarmProfileId, Dt as NC_TEMPLATE_VARS, E as DEFAULT_EVENT_COLOR, Ei as subjectPathSvgPoints, En as TrackRelationKindSchema, Er as isAudioClassName, Et as NC_TAXONOMY, F as EVENT_DENSITY_BATCH_MAX, Fi as templateVarsFor, Fn as alertEpisodeKind, Fr as isRetiredClearKey, Ft as NcRuleActionSchema, G as ListTrackRelationsResultSchema, Gi as errMsg, Gn as buildEventKindDescriptor, Gr as ncMediaPolicyError, Gt as NcSnoozeSuppressedSchema, H as LABEL_SUPPLY_MACRO, Hi as evaluateSensorEdge, Hn as assertTimelapseCadences, Hr as linkedStepOf, Ht as NcSharedSequenceSchema, I as EVENT_KIND_BY_CAP, Ii as vectorDimFromBase64, In as alertEpisodePayload, Ir as isRootSuppliableStepId, It as NcRuleInputSchema, J as MAX_BIRTH_DECISION_RECORDS, Ji as InvalidRecordError, Jn as calendarEventLocalSpan, Jr as occupancyScope, Jt as NcTaxonomySchema, K as LockStateSchema, Ki as BaseAddon, Kn as buildSubjectPath, Kr as normalizeNcMediaPolicy, Kt as NcStateSummarySectionIdSchema, L as EVENT_OWNER_TYPES, Li as viewerLinkBaseOf, Ln as applyBlockingEdit, Lr as isScheduleActive, Lt as NcRulePatchSchema, M as EMBEDDING_MODEL_FAILED, Mi as systemEventSummaryScheduleOf, Mn as alarmDeviceSecureOnArm, Mr as isKnownTemplateVar, Mt as NcAlarmSettingsPatchSchema, N as EMBEDDING_REQUIREMENTS_FAILED, Ni as systemEventSummarySplitOf, Nn as alarmPanelCapability, Nr as isLabelSupplyStepId, Nt as NcConditionDescriptorSchema, O as DETECTION_MACRO_CLASSES, Oi as syncActiveAlarmProfileSettings, On as TrackSideSchema, Or as isDetectionMacroClass, Ot as NcAlarmConfigSchema, P as EMBEDDING_REQUIREMENTS_UNAVAILABLE, Pi as templateCarriesSummary, Pn as alertEpisodeId, Pr as isMediaOwnerType, Pt as NcConditionsSchema, Q as MOTION_CLOSE_AFTER_MS, Qi as customAction, Qn as coreBlockIdFromAddonId, Qr as pipelineAnalyticsCapability, Qt as OPS_LOG_DEFAULT_LIMIT, R as EXPORT_DENSE_MAX_RANGES, Ri as withSystemEventClasses, Rn as applyModeDelaysEdits, Rr as isSystemDelivery, Rt as NcRuleSchema, S as ClearTrackRelationInputSchema, Sa as unknown, Si as startMoverUnderClearance, Sn as TimelapseRuleInputSchema, Sr as isAlarmControllableCap, St as NC_SENSOR_TRANSITION_KINDS, T as DEFAULT_DETAIL_CROP_CONVENTION, Ti as subjectPathSampleFromBox, Tn as TrackPuritySchema, Tr as isAppLinkBase, Tt as NC_TANK_SYSTEM_EVENT_KINDS, U as LabelAttributionSchema, Ui as isSourceCap, Un as audioMetricsCapability, Ur as mayWriteToLocation, Ut as NcSnoozeInputSchema, V as FailureCounters, Vi as canonicalHash, Vn as armRemovalReconcile, Vr as kebabToCamel, Vt as NcScheduleSchema, W as ListTrackRelationsInputSchema, Wi as DeviceType, Wn as audioModeOf, Wr as memoizePinnedFfmpeg, Wt as NcSnoozeSchema, X as MAX_TRACK_PURITIES, Xi as RECORD_QUERY_MAX, Xn as cloneAlarmSettings, Xt as NcTemplatePreviewSchema, Y as MAX_BIRTH_LATENCY_PROXY_MS, Yi as RECORD_MAX_DATA_BYTES, Yn as classifyRetrainReview, Yr as parseAlertEpisodePayload, Yt as NcTemplatePreviewInputSchema, Z as MAX_TRACK_RELATIONS, Zi as createEvent, Zn as consumableLowPercentOf, Zr as pickFaceRescoreIntervalMinutes, Zt as NcTemplateVarDescriptorSchema, _ as BIRTH_DECISION_DEFAULT_LIMIT, _a as strictObject, _i as ruleKindOf, _n as SetTrackPurityInputSchema, _r as evictionPolicyOfLocation, _t as NC_CONSUMABLE_SYSTEM_EVENT_KINDS, a as CLIP_EMBEDDING_STEP_ID, aa as sleep$1, ai as resolveClipSearchMinScore, an as RetrainOriginSchema, ar as describeSystemEventDeliveryProblem, at as NC_ALARM_NOTIFY_FIELDS, b as BucketAccumulator, ba as tuple, bi as sensorRaisedOf, bn as TIMELAPSE_DENSE_FLOOR_SEC, br as gifDeriveSpeed, bt as NC_GROUPING_MAX_SEC, c as readClusterModelPinStrict, ca as array, ci as resolveModeNotifyPolicy, cn as SCENE_CONFIRM_DEFAULT_TIMEOUT_MS, cr as deviceRemovalHookCapability, ct as NC_AUDIO_CONFIRM_HITS_DEFAULT, d as APPEARANCE_BLOCKS, da as literal, di as retrainRevisionConflictMessage, dn as SCENE_DEFAULT_OBSERVATION_SPACING_SEC, dr as embeddingRefusalOf, dt as NC_CLIP_PRE_ROLL_DEFAULT_SEC, ea as defineRecordKinds, ei as projectSubjectPath, er as createAlarmProfile, et as MotionTriggeredBySchema, f as APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT, fa as looseObject, fi as rootSupplyServes, fn as SCENE_DEFAULT_QUIET_SECONDS, ft as NC_CLIP_RETENTION_MAX_SEC, g as ArchivedDebugNoteSchema, ga as record, gi as ruleGroupingApplies, gn as SceneMonitorSchema, gr as eventKindLabel, gt as NC_CONSUMABLE_LOW_PERCENT_DEFAULT, h as AlarmArmModeSchema, ha as partialRecord, hi as ruleDeviceCompatCapQueries, hn as SCENE_RESET_RECAPTURES, hr as ensureAlarmProfiles, ht as NC_CONFIRM_DEFAULT_TIMEOUT_MS, ii as renameAlarmProfile, in as RetrainDismissedSchema, ir as deriveRecordingMode, it as NC_ALARM_DELAY_MAX_SEC, j as DetectionSourceSchema, ji as systemEventFilterApplies, jn as addonWidgetsSourceCapability, jr as isEventOwnerType, jt as NcAlarmSensorsSchema, k as DETECTION_PIPELINE_CAP_NAME, ki as systemEventDeliveryProblems, kn as TrackSourceSchema, kr as isDrawableSubjectPath, kt as NcAlarmPostTriggeredActionSchema, l as resolveClusterModelPin, la as boolean, li as resolveNcMediaImage, ln as SCENE_DEFAULT_ANCHOR_THRESHOLD, lt as NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT, m as AUDIO_MACRO_LABELS, ma as object, mi as ruleBelongsToAlarm$1, mn as SCENE_DIVERGED, mr as encodeVectorBase64, mt as NC_CONFIRM_DEFAULT_MAX_IMAGE_PX, na as isDeviceScopedCap, ni as readMotionTriggeredBy, nn as RECORDING_SOURCE_CAMSTACK_ADDON, nr as deriveDetailCropRect, nt as NC_ALARM_DEFAULT_TRIGGERED_DURATION_SEC, o as CLUSTER_MODEL_OWNER_ADDON_ID, oa as ZodObject, oi as resolveLocationMode, on as RetrainStatusSchema, or as describeSystemEventFamilyProblem, ot as NC_ALARM_SYSTEM_EVENT_KINDS, p as ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT, pa as number, pi as ruleAutoTriggersAlarm, pn as SCENE_DEFAULT_UNCOVERED_POLICY, pt as NC_CONDITION_CATALOG, q as MAX_ARCHIVED_DEBUG_NOTES, qi as CamProfileSchema, qn as buildViewerLink, qr as notificationRulesCapability, qt as NcSystemEventKindSchema, ra as nodePin, ri as readTimelapseGeneratedAt, rn as RebuildObjectEmbeddingsRefusalSchema, rr as derivePostTriggeredAction, rt as NC_ALARM_DELAY_FIELDS, s as FACE_EMBEDDING_STEP_ID, sa as _enum, si as resolveModeDelays, sn as SCENE_CONFIRM_DEFAULT_MAX_IMAGE_PX, sr as deviceAttentionKind, st as NC_ALARM_TRIGGERED_MAX_SEC, t as BUILTIN_CLIP_MODELS, ta as hydrateSchema, ti as readDeviceStateFrom, tn as RECORDING_EXPORT_MAX_READ_BYTES, tr as deleteAlarmProfile, tt as NC_ALARM_DEFAULT_PROFILE_ID, u as APPEARANCE_BIN_COUNT, ua as discriminatedUnion, un as SCENE_DEFAULT_CHECK_INTERVAL_SEC, ut as NC_CLIP_POST_ROLL_DEFAULT_SEC, v as BaseDevice, va as string, vi as sceneMonitorCapability, vn as SetTrackPurityResultSchema, vr as faceGalleryCapability, vt as NC_DEFAULT_SNOOZE_MINUTES, w as CoverStateSchema, wi as subKindsOf, wn as TimelapseRuleSchema, wr as isAlertEpisodeSeverity, wt as NC_SYSTEM_EVENT_KIND_GROUP_SPECS, x as COCO_TO_MACRO, xa as union, xi as servedTemplateVars, xn as TRACK_RELATIONS_DEFAULT_LIMIT, xr as gifFromMp4Args, xt as NC_GROUPING_MIN_SEC, y as BirthDecisionRecordSchema, ya as templateLiteral, yi as secureActuationFor, yn as SetTrackRelationInputSchema, yr as failureContributionCapability, yt as NC_GROUPING_DEFAULT_SEC, z as FIRST_LEVEL_MACRO_CLASSES, zi as zoneAnalyticsCapability, zn as applyNonBlockingEdit, zr as isSystemEventSummaryRule, zt as NcRuleTargetSchema } from "../clip-model-registry-BpS_EthX.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";
@@ -5406,41 +5406,106 @@ var NC_TRACKS_AT_INSTANT_LIMIT = 25;
5406
5406
  */
5407
5407
  var NC_TRACK_LIFE_SLACK_MS = 200;
5408
5408
  /**
5409
+ * A position this close to the instant is drawn as it is: one detection tick,
5410
+ * the same notion as {@link NC_TRACK_LIFE_SLACK_MS}. Anything farther is a
5411
+ * position of a MOVED subject, so it is either interpolated (a position on
5412
+ * each side inside the tolerance) or the track is left out — never drawn at a
5413
+ * later place than it was at the picture's instant.
5414
+ */
5415
+ var NC_BOX_EXACT_MS = NC_TRACK_LIFE_SLACK_MS;
5416
+ /** The box at `timestamp`: a near position as is, else the bracketing pair interpolated. */
5417
+ function boxAt(positions, timestamp, toleranceMs) {
5418
+ let nearest = null;
5419
+ let before = null;
5420
+ let after = null;
5421
+ for (const p of positions) {
5422
+ const d = p.timestamp - timestamp;
5423
+ if (nearest === null || Math.abs(d) < Math.abs(nearest.timestamp - timestamp)) nearest = p;
5424
+ if (d <= 0 && (before === null || p.timestamp > before.timestamp)) before = p;
5425
+ if (d >= 0 && (after === null || p.timestamp < after.timestamp)) after = p;
5426
+ }
5427
+ if (nearest === null) return null;
5428
+ const dt = nearest.timestamp - timestamp;
5429
+ if (Math.abs(dt) <= NC_BOX_EXACT_MS) return {
5430
+ bbox: nearest.bbox,
5431
+ score: nearest.score,
5432
+ dtMs: dt,
5433
+ interpolated: false
5434
+ };
5435
+ if (before === null || after === null || timestamp - before.timestamp > toleranceMs || after.timestamp - timestamp > toleranceMs) return null;
5436
+ const span = after.timestamp - before.timestamp;
5437
+ const f = span === 0 ? 0 : (timestamp - before.timestamp) / span;
5438
+ const lerp = (a, b) => a + (b - a) * f;
5439
+ return {
5440
+ bbox: {
5441
+ x: lerp(before.bbox.x, after.bbox.x),
5442
+ y: lerp(before.bbox.y, after.bbox.y),
5443
+ w: lerp(before.bbox.w, after.bbox.w),
5444
+ h: lerp(before.bbox.h, after.bbox.h)
5445
+ },
5446
+ score: nearest.score,
5447
+ dtMs: dt,
5448
+ interpolated: true
5449
+ };
5450
+ }
5451
+ /**
5409
5452
  * Every source track ALIVE at `timestamp` (± {@link NC_TRACK_LIFE_SLACK_MS})
5410
- * with a position within `toleranceMs` of it, its nearest box normalised,
5411
- * deduplicated by track id (a live copy and a persisted copy of one track are
5412
- * one track). Pure.
5453
+ * with a box AT that instant: a trail position within {@link NC_BOX_EXACT_MS},
5454
+ * else the linear interpolation of the positions bracketing it (each within
5455
+ * `toleranceMs`). A track with neither is not drawn — `onDrop` names it.
5456
+ * Deduplicated by track id (a live copy and a persisted copy are one track).
5457
+ * Pure.
5413
5458
  */
5414
- function tracksAtInstant(sources, timestamp, toleranceMs, fallbackDims) {
5459
+ function tracksAtInstant(sources, timestamp, toleranceMs, fallbackDims, onDrop) {
5415
5460
  const out = /* @__PURE__ */ new Map();
5416
5461
  for (const track of sources) {
5417
5462
  if (out.has(track.trackId)) continue;
5418
- if (track.firstSeen > timestamp + NC_TRACK_LIFE_SLACK_MS || track.lastSeen < timestamp - NC_TRACK_LIFE_SLACK_MS) continue;
5463
+ if (track.firstSeen > timestamp + NC_TRACK_LIFE_SLACK_MS || track.lastSeen < timestamp - NC_TRACK_LIFE_SLACK_MS) {
5464
+ onDrop?.({
5465
+ trackId: track.trackId,
5466
+ className: track.className,
5467
+ reason: "outside-life"
5468
+ });
5469
+ continue;
5470
+ }
5419
5471
  const w = track.frameWidth ?? fallbackDims?.w ?? 0;
5420
5472
  const h = track.frameHeight ?? fallbackDims?.h ?? 0;
5421
- if (w <= 0 || h <= 0) continue;
5422
- let best = null;
5423
- let bestDelta = Number.POSITIVE_INFINITY;
5424
- for (const p of track.positions) {
5425
- const delta = Math.abs(p.timestamp - timestamp);
5426
- if (delta < bestDelta) {
5427
- bestDelta = delta;
5428
- best = p;
5429
- }
5473
+ if (w <= 0 || h <= 0) {
5474
+ onDrop?.({
5475
+ trackId: track.trackId,
5476
+ className: track.className,
5477
+ reason: "no-frame-dims"
5478
+ });
5479
+ continue;
5480
+ }
5481
+ const at = boxAt(track.positions, timestamp, toleranceMs);
5482
+ if (at === null) {
5483
+ const nearestDtMs = track.positions.reduce((best, p) => {
5484
+ const d = p.timestamp - timestamp;
5485
+ return best === void 0 || Math.abs(d) < Math.abs(best) ? d : best;
5486
+ }, void 0);
5487
+ onDrop?.({
5488
+ trackId: track.trackId,
5489
+ className: track.className,
5490
+ reason: "no-position-near-instant",
5491
+ ...nearestDtMs !== void 0 ? { nearestDtMs } : {}
5492
+ });
5493
+ continue;
5430
5494
  }
5431
- if (best === null || bestDelta > toleranceMs) continue;
5432
5495
  const label = track.subLabel ?? track.label;
5433
5496
  out.set(track.trackId, {
5434
5497
  trackId: track.trackId,
5435
5498
  className: track.className,
5436
5499
  ...label !== void 0 && label !== track.className ? { label } : {},
5437
- ...best.score !== void 0 ? { confidence: best.score } : {},
5500
+ ...at.score !== void 0 ? { confidence: at.score } : {},
5438
5501
  bbox: {
5439
- x: best.bbox.x / w,
5440
- y: best.bbox.y / h,
5441
- w: best.bbox.w / w,
5442
- h: best.bbox.h / h
5443
- }
5502
+ x: at.bbox.x / w,
5503
+ y: at.bbox.y / h,
5504
+ w: at.bbox.w / w,
5505
+ h: at.bbox.h / h
5506
+ },
5507
+ dtMs: at.dtMs,
5508
+ interpolated: at.interpolated
5444
5509
  });
5445
5510
  }
5446
5511
  return [...out.values()];
@@ -19342,11 +19407,16 @@ var DebugNoteArchiveStore = class {
19342
19407
  };
19343
19408
  //#endregion
19344
19409
  //#region src/pipeline-analytics/store/event-ledger-collection.ts
19410
+ /**
19411
+ * One event ledger (motion, audio, sensor, faces, plates …) over its
19412
+ * `ctx.records` kind. Every node has `ctx.records`, so there is no other path.
19413
+ */
19345
19414
  /** Matches {@link EventStore.LEDGER_PAGE_SIZE} — kept local to avoid a circular import. */
19346
19415
  var LEDGER_PAGE_SIZE = 500;
19347
19416
  var EventLedgerCollection = class EventLedgerCollection {
19348
19417
  collection;
19349
19418
  kind;
19419
+ records;
19350
19420
  autoIntegerId;
19351
19421
  legacyAtField;
19352
19422
  deviceIdMode;
@@ -19362,6 +19432,7 @@ var EventLedgerCollection = class EventLedgerCollection {
19362
19432
  this.logger = deps.logger;
19363
19433
  this.deriveBody = deps.deriveBody;
19364
19434
  this.indexFields = deps.definition.declaration.indexes.map((i) => i.fields);
19435
+ this.records = deps.records;
19365
19436
  const handle = deps.records.kind(deps.definition);
19366
19437
  this.kind = handle;
19367
19438
  }
@@ -19380,6 +19451,31 @@ var EventLedgerCollection = class EventLedgerCollection {
19380
19451
  }
19381
19452
  await this.kind.put(put);
19382
19453
  }
19454
+ /**
19455
+ * `upsertRow` as an op of {@link EventLedgerCollection.transact}. A row that
19456
+ * cannot be mapped THROWS here: inside a transaction a silently skipped write
19457
+ * would let the rest of the call commit without it.
19458
+ */
19459
+ async txUpsert(id, value) {
19460
+ const put = this.buildRecordPut(id, value);
19461
+ if (put === null) throw new InvalidRecordError(`${this.collection}/${id}: the record could not be mapped`);
19462
+ return this.kind.txPut(put);
19463
+ }
19464
+ /** `update` as an op of {@link EventLedgerCollection.transact}. */
19465
+ txUpdate(id, patch) {
19466
+ return this.kind.txPatch(id, this.derived(patch, "patch"));
19467
+ }
19468
+ /** `deleteKey` as an op of {@link EventLedgerCollection.transact}. */
19469
+ txDelete(id) {
19470
+ return this.kind.txDelete(id);
19471
+ }
19472
+ /**
19473
+ * Run ops (built by the `tx*` methods of ledgers whose kinds share a
19474
+ * `transactFamily`) in ONE transaction: all land or none does.
19475
+ */
19476
+ transact(ops) {
19477
+ return this.records.transact(ops);
19478
+ }
19383
19479
  async insert(record) {
19384
19480
  const idNum = this.autoIntegerId ? await this.kind.allocateId() : null;
19385
19481
  const id = idNum !== null ? String(idNum) : typeof record["id"] === "string" ? record["id"] : null;
@@ -22321,8 +22417,9 @@ var RetrainAnnotationStore = class {
22321
22417
  * The old rows' deletion, the new rows, the frame's `dismissed` set and its
22322
22418
  * bumped `revision` run under a per-frame commit lock, guarded by
22323
22419
  * `commit.fromRevision`: a concurrent save in this process leaves one winner
22324
- * and one `conflict` — never a blend. The steps are separate records writes,
22325
- * so a crash between them is NOT rolled back.
22420
+ * and one `conflict` — never a blend. The deletion, the new rows and the frame
22421
+ * row are ONE records `transact` (the four retrain kinds share a family): a
22422
+ * failure leaves the frame exactly as it was.
22326
22423
  *
22327
22424
  * Returns the persisted rows so the caller renders ids it can address.
22328
22425
  */
@@ -22439,21 +22536,14 @@ var RetrainAnnotationStore = class {
22439
22536
  }
22440
22537
  return stamped;
22441
22538
  }
22442
- /** Remove every annotation of a frame — the operator un-selecting it. */
22443
- async deleteForFrame(mediaKey) {
22444
- const rows = await this.listByFrame(mediaKey);
22445
- for (const row of rows) try {
22446
- await this.annotations.deleteKey(row.id);
22447
- } catch (err) {
22448
- this.logger.warn("retrain annotation delete failed", {
22449
- tags: { deviceId: row.deviceId },
22450
- meta: {
22451
- annotationId: row.id,
22452
- error: String(err)
22453
- }
22454
- });
22455
- }
22456
- return rows.length;
22539
+ /**
22540
+ * The delete ops of every annotation of a frame, for ONE transaction with
22541
+ * the frame row and its memberships (RetrainService.removeFrame). A failed
22542
+ * read THROWS: "no annotations" must never be the answer to an unreadable
22543
+ * store, because the frame row would then be deleted over live boxes.
22544
+ */
22545
+ async deleteOpsForFrame(mediaKey) {
22546
+ return (await this.annotations.query({ where: { mediaKey } })).map((row) => this.annotations.txDelete(row.id));
22457
22547
  }
22458
22548
  async replaceForFrameOnRecords(mediaKey, rows, commit, nextRevision) {
22459
22549
  const frame = await this.frames.get(mediaKey);
@@ -22466,12 +22556,14 @@ var RetrainAnnotationStore = class {
22466
22556
  kind: "conflict",
22467
22557
  currentRevision
22468
22558
  };
22469
- await this.annotations.deleteWhere({ where: { mediaKey } });
22470
- for (const row of rows) await this.annotations.upsertRow(row.id, this.toRecord(row));
22471
- await this.frames.update(mediaKey, {
22559
+ const ops = [];
22560
+ for (const existing of await this.annotations.query({ where: { mediaKey } })) ops.push(this.annotations.txDelete(existing.id));
22561
+ for (const row of rows) ops.push(await this.annotations.txUpsert(row.id, this.toRecord(row)));
22562
+ ops.push(await this.frames.txUpdate(mediaKey, {
22472
22563
  revision: nextRevision,
22473
22564
  ...commit.dismissed !== void 0 ? { dismissed: [...commit.dismissed] } : {}
22474
- });
22565
+ }));
22566
+ await this.frames.transact(ops);
22475
22567
  return {
22476
22568
  kind: "saved",
22477
22569
  rows,
@@ -22489,8 +22581,10 @@ var RetrainAnnotationStore = class {
22489
22581
  kind: "conflict",
22490
22582
  currentRevision
22491
22583
  };
22492
- for (const row of eligible) await this.annotations.update(row.id, { origin: origins.get(row.id) ?? null });
22493
- await this.frames.update(mediaKey, { revision: nextRevision });
22584
+ const ops = [];
22585
+ for (const row of eligible) ops.push(await this.annotations.txUpdate(row.id, { origin: origins.get(row.id) ?? null }));
22586
+ ops.push(await this.frames.txUpdate(mediaKey, { revision: nextRevision }));
22587
+ await this.frames.transact(ops);
22494
22588
  return {
22495
22589
  kind: "updated",
22496
22590
  updated: eligible.length,
@@ -22661,16 +22755,16 @@ var RetrainCollectionStore = class {
22661
22755
  }, counts.get(input.id) ?? 0)
22662
22756
  };
22663
22757
  }
22664
- /** Remove the collection and its memberships — members first, so a crash
22665
- * never leaves memberships pointing at a name that no longer exists. */
22758
+ /** Remove the collection and its memberships in ONE transaction: a failure
22759
+ * leaves the collection with all its members, never memberships pointing at
22760
+ * a name that no longer exists, nor a collection that silently lost some. */
22666
22761
  async delete(id) {
22667
22762
  if (await this.readRow(id) === null) return {
22668
22763
  deleted: false,
22669
22764
  memberFrameIds: []
22670
22765
  };
22671
22766
  const members = await this.memberships.query({ where: { collectionId: id } });
22672
- for (const m of members) await this.memberships.deleteKey(m.id);
22673
- await this.collections.deleteKey(id);
22767
+ await this.collections.transact([...members.map((m) => this.memberships.txDelete(m.id)), this.collections.txDelete(id)]);
22674
22768
  this.logger.info("retrain collection deleted", { meta: {
22675
22769
  collectionId: id,
22676
22770
  members: members.length
@@ -22699,11 +22793,29 @@ var RetrainCollectionStore = class {
22699
22793
  await this.memberships.deleteKey(key);
22700
22794
  return true;
22701
22795
  }
22702
- /** Remove a frame from EVERY collection — the frame itself is leaving. */
22703
- async forgetFrame(frameId) {
22704
- const rows = await this.membershipRows({ frameId });
22705
- for (const r of rows) await this.memberships.deleteKey(r.id);
22706
- return rows.length;
22796
+ /**
22797
+ * The delete ops of every membership of a frame, for ONE transaction with
22798
+ * the frame row and its annotations (RetrainService.removeFrame). A failed
22799
+ * read THROWS: the frame row must not be deleted over memberships nobody
22800
+ * could list.
22801
+ */
22802
+ async forgetFrameOps(frameId) {
22803
+ return (await this.memberships.query({ where: { frameId } })).map((r) => this.memberships.txDelete(r.id));
22804
+ }
22805
+ /**
22806
+ * The op that adds a frame to a collection, for ONE transaction with the
22807
+ * frame's own row (a still stored from the recording). `null` when it is
22808
+ * already a member: there is nothing to write.
22809
+ */
22810
+ async addFrameOp(input) {
22811
+ const key = membershipKey(input.collectionId, input.frameId);
22812
+ if (await this.memberships.get(key) !== null) return null;
22813
+ return this.memberships.txUpsert(key, {
22814
+ collectionId: input.collectionId,
22815
+ frameId: input.frameId,
22816
+ deviceId: input.deviceId,
22817
+ addedAt: this.now()
22818
+ });
22707
22819
  }
22708
22820
  /** The frames of a collection, in the order they were added. */
22709
22821
  async listFrameIds(collectionId) {
@@ -23295,7 +23407,7 @@ var RetrainFrameStore = class {
23295
23407
  * returned untouched; the blob lands before the row; a refusal is named.
23296
23408
  * `capturedAt` IS the instant — the camera saw this frame then.
23297
23409
  */
23298
- async storeRecordingStill(input) {
23410
+ async storeRecordingStill(input, withRow = []) {
23299
23411
  const frameId = recordingFrameId(input.deviceId, input.epochMs);
23300
23412
  const existing = await this.get(frameId);
23301
23413
  if (existing !== null) return {
@@ -23342,7 +23454,7 @@ var RetrainFrameStore = class {
23342
23454
  relativePath: path,
23343
23455
  data: input.bytes
23344
23456
  });
23345
- await this.ledger.upsertRow(frameId, {
23457
+ const row = await this.ledger.txUpsert(frameId, {
23346
23458
  deviceId: frame.deviceId,
23347
23459
  trackId: "",
23348
23460
  sourceMediaId: 0,
@@ -23359,6 +23471,7 @@ var RetrainFrameStore = class {
23359
23471
  origin: "recording",
23360
23472
  epochMs: input.epochMs
23361
23473
  });
23474
+ await this.ledger.transact([row, ...withRow]);
23362
23475
  };
23363
23476
  try {
23364
23477
  if (this.writeGate) await this.writeGate.run(persist);
@@ -23412,22 +23525,33 @@ var RetrainFrameStore = class {
23412
23525
  /**
23413
23526
  * Drop a copy and its blob — the operator un-selecting a frame.
23414
23527
  *
23415
- * The caller must have removed the frame's annotations first; this store does
23416
- * not cascade, because a store that deletes rows in another table on a
23417
- * best-effort write is how a half-deleted annotation set happens.
23528
+ * The ROW goes first, in one transaction with `withRow` (the frame's
23529
+ * annotations and collection memberships, which the caller builds): a failure
23530
+ * leaves the frame, its boxes and its memberships all in place, and throws.
23531
+ * The blob goes after: if that fails the row is already gone and the bytes
23532
+ * are reclaimable junk, logged, never a row pointing at missing media.
23418
23533
  */
23419
- async deleteFrame(frame) {
23534
+ async deleteFrame(frame, withRow = []) {
23420
23535
  const remove = async () => {
23536
+ try {
23537
+ await this.ledger.transact([...withRow, this.ledger.txDelete(frame.frameId)]);
23538
+ } catch (err) {
23539
+ this.logger.error("retrain frame delete failed; nothing was removed", {
23540
+ tags: { deviceId: frame.deviceId },
23541
+ meta: {
23542
+ frameId: frame.frameId,
23543
+ error: String(err)
23544
+ }
23545
+ });
23546
+ throw err;
23547
+ }
23421
23548
  try {
23422
23549
  await this.storage.delete({
23423
23550
  location: frame.locationId ?? LEGACY_RETRAIN_MEDIA_LOCATION,
23424
23551
  relativePath: framePath(frame)
23425
23552
  });
23426
- } catch {}
23427
- try {
23428
- await this.ledger.deleteKey(frame.frameId);
23429
23553
  } catch (err) {
23430
- this.logger.warn("RetrainFrameStore.deleteFrame row delete failed", {
23554
+ this.logger.warn("retrain frame removed but its blob could not be deleted", {
23431
23555
  tags: { deviceId: frame.deviceId },
23432
23556
  meta: {
23433
23557
  frameId: frame.frameId,
@@ -28405,7 +28529,9 @@ function incomingFromSystemEvent(event, lookup) {
28405
28529
  const blindForMs = numberField(data, "blindForMs");
28406
28530
  if (deviceId === void 0 || blindForMs === void 0) return null;
28407
28531
  const identity = lookup(deviceId);
28408
- const minutes = Math.max(1, Math.round(blindForMs / 6e4));
28532
+ const motionMs = numberField(data, "motionMs") ?? blindForMs;
28533
+ const sessions = numberField(data, "sessions") ?? 1;
28534
+ const minutes = Math.max(1, Math.round(motionMs / 6e4));
28409
28535
  return systemSubject({
28410
28536
  facts,
28411
28537
  kind: "detection-blind",
@@ -28414,13 +28540,39 @@ function incomingFromSystemEvent(event, lookup) {
28414
28540
  bodyKey: "system.detection-blind.body",
28415
28541
  textParams: {
28416
28542
  ...deviceTextParams(deviceId, identity),
28417
- minutes: String(minutes)
28543
+ minutes: String(minutes),
28544
+ sessions: String(sessions)
28418
28545
  },
28419
28546
  textCount: minutes,
28420
28547
  deviceId,
28421
28548
  ...identity !== void 0 ? { deviceType: identity.type } : {}
28422
28549
  });
28423
28550
  }
28551
+ case "pipeline.motion-noisy":
28552
+ case "pipeline.motion-calm": {
28553
+ const deviceId = numberField(data, "deviceId");
28554
+ const dutyPct = numberField(data, "dutyPct");
28555
+ const sessions = numberField(data, "sessions");
28556
+ const windowMs = numberField(data, "windowMs");
28557
+ if (deviceId === void 0 || dutyPct === void 0 || sessions === void 0 || windowMs === void 0) return null;
28558
+ const noisy = event.category === "pipeline.motion-noisy";
28559
+ const identity = lookup(deviceId);
28560
+ return systemSubject({
28561
+ facts,
28562
+ kind: noisy ? "motion-noisy" : "motion-calm",
28563
+ subject: `motion-noise:${deviceId}`,
28564
+ titleKey: noisy ? "system.motion-noisy.title" : "system.motion-calm.title",
28565
+ bodyKey: noisy ? "system.motion-noisy.body" : "system.motion-calm.body",
28566
+ textParams: {
28567
+ ...deviceTextParams(deviceId, identity),
28568
+ minutes: String(Math.max(1, Math.round(windowMs / 6e4))),
28569
+ duty: String(dutyPct),
28570
+ sessions: String(sessions)
28571
+ },
28572
+ deviceId,
28573
+ ...identity !== void 0 ? { deviceType: identity.type } : {}
28574
+ });
28575
+ }
28424
28576
  case "recording.health.stalled": {
28425
28577
  const deviceId = numberField(data, "deviceId");
28426
28578
  const idleMs = numberField(data, "idleMs");
@@ -28538,7 +28690,7 @@ function incomingFromSystemEvent(event, lookup) {
28538
28690
  case "system.restarting": return incomingFromNodeRestarting(facts, data);
28539
28691
  case "recording.export.completed": return incomingFromExportCompleted(facts, data);
28540
28692
  case "backup.run-completed": return incomingFromBackupCompleted(facts, data);
28541
- case "alert.episode": return incomingFromAlertEpisode(facts);
28693
+ case "alert.episode": return incomingFromAlertEpisode(facts, lookup);
28542
28694
  default: return null;
28543
28695
  }
28544
28696
  }
@@ -28554,9 +28706,11 @@ function incomingFromSystemEvent(event, lookup) {
28554
28706
  * Whether an edge is notified at all (once per episode, reconciled from the
28555
28707
  * alerts store) is decided before this point, by `NcAlertEpisodeLedger`.
28556
28708
  */
28557
- function incomingFromAlertEpisode(facts) {
28709
+ function incomingFromAlertEpisode(facts, lookup) {
28558
28710
  const payload = parseAlertEpisodePayload(facts.data);
28559
28711
  if (payload === null) return null;
28712
+ const attention = incomingFromDeviceAttention(facts, payload, lookup);
28713
+ if (attention !== null) return attention;
28560
28714
  const kind = alertEpisodeKind(payload.severity, payload.phase);
28561
28715
  if (kind === null) return null;
28562
28716
  return systemSubject({
@@ -28577,6 +28731,38 @@ function incomingFromAlertEpisode(facts) {
28577
28731
  ...payload.nodeId !== void 0 ? { nodeId: payload.nodeId } : {}
28578
28732
  });
28579
28733
  }
28734
+ /**
28735
+ * A CRITICAL alert whose source is a DEVICE (D911) is announced in the devices
28736
+ * family — `device-attention-required` / `-resolved`, carrying the device id so
28737
+ * a rule's device filters apply — and NOT as `alert-critical`, so one alert
28738
+ * never notifies twice through two families. A device source whose id is not a
28739
+ * device id falls through to the generic alert kinds.
28740
+ */
28741
+ function incomingFromDeviceAttention(facts, payload, lookup) {
28742
+ if (payload.sourceType !== "device" || payload.sourceId === void 0) return null;
28743
+ const kind = deviceAttentionKind(payload.severity, payload.phase);
28744
+ if (kind === null) return null;
28745
+ const deviceId = Number(payload.sourceId);
28746
+ if (!Number.isInteger(deviceId)) return null;
28747
+ const identity = lookup?.(deviceId);
28748
+ return systemSubject({
28749
+ facts,
28750
+ kind,
28751
+ subject: `alert:${payload.episodeId}`,
28752
+ titleKey: `system.${kind}.title`,
28753
+ bodyKey: `system.${kind}.body`,
28754
+ textParams: {
28755
+ ...deviceTextParams(deviceId, identity),
28756
+ title: payload.title,
28757
+ message: payload.message,
28758
+ category: payload.category,
28759
+ actionUrl: payload.actionUrl ?? ""
28760
+ },
28761
+ deviceId,
28762
+ ...identity !== void 0 ? { deviceType: identity.type } : {},
28763
+ ...payload.nodeId !== void 0 ? { nodeId: payload.nodeId } : {}
28764
+ });
28765
+ }
28580
28766
  /** The shells whose update has its own sentence. Anything else gets the plain
28581
28767
  * one: a body that names a shell nobody observed is worse than a vague body. */
28582
28768
  var WRAPPER_BODY_KINDS = new Set([
@@ -30567,9 +30753,13 @@ var en_default = {
30567
30753
  "system.addon-crash-loop.body": "The {{addons}} addon on node {{nodeId}} crashed {{count}} times in a row and will NOT be restarted. Everything it provides is offline until it is repaired.",
30568
30754
  "system.detection-blind.title": "Detecting nothing — {{deviceName}}",
30569
30755
  "system.detection-blind.body": {
30570
- "one": "Camera {{deviceName}} has been analysed for {{minutes}} minute with no detection at all",
30571
- "other": "Camera {{deviceName}} has been analysed for {{minutes}} minutes with no detection at all"
30756
+ "one": "Camera {{deviceName}} moved for {{minutes}} minute over {{sessions}} sessions and the detector produced nothing at all, not even a weak candidate",
30757
+ "other": "Camera {{deviceName}} moved for {{minutes}} minutes over {{sessions}} sessions and the detector produced nothing at all, not even a weak candidate"
30572
30758
  },
30759
+ "system.motion-noisy.title": "Constant motion, no subject — {{deviceName}}",
30760
+ "system.motion-noisy.body": "Camera {{deviceName}} has been in motion {{duty}}% of the last {{minutes}} minutes ({{sessions}} sessions) without a single detection. The detector is fine — tune this camera's motion zones or sensitivity.",
30761
+ "system.motion-calm.title": "Motion calm again — {{deviceName}}",
30762
+ "system.motion-calm.body": "Camera {{deviceName}} is no longer in constant motion ({{duty}}% of the last {{minutes}} minutes, {{sessions}} sessions)",
30573
30763
  "system.recording-stalled.title": "Recording stalled — {{deviceName}}",
30574
30764
  "system.recording-stalled.body": {
30575
30765
  "one": "Camera {{deviceName}} has not written a recording segment for {{minutes}} minute",
@@ -30579,6 +30769,10 @@ var en_default = {
30579
30769
  "system.recording-healthy.body": "Camera {{deviceName}} is writing recording segments again",
30580
30770
  "system.recording-degraded.title": "Recording degraded — {{deviceName}}",
30581
30771
  "system.recording-degraded.body": "Camera {{deviceName}} exhausted its writer restart budget ({{message}})",
30772
+ "system.device-attention-required.title": "{{title}}",
30773
+ "system.device-attention-required.body": "{{message}}",
30774
+ "system.device-attention-resolved.title": "Resolved: {{title}}",
30775
+ "system.device-attention-resolved.body": "{{deviceName}} no longer needs attention",
30582
30776
  "system.storage-location-low.title": "Storage low — {{locationName}}",
30583
30777
  "system.storage-location-low.body": "Location {{locationName}} is down to {{freePercent}}% free ({{reason}})",
30584
30778
  "system.storage-location-critical.title": "Storage critical — {{locationName}}",
@@ -30967,6 +31161,10 @@ var it_default = {
30967
31161
  "system.recording-healthy.body": "La camera {{deviceName}} scrive di nuovo i segmenti",
30968
31162
  "system.recording-degraded.title": "Registrazione degradata — {{deviceName}}",
30969
31163
  "system.recording-degraded.body": "La camera {{deviceName}} ha esaurito i riavvii del writer ({{message}})",
31164
+ "system.device-attention-required.title": "{{title}}",
31165
+ "system.device-attention-required.body": "{{message}}",
31166
+ "system.device-attention-resolved.title": "Risolto: {{title}}",
31167
+ "system.device-attention-resolved.body": "{{deviceName}} non richiede più intervento",
30970
31168
  "system.storage-location-low.title": "Storage basso — {{locationName}}",
30971
31169
  "system.storage-location-low.body": "La location {{locationName}} è al {{freePercent}}% libero ({{reason}})",
30972
31170
  "system.storage-location-critical.title": "Storage critico — {{locationName}}",
@@ -30975,9 +31173,13 @@ var it_default = {
30975
31173
  "system.storage-location-ok.body": "La location {{locationName}} ha recuperato spazio libero",
30976
31174
  "system.detection-blind.title": "Senza detection — {{deviceName}}",
30977
31175
  "system.detection-blind.body": {
30978
- "one": "La camera {{deviceName}} è analizzata da {{minutes}} minuto senza alcun rilevamento",
30979
- "other": "La camera {{deviceName}} è analizzata da {{minutes}} minuti senza alcun rilevamento"
31176
+ "one": "La camera {{deviceName}} ha avuto movimento per {{minutes}} minuto in {{sessions}} sessioni e il detector non ha prodotto nulla, nemmeno un candidato debole",
31177
+ "other": "La camera {{deviceName}} ha avuto movimento per {{minutes}} minuti in {{sessions}} sessioni e il detector non ha prodotto nulla, nemmeno un candidato debole"
30980
31178
  },
31179
+ "system.motion-noisy.title": "Movimento continuo senza soggetto — {{deviceName}}",
31180
+ "system.motion-noisy.body": "La camera {{deviceName}} è stata in movimento il {{duty}}% degli ultimi {{minutes}} minuti ({{sessions}} sessioni) senza alcun rilevamento. Il detector funziona — regola le zone di movimento o la sensibilità di questa camera.",
31181
+ "system.motion-calm.title": "Movimento di nuovo calmo — {{deviceName}}",
31182
+ "system.motion-calm.body": "La camera {{deviceName}} non è più in movimento continuo ({{duty}}% degli ultimi {{minutes}} minuti, {{sessions}} sessioni)",
30981
31183
  "system.addon-update-available.title": {
30982
31184
  "one": "{{count}} aggiornamento addon disponibile",
30983
31185
  "other": "{{count}} aggiornamenti addon disponibili"
@@ -33537,6 +33739,7 @@ function systemEventSubject(kind, scope) {
33537
33739
  if (kind === "node-online" || kind === "node-offline") return `node:${scope.nodeId ?? "hub"}`;
33538
33740
  if (kind === "node-inference-unavailable") return `node-inference:${scope.nodeId ?? "hub"}`;
33539
33741
  if (kind === "detection-blind") return `detection-blind:${scope.deviceId ?? 0}`;
33742
+ if (kind === "motion-noisy" || kind === "motion-calm") return `motion-noise:${scope.deviceId ?? 0}`;
33540
33743
  if (kind === "addon-crash-loop") return `addon-crash:${scope.nodeId ?? "hub"}:${TEST_CRASHED_RUNNER}`;
33541
33744
  if (kind === "addon-update-available" || kind === "server-update-available") return `package:${scope.packageName ?? "@camstack/server"}`;
33542
33745
  if (kind === "wrapper-update-available") return `wrapper:${scope.nodeId ?? "hub"}`;
@@ -33682,6 +33885,8 @@ function planRuleTest(input) {
33682
33885
  seconds: "30",
33683
33886
  devices: "cuda:0",
33684
33887
  minutes: "15",
33888
+ duty: "55",
33889
+ sessions: "96",
33685
33890
  addons: TEST_CRASHED_RUNNER,
33686
33891
  list: "@camstack/addon-pipeline 1.0.1 (current 1.0.0)",
33687
33892
  nodes: "hub",
@@ -40324,7 +40529,17 @@ var NcNotificationImageStage = class {
40324
40529
  ...subjectBox,
40325
40530
  label: imageLabelText(payload.subject.label ?? payload.subject.className, payload.subject.confidence)
40326
40531
  } : null;
40327
- const others = mode === "scene-boxes" ? otherTracks(await this.tracksAt(camera, source.timestamp), subjectTrackId, subjectBox, payload.subject.className).map((t) => ({
40532
+ const othersDrawn = mode === "scene-boxes" ? otherTracks(await this.tracksAt(camera, source.timestamp), subjectTrackId, subjectBox, payload.subject.className) : [];
40533
+ if (mode === "scene-boxes") this.deps.logger.info("scene-boxes: other boxes drawn", {
40534
+ tags: { deviceId: camera },
40535
+ meta: {
40536
+ ruleId: entry.ruleId,
40537
+ recordId: entry.recordId,
40538
+ instant: source.timestamp,
40539
+ drawn: othersDrawn.map((t) => `${t.trackId}/${t.className}/dt=${t.dtMs ?? "?"}ms/${t.interpolated === true ? "interpolated" : "exact"}`).join(",")
40540
+ }
40541
+ });
40542
+ const others = mode === "scene-boxes" ? othersDrawn.map((t) => ({
40328
40543
  ...t.bbox,
40329
40544
  label: imageLabelText(t.label ?? t.className, t.confidence),
40330
40545
  ...t.confidence !== void 0 ? { confidence: t.confidence } : {}
@@ -87637,7 +87852,12 @@ var RetrainCollectionService = class {
87637
87852
  reason: "unknown-collection"
87638
87853
  };
87639
87854
  }
87640
- const stored = await this.storeStill(input.deviceId, input.epochMs);
87855
+ const membershipOp = await this.deps.collections.addFrameOp({
87856
+ collectionId: input.collectionId,
87857
+ frameId: recordingFrameId(input.deviceId, input.epochMs),
87858
+ deviceId: input.deviceId
87859
+ });
87860
+ const stored = await this.storeStill(input.deviceId, input.epochMs, membershipOp === null ? [] : [membershipOp]);
87641
87861
  if (stored.kind === "refused") {
87642
87862
  this.deps.logger.info("retrain collection add refused", {
87643
87863
  tags,
@@ -87649,7 +87869,7 @@ var RetrainCollectionService = class {
87649
87869
  });
87650
87870
  return stored;
87651
87871
  }
87652
- await this.deps.collections.addFrame({
87872
+ if (stored.reused) await this.deps.collections.addFrame({
87653
87873
  collectionId: input.collectionId,
87654
87874
  frameId: stored.frame.frameId,
87655
87875
  deviceId: input.deviceId
@@ -87714,7 +87934,7 @@ var RetrainCollectionService = class {
87714
87934
  const ids = await this.deps.collections.listFrameIds(input.collectionId);
87715
87935
  return this.deps.retrain.toWireFrames(await this.deps.frames.getMany(ids));
87716
87936
  }
87717
- async storeStill(deviceId, epochMs) {
87937
+ async storeStill(deviceId, epochMs, withRow) {
87718
87938
  const existing = await this.deps.frames.get(recordingFrameId(deviceId, epochMs));
87719
87939
  if (existing !== null) return {
87720
87940
  kind: "stored",
@@ -87734,7 +87954,7 @@ var RetrainCollectionService = class {
87734
87954
  deviceId,
87735
87955
  epochMs,
87736
87956
  bytes: still.jpeg
87737
- });
87957
+ }, withRow);
87738
87958
  return stored.kind === "copied" ? {
87739
87959
  kind: "stored",
87740
87960
  frame: stored.frame,
@@ -90057,9 +90277,9 @@ var RetrainService = class {
90057
90277
  ...this.frameUrls(updated.frameId)
90058
90278
  };
90059
90279
  }
90060
- /** Un-select: annotations first, then the copy. Never the other way round —
90061
- * an annotation whose frame is gone is unopenable and unfixable. The frame's
90062
- * collection memberships go with it. */
90280
+ /** Un-select: the frame row, its annotations and its collection memberships
90281
+ * leave in one transaction (an annotation whose frame is gone is unopenable
90282
+ * and unfixable, so they never part); the blob is deleted after the row. */
90063
90283
  async deselectFrame(input) {
90064
90284
  const frame = await this.deps.frames.get(input.frameId);
90065
90285
  if (frame === null) {
@@ -90078,11 +90298,16 @@ var RetrainService = class {
90078
90298
  removedAnnotations: await this.removeFrame(frame)
90079
90299
  };
90080
90300
  }
90081
- /** Remove a frame from the dataset: annotations, memberships, then the copy. */
90301
+ /**
90302
+ * Remove a frame from the dataset. The frame row, its annotations and its
90303
+ * collection memberships leave in ONE transaction (a failure removes nothing
90304
+ * and throws); the blob is deleted after the row, never before.
90305
+ */
90082
90306
  async removeFrame(frame) {
90083
- const removedAnnotations = await this.deps.annotations.deleteForFrame(frame.frameId);
90084
- await this.deps.memberships?.forgetFrame(frame.frameId);
90085
- await this.deps.frames.deleteFrame(frame);
90307
+ const annotationOps = await this.deps.annotations.deleteOpsForFrame(frame.frameId);
90308
+ const membershipOps = await this.deps.memberships?.forgetFrameOps(frame.frameId) ?? [];
90309
+ await this.deps.frames.deleteFrame(frame, [...annotationOps, ...membershipOps]);
90310
+ const removedAnnotations = annotationOps.length;
90086
90311
  this.deps.logger.info("retrain frame removed from the dataset", {
90087
90312
  tags: { deviceId: frame.deviceId },
90088
90313
  meta: {
@@ -90276,7 +90501,8 @@ var RetrainService = class {
90276
90501
  * The guarded replace. A caller that names the revision it saw gets exactly
90277
90502
  * one attempt: a different current revision is a conflict, never a retry —
90278
90503
  * the point is that it must look again. A caller that names none asked for
90279
- * last-write-wins, so a race lost between our read and the transaction is
90504
+ * last-write-wins, so a race lost between our revision read and the records
90505
+ * `transact` that commits the save (a per-frame lock serialises the two) is
90280
90506
  * retried on the fresh revision, a bounded number of times.
90281
90507
  */
90282
90508
  async replaceGuarded(frame, input, drafts, dismissed) {
@@ -103903,6 +104129,8 @@ var NC_SYSTEM_EVENT_CATEGORIES = [
103903
104129
  EventCategory.WorkerOffline,
103904
104130
  EventCategory.PipelineNodeInferenceUnavailable,
103905
104131
  EventCategory.PipelineDetectionBlind,
104132
+ EventCategory.PipelineMotionNoisy,
104133
+ EventCategory.PipelineMotionCalm,
103906
104134
  EventCategory.RecordingHealthStalled,
103907
104135
  EventCategory.RecordingHealthOk,
103908
104136
  EventCategory.RecordingHealthDegraded,
@@ -106921,6 +107149,18 @@ Object.freeze({
106921
107149
  "empty"
106922
107150
  ]
106923
107151
  },
107152
+ {
107153
+ "path": "filterCleaningDue",
107154
+ "valueType": "boolean"
107155
+ },
107156
+ {
107157
+ "path": "machineCareDue",
107158
+ "valueType": "boolean"
107159
+ },
107160
+ {
107161
+ "path": "machineCareRemainingRuns",
107162
+ "valueType": "number"
107163
+ },
106924
107164
  {
106925
107165
  "path": "halfLoad",
106926
107166
  "valueType": "boolean"
@@ -116215,7 +116455,16 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
116215
116455
  since: timestamp - toleranceMs,
116216
116456
  limit: NC_TRACKS_AT_INSTANT_LIMIT
116217
116457
  });
116218
- return tracksAtInstant([...live, ...persisted.tracks], timestamp, toleranceMs, this.lastFrameDimsByDevice.get(deviceId));
116458
+ return tracksAtInstant([...live, ...persisted.tracks], timestamp, toleranceMs, this.lastFrameDimsByDevice.get(deviceId), (drop) => this.ctx.logger.info("scene-boxes: other track not drawn", {
116459
+ tags: { deviceId },
116460
+ meta: {
116461
+ trackId: drop.trackId,
116462
+ className: drop.className,
116463
+ reason: drop.reason,
116464
+ instant: timestamp,
116465
+ ...drop.nearestDtMs !== void 0 ? { nearestDtMs: drop.nearestDtMs } : {}
116466
+ }
116467
+ }));
116219
116468
  },
116220
116469
  getDeviceName,
116221
116470
  getDeviceLocation,