frizz 0.12.10 → 0.12.12

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 (102) hide show
  1. package/dist/claude-agent-broker.js +56 -17
  2. package/dist/codex-app-server-daemon.js +57 -11
  3. package/dist/dev-child.js +1207 -517
  4. package/dist/frizz.js +591 -77
  5. package/package.json +1 -1
  6. package/runtime/cc-worker/bin/frizz-mcp.mjs +76 -18
  7. package/runtime/cc-worker/hooks/bash-background.d.mts +1 -1
  8. package/runtime/cc-worker/hooks/bash-background.mjs +17 -6
  9. package/runtime/cc-worker/hooks/deny-ask.mjs +5 -4
  10. package/runtime/cc-worker/hooks/deny-plan.mjs +3 -3
  11. package/runtime/cc-worker/hooks/session-seed.mjs +1 -1
  12. package/runtime/cc-worker/skills/gh/SKILL.md +3 -3
  13. package/web-dist/assets/{TerminalPane-BLyRh8S1.js → TerminalPane-CTuT1746.js} +1 -1
  14. package/web-dist/assets/{abnfDiagram-VRR7QNED-B0n1m57h.js → abnfDiagram-VRR7QNED-C9lXEgoU.js} +1 -1
  15. package/web-dist/assets/architecture-TIHT7OUA-cPNCo9oK.js +1 -0
  16. package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-CW78Jo4Q.js → architectureDiagram-ZJ3FMSHR-BmJyQxby.js} +1 -1
  17. package/web-dist/assets/{blockDiagram-677ZJIJ3-DasDnytT.js → blockDiagram-677ZJIJ3-DYTepy7i.js} +1 -1
  18. package/web-dist/assets/{c4Diagram-LMCZKHZV-B7cCJxqg.js → c4Diagram-LMCZKHZV-CNaJlw58.js} +1 -1
  19. package/web-dist/assets/channel-D5dgm6BA.js +1 -0
  20. package/web-dist/assets/{chunk-32BRIVSS-BBBSn1aq.js → chunk-32BRIVSS-uAMm81q2.js} +1 -1
  21. package/web-dist/assets/{chunk-52WLFC77-B5lATDKz.js → chunk-52WLFC77-DjszZCE7.js} +1 -1
  22. package/web-dist/assets/{chunk-C7G6YPKG-B86e9JiF.js → chunk-C7G6YPKG-BuHoup14.js} +1 -1
  23. package/web-dist/assets/{chunk-EX3LRPZG-CpKL4dGX.js → chunk-EX3LRPZG-Bg9UEQvR.js} +1 -1
  24. package/web-dist/assets/{chunk-FWX5IMBZ-Dp3AvQlT.js → chunk-FWX5IMBZ-CHnQfTLw.js} +2 -2
  25. package/web-dist/assets/{chunk-HOUHSVGY-i9yVPrLo.js → chunk-HOUHSVGY-ByjeQLq2.js} +1 -1
  26. package/web-dist/assets/{chunk-ICXQ74PX--Y7uMkOf.js → chunk-ICXQ74PX-DeM9b_DJ.js} +1 -1
  27. package/web-dist/assets/{chunk-MOJQB5TN-DyMHpsmW.js → chunk-MOJQB5TN-DxLERy2q.js} +1 -1
  28. package/web-dist/assets/{chunk-OGEWGWER-1mtDKLBA.js → chunk-OGEWGWER-sBPjsAxh.js} +1 -1
  29. package/web-dist/assets/{chunk-PUDLZKDR-CFgSrqyc.js → chunk-PUDLZKDR-CarEdLd9.js} +1 -1
  30. package/web-dist/assets/{chunk-Q4XR5HBZ-BPhNENQ8.js → chunk-Q4XR5HBZ-BfXpvkfr.js} +1 -1
  31. package/web-dist/assets/{chunk-V7JOEXUC-CMrXD-em.js → chunk-V7JOEXUC-B3FaJqr_.js} +1 -1
  32. package/web-dist/assets/{chunk-VAUOI2AC-B6lbggln.js → chunk-VAUOI2AC-DHsDLPEL.js} +1 -1
  33. package/web-dist/assets/{chunk-VR4S4FIN-B9qypAjb.js → chunk-VR4S4FIN-ObNNjO-z.js} +1 -1
  34. package/web-dist/assets/{chunk-WYO6CB5R-CI9tkIhS.js → chunk-WYO6CB5R-JZxgPfBf.js} +1 -1
  35. package/web-dist/assets/{chunk-ZGVPDNZ5-DFJPi6M6.js → chunk-ZGVPDNZ5-rLSAye5U.js} +1 -1
  36. package/web-dist/assets/classDiagram-OUVF2IWQ-Bj_Hjv7y.js +1 -0
  37. package/web-dist/assets/classDiagram-v2-EOCWNBFH-Bj_Hjv7y.js +1 -0
  38. package/web-dist/assets/{cynefin-VYW2F7L2-g28vb2Hf.js → cynefin-VYW2F7L2-B0-Xy-xW.js} +1 -1
  39. package/web-dist/assets/{cynefinDiagram-TSTJHNR4-bBtOt0pp.js → cynefinDiagram-TSTJHNR4-Dd3QCTMp.js} +1 -1
  40. package/web-dist/assets/{dagre-VKFMJZFB-DuIcY2-t.js → dagre-VKFMJZFB-c_sDjRhh.js} +1 -1
  41. package/web-dist/assets/{diagram-FQU43EPY-CsYoD3ve.js → diagram-FQU43EPY-DlrOA7Q2.js} +1 -1
  42. package/web-dist/assets/{diagram-G47NLZAW-H3NxrIKS.js → diagram-G47NLZAW-DNwGdtwN.js} +1 -1
  43. package/web-dist/assets/{diagram-NH7WQ7WH-DIojGMfZ.js → diagram-NH7WQ7WH-CPNunIAd.js} +1 -1
  44. package/web-dist/assets/{diagram-OA4YK3LP-D0L444Xe.js → diagram-OA4YK3LP-BZVJWnon.js} +1 -1
  45. package/web-dist/assets/{diagram-WEI45ONY-C3PEfMxp.js → diagram-WEI45ONY-B8UEevkd.js} +1 -1
  46. package/web-dist/assets/{ebnfDiagram-CCIWWBDH-Dknugppg.js → ebnfDiagram-CCIWWBDH-BGCxDQf1.js} +1 -1
  47. package/web-dist/assets/{erDiagram-Q63AITRT-Ds5u_SEw.js → erDiagram-Q63AITRT-CKnUuelS.js} +1 -1
  48. package/web-dist/assets/eventmodeling-45OFAUF4-DvqeSNur.js +1 -0
  49. package/web-dist/assets/flowDiagram-23GEKE2U-DT_LFo10.js +1 -0
  50. package/web-dist/assets/{ganttDiagram-NO4QXBWP-KFFdgLKc.js → ganttDiagram-NO4QXBWP-2-k1ZZhN.js} +1 -1
  51. package/web-dist/assets/{gitGraph-TEB2WS4Q-B62DXBoO.js → gitGraph-TEB2WS4Q-Ci3lt5M_.js} +1 -1
  52. package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-BPtTY3Ld.js → gitGraphDiagram-IHSO6WYX-B_AQwuvk.js} +1 -1
  53. package/web-dist/assets/index-CSVjp00Q.css +1 -0
  54. package/web-dist/assets/index-D5VGTEZg.js +319 -0
  55. package/web-dist/assets/{info-DKCQHKI2-Ct-TkGHr.js → info-DKCQHKI2-m3mT757b.js} +1 -1
  56. package/web-dist/assets/{infoDiagram-FWYZ7A6U-j0jFbDdJ.js → infoDiagram-FWYZ7A6U-CQw6f3Hj.js} +1 -1
  57. package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-DgfNQn9k.js → ishikawaDiagram-FXEZZL3T-C-7JgXGg.js} +1 -1
  58. package/web-dist/assets/{journeyDiagram-5HDEW3XC-BfykOv3I.js → journeyDiagram-5HDEW3XC-DhPxGm-x.js} +1 -1
  59. package/web-dist/assets/{kanban-definition-HUTT4EX6-BvhHHrMj.js → kanban-definition-HUTT4EX6-pYAdpAN-.js} +1 -1
  60. package/web-dist/assets/{line-DZ-APW6S.js → line-DtHJLrdk.js} +1 -1
  61. package/web-dist/assets/{mermaid-parser.core-BWisef3-.js → mermaid-parser.core-CiDWeD1W.js} +3 -3
  62. package/web-dist/assets/{mermaid.core-DnlDGPhM.js → mermaid.core-BIRnljFs.js} +3 -3
  63. package/web-dist/assets/{mindmap-definition-LN4V7U3C-BoTGWSEy.js → mindmap-definition-LN4V7U3C-AwCgXi_v.js} +1 -1
  64. package/web-dist/assets/{packet-7NZHBO7P-DaifVkPE.js → packet-7NZHBO7P-CnOMRKg1.js} +1 -1
  65. package/web-dist/assets/{pegDiagram-2B236MQR-DpLfBJwm.js → pegDiagram-2B236MQR-KwEiKY6p.js} +1 -1
  66. package/web-dist/assets/{pie-RZYD4A2V-BvB0Jxcm.js → pie-RZYD4A2V-BXVw5n_F.js} +1 -1
  67. package/web-dist/assets/{pieDiagram-ENE6RG2P-CSdBcMSK.js → pieDiagram-ENE6RG2P-BKeGzq7n.js} +1 -1
  68. package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-i7k-hoMS.js → quadrantDiagram-ABIIQ3AL-_B_KnoiC.js} +1 -1
  69. package/web-dist/assets/{radar-I7S5WNFK-DpnvOCzG.js → radar-I7S5WNFK-BDV-2CJh.js} +1 -1
  70. package/web-dist/assets/{railroad-3IZDKUUU-Bj4Lhzob.js → railroad-3IZDKUUU-CJLCawbl.js} +1 -1
  71. package/web-dist/assets/railroad-abnf-AHOZXSZD-BLgEAPud.js +1 -0
  72. package/web-dist/assets/railroad-ebnf-EBAXGLYW-Czt3Iqq1.js +1 -0
  73. package/web-dist/assets/railroad-peg-LSFZ7HO6-HPyLt5Zu.js +1 -0
  74. package/web-dist/assets/{railroadDiagram-RFXS5EU6-3HJeC9YI.js → railroadDiagram-RFXS5EU6-BVV6ZmA7.js} +1 -1
  75. package/web-dist/assets/{requirementDiagram-TGXJPOKE-CeBCsZVw.js → requirementDiagram-TGXJPOKE-D3JoXNiN.js} +1 -1
  76. package/web-dist/assets/{sankeyDiagram-HTMAVEWB-BPhonqDa.js → sankeyDiagram-HTMAVEWB-D7r0TcuX.js} +1 -1
  77. package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-C5nocNwQ.js → sequenceDiagram-DBY2YBRQ-B35koHCj.js} +1 -1
  78. package/web-dist/assets/{stateDiagram-2N3HPSRC-CzAZsCPb.js → stateDiagram-2N3HPSRC-DrFIFrPb.js} +1 -1
  79. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-D57MsDPe.js +1 -0
  80. package/web-dist/assets/{swimlanes-5IMT3BWC-DRn8Vs4e.js → swimlanes-5IMT3BWC-D14gjDvr.js} +1 -1
  81. package/web-dist/assets/swimlanesDiagram-G3AALYLV-DC2nRhL8.js +8 -0
  82. package/web-dist/assets/{timeline-definition-FHXFAJF6-Bc99eShR.js → timeline-definition-FHXFAJF6-DYuBi6LS.js} +1 -1
  83. package/web-dist/assets/{treeView-QDETBFTQ--Hn_52w1.js → treeView-QDETBFTQ-DWCgtuaU.js} +1 -1
  84. package/web-dist/assets/{treemap-6X3UGDF4-BCI_8eXP.js → treemap-6X3UGDF4-QuJpQ-gt.js} +1 -1
  85. package/web-dist/assets/{vennDiagram-L72KCM5P-BR-5GJF6.js → vennDiagram-L72KCM5P-BgtM82oJ.js} +1 -1
  86. package/web-dist/assets/{wardley-OPB4EBWU-4HuUekM-.js → wardley-OPB4EBWU-CWh_aioC.js} +1 -1
  87. package/web-dist/assets/{wardleyDiagram-EHGQE667-BI9w8zpX.js → wardleyDiagram-EHGQE667-BNWSkBva.js} +1 -1
  88. package/web-dist/assets/{xychartDiagram-FW5EYKEG-BZ72575j.js → xychartDiagram-FW5EYKEG-Bc6i6hg5.js} +1 -1
  89. package/web-dist/index.html +2 -2
  90. package/web-dist/assets/architecture-TIHT7OUA-BOgxi8qb.js +0 -1
  91. package/web-dist/assets/channel-cwFXt8Vr.js +0 -1
  92. package/web-dist/assets/classDiagram-OUVF2IWQ-BLP_ClYo.js +0 -1
  93. package/web-dist/assets/classDiagram-v2-EOCWNBFH-BLP_ClYo.js +0 -1
  94. package/web-dist/assets/eventmodeling-45OFAUF4-DgF-cIkx.js +0 -1
  95. package/web-dist/assets/flowDiagram-23GEKE2U-CB3C8FCr.js +0 -1
  96. package/web-dist/assets/index-B-zUKqGI.js +0 -319
  97. package/web-dist/assets/index-BIGkwpMf.css +0 -1
  98. package/web-dist/assets/railroad-abnf-AHOZXSZD-scsBBZv_.js +0 -1
  99. package/web-dist/assets/railroad-ebnf-EBAXGLYW-z2-UIe31.js +0 -1
  100. package/web-dist/assets/railroad-peg-LSFZ7HO6-Dm1rBPEF.js +0 -1
  101. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-DEGF_nZS.js +0 -1
  102. package/web-dist/assets/swimlanesDiagram-G3AALYLV-CBLKdauI.js +0 -8
@@ -2,7 +2,7 @@ import { createRequire as __frizzCreateRequire } from "node:module"; const requi
2
2
 
3
3
  // packages/server/src/backend/claude-agent-broker.ts
4
4
  import net2 from "node:net";
5
- import { readFileSync as readFileSync4, realpathSync as realpathSync2, unlinkSync as unlinkSync2, writeFileSync } from "node:fs";
5
+ import { readFileSync as readFileSync5, realpathSync as realpathSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
6
6
  import { randomUUID as randomUUID2 } from "node:crypto";
7
7
  import { fileURLToPath } from "node:url";
8
8
 
@@ -35355,13 +35355,50 @@ function objectValue(value, label) {
35355
35355
  return value;
35356
35356
  }
35357
35357
 
35358
+ // packages/server/src/runtime-lease.ts
35359
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync as readdirSync2, readFileSync as readFileSync2, unlinkSync as unlinkSync2, writeFileSync } from "node:fs";
35360
+ import { dirname as dirname4, join as join5 } from "node:path";
35361
+ var PROVISIONED_MARKER = "provisioned.json";
35362
+ var LEASES_DIR = ".leases";
35363
+ var MAX_ASCENT = 6;
35364
+ function runtimeVersionDir(bin) {
35365
+ let dir = dirname4(bin);
35366
+ for (let step = 0; step < MAX_ASCENT; step++) {
35367
+ if (existsSync2(join5(dir, PROVISIONED_MARKER))) return dir;
35368
+ const parent = dirname4(dir);
35369
+ if (parent === dir) return void 0;
35370
+ dir = parent;
35371
+ }
35372
+ return void 0;
35373
+ }
35374
+ function leaseRuntime(bin, role) {
35375
+ const versionDir = runtimeVersionDir(bin);
35376
+ if (!versionDir) return () => {
35377
+ };
35378
+ const path = join5(versionDir, LEASES_DIR, `${process.pid}.json`);
35379
+ try {
35380
+ mkdirSync2(dirname4(path), { recursive: true });
35381
+ const lease = { pid: process.pid, role, bin, at: (/* @__PURE__ */ new Date()).toISOString() };
35382
+ writeFileSync(path, JSON.stringify(lease));
35383
+ } catch {
35384
+ return () => {
35385
+ };
35386
+ }
35387
+ return () => {
35388
+ try {
35389
+ unlinkSync2(path);
35390
+ } catch {
35391
+ }
35392
+ };
35393
+ }
35394
+
35358
35395
  // packages/server/src/backend/project-mcp-servers.ts
35359
- import { readFileSync as readFileSync2 } from "node:fs";
35396
+ import { readFileSync as readFileSync3 } from "node:fs";
35360
35397
  import { homedir } from "node:os";
35361
- import { join as join5 } from "node:path";
35398
+ import { join as join6 } from "node:path";
35362
35399
  function readJsonObject(path) {
35363
35400
  try {
35364
- const parsed = JSON.parse(readFileSync2(path, "utf8"));
35401
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
35365
35402
  return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
35366
35403
  } catch {
35367
35404
  return void 0;
@@ -35455,15 +35492,15 @@ function projectMcpServers(cwd, options = {}) {
35455
35492
  const env = options.env ?? process.env;
35456
35493
  const home = options.home ?? homedir();
35457
35494
  const configOverride = options.claudeConfigDir ?? (env.CLAUDE_CONFIG_DIR?.trim() ? env.CLAUDE_CONFIG_DIR.trim() : void 0);
35458
- const accountFile = configOverride ? join5(configOverride, ".claude.json") : join5(home, ".claude.json");
35459
- const userSettingsFile = join5(configOverride ?? join5(home, ".claude"), "settings.json");
35495
+ const accountFile = configOverride ? join6(configOverride, ".claude.json") : join6(home, ".claude.json");
35496
+ const userSettingsFile = join6(configOverride ?? join6(home, ".claude"), "settings.json");
35460
35497
  const account = readJsonObject(accountFile);
35461
35498
  const out = userScopeRemoteServers(account, cwd, env);
35462
- const declared = objectField(readJsonObject(join5(cwd, ".mcp.json")), "mcpServers");
35499
+ const declared = objectField(readJsonObject(join6(cwd, ".mcp.json")), "mcpServers");
35463
35500
  if (!declared) return out;
35464
35501
  const approval = collectApproval([
35465
- readJsonObject(join5(cwd, ".claude", "settings.json")),
35466
- readJsonObject(join5(cwd, ".claude", "settings.local.json")),
35502
+ readJsonObject(join6(cwd, ".claude", "settings.json")),
35503
+ readJsonObject(join6(cwd, ".claude", "settings.local.json")),
35467
35504
  readJsonObject(userSettingsFile),
35468
35505
  objectField(objectField(account, "projects"), cwd)
35469
35506
  ]);
@@ -35494,12 +35531,12 @@ function claudeCompactionWindowOf(env) {
35494
35531
  }
35495
35532
 
35496
35533
  // packages/server/src/backend/claude-broker-diagnostics.ts
35497
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, renameSync as renameSync2, statSync as statSync2 } from "node:fs";
35498
- import { join as join6 } from "node:path";
35534
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, statSync as statSync2 } from "node:fs";
35535
+ import { join as join7 } from "node:path";
35499
35536
  var MAX_BYTES = 4 * 1024 * 1024;
35500
35537
  function appendRecord(path, record) {
35501
35538
  try {
35502
- mkdirSync2(join6(path, ".."), { recursive: true });
35539
+ mkdirSync3(join7(path, ".."), { recursive: true });
35503
35540
  try {
35504
35541
  if (statSync2(path).size > MAX_BYTES) renameSync2(path, `${path}.1`);
35505
35542
  } catch {
@@ -35560,6 +35597,7 @@ function runClaudeBroker(config) {
35560
35597
  };
35561
35598
  const writeDiagnostic = config.diagnosticLogPath ? createClaudeBrokerDiagnosticWriter(config.diagnosticLogPath, { daemonPid: process.pid, generation }) : void 0;
35562
35599
  const writeExit = config.diagnosticLogPath ? createClaudeBrokerExitWriter(config.diagnosticLogPath, { daemonPid: process.pid, generation }) : void 0;
35600
+ const releaseRuntimeLease = leaseRuntime(config.executablePath, "claude-broker");
35563
35601
  const factory = createClaudeQueryFactory({ enabled: true, executablePath: config.executablePath });
35564
35602
  const env = { ...inheritWorkerEnvironment(config.env), ...config.workerEnv ?? {} };
35565
35603
  const handle = factory.start({
@@ -35740,7 +35778,7 @@ function runClaudeBroker(config) {
35740
35778
  const recordOwner = () => {
35741
35779
  if (!config.recordPath) return null;
35742
35780
  try {
35743
- return JSON.parse(readFileSync4(config.recordPath, "utf8")).daemonPid;
35781
+ return JSON.parse(readFileSync5(config.recordPath, "utf8")).daemonPid;
35744
35782
  } catch {
35745
35783
  return null;
35746
35784
  }
@@ -35750,18 +35788,19 @@ function runClaudeBroker(config) {
35750
35788
  if (closed) return;
35751
35789
  closed = true;
35752
35790
  writeExit?.(reason, detail);
35791
+ releaseRuntimeLease();
35753
35792
  clearTimeout(idleTimer);
35754
35793
  clearInterval(reach);
35755
35794
  const owner = recordOwner();
35756
35795
  if (config.recordPath && owner === process.pid) {
35757
35796
  try {
35758
- unlinkSync2(config.recordPath);
35797
+ unlinkSync3(config.recordPath);
35759
35798
  } catch {
35760
35799
  }
35761
35800
  }
35762
35801
  if (!(published && owner !== null && owner !== process.pid) && published && process.platform !== "win32") {
35763
35802
  try {
35764
- unlinkSync2(config.socketPath);
35803
+ unlinkSync3(config.socketPath);
35765
35804
  } catch {
35766
35805
  }
35767
35806
  }
@@ -35800,7 +35839,7 @@ function runClaudeBroker(config) {
35800
35839
  void shutdown(1, "socket-listen-failed", message);
35801
35840
  });
35802
35841
  try {
35803
- unlinkSync2(config.socketPath);
35842
+ unlinkSync3(config.socketPath);
35804
35843
  } catch {
35805
35844
  }
35806
35845
  server.listen(config.socketPath, () => {
@@ -35808,7 +35847,7 @@ function runClaudeBroker(config) {
35808
35847
  if (config.recordPath) {
35809
35848
  const record = { daemonPid: process.pid, socketPath: config.socketPath, sessionId: config.sessionId, generation, createdAt: (/* @__PURE__ */ new Date()).toISOString(), capabilities: BROKER_CAPABILITIES, compactionWindow: claudeCompactionWindowOf(config.workerEnv) };
35810
35849
  try {
35811
- writeFileSync(config.recordPath, JSON.stringify(record), { mode: 384 });
35850
+ writeFileSync2(config.recordPath, JSON.stringify(record), { mode: 384 });
35812
35851
  } catch {
35813
35852
  }
35814
35853
  }
@@ -3,8 +3,8 @@ import { createRequire as __frizzCreateRequire } from "node:module"; const requi
3
3
  // packages/server/src/backend/codex-app-server-daemon.ts
4
4
  import { spawn } from "node:child_process";
5
5
  import { createServer } from "node:net";
6
- import { existsSync, readFileSync, unlinkSync as unlinkSync2, writeFileSync } from "node:fs";
7
- import { dirname } from "node:path";
6
+ import { existsSync as existsSync2, readFileSync as readFileSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
7
+ import { dirname as dirname2 } from "node:path";
8
8
  import { StringDecoder } from "node:string_decoder";
9
9
 
10
10
  // packages/server/src/backend/stale-socket-sweep.ts
@@ -70,6 +70,43 @@ function sweepStaleSockets(options, deps = {}) {
70
70
  });
71
71
  }
72
72
 
73
+ // packages/server/src/runtime-lease.ts
74
+ import { existsSync, mkdirSync, readdirSync as readdirSync2, readFileSync, unlinkSync as unlinkSync2, writeFileSync } from "node:fs";
75
+ import { dirname, join as join2 } from "node:path";
76
+ var PROVISIONED_MARKER = "provisioned.json";
77
+ var LEASES_DIR = ".leases";
78
+ var MAX_ASCENT = 6;
79
+ function runtimeVersionDir(bin) {
80
+ let dir = dirname(bin);
81
+ for (let step = 0; step < MAX_ASCENT; step++) {
82
+ if (existsSync(join2(dir, PROVISIONED_MARKER))) return dir;
83
+ const parent = dirname(dir);
84
+ if (parent === dir) return void 0;
85
+ dir = parent;
86
+ }
87
+ return void 0;
88
+ }
89
+ function leaseRuntime(bin, role) {
90
+ const versionDir = runtimeVersionDir(bin);
91
+ if (!versionDir) return () => {
92
+ };
93
+ const path = join2(versionDir, LEASES_DIR, `${process.pid}.json`);
94
+ try {
95
+ mkdirSync(dirname(path), { recursive: true });
96
+ const lease = { pid: process.pid, role, bin, at: (/* @__PURE__ */ new Date()).toISOString() };
97
+ writeFileSync(path, JSON.stringify(lease));
98
+ } catch {
99
+ return () => {
100
+ };
101
+ }
102
+ return () => {
103
+ try {
104
+ unlinkSync2(path);
105
+ } catch {
106
+ }
107
+ };
108
+ }
109
+
73
110
  // packages/server/src/backend/codex-app-server-daemon.ts
74
111
  var MAX_QUEUED_LINES = 2e4;
75
112
  var MAX_QUEUED_BYTES = 64 * 1024 * 1024;
@@ -118,10 +155,18 @@ function lineReader(onLine, onOverflow) {
118
155
  }
119
156
  function main() {
120
157
  const config = readConfig();
158
+ const releaseRuntimeLease = leaseRuntime(config.codexBin, "codex-app-server");
121
159
  const child = spawn(config.codexBin, config.appServerArgs ?? ["app-server", "--stdio"], {
122
160
  cwd: config.cwd,
123
161
  env: config.env,
124
- stdio: ["pipe", "pipe", "pipe"]
162
+ stdio: ["pipe", "pipe", "pipe"],
163
+ // This daemon is forked `detached`, which on Windows is DETACHED_PROCESS: it owns NO console. A
164
+ // console-less parent starting a console-subsystem exe (codex.exe) without CREATE_NO_WINDOW gets
165
+ // a fresh, VISIBLE console allocated for it — a black `codex.exe` window on every Codex dispatch,
166
+ // and closing it killed the app-server and every Codex thread in the project (Windows audit
167
+ // 2026-09-11, finding 4; the same mechanism PR #32 found for the update successor). The Claude
168
+ // side was safe only because the SDK passes windowsHide in its own spawn.
169
+ windowsHide: true
125
170
  });
126
171
  let client = null;
127
172
  let queuedLines = [];
@@ -131,7 +176,7 @@ function main() {
131
176
  let published = false;
132
177
  const recordOwner = () => {
133
178
  try {
134
- const value = JSON.parse(readFileSync(config.recordPath, "utf8"));
179
+ const value = JSON.parse(readFileSync2(config.recordPath, "utf8"));
135
180
  return typeof value.daemonPid === "number" ? value.daemonPid : null;
136
181
  } catch {
137
182
  return null;
@@ -145,21 +190,21 @@ function main() {
145
190
  const owner = recordOwner();
146
191
  if (owner === process.pid) {
147
192
  try {
148
- unlinkSync2(config.recordPath);
193
+ unlinkSync3(config.recordPath);
149
194
  } catch {
150
195
  }
151
196
  }
152
197
  if (published && owner !== null && owner !== process.pid) return;
153
198
  if (published && process.platform !== "win32") {
154
199
  try {
155
- unlinkSync2(config.socketPath);
200
+ unlinkSync3(config.socketPath);
156
201
  } catch {
157
202
  }
158
203
  }
159
204
  };
160
205
  const writeExitBreadcrumb = (reason) => {
161
206
  try {
162
- writeFileSync(`${config.recordPath}.exit`, JSON.stringify({
207
+ writeFileSync2(`${config.recordPath}.exit`, JSON.stringify({
163
208
  projectId: config.projectId,
164
209
  generation: config.generation,
165
210
  daemonPid: process.pid,
@@ -172,6 +217,7 @@ function main() {
172
217
  };
173
218
  const die = (code, reason) => {
174
219
  writeExitBreadcrumb(reason);
220
+ releaseRuntimeLease();
175
221
  cleanup();
176
222
  process.exit(code);
177
223
  };
@@ -279,7 +325,7 @@ function main() {
279
325
  toServer(message);
280
326
  };
281
327
  const writeRecord = () => {
282
- writeFileSync(config.recordPath, JSON.stringify({
328
+ writeFileSync2(config.recordPath, JSON.stringify({
283
329
  projectId: config.projectId,
284
330
  generation: config.generation,
285
331
  daemonPid: process.pid,
@@ -323,11 +369,11 @@ function main() {
323
369
  sock.on("close", drop);
324
370
  sock.on("error", drop);
325
371
  });
326
- const sweepOwnFamily = () => sweepStaleSockets({ dir: dirname(config.socketPath), prefix: "frizz-codex-", keep: [config.socketPath] });
372
+ const sweepOwnFamily = () => sweepStaleSockets({ dir: dirname2(config.socketPath), prefix: "frizz-codex-", keep: [config.socketPath] });
327
373
  const startListening = () => {
328
- if (process.platform !== "win32" && existsSync(config.socketPath)) {
374
+ if (process.platform !== "win32" && existsSync2(config.socketPath)) {
329
375
  try {
330
- unlinkSync2(config.socketPath);
376
+ unlinkSync3(config.socketPath);
331
377
  } catch {
332
378
  }
333
379
  }