@cmmd-center/forge 0.9.7 → 0.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.cjs CHANGED
@@ -95950,6 +95950,35 @@ const prepareReplicaSummary = require_Schema$1.fn("prepareReplicaSummary")(funct
95950
95950
  candidate
95951
95951
  });
95952
95952
  });
95953
+ /**
95954
+ * Contains a per-thread hydration failure so it cannot brick the runtime.
95955
+ *
95956
+ * Hydration is a recovery convenience: it replays durable history into a fresh
95957
+ * runtime. One thread that fails identity or generation checks used to fail the
95958
+ * WHOLE hydration, which `serverRuntimeStartup` turned into
95959
+ * `commandGate.failCommandReady()` — the HTTP server kept serving 200 and the
95960
+ * runtime still reported `server_ready`, while every turn was refused with
95961
+ * "Could not connect".
95962
+ *
95963
+ * Observed in production 2026-08-31: a thread replayed from a DESTROYED runtime
95964
+ * failed its generation check, and because the poison row lives in CMMD's
95965
+ * durable replica rather than on the guest, destroying and reprovisioning the
95966
+ * sprite did not clear it. One bad row could brick every future runtime for
95967
+ * that user, permanently.
95968
+ *
95969
+ * Structural failures (index runtime identity changing between pages, a
95970
+ * repeated cursor) stay fatal on purpose: those mean the index itself cannot be
95971
+ * trusted, so continuing would hydrate an unknown mixture.
95972
+ */
95973
+ function skipUnhydratableThread(operation, threadId, state) {
95974
+ return operation.pipe(require_Schema$1.catchTag("RuntimeReplicaHydrationError", (error) => require_Schema$1.gen(function* () {
95975
+ state.unhydratableThreadIds.push(threadId);
95976
+ yield* require_Schema$1.logWarning("skipped a thread that could not be hydrated", {
95977
+ threadId,
95978
+ detail: error.detail
95979
+ });
95980
+ })));
95981
+ }
95953
95982
  const applyPreparedReplica = require_Schema$1.fn("applyPreparedReplica")(function* (expectedRuntimeId, prepared, state, dependencies) {
95954
95983
  const { summary, candidate } = prepared;
95955
95984
  if (!(yield* dependencies.restoreThreadCursor({
@@ -95975,7 +96004,7 @@ function prepareReplicaPages(expectedRuntimeId, cursor, state, dependencies) {
95975
96004
  if (index === null) return;
95976
96005
  if (state.runtimeIdentity === null) state.runtimeIdentity = index.runtime;
95977
96006
  else if (!replicaRuntimeMatches(state.runtimeIdentity, index.runtime)) return yield* replicaHydrationFailure("index runtime identity changed between pages");
95978
- yield* require_Schema$1.forEach(index.threads, (summary) => prepareReplicaSummary(expectedRuntimeId, index, summary, state, dependencies), {
96007
+ yield* require_Schema$1.forEach(index.threads, (summary) => skipUnhydratableThread(prepareReplicaSummary(expectedRuntimeId, index, summary, state, dependencies), summary.threadId, state), {
95979
96008
  concurrency: 1,
95980
96009
  discard: true
95981
96010
  });
@@ -95995,16 +96024,19 @@ const hydrateRuntimeReplica = require_Schema$1.fn("hydrateRuntimeReplica")(funct
95995
96024
  prepared: [],
95996
96025
  runtimeIdentity: null,
95997
96026
  hydrated: 0,
95998
- skippedExisting: 0
96027
+ skippedExisting: 0,
96028
+ unhydratableThreadIds: []
95999
96029
  };
96000
96030
  yield* prepareReplicaPages(input.expectedRuntimeId, void 0, state, dependencies);
96001
- yield* require_Schema$1.forEach(state.prepared, (prepared) => applyPreparedReplica(input.expectedRuntimeId, prepared, state, dependencies), {
96031
+ yield* require_Schema$1.forEach(state.prepared, (prepared) => skipUnhydratableThread(applyPreparedReplica(input.expectedRuntimeId, prepared, state, dependencies), prepared.summary.threadId, state), {
96002
96032
  concurrency: 1,
96003
96033
  discard: true
96004
96034
  });
96005
96035
  return {
96006
96036
  hydrated: state.hydrated,
96007
- skippedExisting: state.skippedExisting
96037
+ skippedExisting: state.skippedExisting,
96038
+ skippedUnhydratable: state.unhydratableThreadIds.length,
96039
+ unhydratableThreadIds: [...state.unhydratableThreadIds]
96008
96040
  };
96009
96041
  });
96010
96042
  //#endregion
package/dist/bin.mjs CHANGED
@@ -22,7 +22,7 @@ import { createCipheriv, createDecipheriv, createHash, createHmac, createPublicK
22
22
  import * as FS$1 from "node:fs";
23
23
  import fs, { accessSync, chmodSync, constants, createReadStream, existsSync, mkdirSync, mkdtempSync, promises, readFile, readFileSync, readdir, readdirSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
24
24
  import * as NodeOS from "node:os";
25
- import os, { homedir, networkInterfaces, tmpdir } from "node:os";
25
+ import $U, { homedir, networkInterfaces, tmpdir } from "node:os";
26
26
  import * as Path$1 from "node:path";
27
27
  import path, { basename, delimiter, dirname, extname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
28
28
  import { pathToFileURL } from "node:url";
@@ -52183,7 +52183,7 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
52183
52183
  const min = forceColor || 0;
52184
52184
  if (env.TERM === "dumb") return min;
52185
52185
  if (process$1.platform === "win32") {
52186
- const osRelease = os.release().split(".");
52186
+ const osRelease = $U.release().split(".");
52187
52187
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2;
52188
52188
  return 1;
52189
52189
  }
@@ -54626,7 +54626,7 @@ var require_ProcessDetector = /* @__PURE__ */ __commonJSMin(((exports) => {
54626
54626
  exports.processDetector = void 0;
54627
54627
  const api_1 = (init_esm$1(), __toCommonJS(esm_exports$1));
54628
54628
  const semconv_1 = require_semconv$1();
54629
- const os$4 = __require("os");
54629
+ const os$3 = __require("os");
54630
54630
  /**
54631
54631
  * ProcessDetector will be used to detect the resources related current process running
54632
54632
  * and being instrumented from the NodeJS Process module.
@@ -54648,7 +54648,7 @@ var require_ProcessDetector = /* @__PURE__ */ __commonJSMin(((exports) => {
54648
54648
  };
54649
54649
  if (process.argv.length > 1) attributes[semconv_1.ATTR_PROCESS_COMMAND] = process.argv[1];
54650
54650
  try {
54651
- const userInfo = os$4.userInfo();
54651
+ const userInfo = os$3.userInfo();
54652
54652
  attributes[semconv_1.ATTR_PROCESS_OWNER] = userInfo.username;
54653
54653
  } catch (e) {
54654
54654
  api_1.diag.debug(`error obtaining process owner: ${e}`);
@@ -76150,7 +76150,7 @@ var require_node_gyp_build = /* @__PURE__ */ __commonJSMin(((exports, module) =>
76150
76150
  var fs$6 = __require("fs");
76151
76151
  var path$5 = __require("path");
76152
76152
  var url$1 = __require("url");
76153
- var os$3 = __require("os");
76153
+ var os$2 = __require("os");
76154
76154
  var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
76155
76155
  var vars = process.config && process.config.variables || {};
76156
76156
  var prebuildsOnly = !!process.env.PREBUILDS_ONLY;
@@ -76158,8 +76158,8 @@ var require_node_gyp_build = /* @__PURE__ */ __commonJSMin(((exports, module) =>
76158
76158
  var abi = versions.modules;
76159
76159
  if (versions.deno || process.isBun) abi = "unsupported";
76160
76160
  var runtime = isElectron() ? "electron" : isNwjs() ? "node-webkit" : "node";
76161
- var arch = process.env.npm_config_arch || os$3.arch();
76162
- var platform = process.env.npm_config_platform || os$3.platform();
76161
+ var arch = process.env.npm_config_arch || os$2.arch();
76162
+ var platform = process.env.npm_config_platform || os$2.platform();
76163
76163
  var libc = process.env.LIBC || (isMusl(platform) ? "musl" : "glibc");
76164
76164
  var armv = process.env.ARM_VERSION || (arch === "arm64" ? "8" : vars.arm_version) || "";
76165
76165
  var uv = (versions.uv || "").split(".")[0];
@@ -93794,7 +93794,7 @@ const launchDetached = (launch) => gen(function* () {
93794
93794
  });
93795
93795
  const OpenLive = effect(Open, gen(function* () {
93796
93796
  const open = yield* tryPromise({
93797
- try: () => import("./open-FIgTDosf.mjs"),
93797
+ try: () => import("./open-D8mGyWmt.mjs"),
93798
93798
  catch: (cause) => new OpenError$1({
93799
93799
  message: "failed to load browser opener",
93800
93800
  cause
@@ -95649,6 +95649,35 @@ const prepareReplicaSummary = fn$1("prepareReplicaSummary")(function* (expectedR
95649
95649
  candidate
95650
95650
  });
95651
95651
  });
95652
+ /**
95653
+ * Contains a per-thread hydration failure so it cannot brick the runtime.
95654
+ *
95655
+ * Hydration is a recovery convenience: it replays durable history into a fresh
95656
+ * runtime. One thread that fails identity or generation checks used to fail the
95657
+ * WHOLE hydration, which `serverRuntimeStartup` turned into
95658
+ * `commandGate.failCommandReady()` — the HTTP server kept serving 200 and the
95659
+ * runtime still reported `server_ready`, while every turn was refused with
95660
+ * "Could not connect".
95661
+ *
95662
+ * Observed in production 2026-08-31: a thread replayed from a DESTROYED runtime
95663
+ * failed its generation check, and because the poison row lives in CMMD's
95664
+ * durable replica rather than on the guest, destroying and reprovisioning the
95665
+ * sprite did not clear it. One bad row could brick every future runtime for
95666
+ * that user, permanently.
95667
+ *
95668
+ * Structural failures (index runtime identity changing between pages, a
95669
+ * repeated cursor) stay fatal on purpose: those mean the index itself cannot be
95670
+ * trusted, so continuing would hydrate an unknown mixture.
95671
+ */
95672
+ function skipUnhydratableThread(operation, threadId, state) {
95673
+ return operation.pipe(catchTag("RuntimeReplicaHydrationError", (error) => gen(function* () {
95674
+ state.unhydratableThreadIds.push(threadId);
95675
+ yield* logWarning$1("skipped a thread that could not be hydrated", {
95676
+ threadId,
95677
+ detail: error.detail
95678
+ });
95679
+ })));
95680
+ }
95652
95681
  const applyPreparedReplica = fn$1("applyPreparedReplica")(function* (expectedRuntimeId, prepared, state, dependencies) {
95653
95682
  const { summary, candidate } = prepared;
95654
95683
  if (!(yield* dependencies.restoreThreadCursor({
@@ -95674,7 +95703,7 @@ function prepareReplicaPages(expectedRuntimeId, cursor, state, dependencies) {
95674
95703
  if (index === null) return;
95675
95704
  if (state.runtimeIdentity === null) state.runtimeIdentity = index.runtime;
95676
95705
  else if (!replicaRuntimeMatches(state.runtimeIdentity, index.runtime)) return yield* replicaHydrationFailure("index runtime identity changed between pages");
95677
- yield* forEach(index.threads, (summary) => prepareReplicaSummary(expectedRuntimeId, index, summary, state, dependencies), {
95706
+ yield* forEach(index.threads, (summary) => skipUnhydratableThread(prepareReplicaSummary(expectedRuntimeId, index, summary, state, dependencies), summary.threadId, state), {
95678
95707
  concurrency: 1,
95679
95708
  discard: true
95680
95709
  });
@@ -95694,16 +95723,19 @@ const hydrateRuntimeReplica = fn$1("hydrateRuntimeReplica")(function* (input, de
95694
95723
  prepared: [],
95695
95724
  runtimeIdentity: null,
95696
95725
  hydrated: 0,
95697
- skippedExisting: 0
95726
+ skippedExisting: 0,
95727
+ unhydratableThreadIds: []
95698
95728
  };
95699
95729
  yield* prepareReplicaPages(input.expectedRuntimeId, void 0, state, dependencies);
95700
- yield* forEach(state.prepared, (prepared) => applyPreparedReplica(input.expectedRuntimeId, prepared, state, dependencies), {
95730
+ yield* forEach(state.prepared, (prepared) => skipUnhydratableThread(applyPreparedReplica(input.expectedRuntimeId, prepared, state, dependencies), prepared.summary.threadId, state), {
95701
95731
  concurrency: 1,
95702
95732
  discard: true
95703
95733
  });
95704
95734
  return {
95705
95735
  hydrated: state.hydrated,
95706
- skippedExisting: state.skippedExisting
95736
+ skippedExisting: state.skippedExisting,
95737
+ skippedUnhydratable: state.unhydratableThreadIds.length,
95738
+ unhydratableThreadIds: [...state.unhydratableThreadIds]
95707
95739
  };
95708
95740
  });
95709
95741
  //#endregion
@@ -186176,7 +186208,7 @@ var Vce = {
186176
186208
  function Ve() {
186177
186209
  return Vce;
186178
186210
  }
186179
- var Us = os.homedir(), lk = os.tmpdir(), { env: Vc } = process$1, Yce = (e) => {
186211
+ var Us = $U.homedir(), lk = $U.tmpdir(), { env: Vc } = process$1, Yce = (e) => {
186180
186212
  let t = path.join(Us, "Library");
186181
186213
  return {
186182
186214
  data: path.join(t, "Application Support", e),
@@ -196376,12 +196408,12 @@ function qZ(e, t) {
196376
196408
  }
196377
196409
  return n;
196378
196410
  }
196379
- var os$2 = "https://code.claude.com/docs/en", kKe = [
196411
+ var os$1 = "https://code.claude.com/docs/en", kKe = [
196380
196412
  {
196381
196413
  matches: (e) => e.path === "permissions.defaultMode" && e.code === "invalid_value",
196382
196414
  tip: {
196383
196415
  suggestion: "Valid modes: \"acceptEdits\" (ask before file changes), \"plan\" (analysis only), \"bypassPermissions\" (auto-accept all), or \"default\" (standard behavior)",
196384
- docLink: `${os$2}/iam#permission-modes`
196416
+ docLink: `${os$1}/iam#permission-modes`
196385
196417
  }
196386
196418
  },
196387
196419
  {
@@ -196396,7 +196428,7 @@ var os$2 = "https://code.claude.com/docs/en", kKe = [
196396
196428
  matches: (e) => e.path.startsWith("env.") && e.code === "invalid_type",
196397
196429
  tip: {
196398
196430
  suggestion: "Environment variables must be strings. Wrap numbers and booleans in quotes. Example: \"DEBUG\": \"true\", \"PORT\": \"3000\"",
196399
- docLink: `${os$2}/settings#environment-variables`
196431
+ docLink: `${os$1}/settings#environment-variables`
196400
196432
  }
196401
196433
  },
196402
196434
  {
@@ -196407,14 +196439,14 @@ var os$2 = "https://code.claude.com/docs/en", kKe = [
196407
196439
  matches: (e) => e.path.startsWith("hooks.") && e.code === "invalid_key",
196408
196440
  tip: {
196409
196441
  suggestion: "Not a recognized hook event. Common events: PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, SessionEnd, Stop. Check spelling and capitalization.",
196410
- docLink: `${os$2}/hooks`
196442
+ docLink: `${os$1}/hooks`
196411
196443
  }
196412
196444
  },
196413
196445
  {
196414
196446
  matches: (e) => /\.hooks\.\d+\.command$/.test(e.path) && e.code === "invalid_type" && e.received === "undefined",
196415
196447
  tip: {
196416
196448
  suggestion: "Command hooks require `command`. For exec form (no shell), set `command` to the executable and `args` to its arguments: {\"type\": \"command\", \"command\": \"echo\", \"args\": [\"hi\"]}. For shell form, set `command` to the full shell string: {\"type\": \"command\", \"command\": \"echo hi\"}.",
196417
- docLink: `${os$2}/hooks#exec-form-and-shell-form`
196449
+ docLink: `${os$1}/hooks#exec-form-and-shell-form`
196418
196450
  }
196419
196451
  },
196420
196452
  {
@@ -196429,7 +196461,7 @@ var os$2 = "https://code.claude.com/docs/en", kKe = [
196429
196461
  matches: (e) => e.code === "unrecognized_keys",
196430
196462
  tip: {
196431
196463
  suggestion: "Check for typos or refer to the documentation for valid fields",
196432
- docLink: `${os$2}/settings`
196464
+ docLink: `${os$1}/settings`
196433
196465
  }
196434
196466
  },
196435
196467
  {
@@ -196444,13 +196476,13 @@ var os$2 = "https://code.claude.com/docs/en", kKe = [
196444
196476
  matches: (e) => e.path === "permissions.additionalDirectories" && e.code === "invalid_type",
196445
196477
  tip: {
196446
196478
  suggestion: "Must be an array of directory paths. Example: [\"~/projects\", \"/tmp/workspace\"]. You can also use --add-dir flag or /add-dir command",
196447
- docLink: `${os$2}/iam#working-directories`
196479
+ docLink: `${os$1}/iam#working-directories`
196448
196480
  }
196449
196481
  }
196450
196482
  ], AKe = {
196451
- permissions: `${os$2}/iam#configuring-permissions`,
196452
- env: `${os$2}/settings#environment-variables`,
196453
- hooks: `${os$2}/hooks`
196483
+ permissions: `${os$1}/iam#configuring-permissions`,
196484
+ env: `${os$1}/settings#environment-variables`,
196485
+ hooks: `${os$1}/hooks`
196454
196486
  };
196455
196487
  function GZ(e) {
196456
196488
  let t = kKe.find((r) => r.matches(e));
@@ -260595,7 +260627,7 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
260595
260627
  var dgram = __require("dgram");
260596
260628
  var thunky = require_thunky();
260597
260629
  var events = __require("events");
260598
- var os$1 = __require("os");
260630
+ var os = __require("os");
260599
260631
  var noop = function() {};
260600
260632
  module.exports = function(opts) {
260601
260633
  if (!opts) opts = {};
@@ -260726,14 +260758,14 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
260726
260758
  return that;
260727
260759
  };
260728
260760
  function defaultInterface() {
260729
- var networks = os$1.networkInterfaces();
260761
+ var networks = os.networkInterfaces();
260730
260762
  var names = Object.keys(networks);
260731
260763
  for (var i = 0; i < names.length; i++) {
260732
260764
  var net = networks[names[i]];
260733
260765
  for (var j = 0; j < net.length; j++) {
260734
260766
  var iface = net[j];
260735
260767
  if (isIPv4(iface.family) && !iface.internal) {
260736
- if (os$1.platform() === "darwin" && names[i] === "en0") return iface.address;
260768
+ if (os.platform() === "darwin" && names[i] === "en0") return iface.address;
260737
260769
  return "0.0.0.0";
260738
260770
  }
260739
260771
  }
@@ -260741,7 +260773,7 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
260741
260773
  return "127.0.0.1";
260742
260774
  }
260743
260775
  function allInterfaces() {
260744
- var networks = os$1.networkInterfaces();
260776
+ var networks = os.networkInterfaces();
260745
260777
  var names = Object.keys(networks);
260746
260778
  var res = [];
260747
260779
  for (var i = 0; i < names.length; i++) {
@@ -311577,7 +311609,7 @@ const connectLoginCommand = make$32("login", {
311577
311609
  })).json();
311578
311610
  },
311579
311611
  openBrowser: async (url) => {
311580
- const open = (await import("./open-FIgTDosf.mjs")).default;
311612
+ const open = (await import("./open-D8mGyWmt.mjs")).default;
311581
311613
  await open(url);
311582
311614
  return true;
311583
311615
  },
@@ -2,7 +2,7 @@
2
2
 
3
3
  import childProcess, { execFile } from "node:child_process";
4
4
  import fs from "node:fs";
5
- import os from "node:os";
5
+ import $U from "node:os";
6
6
  import path from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
8
  import process from "node:process";
@@ -49,7 +49,7 @@ function isInsideContainer() {
49
49
  //#region ../../node_modules/.bun/is-wsl@3.1.1/node_modules/is-wsl/index.js
50
50
  const isWsl = () => {
51
51
  if (process.platform !== "linux") return false;
52
- if (os.release().toLowerCase().includes("microsoft")) {
52
+ if ($U.release().toLowerCase().includes("microsoft")) {
53
53
  if (isInsideContainer()) return false;
54
54
  return true;
55
55
  }
@@ -589,4 +589,4 @@ defineLazyProperty(apps, "safari", () => detectPlatformBinary({ darwin: "Safari"
589
589
  //#endregion
590
590
  export { apps, open as default, openApp };
591
591
 
592
- //# sourceMappingURL=open-FIgTDosf.mjs.map
592
+ //# sourceMappingURL=open-D8mGyWmt.mjs.map
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "cmmd-forge": "dist/bin.mjs"
10
10
  },
11
11
  "type": "module",
12
- "version": "0.9.7",
12
+ "version": "0.9.8",
13
13
  "engines": {
14
14
  "node": "^22.16 || ^23.11 || >=24.10"
15
15
  },