@camstack/addon-pipeline 1.2.151 → 1.2.152

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 (35) hide show
  1. package/dist/audio-analyzer/index.js +2 -2
  2. package/dist/audio-analyzer/index.mjs +2 -2
  3. package/dist/detection-pipeline/index.js +5 -5
  4. package/dist/detection-pipeline/index.mjs +4 -4
  5. package/dist/{dist-hmG3nfuW.js → dist-BpofTthV.js} +54 -7
  6. package/dist/{dist-BjzcUac4.mjs → dist-DoaR6NDJ.mjs} +54 -7
  7. package/dist/{lazy-sharp-RLE6klOt.js → lazy-sharp-D6sSNL-G.js} +1 -1
  8. package/dist/{local-frame-registry-Ct2vQ7Dp.js → local-frame-registry-4MCvZQ2t.js} +1 -1
  9. package/dist/{local-frame-registry-BFaxbRtK.mjs → local-frame-registry-Dr8irbU_.mjs} +1 -1
  10. package/dist/motion-wasm/index.js +2 -2
  11. package/dist/motion-wasm/index.mjs +1 -1
  12. package/dist/{node-U9fJ-bQN.mjs → node-CeSZTDKV.mjs} +1 -1
  13. package/dist/{node-BwXwfrvA.js → node-DG_kTYFM.js} +1 -1
  14. package/dist/pipeline-runner/index.js +5 -5
  15. package/dist/pipeline-runner/index.mjs +4 -4
  16. package/dist/{process-memory-4WDUPavu.mjs → process-memory-DJoquJSu.mjs} +1 -1
  17. package/dist/{process-memory-DR9jSxpX.js → process-memory-DglWLA3J.js} +1 -1
  18. package/dist/recorder/index.js +167 -28
  19. package/dist/recorder/index.mjs +167 -28
  20. package/dist/{segment-demux-js-kUN5AQVv.mjs → segment-demux-js-Clx6DzLe.mjs} +1 -1
  21. package/dist/{segment-demux-js-zqUNh3pj.js → segment-demux-js-DUSMkFTq.js} +1 -1
  22. package/dist/session-decode/decode-worker-child.js +2 -2
  23. package/dist/session-decode/decode-worker-child.mjs +1 -1
  24. package/dist/stream-broker/_stub.js +1 -1
  25. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BOXQSR0X.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BntoKYim.mjs} +3 -3
  26. package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CyIaTPRY.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-C-HJX19g.mjs} +1 -1
  27. package/dist/stream-broker/demux-worker-child.js +1 -1
  28. package/dist/stream-broker/demux-worker-child.mjs +1 -1
  29. package/dist/stream-broker/{hostInit-CnUhcNPG.mjs → hostInit--5tl1XaO.mjs} +3 -3
  30. package/dist/stream-broker/index.js +3 -3
  31. package/dist/stream-broker/index.mjs +3 -3
  32. package/dist/stream-broker/remoteEntry.js +1 -1
  33. package/dist/{worker-protocol-BzlEZ56r.mjs → worker-protocol-Ar0-GAh5.mjs} +1 -1
  34. package/dist/{worker-protocol-DE_jjbFA.js → worker-protocol-C8bHw-bu.js} +1 -1
  35. package/package.json +1 -1
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-hmG3nfuW.js");
6
- const require_process_memory = require("../process-memory-DR9jSxpX.js");
5
+ const require_dist = require("../dist-BpofTthV.js");
6
+ const require_process_memory = require("../process-memory-DglWLA3J.js");
7
7
  let node_fs = require("node:fs");
8
8
  node_fs = require_dist.__toESM(node_fs);
9
9
  let node_path = require("node:path");
@@ -1,6 +1,6 @@
1
1
  import { n as __require } from "../chunk-DnnnRqeS.mjs";
2
- import { A as audioAnalysisCapability, It as hydrateSchema, S as PoolMemoryWatchdog, _t as resolvePoolMemoryPolicy, j as audioAnalyzerCapability, jt as BaseAddon, n as AUDIO_BACKEND_CHOICES, nt as mapAudioLabelToMacro, s as DEFAULT_AUDIO_ANALYZER_CONFIG, v as HF_BASE_URL, wt as errMsg } from "../dist-BjzcUac4.mjs";
3
- import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-4WDUPavu.mjs";
2
+ import { A as audioAnalysisCapability, It as hydrateSchema, S as PoolMemoryWatchdog, _t as resolvePoolMemoryPolicy, j as audioAnalyzerCapability, jt as BaseAddon, n as AUDIO_BACKEND_CHOICES, nt as mapAudioLabelToMacro, s as DEFAULT_AUDIO_ANALYZER_CONFIG, v as HF_BASE_URL, wt as errMsg } from "../dist-DoaR6NDJ.mjs";
3
+ import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DJoquJSu.mjs";
4
4
  import * as fs from "node:fs";
5
5
  import * as path$1 from "node:path";
6
6
  import { downloadFile } from "@camstack/system/addon-utils";
@@ -2,12 +2,12 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-hmG3nfuW.js");
6
- const require_node = require("../node-BwXwfrvA.js");
7
- const require_local_frame_registry = require("../local-frame-registry-Ct2vQ7Dp.js");
8
- const require_lazy_sharp = require("../lazy-sharp-RLE6klOt.js");
5
+ const require_dist = require("../dist-BpofTthV.js");
6
+ const require_node = require("../node-DG_kTYFM.js");
7
+ const require_local_frame_registry = require("../local-frame-registry-4MCvZQ2t.js");
8
+ const require_lazy_sharp = require("../lazy-sharp-D6sSNL-G.js");
9
9
  const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-DaUBcb13.js");
10
- const require_process_memory = require("../process-memory-DR9jSxpX.js");
10
+ const require_process_memory = require("../process-memory-DglWLA3J.js");
11
11
  let node_fs = require("node:fs");
12
12
  node_fs = require_dist.__toESM(node_fs);
13
13
  let node_path = require("node:path");
@@ -1,10 +1,10 @@
1
1
  import { n as __require } from "../chunk-DnnnRqeS.mjs";
2
- import { Bt as nodePin, Ft as createEvent, It as hydrateSchema, Kt as array, O as YAMNET_TO_MACRO, Q as inferModelProvider, Qt as object, S as PoolMemoryWatchdog, St as supportedRuntimes$1, Vt as parseJsonUnknown, W as detectionPipelineCapability, Wt as sleep, Y as evaluateZoneRules, _t as resolvePoolMemoryPolicy, at as overlayClusterStepSettings, c as DEFAULT_CLUSTER_STEP_MODELS, ct as pickClusterStepSettings, dt as pipelineExecutorCapability, en as string, et as loadContributionCapability, ht as resolveClusterStepModelId, jt as BaseAddon, l as DEFAULT_CLUSTER_STEP_SETTINGS, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, q as enumerateInferenceDevices, st as pickClusterStepModels, t as APPLE_SA_TO_MACRO, tn as union, wt as errMsg, yt as runtimeDevices$1, z as defaultDeviceFor$1 } from "../dist-BjzcUac4.mjs";
3
- import { a as readProcessCost } from "../node-U9fJ-bQN.mjs";
4
- import { a as getDefaultModelForFormat, c as getStepDefinition, i as ALL_STEPS, l as resolveModelForFormat, o as getDefaultModelForFormatFromDef, r as ALL_PIPELINE_STEPS, s as getStep, t as localFrameRegistry, u as landmarkPrecisionVerdict } from "../local-frame-registry-BFaxbRtK.mjs";
2
+ import { Bt as nodePin, Ft as createEvent, It as hydrateSchema, Kt as array, O as YAMNET_TO_MACRO, Q as inferModelProvider, Qt as object, S as PoolMemoryWatchdog, St as supportedRuntimes$1, Vt as parseJsonUnknown, W as detectionPipelineCapability, Wt as sleep, Y as evaluateZoneRules, _t as resolvePoolMemoryPolicy, at as overlayClusterStepSettings, c as DEFAULT_CLUSTER_STEP_MODELS, ct as pickClusterStepSettings, dt as pipelineExecutorCapability, en as string, et as loadContributionCapability, ht as resolveClusterStepModelId, jt as BaseAddon, l as DEFAULT_CLUSTER_STEP_SETTINGS, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, q as enumerateInferenceDevices, st as pickClusterStepModels, t as APPLE_SA_TO_MACRO, tn as union, wt as errMsg, yt as runtimeDevices$1, z as defaultDeviceFor$1 } from "../dist-DoaR6NDJ.mjs";
3
+ import { a as readProcessCost } from "../node-CeSZTDKV.mjs";
4
+ import { a as getDefaultModelForFormat, c as getStepDefinition, i as ALL_STEPS, l as resolveModelForFormat, o as getDefaultModelForFormatFromDef, r as ALL_PIPELINE_STEPS, s as getStep, t as localFrameRegistry, u as landmarkPrecisionVerdict } from "../local-frame-registry-Dr8irbU_.mjs";
5
5
  import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
6
6
  import { n as startEventLoopStallMonitor } from "../event-loop-stall-monitor-DXLNBMkY.mjs";
7
- import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-4WDUPavu.mjs";
7
+ import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DJoquJSu.mjs";
8
8
  import * as fs from "node:fs";
9
9
  import * as path$1 from "node:path";
10
10
  import { spawn } from "node:child_process";
@@ -9338,6 +9338,21 @@ var RelocateJobSchema = object({
9338
9338
  bytesMoved: number().int(),
9339
9339
  /** Total files discovered up front; null while (or when) unknown. */
9340
9340
  filesTotal: number().int().nullable(),
9341
+ /**
9342
+ * Rows this run CORRECTED while moving them — a durable mutation the move
9343
+ * made that nobody asked for, so it is reported where the operator reads the
9344
+ * job rather than only in a log line.
9345
+ *
9346
+ * A footage segment records its byte count in its own NAME, and the durable
9347
+ * hour row derives its aggregates from those names. A file that does not
9348
+ * match its name therefore makes the ledger's sums — and with them quota and
9349
+ * pressure eviction — wrong by the difference, and only a rename can fix it.
9350
+ * On 2026-08-30 one such row also stalled a 110 749-file drain permanently.
9351
+ *
9352
+ * Absent on lanes where the question has no meaning: a media blob's size is
9353
+ * in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
9354
+ */
9355
+ rowsReconciled: number().int().nonnegative().optional(),
9341
9356
  startedAt: number(),
9342
9357
  finishedAt: number().nullable(),
9343
9358
  error: string().nullable()
@@ -9406,14 +9421,42 @@ var RelocateMediaInputSchema = object({
9406
9421
  /** Omitted = `move`, the pre-existing behaviour. */
9407
9422
  mode: MediaRelocateModeSchema.optional()
9408
9423
  });
9409
- /** How many rows still carry NO `locationId` — the population a repoint would
9410
- * silently re-aim at a disk that does not hold their bytes. Zero is the only
9411
- * value that permits a non-blocking `eventMedia` cutover. */
9412
- var UnstampedEventMediaCountSchema = object({
9413
- media: number().int().nonnegative(),
9414
- retrainFrames: number().int().nonnegative(),
9415
- total: number().int().nonnegative()
9424
+ /**
9425
+ * The unstamped population of ONE collection split, because the gate and the
9426
+ * operator ask two different questions and only one of them has to be cheap.
9427
+ *
9428
+ * `present` is the GATE: "is there at least one row that would be orphaned by a
9429
+ * repoint". It is a single indexed seek to the first matching row, so it stays
9430
+ * answerable on a saturated disk and answers in O(log n) precisely in the state
9431
+ * that matters — after a seal, when the population is empty.
9432
+ *
9433
+ * `rows` is the NUMBER, for the refusal message and the operator's sense of
9434
+ * scale. It is a second, indexed `COUNT(*)`, and `null` means **not
9435
+ * measurable** — never zero. `{ present: true, rows: null }` is a legitimate
9436
+ * and useful answer: "there are some, and this read could not say how many"
9437
+ * still refuses the cutover, which is the whole job.
9438
+ */
9439
+ var UnstampedRowsSchema = object({
9440
+ present: boolean(),
9441
+ rows: number().int().nonnegative().nullable()
9416
9442
  });
9443
+ /**
9444
+ * How many rows still carry NO `locationId` — the population a repoint would
9445
+ * silently re-aim at a disk that does not hold their bytes.
9446
+ *
9447
+ * **`null` = the count could not be taken**, and it is NOT permission to cut
9448
+ * over. The gate opens on a measured absence and on nothing else; an unread
9449
+ * collection and an empty one are different facts, and this repo has already
9450
+ * paid for conflating them (`RelocateResidueSchema`, D295).
9451
+ */
9452
+ var UnstampedEventMediaCountSchema = object({
9453
+ media: UnstampedRowsSchema,
9454
+ retrainFrames: UnstampedRowsSchema,
9455
+ /** True when EITHER collection holds one. The refusal reads this. */
9456
+ anyPresent: boolean(),
9457
+ /** Sum across both, or `null` when either lane could not be counted. */
9458
+ total: number().int().nonnegative().nullable()
9459
+ }).nullable();
9417
9460
  var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: string().min(1) });
9418
9461
  /** The independently selectable logical storage classes — every class
9419
9462
  * `storage.listLocationDeclarations` reports, so an operator never meets a
@@ -9524,6 +9567,10 @@ var StorageMigrationMoveProgressSchema = object({
9524
9567
  /** The archive census — the **M** of "N of M" (D295). `null` = unknowable. */
9525
9568
  filesTotal: number().int().nonnegative().nullable(),
9526
9569
  bytesMoved: number().int().nonnegative(),
9570
+ /** Rows the mover corrected while moving them — see `RelocateJob`. Absent on
9571
+ * a lane that cannot reconcile. A migration that silently rewrote durable
9572
+ * rows would be the same failure as one that silently skipped them. */
9573
+ rowsReconciled: number().int().nonnegative().optional(),
9527
9574
  /** The MOVER's start, not the migration's: a drain restarted after an addon
9528
9575
  * crash gets a new mover, and a rate computed from the migration's start
9529
9576
  * would silently average in the time nothing was running. */
@@ -9315,6 +9315,21 @@ var RelocateJobSchema = object({
9315
9315
  bytesMoved: number().int(),
9316
9316
  /** Total files discovered up front; null while (or when) unknown. */
9317
9317
  filesTotal: number().int().nullable(),
9318
+ /**
9319
+ * Rows this run CORRECTED while moving them — a durable mutation the move
9320
+ * made that nobody asked for, so it is reported where the operator reads the
9321
+ * job rather than only in a log line.
9322
+ *
9323
+ * A footage segment records its byte count in its own NAME, and the durable
9324
+ * hour row derives its aggregates from those names. A file that does not
9325
+ * match its name therefore makes the ledger's sums — and with them quota and
9326
+ * pressure eviction — wrong by the difference, and only a rename can fix it.
9327
+ * On 2026-08-30 one such row also stalled a 110 749-file drain permanently.
9328
+ *
9329
+ * Absent on lanes where the question has no meaning: a media blob's size is
9330
+ * in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
9331
+ */
9332
+ rowsReconciled: number().int().nonnegative().optional(),
9318
9333
  startedAt: number(),
9319
9334
  finishedAt: number().nullable(),
9320
9335
  error: string().nullable()
@@ -9383,14 +9398,42 @@ var RelocateMediaInputSchema = object({
9383
9398
  /** Omitted = `move`, the pre-existing behaviour. */
9384
9399
  mode: MediaRelocateModeSchema.optional()
9385
9400
  });
9386
- /** How many rows still carry NO `locationId` — the population a repoint would
9387
- * silently re-aim at a disk that does not hold their bytes. Zero is the only
9388
- * value that permits a non-blocking `eventMedia` cutover. */
9389
- var UnstampedEventMediaCountSchema = object({
9390
- media: number().int().nonnegative(),
9391
- retrainFrames: number().int().nonnegative(),
9392
- total: number().int().nonnegative()
9401
+ /**
9402
+ * The unstamped population of ONE collection split, because the gate and the
9403
+ * operator ask two different questions and only one of them has to be cheap.
9404
+ *
9405
+ * `present` is the GATE: "is there at least one row that would be orphaned by a
9406
+ * repoint". It is a single indexed seek to the first matching row, so it stays
9407
+ * answerable on a saturated disk and answers in O(log n) precisely in the state
9408
+ * that matters — after a seal, when the population is empty.
9409
+ *
9410
+ * `rows` is the NUMBER, for the refusal message and the operator's sense of
9411
+ * scale. It is a second, indexed `COUNT(*)`, and `null` means **not
9412
+ * measurable** — never zero. `{ present: true, rows: null }` is a legitimate
9413
+ * and useful answer: "there are some, and this read could not say how many"
9414
+ * still refuses the cutover, which is the whole job.
9415
+ */
9416
+ var UnstampedRowsSchema = object({
9417
+ present: boolean(),
9418
+ rows: number().int().nonnegative().nullable()
9393
9419
  });
9420
+ /**
9421
+ * How many rows still carry NO `locationId` — the population a repoint would
9422
+ * silently re-aim at a disk that does not hold their bytes.
9423
+ *
9424
+ * **`null` = the count could not be taken**, and it is NOT permission to cut
9425
+ * over. The gate opens on a measured absence and on nothing else; an unread
9426
+ * collection and an empty one are different facts, and this repo has already
9427
+ * paid for conflating them (`RelocateResidueSchema`, D295).
9428
+ */
9429
+ var UnstampedEventMediaCountSchema = object({
9430
+ media: UnstampedRowsSchema,
9431
+ retrainFrames: UnstampedRowsSchema,
9432
+ /** True when EITHER collection holds one. The refusal reads this. */
9433
+ anyPresent: boolean(),
9434
+ /** Sum across both, or `null` when either lane could not be counted. */
9435
+ total: number().int().nonnegative().nullable()
9436
+ }).nullable();
9394
9437
  var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: string().min(1) });
9395
9438
  /** The independently selectable logical storage classes — every class
9396
9439
  * `storage.listLocationDeclarations` reports, so an operator never meets a
@@ -9501,6 +9544,10 @@ var StorageMigrationMoveProgressSchema = object({
9501
9544
  /** The archive census — the **M** of "N of M" (D295). `null` = unknowable. */
9502
9545
  filesTotal: number().int().nonnegative().nullable(),
9503
9546
  bytesMoved: number().int().nonnegative(),
9547
+ /** Rows the mover corrected while moving them — see `RelocateJob`. Absent on
9548
+ * a lane that cannot reconcile. A migration that silently rewrote durable
9549
+ * rows would be the same failure as one that silently skipped them. */
9550
+ rowsReconciled: number().int().nonnegative().optional(),
9504
9551
  /** The MOVER's start, not the migration's: a drain restarted after an addon
9505
9552
  * crash gets a new mover, and a rate computed from the migration's start
9506
9553
  * would silently average in the time nothing was running. */
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-hmG3nfuW.js");
1
+ const require_dist = require("./dist-BpofTthV.js");
2
2
  let node_path = require("node:path");
3
3
  node_path = require_dist.__toESM(node_path);
4
4
  let node_url = require("node:url");
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-hmG3nfuW.js");
1
+ const require_dist = require("./dist-BpofTthV.js");
2
2
  let node_crypto = require("node:crypto");
3
3
  //#region src/detection-pipeline/registry/model-catalogs.ts
4
4
  var HF_REPO = "camstack/camstack-models";
@@ -1,4 +1,4 @@
1
- import { M as audioKindId, Z as hfModelUrl, a as COCO_80_LABELS, o as COCO_TO_MACRO, r as AUDIO_MACRO_LABELS } from "./dist-BjzcUac4.mjs";
1
+ import { M as audioKindId, Z as hfModelUrl, a as COCO_80_LABELS, o as COCO_TO_MACRO, r as AUDIO_MACRO_LABELS } from "./dist-DoaR6NDJ.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  //#region src/detection-pipeline/registry/model-catalogs.ts
4
4
  var HF_REPO = "camstack/camstack-models";
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-hmG3nfuW.js");
6
- const require_lazy_sharp = require("../lazy-sharp-RLE6klOt.js");
5
+ const require_dist = require("../dist-BpofTthV.js");
6
+ const require_lazy_sharp = require("../lazy-sharp-D6sSNL-G.js");
7
7
  let node_fs = require("node:fs");
8
8
  let node_path = require("node:path");
9
9
  //#region src/motion-wasm/wasm-motion-detector.ts
@@ -1,4 +1,4 @@
1
- import { It as hydrateSchema, Pt as DeviceType, Y as evaluateZoneRules, it as motionDetectionCapability, jt as BaseAddon } from "../dist-BjzcUac4.mjs";
1
+ import { It as hydrateSchema, Pt as DeviceType, Y as evaluateZoneRules, it as motionDetectionCapability, jt as BaseAddon } from "../dist-DoaR6NDJ.mjs";
2
2
  import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
3
3
  import { readFileSync } from "node:fs";
4
4
  import { join } from "node:path";
@@ -1,4 +1,4 @@
1
- import { Dt as buildFfmpegArgs, Et as Fmp4BoxSplitter, kt as isSoftwareDecode, wt as errMsg } from "./dist-BjzcUac4.mjs";
1
+ import { Dt as buildFfmpegArgs, Et as Fmp4BoxSplitter, kt as isSoftwareDecode, wt as errMsg } from "./dist-DoaR6NDJ.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import "node:fs";
4
4
  import "node:path";
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-hmG3nfuW.js");
1
+ const require_dist = require("./dist-BpofTthV.js");
2
2
  let node_crypto = require("node:crypto");
3
3
  let node_fs = require("node:fs");
4
4
  node_fs = require_dist.__toESM(node_fs, 1);
@@ -2,12 +2,12 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-hmG3nfuW.js");
6
- const require_node = require("../node-BwXwfrvA.js");
7
- const require_local_frame_registry = require("../local-frame-registry-Ct2vQ7Dp.js");
8
- const require_worker_protocol = require("../worker-protocol-DE_jjbFA.js");
5
+ const require_dist = require("../dist-BpofTthV.js");
6
+ const require_node = require("../node-DG_kTYFM.js");
7
+ const require_local_frame_registry = require("../local-frame-registry-4MCvZQ2t.js");
8
+ const require_worker_protocol = require("../worker-protocol-C8bHw-bu.js");
9
9
  const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
10
- const require_lazy_sharp = require("../lazy-sharp-RLE6klOt.js");
10
+ const require_lazy_sharp = require("../lazy-sharp-D6sSNL-G.js");
11
11
  const require_restream_intent = require("../restream-intent-Cv9x3jmu.js");
12
12
  const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-DaUBcb13.js");
13
13
  const require_remote_restream = require("../remote-restream-CO36Sr30.js");
@@ -1,7 +1,7 @@
1
- import { B as defineCustomActions, Bt as nodePin, Ft as createEvent, Gt as _enum, H as deriveDetailCropRect, Kt as array, L as customAction, Qt as object, X as failureContributionCapability, Xt as literal, Yt as lazy, Zt as number, _ as FailureCounters, en as string, et as loadContributionCapability, ft as pipelineRunnerCapability, jt as BaseAddon, lt as pickDetailCropConvention, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, p as DEFAULT_NATIVE_LEASE_SETTINGS, qt as boolean, u as DEFAULT_DETAIL_CROP_CONVENTION, ut as pickNativeLeaseOverride, wt as errMsg } from "../dist-BjzcUac4.mjs";
2
- import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-U9fJ-bQN.mjs";
3
- import { c as getStepDefinition, n as resolveFrameViewGeometry, t as localFrameRegistry } from "../local-frame-registry-BFaxbRtK.mjs";
4
- import { a as nativeLeaseSettingEnv, t as isWorkerReply } from "../worker-protocol-BzlEZ56r.mjs";
1
+ import { B as defineCustomActions, Bt as nodePin, Ft as createEvent, Gt as _enum, H as deriveDetailCropRect, Kt as array, L as customAction, Qt as object, X as failureContributionCapability, Xt as literal, Yt as lazy, Zt as number, _ as FailureCounters, en as string, et as loadContributionCapability, ft as pipelineRunnerCapability, jt as BaseAddon, lt as pickDetailCropConvention, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, p as DEFAULT_NATIVE_LEASE_SETTINGS, qt as boolean, u as DEFAULT_DETAIL_CROP_CONVENTION, ut as pickNativeLeaseOverride, wt as errMsg } from "../dist-DoaR6NDJ.mjs";
2
+ import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-CeSZTDKV.mjs";
3
+ import { c as getStepDefinition, n as resolveFrameViewGeometry, t as localFrameRegistry } from "../local-frame-registry-Dr8irbU_.mjs";
4
+ import { a as nativeLeaseSettingEnv, t as isWorkerReply } from "../worker-protocol-Ar0-GAh5.mjs";
5
5
  import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
6
6
  import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
7
7
  import { n as withDetectionIntent } from "../restream-intent-B4BXZra7.mjs";
@@ -1,4 +1,4 @@
1
- import { ot as parseProcStatus } from "./dist-BjzcUac4.mjs";
1
+ import { ot as parseProcStatus } from "./dist-DoaR6NDJ.mjs";
2
2
  import * as fs from "node:fs";
3
3
  import { execFile } from "node:child_process";
4
4
  //#region src/shared/node-topology-platform.ts
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-hmG3nfuW.js");
1
+ const require_dist = require("./dist-BpofTthV.js");
2
2
  let node_fs = require("node:fs");
3
3
  node_fs = require_dist.__toESM(node_fs);
4
4
  let node_child_process = require("node:child_process");
@@ -1,5 +1,5 @@
1
- const require_dist = require("../dist-hmG3nfuW.js");
2
- const require_node = require("../node-BwXwfrvA.js");
1
+ const require_dist = require("../dist-BpofTthV.js");
2
+ const require_node = require("../node-DG_kTYFM.js");
3
3
  const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
4
4
  const require_restream_intent = require("../restream-intent-Cv9x3jmu.js");
5
5
  const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-DaUBcb13.js");
@@ -1621,32 +1621,73 @@ function snapshot(j) {
1621
1621
  filesMoved: j.filesMoved,
1622
1622
  bytesMoved: j.bytesMoved,
1623
1623
  filesTotal: j.filesTotal,
1624
+ rowsReconciled: j.rowsReconciled,
1624
1625
  startedAt: j.startedAt,
1625
1626
  finishedAt: j.finishedAt,
1626
1627
  error: j.error
1627
1628
  };
1628
1629
  }
1629
1630
  /**
1630
- * One file's COPY: copy-if-absent → verify size. The source is left in place.
1631
+ * The row's source file is not on disk.
1632
+ *
1633
+ * Carries `code: 'ENOENT'` because that is how every caller here already tells
1634
+ * a ghost row from a real failure, and {@link copyVerified} now discovers the
1635
+ * absence with a `stat` rather than by letting `copyFile` raise it.
1636
+ */
1637
+ var RelocateSourceMissingError = class extends Error {
1638
+ code = "ENOENT";
1639
+ constructor(src) {
1640
+ super(`relocate source missing: ${src}`);
1641
+ this.name = "RelocateSourceMissingError";
1642
+ }
1643
+ };
1644
+ /**
1645
+ * One file's COPY: copy-if-absent → verify the destination against the SOURCE'S
1646
+ * OWN SIZE. The source is left in place.
1631
1647
  *
1632
1648
  * Split out of {@link moveFile} because the durable index re-point has to
1633
1649
  * happen while BOTH locations still hold the bytes — see
1634
- * `SegmentHourLedger.repointSegments`. Returns the bytes that were copied
1635
- * (0 when the destination already held a complete copy).
1650
+ * `SegmentHourLedger.repointSegments`.
1651
+ *
1652
+ * **`recordedBytes` is never the verify's reference.** It used to be, and it
1653
+ * cannot be: `fs.copyFile` truncates and replaces, so the destination always
1654
+ * equals the source, and comparing that result against a number the LEDGER
1655
+ * remembers can only ever fail when the ledger is wrong. On 2026-08-30 that
1656
+ * reported a byte-perfect copy as corruption and killed a 110 749-file drain
1657
+ * on its 12 440th file:
1658
+ *
1659
+ * relocate verify failed: …/1787926410000-9966-274432.m4s
1660
+ * is 783801B, expected 274432B
1661
+ *
1662
+ * Both files measured 783801 B on the hub. What is faithful is "the
1663
+ * destination equals the source", and that is what is asserted here; the
1664
+ * recorded number survives only as the reference for a destination whose
1665
+ * source is already GONE, where there is nothing else left to compare against.
1636
1666
  */
1637
- async function copyVerified(src, dst, srcBytes) {
1638
- let dstBytes = null;
1639
- try {
1640
- dstBytes = (await node_fs.promises.stat(dst)).size;
1641
- } catch {
1642
- dstBytes = null;
1643
- }
1644
- if (dstBytes === srcBytes) return 0;
1667
+ async function copyVerified(src, dst, recordedBytes) {
1668
+ const dstBytes = await fileSize(dst);
1669
+ const srcBytes = await fileSize(src);
1670
+ if (dstBytes !== null && dstBytes === (srcBytes ?? recordedBytes)) return {
1671
+ copied: 0,
1672
+ srcBytes: dstBytes
1673
+ };
1674
+ if (srcBytes === null) throw new RelocateSourceMissingError(src);
1645
1675
  await node_fs.promises.mkdir(node_path.default.dirname(dst), { recursive: true });
1646
1676
  await node_fs.promises.copyFile(src, dst);
1647
1677
  const after = await node_fs.promises.stat(dst);
1648
1678
  if (after.size !== srcBytes) throw new Error(`relocate verify failed: ${dst} is ${after.size}B, expected ${srcBytes}B`);
1649
- return srcBytes;
1679
+ return {
1680
+ copied: srcBytes,
1681
+ srcBytes
1682
+ };
1683
+ }
1684
+ /** A file's size, or `null` when it is not there. */
1685
+ async function fileSize(p) {
1686
+ try {
1687
+ return (await node_fs.promises.stat(p)).size;
1688
+ } catch {
1689
+ return null;
1690
+ }
1650
1691
  }
1651
1692
  var RelocateEngine = class {
1652
1693
  deps;
@@ -1700,6 +1741,14 @@ var RelocateEngine = class {
1700
1741
  if (!to) throw new Error(`unknown target location: ${input.toLocationId}`);
1701
1742
  if (from.id === to.id) throw new Error("source and target locations are identical");
1702
1743
  if (to.readOnly) throw new Error(`target location is read-only: ${to.id}`);
1744
+ if (to.enabled === false) this.deps.logger.warn("relocate: target location is DISABLED (standby) — moving to it because the operator named it; placement still never chooses it for new writes", {
1745
+ ...input.deviceId !== void 0 ? { tags: { deviceId: input.deviceId } } : {},
1746
+ meta: {
1747
+ fromLocationId: from.id,
1748
+ toLocationId: to.id,
1749
+ footageClass: input.footageClass ?? null
1750
+ }
1751
+ });
1703
1752
  const job = {
1704
1753
  jobId: this.deps.newId(),
1705
1754
  state: "queued",
@@ -1714,6 +1763,7 @@ var RelocateEngine = class {
1714
1763
  filesMoved: 0,
1715
1764
  bytesMoved: 0,
1716
1765
  filesTotal: null,
1766
+ rowsReconciled: 0,
1717
1767
  startedAt: this.deps.now(),
1718
1768
  finishedAt: null,
1719
1769
  error: null,
@@ -1867,7 +1917,8 @@ var RelocateEngine = class {
1867
1917
  toLocationId: job.toLocationId,
1868
1918
  archiveSegments: job.filesTotal,
1869
1919
  seen,
1870
- moved: job.filesMoved
1920
+ moved: job.filesMoved,
1921
+ rowsReconciled: job.rowsReconciled
1871
1922
  };
1872
1923
  if (archive === null) {
1873
1924
  this.deps.logger.warn("relocate: coverage UNKNOWN — with no durable ledger this node cannot say what the source still holds", {
@@ -1962,6 +2013,56 @@ var RelocateEngine = class {
1962
2013
  return `${DESTINATION_FULL_PREFIX}: ${to.id} has ${(Math.round(free * 100) / 100).toString()}% free, below its ${floor.toString()}% floor — everything not yet moved is still readable at ${job.fromLocationId}`;
1963
2014
  }
1964
2015
  /**
2016
+ * The row as the TARGET should record it, given what the source file
2017
+ * actually measured.
2018
+ *
2019
+ * Equal sizes — every ordinary segment — hand the row straight back. A
2020
+ * disagreement is reconciled rather than carried over, and reconciling it
2021
+ * means RENAMING: a segment's byte count is part of its name
2022
+ * (`segmentRelPath`), the durable hour row derives `bytes` from those names
2023
+ * (`hourAggregate`), and those sums are what `StorageEvictableProvider` reads
2024
+ * when a disk fills. Copying the file under its wrong name would carry the
2025
+ * wrong number to the new disk and leave nothing able to correct it — a disk
2026
+ * walk re-parses the same name and agrees with itself.
2027
+ *
2028
+ * The rename happens at the DESTINATION, before the ledger is touched, so a
2029
+ * crash here leaves the source wholly authoritative and untouched: the next
2030
+ * run re-copies under the old name and re-renames. Nothing is dropped
2031
+ * silently — every re-stamp is one `warn` with `tags: { deviceId }` and both
2032
+ * numbers, and the count rides the job record to the operator.
2033
+ */
2034
+ async reconciled(job, row, to, srcBytes) {
2035
+ if (srcBytes === row.bytes) return row;
2036
+ const fixed = restampSegmentBytes(row, srcBytes);
2037
+ if (fixed === null) {
2038
+ this.deps.logger.warn("relocate: the recorded size disagrees with the file, and the path is not a canonical segment name — moved as-is, the durable byte count stays WRONG", {
2039
+ tags: { deviceId: row.deviceId },
2040
+ meta: {
2041
+ jobId: job.jobId,
2042
+ path: row.path,
2043
+ recordedBytes: row.bytes,
2044
+ actualBytes: srcBytes
2045
+ }
2046
+ });
2047
+ return row;
2048
+ }
2049
+ await node_fs.promises.rename(node_path.default.join(to.root, row.path), node_path.default.join(to.root, fixed.path));
2050
+ job.rowsReconciled += 1;
2051
+ this.deps.logger.warn("relocate: RECONCILED a row whose recorded size disagreed with the file — the file is the fact, the name and the durable row now say so", {
2052
+ tags: { deviceId: row.deviceId },
2053
+ meta: {
2054
+ jobId: job.jobId,
2055
+ fromPath: row.path,
2056
+ toPath: fixed.path,
2057
+ recordedBytes: row.bytes,
2058
+ actualBytes: srcBytes,
2059
+ deltaBytes: srcBytes - row.bytes,
2060
+ toLocationId: to.id
2061
+ }
2062
+ });
2063
+ return fixed;
2064
+ }
2065
+ /**
1965
2066
  * Move ONE hour of one (device, profile): copy+verify every file, re-point
1966
2067
  * the durable hour row, delete the sources, re-point the RAM index.
1967
2068
  *
@@ -1980,9 +2081,12 @@ var RelocateEngine = class {
1980
2081
  if (job.cancelRequested) return;
1981
2082
  const src = node_path.default.join(from.root, row.path);
1982
2083
  const dst = node_path.default.join(to.root, row.path);
2084
+ let pacedBytes = row.bytes;
1983
2085
  try {
1984
- copiedBytes += await copyVerified(src, dst, row.bytes);
1985
- movable.push(row);
2086
+ const outcome = await copyVerified(src, dst, row.bytes);
2087
+ pacedBytes = outcome.srcBytes;
2088
+ copiedBytes += outcome.copied;
2089
+ movable.push(await this.reconciled(job, row, to, outcome.srcBytes));
1986
2090
  } catch (err) {
1987
2091
  if (!isEnoent(err)) throw err;
1988
2092
  this.deps.index.removeSegments([row.path]);
@@ -1994,7 +2098,7 @@ var RelocateEngine = class {
1994
2098
  }
1995
2099
  });
1996
2100
  }
1997
- await sleep(row.bytes / bytesPerMs);
2101
+ await sleep(pacedBytes / bytesPerMs);
1998
2102
  }
1999
2103
  if (movable.length === 0) return;
2000
2104
  if (job.cancelRequested) return;
@@ -2017,11 +2121,16 @@ var RelocateEngine = class {
2017
2121
  });
2018
2122
  return;
2019
2123
  }
2020
- if (!samePhysicalRoot) for (const row of movable) await node_fs.promises.rm(node_path.default.join(from.root, row.path), { force: true });
2124
+ if (!samePhysicalRoot) for (const row of movable) await node_fs.promises.rm(node_path.default.join(from.root, row.fromPath ?? row.path), { force: true });
2021
2125
  for (const row of movable) {
2022
- this.deps.index.removeSegments([row.path]);
2126
+ this.deps.index.removeSegments([row.fromPath ?? row.path]);
2023
2127
  this.deps.index.addSegment({
2024
- ...row,
2128
+ deviceId: row.deviceId,
2129
+ profile: row.profile,
2130
+ startMs: row.startMs,
2131
+ durMs: row.durMs,
2132
+ bytes: row.bytes,
2133
+ path: row.path,
2025
2134
  locationId: to.id
2026
2135
  });
2027
2136
  }
@@ -2031,6 +2140,25 @@ var RelocateEngine = class {
2031
2140
  }
2032
2141
  };
2033
2142
  /**
2143
+ * The same segment, recorded at its REAL size — or `null` when this path is not
2144
+ * one this repo names, in which case nothing here may rename it.
2145
+ *
2146
+ * The refusal is a round-trip, not a shape guess: the canonical name for the
2147
+ * row's own fields must reproduce `row.path` exactly before the corrected name
2148
+ * is trusted. A path that fails it came from somewhere else (a hand-placed
2149
+ * file, a future layout), and renaming it would move footage to a name no
2150
+ * reader derives.
2151
+ */
2152
+ function restampSegmentBytes(row, actualBytes) {
2153
+ if (segmentRelPath(row.deviceId, row.profile, row.startMs, row.durMs, row.bytes) !== row.path) return null;
2154
+ return {
2155
+ ...row,
2156
+ bytes: actualBytes,
2157
+ path: segmentRelPath(row.deviceId, row.profile, row.startMs, row.durMs, actualBytes),
2158
+ fromPath: row.path
2159
+ };
2160
+ }
2161
+ /**
2034
2162
  * The archive slice this job moves, or `null` when it selects nothing at all.
2035
2163
  *
2036
2164
  * ONE derivation for the census and for the stream. Deriving them separately
@@ -8630,6 +8758,13 @@ var SegmentHourLedger = class SegmentHourLedger {
8630
8758
  * the index `hydrated`: nothing would ever walk that hour again, and the
8631
8759
  * segment would sit on disk permanently unreachable.
8632
8760
  *
8761
+ * **Two path sets, not one.** A path can arrive at the target under a
8762
+ * DIFFERENT name than it leaves the source under: a mover that found a file
8763
+ * larger than its recorded size reconciles the row, and the byte count is
8764
+ * part of the name. So the source row is shrunk by what is LEAVING it and the
8765
+ * target row grows by what is ARRIVING — conflating them would leave the
8766
+ * source row naming a file the caller is about to delete.
8767
+ *
8633
8768
  * Returns `false` when NOTHING was repointed and the caller must delete
8634
8769
  * nothing. An hour whose detail could not be read decides nothing (D49) —
8635
8770
  * the same refusal {@link dropSegments} makes for eviction.
@@ -8642,11 +8777,15 @@ var SegmentHourLedger = class SegmentHourLedger {
8642
8777
  const entry = byHour.get(key);
8643
8778
  if (entry === void 0) byHour.set(key, {
8644
8779
  row,
8645
- paths: new Set([row.path])
8780
+ leaving: new Set([row.fromPath ?? row.path]),
8781
+ arriving: new Set([row.path])
8646
8782
  });
8647
- else entry.paths.add(row.path);
8783
+ else {
8784
+ entry.leaving.add(row.fromPath ?? row.path);
8785
+ entry.arriving.add(row.path);
8786
+ }
8648
8787
  }
8649
- for (const [sourceKey, { row, paths }] of byHour) {
8788
+ for (const [sourceKey, { row, leaving, arriving }] of byHour) {
8650
8789
  const held = await this.resident(sourceKey, row.deviceId);
8651
8790
  if (held === null) {
8652
8791
  this.logger.warn("recorder: hour detail unavailable — this relocation is REFUSED and nothing is deleted; the segments stay where they are", {
@@ -8654,7 +8793,7 @@ var SegmentHourLedger = class SegmentHourLedger {
8654
8793
  meta: {
8655
8794
  key: sourceKey,
8656
8795
  toLocationId,
8657
- paths: paths.size
8796
+ paths: leaving.size
8658
8797
  }
8659
8798
  });
8660
8799
  return false;
@@ -8667,12 +8806,12 @@ var SegmentHourLedger = class SegmentHourLedger {
8667
8806
  meta: {
8668
8807
  key: targetKey,
8669
8808
  fromLocationId: row.locationId,
8670
- paths: paths.size
8809
+ paths: arriving.size
8671
8810
  }
8672
8811
  });
8673
8812
  return false;
8674
8813
  }
8675
- const merged = uniquePaths([...target?.paths ?? [], ...paths]);
8814
+ const merged = uniquePaths([...target?.paths ?? [], ...arriving]);
8676
8815
  await this.ledger.put(segmentHourRow({
8677
8816
  key: targetKey,
8678
8817
  deviceId: row.deviceId,
@@ -8681,7 +8820,7 @@ var SegmentHourLedger = class SegmentHourLedger {
8681
8820
  hourStartMs: held.hourStartMs,
8682
8821
  paths: merged
8683
8822
  }));
8684
- const next = held.paths.filter((p) => !paths.has(p));
8823
+ const next = held.paths.filter((p) => !leaving.has(p));
8685
8824
  if (next.length === 0) await this.ledger.forget(sourceKey);
8686
8825
  else await this.ledger.put(segmentHourRow({
8687
8826
  ...held,