@camstack/addon-provider-dreame 0.2.83 → 0.2.85

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/addon.js CHANGED
@@ -71436,11 +71436,30 @@ var SensorEventSchema = object({
71436
71436
  value: record(string(), unknown()).nullable(),
71437
71437
  timestamp: number()
71438
71438
  });
71439
+ /**
71440
+ * One stored sighting on a track's trajectory.
71441
+ *
71442
+ * The array these live in is returned in TIME order (D399) — it is APPENDED in
71443
+ * arrival order, and the two detector passes interleave, so a consumer must not
71444
+ * assume the two are the same on a row written by an older build.
71445
+ */
71439
71446
  var TrackPositionSchema = object({
71440
71447
  x: number(),
71441
71448
  y: number(),
71442
71449
  timestamp: number(),
71443
- bbox: BoundingBoxSchema
71450
+ bbox: BoundingBoxSchema,
71451
+ /**
71452
+ * Which detector pass measured this box (D399): `frame` is the full-frame
71453
+ * pass on the analysis raster, `recovery` is the native-resolution
71454
+ * small-subject second pass (D377/D378). Both write into one array, and until
71455
+ * this field existed the only way to tell them apart was that full-frame boxes
71456
+ * are exact multiples of 1.2 while recovery boxes are full-precision floats.
71457
+ * Absent on rows written before D399.
71458
+ */
71459
+ source: _enum(["frame", "recovery"]).optional(),
71460
+ /** Detection score of this box, so a position can be weighed and not only
71461
+ * plotted. Absent on rows written before D399. */
71462
+ score: number().optional()
71444
71463
  });
71445
71464
  var TrackSnapshotSchema = object({
71446
71465
  timestamp: number(),
@@ -71840,14 +71859,25 @@ var TrackSchema = object({
71840
71859
  */
71841
71860
  hasRider: boolean().optional(),
71842
71861
  /**
71843
- * WHY this track ended without a NATIVE best-shot tile
71844
- * ([D276](../decisions/adr-0276-a-stand-in-tile-is-provisional-and-a-close-says-why.md)) —
71862
+ * WHY this track ended without a NATIVE best-shot FRAME
71863
+ * ([D276](../decisions/adr-0276-a-stand-in-tile-is-provisional-and-a-close-says-why.md),
71864
+ * widened by [D400](../decisions/adr-0400-the-picture-is-judged-on-what-is-delivered.md)) —
71845
71865
  * a composed token line (`no-key-frame capture=keyframe:native-missx4`,
71846
- * `derive-returned-null tile=standin`, …) written at close and CLEARED by
71847
- * the late-keyFrame upgrade when a native tile lands after all. The
71848
- * operator-facing answer to "perché manca l'immagine?" on a track whose
71866
+ * `derive-returned-null tile=standin`,
71867
+ * `native-tile tile=native no-key-frame-at-close`, …) written at close and
71868
+ * CLEARED by the late-keyFrame upgrade when a native tile lands after all.
71869
+ * The operator-facing answer to "perché manca l'immagine?" on a track whose
71849
71870
  * tile is a face/plate stand-in, a raster crop, or an icon.
71850
71871
  *
71872
+ * **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
71873
+ * the TILE ranked below native, so a track whose thumbnail landed natively
71874
+ * while its key frame missed carried no reason at all — three of the four
71875
+ * `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
71876
+ * that shape, and their "niente ultimo" had no cause anywhere on the row.
71877
+ * The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
71878
+ * lastFrame copy source`), so its absence is now on this line whatever the
71879
+ * tile ended up being.
71880
+ *
71851
71881
  * **Absent ≠ "missed silently"**: a row written before the column, a hub
71852
71882
  * that predates the field, and every track whose tile landed native all
71853
71883
  * omit it. Render nothing when absent.
@@ -77936,6 +77966,59 @@ var IdentitySampleInfoSchema = object({
77936
77966
  deviceId: number().int().optional(),
77937
77967
  base64: string().optional()
77938
77968
  });
77969
+ /**
77970
+ * One enrolled sample, judged against the gallery it lives in.
77971
+ *
77972
+ * The gallery is the one input to recognition nobody re-reads: a sample
77973
+ * enrolled from the wrong face keeps voting forever, and because the matches it
77974
+ * pulls then look confident, nobody goes back. The 2026-09-08 audit found
77975
+ * exactly one such pair on this cluster — a sample scoring 0.61 against three
77976
+ * samples of ANOTHER person, enrolled from the same camera in the same minute,
77977
+ * where every other cross-identity pair sits under 0.50.
77978
+ */
77979
+ var IdentitySampleAuditRowSchema = object({
77980
+ sampleId: string(),
77981
+ enrolledAt: number().int(),
77982
+ deviceId: number().int().optional(),
77983
+ source: _enum(["detected", "photo"]),
77984
+ /** The enrolled crop's media key, so the panel can show the evidence. */
77985
+ mediaKey: string().optional(),
77986
+ /**
77987
+ * False = the sample is stamped with a DIFFERENT face model, and a cosine
77988
+ * across feature spaces is a well-formed float with no meaning. Every number
77989
+ * below then says nothing — it must read as "cannot say", never as an
77990
+ * accusation and never as a clean bill: this list ends in a Remove button.
77991
+ */
77992
+ comparable: boolean(),
77993
+ /** Mean cosine against this person's other samples. Null when there are none
77994
+ * to compare with — never 0, which would read as "opposite". */
77995
+ selfMean: number().nullable(),
77996
+ /** The other person this sample looks most like, when it looks like one.
77997
+ * This is the half that convicts: not looking like yourself can be a hard
77998
+ * angle; looking like someone the gallery can NAME is a mis-enrolment. */
77999
+ bestForeign: object({
78000
+ identityId: string(),
78001
+ name: string(),
78002
+ score: number()
78003
+ }).optional(),
78004
+ /** 0 = nothing to say. Higher = look at this one sooner. */
78005
+ suspicion: number()
78006
+ });
78007
+ var IdentitySampleAuditSchema = object({
78008
+ identityId: string(),
78009
+ name: string(),
78010
+ /** The cluster face model every comparison was made in. */
78011
+ modelId: string(),
78012
+ totalSamples: number().int(),
78013
+ comparableSamples: number().int(),
78014
+ flagged: number().int(),
78015
+ /** The bar `flagged` counts against, so the panel states the RULE and not
78016
+ * only its current result. */
78017
+ flagThreshold: number(),
78018
+ /** Worst first. A row with nothing to say still appears, at the bottom: the
78019
+ * operator asked to see the gallery, not only its accusations. */
78020
+ rows: array(IdentitySampleAuditRowSchema).readonly()
78021
+ });
77939
78022
  var FaceInfoSchema = object({
77940
78023
  faceId: string(),
77941
78024
  deviceId: number().int(),
@@ -78087,7 +78170,7 @@ includeCrops: boolean().optional() }).optional(), array(IdentitySchema).readonly
78087
78170
  }), method(object({ id: string() }), _void(), {
78088
78171
  kind: "mutation",
78089
78172
  auth: "admin"
78090
- }), method(object({ identityId: string() }), array(IdentitySampleInfoSchema).readonly()), method(object({
78173
+ }), method(object({ identityId: string() }), array(IdentitySampleInfoSchema).readonly()), method(object({ identityId: string().min(1) }), IdentitySampleAuditSchema, { auth: "admin" }), method(object({
78091
78174
  identityId: string(),
78092
78175
  sampleId: string()
78093
78176
  }), _void(), {
@@ -88728,6 +88811,12 @@ Object.freeze({
88728
88811
  addonId: null,
88729
88812
  access: "create"
88730
88813
  },
88814
+ "faceGallery.auditIdentitySamples": {
88815
+ capName: "face-gallery",
88816
+ capScope: "system",
88817
+ addonId: null,
88818
+ access: "view"
88819
+ },
88731
88820
  "faceGallery.createIdentity": {
88732
88821
  capName: "face-gallery",
88733
88822
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -71433,11 +71433,30 @@ var SensorEventSchema = object({
71433
71433
  value: record(string(), unknown()).nullable(),
71434
71434
  timestamp: number()
71435
71435
  });
71436
+ /**
71437
+ * One stored sighting on a track's trajectory.
71438
+ *
71439
+ * The array these live in is returned in TIME order (D399) — it is APPENDED in
71440
+ * arrival order, and the two detector passes interleave, so a consumer must not
71441
+ * assume the two are the same on a row written by an older build.
71442
+ */
71436
71443
  var TrackPositionSchema = object({
71437
71444
  x: number(),
71438
71445
  y: number(),
71439
71446
  timestamp: number(),
71440
- bbox: BoundingBoxSchema
71447
+ bbox: BoundingBoxSchema,
71448
+ /**
71449
+ * Which detector pass measured this box (D399): `frame` is the full-frame
71450
+ * pass on the analysis raster, `recovery` is the native-resolution
71451
+ * small-subject second pass (D377/D378). Both write into one array, and until
71452
+ * this field existed the only way to tell them apart was that full-frame boxes
71453
+ * are exact multiples of 1.2 while recovery boxes are full-precision floats.
71454
+ * Absent on rows written before D399.
71455
+ */
71456
+ source: _enum(["frame", "recovery"]).optional(),
71457
+ /** Detection score of this box, so a position can be weighed and not only
71458
+ * plotted. Absent on rows written before D399. */
71459
+ score: number().optional()
71441
71460
  });
71442
71461
  var TrackSnapshotSchema = object({
71443
71462
  timestamp: number(),
@@ -71837,14 +71856,25 @@ var TrackSchema = object({
71837
71856
  */
71838
71857
  hasRider: boolean().optional(),
71839
71858
  /**
71840
- * WHY this track ended without a NATIVE best-shot tile
71841
- * ([D276](../decisions/adr-0276-a-stand-in-tile-is-provisional-and-a-close-says-why.md)) —
71859
+ * WHY this track ended without a NATIVE best-shot FRAME
71860
+ * ([D276](../decisions/adr-0276-a-stand-in-tile-is-provisional-and-a-close-says-why.md),
71861
+ * widened by [D400](../decisions/adr-0400-the-picture-is-judged-on-what-is-delivered.md)) —
71842
71862
  * a composed token line (`no-key-frame capture=keyframe:native-missx4`,
71843
- * `derive-returned-null tile=standin`, …) written at close and CLEARED by
71844
- * the late-keyFrame upgrade when a native tile lands after all. The
71845
- * operator-facing answer to "perché manca l'immagine?" on a track whose
71863
+ * `derive-returned-null tile=standin`,
71864
+ * `native-tile tile=native no-key-frame-at-close`, …) written at close and
71865
+ * CLEARED by the late-keyFrame upgrade when a native tile lands after all.
71866
+ * The operator-facing answer to "perché manca l'immagine?" on a track whose
71846
71867
  * tile is a face/plate stand-in, a raster crop, or an icon.
71847
71868
  *
71869
+ * **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
71870
+ * the TILE ranked below native, so a track whose thumbnail landed natively
71871
+ * while its key frame missed carried no reason at all — three of the four
71872
+ * `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
71873
+ * that shape, and their "niente ultimo" had no cause anywhere on the row.
71874
+ * The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
71875
+ * lastFrame copy source`), so its absence is now on this line whatever the
71876
+ * tile ended up being.
71877
+ *
71848
71878
  * **Absent ≠ "missed silently"**: a row written before the column, a hub
71849
71879
  * that predates the field, and every track whose tile landed native all
71850
71880
  * omit it. Render nothing when absent.
@@ -77933,6 +77963,59 @@ var IdentitySampleInfoSchema = object({
77933
77963
  deviceId: number().int().optional(),
77934
77964
  base64: string().optional()
77935
77965
  });
77966
+ /**
77967
+ * One enrolled sample, judged against the gallery it lives in.
77968
+ *
77969
+ * The gallery is the one input to recognition nobody re-reads: a sample
77970
+ * enrolled from the wrong face keeps voting forever, and because the matches it
77971
+ * pulls then look confident, nobody goes back. The 2026-09-08 audit found
77972
+ * exactly one such pair on this cluster — a sample scoring 0.61 against three
77973
+ * samples of ANOTHER person, enrolled from the same camera in the same minute,
77974
+ * where every other cross-identity pair sits under 0.50.
77975
+ */
77976
+ var IdentitySampleAuditRowSchema = object({
77977
+ sampleId: string(),
77978
+ enrolledAt: number().int(),
77979
+ deviceId: number().int().optional(),
77980
+ source: _enum(["detected", "photo"]),
77981
+ /** The enrolled crop's media key, so the panel can show the evidence. */
77982
+ mediaKey: string().optional(),
77983
+ /**
77984
+ * False = the sample is stamped with a DIFFERENT face model, and a cosine
77985
+ * across feature spaces is a well-formed float with no meaning. Every number
77986
+ * below then says nothing — it must read as "cannot say", never as an
77987
+ * accusation and never as a clean bill: this list ends in a Remove button.
77988
+ */
77989
+ comparable: boolean(),
77990
+ /** Mean cosine against this person's other samples. Null when there are none
77991
+ * to compare with — never 0, which would read as "opposite". */
77992
+ selfMean: number().nullable(),
77993
+ /** The other person this sample looks most like, when it looks like one.
77994
+ * This is the half that convicts: not looking like yourself can be a hard
77995
+ * angle; looking like someone the gallery can NAME is a mis-enrolment. */
77996
+ bestForeign: object({
77997
+ identityId: string(),
77998
+ name: string(),
77999
+ score: number()
78000
+ }).optional(),
78001
+ /** 0 = nothing to say. Higher = look at this one sooner. */
78002
+ suspicion: number()
78003
+ });
78004
+ var IdentitySampleAuditSchema = object({
78005
+ identityId: string(),
78006
+ name: string(),
78007
+ /** The cluster face model every comparison was made in. */
78008
+ modelId: string(),
78009
+ totalSamples: number().int(),
78010
+ comparableSamples: number().int(),
78011
+ flagged: number().int(),
78012
+ /** The bar `flagged` counts against, so the panel states the RULE and not
78013
+ * only its current result. */
78014
+ flagThreshold: number(),
78015
+ /** Worst first. A row with nothing to say still appears, at the bottom: the
78016
+ * operator asked to see the gallery, not only its accusations. */
78017
+ rows: array(IdentitySampleAuditRowSchema).readonly()
78018
+ });
77936
78019
  var FaceInfoSchema = object({
77937
78020
  faceId: string(),
77938
78021
  deviceId: number().int(),
@@ -78084,7 +78167,7 @@ includeCrops: boolean().optional() }).optional(), array(IdentitySchema).readonly
78084
78167
  }), method(object({ id: string() }), _void(), {
78085
78168
  kind: "mutation",
78086
78169
  auth: "admin"
78087
- }), method(object({ identityId: string() }), array(IdentitySampleInfoSchema).readonly()), method(object({
78170
+ }), method(object({ identityId: string() }), array(IdentitySampleInfoSchema).readonly()), method(object({ identityId: string().min(1) }), IdentitySampleAuditSchema, { auth: "admin" }), method(object({
78088
78171
  identityId: string(),
78089
78172
  sampleId: string()
78090
78173
  }), _void(), {
@@ -88725,6 +88808,12 @@ Object.freeze({
88725
88808
  addonId: null,
88726
88809
  access: "create"
88727
88810
  },
88811
+ "faceGallery.auditIdentitySamples": {
88812
+ capName: "face-gallery",
88813
+ capScope: "system",
88814
+ addonId: null,
88815
+ access: "view"
88816
+ },
88728
88817
  "faceGallery.createIdentity": {
88729
88818
  capName: "face-gallery",
88730
88819
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-dreame",
3
- "version": "0.2.83",
3
+ "version": "0.2.85",
4
4
  "description": "Dreame robot-vacuum / lawn-mower device-provider addon for CamStack — wraps the @apocaliss92/nodedreame Dreamehome cloud client",
5
5
  "keywords": [
6
6
  "camstack",