@camstack/system 1.1.56 → 1.1.58

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 (51) hide show
  1. package/dist/addon-runner.js +2 -2
  2. package/dist/addon-runner.mjs +2 -2
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.js +1 -1
  8. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  9. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  10. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  11. package/dist/builtins/console-logging/index.js +1 -1
  12. package/dist/builtins/console-logging/index.mjs +1 -1
  13. package/dist/builtins/device-manager/device-manager.addon.js +1 -1
  14. package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
  15. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  16. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  17. package/dist/builtins/hub-forwarder/index.js +1 -1
  18. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  19. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  20. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  21. package/dist/builtins/local-network/local-network.addon.js +1 -1
  22. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  23. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  24. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  25. package/dist/builtins/platform-probe/index.js +1 -1
  26. package/dist/builtins/platform-probe/index.mjs +1 -1
  27. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  28. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  29. package/dist/builtins/snapshot/index.js +1 -1
  30. package/dist/builtins/snapshot/index.mjs +1 -1
  31. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  32. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  33. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
  34. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
  35. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  36. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  37. package/dist/builtins/system-config/system-config.addon.js +1 -1
  38. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  39. package/dist/builtins/winston-logging/index.js +1 -1
  40. package/dist/builtins/winston-logging/index.mjs +1 -1
  41. package/dist/{dist-JAF9YR1q.mjs → dist-BNevCEAo.mjs} +0 -70
  42. package/dist/{dist-Bg795EQF.js → dist-BY6NWf-c.js} +0 -70
  43. package/dist/index.js +44 -107
  44. package/dist/index.mjs +45 -106
  45. package/dist/kernel/addon-loader.d.ts +7 -2
  46. package/dist/kernel/index.d.ts +1 -3
  47. package/dist/kernel/lifecycle/lifecycle-job-engine.d.ts +21 -26
  48. package/dist/{manifest-python-deps-eI3-3FeW.js → manifest-python-deps-D2G0DFWp.js} +1 -1
  49. package/dist/{manifest-python-deps-9wuRyL-k.mjs → manifest-python-deps-DtCMZhuR.mjs} +1 -1
  50. package/package.json +1 -1
  51. package/dist/kernel/lifecycle/framework-staging.d.ts +0 -15
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk-Cek0wNdY.js");
3
- const require_dist = require("./dist-Bg795EQF.js");
3
+ const require_dist = require("./dist-BY6NWf-c.js");
4
4
  const require_model_download_service = require("./model-download-service-hf0ookyy.js");
5
- const require_manifest_python_deps = require("./manifest-python-deps-eI3-3FeW.js");
5
+ const require_manifest_python_deps = require("./manifest-python-deps-D2G0DFWp.js");
6
6
  const require_resource_monitor = require("./resource-monitor-DNNomR-i.js");
7
7
  const require_builtins_sqlite_storage_filesystem_storage_addon = require("./builtins/sqlite-storage/filesystem-storage.addon.js");
8
8
  const require_builtins_sqlite_storage_sqlite_settings_addon = require("./builtins/sqlite-storage/sqlite-settings.addon.js");
@@ -2308,9 +2308,15 @@ var AddonLoader = class {
2308
2308
  else i++;
2309
2309
  }
2310
2310
  /** Scan addons directory and load all addon packages.
2311
- * Supports scoped layout: addons/@scope/package-name/ */
2312
- async loadFromDirectory(addonsDir) {
2311
+ * Supports scoped layout: addons/@scope/package-name/
2312
+ *
2313
+ * `skipPackages` names scoped packages (e.g. `@camstack/system`) that the
2314
+ * caller loads from elsewhere — the single-copy model loads the framework
2315
+ * BUILTINS from the active closure, not the (now-inert) addons-dir copy, so
2316
+ * the addons-dir `@camstack/system` must NOT be double-loaded here. */
2317
+ async loadFromDirectory(addonsDir, skipPackages = []) {
2313
2318
  if (!node_fs.existsSync(addonsDir)) return;
2319
+ const skip = new Set(skipPackages);
2314
2320
  const entries = node_fs.readdirSync(addonsDir, { withFileTypes: true });
2315
2321
  for (const entry of entries) {
2316
2322
  if (!isDirectoryEntry(entry, addonsDir)) continue;
@@ -2319,10 +2325,12 @@ var AddonLoader = class {
2319
2325
  const scopeEntries = node_fs.readdirSync(scopeDir, { withFileTypes: true });
2320
2326
  for (const scopeEntry of scopeEntries) {
2321
2327
  if (!isDirectoryEntry(scopeEntry, scopeDir)) continue;
2328
+ if (skip.has(`${entry.name}/${scopeEntry.name}`)) continue;
2322
2329
  await this.tryLoadAddon(node_path.join(scopeDir, scopeEntry.name));
2323
2330
  }
2324
2331
  continue;
2325
2332
  }
2333
+ if (skip.has(entry.name)) continue;
2326
2334
  await this.tryLoadAddon(node_path.join(addonsDir, entry.name));
2327
2335
  }
2328
2336
  }
@@ -93071,7 +93079,7 @@ var JobJournal = class {
93071
93079
  };
93072
93080
  //#endregion
93073
93081
  //#region src/kernel/lifecycle/staging-area.ts
93074
- function safeSegment$1(name) {
93082
+ function safeSegment(name) {
93075
93083
  return name.replace(/[^a-zA-Z0-9._-]/g, "_");
93076
93084
  }
93077
93085
  var StagingArea = class {
@@ -93082,7 +93090,7 @@ var StagingArea = class {
93082
93090
  this.deps = deps;
93083
93091
  }
93084
93092
  async fetchAndStage(input) {
93085
- const destDir = node_path.join(this.stagingDir, input.jobId, safeSegment$1(input.name));
93093
+ const destDir = node_path.join(this.stagingDir, input.jobId, safeSegment(input.name));
93086
93094
  node_fs.rmSync(destDir, {
93087
93095
  recursive: true,
93088
93096
  force: true
@@ -93218,50 +93226,22 @@ var LifecycleJobEngine = class {
93218
93226
  }
93219
93227
  }
93220
93228
  /**
93221
- * Run the framework task: stage lockstep → `staged` → requestFrameworkSwap.
93222
- * In production the process exits after requestFrameworkSwap and the reboot
93223
- * finalizes the job, so this returns the current durable job WITHOUT
93224
- * finalization. Returns null only if the framework deps are not wired (the
93225
- * task is marked `failed` and the caller finalizes the job).
93226
- */
93227
- async runFrameworkTask(job, task) {
93228
- const { stageFramework, requestFrameworkSwap } = this.deps;
93229
- if (stageFramework === void 0 || requestFrameworkSwap === void 0) {
93230
- this.advance(job.jobId, task, "failed", {
93231
- error: "framework swap deps not wired",
93232
- finishedAtMs: this.deps.now()
93233
- });
93234
- return null;
93235
- }
93236
- try {
93237
- this.advance(job.jobId, task, "fetching", {
93238
- startedAtMs: this.deps.now(),
93239
- attempts: task.attempts + 1
93240
- });
93241
- const ac = new AbortController();
93242
- const timer = setTimeout(() => ac.abort(), this.deps.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS);
93243
- let packages;
93244
- try {
93245
- packages = await stageFramework(task, ac.signal);
93246
- } finally {
93247
- clearTimeout(timer);
93248
- }
93249
- const [firstPackage] = packages;
93250
- if (!firstPackage) throw new Error("stageFramework returned no packages");
93251
- this.advance(job.jobId, task, "staged", { stagedPath: firstPackage.stagedPath });
93252
- requestFrameworkSwap({
93253
- jobId: job.jobId,
93254
- taskId: task.taskId,
93255
- packages
93256
- });
93257
- return this.deps.journal.getJob(job.jobId) ?? job;
93258
- } catch (err) {
93259
- this.advance(job.jobId, task, "failed", {
93260
- error: err instanceof Error ? err.message : String(err),
93261
- finishedAtMs: this.deps.now()
93262
- });
93263
- return null;
93264
- }
93229
+ * Mark a framework task `skipped`.
93230
+ *
93231
+ * Framework packages (`@camstack/system` + its lockstep companions) are NO
93232
+ * LONGER updated through this engine. The legacy `/data/framework` per-package
93233
+ * swap was removed in the single-copy framework collapse (2026-07-18) — the
93234
+ * running framework is loaded from the active server-root single copy, and
93235
+ * framework/cap updates now ship EXCLUSIVELY via `applyServerUpdate` (the
93236
+ * node-root ServerUpdateService). Any framework task that still reaches this
93237
+ * engine (e.g. an "Update all" bulk job that swept `@camstack/system`) is
93238
+ * skipped, never applied — applying it would swap a dead dir.
93239
+ */
93240
+ skipFrameworkTask(job, task) {
93241
+ this.advance(job.jobId, task, "skipped", {
93242
+ startedAtMs: task.startedAtMs ?? this.deps.now(),
93243
+ finishedAtMs: this.deps.now()
93244
+ });
93265
93245
  }
93266
93246
  /**
93267
93247
  * Run the addon fetch phase with a bounded-concurrency worker pool. At most
@@ -93289,24 +93269,24 @@ var LifecycleJobEngine = class {
93289
93269
  * §10 boot reconcile: re-drive every NON-TERMINAL addon task of a job that
93290
93270
  * was interrupted mid-flight (e.g. a crash) from its on-disk checkpoint.
93291
93271
  *
93292
- * Framework tasks are LEFT UNTOUCHED they are owned by the F2
93293
- * `resumeFrameworkSwapJob` path (which marks `applied`→`done` on a healthy
93294
- * reboot). Terminal addon tasks (`done`/`failed`/`skipped`) are skipped.
93272
+ * Framework tasks are NOT applied by this engine (single-copy collapse
93273
+ * framework updates ship via `applyServerUpdate`). Any stray non-terminal
93274
+ * framework task is marked `skipped` so the interrupted job can finalize
93275
+ * instead of hanging `running` forever. Terminal addon tasks
93276
+ * (`done`/`failed`/`skipped`) are left as-is.
93295
93277
  *
93296
93278
  * Apply is idempotent (`applyAddonUpdate` backs up the live dir + restores on
93297
93279
  * failure), so every non-terminal addon phase collapses to:
93298
93280
  * ensure staged (reuse a still-valid `stagedPath` or re-fetch) → apply → done;
93299
93281
  * on failure → `failed`.
93300
- *
93301
- * The job is finalized (`completed`/`partially-failed`/`failed` + staging
93302
- * cleanup) ONLY when ALL tasks — including any framework task — are terminal.
93303
- * If a framework task is still non-terminal the job is LEFT `running` (the
93304
- * reboot/F2 path finalizes it).
93305
93282
  */
93306
93283
  async reconcileJob(job) {
93307
93284
  const exists = this.deps.stagedPathExists ?? ((p) => node_fs.existsSync(p));
93308
93285
  for (const task of job.tasks) {
93309
- if (task.target === "framework") continue;
93286
+ if (task.target === "framework") {
93287
+ if (!this.isTerminal(task.phase)) this.skipFrameworkTask(job, task);
93288
+ continue;
93289
+ }
93310
93290
  if (this.isTerminal(task.phase)) continue;
93311
93291
  await this.reconcileAddonTask(job, task, exists);
93312
93292
  }
@@ -93328,9 +93308,10 @@ var LifecycleJobEngine = class {
93328
93308
  }
93329
93309
  /**
93330
93310
  * Finalize a reconciled job: `completed` if all addon tasks succeeded,
93331
- * `failed` if all failed, `partially-failed` if mixed but ONLY when every
93332
- * task (including framework) is terminal. If any task is still non-terminal
93333
- * (a framework task pending its reboot resume), leave the job `running`.
93311
+ * `failed` if all failed, `partially-failed` if mixed. A skipped framework
93312
+ * task counts as neither success nor failure. Defensive: if a task is still
93313
+ * non-terminal (should not happen reconcile drives every task terminal),
93314
+ * leave the job `running` and do not clean staging.
93334
93315
  */
93335
93316
  finalizeReconciledJob(jobId) {
93336
93317
  const current = this.deps.journal.getJob(jobId);
@@ -93346,6 +93327,7 @@ var LifecycleJobEngine = class {
93346
93327
  async runJob(job) {
93347
93328
  const addonTasks = job.tasks.filter((t) => t.target !== "framework");
93348
93329
  const frameworkTasks = job.tasks.filter((t) => t.target === "framework");
93330
+ for (const task of frameworkTasks) this.skipFrameworkTask(job, task);
93349
93331
  let failures = 0;
93350
93332
  let successes = 0;
93351
93333
  const fetchOutcomes = await this.fetchAddonsBounded(job, addonTasks);
@@ -93355,11 +93337,6 @@ var LifecycleJobEngine = class {
93355
93337
  if (await this.applyAddonTask(job, outcome.task, outcome.stagedPath)) successes += 1;
93356
93338
  else failures += 1;
93357
93339
  }
93358
- for (const task of frameworkTasks) {
93359
- const result = await this.runFrameworkTask(job, task);
93360
- if (result !== null) return result;
93361
- failures += 1;
93362
- }
93363
93340
  const state = failures === 0 ? "completed" : successes === 0 ? "failed" : "partially-failed";
93364
93341
  const finalJob = this.deps.journal.setJobState(job.jobId, state);
93365
93342
  this.deps.staging.cleanup(job.jobId);
@@ -93367,44 +93344,6 @@ var LifecycleJobEngine = class {
93367
93344
  }
93368
93345
  };
93369
93346
  //#endregion
93370
- //#region src/kernel/lifecycle/framework-staging.ts
93371
- var FRAMEWORK_LOCKSTEP = [
93372
- "@camstack/system",
93373
- "@camstack/types",
93374
- "@camstack/sdk",
93375
- "@camstack/shm-ring"
93376
- ];
93377
- function safeSegment(name) {
93378
- return name.replace(/[^a-zA-Z0-9._-]/g, "_");
93379
- }
93380
- async function stageFrameworkLockstep(input) {
93381
- const stagingArea = new StagingArea(input.stagingDir, {
93382
- fetchTarball: input.fetchTarball,
93383
- extract: input.extract
93384
- });
93385
- const results = [];
93386
- const primary = FRAMEWORK_LOCKSTEP[0];
93387
- for (const pkg of FRAMEWORK_LOCKSTEP) {
93388
- const version = pkg === primary ? input.toVersion : await input.resolveVersion(pkg);
93389
- const { stagedPath } = await stagingArea.fetchAndStage({
93390
- jobId: input.jobId,
93391
- name: pkg,
93392
- version,
93393
- signal: input.signal
93394
- });
93395
- const backupPath = node_path.join(input.stagingDir, input.jobId, ".bak-fw", safeSegment(pkg));
93396
- const fromVersion = input.currentVersionOf(pkg);
93397
- results.push({
93398
- name: pkg,
93399
- stagedPath,
93400
- backupPath,
93401
- toVersion: version,
93402
- fromVersion
93403
- });
93404
- }
93405
- return results;
93406
- }
93407
- //#endregion
93408
93347
  exports.AGENT_CAP_FWD_ACTION = require_manifest_python_deps.AGENT_CAP_FWD_ACTION;
93409
93348
  exports.AGENT_CAP_FWD_SERVICE = require_manifest_python_deps.AGENT_CAP_FWD_SERVICE;
93410
93349
  exports.AGENT_READINESS_SERVICE_NAME = AGENT_READINESS_SERVICE_NAME;
@@ -93444,7 +93383,6 @@ exports.DeviceStore = require_builtins_sqlite_storage_index.DeviceStore$1;
93444
93383
  exports.EVENT_TOPIC_PREFIX = require_manifest_python_deps.EVENT_TOPIC_PREFIX;
93445
93384
  exports.EngineManagerResolver = EngineManagerResolver;
93446
93385
  exports.EventBus = EventBus;
93447
- exports.FRAMEWORK_LOCKSTEP = FRAMEWORK_LOCKSTEP;
93448
93386
  exports.FeatureManager = FeatureManager;
93449
93387
  exports.FilesystemStorageAddon = require_builtins_sqlite_storage_filesystem_storage_addon.FilesystemStorageAddon;
93450
93388
  exports.FilesystemStorageProvider = require_builtins_sqlite_storage_filesystem_storage_addon.FilesystemStorageProvider;
@@ -93682,7 +93620,6 @@ exports.scopesAllowDeviceCap = scopesAllowDeviceCap;
93682
93620
  exports.serializeTypedArrays = require_manifest_python_deps.serializeTypedArrays;
93683
93621
  exports.setHubConnected = require_manifest_python_deps.setHubConnected;
93684
93622
  exports.setNodeEventInterest = require_manifest_python_deps.setNodeEventInterest;
93685
- exports.stageFrameworkLockstep = stageFrameworkLockstep;
93686
93623
  exports.stripCamstackDeps = stripCamstackDeps;
93687
93624
  exports.subscribePassthrough = require_manifest_python_deps.subscribePassthrough;
93688
93625
  exports.udsChildLogToWorkerEntry = require_manifest_python_deps.udsChildLogToWorkerEntry;
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { A as isArrayOutputSchema, Ct as parseJsonObject, D as extractNestedAddonId, Dt as scopeKey, Et as resolveCapMount, F as lifecycleJobSchema, G as procedureAuthKey, H as objectInputDeclaresAddonId, M as isObjectInput, N as isVoidInput, P as kebabToCamel, R as looseSchema, Tt as readinessKey, _t as createEvent, at as DATAPLANE_SECRET_HEADER$1, bt as expandCapMethods, dt as ReadinessRegistry, ft as ReadinessTimeoutError, gt as asString$1, ht as asNumber, j as isCollectionArrayMethod, kt as EventCategory$1, mt as asJsonObject$1, o as METHOD_ACCESS_MAP, ot as DEVICE_SETTINGS_CONTRIBUTION_METHODS, p as addonSettingsCapability, rt as errMsg$1, s as RUNTIME_DEFAULTS, st as DEVICE_STATUS_METHOD, t as ALL_CAPABILITY_DEFINITIONS, vt as emitDownForOwnedCaps, wt as parseJsonUnknown$1 } from "./dist-JAF9YR1q.mjs";
1
+ import { A as isArrayOutputSchema, Ct as parseJsonObject, D as extractNestedAddonId, Dt as scopeKey, Et as resolveCapMount, F as lifecycleJobSchema, G as procedureAuthKey, H as objectInputDeclaresAddonId, M as isObjectInput, N as isVoidInput, P as kebabToCamel, R as looseSchema, Tt as readinessKey, _t as createEvent, at as DATAPLANE_SECRET_HEADER$1, bt as expandCapMethods, dt as ReadinessRegistry, ft as ReadinessTimeoutError, gt as asString$1, ht as asNumber, j as isCollectionArrayMethod, kt as EventCategory$1, mt as asJsonObject$1, o as METHOD_ACCESS_MAP, ot as DEVICE_SETTINGS_CONTRIBUTION_METHODS, p as addonSettingsCapability, rt as errMsg$1, s as RUNTIME_DEFAULTS, st as DEVICE_STATUS_METHOD, t as ALL_CAPABILITY_DEFINITIONS, vt as emitDownForOwnedCaps, wt as parseJsonUnknown$1 } from "./dist-BNevCEAo.mjs";
2
2
  import { a as downloadModel, c as getModelFilePath, d as contentTypeFor, f as createAuthenticatedFileServer, h as resolveFilePath, i as downloadFile, l as isModelDownloaded, m as parseTokenizedUrl, n as collectModelFiles, o as ensureModel, p as parseRangeHeader, r as deleteModelFromDisk, s as fetchJson, t as ModelDownloadService, u as createFileDataPlaneHandler } from "./model-download-service-Cp9f4dk6.mjs";
3
- import { $ as buildUdsNativeCapProxy, A as createParentUnownedCallHandler, B as AGENT_CAP_FWD_SERVICE, C as buildLinkChain, D as HUB_CAP_FWD_ACTION, E as localProviderLink, F as createUdsLoggerWithControl, G as createLocalTransport, H as CapRouteError, I as LocalChildClient, J as SocketChannel, K as UdsLocalTransportClient, L as LocalChildRegistry, M as createUdsEventBus, N as udsChildLogToWorkerEntry, O as HUB_CAP_FWD_SERVICE, P as createUdsLogger, Q as buildNativeCapProxy, R as UDS_NO_ROUTE_PREFIX, S as brokerTransportLink, T as ipcParentLink, U as classifyCapRoute, V as CapRouteResolver, W as callWithServiceDiscovery, X as FrameDecoder, Y as localEndpointPath, Z as encodeFrame, _ as resolveHwAccel, _t as CapabilityUnavailableError, a as getWorkerDeviceRegistry, at as createAddonService, b as getCapUsageRegistry, bt as resolveAddonClass, c as setHubConnected, ct as capActionName, d as getMoleculerEventStats, dt as capServiceName, et as createBrokerDeviceManagerApi, f as registerEventBusService, ft as parseCapAction, g as createKernelHwAccel, gt as CapabilityHandle, h as AddonDepsManager, ht as DeviceRegistry, i as createUdsAddonContext, j as createUdsEventBridge, k as createHubCapForwardService, l as EVENT_TOPIC_PREFIX, lt as capActionSuffix, m as subscribePassthrough, mt as serializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as validateProviderRegistrations, p as setNodeEventInterest, pt as deserializeTypedArrays, q as UdsLocalTransportServer, r as createAddonContext, rt as mountNativeCapService, s as getOrInitReadinessRegistryForClient, st as NATIVE_PROVIDER_SERVICE_INFIX, t as installManifestPythonDeps, u as getBrokerEventBus, ut as capBareAction, v as CapUsageRegistry, vt as installManifestNativeDeps, w as ipcChildLink, x as brokerCallForCap, xt as createAddonDataPlaneFacility, y as __resetCapUsageRegistryForTests, yt as runNpm, z as AGENT_CAP_FWD_ACTION } from "./manifest-python-deps-9wuRyL-k.mjs";
3
+ import { $ as buildUdsNativeCapProxy, A as createParentUnownedCallHandler, B as AGENT_CAP_FWD_SERVICE, C as buildLinkChain, D as HUB_CAP_FWD_ACTION, E as localProviderLink, F as createUdsLoggerWithControl, G as createLocalTransport, H as CapRouteError, I as LocalChildClient, J as SocketChannel, K as UdsLocalTransportClient, L as LocalChildRegistry, M as createUdsEventBus, N as udsChildLogToWorkerEntry, O as HUB_CAP_FWD_SERVICE, P as createUdsLogger, Q as buildNativeCapProxy, R as UDS_NO_ROUTE_PREFIX, S as brokerTransportLink, T as ipcParentLink, U as classifyCapRoute, V as CapRouteResolver, W as callWithServiceDiscovery, X as FrameDecoder, Y as localEndpointPath, Z as encodeFrame, _ as resolveHwAccel, _t as CapabilityUnavailableError, a as getWorkerDeviceRegistry, at as createAddonService, b as getCapUsageRegistry, bt as resolveAddonClass, c as setHubConnected, ct as capActionName, d as getMoleculerEventStats, dt as capServiceName, et as createBrokerDeviceManagerApi, f as registerEventBusService, ft as parseCapAction, g as createKernelHwAccel, gt as CapabilityHandle, h as AddonDepsManager, ht as DeviceRegistry, i as createUdsAddonContext, j as createUdsEventBridge, k as createHubCapForwardService, l as EVENT_TOPIC_PREFIX, lt as capActionSuffix, m as subscribePassthrough, mt as serializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as validateProviderRegistrations, p as setNodeEventInterest, pt as deserializeTypedArrays, q as UdsLocalTransportServer, r as createAddonContext, rt as mountNativeCapService, s as getOrInitReadinessRegistryForClient, st as NATIVE_PROVIDER_SERVICE_INFIX, t as installManifestPythonDeps, u as getBrokerEventBus, ut as capBareAction, v as CapUsageRegistry, vt as installManifestNativeDeps, w as ipcChildLink, x as brokerCallForCap, xt as createAddonDataPlaneFacility, y as __resetCapUsageRegistryForTests, yt as runNpm, z as AGENT_CAP_FWD_ACTION } from "./manifest-python-deps-DtCMZhuR.mjs";
4
4
  import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-Le3l0qS2.mjs";
5
5
  import { FilesystemStorageAddon, t as FilesystemStorageProvider } from "./builtins/sqlite-storage/filesystem-storage.addon.mjs";
6
6
  import { SqliteSettingsAddon, t as SqliteSettingsBackend } from "./builtins/sqlite-storage/sqlite-settings.addon.mjs";
@@ -2300,9 +2300,15 @@ var AddonLoader = class {
2300
2300
  else i++;
2301
2301
  }
2302
2302
  /** Scan addons directory and load all addon packages.
2303
- * Supports scoped layout: addons/@scope/package-name/ */
2304
- async loadFromDirectory(addonsDir) {
2303
+ * Supports scoped layout: addons/@scope/package-name/
2304
+ *
2305
+ * `skipPackages` names scoped packages (e.g. `@camstack/system`) that the
2306
+ * caller loads from elsewhere — the single-copy model loads the framework
2307
+ * BUILTINS from the active closure, not the (now-inert) addons-dir copy, so
2308
+ * the addons-dir `@camstack/system` must NOT be double-loaded here. */
2309
+ async loadFromDirectory(addonsDir, skipPackages = []) {
2305
2310
  if (!fs$17.existsSync(addonsDir)) return;
2311
+ const skip = new Set(skipPackages);
2306
2312
  const entries = fs$17.readdirSync(addonsDir, { withFileTypes: true });
2307
2313
  for (const entry of entries) {
2308
2314
  if (!isDirectoryEntry(entry, addonsDir)) continue;
@@ -2311,10 +2317,12 @@ var AddonLoader = class {
2311
2317
  const scopeEntries = fs$17.readdirSync(scopeDir, { withFileTypes: true });
2312
2318
  for (const scopeEntry of scopeEntries) {
2313
2319
  if (!isDirectoryEntry(scopeEntry, scopeDir)) continue;
2320
+ if (skip.has(`${entry.name}/${scopeEntry.name}`)) continue;
2314
2321
  await this.tryLoadAddon(path$39.join(scopeDir, scopeEntry.name));
2315
2322
  }
2316
2323
  continue;
2317
2324
  }
2325
+ if (skip.has(entry.name)) continue;
2318
2326
  await this.tryLoadAddon(path$39.join(addonsDir, entry.name));
2319
2327
  }
2320
2328
  }
@@ -93063,7 +93071,7 @@ var JobJournal = class {
93063
93071
  };
93064
93072
  //#endregion
93065
93073
  //#region src/kernel/lifecycle/staging-area.ts
93066
- function safeSegment$1(name) {
93074
+ function safeSegment(name) {
93067
93075
  return name.replace(/[^a-zA-Z0-9._-]/g, "_");
93068
93076
  }
93069
93077
  var StagingArea = class {
@@ -93074,7 +93082,7 @@ var StagingArea = class {
93074
93082
  this.deps = deps;
93075
93083
  }
93076
93084
  async fetchAndStage(input) {
93077
- const destDir = path$39.join(this.stagingDir, input.jobId, safeSegment$1(input.name));
93085
+ const destDir = path$39.join(this.stagingDir, input.jobId, safeSegment(input.name));
93078
93086
  fs$17.rmSync(destDir, {
93079
93087
  recursive: true,
93080
93088
  force: true
@@ -93210,50 +93218,22 @@ var LifecycleJobEngine = class {
93210
93218
  }
93211
93219
  }
93212
93220
  /**
93213
- * Run the framework task: stage lockstep → `staged` → requestFrameworkSwap.
93214
- * In production the process exits after requestFrameworkSwap and the reboot
93215
- * finalizes the job, so this returns the current durable job WITHOUT
93216
- * finalization. Returns null only if the framework deps are not wired (the
93217
- * task is marked `failed` and the caller finalizes the job).
93218
- */
93219
- async runFrameworkTask(job, task) {
93220
- const { stageFramework, requestFrameworkSwap } = this.deps;
93221
- if (stageFramework === void 0 || requestFrameworkSwap === void 0) {
93222
- this.advance(job.jobId, task, "failed", {
93223
- error: "framework swap deps not wired",
93224
- finishedAtMs: this.deps.now()
93225
- });
93226
- return null;
93227
- }
93228
- try {
93229
- this.advance(job.jobId, task, "fetching", {
93230
- startedAtMs: this.deps.now(),
93231
- attempts: task.attempts + 1
93232
- });
93233
- const ac = new AbortController();
93234
- const timer = setTimeout(() => ac.abort(), this.deps.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS);
93235
- let packages;
93236
- try {
93237
- packages = await stageFramework(task, ac.signal);
93238
- } finally {
93239
- clearTimeout(timer);
93240
- }
93241
- const [firstPackage] = packages;
93242
- if (!firstPackage) throw new Error("stageFramework returned no packages");
93243
- this.advance(job.jobId, task, "staged", { stagedPath: firstPackage.stagedPath });
93244
- requestFrameworkSwap({
93245
- jobId: job.jobId,
93246
- taskId: task.taskId,
93247
- packages
93248
- });
93249
- return this.deps.journal.getJob(job.jobId) ?? job;
93250
- } catch (err) {
93251
- this.advance(job.jobId, task, "failed", {
93252
- error: err instanceof Error ? err.message : String(err),
93253
- finishedAtMs: this.deps.now()
93254
- });
93255
- return null;
93256
- }
93221
+ * Mark a framework task `skipped`.
93222
+ *
93223
+ * Framework packages (`@camstack/system` + its lockstep companions) are NO
93224
+ * LONGER updated through this engine. The legacy `/data/framework` per-package
93225
+ * swap was removed in the single-copy framework collapse (2026-07-18) — the
93226
+ * running framework is loaded from the active server-root single copy, and
93227
+ * framework/cap updates now ship EXCLUSIVELY via `applyServerUpdate` (the
93228
+ * node-root ServerUpdateService). Any framework task that still reaches this
93229
+ * engine (e.g. an "Update all" bulk job that swept `@camstack/system`) is
93230
+ * skipped, never applied — applying it would swap a dead dir.
93231
+ */
93232
+ skipFrameworkTask(job, task) {
93233
+ this.advance(job.jobId, task, "skipped", {
93234
+ startedAtMs: task.startedAtMs ?? this.deps.now(),
93235
+ finishedAtMs: this.deps.now()
93236
+ });
93257
93237
  }
93258
93238
  /**
93259
93239
  * Run the addon fetch phase with a bounded-concurrency worker pool. At most
@@ -93281,24 +93261,24 @@ var LifecycleJobEngine = class {
93281
93261
  * §10 boot reconcile: re-drive every NON-TERMINAL addon task of a job that
93282
93262
  * was interrupted mid-flight (e.g. a crash) from its on-disk checkpoint.
93283
93263
  *
93284
- * Framework tasks are LEFT UNTOUCHED they are owned by the F2
93285
- * `resumeFrameworkSwapJob` path (which marks `applied`→`done` on a healthy
93286
- * reboot). Terminal addon tasks (`done`/`failed`/`skipped`) are skipped.
93264
+ * Framework tasks are NOT applied by this engine (single-copy collapse
93265
+ * framework updates ship via `applyServerUpdate`). Any stray non-terminal
93266
+ * framework task is marked `skipped` so the interrupted job can finalize
93267
+ * instead of hanging `running` forever. Terminal addon tasks
93268
+ * (`done`/`failed`/`skipped`) are left as-is.
93287
93269
  *
93288
93270
  * Apply is idempotent (`applyAddonUpdate` backs up the live dir + restores on
93289
93271
  * failure), so every non-terminal addon phase collapses to:
93290
93272
  * ensure staged (reuse a still-valid `stagedPath` or re-fetch) → apply → done;
93291
93273
  * on failure → `failed`.
93292
- *
93293
- * The job is finalized (`completed`/`partially-failed`/`failed` + staging
93294
- * cleanup) ONLY when ALL tasks — including any framework task — are terminal.
93295
- * If a framework task is still non-terminal the job is LEFT `running` (the
93296
- * reboot/F2 path finalizes it).
93297
93274
  */
93298
93275
  async reconcileJob(job) {
93299
93276
  const exists = this.deps.stagedPathExists ?? ((p) => fs$17.existsSync(p));
93300
93277
  for (const task of job.tasks) {
93301
- if (task.target === "framework") continue;
93278
+ if (task.target === "framework") {
93279
+ if (!this.isTerminal(task.phase)) this.skipFrameworkTask(job, task);
93280
+ continue;
93281
+ }
93302
93282
  if (this.isTerminal(task.phase)) continue;
93303
93283
  await this.reconcileAddonTask(job, task, exists);
93304
93284
  }
@@ -93320,9 +93300,10 @@ var LifecycleJobEngine = class {
93320
93300
  }
93321
93301
  /**
93322
93302
  * Finalize a reconciled job: `completed` if all addon tasks succeeded,
93323
- * `failed` if all failed, `partially-failed` if mixed but ONLY when every
93324
- * task (including framework) is terminal. If any task is still non-terminal
93325
- * (a framework task pending its reboot resume), leave the job `running`.
93303
+ * `failed` if all failed, `partially-failed` if mixed. A skipped framework
93304
+ * task counts as neither success nor failure. Defensive: if a task is still
93305
+ * non-terminal (should not happen reconcile drives every task terminal),
93306
+ * leave the job `running` and do not clean staging.
93326
93307
  */
93327
93308
  finalizeReconciledJob(jobId) {
93328
93309
  const current = this.deps.journal.getJob(jobId);
@@ -93338,6 +93319,7 @@ var LifecycleJobEngine = class {
93338
93319
  async runJob(job) {
93339
93320
  const addonTasks = job.tasks.filter((t) => t.target !== "framework");
93340
93321
  const frameworkTasks = job.tasks.filter((t) => t.target === "framework");
93322
+ for (const task of frameworkTasks) this.skipFrameworkTask(job, task);
93341
93323
  let failures = 0;
93342
93324
  let successes = 0;
93343
93325
  const fetchOutcomes = await this.fetchAddonsBounded(job, addonTasks);
@@ -93347,11 +93329,6 @@ var LifecycleJobEngine = class {
93347
93329
  if (await this.applyAddonTask(job, outcome.task, outcome.stagedPath)) successes += 1;
93348
93330
  else failures += 1;
93349
93331
  }
93350
- for (const task of frameworkTasks) {
93351
- const result = await this.runFrameworkTask(job, task);
93352
- if (result !== null) return result;
93353
- failures += 1;
93354
- }
93355
93332
  const state = failures === 0 ? "completed" : successes === 0 ? "failed" : "partially-failed";
93356
93333
  const finalJob = this.deps.journal.setJobState(job.jobId, state);
93357
93334
  this.deps.staging.cleanup(job.jobId);
@@ -93359,42 +93336,4 @@ var LifecycleJobEngine = class {
93359
93336
  }
93360
93337
  };
93361
93338
  //#endregion
93362
- //#region src/kernel/lifecycle/framework-staging.ts
93363
- var FRAMEWORK_LOCKSTEP = [
93364
- "@camstack/system",
93365
- "@camstack/types",
93366
- "@camstack/sdk",
93367
- "@camstack/shm-ring"
93368
- ];
93369
- function safeSegment(name) {
93370
- return name.replace(/[^a-zA-Z0-9._-]/g, "_");
93371
- }
93372
- async function stageFrameworkLockstep(input) {
93373
- const stagingArea = new StagingArea(input.stagingDir, {
93374
- fetchTarball: input.fetchTarball,
93375
- extract: input.extract
93376
- });
93377
- const results = [];
93378
- const primary = FRAMEWORK_LOCKSTEP[0];
93379
- for (const pkg of FRAMEWORK_LOCKSTEP) {
93380
- const version = pkg === primary ? input.toVersion : await input.resolveVersion(pkg);
93381
- const { stagedPath } = await stagingArea.fetchAndStage({
93382
- jobId: input.jobId,
93383
- name: pkg,
93384
- version,
93385
- signal: input.signal
93386
- });
93387
- const backupPath = path$39.join(input.stagingDir, input.jobId, ".bak-fw", safeSegment(pkg));
93388
- const fromVersion = input.currentVersionOf(pkg);
93389
- results.push({
93390
- name: pkg,
93391
- stagedPath,
93392
- backupPath,
93393
- toVersion: version,
93394
- fromVersion
93395
- });
93396
- }
93397
- return results;
93398
- }
93399
- //#endregion
93400
- export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CustomActionRegistry, DEFAULT_DATA_PATH, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FRAMEWORK_LOCKSTEP, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, METHOD_ACCESS_MAP, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, RESTART_MARKER_FILE, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, __resetCapUsageRegistryForTests, adaptBrokerToCluster, addonSettingsCapability, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterSecretMatches, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensurePython, ensureTlsCert, expandCapMethods, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcChildLink, ipcParentLink, isAddonDeploySource, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceNewer, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, proxyToUpstream, readPendingRestart, readinessKey, registerEventBusService, resolveFilePath, resolveHwAccel, scheduleSelfRestart, scopeKey, scopesAllowDeviceCap, serializeTypedArrays, setHubConnected, setNodeEventInterest, stageFrameworkLockstep, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };
93339
+ export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CustomActionRegistry, DEFAULT_DATA_PATH, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, METHOD_ACCESS_MAP, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, RESTART_MARKER_FILE, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, __resetCapUsageRegistryForTests, adaptBrokerToCluster, addonSettingsCapability, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterSecretMatches, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensurePython, ensureTlsCert, expandCapMethods, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcChildLink, ipcParentLink, isAddonDeploySource, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceNewer, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, proxyToUpstream, readPendingRestart, readinessKey, registerEventBusService, resolveFilePath, resolveHwAccel, scheduleSelfRestart, scopeKey, scopesAllowDeviceCap, serializeTypedArrays, setHubConnected, setNodeEventInterest, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };
@@ -72,8 +72,13 @@ export declare class AddonLoader {
72
72
  /** Forget any tracked failures for a given package — uninstall path. */
73
73
  clearLoadFailures(packageName: string): void;
74
74
  /** Scan addons directory and load all addon packages.
75
- * Supports scoped layout: addons/@scope/package-name/ */
76
- loadFromDirectory(addonsDir: string): Promise<void>;
75
+ * Supports scoped layout: addons/@scope/package-name/
76
+ *
77
+ * `skipPackages` names scoped packages (e.g. `@camstack/system`) that the
78
+ * caller loads from elsewhere — the single-copy model loads the framework
79
+ * BUILTINS from the active closure, not the (now-inert) addons-dir copy, so
80
+ * the addons-dir `@camstack/system` must NOT be double-loaded here. */
81
+ loadFromDirectory(addonsDir: string, skipPackages?: readonly string[]): Promise<void>;
77
82
  private tryLoadAddon;
78
83
  /** Load addon from a specific directory (package.json + dist/) */
79
84
  loadFromAddonDir(addonDir: string): Promise<void>;
@@ -77,7 +77,5 @@ export type { ReadinessHandler, ReadinessTransition, AwaitReadyOptions, Readines
77
77
  export { JobJournal } from './lifecycle/job-journal.js';
78
78
  export { StagingArea } from './lifecycle/staging-area.js';
79
79
  export { LifecycleJobEngine } from './lifecycle/lifecycle-job-engine.js';
80
- export type { ApplyAddonUpdateFn, EmitFn, StageFrameworkFn, RequestFrameworkSwapFn, } from './lifecycle/lifecycle-job-engine.js';
80
+ export type { ApplyAddonUpdateFn, EmitFn } from './lifecycle/lifecycle-job-engine.js';
81
81
  export type { TarballFetcher, ExtractFn } from './lifecycle/staging-area.js';
82
- export { stageFrameworkLockstep, FRAMEWORK_LOCKSTEP } from './lifecycle/framework-staging.js';
83
- export type { StageFrameworkInput } from './lifecycle/framework-staging.js';
@@ -1,18 +1,12 @@
1
1
  import { JobJournal } from './job-journal.js';
2
2
  import { StagingArea } from './staging-area.js';
3
- import { LifecycleJob, LifecycleTask, TaskLogEntry, FrameworkSwapPackage } from '@camstack/types';
3
+ import { LifecycleJob, TaskLogEntry } from '@camstack/types';
4
4
  export type ApplyAddonUpdateFn = (input: {
5
5
  name: string;
6
6
  version: string;
7
7
  stagedPath: string;
8
8
  }) => Promise<void>;
9
9
  export type EmitFn = (kind: 'progress' | 'log', job: LifecycleJob, entry?: TaskLogEntry) => void;
10
- export type StageFrameworkFn = (task: LifecycleTask, signal: AbortSignal) => Promise<FrameworkSwapPackage[]>;
11
- export type RequestFrameworkSwapFn = (input: {
12
- jobId: string;
13
- taskId: string;
14
- packages: FrameworkSwapPackage[];
15
- }) => void;
16
10
  interface Deps {
17
11
  readonly journal: JobJournal;
18
12
  readonly staging: StagingArea;
@@ -21,8 +15,6 @@ interface Deps {
21
15
  readonly now: () => number;
22
16
  readonly fetchTimeoutMs?: number;
23
17
  readonly fetchConcurrency?: number;
24
- readonly stageFramework?: StageFrameworkFn;
25
- readonly requestFrameworkSwap?: RequestFrameworkSwapFn;
26
18
  /**
27
19
  * Predicate used by `reconcileJob` to decide whether a task's recorded
28
20
  * `stagedPath` directory still exists on disk (so apply can reuse it instead
@@ -48,13 +40,18 @@ export declare class LifecycleJobEngine {
48
40
  */
49
41
  private applyAddonTask;
50
42
  /**
51
- * Run the framework task: stage lockstep → `staged` → requestFrameworkSwap.
52
- * In production the process exits after requestFrameworkSwap and the reboot
53
- * finalizes the job, so this returns the current durable job WITHOUT
54
- * finalization. Returns null only if the framework deps are not wired (the
55
- * task is marked `failed` and the caller finalizes the job).
43
+ * Mark a framework task `skipped`.
44
+ *
45
+ * Framework packages (`@camstack/system` + its lockstep companions) are NO
46
+ * LONGER updated through this engine. The legacy `/data/framework` per-package
47
+ * swap was removed in the single-copy framework collapse (2026-07-18) — the
48
+ * running framework is loaded from the active server-root single copy, and
49
+ * framework/cap updates now ship EXCLUSIVELY via `applyServerUpdate` (the
50
+ * node-root ServerUpdateService). Any framework task that still reaches this
51
+ * engine (e.g. an "Update all" bulk job that swept `@camstack/system`) is
52
+ * skipped, never applied — applying it would swap a dead dir.
56
53
  */
57
- private runFrameworkTask;
54
+ private skipFrameworkTask;
58
55
  /**
59
56
  * Run the addon fetch phase with a bounded-concurrency worker pool. At most
60
57
  * `fetchConcurrency` fetches are in flight at once; completion order may vary
@@ -65,19 +62,16 @@ export declare class LifecycleJobEngine {
65
62
  * §10 boot reconcile: re-drive every NON-TERMINAL addon task of a job that
66
63
  * was interrupted mid-flight (e.g. a crash) from its on-disk checkpoint.
67
64
  *
68
- * Framework tasks are LEFT UNTOUCHED they are owned by the F2
69
- * `resumeFrameworkSwapJob` path (which marks `applied`→`done` on a healthy
70
- * reboot). Terminal addon tasks (`done`/`failed`/`skipped`) are skipped.
65
+ * Framework tasks are NOT applied by this engine (single-copy collapse
66
+ * framework updates ship via `applyServerUpdate`). Any stray non-terminal
67
+ * framework task is marked `skipped` so the interrupted job can finalize
68
+ * instead of hanging `running` forever. Terminal addon tasks
69
+ * (`done`/`failed`/`skipped`) are left as-is.
71
70
  *
72
71
  * Apply is idempotent (`applyAddonUpdate` backs up the live dir + restores on
73
72
  * failure), so every non-terminal addon phase collapses to:
74
73
  * ensure staged (reuse a still-valid `stagedPath` or re-fetch) → apply → done;
75
74
  * on failure → `failed`.
76
- *
77
- * The job is finalized (`completed`/`partially-failed`/`failed` + staging
78
- * cleanup) ONLY when ALL tasks — including any framework task — are terminal.
79
- * If a framework task is still non-terminal the job is LEFT `running` (the
80
- * reboot/F2 path finalizes it).
81
75
  */
82
76
  reconcileJob(job: LifecycleJob): Promise<LifecycleJob>;
83
77
  private isTerminal;
@@ -88,9 +82,10 @@ export declare class LifecycleJobEngine {
88
82
  private reconcileAddonTask;
89
83
  /**
90
84
  * Finalize a reconciled job: `completed` if all addon tasks succeeded,
91
- * `failed` if all failed, `partially-failed` if mixed but ONLY when every
92
- * task (including framework) is terminal. If any task is still non-terminal
93
- * (a framework task pending its reboot resume), leave the job `running`.
85
+ * `failed` if all failed, `partially-failed` if mixed. A skipped framework
86
+ * task counts as neither success nor failure. Defensive: if a task is still
87
+ * non-terminal (should not happen reconcile drives every task terminal),
88
+ * leave the job `running` and do not clean staging.
94
89
  */
95
90
  private finalizeReconciledJob;
96
91
  runJob(job: LifecycleJob): Promise<LifecycleJob>;
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-Cek0wNdY.js");
2
- const require_dist = require("./dist-Bg795EQF.js");
2
+ const require_dist = require("./dist-BY6NWf-c.js");
3
3
  let _camstack_types_node = require("@camstack/types/node");
4
4
  let node_http = require("node:http");
5
5
  let node_fs = require("node:fs");