@camstack/types 1.2.279 → 1.2.281

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.
@@ -88,8 +88,8 @@ export { type IOauthIntegrationProvider, type OauthIntegrationDescriptor, OauthI
88
88
  export { AnalyticsLtsSeriesSchema, type AudioEvent, type AudioEventDraft, AudioEventSchema, type DetectionSource, DetectionSourceSchema, EVENT_DENSITY_BATCH_MAX, type EventDensityBucket, EventDensityBucketSchema, type EventDensityForDevice, EventDensityForDeviceSchema, type EventKind, type EventKindCategory, EventKindCategorySchema, type EventKindDescriptor, EventKindDescriptorSchema, type EventKindIcon, EventKindIconSchema, EventKindSchema, type EventKindsForDevice, EventKindsForDeviceSchema, type EventMediaKindBreakdown, type EventMediaKindFootprint, type EventPruneCounts, type EventStoreDeviceFootprint, type EventStoreFootprint, type IPipelineAnalyticsProvider, type KeyEvent, KeyEventSchema, type KeyEventsForDevice, type LabelAttribution, LabelAttributionSchema, type LabelTier, LabelTierSchema, LTS_SCOPE_CLASS_SEPARATOR, type LtsBucket, LtsBucketSchema, MAX_TRACK_DEBUG_NOTE_LEN, type MediaFile, type MediaFileBytes, type MediaFileInfo, MediaFileInfoSchema, type MediaFileKind, MediaFileKindEnum, type MediaFileRef, MediaFileRefSchema, MediaFileSchema, type MotionEvent, type MotionEventDraft, MotionEventSchema, type ObjectEvent, type ObjectEventDraft, ObjectEventSchema, occupancyScope, parseOccupancyScope, pipelineAnalyticsCapability, type RecentTracksPage, RecentTracksPageSchema, type RecentTracksQuery, RecentTracksQueryInput, type RetrainAnnotation, type RetrainAnnotationDraft, RetrainAnnotationDraftSchema, RetrainAnnotationKindSchema, RetrainAnnotationSchema, RetrainAnnotationSourceSchema, type RetrainAssistResult, RetrainAssistResultSchema, RetrainAssistSubjectSchema, RetrainCopyRefusalSchema, type RetrainFrame, type RetrainFrameCandidate, RetrainFrameCandidateSchema, type RetrainFrameList, RetrainFrameListSchema, RetrainFrameSchema, type RetrainFrameSelection, RetrainFrameSelectionSchema, type RetrainMacroClass, RetrainMacroClassSchema, type RetrainStatus, RetrainStatusSchema, type RetrainTrack, RetrainTrackSchema, type RetrainTransitionResult, RetrainTransitionResultSchema, type RebuildObjectEmbeddingsRefusal, RebuildObjectEmbeddingsRefusalSchema, type ScoredObjectEvent, ScoredObjectEventSchema, type SensorEvent, SensorEventSchema, type Track, type TrackCascadeCounts, TrackCascadeCountsSchema, type TrackEnvelope, TrackEnvelopeSchema, TrackedDetectionSchema, type TrackFlags, type TrackFlagsPatch, TrackFlagsPatchSchema, TrackFlagsSchema, type TrackProjection, TrackProjectionSchema, TrackSchema, type TrackSource, TrackSourceSchema, type TrackState, TrackStateSchema, type TrackZoneFilter, TrackZoneFilterSchema, type TrainingExportDeviceTotals, TrainingExportDeviceTotalsSchema, type TrainingExportSummary, TrainingExportSummarySchema, type ZoneCrossing, type ZoneCrossingDirection, ZoneCrossingDirectionSchema, ZoneCrossingSchema, } from './pipeline-analytics.cap.js';
89
89
  export type { EffectiveTuning, EffectiveTuningInput, NativeCropRef, PipelineStepInputOutput, PipelineValidationIssue, PipelineValidationResult, } from './pipeline-executor.cap.js';
90
90
  export { EffectiveTuningSchema, ModelSubstitutionSchema, NativeCropRefSchema, PipelineDefaultStepSchema, PipelineEngineChoiceSchema, PipelineRunResultBridge, PipelineStepInputSchema, PipelineValidationIssueSchema, PipelineValidationResultSchema, pipelineExecutorCapability, } from './pipeline-executor.cap.js';
91
- export type { CameraAssignmentStatus, CameraAudioStatus, CameraBrokerProfile, CameraBrokerStatus, CameraDecoderShm, CameraDecoderStatus, CameraDetectionPhase, CameraDetectionProvisioning, CameraDetectionProvisioningState, CameraDetectionStatus, CameraMotionStatus, CameraRecordingMode, CameraRecordingStatus, CameraSourceStatus, CameraSourceStream, CameraStatus, CameraStatusDegradation, CameraStatusDegradationReason, CameraStatusStage, ClusterModelChoice, ClusterModelChoiceUnreadableReason, DiskReconcileJob, InferenceDeviceExclusionReason, IngestOwner, NodeInferenceDevice, NodeInferenceDevices, SetCameraSensorsInput, } from './pipeline-orchestrator.cap.js';
92
- export { AgentLoadSummarySchema, CLUSTER_MODEL_CHOICE_UNREADABLE_REASONS, ClusterModelChoiceSchema, CameraAssignmentStatusSchema, CameraAudioStatusSchema, CameraBrokerProfileSchema, CameraBrokerStatusSchema, CameraDecoderShmSchema, CameraDecoderStatusSchema, CameraDetectionPhaseSchema, CameraDetectionProvisioningSchema, CameraDetectionProvisioningStateSchema, CameraDetectionStatusSchema, CameraMotionStatusSchema, CameraRecordingModeSchema, CameraRecordingStatusSchema, CameraSourceStatusSchema, CameraSourceStreamSchema, CameraStatusDegradationReasonSchema, CameraStatusDegradationSchema, CameraStatusSchema, CameraStatusStageSchema, CapabilityBindingsSchema, DiskReconcileJobSchema, GlobalMetricsSchema, INFERENCE_DEVICE_EXCLUSION_REASONS, InferenceDeviceExclusionReasonSchema, IngestOwnerSchema, PipelineAssignmentSchema, pipelineOrchestratorCapability, SetCameraSensorsInputSchema, } from './pipeline-orchestrator.cap.js';
91
+ export type { CameraAssignmentStatus, CameraAudioStatus, CameraBrokerProfile, CameraBrokerStatus, CameraDecoderShm, CameraDecoderStatus, CameraDetectionPhase, CameraDetectionProvisioning, CameraDetectionProvisioningState, CameraDetectionStatus, CameraMotionStatus, CameraRecordingMode, CameraRecordingStatus, CameraSourceStatus, CameraSourceStream, CameraStatus, CameraStatusDegradation, CameraStatusDegradationReason, CameraStatusStage, ClusterModelChoice, ClusterModelChoiceUnreadableReason, DiskReconcileJob, InferenceDeviceExclusionReason, IngestOwner, NodeInferenceDevice, NodeInferenceDevices, OccupancyLookAnswer, OccupancyLookRefusal, OccupancyLookRequest, SetCameraSensorsInput, } from './pipeline-orchestrator.cap.js';
92
+ export { AgentLoadSummarySchema, CLUSTER_MODEL_CHOICE_UNREADABLE_REASONS, ClusterModelChoiceSchema, CameraAssignmentStatusSchema, CameraAudioStatusSchema, CameraBrokerProfileSchema, CameraBrokerStatusSchema, CameraDecoderShmSchema, CameraDecoderStatusSchema, CameraDetectionPhaseSchema, CameraDetectionProvisioningSchema, CameraDetectionProvisioningStateSchema, CameraDetectionStatusSchema, CameraMotionStatusSchema, CameraRecordingModeSchema, CameraRecordingStatusSchema, CameraSourceStatusSchema, CameraSourceStreamSchema, CameraStatusDegradationReasonSchema, CameraStatusDegradationSchema, CameraStatusSchema, CameraStatusStageSchema, CapabilityBindingsSchema, DiskReconcileJobSchema, GlobalMetricsSchema, INFERENCE_DEVICE_EXCLUSION_REASONS, InferenceDeviceExclusionReasonSchema, IngestOwnerSchema, OccupancyLookAnswerSchema, OccupancyLookRefusalSchema, OccupancyLookRequestSchema, PipelineAssignmentSchema, pipelineOrchestratorCapability, SetCameraSensorsInputSchema, } from './pipeline-orchestrator.cap.js';
93
93
  export type { DetailParent, DetailResult, MotionSource, MotionSources, OccupancyBurstRefusal, ParkedFrameKind, ParkedTrackFrame, ParkRefusal, ParkTrackFrameResult, ReportMotionInput, RunDetailSubtreeInput, RunDetailSubtreeResult, RunnerFrameSource, RunnerInferenceDevice, RunnerJumpStepProvisioning, RunStatelessStepInput, RunStatelessStepResult, StatelessStepRefusal, } from './pipeline-runner.cap.js';
94
94
  export { type DetectionSources, DetectionSourcesSchema, FrameLazyCountersSchema, FrameLazyMetricsSchema, MOTION_SOURCE_LABELS, MotionSourceEnum, MotionSourcesSchema, motionSourceLabel, type NativeCropBbox, NativeCropBboxSchema, NativeCropResultSchema, OccupancyBurstRefusalSchema, ParkedFrameKindSchema, ParkedTrackFrameSchema, ParkRefusalSchema, ParkTrackFrameResultSchema, pipelineRunnerCapability, ReportMotionInputSchema, RunnerCameraConfigSchema, RunnerCameraDeviceUIFields, RunnerFrameSourceSchema, RunnerInferenceDeviceSchema, RunnerJumpStepProvisioningSchema, RunnerLocalLoadSchema, RunnerLocalMetricsSchema, } from './pipeline-runner.cap.js';
95
95
  export { AUDIO_NOT_CLASSIFIED_REASONS, AudioChunkInputSchema, AudioClassificationLabelSchema, AudioClassifyOutcomeSchema, AudioLevelSchema, BoundingBoxSchema, FrameInputSchema, SpatialDetectionSchema, } from './schemas/detection-shared.js';
@@ -890,10 +890,12 @@ export type NcMediaPolicy = z.infer<typeof NcMediaPolicySchema>;
890
890
  /**
891
891
  * Cooldown GRANULARITY over the subject's class — how much a fired
892
892
  * notification suppresses.
893
- * - `shared` (default, and the absent value) — one window for the whole
894
- * rule/scope: a cat silences the next dog for `cooldownSec`.
895
- * - `per-class` — an independent window per detected class, so cat→dog fires
896
- * at once and cat→cat still waits.
893
+ * - `per-class` (default, and the absent value since 2026-10-01 — D36) — an
894
+ * independent window per detected class: cat→dog fires at once, cat→cat
895
+ * still waits.
896
+ * - `shared` — one window for the whole rule/scope: a cat silences the next
897
+ * dog for `cooldownSec`. Only written when an operator picks it; it is no
898
+ * longer what an unset rule means.
897
899
  *
898
900
  * AUDIO subjects are ALWAYS per-class regardless of this setting: a scream
899
901
  * must not be swallowed by a bark's window (the precedent this generalizes —
@@ -2890,6 +2890,11 @@ export declare const pipelineAnalyticsCapability: {
2890
2890
  *
2891
2891
  * Operator-driven from the DI Events page (batch delete). Routes through
2892
2892
  * the same widened track-deletion cascade (design §5.2).
2893
+ *
2894
+ * `sparedMediaIds` (D683 Task 14): media rows the cascade LEFT because a
2895
+ * live stationary entry vouches for them (its key frame, owned by a track
2896
+ * that moved and was kept). Released when the entry retires. Optional:
2897
+ * absent from a provider that predates it.
2893
2898
  */
2894
2899
  readonly deleteTracks: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
2895
2900
  deviceId: z.ZodNumber;
@@ -2897,6 +2902,7 @@ export declare const pipelineAnalyticsCapability: {
2897
2902
  }, z.core.$strip>, z.ZodObject<{
2898
2903
  deleted: z.ZodNumber;
2899
2904
  failed: z.ZodReadonly<z.ZodArray<z.ZodString>>;
2905
+ sparedMediaIds: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodNumber>>>;
2900
2906
  }, z.core.$strip>, "mutation">;
2901
2907
  /**
2902
2908
  * Set the per-track operator flags (`markForTrain`, `debug`, `favourited`) on ONE track.
@@ -712,6 +712,45 @@ export declare const SetCameraSensorsInputSchema: z.ZodObject<{
712
712
  }, z.core.$strip>>;
713
713
  }, z.core.$strip>;
714
714
  export type SetCameraSensorsInput = z.infer<typeof SetCameraSensorsInputSchema>;
715
+ /**
716
+ * Why an early occupancy look (D691) was not scheduled.
717
+ *
718
+ * - `unknown-camera` — no session was ever dispatched for it, so there is no
719
+ * node and no config to attach a burst with.
720
+ * - `out-of-range` — the ask is negative or further out than the orchestrator
721
+ * will hold a timer for; the parked-object cadence is the answer there.
722
+ * - `no-burst-producer` — this build has no burst producer at all.
723
+ * - `already-looked` — this camera's ONE early look since its last session has
724
+ * been spent. A look's own burst can re-arm a flickering flip, and a look
725
+ * per arm would chain a burst every ~30 s forever (review H2); the next
726
+ * real session re-arms the budget.
727
+ */
728
+ export declare const OccupancyLookRefusalSchema: z.ZodEnum<{
729
+ "unknown-camera": "unknown-camera";
730
+ "out-of-range": "out-of-range";
731
+ "no-burst-producer": "no-burst-producer";
732
+ "already-looked": "already-looked";
733
+ }>;
734
+ export type OccupancyLookRefusal = z.infer<typeof OccupancyLookRefusalSchema>;
735
+ /** The input of `requestOccupancyLook` (D691). */
736
+ export declare const OccupancyLookRequestSchema: z.ZodObject<{
737
+ deviceId: z.ZodNumber;
738
+ afterMs: z.ZodNumber;
739
+ reason: z.ZodString;
740
+ }, z.core.$strip>;
741
+ export type OccupancyLookRequest = z.infer<typeof OccupancyLookRequestSchema>;
742
+ /** The answer of `requestOccupancyLook` (D691). */
743
+ export declare const OccupancyLookAnswerSchema: z.ZodObject<{
744
+ scheduled: z.ZodBoolean;
745
+ dueInMs: z.ZodOptional<z.ZodNumber>;
746
+ refusedBecause: z.ZodOptional<z.ZodEnum<{
747
+ "unknown-camera": "unknown-camera";
748
+ "out-of-range": "out-of-range";
749
+ "no-burst-producer": "no-burst-producer";
750
+ "already-looked": "already-looked";
751
+ }>>;
752
+ }, z.core.$strip>;
753
+ export type OccupancyLookAnswer = z.infer<typeof OccupancyLookAnswerSchema>;
715
754
  export declare const pipelineOrchestratorCapability: {
716
755
  readonly name: "pipeline-orchestrator";
717
756
  readonly scope: "system";
@@ -719,6 +758,29 @@ export declare const pipelineOrchestratorCapability: {
719
758
  readonly nodeIdMode: "data";
720
759
  readonly exposesDeviceSettings: true;
721
760
  readonly methods: {
761
+ /**
762
+ * D691 — an occupancy flip is pending on this camera and can commit
763
+ * `afterMs` from now: dial ONE occupancy burst at the end of its sustain
764
+ * window instead of leaving the commit to the 300 s parked-object cadence.
765
+ * Called by the notification centre, the only component that knows a flip
766
+ * is pending; the dial is the recheck's own (attach on the last session
767
+ * node, `requestOccupancyBurst`, detach). One pending look per camera; a
768
+ * session open at the due time is the look, and no burst is dialled.
769
+ */
770
+ readonly requestOccupancyLook: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
771
+ deviceId: z.ZodNumber;
772
+ afterMs: z.ZodNumber;
773
+ reason: z.ZodString;
774
+ }, z.core.$strip>, z.ZodObject<{
775
+ scheduled: z.ZodBoolean;
776
+ dueInMs: z.ZodOptional<z.ZodNumber>;
777
+ refusedBecause: z.ZodOptional<z.ZodEnum<{
778
+ "unknown-camera": "unknown-camera";
779
+ "out-of-range": "out-of-range";
780
+ "no-burst-producer": "no-burst-producer";
781
+ "already-looked": "already-looked";
782
+ }>>;
783
+ }, z.core.$strip>, "mutation">;
722
784
  /** Internal storage-migration participant lease. While held, dispatch
723
785
  * requests are accepted as pending but no new runner attachment starts. */
724
786
  readonly pauseForStorageMigration: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
@@ -6131,6 +6131,13 @@ export type AppRouter = TrpcCoreRouter<{
6131
6131
  output: z.infer<typeof DEVICE_SETTINGS_CONTRIBUTION_METHODS.applyDeviceSettingsPatch.output>;
6132
6132
  meta: object;
6133
6133
  }>;
6134
+ requestOccupancyLook: TRPCMutationProcedure<{
6135
+ input: {
6136
+ [x: string]: unknown;
6137
+ } & z.input<typeof pipelineOrchestratorCapability.methods.requestOccupancyLook.input>;
6138
+ output: z.infer<typeof pipelineOrchestratorCapability.methods.requestOccupancyLook.output>;
6139
+ meta: object;
6140
+ }>;
6134
6141
  pauseForStorageMigration: TRPCMutationProcedure<{
6135
6142
  input: {
6136
6143
  [x: string]: unknown;
@@ -6,7 +6,7 @@
6
6
  * scope+access check inside `protectedProcedure` (see
7
7
  * `server/backend/src/api/trpc/trpc.middleware.ts`).
8
8
  *
9
- * Coverage: 1195 method paths across 162 capabilities.
9
+ * Coverage: 1196 method paths across 162 capabilities.
10
10
  */
11
11
  import type { CapabilityMethodAccess } from '../capabilities/capability-definition.js';
12
12
  export interface MethodAccessRecord {
@@ -6,8 +6,8 @@
6
6
  * system-scope cap that takes a deviceId was previously never device-filtered
7
7
  * — see the generator header).
8
8
  *
9
- * Coverage: 407 methods carry a device reference, of which
10
- * 144 are on SYSTEM-scope caps.
9
+ * Coverage: 408 methods carry a device reference, of which
10
+ * 145 are on SYSTEM-scope caps.
11
11
  *
12
12
  * Top-level fields, number arrays, and one-level arrays of objects carrying
13
13
  * a numeric device field (targets[].deviceId) are all mapped; the matcher
@@ -86,7 +86,7 @@ export interface SystemProxy {
86
86
  readonly notificationRules: Pick<InferProvider<typeof notificationRulesCapability>, 'listRules' | 'getRule' | 'createRule' | 'updateRule' | 'deleteRule' | 'setRuleEnabled' | 'getClipRetentionAsks' | 'listDeviceMutes' | 'testRule' | 'previewStateSummary' | 'getConditionCatalog' | 'getTemplateCatalog' | 'previewTemplate' | 'getHistory' | 'getRuleLastRuns' | 'resolveArtifactUrl' | 'listSnoozes' | 'createSnooze' | 'cancelSnooze' | 'getAlarmConfig' | 'setAlarmConfig'>;
87
87
  readonly osdManager: Pick<InferProvider<typeof osdManagerCapability>, 'getConditionSupport' | 'copyDeviceConfiguration'>;
88
88
  readonly pipelineExecutor: Pick<InferProvider<typeof pipelineExecutorCapability>, 'getAvailableEngines' | 'getSelectedEngine' | 'getDefaultSteps' | 'getEngineProvisioning' | 'getVideoPipelineSteps' | 'setVideoPipelineSteps' | 'clearDeviceOverrides' | 'getInferenceDeviceHealth' | 'rearmInferenceDevice' | 'getSchema' | 'getGlobalSteps' | 'getGlobalPipelineConfig' | 'getOrchestratorConfigSchema' | 'validatePipeline' | 'listTemplates' | 'saveTemplate' | 'updateTemplate' | 'deleteTemplate' | 'getCapabilities' | 'getAddonModels' | 'downloadModel' | 'deleteModel' | 'cacheFrameInPool' | 'inferCached' | 'uncacheFrame' | 'getEffectiveTuning' | 'listLoadedEngines' | 'spinEngine' | 'killEngine' | 'listReferenceImages' | 'getReferenceImage' | 'getReferenceAudioFiles' | 'getReferenceAudio' | 'getAudioCapabilities' | 'runAudioTest' | 'getDetectionConfigSchema'>;
89
- readonly pipelineOrchestrator: Pick<InferProvider<typeof pipelineOrchestratorCapability>, 'pauseForStorageMigration' | 'resumeForStorageMigration' | 'rebalance' | 'getPipelineAssignments' | 'getAgentLoad' | 'getClusterModelChoice' | 'getGlobalMetrics' | 'getCapabilityBindings' | 'setCapabilityBinding' | 'getIngestOwner' | 'getAudioNodeLoad' | 'getAudioAssignments' | 'getAgentSettings' | 'listAgentSettings' | 'removeAgentSettings' | 'setAgentMaxCameras' | 'setAgentDetectWeight' | 'setAgentCapabilities' | 'setAgentDecodeLimits' | 'setAgentReachableHost' | 'setAgentInferenceDevices' | 'getNodeInferenceDevices' | 'resetNodePipelineDefaults' | 'getCameraStatuses' | 'setCameraSensors' | 'reconcileFromDisk' | 'getReconcileFromDiskStatus' | 'listTemplates' | 'saveTemplate' | 'updateTemplate' | 'deleteTemplate'>;
89
+ readonly pipelineOrchestrator: Pick<InferProvider<typeof pipelineOrchestratorCapability>, 'requestOccupancyLook' | 'pauseForStorageMigration' | 'resumeForStorageMigration' | 'rebalance' | 'getPipelineAssignments' | 'getAgentLoad' | 'getClusterModelChoice' | 'getGlobalMetrics' | 'getCapabilityBindings' | 'setCapabilityBinding' | 'getIngestOwner' | 'getAudioNodeLoad' | 'getAudioAssignments' | 'getAgentSettings' | 'listAgentSettings' | 'removeAgentSettings' | 'setAgentMaxCameras' | 'setAgentDetectWeight' | 'setAgentCapabilities' | 'setAgentDecodeLimits' | 'setAgentReachableHost' | 'setAgentInferenceDevices' | 'getNodeInferenceDevices' | 'resetNodePipelineDefaults' | 'getCameraStatuses' | 'setCameraSensors' | 'reconcileFromDisk' | 'getReconcileFromDiskStatus' | 'listTemplates' | 'saveTemplate' | 'updateTemplate' | 'deleteTemplate'>;
90
90
  readonly pipelineRunner: Pick<InferProvider<typeof pipelineRunnerCapability>, 'attachCamera' | 'reportMotion' | 'getLocalLoad' | 'getLocalMetrics' | 'getAllCameraMetrics' | 'getLocalCameras' | 'getNativeCrop' | 'runStatelessStep'>;
91
91
  readonly plateGallery: Pick<InferProvider<typeof plateGalleryCapability>, 'getPlateMedia' | 'searchPlates' | 'suggestPlateClusters' | 'correctPlateText' | 'deletePlate' | 'listVehicles' | 'createVehicle' | 'renameVehicle' | 'deleteVehicle' | 'listVehicleSamples' | 'removeVehicleSample' | 'assignPlate' | 'unassignPlate' | 'assignPlates' | 'unassignPlates'>;
92
92
  readonly recordingArchive: Pick<InferProvider<typeof recordingArchiveCapability>, 'getAvailabilityBatch' | 'getDaysWithRecordingsBatch' | 'getStorageUsage' | 'listOpsLog' | 'pauseForStorageMigration' | 'resumeForStorageMigration' | 'refreshStorageLocationsForMigration' | 'startStorageMigrationMove' | 'getStorageMigrationMoveStatus' | 'cancelStorageMigrationMove' | 'relocateFootage' | 'listRelocateJobs' | 'getRelocateResidue' | 'reconcileLedgerAgainstDisk' | 'cancelRelocateJob' | 'planStorageRebalance' | 'startStorageRebalance' | 'getPlacement' | 'setDevicePlacement'>;
package/dist/index.d.ts CHANGED
@@ -124,6 +124,7 @@ export { emitDownForOwnedCaps, ReadinessRegistry, ReadinessTimeoutError, readine
124
124
  export * from './stream-selection.js';
125
125
  export type { AgentAddonConfig, AgentPipelineSettings, CameraPipelineSettings, CameraStepOverridePatch, DeviceStepConfig, } from './types/agent-pipeline-settings.js';
126
126
  export * from './types/analytics.js';
127
+ export * from './types/appearance.js';
127
128
  export type { CameraPipelineConfig, PipelineTemplate as CameraPipelineTemplate, } from './types/camera-pipeline.js';
128
129
  export * from './types/config.js';
129
130
  export * from './types/detection.js';
@@ -235,7 +236,7 @@ export { audioIsFailClosed, audioKindId, audioLabelChoices, audioModeOf, audioOr
235
236
  export { isAudioClassName, isBaseConditionKey, knownValues, NC_BASE_CONDITION_KEYS, type NcBaseConditionKey, pickerForCondition, pickerForRuleClasses, type TaxonomyGroup, type TaxonomyOption, type TaxonomyPicker, } from './notification/condition-taxonomy.js';
236
237
  export { type PreparedAction, type PreparedAttachment, type PreparedNotification, prepareNotification, type ResolvedLevel, } from './notification/degrade-engine.js';
237
238
  export { htmlToText, markdownToHtmlLite, markdownToText, type NotificationFormat as NotificationBodyFormat, resolveFormat, textToHtml, transcodeBody, } from './notification/format-transcode.js';
238
- export { conditionExclusionReason, conditionVisibleForKind, defaultDeliveryForSection, droppedConditionsForKind, isAudioRule, isOccupancyRule, isSystemDelivery, isSystemRuleKind, kindsForDiscriminator, NC_AUDIO_SEED, NC_OCCUPANCY_DEFAULTS, NC_RULE_EDITOR_SECTION_ORDER, NC_RULE_KIND_SPECS, NC_RULE_SECTIONS, NC_SYSTEM_DELIVERY, NC_SYSTEM_RULE_KINDS, type NcDroppedCondition, type NcKindVisibilitySubject, type NcRuleEditorSection, type NcRuleEditorSectionKey, type NcRuleKind, type NcRuleKindSpec, type NcRuleOwningSectionKey, type NcRuleSection, type NcRuleSectionKey, type NcRuleSectionSubject, type NcRuleSeed, parseRuleSection, ruleEditorSectionsForKind, ruleKindOf, ruleKindSpec, ruleMatchesSection, ruleSection, ruleSectionOf, ruleSeedForSection, systemFamilyOfKind, systemRuleKindOf, } from './notification/rule-kinds.js';
239
+ export { conditionExclusionReason, conditionVisibleForKind, defaultDeliveryForSection, droppedConditionsForKind, isAudioRule, isOccupancyRule, isSystemDelivery, isSystemRuleKind, kindsForDiscriminator, NC_AUDIO_SEED, NC_CAMERA_SCOPE_CAP_NAME, NC_OCCUPANCY_DEFAULTS, NC_RULE_EDITOR_SECTION_ORDER, NC_RULE_KIND_SPECS, NC_RULE_SECTIONS, NC_SYSTEM_DELIVERY, NC_SYSTEM_RULE_KINDS, type NcDroppedCondition, type NcKindVisibilitySubject, type NcRuleEditorSection, type NcRuleEditorSectionKey, type NcRuleKind, type NcRuleKindSpec, type NcRuleOwningSectionKey, type NcRuleSection, type NcRuleSectionKey, type NcRuleSectionSubject, type NcRuleSeed, parseRuleSection, ruleDeviceCompatCapNames, ruleDeviceCompatCapQueries, ruleEditorSectionsForKind, ruleKindOf, ruleKindSpec, ruleMatchesSection, ruleSection, ruleSectionOf, ruleSeedForSection, systemFamilyOfKind, systemRuleKindOf, } from './notification/rule-kinds.js';
239
240
  export { isScheduleActive } from './notification/schedule.js';
240
241
  export { NC_ALARM_OPENING_EVENT_KINDS, NC_SENSOR_TRANSITION_NEVER_FIRES_WARNING, type NcAlarmMembershipSubject, type NcAlarmOpeningEventKind, ruleBelongsToAlarm, sensorTransitionNeverFires, } from './notification/alarm-membership.js';
241
242
  export { NC_SENSOR_RAISED_FIELD_BY_KIND, NC_SENSOR_TRANSITION_KINDS, NC_SENSOR_TRANSITION_UNSUPPORTED_REASON, sensorRaisedOf, sensorTransitionOffered, } from './notification/sensor-raised.js';
package/dist/index.js CHANGED
@@ -4990,6 +4990,44 @@ function pickClosestResolution(entries, target) {
4990
4990
  }])].sort((a, b) => compareToTarget(a.pixels, b.pixels, targetPixels))[0]?.entry;
4991
4991
  }
4992
4992
  //#endregion
4993
+ //#region src/types/appearance.ts
4994
+ /**
4995
+ * A model-free appearance descriptor of one detection box (D683 §8).
4996
+ *
4997
+ * Computed on the runner from the analysis raster the frame already leased
4998
+ * (`pipeline-runner/appearance-descriptor.ts`), carried on `ObjectDetection`
4999
+ * and mirrored onto the tracker's `SpatialDetection`. A vector about a box,
5000
+ * never pixels (D9/D18). No learned weights, so no licence question (O6).
5001
+ *
5002
+ * Layout: the box shrunk 10 % per side, split into an upper and a lower half;
5003
+ * per half a hue–saturation histogram (8 hue × 4 saturation), a value histogram
5004
+ * (8) and a magnitude-weighted gradient-orientation histogram (8). Each block
5005
+ * is L1-normalised and quantised to integers 0–255. About 300 bytes of JSON.
5006
+ */
5007
+ var APPEARANCE_DESCRIPTOR_VERSION = 1;
5008
+ var APPEARANCE_BIN_COUNT = 96;
5009
+ var APPEARANCE_BLOCKS = {
5010
+ upperHs: [0, 32],
5011
+ upperV: [32, 40],
5012
+ upperGrad: [40, 48],
5013
+ lowerHs: [48, 80],
5014
+ lowerV: [80, 88],
5015
+ lowerGrad: [88, 96]
5016
+ };
5017
+ /**
5018
+ * Whether appearance may influence anything at all (D683 §3.2, fix round 1
5019
+ * ruling 2026-09-30 on the Task 10 cost-bench STOP): OFF until the
5020
+ * descriptor is calibrated on tapes that carry it (Task 23, review M9).
5021
+ *
5022
+ * This is the ONE authority both addons read — never two settings that
5023
+ * could disagree (CLAUDE.md D62). The tracker's `TrackerV2Config.appearanceResolvesAmbiguity`
5024
+ * default reads it (`addon-post-analysis/pipeline/tracker-v2/types.ts`); the
5025
+ * runner's cost gate reads it too (`addon-pipeline/pipeline-runner/appearance-attach.ts`),
5026
+ * short-circuiting BEFORE any crop, resample or descriptor is computed, so a
5027
+ * disabled camera costs nothing extra per frame.
5028
+ */
5029
+ var APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT = false;
5030
+ //#endregion
4993
5031
  //#region src/types/overlay-layer.ts
4994
5032
  var OVERLAY_LAYERS = [
4995
5033
  "motion",
@@ -19541,10 +19579,12 @@ var NcMediaPolicySchema = zod.z.object({
19541
19579
  /**
19542
19580
  * Cooldown GRANULARITY over the subject's class — how much a fired
19543
19581
  * notification suppresses.
19544
- * - `shared` (default, and the absent value) — one window for the whole
19545
- * rule/scope: a cat silences the next dog for `cooldownSec`.
19546
- * - `per-class` — an independent window per detected class, so cat→dog fires
19547
- * at once and cat→cat still waits.
19582
+ * - `per-class` (default, and the absent value since 2026-10-01 — D36) — an
19583
+ * independent window per detected class: cat→dog fires at once, cat→cat
19584
+ * still waits.
19585
+ * - `shared` — one window for the whole rule/scope: a cat silences the next
19586
+ * dog for `cooldownSec`. Only written when an operator picks it; it is no
19587
+ * longer what an unset rule means.
19548
19588
  *
19549
19589
  * AUDIO subjects are ALWAYS per-class regardless of this setting: a scream
19550
19590
  * must not be swallowed by a bark's window (the precedent this generalizes —
@@ -19559,8 +19599,11 @@ var NcThrottleSchema = zod.z.object({
19559
19599
  /**
19560
19600
  * Class granularity of the cooldown key. Optional rather than defaulted:
19561
19601
  * a Zod default does NOT run on the addon→addon cap path, so a persisted
19562
- * rule authored before this field simply carries none — and the engine
19563
- * reads absent as `shared`, the pre-existing behaviour.
19602
+ * rule authored before this field simply carries none. The engine used to
19603
+ * read absent as `shared` (D36); since 2026-10-01 it reads absent as
19604
+ * `per-class` — the operator's default — and only an explicit `shared`
19605
+ * still means `shared`. See `cooldownKey` / `keysPerClass` in the rule
19606
+ * engine, and D36's dated note.
19564
19607
  */
19565
19608
  granularity: NcThrottleGranularitySchema.optional()
19566
19609
  });
@@ -24018,13 +24061,19 @@ var pipelineAnalyticsCapability = {
24018
24061
  *
24019
24062
  * Operator-driven from the DI Events page (batch delete). Routes through
24020
24063
  * the same widened track-deletion cascade (design §5.2).
24064
+ *
24065
+ * `sparedMediaIds` (D683 Task 14): media rows the cascade LEFT because a
24066
+ * live stationary entry vouches for them (its key frame, owned by a track
24067
+ * that moved and was kept). Released when the entry retires. Optional:
24068
+ * absent from a provider that predates it.
24021
24069
  */
24022
24070
  deleteTracks: require_sleep.method(zod.z.object({
24023
24071
  deviceId: zod.z.number(),
24024
24072
  trackIds: zod.z.array(zod.z.string()).min(1)
24025
24073
  }), zod.z.object({
24026
24074
  deleted: zod.z.number().int(),
24027
- failed: zod.z.array(zod.z.string()).readonly()
24075
+ failed: zod.z.array(zod.z.string()).readonly(),
24076
+ sparedMediaIds: zod.z.array(zod.z.number().int()).readonly().optional()
24028
24077
  }), {
24029
24078
  kind: "mutation",
24030
24079
  auth: "admin"
@@ -27369,6 +27418,42 @@ var SetCameraSensorsInputSchema = zod.z.object({
27369
27418
  /** `null` removes the attachment: the camera goes back to `not-configured`. */
27370
27419
  config: CameraSensorsConfigSchema.nullable()
27371
27420
  });
27421
+ /**
27422
+ * Why an early occupancy look (D691) was not scheduled.
27423
+ *
27424
+ * - `unknown-camera` — no session was ever dispatched for it, so there is no
27425
+ * node and no config to attach a burst with.
27426
+ * - `out-of-range` — the ask is negative or further out than the orchestrator
27427
+ * will hold a timer for; the parked-object cadence is the answer there.
27428
+ * - `no-burst-producer` — this build has no burst producer at all.
27429
+ * - `already-looked` — this camera's ONE early look since its last session has
27430
+ * been spent. A look's own burst can re-arm a flickering flip, and a look
27431
+ * per arm would chain a burst every ~30 s forever (review H2); the next
27432
+ * real session re-arms the budget.
27433
+ */
27434
+ var OccupancyLookRefusalSchema = zod.z.enum([
27435
+ "unknown-camera",
27436
+ "out-of-range",
27437
+ "no-burst-producer",
27438
+ "already-looked"
27439
+ ]);
27440
+ /** The input of `requestOccupancyLook` (D691). */
27441
+ var OccupancyLookRequestSchema = zod.z.object({
27442
+ deviceId: zod.z.number().int().nonnegative(),
27443
+ /** How long from NOW until the pending flip's sustain window ends. RELATIVE,
27444
+ * so the caller's clock and the orchestrator's never have to agree. */
27445
+ afterMs: zod.z.number().finite(),
27446
+ /** Why, for the log. */
27447
+ reason: zod.z.string()
27448
+ });
27449
+ /** The answer of `requestOccupancyLook` (D691). */
27450
+ var OccupancyLookAnswerSchema = zod.z.object({
27451
+ scheduled: zod.z.boolean(),
27452
+ /** When `scheduled`: how long until the burst is dialled. */
27453
+ dueInMs: zod.z.number().optional(),
27454
+ /** When not `scheduled`: why. */
27455
+ refusedBecause: OccupancyLookRefusalSchema.optional()
27456
+ });
27372
27457
  var pipelineOrchestratorCapability = {
27373
27458
  name: "pipeline-orchestrator",
27374
27459
  scope: "system",
@@ -27376,6 +27461,19 @@ var pipelineOrchestratorCapability = {
27376
27461
  nodeIdMode: "data",
27377
27462
  exposesDeviceSettings: true,
27378
27463
  methods: {
27464
+ /**
27465
+ * D691 — an occupancy flip is pending on this camera and can commit
27466
+ * `afterMs` from now: dial ONE occupancy burst at the end of its sustain
27467
+ * window instead of leaving the commit to the 300 s parked-object cadence.
27468
+ * Called by the notification centre, the only component that knows a flip
27469
+ * is pending; the dial is the recheck's own (attach on the last session
27470
+ * node, `requestOccupancyBurst`, detach). One pending look per camera; a
27471
+ * session open at the due time is the look, and no burst is dialled.
27472
+ */
27473
+ requestOccupancyLook: require_sleep.method(OccupancyLookRequestSchema, OccupancyLookAnswerSchema, {
27474
+ kind: "mutation",
27475
+ auth: "admin"
27476
+ }),
27379
27477
  /** Internal storage-migration participant lease. While held, dispatch
27380
27478
  * requests are accepted as pending but no new runner attachment starts. */
27381
27479
  pauseForStorageMigration: require_sleep.method(StorageMigrationLeaseInputSchema, zod.z.object({ paused: zod.z.literal(true) }), {
@@ -57257,6 +57355,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
57257
57355
  addonId: null,
57258
57356
  access: "delete"
57259
57357
  },
57358
+ "pipelineOrchestrator.requestOccupancyLook": {
57359
+ capName: "pipeline-orchestrator",
57360
+ capScope: "system",
57361
+ addonId: null,
57362
+ access: "create"
57363
+ },
57260
57364
  "pipelineOrchestrator.resetNodePipelineDefaults": {
57261
57365
  capName: "pipeline-orchestrator",
57262
57366
  capScope: "system",
@@ -61384,6 +61488,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
61384
61488
  form: "single",
61385
61489
  optional: false
61386
61490
  }],
61491
+ "pipelineOrchestrator.requestOccupancyLook": [{
61492
+ name: "deviceId",
61493
+ form: "single",
61494
+ optional: false
61495
+ }],
61387
61496
  "pipelineOrchestrator.resolvePipeline": [{
61388
61497
  name: "deviceId",
61389
61498
  form: "single",
@@ -62219,6 +62328,7 @@ var SYSTEM_SCOPE_DEVICE_METHODS = [
62219
62328
  "pipelineOrchestrator.getCameraSwitches",
62220
62329
  "pipelineOrchestrator.getPipelineAssignment",
62221
62330
  "pipelineOrchestrator.getPipelineDevicePin",
62331
+ "pipelineOrchestrator.requestOccupancyLook",
62222
62332
  "pipelineOrchestrator.resolvePipeline",
62223
62333
  "pipelineOrchestrator.setCameraPipelineForAgent",
62224
62334
  "pipelineOrchestrator.setCameraSensors",
@@ -63182,6 +63292,7 @@ function createSystemProxy(api) {
63182
63292
  getDetectionConfigSchema: (input) => dispatch("pipelineExecutor", "getDetectionConfigSchema", "query", input)
63183
63293
  },
63184
63294
  pipelineOrchestrator: {
63295
+ requestOccupancyLook: (input) => dispatch("pipelineOrchestrator", "requestOccupancyLook", "mutation", input),
63185
63296
  pauseForStorageMigration: (input) => dispatch("pipelineOrchestrator", "pauseForStorageMigration", "mutation", input),
63186
63297
  resumeForStorageMigration: (input) => dispatch("pipelineOrchestrator", "resumeForStorageMigration", "mutation", input),
63187
63298
  rebalance: (input) => dispatch("pipelineOrchestrator", "rebalance", "mutation", input),
@@ -64665,6 +64776,74 @@ function isSystemDelivery(delivery) {
64665
64776
  return delivery === NC_SYSTEM_DELIVERY;
64666
64777
  }
64667
64778
  /**
64779
+ * Which capability a device must carry to be OFFERED on a rule of this kind's
64780
+ * device-scope picker (operator ruling, 2026-10-01). `null` means "no
64781
+ * capability filter for this kind" — either every device applies (the system
64782
+ * families, each already a separate concern; see
64783
+ * `docs/architecture/notifications.md`'s D637 `deviceIds` table) or `mixed`,
64784
+ * which authors nothing.
64785
+ *
64786
+ * DERIVED, never a hand-picked list:
64787
+ * - `sensor` reads `EVENTFUL_CAP_NAMES` — the SAME cap table the engine
64788
+ * itself turns a linked device's bound caps into sensor event kinds with
64789
+ * (`EVENT_KIND_BY_CAP`). A device this picker offers for a sensor rule is
64790
+ * exactly a device the rule's `sensorKinds` condition could ever name.
64791
+ * - `detection` (which a package-event rule is — there is no separate
64792
+ * `package` kind, D637) / `occupancy` read the one pipeline cap a camera
64793
+ * needs to produce the detections / counts / parcels those kinds match on.
64794
+ * - `sound` reads the one cap a device needs to produce the audio metrics a
64795
+ * sound rule's sampling window is built from.
64796
+ * - `device-events` / `system` / `alarm` / `mixed` are `null`: a device
64797
+ * event rule's `deviceIds` legitimately spans every device type (liveness,
64798
+ * battery, consumable, `detection-blind`), a system rule has no device
64799
+ * scope at all (dropped from the editor's tabs), and `alarm`'s `deviceIds`
64800
+ * is a reference to whichever camera's rule set it off — not a scope this
64801
+ * picker authors.
64802
+ *
64803
+ * Callers resolve the ids via `deviceManager.listDeviceIdsByCaps` (max 16
64804
+ * names — `EVENTFUL_CAP_NAMES` is exactly 16) and must treat an unanswered
64805
+ * read as "unknown", never as "no devices" (D315): this function only names
64806
+ * WHICH caps to ask for, not what to show while the answer is pending.
64807
+ */
64808
+ function ruleDeviceCompatCapNames(kind) {
64809
+ switch (kind) {
64810
+ case "sensor": return EVENTFUL_CAP_NAMES;
64811
+ case "detection":
64812
+ case "occupancy": return ["detection-pipeline"];
64813
+ case "sound": return ["audio-metrics"];
64814
+ case "device-events":
64815
+ case "system":
64816
+ case "alarm":
64817
+ case "mixed": return null;
64818
+ }
64819
+ }
64820
+ /**
64821
+ * The capability every CAMERA carries: `camera-streams` is a `defaultActive`
64822
+ * wrapper bound to every `Camera`-type device (`camera-streams.cap.ts`).
64823
+ * Named once, because a sensor rule's compatible set needs it (below).
64824
+ */
64825
+ var NC_CAMERA_SCOPE_CAP_NAME = "camera-streams";
64826
+ /**
64827
+ * Every capability QUERY whose union is the set of devices a rule of this kind
64828
+ * may be SCOPED to (`conditions.devices`) — what the save-time guard and the
64829
+ * admin's Devices tab ask `deviceManager.listDeviceIdsByCaps`, one call per
64830
+ * entry. `null` exactly where {@link ruleDeviceCompatCapNames} is `null`.
64831
+ *
64832
+ * Several queries rather than one list because `listDeviceIdsByCaps` takes at
64833
+ * most 16 names and `EVENTFUL_CAP_NAMES` is already exactly 16.
64834
+ *
64835
+ * A `sensor` rule's set is the eventful devices PLUS every camera (fix round
64836
+ * 1, 2026-10-01): the engine matches a sensor rule scoped to a CAMERA — a
64837
+ * per-camera row carries the camera's id, and a linked set matches on
64838
+ * `rowCameraIds` (D630 §6) — so a camera-scoped sensor rule is legitimate and
64839
+ * a guard that refused it would make every such stored rule un-editable.
64840
+ */
64841
+ function ruleDeviceCompatCapQueries(kind) {
64842
+ const primary = ruleDeviceCompatCapNames(kind);
64843
+ if (primary === null) return null;
64844
+ return kind === "sensor" ? [primary, [NC_CAMERA_SCOPE_CAP_NAME]] : [primary];
64845
+ }
64846
+ /**
64668
64847
  * Which kind of rule is this?
64669
64848
  *
64670
64849
  * The CONDITION wins over the delivery wherever the engine says it does, and
@@ -64738,12 +64917,20 @@ var NC_RULE_SECTIONS = [
64738
64917
  },
64739
64918
  {
64740
64919
  key: "detection",
64741
- label: "Detections & devices",
64742
- blurb: "Rules driven by what the cameras and sensors SEE — detections, tracks, doorbell presses and package events.",
64920
+ label: "Detections",
64921
+ blurb: "Rules driven by what the cameras SEE — detections, tracks and package events.",
64743
64922
  newRuleLabel: "New detection rule",
64744
64923
  emptyHint: "No detection rules yet. Create one to be told what your cameras see.",
64745
64924
  creatable: true
64746
64925
  },
64926
+ {
64927
+ key: "sensor",
64928
+ label: "Sensors",
64929
+ blurb: "Rules driven by a device or sensor CHANGING STATE — a doorbell press, a linked sensor opening or closing. The picture comes from the camera the sensor is attributed to.",
64930
+ newRuleLabel: "New sensor rule",
64931
+ emptyHint: "No sensor rules yet. Create one to be told when a doorbell is pressed or a linked sensor changes.",
64932
+ creatable: true
64933
+ },
64747
64934
  {
64748
64935
  key: "audio",
64749
64936
  label: "Sound",
@@ -64815,22 +65002,28 @@ function isOccupancyRule(subject) {
64815
65002
  * `all` always matches — a section that hides a rule is how an operator
64816
65003
  * concludes it was deleted. The others PARTITION the list: sound and
64817
65004
  * occupancy are claimed by their condition, a system-event rule by its trigger
64818
- * and then by the family of its event kinds (or `mixed`, D637), and
64819
- * everything left over — including a trigger this build has never heard of —
64820
- * counts as a detection rule so it stays visible somewhere.
64821
- *
64822
- * Keyed on the CONDITION for two of them, because the trigger alone cannot
64823
- * answer: a sound rule is `immediate` and an occupancy rule is `device-event`,
64824
- * and in each case the condition is the discriminator the engine itself uses.
64825
- * A section keyed on delivery would put both back in the pile they are
64826
- * invisible in.
65005
+ * and then by the family of its event kinds (or `mixed`, D637), `sensor`
65006
+ * claims the `device-event` trigger that occupancy did not (operator ruling,
65007
+ * 2026-10-01 — a doorbell press used to fall into `detection` for want of its
65008
+ * own section, which is the "everything mixed together" the viewer's
65009
+ * `ruleKindOf`-based list had already fixed and the admin's section strip had
65010
+ * not), and everything left over — including a trigger this build has never
65011
+ * heard of — counts as a detection rule so it stays visible somewhere.
65012
+ *
65013
+ * Keyed on the CONDITION for sound and occupancy, because the trigger alone
65014
+ * cannot answer: a sound rule is `immediate` and an occupancy rule is
65015
+ * `device-event`, and in each case the condition is the discriminator the
65016
+ * engine itself uses. `sensor` IS keyed on the trigger, same as `ruleKindOf`'s
65017
+ * `'sensor'` kind — a device-event subject with no occupancy condition is a
65018
+ * sensor rule, full stop.
64827
65019
  */
64828
65020
  function ruleMatchesSection(subject, section) {
64829
65021
  if (section === "all") return true;
64830
65022
  if (isSystemDelivery(subject.delivery)) return ruleKindOf(subject) === section;
64831
65023
  if (section === "audio") return isAudioRule(subject);
64832
65024
  if (section === "occupancy") return isOccupancyRule(subject);
64833
- if (section === "detection") return !isAudioRule(subject) && !isOccupancyRule(subject);
65025
+ if (section === "sensor") return subject.delivery === "device-event" && !isOccupancyRule(subject);
65026
+ if (section === "detection") return !isAudioRule(subject) && !isOccupancyRule(subject) && subject.delivery !== "device-event";
64834
65027
  return false;
64835
65028
  }
64836
65029
  /**
@@ -64844,6 +65037,7 @@ function ruleSectionOf(subject) {
64844
65037
  if (isSystemDelivery(subject.delivery)) return systemRuleKindOf(subject.conditions.systemEvent);
64845
65038
  if (isAudioRule(subject)) return "audio";
64846
65039
  if (isOccupancyRule(subject)) return "occupancy";
65040
+ if (subject.delivery === "device-event") return "sensor";
64847
65041
  return "detection";
64848
65042
  }
64849
65043
  /**
@@ -64901,6 +65095,10 @@ function ruleSeedForSection(section) {
64901
65095
  delivery: "device-event",
64902
65096
  conditions: { occupancy: NC_OCCUPANCY_DEFAULTS }
64903
65097
  };
65098
+ case "sensor": return {
65099
+ delivery: "device-event",
65100
+ conditions: {}
65101
+ };
64904
65102
  default: return {
64905
65103
  delivery: "immediate",
64906
65104
  conditions: { source: "pipeline" }
@@ -68890,6 +69088,10 @@ exports.ACCESSORY_LABEL = ACCESSORY_LABEL;
68890
69088
  exports.ACCESS_ROLES = ACCESS_ROLES;
68891
69089
  exports.ALEXA_EGRESS_PROFILE = ALEXA_EGRESS_PROFILE;
68892
69090
  exports.ALL_CAPABILITY_DEFINITIONS = ALL_CAPABILITY_DEFINITIONS;
69091
+ exports.APPEARANCE_BIN_COUNT = APPEARANCE_BIN_COUNT;
69092
+ exports.APPEARANCE_BLOCKS = APPEARANCE_BLOCKS;
69093
+ exports.APPEARANCE_DESCRIPTOR_VERSION = APPEARANCE_DESCRIPTOR_VERSION;
69094
+ exports.APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT = APPEARANCE_RESOLVES_AMBIGUITY_DEFAULT;
68893
69095
  exports.APPLE_SA_TO_MACRO = APPLE_SA_TO_MACRO;
68894
69096
  exports.ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT = ARCHIVED_DEBUG_NOTES_DEFAULT_LIMIT;
68895
69097
  exports.AUDIO_ANALYSIS_CAP_NAME = AUDIO_ANALYSIS_CAP_NAME;
@@ -69669,6 +69871,7 @@ exports.NC_AUDIO_SEED = NC_AUDIO_SEED;
69669
69871
  exports.NC_AUTHORABLE_SYSTEM_EVENT_KINDS = NC_AUTHORABLE_SYSTEM_EVENT_KINDS;
69670
69872
  exports.NC_BASE_CONDITION_KEYS = NC_BASE_CONDITION_KEYS;
69671
69873
  exports.NC_BATTERY_CONSUMABLE_SYSTEM_EVENT_KINDS = NC_BATTERY_CONSUMABLE_SYSTEM_EVENT_KINDS;
69874
+ exports.NC_CAMERA_SCOPE_CAP_NAME = NC_CAMERA_SCOPE_CAP_NAME;
69672
69875
  exports.NC_CLIP_POST_ROLL_DEFAULT_SEC = NC_CLIP_POST_ROLL_DEFAULT_SEC;
69673
69876
  exports.NC_CLIP_PRE_ROLL_DEFAULT_SEC = NC_CLIP_PRE_ROLL_DEFAULT_SEC;
69674
69877
  exports.NC_CLIP_RETENTION_MAX_SEC = NC_CLIP_RETENTION_MAX_SEC;
@@ -69821,6 +70024,9 @@ exports.OWNER_ONLY_EVENT_CATEGORIES = require_event_category.OWNER_ONLY_EVENT_CA
69821
70024
  exports.OauthIntegrationDescriptorSchema = OauthIntegrationDescriptorSchema;
69822
70025
  exports.ObjectEventSchema = ObjectEventSchema;
69823
70026
  exports.OccupancyBurstRefusalSchema = OccupancyBurstRefusalSchema;
70027
+ exports.OccupancyLookAnswerSchema = OccupancyLookAnswerSchema;
70028
+ exports.OccupancyLookRefusalSchema = OccupancyLookRefusalSchema;
70029
+ exports.OccupancyLookRequestSchema = OccupancyLookRequestSchema;
69824
70030
  exports.OnboardFieldSupportSchema = OnboardFieldSupportSchema;
69825
70031
  exports.OnboardRecordTrackSchema = OnboardRecordTrackSchema;
69826
70032
  exports.OnboardScheduleSupportSchema = OnboardScheduleSupportSchema;
@@ -70777,6 +70983,8 @@ exports.resolveViewableDeviceIds = resolveViewableDeviceIds;
70777
70983
  exports.roleSpec = roleSpec;
70778
70984
  exports.roomCompositionExample = roomCompositionExample;
70779
70985
  exports.ruleBelongsToAlarm = ruleBelongsToAlarm;
70986
+ exports.ruleDeviceCompatCapNames = ruleDeviceCompatCapNames;
70987
+ exports.ruleDeviceCompatCapQueries = ruleDeviceCompatCapQueries;
70780
70988
  exports.ruleEditorSectionsForKind = ruleEditorSectionsForKind;
70781
70989
  exports.ruleKindOf = ruleKindOf;
70782
70990
  exports.ruleKindSpec = ruleKindSpec;