@camstack/addon-export-google 0.1.9 → 0.1.10

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.
@@ -8196,6 +8196,21 @@ var RelocateJobSchema = object({
8196
8196
  bytesMoved: number().int(),
8197
8197
  /** Total files discovered up front; null while (or when) unknown. */
8198
8198
  filesTotal: number().int().nullable(),
8199
+ /**
8200
+ * Rows this run CORRECTED while moving them — a durable mutation the move
8201
+ * made that nobody asked for, so it is reported where the operator reads the
8202
+ * job rather than only in a log line.
8203
+ *
8204
+ * A footage segment records its byte count in its own NAME, and the durable
8205
+ * hour row derives its aggregates from those names. A file that does not
8206
+ * match its name therefore makes the ledger's sums — and with them quota and
8207
+ * pressure eviction — wrong by the difference, and only a rename can fix it.
8208
+ * On 2026-08-30 one such row also stalled a 110 749-file drain permanently.
8209
+ *
8210
+ * Absent on lanes where the question has no meaning: a media blob's size is
8211
+ * in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
8212
+ */
8213
+ rowsReconciled: number().int().nonnegative().optional(),
8199
8214
  startedAt: number(),
8200
8215
  finishedAt: number().nullable(),
8201
8216
  error: string().nullable()
@@ -8264,14 +8279,42 @@ var RelocateMediaInputSchema = object({
8264
8279
  /** Omitted = `move`, the pre-existing behaviour. */
8265
8280
  mode: MediaRelocateModeSchema.optional()
8266
8281
  });
8267
- /** How many rows still carry NO `locationId` — the population a repoint would
8268
- * silently re-aim at a disk that does not hold their bytes. Zero is the only
8269
- * value that permits a non-blocking `eventMedia` cutover. */
8270
- var UnstampedEventMediaCountSchema = object({
8271
- media: number().int().nonnegative(),
8272
- retrainFrames: number().int().nonnegative(),
8273
- total: number().int().nonnegative()
8282
+ /**
8283
+ * The unstamped population of ONE collection split, because the gate and the
8284
+ * operator ask two different questions and only one of them has to be cheap.
8285
+ *
8286
+ * `present` is the GATE: "is there at least one row that would be orphaned by a
8287
+ * repoint". It is a single indexed seek to the first matching row, so it stays
8288
+ * answerable on a saturated disk and answers in O(log n) precisely in the state
8289
+ * that matters — after a seal, when the population is empty.
8290
+ *
8291
+ * `rows` is the NUMBER, for the refusal message and the operator's sense of
8292
+ * scale. It is a second, indexed `COUNT(*)`, and `null` means **not
8293
+ * measurable** — never zero. `{ present: true, rows: null }` is a legitimate
8294
+ * and useful answer: "there are some, and this read could not say how many"
8295
+ * still refuses the cutover, which is the whole job.
8296
+ */
8297
+ var UnstampedRowsSchema = object({
8298
+ present: boolean(),
8299
+ rows: number().int().nonnegative().nullable()
8274
8300
  });
8301
+ /**
8302
+ * How many rows still carry NO `locationId` — the population a repoint would
8303
+ * silently re-aim at a disk that does not hold their bytes.
8304
+ *
8305
+ * **`null` = the count could not be taken**, and it is NOT permission to cut
8306
+ * over. The gate opens on a measured absence and on nothing else; an unread
8307
+ * collection and an empty one are different facts, and this repo has already
8308
+ * paid for conflating them (`RelocateResidueSchema`, D295).
8309
+ */
8310
+ var UnstampedEventMediaCountSchema = object({
8311
+ media: UnstampedRowsSchema,
8312
+ retrainFrames: UnstampedRowsSchema,
8313
+ /** True when EITHER collection holds one. The refusal reads this. */
8314
+ anyPresent: boolean(),
8315
+ /** Sum across both, or `null` when either lane could not be counted. */
8316
+ total: number().int().nonnegative().nullable()
8317
+ }).nullable();
8275
8318
  var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: string().min(1) });
8276
8319
  /** The independently selectable logical storage classes — every class
8277
8320
  * `storage.listLocationDeclarations` reports, so an operator never meets a
@@ -8382,6 +8425,10 @@ var StorageMigrationMoveProgressSchema = object({
8382
8425
  /** The archive census — the **M** of "N of M" (D295). `null` = unknowable. */
8383
8426
  filesTotal: number().int().nonnegative().nullable(),
8384
8427
  bytesMoved: number().int().nonnegative(),
8428
+ /** Rows the mover corrected while moving them — see `RelocateJob`. Absent on
8429
+ * a lane that cannot reconcile. A migration that silently rewrote durable
8430
+ * rows would be the same failure as one that silently skipped them. */
8431
+ rowsReconciled: number().int().nonnegative().optional(),
8385
8432
  /** The MOVER's start, not the migration's: a drain restarted after an addon
8386
8433
  * crash gets a new mover, and a rate computed from the migration's start
8387
8434
  * would silently average in the time nothing was running. */
@@ -8192,6 +8192,21 @@ var RelocateJobSchema = object({
8192
8192
  bytesMoved: number().int(),
8193
8193
  /** Total files discovered up front; null while (or when) unknown. */
8194
8194
  filesTotal: number().int().nullable(),
8195
+ /**
8196
+ * Rows this run CORRECTED while moving them — a durable mutation the move
8197
+ * made that nobody asked for, so it is reported where the operator reads the
8198
+ * job rather than only in a log line.
8199
+ *
8200
+ * A footage segment records its byte count in its own NAME, and the durable
8201
+ * hour row derives its aggregates from those names. A file that does not
8202
+ * match its name therefore makes the ledger's sums — and with them quota and
8203
+ * pressure eviction — wrong by the difference, and only a rename can fix it.
8204
+ * On 2026-08-30 one such row also stalled a 110 749-file drain permanently.
8205
+ *
8206
+ * Absent on lanes where the question has no meaning: a media blob's size is
8207
+ * in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
8208
+ */
8209
+ rowsReconciled: number().int().nonnegative().optional(),
8195
8210
  startedAt: number(),
8196
8211
  finishedAt: number().nullable(),
8197
8212
  error: string().nullable()
@@ -8260,14 +8275,42 @@ var RelocateMediaInputSchema = object({
8260
8275
  /** Omitted = `move`, the pre-existing behaviour. */
8261
8276
  mode: MediaRelocateModeSchema.optional()
8262
8277
  });
8263
- /** How many rows still carry NO `locationId` — the population a repoint would
8264
- * silently re-aim at a disk that does not hold their bytes. Zero is the only
8265
- * value that permits a non-blocking `eventMedia` cutover. */
8266
- var UnstampedEventMediaCountSchema = object({
8267
- media: number().int().nonnegative(),
8268
- retrainFrames: number().int().nonnegative(),
8269
- total: number().int().nonnegative()
8278
+ /**
8279
+ * The unstamped population of ONE collection split, because the gate and the
8280
+ * operator ask two different questions and only one of them has to be cheap.
8281
+ *
8282
+ * `present` is the GATE: "is there at least one row that would be orphaned by a
8283
+ * repoint". It is a single indexed seek to the first matching row, so it stays
8284
+ * answerable on a saturated disk and answers in O(log n) precisely in the state
8285
+ * that matters — after a seal, when the population is empty.
8286
+ *
8287
+ * `rows` is the NUMBER, for the refusal message and the operator's sense of
8288
+ * scale. It is a second, indexed `COUNT(*)`, and `null` means **not
8289
+ * measurable** — never zero. `{ present: true, rows: null }` is a legitimate
8290
+ * and useful answer: "there are some, and this read could not say how many"
8291
+ * still refuses the cutover, which is the whole job.
8292
+ */
8293
+ var UnstampedRowsSchema = object({
8294
+ present: boolean(),
8295
+ rows: number().int().nonnegative().nullable()
8270
8296
  });
8297
+ /**
8298
+ * How many rows still carry NO `locationId` — the population a repoint would
8299
+ * silently re-aim at a disk that does not hold their bytes.
8300
+ *
8301
+ * **`null` = the count could not be taken**, and it is NOT permission to cut
8302
+ * over. The gate opens on a measured absence and on nothing else; an unread
8303
+ * collection and an empty one are different facts, and this repo has already
8304
+ * paid for conflating them (`RelocateResidueSchema`, D295).
8305
+ */
8306
+ var UnstampedEventMediaCountSchema = object({
8307
+ media: UnstampedRowsSchema,
8308
+ retrainFrames: UnstampedRowsSchema,
8309
+ /** True when EITHER collection holds one. The refusal reads this. */
8310
+ anyPresent: boolean(),
8311
+ /** Sum across both, or `null` when either lane could not be counted. */
8312
+ total: number().int().nonnegative().nullable()
8313
+ }).nullable();
8271
8314
  var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: string().min(1) });
8272
8315
  /** The independently selectable logical storage classes — every class
8273
8316
  * `storage.listLocationDeclarations` reports, so an operator never meets a
@@ -8378,6 +8421,10 @@ var StorageMigrationMoveProgressSchema = object({
8378
8421
  /** The archive census — the **M** of "N of M" (D295). `null` = unknowable. */
8379
8422
  filesTotal: number().int().nonnegative().nullable(),
8380
8423
  bytesMoved: number().int().nonnegative(),
8424
+ /** Rows the mover corrected while moving them — see `RelocateJob`. Absent on
8425
+ * a lane that cannot reconcile. A migration that silently rewrote durable
8426
+ * rows would be the same failure as one that silently skipped them. */
8427
+ rowsReconciled: number().int().nonnegative().optional(),
8381
8428
  /** The MOVER's start, not the migration's: a drain restarted after an addon
8382
8429
  * crash gets a new mover, and a rate computed from the migration's start
8383
8430
  * would silently average in the time nothing was running. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-google",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Google Home export — hub-side smart-home fulfillment (SYNC / QUERY / EXECUTE / DISCONNECT) for the non-camera fleet, served over the hub's own OAuth account link. No Google credential is stored, sent or required.",
5
5
  "keywords": [
6
6
  "camstack",