frizz 0.10.0 → 0.11.0

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 (92) hide show
  1. package/dist/dev-child.js +408 -190
  2. package/dist/frizz.js +243 -13
  3. package/package.json +2 -2
  4. package/web-dist/assets/{TerminalPane-XNji7D_c.js → TerminalPane-DzTdpZim.js} +1 -1
  5. package/web-dist/assets/{abnfDiagram-VRR7QNED-gPeb-B7g.js → abnfDiagram-VRR7QNED-BpxlBYqa.js} +1 -1
  6. package/web-dist/assets/architecture-TIHT7OUA-Cyj72dua.js +1 -0
  7. package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-DV69ktbl.js → architectureDiagram-ZJ3FMSHR-yyvTAq0j.js} +1 -1
  8. package/web-dist/assets/{blockDiagram-677ZJIJ3-D8vw5eim.js → blockDiagram-677ZJIJ3-BLqVDdZ-.js} +1 -1
  9. package/web-dist/assets/{c4Diagram-LMCZKHZV--9PLGn-L.js → c4Diagram-LMCZKHZV-BrKEPLUT.js} +1 -1
  10. package/web-dist/assets/channel-DgpcWDXI.js +1 -0
  11. package/web-dist/assets/{chunk-32BRIVSS-D4BSk0FZ.js → chunk-32BRIVSS-S-tSRtT-.js} +1 -1
  12. package/web-dist/assets/{chunk-52WLFC77-WNcmTkcR.js → chunk-52WLFC77-DE9X7l52.js} +1 -1
  13. package/web-dist/assets/{chunk-C7G6YPKG-BDlcLa5W.js → chunk-C7G6YPKG-BdNBZMEZ.js} +1 -1
  14. package/web-dist/assets/{chunk-EX3LRPZG-CFnqFt7s.js → chunk-EX3LRPZG-D1TPCp23.js} +1 -1
  15. package/web-dist/assets/{chunk-FWX5IMBZ-Ci9LgOOg.js → chunk-FWX5IMBZ-Bi7A_VUf.js} +2 -2
  16. package/web-dist/assets/{chunk-HOUHSVGY-BTD_X5OP.js → chunk-HOUHSVGY-cdZH3cLd.js} +1 -1
  17. package/web-dist/assets/{chunk-ICXQ74PX-D2Y3Ys5K.js → chunk-ICXQ74PX-C4V2E3yL.js} +1 -1
  18. package/web-dist/assets/{chunk-MOJQB5TN-C-GDt7vC.js → chunk-MOJQB5TN-C-zmX9mY.js} +1 -1
  19. package/web-dist/assets/{chunk-OGEWGWER-DvnPoUnz.js → chunk-OGEWGWER-CwGTe6tT.js} +1 -1
  20. package/web-dist/assets/{chunk-PUDLZKDR-C3AymM-j.js → chunk-PUDLZKDR-D7GuPy2U.js} +1 -1
  21. package/web-dist/assets/{chunk-Q4XR5HBZ-DmyBNAl6.js → chunk-Q4XR5HBZ-4DNJYqvP.js} +1 -1
  22. package/web-dist/assets/{chunk-V7JOEXUC-DTuPUeRa.js → chunk-V7JOEXUC-CdOmZJqy.js} +1 -1
  23. package/web-dist/assets/{chunk-VAUOI2AC-CcW8PviB.js → chunk-VAUOI2AC-D0qOoeHa.js} +1 -1
  24. package/web-dist/assets/{chunk-VR4S4FIN-0tm6n83G.js → chunk-VR4S4FIN-D13PW9Ld.js} +1 -1
  25. package/web-dist/assets/{chunk-WYO6CB5R-CH3ADqeI.js → chunk-WYO6CB5R-DPd8fNip.js} +1 -1
  26. package/web-dist/assets/{chunk-ZGVPDNZ5-BHFnlpXH.js → chunk-ZGVPDNZ5-DEoZANj0.js} +1 -1
  27. package/web-dist/assets/classDiagram-OUVF2IWQ-22nxxqBO.js +1 -0
  28. package/web-dist/assets/classDiagram-v2-EOCWNBFH-22nxxqBO.js +1 -0
  29. package/web-dist/assets/{cynefin-VYW2F7L2-DtFCLOIN.js → cynefin-VYW2F7L2-CQfP_SH_.js} +1 -1
  30. package/web-dist/assets/{cynefinDiagram-TSTJHNR4-llFTHp2q.js → cynefinDiagram-TSTJHNR4-B_q23LrX.js} +1 -1
  31. package/web-dist/assets/{dagre-VKFMJZFB-CvBRVl_k.js → dagre-VKFMJZFB-Drf-81Vi.js} +1 -1
  32. package/web-dist/assets/{diagram-FQU43EPY-D1QXo6ri.js → diagram-FQU43EPY-CreTIGTP.js} +1 -1
  33. package/web-dist/assets/{diagram-G47NLZAW-2pZew-Bk.js → diagram-G47NLZAW-BBNZRSgW.js} +1 -1
  34. package/web-dist/assets/{diagram-NH7WQ7WH-Ch9JRwGN.js → diagram-NH7WQ7WH-DITd_c_z.js} +1 -1
  35. package/web-dist/assets/{diagram-OA4YK3LP-BIbrLf02.js → diagram-OA4YK3LP-HMl5mDli.js} +1 -1
  36. package/web-dist/assets/{diagram-WEI45ONY-D3KtL2s-.js → diagram-WEI45ONY-CxkP1cxL.js} +1 -1
  37. package/web-dist/assets/{ebnfDiagram-CCIWWBDH-D829sKG_.js → ebnfDiagram-CCIWWBDH-cOqwSqSu.js} +1 -1
  38. package/web-dist/assets/{erDiagram-Q63AITRT-Cj3Grovg.js → erDiagram-Q63AITRT-CEaFJZJ5.js} +1 -1
  39. package/web-dist/assets/eventmodeling-45OFAUF4-OZo7EY27.js +1 -0
  40. package/web-dist/assets/flowDiagram-23GEKE2U-BTrtNMK0.js +1 -0
  41. package/web-dist/assets/{ganttDiagram-NO4QXBWP-CGHaXF-g.js → ganttDiagram-NO4QXBWP-B83_pEFL.js} +1 -1
  42. package/web-dist/assets/{gitGraph-TEB2WS4Q-BbxeaotX.js → gitGraph-TEB2WS4Q-CcZy9vvP.js} +1 -1
  43. package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-C4WHE0cI.js → gitGraphDiagram-IHSO6WYX-dHJwoE1p.js} +1 -1
  44. package/web-dist/assets/{index-BpCFdr7Z.css → index-C_iC5T6e.css} +1 -1
  45. package/web-dist/assets/index-DRUjlRIw.js +318 -0
  46. package/web-dist/assets/{info-DKCQHKI2-3fKpn7Qr.js → info-DKCQHKI2-DqY5he2n.js} +1 -1
  47. package/web-dist/assets/{infoDiagram-FWYZ7A6U-CDQl4JMv.js → infoDiagram-FWYZ7A6U-COKKCbGB.js} +1 -1
  48. package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-CDKjMW-u.js → ishikawaDiagram-FXEZZL3T-C8yanhbC.js} +1 -1
  49. package/web-dist/assets/{journeyDiagram-5HDEW3XC-BOsabu1Z.js → journeyDiagram-5HDEW3XC-xOm9kUhr.js} +1 -1
  50. package/web-dist/assets/{kanban-definition-HUTT4EX6-KTuh-6eN.js → kanban-definition-HUTT4EX6-Cs_nVoSG.js} +1 -1
  51. package/web-dist/assets/{line-KaxbYSN3.js → line-BRWDTY95.js} +1 -1
  52. package/web-dist/assets/{mermaid-parser.core-B53huyyd.js → mermaid-parser.core-_snubxnm.js} +3 -3
  53. package/web-dist/assets/{mermaid.core-Bz6B5ouC.js → mermaid.core-B_sHF_kX.js} +3 -3
  54. package/web-dist/assets/{mindmap-definition-LN4V7U3C-Bb7T7B3a.js → mindmap-definition-LN4V7U3C-CROqMxsQ.js} +1 -1
  55. package/web-dist/assets/{packet-7NZHBO7P-w3lynC8r.js → packet-7NZHBO7P-Cy6k0ePg.js} +1 -1
  56. package/web-dist/assets/{pegDiagram-2B236MQR-nQ7c2Z03.js → pegDiagram-2B236MQR-CiPu5Dg4.js} +1 -1
  57. package/web-dist/assets/{pie-RZYD4A2V-B3Yko5Wb.js → pie-RZYD4A2V-BGbuoQNT.js} +1 -1
  58. package/web-dist/assets/{pieDiagram-ENE6RG2P-CN4Lp5HG.js → pieDiagram-ENE6RG2P-DXkmXblw.js} +1 -1
  59. package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-3QTB92dH.js → quadrantDiagram-ABIIQ3AL-BanFSlsg.js} +1 -1
  60. package/web-dist/assets/{radar-I7S5WNFK-8ZsXt0FI.js → radar-I7S5WNFK-CGQFn8j-.js} +1 -1
  61. package/web-dist/assets/{railroad-3IZDKUUU-C4IKxzEZ.js → railroad-3IZDKUUU-B5ADtgsA.js} +1 -1
  62. package/web-dist/assets/railroad-abnf-AHOZXSZD-C5nN5q7B.js +1 -0
  63. package/web-dist/assets/railroad-ebnf-EBAXGLYW-Bmr9Qqwv.js +1 -0
  64. package/web-dist/assets/railroad-peg-LSFZ7HO6-CEoELuaR.js +1 -0
  65. package/web-dist/assets/{railroadDiagram-RFXS5EU6-DrGnmjpD.js → railroadDiagram-RFXS5EU6-CItx2rmJ.js} +1 -1
  66. package/web-dist/assets/{requirementDiagram-TGXJPOKE-Bh9XNuxa.js → requirementDiagram-TGXJPOKE-xR5EF8t9.js} +1 -1
  67. package/web-dist/assets/{sankeyDiagram-HTMAVEWB-CXy3ra5-.js → sankeyDiagram-HTMAVEWB-5Xc3Jm9J.js} +1 -1
  68. package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-B7ESCT52.js → sequenceDiagram-DBY2YBRQ-vKameWMa.js} +1 -1
  69. package/web-dist/assets/{stateDiagram-2N3HPSRC-DFr9k5Xv.js → stateDiagram-2N3HPSRC-cd0jZZvF.js} +1 -1
  70. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-CxXmUa7L.js +1 -0
  71. package/web-dist/assets/{swimlanes-5IMT3BWC-B2RKoz1q.js → swimlanes-5IMT3BWC-9iMSvVuR.js} +1 -1
  72. package/web-dist/assets/swimlanesDiagram-G3AALYLV-VlGeDigP.js +8 -0
  73. package/web-dist/assets/{timeline-definition-FHXFAJF6-KpTqaG5g.js → timeline-definition-FHXFAJF6-C6_2LRwZ.js} +1 -1
  74. package/web-dist/assets/{treeView-QDETBFTQ-oB1a6ikv.js → treeView-QDETBFTQ-CX8-eA8C.js} +1 -1
  75. package/web-dist/assets/{treemap-6X3UGDF4-DO8OvvZg.js → treemap-6X3UGDF4-DaUY20IG.js} +1 -1
  76. package/web-dist/assets/{vennDiagram-L72KCM5P-BgTjK4_q.js → vennDiagram-L72KCM5P-CZLt-iPN.js} +1 -1
  77. package/web-dist/assets/{wardley-OPB4EBWU-CGyjn939.js → wardley-OPB4EBWU-Cjp9-zMo.js} +1 -1
  78. package/web-dist/assets/{wardleyDiagram-EHGQE667-CM_HxruS.js → wardleyDiagram-EHGQE667-BF_U8_o5.js} +1 -1
  79. package/web-dist/assets/{xychartDiagram-FW5EYKEG-vamHu0jN.js → xychartDiagram-FW5EYKEG-CJEIPPRH.js} +1 -1
  80. package/web-dist/index.html +2 -2
  81. package/web-dist/assets/architecture-TIHT7OUA-BsgSgexh.js +0 -1
  82. package/web-dist/assets/channel-ClLnncxh.js +0 -1
  83. package/web-dist/assets/classDiagram-OUVF2IWQ-CwLnPgud.js +0 -1
  84. package/web-dist/assets/classDiagram-v2-EOCWNBFH-CwLnPgud.js +0 -1
  85. package/web-dist/assets/eventmodeling-45OFAUF4-CzZyv3HA.js +0 -1
  86. package/web-dist/assets/flowDiagram-23GEKE2U-rQ7PRoGL.js +0 -1
  87. package/web-dist/assets/index-CiaKj-0V.js +0 -506
  88. package/web-dist/assets/railroad-abnf-AHOZXSZD-g2si5iUv.js +0 -1
  89. package/web-dist/assets/railroad-ebnf-EBAXGLYW-BikkLG6y.js +0 -1
  90. package/web-dist/assets/railroad-peg-LSFZ7HO6-Dv4rDehz.js +0 -1
  91. package/web-dist/assets/stateDiagram-v2-6OUMAXLB-BQUd0MEa.js +0 -1
  92. package/web-dist/assets/swimlanesDiagram-G3AALYLV-GWn4zXxj.js +0 -8
package/dist/dev-child.js CHANGED
@@ -4762,10 +4762,10 @@ var require_resolve_block_map = __commonJS({
4762
4762
  let offset = bm.offset;
4763
4763
  let commentEnd = null;
4764
4764
  for (const collItem of bm.items) {
4765
- const { start, key, sep: sep5, value } = collItem;
4765
+ const { start, key, sep: sep6, value } = collItem;
4766
4766
  const keyProps = resolveProps.resolveProps(start, {
4767
4767
  indicator: "explicit-key-ind",
4768
- next: key ?? sep5?.[0],
4768
+ next: key ?? sep6?.[0],
4769
4769
  offset,
4770
4770
  onError,
4771
4771
  parentIndent: bm.indent,
@@ -4779,7 +4779,7 @@ var require_resolve_block_map = __commonJS({
4779
4779
  else if ("indent" in key && key.indent !== bm.indent)
4780
4780
  onError(offset, "BAD_INDENT", startColMsg);
4781
4781
  }
4782
- if (!keyProps.anchor && !keyProps.tag && !sep5) {
4782
+ if (!keyProps.anchor && !keyProps.tag && !sep6) {
4783
4783
  commentEnd = keyProps.end;
4784
4784
  if (keyProps.comment) {
4785
4785
  if (map.comment)
@@ -4803,7 +4803,7 @@ var require_resolve_block_map = __commonJS({
4803
4803
  ctx.atKey = false;
4804
4804
  if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
4805
4805
  onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
4806
- const valueProps = resolveProps.resolveProps(sep5 ?? [], {
4806
+ const valueProps = resolveProps.resolveProps(sep6 ?? [], {
4807
4807
  indicator: "map-value-ind",
4808
4808
  next: value,
4809
4809
  offset: keyNode.range[2],
@@ -4819,7 +4819,7 @@ var require_resolve_block_map = __commonJS({
4819
4819
  if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
4820
4820
  onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
4821
4821
  }
4822
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep5, null, valueProps, onError);
4822
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep6, null, valueProps, onError);
4823
4823
  if (ctx.schema.compat)
4824
4824
  utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
4825
4825
  offset = valueNode.range[2];
@@ -4910,7 +4910,7 @@ var require_resolve_end = __commonJS({
4910
4910
  let comment = "";
4911
4911
  if (end) {
4912
4912
  let hasSpace = false;
4913
- let sep5 = "";
4913
+ let sep6 = "";
4914
4914
  for (const token of end) {
4915
4915
  const { source, type } = token;
4916
4916
  switch (type) {
@@ -4924,13 +4924,13 @@ var require_resolve_end = __commonJS({
4924
4924
  if (!comment)
4925
4925
  comment = cb;
4926
4926
  else
4927
- comment += sep5 + cb;
4928
- sep5 = "";
4927
+ comment += sep6 + cb;
4928
+ sep6 = "";
4929
4929
  break;
4930
4930
  }
4931
4931
  case "newline":
4932
4932
  if (comment)
4933
- sep5 += source;
4933
+ sep6 += source;
4934
4934
  hasSpace = true;
4935
4935
  break;
4936
4936
  default:
@@ -4973,18 +4973,18 @@ var require_resolve_flow_collection = __commonJS({
4973
4973
  let offset = fc.offset + fc.start.source.length;
4974
4974
  for (let i = 0; i < fc.items.length; ++i) {
4975
4975
  const collItem = fc.items[i];
4976
- const { start, key, sep: sep5, value } = collItem;
4976
+ const { start, key, sep: sep6, value } = collItem;
4977
4977
  const props = resolveProps.resolveProps(start, {
4978
4978
  flow: fcName,
4979
4979
  indicator: "explicit-key-ind",
4980
- next: key ?? sep5?.[0],
4980
+ next: key ?? sep6?.[0],
4981
4981
  offset,
4982
4982
  onError,
4983
4983
  parentIndent: fc.indent,
4984
4984
  startOnNewline: false
4985
4985
  });
4986
4986
  if (!props.found) {
4987
- if (!props.anchor && !props.tag && !sep5 && !value) {
4987
+ if (!props.anchor && !props.tag && !sep6 && !value) {
4988
4988
  if (i === 0 && props.comma)
4989
4989
  onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
4990
4990
  else if (i < fc.items.length - 1)
@@ -5038,8 +5038,8 @@ var require_resolve_flow_collection = __commonJS({
5038
5038
  }
5039
5039
  }
5040
5040
  }
5041
- if (!isMap && !sep5 && !props.found) {
5042
- const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep5, null, props, onError);
5041
+ if (!isMap && !sep6 && !props.found) {
5042
+ const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep6, null, props, onError);
5043
5043
  coll.items.push(valueNode);
5044
5044
  offset = valueNode.range[2];
5045
5045
  if (isBlock(value))
@@ -5051,7 +5051,7 @@ var require_resolve_flow_collection = __commonJS({
5051
5051
  if (isBlock(key))
5052
5052
  onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
5053
5053
  ctx.atKey = false;
5054
- const valueProps = resolveProps.resolveProps(sep5 ?? [], {
5054
+ const valueProps = resolveProps.resolveProps(sep6 ?? [], {
5055
5055
  flow: fcName,
5056
5056
  indicator: "map-value-ind",
5057
5057
  next: value,
@@ -5062,8 +5062,8 @@ var require_resolve_flow_collection = __commonJS({
5062
5062
  });
5063
5063
  if (valueProps.found) {
5064
5064
  if (!isMap && !props.found && ctx.options.strict) {
5065
- if (sep5)
5066
- for (const st of sep5) {
5065
+ if (sep6)
5066
+ for (const st of sep6) {
5067
5067
  if (st === valueProps.found)
5068
5068
  break;
5069
5069
  if (st.type === "newline") {
@@ -5080,7 +5080,7 @@ var require_resolve_flow_collection = __commonJS({
5080
5080
  else
5081
5081
  onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
5082
5082
  }
5083
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep5, null, valueProps, onError) : null;
5083
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep6, null, valueProps, onError) : null;
5084
5084
  if (valueNode) {
5085
5085
  if (isBlock(value))
5086
5086
  onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
@@ -5260,7 +5260,7 @@ var require_resolve_block_scalar = __commonJS({
5260
5260
  chompStart = i + 1;
5261
5261
  }
5262
5262
  let value = "";
5263
- let sep5 = "";
5263
+ let sep6 = "";
5264
5264
  let prevMoreIndented = false;
5265
5265
  for (let i = 0; i < contentStart; ++i)
5266
5266
  value += lines[i][0].slice(trimIndent) + "\n";
@@ -5277,24 +5277,24 @@ var require_resolve_block_scalar = __commonJS({
5277
5277
  indent = "";
5278
5278
  }
5279
5279
  if (type === Scalar.Scalar.BLOCK_LITERAL) {
5280
- value += sep5 + indent.slice(trimIndent) + content;
5281
- sep5 = "\n";
5280
+ value += sep6 + indent.slice(trimIndent) + content;
5281
+ sep6 = "\n";
5282
5282
  } else if (indent.length > trimIndent || content[0] === " ") {
5283
- if (sep5 === " ")
5284
- sep5 = "\n";
5285
- else if (!prevMoreIndented && sep5 === "\n")
5286
- sep5 = "\n\n";
5287
- value += sep5 + indent.slice(trimIndent) + content;
5288
- sep5 = "\n";
5283
+ if (sep6 === " ")
5284
+ sep6 = "\n";
5285
+ else if (!prevMoreIndented && sep6 === "\n")
5286
+ sep6 = "\n\n";
5287
+ value += sep6 + indent.slice(trimIndent) + content;
5288
+ sep6 = "\n";
5289
5289
  prevMoreIndented = true;
5290
5290
  } else if (content === "") {
5291
- if (sep5 === "\n")
5291
+ if (sep6 === "\n")
5292
5292
  value += "\n";
5293
5293
  else
5294
- sep5 = "\n";
5294
+ sep6 = "\n";
5295
5295
  } else {
5296
- value += sep5 + content;
5297
- sep5 = " ";
5296
+ value += sep6 + content;
5297
+ sep6 = " ";
5298
5298
  prevMoreIndented = false;
5299
5299
  }
5300
5300
  }
@@ -5476,25 +5476,25 @@ var require_resolve_flow_scalar = __commonJS({
5476
5476
  if (!match2)
5477
5477
  return source;
5478
5478
  let res = match2[1];
5479
- let sep5 = " ";
5479
+ let sep6 = " ";
5480
5480
  let pos = first.lastIndex;
5481
5481
  line.lastIndex = pos;
5482
5482
  while (match2 = line.exec(source)) {
5483
5483
  if (match2[1] === "") {
5484
- if (sep5 === "\n")
5485
- res += sep5;
5484
+ if (sep6 === "\n")
5485
+ res += sep6;
5486
5486
  else
5487
- sep5 = "\n";
5487
+ sep6 = "\n";
5488
5488
  } else {
5489
- res += sep5 + match2[1];
5490
- sep5 = " ";
5489
+ res += sep6 + match2[1];
5490
+ sep6 = " ";
5491
5491
  }
5492
5492
  pos = line.lastIndex;
5493
5493
  }
5494
5494
  const last = /[ \t]*(.*)/sy;
5495
5495
  last.lastIndex = pos;
5496
5496
  match2 = last.exec(source);
5497
- return res + sep5 + (match2?.[1] ?? "");
5497
+ return res + sep6 + (match2?.[1] ?? "");
5498
5498
  }
5499
5499
  function doubleQuotedValue(source, onError) {
5500
5500
  let res = "";
@@ -6304,14 +6304,14 @@ var require_cst_stringify = __commonJS({
6304
6304
  }
6305
6305
  }
6306
6306
  }
6307
- function stringifyItem({ start, key, sep: sep5, value }) {
6307
+ function stringifyItem({ start, key, sep: sep6, value }) {
6308
6308
  let res = "";
6309
6309
  for (const st of start)
6310
6310
  res += st.source;
6311
6311
  if (key)
6312
6312
  res += stringifyToken(key);
6313
- if (sep5)
6314
- for (const st of sep5)
6313
+ if (sep6)
6314
+ for (const st of sep6)
6315
6315
  res += st.source;
6316
6316
  if (value)
6317
6317
  res += stringifyToken(value);
@@ -7478,18 +7478,18 @@ var require_parser = __commonJS({
7478
7478
  if (this.type === "map-value-ind") {
7479
7479
  const prev = getPrevProps(this.peek(2));
7480
7480
  const start = getFirstKeyStartProps(prev);
7481
- let sep5;
7481
+ let sep6;
7482
7482
  if (scalar.end) {
7483
- sep5 = scalar.end;
7484
- sep5.push(this.sourceToken);
7483
+ sep6 = scalar.end;
7484
+ sep6.push(this.sourceToken);
7485
7485
  delete scalar.end;
7486
7486
  } else
7487
- sep5 = [this.sourceToken];
7487
+ sep6 = [this.sourceToken];
7488
7488
  const map = {
7489
7489
  type: "block-map",
7490
7490
  offset: scalar.offset,
7491
7491
  indent: scalar.indent,
7492
- items: [{ start, key: scalar, sep: sep5 }]
7492
+ items: [{ start, key: scalar, sep: sep6 }]
7493
7493
  };
7494
7494
  this.onKeyLine = true;
7495
7495
  this.stack[this.stack.length - 1] = map;
@@ -7642,15 +7642,15 @@ var require_parser = __commonJS({
7642
7642
  } else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
7643
7643
  const start2 = getFirstKeyStartProps(it.start);
7644
7644
  const key = it.key;
7645
- const sep5 = it.sep;
7646
- sep5.push(this.sourceToken);
7645
+ const sep6 = it.sep;
7646
+ sep6.push(this.sourceToken);
7647
7647
  delete it.key;
7648
7648
  delete it.sep;
7649
7649
  this.stack.push({
7650
7650
  type: "block-map",
7651
7651
  offset: this.offset,
7652
7652
  indent: this.indent,
7653
- items: [{ start: start2, key, sep: sep5 }]
7653
+ items: [{ start: start2, key, sep: sep6 }]
7654
7654
  });
7655
7655
  } else if (start.length > 0) {
7656
7656
  it.sep = it.sep.concat(start, this.sourceToken);
@@ -7844,13 +7844,13 @@ var require_parser = __commonJS({
7844
7844
  const prev = getPrevProps(parent);
7845
7845
  const start = getFirstKeyStartProps(prev);
7846
7846
  fixFlowSeqItems(fc);
7847
- const sep5 = fc.end.splice(1, fc.end.length);
7848
- sep5.push(this.sourceToken);
7847
+ const sep6 = fc.end.splice(1, fc.end.length);
7848
+ sep6.push(this.sourceToken);
7849
7849
  const map = {
7850
7850
  type: "block-map",
7851
7851
  offset: fc.offset,
7852
7852
  indent: fc.indent,
7853
- items: [{ start, key: fc, sep: sep5 }]
7853
+ items: [{ start, key: fc, sep: sep6 }]
7854
7854
  };
7855
7855
  this.onKeyLine = true;
7856
7856
  this.stack[this.stack.length - 1] = map;
@@ -15746,11 +15746,25 @@ async function ghInstalled() {
15746
15746
  }
15747
15747
  }
15748
15748
  async function ghAuthed() {
15749
+ if (Date.now() < ghAuthedUntil) return true;
15750
+ if (ghAuthedInFlight) return await ghAuthedInFlight;
15751
+ const probe = (async () => {
15752
+ const authed = await (async () => {
15753
+ try {
15754
+ await gh(["auth", "status", "--active"]);
15755
+ return true;
15756
+ } catch {
15757
+ return await ghHasToken();
15758
+ }
15759
+ })();
15760
+ if (authed) ghAuthedUntil = Date.now() + GH_AUTHED_TTL_MS;
15761
+ return authed;
15762
+ })();
15763
+ ghAuthedInFlight = probe;
15749
15764
  try {
15750
- await gh(["auth", "status", "--active"]);
15751
- return true;
15752
- } catch {
15753
- return await ghHasToken();
15765
+ return await probe;
15766
+ } finally {
15767
+ ghAuthedInFlight = null;
15754
15768
  }
15755
15769
  }
15756
15770
  async function ghHasToken() {
@@ -16044,7 +16058,7 @@ function effectiveTemplate(custom2) {
16044
16058
  if (custom2 && custom2.trim().length > 0) return custom2;
16045
16059
  return DEFAULT_GITHUB_PROMPT;
16046
16060
  }
16047
- var pexec, GH_TIMEOUT, GH_MAXBUF, SEARCH_SORT, SEARCH_RESULT_WINDOW, LINKED_PR_CHUNK, GITHUB_PAGE_SIZE, BODY_CAP, DEFAULT_GITHUB_PROMPT;
16061
+ var pexec, GH_TIMEOUT, GH_MAXBUF, GH_AUTHED_TTL_MS, ghAuthedUntil, ghAuthedInFlight, SEARCH_SORT, SEARCH_RESULT_WINDOW, LINKED_PR_CHUNK, GITHUB_PAGE_SIZE, BODY_CAP, DEFAULT_GITHUB_PROMPT;
16048
16062
  var init_github = __esm({
16049
16063
  "packages/server/src/github.ts"() {
16050
16064
  "use strict";
@@ -16052,6 +16066,9 @@ var init_github = __esm({
16052
16066
  pexec = promisify(execFile);
16053
16067
  GH_TIMEOUT = 8e3;
16054
16068
  GH_MAXBUF = 16 * 1024 * 1024;
16069
+ GH_AUTHED_TTL_MS = 3e4;
16070
+ ghAuthedUntil = 0;
16071
+ ghAuthedInFlight = null;
16055
16072
  SEARCH_SORT = {
16056
16073
  reactions: "reactions",
16057
16074
  recent: "updated"
@@ -18631,6 +18648,15 @@ function slugMintedFromTitle(slug, title) {
18631
18648
  const derived = slugify(title);
18632
18649
  return derived === slug || derived === slug.replace(/-\d+$/, "");
18633
18650
  }
18651
+ function groupBySlug(rows) {
18652
+ const bySlug = /* @__PURE__ */ new Map();
18653
+ for (const row of rows) {
18654
+ const bucket = bySlug.get(row.thread_slug);
18655
+ if (bucket) bucket.push(row);
18656
+ else bySlug.set(row.thread_slug, [row]);
18657
+ }
18658
+ return bySlug;
18659
+ }
18634
18660
  function ensureStorageSchema(db) {
18635
18661
  db.exec(STORAGE_SCHEMA);
18636
18662
  for (const column of ["pinned_at TEXT"]) {
@@ -18982,6 +19008,9 @@ function createStorage(source, projectId) {
18982
19008
  const armedTimersBySlugStmt = scope.prepare(
18983
19009
  "SELECT * FROM thread_timer WHERE project_id = @project_id AND thread_slug = ? AND state = 'armed' ORDER BY fire_at, id"
18984
19010
  );
19011
+ const armedTimersStmt = scope.prepare(
19012
+ "SELECT * FROM thread_timer WHERE project_id = @project_id AND state = 'armed' ORDER BY fire_at, id"
19013
+ );
18985
19014
  const timerByIdStmt = scope.prepare("SELECT * FROM thread_timer WHERE project_id = @project_id AND id = ?");
18986
19015
  const dueTimersStmt = scope.prepare(
18987
19016
  "SELECT * FROM thread_timer WHERE project_id = @project_id AND state = 'armed' AND fire_at <= ? ORDER BY fire_at, id"
@@ -19081,6 +19110,9 @@ function createStorage(source, projectId) {
19081
19110
  const openThreadQuestionsStmt = scope.prepare(
19082
19111
  "SELECT * FROM thread_question WHERE project_id = @project_id AND state = 'open' ORDER BY asked_at, rowid"
19083
19112
  );
19113
+ const allThreadQuestionsStmt = scope.prepare(
19114
+ "SELECT * FROM thread_question WHERE project_id = @project_id ORDER BY asked_at, rowid"
19115
+ );
19084
19116
  const answerThreadQuestionStmt = scope.prepare(`
19085
19117
  UPDATE thread_question SET state = 'answered', answer = ?, settled_at = ?
19086
19118
  WHERE project_id = @project_id AND id = ? AND state = 'open'
@@ -19106,6 +19138,9 @@ function createStorage(source, projectId) {
19106
19138
  ON CONFLICT(project_id, thread_slug) DO UPDATE SET body = excluded.body, done_at = excluded.done_at
19107
19139
  `);
19108
19140
  const getThreadDoneStmt = scope.prepare("SELECT body, done_at FROM thread_done WHERE project_id = @project_id AND thread_slug = ?");
19141
+ const allThreadDoneStmt = scope.prepare(
19142
+ "SELECT thread_slug, body, done_at FROM thread_done WHERE project_id = @project_id"
19143
+ );
19109
19144
  const clearThreadDoneStmt = scope.prepare("DELETE FROM thread_done WHERE project_id = @project_id AND thread_slug = ?");
19110
19145
  const clearExpiredSnoozesStmt = scope.prepare(`
19111
19146
  UPDATE session SET snoozed_until = NULL
@@ -19259,6 +19294,7 @@ function createStorage(source, projectId) {
19259
19294
  SET model = ?, effort = ?, profile_revision = profile_revision + 1
19260
19295
  WHERE project_id = @project_id AND slug = ? AND session_id = ? AND runtime_generation = ?
19261
19296
  AND runtime_control IS NULL AND profile_pending_model IS NULL AND profile_pending_effort IS NULL
19297
+ AND (profile_set_at IS NULL OR backend = 'codex')
19262
19298
  AND (model IS NOT ? OR effort IS NOT ?)
19263
19299
  `);
19264
19300
  const beginRuntimeGenerationStmt = scope.prepare(`
@@ -19599,6 +19635,9 @@ function createStorage(source, projectId) {
19599
19635
  resetParkBumps: (slug) => void resetParkBumpsStmt.run(slug),
19600
19636
  armPrWatch: (watch2) => void armPrWatchStmt.run(watch2),
19601
19637
  listPrWatches: (slug, opts) => (opts?.armedOnly ? armedPrWatchesBySlugStmt : prWatchesBySlugStmt).all(slug),
19638
+ // Grouped off `armedPrWatchesStmt` — the scheduler's own whole-project read, which already carries
19639
+ // the identical `state = 'armed'` predicate and `created_at, id` order the per-slug statement uses.
19640
+ armedPrWatchesBySlug: () => groupBySlug(armedPrWatchesStmt.all()),
19602
19641
  getPrWatch: (id) => prWatchByIdStmt.get(id),
19603
19642
  armedPrWatches: () => armedPrWatchesStmt.all(),
19604
19643
  expiredPrWatches: (nowMs) => expiredPrWatchesStmt.all(nowMs),
@@ -19616,6 +19655,9 @@ function createStorage(source, projectId) {
19616
19655
  return threadWatchByIdStmt.get(w.id);
19617
19656
  },
19618
19657
  listThreadWatches: (slug, opts) => (opts?.armedOnly ? armedThreadWatchesBySlugStmt : threadWatchesBySlugStmt).all(slug),
19658
+ // Grouped off `armedThreadWatchesStmt`, for the same reason as the PR watchers above: it is already
19659
+ // the identical predicate and order, asked of the whole project instead of one slug.
19660
+ armedThreadWatchesBySlug: () => groupBySlug(armedThreadWatchesStmt.all()),
19619
19661
  getThreadWatch: (id) => threadWatchByIdStmt.get(id),
19620
19662
  expiredThreadWatches: (nowMs) => expiredThreadWatchesStmt.all(nowMs),
19621
19663
  armedThreadWatches: () => armedThreadWatchesStmt.all(),
@@ -19624,6 +19666,7 @@ function createStorage(source, projectId) {
19624
19666
  return threadQuestionByIdStmt.get(q.id);
19625
19667
  },
19626
19668
  listThreadQuestions: (slug, opts) => (opts?.openOnly ? openThreadQuestionsBySlugStmt : threadQuestionsBySlugStmt).all(slug),
19669
+ threadQuestionsBySlug: () => groupBySlug(allThreadQuestionsStmt.all()),
19627
19670
  getThreadQuestion: (id) => threadQuestionByIdStmt.get(id),
19628
19671
  openThreadQuestions: () => openThreadQuestionsStmt.all(),
19629
19672
  answerThreadQuestion: (id, answer, atMs) => answerThreadQuestionStmt.run(answer, atMs, id).changes === 1,
@@ -19638,11 +19681,19 @@ function createStorage(source, projectId) {
19638
19681
  const row = getThreadDoneStmt.get(slug);
19639
19682
  return row ? { body: row.body, doneAt: row.done_at } : void 0;
19640
19683
  },
19684
+ // The same ms→`doneAt` mapping as `getThreadDone`, applied once per row instead of once per call,
19685
+ // so the board reads the identical shape out of the map that it read out of the single-row call.
19686
+ threadDoneBySlug: () => {
19687
+ const bySlug = /* @__PURE__ */ new Map();
19688
+ for (const row of allThreadDoneStmt.all()) bySlug.set(row.thread_slug, { body: row.body, doneAt: row.done_at });
19689
+ return bySlug;
19690
+ },
19641
19691
  clearThreadDone: (slug) => clearThreadDoneStmt.run(slug).changes > 0,
19642
19692
  dropThreadWatch: (slug, id, settledAtMs) => dropThreadWatchStmt.run(settledAtMs, id, slug).changes === 1,
19643
19693
  settleThreadWatch: (id, settledAtMs, state = "settled") => settleThreadWatchStmt.run(state, settledAtMs, id).changes === 1,
19644
19694
  armThreadTimer: (timer) => void armTimerStmt.run(timer),
19645
19695
  listThreadTimers: (slug, opts) => (opts?.armedOnly ? armedTimersBySlugStmt : timersBySlugStmt).all(slug),
19696
+ armedThreadTimersBySlug: () => groupBySlug(armedTimersStmt.all()),
19646
19697
  getThreadTimer: (id) => timerByIdStmt.get(id),
19647
19698
  dueThreadTimers: (nowMs) => dueTimersStmt.all(nowMs),
19648
19699
  cancelThreadTimer: (slug, id, settledAtMs) => cancelTimerStmt.run(settledAtMs, id, slug).changes === 1,
@@ -22695,20 +22746,41 @@ var init_tail_cache = __esm({
22695
22746
 
22696
22747
  // packages/server/src/tailer.ts
22697
22748
  import { statSync as statSync8, openSync as openSync10, readSync as readSync4, closeSync as closeSync9, readdirSync as readdirSync5, realpathSync as realpathSync5, mkdirSync as mkdirSync10, writeFileSync as writeFileSync8, readFileSync as readFileSync12, existsSync as existsSync5 } from "node:fs";
22698
- import { execFileSync as execFileSync4 } from "node:child_process";
22749
+ import { execFile as execFile2 } from "node:child_process";
22750
+ import { promisify as promisify2 } from "node:util";
22699
22751
  import { basename as basename4, join as join18 } from "node:path";
22700
22752
  import { homedir as homedir7 } from "node:os";
22701
- function probeShellAlive(outputFile) {
22702
- if (!existsSync5(outputFile)) return void 0;
22753
+ async function probeShellsAlive(outputFiles) {
22754
+ const verdicts = /* @__PURE__ */ new Map();
22755
+ const live = [];
22756
+ for (const file of outputFiles) {
22757
+ if (!existsSync5(file)) {
22758
+ verdicts.set(file, void 0);
22759
+ continue;
22760
+ }
22761
+ try {
22762
+ live.push({ requested: file, real: realpathSync5(file) });
22763
+ } catch {
22764
+ verdicts.set(file, void 0);
22765
+ }
22766
+ }
22767
+ if (live.length === 0) return verdicts;
22768
+ let stdout = "";
22703
22769
  try {
22704
- const out = execFileSync4("lsof", ["-t", "--", outputFile], { encoding: "utf8", timeout: 4e3, stdio: ["ignore", "pipe", "ignore"] });
22705
- return out.trim().length > 0;
22770
+ stdout = (await execFileAsync("lsof", ["-F", "pn", "--", ...live.map((f) => f.real)], { encoding: "utf8", timeout: 8e3 })).stdout;
22706
22771
  } catch (err) {
22707
22772
  const e = err;
22708
- if (e.code === "ENOENT") return void 0;
22709
- if (e.status === 1) return false;
22710
- return void 0;
22773
+ const ran = typeof e.code === "number" && !e.killed;
22774
+ if (!ran) {
22775
+ for (const f of live) verdicts.set(f.requested, void 0);
22776
+ return verdicts;
22777
+ }
22778
+ stdout = e.stdout ?? "";
22711
22779
  }
22780
+ const held = /* @__PURE__ */ new Set();
22781
+ for (const line of stdout.split("\n")) if (line.startsWith("n")) held.add(line.slice(1));
22782
+ for (const f of live) verdicts.set(f.requested, held.has(f.real));
22783
+ return verdicts;
22712
22784
  }
22713
22785
  function activityMinute(at) {
22714
22786
  if (!at) return "";
@@ -23905,16 +23977,48 @@ ${ask}`;
23905
23977
  return void 0;
23906
23978
  }
23907
23979
  const shellAliveCache = /* @__PURE__ */ new Map();
23980
+ const shellProbeWanted = /* @__PURE__ */ new Set();
23981
+ let shellProbeInFlight = false;
23982
+ let shellProbeArmed;
23983
+ function armShellProbeFlush() {
23984
+ if (shellProbeArmed) return;
23985
+ shellProbeArmed = setTimeout(() => {
23986
+ shellProbeArmed = void 0;
23987
+ flushShellProbes();
23988
+ }, 0);
23989
+ shellProbeArmed.unref?.();
23990
+ }
23991
+ function flushShellProbes() {
23992
+ if (shellProbeInFlight || shellProbeWanted.size === 0) return;
23993
+ const batch = [...shellProbeWanted];
23994
+ shellProbeWanted.clear();
23995
+ shellProbeInFlight = true;
23996
+ void probeShellsAlive(batch).then((verdicts) => {
23997
+ for (const [file, alive] of verdicts) {
23998
+ if (alive === void 0) continue;
23999
+ shellAliveCache.set(file, { at: now(), alive });
24000
+ }
24001
+ if (verdicts.size > 0) deps.onChange();
24002
+ }).catch(() => {
24003
+ }).finally(() => {
24004
+ shellProbeInFlight = false;
24005
+ });
24006
+ }
23908
24007
  function shellIsGone(e) {
23909
24008
  if (!e.outputFile) return false;
23910
24009
  const started = Date.parse(e.startedAt);
23911
24010
  if (!Number.isFinite(started) || now() - started < SHELL_PROBE_GRACE_MS) return false;
23912
24011
  const cached2 = shellAliveCache.get(e.outputFile);
23913
24012
  if (cached2 && (cached2.alive === false || now() - cached2.at < SHELL_PROBE_TTL_MS)) return !cached2.alive;
23914
- const alive = (deps.shellAlive ?? probeShellAlive)(e.outputFile);
23915
- if (alive === void 0) return false;
23916
- shellAliveCache.set(e.outputFile, { at: now(), alive });
23917
- return !alive;
24013
+ if (deps.shellAlive) {
24014
+ const alive = deps.shellAlive(e.outputFile);
24015
+ if (alive === void 0) return false;
24016
+ shellAliveCache.set(e.outputFile, { at: now(), alive });
24017
+ return !alive;
24018
+ }
24019
+ shellProbeWanted.add(e.outputFile);
24020
+ armShellProbeFlush();
24021
+ return false;
23918
24022
  }
23919
24023
  function backgroundShellLookup(slug, id) {
23920
24024
  const state = states.get(slug);
@@ -24395,14 +24499,27 @@ ${detail2}
24395
24499
  let primedRows = 0;
24396
24500
  const tickStartedMs = monotonicNow();
24397
24501
  primeIncomplete = false;
24502
+ const primeDeferred = (row) => (
24503
+ // Yield the slot to a still-cold visible row — but never at the cost of the forward-progress
24504
+ // guarantee above. `primedRows > 0` keeps the archive advancing by at least one row per tick
24505
+ // even if a visible row were somehow to stay cold indefinitely, so deferral can never become
24506
+ // starvation. The visible row still primes on this same tick; it just is not necessarily first.
24507
+ coldVisibleRow && primedRows > 0 && rowIsArchived(row) || primedRows >= MAX_PRIME_ROWS_PER_TICK || primedRows > 0 && monotonicNow() - tickStartedMs > PRIME_BUDGET_MS
24508
+ );
24398
24509
  for (const row of rows) {
24399
24510
  if (primeProgress && primed % PRIME_PROGRESS_EVERY === 0) primeProgress(primed, rows.length);
24400
24511
  primed++;
24401
24512
  const backend = resolveBackend(row.backend);
24402
24513
  const nativeId = row.agent_session_id ?? row.transcript_id ?? row.session_id;
24403
- let state = states.get(row.slug);
24514
+ const known = states.get(row.slug);
24404
24515
  const runtimeGeneration = row.runtime_generation ?? 0;
24405
- if (!state || state.sessionId !== row.session_id || state.nativeSessionId !== nativeId || state.runtimeGeneration !== runtimeGeneration) {
24516
+ const keepable = known !== void 0 && known.sessionId === row.session_id && known.nativeSessionId === nativeId && known.runtimeGeneration === runtimeGeneration;
24517
+ let state = keepable ? known : void 0;
24518
+ if (!state && primeDeferred(row)) {
24519
+ primeIncomplete = true;
24520
+ continue;
24521
+ }
24522
+ if (!state) {
24406
24523
  const path = backend.transcriptPath(nativeId) ?? join18(logDir, `${nativeId}.jsonl`);
24407
24524
  state = newTailState(row.slug, row.session_id, path, false, nativeId, runtimeGeneration);
24408
24525
  state.dismissedOps = deps.storage.retiredOps(row.slug, row.session_id);
@@ -24416,13 +24533,7 @@ ${detail2}
24416
24533
  const prevNoTranscript = state.noTranscript;
24417
24534
  if (row.backend !== "codex" && !resolveTranscript(state, row, nowMs)) continue;
24418
24535
  if (!state.primed) {
24419
- if (
24420
- // Yield the slot to a still-cold visible row — but never at the cost of the forward-progress
24421
- // guarantee below. `primedRows > 0` keeps the archive advancing by at least one row per tick
24422
- // even if a visible row were somehow to stay cold indefinitely, so deferral can never become
24423
- // starvation. The visible row still primes on this same tick; it just is not necessarily first.
24424
- coldVisibleRow && primedRows > 0 && rowIsArchived(row) || primedRows >= MAX_PRIME_ROWS_PER_TICK || primedRows > 0 && monotonicNow() - tickStartedMs > PRIME_BUDGET_MS
24425
- ) {
24536
+ if (primeDeferred(row)) {
24426
24537
  primeIncomplete = true;
24427
24538
  continue;
24428
24539
  }
@@ -24727,7 +24838,7 @@ ${detail2}
24727
24838
  stopped = false;
24728
24839
  primeProgress = onPrimeProgress;
24729
24840
  try {
24730
- tick();
24841
+ tickWithBudget();
24731
24842
  } finally {
24732
24843
  primeProgress = void 0;
24733
24844
  }
@@ -24752,7 +24863,7 @@ function landsAfterRead(eventAt, lastReadAt) {
24752
24863
  if (!Number.isFinite(e) || !Number.isFinite(r)) return true;
24753
24864
  return e > r;
24754
24865
  }
24755
- var IDLE_BACKSTOP_MS, RUNTIME_CHASE_MAX, POLL_MS2, MAX_PRIME_ROWS_PER_TICK, PRIME_BUDGET_MS, TRANSCRIPT_READ_WINDOW, EMPTY_BUFFER, MAX_POLL_MS, SUBAGENT_STALE_MS, SHELL_PROBE_TTL_MS, SHELL_PROBE_GRACE_MS, FOREIGN_FRESH_MS, FOREIGN_MAX, FOREIGN_SCAN_EVERY, CACHE_FLUSH_MS, PRIME_PROGRESS_EVERY, DISCOVER_RETRY_MS, DISCOVER_RETRY_MAX_MS, RETAINED_SUBAGENTS_MAX, RETAINED_SHELLS_MAX, DESCENDANT_TERMINALS_MAX, PENDING_RESUMES_MAX, PENDING_SHELLS_MAX, RESUME_REPLAY_SLACK_MS, FIRST_USER_TEXT_MAX, QUESTION_BLOCK_RE, SIGNAL_FENCE_RE, FENCE_BODY_MAX, LAUNCH_ACK_RE, AUTO_BACKGROUND_ACK_RE, DESCENDANT_SIDECAR_MAX, DESCENDANT_NOTIFY_GRACE_MS, MAX_OWNED_TOOL_USE_IDS, BROKER_LIVENESS_TTL_MS, UNRESTORED_TAIL_FIELDS;
24866
+ var IDLE_BACKSTOP_MS, RUNTIME_CHASE_MAX, POLL_MS2, MAX_PRIME_ROWS_PER_TICK, PRIME_BUDGET_MS, TRANSCRIPT_READ_WINDOW, EMPTY_BUFFER, MAX_POLL_MS, SUBAGENT_STALE_MS, SHELL_PROBE_TTL_MS, SHELL_PROBE_GRACE_MS, execFileAsync, FOREIGN_FRESH_MS, FOREIGN_MAX, FOREIGN_SCAN_EVERY, CACHE_FLUSH_MS, PRIME_PROGRESS_EVERY, DISCOVER_RETRY_MS, DISCOVER_RETRY_MAX_MS, RETAINED_SUBAGENTS_MAX, RETAINED_SHELLS_MAX, DESCENDANT_TERMINALS_MAX, PENDING_RESUMES_MAX, PENDING_SHELLS_MAX, RESUME_REPLAY_SLACK_MS, FIRST_USER_TEXT_MAX, QUESTION_BLOCK_RE, SIGNAL_FENCE_RE, FENCE_BODY_MAX, LAUNCH_ACK_RE, AUTO_BACKGROUND_ACK_RE, DESCENDANT_SIDECAR_MAX, DESCENDANT_NOTIFY_GRACE_MS, MAX_OWNED_TOOL_USE_IDS, BROKER_LIVENESS_TTL_MS, UNRESTORED_TAIL_FIELDS;
24756
24867
  var init_tailer = __esm({
24757
24868
  "packages/server/src/tailer.ts"() {
24758
24869
  "use strict";
@@ -24785,6 +24896,7 @@ var init_tailer = __esm({
24785
24896
  SUBAGENT_STALE_MS = 15 * 6e4;
24786
24897
  SHELL_PROBE_TTL_MS = 3e4;
24787
24898
  SHELL_PROBE_GRACE_MS = 6e4;
24899
+ execFileAsync = promisify2(execFile2);
24788
24900
  FOREIGN_FRESH_MS = 24 * 60 * 6e4;
24789
24901
  FOREIGN_MAX = 20;
24790
24902
  FOREIGN_SCAN_EVERY = 5;
@@ -30678,11 +30790,11 @@ var init_codex_app_server = __esm({
30678
30790
  init_logging();
30679
30791
  CODEX_APP_SERVER_PROVIDER = "codex-app-server";
30680
30792
  CODEX_NATIVE_LISTEN_FLAG = "FRIZZ_CODEX_NATIVE_LISTEN";
30681
- CODEX_APP_SERVER_SUPPORTED_VERSION = "0.146.0";
30793
+ CODEX_APP_SERVER_SUPPORTED_VERSION = "0.153.2";
30682
30794
  CODEX_APP_SERVER_PROTOCOL_REVISION = Object.freeze({
30683
30795
  packageVersion: CODEX_APP_SERVER_SUPPORTED_VERSION,
30684
- sourceTag: "rust-v0.146.0",
30685
- sourceCommit: "e363b08c9175ac1cbe5893615dd2cb9ddf95043b"
30796
+ sourceTag: "rust-v0.153.2",
30797
+ sourceCommit: "657a993cbee87acf52d14b758ce49dbd46d1b8eb"
30686
30798
  });
30687
30799
  PROTOCOL_FINGERPRINT = [
30688
30800
  CODEX_APP_SERVER_PROTOCOL_REVISION.sourceTag,
@@ -33162,8 +33274,8 @@ import { join as join23 } from "node:path";
33162
33274
  import { homedir as homedir9, platform } from "node:os";
33163
33275
  import { createHash as createHash10 } from "node:crypto";
33164
33276
  import { mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
33165
- import { execFile as execFile2 } from "node:child_process";
33166
- import { promisify as promisify2 } from "node:util";
33277
+ import { execFile as execFile3 } from "node:child_process";
33278
+ import { promisify as promisify3 } from "node:util";
33167
33279
  function claudeConfigDir() {
33168
33280
  const override = process.env.CLAUDE_CONFIG_DIR;
33169
33281
  return override && override.trim() ? override : join23(homedir9(), ".claude");
@@ -33184,7 +33296,7 @@ function tokenFromCredentialsJson(raw2) {
33184
33296
  async function readKeychainToken() {
33185
33297
  if (platform() !== "darwin") return void 0;
33186
33298
  try {
33187
- const { stdout } = await execFileAsync("security", ["find-generic-password", "-s", "Claude Code-credentials", "-w"], {
33299
+ const { stdout } = await execFileAsync2("security", ["find-generic-password", "-s", "Claude Code-credentials", "-w"], {
33188
33300
  encoding: "utf8",
33189
33301
  timeout: 4e3
33190
33302
  });
@@ -33312,7 +33424,7 @@ async function acquireLock(path) {
33312
33424
  }
33313
33425
  }
33314
33426
  async function runClaudeUsage(claudeBin) {
33315
- const { stdout } = await execFileAsync(
33427
+ const { stdout } = await execFileAsync2(
33316
33428
  // Never a bare name: on Windows `execFile("claude")` is ENOENT and `execFile("claude.cmd")` is
33317
33429
  // EINVAL (node refuses .cmd/.bat without a shell since CVE-2024-27980), so this reader could
33318
33430
  // never reach the CLI there and every quota refresh threw. See auth-status.ts for the measurement.
@@ -33519,13 +33631,13 @@ async function readClaudeQuota(claudeBin = "claude", deps = {}, options = {}) {
33519
33631
  });
33520
33632
  }
33521
33633
  }
33522
- var execFileAsync, USAGE_URL, OAUTH_BETA, USER_AGENT, ENDPOINT_TIMEOUT_MS, OK_TTL_MS, FAIL_TTL_MS, STALE_MAX_AGE_MS, CLI_TIMEOUT_MS, LOCK_STALE_MS, LOCK_WAIT_MS, LOCK_POLL_MS2, LINE_WINDOWS, MONTH_INDEX, backgroundRefreshes;
33634
+ var execFileAsync2, USAGE_URL, OAUTH_BETA, USER_AGENT, ENDPOINT_TIMEOUT_MS, OK_TTL_MS, FAIL_TTL_MS, STALE_MAX_AGE_MS, CLI_TIMEOUT_MS, LOCK_STALE_MS, LOCK_WAIT_MS, LOCK_POLL_MS2, LINE_WINDOWS, MONTH_INDEX, backgroundRefreshes;
33523
33635
  var init_claude_quota = __esm({
33524
33636
  "packages/server/src/backend/claude-quota.ts"() {
33525
33637
  "use strict";
33526
33638
  init_frizz_paths();
33527
33639
  init_claude_broker_host();
33528
- execFileAsync = promisify2(execFile2);
33640
+ execFileAsync2 = promisify3(execFile3);
33529
33641
  USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
33530
33642
  OAUTH_BETA = "oauth-2025-04-20";
33531
33643
  USER_AGENT = "claude-code/2.0.0";
@@ -33630,10 +33742,10 @@ var init_quota = __esm({
33630
33742
  });
33631
33743
 
33632
33744
  // packages/server/src/frizz.ts
33633
- import { execFile as execFile3 } from "node:child_process";
33745
+ import { execFile as execFile4 } from "node:child_process";
33634
33746
  import { lstatSync as lstatSync2, realpathSync as realpathSync6 } from "node:fs";
33635
33747
  import { basename as basename5, dirname as dirname9, join as join24, resolve as resolve5 } from "node:path";
33636
- import { promisify as promisify3 } from "node:util";
33748
+ import { promisify as promisify4 } from "node:util";
33637
33749
  function frizzScriptsDir() {
33638
33750
  if (process.env.FRIZZ_SCRIPTS_DIR) return process.env.FRIZZ_SCRIPTS_DIR;
33639
33751
  return resolve5(import.meta.dirname, "..", "..", "..", "board");
@@ -33690,7 +33802,7 @@ var init_frizz = __esm({
33690
33802
  "packages/server/src/frizz.ts"() {
33691
33803
  "use strict";
33692
33804
  init_src();
33693
- execFileP = promisify3(execFile3);
33805
+ execFileP = promisify4(execFile4);
33694
33806
  }
33695
33807
  });
33696
33808
 
@@ -34643,9 +34755,10 @@ When delegation is explicitly authorized:
34643
34755
  - \`gpt-5.6-luna\` + \`medium\` or \`gpt-5.6-terra\` + \`medium\` for fully specified mechanical QA,
34644
34756
  documentation, straightforward tests, and exact collection or edits.
34645
34757
  - \`gpt-5.6-terra\` + \`high\` only after observed cross-layer or concurrency ambiguity.
34646
- - \`gpt-5.6-sol\` + \`high\` or \`xhigh\` only for evidenced high-risk runtime, persistence,
34647
- process-control, provider-protocol, or complex-concurrency work. Before any Sol or xhigh spawn,
34648
- state the observed evidence, the specific risk/ambiguity, and why Terra + medium is inadequate.
34758
+ - \`gpt-6-astra\` + \`high\` or \`xhigh\` (or \`gpt-5.6-sol\` when Astra is absent from the live
34759
+ model catalog) only for evidenced high-risk runtime, persistence, process-control,
34760
+ provider-protocol, or complex-concurrency work. Before any Astra, Sol or xhigh spawn, state the
34761
+ observed evidence, the specific risk/ambiguity, and why Terra + medium is inadequate.
34649
34762
 
34650
34763
  ## Automated waits in Codex
34651
34764
 
@@ -35710,8 +35823,8 @@ var init_claude_agent_broker_bridge = __esm({
35710
35823
  import { join as join27 } from "node:path";
35711
35824
  import { homedir as homedir12, platform as platform2 } from "node:os";
35712
35825
  import { readFileSync as readFileSync17, statSync as statSync11 } from "node:fs";
35713
- import { execFile as execFile4 } from "node:child_process";
35714
- import { promisify as promisify4 } from "node:util";
35826
+ import { execFile as execFile5 } from "node:child_process";
35827
+ import { promisify as promisify5 } from "node:util";
35715
35828
  function claudeConfigDir2() {
35716
35829
  const override = process.env.CLAUDE_CONFIG_DIR;
35717
35830
  return override && override.trim() ? override : join27(homedir12(), ".claude");
@@ -35729,7 +35842,7 @@ async function claudeKeychainState() {
35729
35842
  if (process.env.FRIZZ_KEYCHAIN_DISABLED && process.env.NODE_ENV !== "production") return "absent";
35730
35843
  if (platform2() !== "darwin") return "absent";
35731
35844
  try {
35732
- const { stdout } = await execFileAsync2("security", ["find-generic-password", "-s", "Claude Code-credentials", "-w"], {
35845
+ const { stdout } = await execFileAsync3("security", ["find-generic-password", "-s", "Claude Code-credentials", "-w"], {
35733
35846
  encoding: "utf8",
35734
35847
  timeout: 4e3
35735
35848
  });
@@ -35769,7 +35882,7 @@ function readCodexAuthState(codexHome = defaultCodexHome()) {
35769
35882
  const accessToken = tokens && typeof tokens.access_token === "string" && tokens.access_token ? tokens.access_token : void 0;
35770
35883
  return apiKey || accessToken ? "authed" : "signed-out";
35771
35884
  }
35772
- async function readCodexBinaryState(codexBin = "codex", exec = execFileAsync2) {
35885
+ async function readCodexBinaryState(codexBin = "codex", exec = execFileAsync3) {
35773
35886
  try {
35774
35887
  await exec(codexBin, ["--version"], { timeout: 5e3 });
35775
35888
  return "present";
@@ -35791,7 +35904,7 @@ function parseClaudeAuthStatusJson(stdout) {
35791
35904
  async function readClaudeAuthStatusCli(opts) {
35792
35905
  try {
35793
35906
  const bin = resolveClaudeExecutableAbsolute(opts?.claudeBin);
35794
- const { stdout } = await execFileAsync2(bin, ["auth", "status", "--json"], {
35907
+ const { stdout } = await execFileAsync3(bin, ["auth", "status", "--json"], {
35795
35908
  encoding: "utf8",
35796
35909
  timeout: opts?.timeoutMs ?? 5e3,
35797
35910
  ...opts?.cwd ? { cwd: opts.cwd } : {}
@@ -35889,14 +36002,14 @@ async function readAuthSnapshot(opts) {
35889
36002
  }
35890
36003
  };
35891
36004
  }
35892
- var execFileAsync2, ProviderAuthRequiredError, claudeAccountMemo;
36005
+ var execFileAsync3, ProviderAuthRequiredError, claudeAccountMemo;
35893
36006
  var init_auth_status = __esm({
35894
36007
  "packages/server/src/backend/auth-status.ts"() {
35895
36008
  "use strict";
35896
36009
  init_claude_quota();
35897
36010
  init_codex();
35898
36011
  init_claude_broker_host();
35899
- execFileAsync2 = promisify4(execFile4);
36012
+ execFileAsync3 = promisify5(execFile5);
35900
36013
  ProviderAuthRequiredError = class extends Error {
35901
36014
  backend;
35902
36015
  constructor(backend) {
@@ -36647,10 +36760,11 @@ var init_dispatch = __esm({
36647
36760
 
36648
36761
  // packages/server/src/board.ts
36649
36762
  import {
36763
+ realpathSync as realpathSync8,
36650
36764
  watch as fsWatch
36651
36765
  } from "node:fs";
36652
36766
  import { homedir as homedir13 } from "node:os";
36653
- import { join as join29 } from "node:path";
36767
+ import { dirname as dirname12, join as join29 } from "node:path";
36654
36768
  import watcher from "@parcel/watcher";
36655
36769
  function appServerTurnStalled(liveness, lastActivityAt, nowMs) {
36656
36770
  if (!liveness) return false;
@@ -36698,6 +36812,9 @@ function registeredLegacyFileIsTerminal(projectDir, slug) {
36698
36812
  const status = raw2?.replace(/^(?:"(.*)"|'(.*)')$/, "$1$2").trim();
36699
36813
  return status === "done" || status === "dismissed";
36700
36814
  }
36815
+ function isBoardRelevantFrizzPath(roots, path) {
36816
+ return path.endsWith(".md") && roots.has(dirname12(path));
36817
+ }
36701
36818
  function futureSnooze(row, nowMs) {
36702
36819
  const parsed = SnoozeUntil.safeParse(row.snoozed_until);
36703
36820
  return parsed.success && Date.parse(parsed.data) > nowMs ? parsed.data : void 0;
@@ -36946,7 +37063,8 @@ function resolveSessionProfile(row, tele) {
36946
37063
  const observedAt = tele?.profileAt ? Date.parse(tele.profileAt) : NaN;
36947
37064
  const spawnedAt = Date.parse(row.spawned_at);
36948
37065
  const setAt = row.profile_set_at ? Date.parse(row.profile_set_at) : NaN;
36949
- const supersededByOperatorSet = Number.isFinite(setAt) && setAt > observedAt;
37066
+ const operatorSetSticks = (row.backend ?? "claude") !== "codex";
37067
+ const supersededByOperatorSet = Number.isFinite(setAt) && (operatorSetSticks || setAt > observedAt);
36950
37068
  const observedIsCurrent = Number.isFinite(observedAt) && Number.isFinite(spawnedAt) && observedAt >= spawnedAt && !supersededByOperatorSet;
36951
37069
  const observedModel = tele?.model ? normalizeObservedThreadModel(row.backend ?? "claude", tele.model) ?? tele.model.trim() : void 0;
36952
37070
  const model = (!persistedModel || observedIsCurrent ? observedModel : void 0) || persistedModel;
@@ -37026,20 +37144,29 @@ function registeredDoneFence(done, lastUserAt) {
37026
37144
  if (Number.isFinite(userAt) && userAt > done.doneAt) return void 0;
37027
37145
  return { kind: "done", body: done.body, hints: [], registered: true };
37028
37146
  }
37029
- function sessionThreadView(projectDir, storage, row, rawTele, registeredLegacyTerminal, interactionPresence, nowMs, codexTurnLiveness, claudeBrokerDaemonAlive, github = {}) {
37030
- const armedPrWatches = storage.listPrWatches(row.slug, { armedOnly: true }).map((w) => ({
37147
+ function readThreadRegistries(storage) {
37148
+ return {
37149
+ prWatches: storage.armedPrWatchesBySlug(),
37150
+ timers: storage.armedThreadTimersBySlug(),
37151
+ questions: storage.threadQuestionsBySlug(),
37152
+ watches: storage.armedThreadWatchesBySlug(),
37153
+ done: storage.threadDoneBySlug()
37154
+ };
37155
+ }
37156
+ function sessionThreadView(projectDir, storage, row, rawTele, registeredLegacyTerminal, interactionPresence, nowMs, codexTurnLiveness, claudeBrokerDaemonAlive, registries, github = {}) {
37157
+ const armedPrWatches = (registries.prWatches.get(row.slug) ?? []).map((w) => ({
37031
37158
  target: `${w.owner}/${w.repo}#${w.number}`,
37032
37159
  createdAt: new Date(w.created_at).toISOString()
37033
37160
  }));
37034
37161
  const registeredPrWatches = new Set(armedPrWatches.map((w) => w.target));
37035
- const armedTimers = storage.listThreadTimers(row.slug, { armedOnly: true }).map((t) => ({
37162
+ const armedTimers = (registries.timers.get(row.slug) ?? []).map((t) => ({
37036
37163
  id: t.id,
37037
37164
  prompt: t.prompt,
37038
37165
  fireAt: new Date(t.fire_at).toISOString(),
37039
37166
  createdAt: new Date(t.created_at).toISOString()
37040
37167
  }));
37041
37168
  const armedTimerIds = new Set(armedTimers.map((t) => t.id));
37042
- const questionRows = storage.listThreadQuestions(row.slug);
37169
+ const questionRows = registries.questions.get(row.slug) ?? [];
37043
37170
  const questions = [];
37044
37171
  for (const q of questionRows) {
37045
37172
  if (q.state !== "open") continue;
@@ -37047,7 +37174,7 @@ function sessionThreadView(projectDir, storage, row, rawTele, registeredLegacyTe
37047
37174
  if (spec) questions.push({ id: q.id, spec, askedAt: new Date(q.asked_at).toISOString() });
37048
37175
  }
37049
37176
  const inFlightAnswers = answersInFlight(questionRows, rawTele?.lastUserAt, row.recurring_on_rest === 1 && Boolean(row.recurring_prompt?.trim()));
37050
- const armedWatches = storage.listThreadWatches(row.slug, { armedOnly: true }).map((w) => ({
37177
+ const armedWatches = (registries.watches.get(row.slug) ?? []).map((w) => ({
37051
37178
  id: w.id,
37052
37179
  kind: w.kind,
37053
37180
  target: w.target,
@@ -37055,7 +37182,7 @@ function sessionThreadView(projectDir, storage, row, rawTele, registeredLegacyTe
37055
37182
  expiresAt: new Date(w.expires_at).toISOString()
37056
37183
  }));
37057
37184
  const supersededDone = questions.length > 0 || armedWatches.length > 0 || armedPrWatches.length > 0 || armedTimers.length > 0;
37058
- const done = supersededDone ? void 0 : registeredDoneFence(storage.getThreadDone(row.slug), rawTele?.lastUserAt);
37185
+ const done = supersededDone ? void 0 : registeredDoneFence(registries.done.get(row.slug), rawTele?.lastUserAt);
37059
37186
  const tele = done && rawTele ? { ...rawTele, lastFence: done } : rawTele;
37060
37187
  const headlessStalled = row.codex_runtime === "app-server" ? appServerTurnStalled(codexTurnLiveness(row.slug, row.session_id), tele?.lastActivityAt, nowMs) : isBrokerClaudeRow(row) ? !claudeBrokerDaemonAlive(row.session_id) : false;
37061
37188
  const headlessLostWork = isBrokerClaudeRow(row) && headlessStalled && hasUnretiredOwnAgents(tele);
@@ -37285,6 +37412,7 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
37285
37412
  function buildSessionThreads(nowMs) {
37286
37413
  const rows = storage.allSessions().filter((row) => ThreadSlug.safeParse(row.slug).success);
37287
37414
  const github = readGithubStatusBook(storage.getSetting(GITHUB_STATUS_SETTING));
37415
+ const registries = readThreadRegistries(storage);
37288
37416
  const currentInteractionKeys = /* @__PURE__ */ new Set();
37289
37417
  const out = [];
37290
37418
  for (const row of rows) {
@@ -37321,6 +37449,7 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
37321
37449
  nowMs,
37322
37450
  codexTurnLiveness,
37323
37451
  claudeBrokerDaemonAlive,
37452
+ registries,
37324
37453
  github
37325
37454
  ));
37326
37455
  }
@@ -37450,7 +37579,23 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
37450
37579
  if (parcelSub || stopped) return Promise.resolve();
37451
37580
  if (watchSetup) return watchSetup;
37452
37581
  const setup = (async () => {
37453
- const next = await subscribe(join29(project.dir, ".frizz"), () => scheduleRebuild());
37582
+ const dir = join29(project.dir, ".frizz");
37583
+ const roots = /* @__PURE__ */ new Set([dir]);
37584
+ try {
37585
+ roots.add(realpathSync8(dir));
37586
+ } catch {
37587
+ }
37588
+ const next = await subscribe(
37589
+ dir,
37590
+ (err, events) => {
37591
+ if (err || !events) {
37592
+ scheduleRebuild();
37593
+ return;
37594
+ }
37595
+ if (events.some((event) => isBoardRelevantFrizzPath(roots, event.path))) scheduleRebuild();
37596
+ },
37597
+ { ignore: FRIZZ_WATCH_IGNORED_DIRS.map((name) => join29(dir, name)) }
37598
+ );
37454
37599
  if (stopped) {
37455
37600
  await next.unsubscribe();
37456
37601
  return;
@@ -37525,7 +37670,7 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
37525
37670
  }
37526
37671
  };
37527
37672
  }
37528
- var DEBOUNCE_MS, RECONCILE_MS, STALL_GRACE_MS, LINE_CAP, DECLARED_PARK_MAX_MS;
37673
+ var DEBOUNCE_MS, RECONCILE_MS, STALL_GRACE_MS, LINE_CAP, FRIZZ_WATCH_IGNORED_DIRS, DECLARED_PARK_MAX_MS;
37529
37674
  var init_board = __esm({
37530
37675
  "packages/server/src/board.ts"() {
37531
37676
  "use strict";
@@ -37545,6 +37690,7 @@ var init_board = __esm({
37545
37690
  RECONCILE_MS = 15e3;
37546
37691
  STALL_GRACE_MS = 3e4;
37547
37692
  LINE_CAP = 240;
37693
+ FRIZZ_WATCH_IGNORED_DIRS = ["threads", ".session-state"];
37548
37694
  DECLARED_PARK_MAX_MS = 24 * 60 * 60 * 1e3;
37549
37695
  }
37550
37696
  });
@@ -37765,8 +37911,8 @@ var init_wake_store = __esm({
37765
37911
  });
37766
37912
 
37767
37913
  // packages/server/src/github-review.ts
37768
- import { execFile as execFile5 } from "node:child_process";
37769
- import { promisify as promisify5 } from "node:util";
37914
+ import { execFile as execFile6 } from "node:child_process";
37915
+ import { promisify as promisify6 } from "node:util";
37770
37916
  function refKey(ref) {
37771
37917
  return `${ref.owner}/${ref.repo}#${ref.number}`;
37772
37918
  }
@@ -37776,7 +37922,7 @@ function conciseError(error) {
37776
37922
  }
37777
37923
  async function defaultGetToken() {
37778
37924
  try {
37779
- const { stdout } = await execFileAsync3(
37925
+ const { stdout } = await execFileAsync4(
37780
37926
  "gh",
37781
37927
  ["auth", "token", "--hostname", "github.com"],
37782
37928
  {
@@ -38082,11 +38228,11 @@ function createGithubReviewFetcher(deps = {}) {
38082
38228
  }
38083
38229
  });
38084
38230
  }
38085
- var execFileAsync3, GH_TIMEOUT_MS, GH_MAX_BUFFER, REQUEST_TIMEOUT_MS, MAX_REFS_PER_REQUEST, RATE_LIMIT_RESERVE;
38231
+ var execFileAsync4, GH_TIMEOUT_MS, GH_MAX_BUFFER, REQUEST_TIMEOUT_MS, MAX_REFS_PER_REQUEST, RATE_LIMIT_RESERVE;
38086
38232
  var init_github_review = __esm({
38087
38233
  "packages/server/src/github-review.ts"() {
38088
38234
  "use strict";
38089
- execFileAsync3 = promisify5(execFile5);
38235
+ execFileAsync4 = promisify6(execFile6);
38090
38236
  GH_TIMEOUT_MS = 3e4;
38091
38237
  GH_MAX_BUFFER = 1024 * 1024;
38092
38238
  REQUEST_TIMEOUT_MS = 3e4;
@@ -38213,8 +38359,8 @@ var init_pr_watch_noise = __esm({
38213
38359
  });
38214
38360
 
38215
38361
  // packages/server/src/scheduler.ts
38216
- import { execFile as execFile6 } from "node:child_process";
38217
- import { promisify as promisify6 } from "node:util";
38362
+ import { execFile as execFile7 } from "node:child_process";
38363
+ import { promisify as promisify7 } from "node:util";
38218
38364
  import { createHash as createHash12, randomUUID as randomUUID14 } from "node:crypto";
38219
38365
  function failureSignature(rollup) {
38220
38366
  const ids = [];
@@ -38458,7 +38604,7 @@ function conciseGhError(err) {
38458
38604
  }
38459
38605
  async function probePrReadable(ref) {
38460
38606
  try {
38461
- await execFileAsync4(
38607
+ await execFileAsync5(
38462
38608
  "gh",
38463
38609
  ["pr", "view", String(ref.number), "--repo", `${ref.owner}/${ref.repo}`, "--json", "state"],
38464
38610
  { timeout: 15e3, maxBuffer: 1e6, env: { ...process.env, GH_PAGER: "cat", GH_PROMPT_DISABLED: "1" } }
@@ -38470,7 +38616,7 @@ async function probePrReadable(ref) {
38470
38616
  }
38471
38617
  async function defaultFetchPr(ref) {
38472
38618
  try {
38473
- const { stdout } = await execFileAsync4(
38619
+ const { stdout } = await execFileAsync5(
38474
38620
  "gh",
38475
38621
  ghPrViewArgs(ref),
38476
38622
  { timeout: 15e3, maxBuffer: 8e6, env: { ...process.env, GH_PAGER: "cat", GH_PROMPT_DISABLED: "1" } }
@@ -38478,7 +38624,7 @@ async function defaultFetchPr(ref) {
38478
38624
  const j = JSON.parse(stdout);
38479
38625
  if (typeof j.state !== "string" || !j.state) return void 0;
38480
38626
  if (typeof j.headRefOid !== "string" || !j.headRefOid) return void 0;
38481
- const runs = await execFileAsync4(
38627
+ const runs = await execFileAsync5(
38482
38628
  "gh",
38483
38629
  ["run", "list", "--repo", `${ref.owner}/${ref.repo}`, "--commit", j.headRefOid, "--limit", "100", "--json", "name,workflowName,status,conclusion,databaseId,event,createdAt"],
38484
38630
  { timeout: 15e3, maxBuffer: 8e6, env: { ...process.env, GH_PAGER: "cat", GH_PROMPT_DISABLED: "1" } }
@@ -39794,7 +39940,7 @@ ${wakeTimeHeader(now(), spokeAt)}`;
39794
39940
  }
39795
39941
  };
39796
39942
  }
39797
- var execFileAsync4, LIMIT_FENCE_PREFIX, LIMIT_HINT_PREFIX, LIMIT_RESUME_GRACE_MS, LIMIT_RESUME_HEADROOM_PERCENT, LIMIT_HEADROOM_MIN_FAULT_AGE_MS, REPORT_FENCE_PREFIX, REPORT_HINT_PREFIX, SNOOZE_FENCE_PREFIX, SNOOZE_HINT_PREFIX, HEARTBEAT_FENCE_PREFIX, HEARTBEAT_HINT_PREFIX, STOP_HOOK_FENCE_PREFIX, STOP_HOOK_HINT_KEY, COMPACT_FENCE_PREFIX, COMPACT_HINT_KEY, TIMER_FENCE_PREFIX, TIMER_HINT_PREFIX, SHELL_FENCE_PREFIX, PR_WATCH_FENCE_PREFIX, PR_WATCH_EXPIRED_FENCE_PREFIX, OWN_WATCH_EXPIRED_FENCE_PREFIX, QUESTION_ANSWER_FENCE_PREFIX, PR_WATCH_POLL_MS, SIGNOFF_FENCE_PREFIX, SIGNOFF_HINT_KEY, SIGNOFF_NUDGE_MAX, PARK_BUMP_MAX, SIGNOFF_NUDGE_SETTING, PARK_FENCE_PREFIX, GITHUB_STATUS_CAP, REVIEW_SEEN_CAP, REVIEW_STEER_CAP, AWAITING_KEY_OF, MID_TURN_HOLD_MAX_MS, WAKE_HOLD_DEFERRAL;
39943
+ var execFileAsync5, LIMIT_FENCE_PREFIX, LIMIT_HINT_PREFIX, LIMIT_RESUME_GRACE_MS, LIMIT_RESUME_HEADROOM_PERCENT, LIMIT_HEADROOM_MIN_FAULT_AGE_MS, REPORT_FENCE_PREFIX, REPORT_HINT_PREFIX, SNOOZE_FENCE_PREFIX, SNOOZE_HINT_PREFIX, HEARTBEAT_FENCE_PREFIX, HEARTBEAT_HINT_PREFIX, STOP_HOOK_FENCE_PREFIX, STOP_HOOK_HINT_KEY, COMPACT_FENCE_PREFIX, COMPACT_HINT_KEY, TIMER_FENCE_PREFIX, TIMER_HINT_PREFIX, SHELL_FENCE_PREFIX, PR_WATCH_FENCE_PREFIX, PR_WATCH_EXPIRED_FENCE_PREFIX, OWN_WATCH_EXPIRED_FENCE_PREFIX, QUESTION_ANSWER_FENCE_PREFIX, PR_WATCH_POLL_MS, SIGNOFF_FENCE_PREFIX, SIGNOFF_HINT_KEY, SIGNOFF_NUDGE_MAX, PARK_BUMP_MAX, SIGNOFF_NUDGE_SETTING, PARK_FENCE_PREFIX, GITHUB_STATUS_CAP, REVIEW_SEEN_CAP, REVIEW_STEER_CAP, AWAITING_KEY_OF, MID_TURN_HOLD_MAX_MS, WAKE_HOLD_DEFERRAL;
39798
39944
  var init_scheduler = __esm({
39799
39945
  "packages/server/src/scheduler.ts"() {
39800
39946
  "use strict";
@@ -39810,7 +39956,7 @@ var init_scheduler = __esm({
39810
39956
  init_pr_watch_noise();
39811
39957
  init_github_review();
39812
39958
  init_logging();
39813
- execFileAsync4 = promisify6(execFile6);
39959
+ execFileAsync5 = promisify7(execFile7);
39814
39960
  LIMIT_FENCE_PREFIX = "limit";
39815
39961
  LIMIT_HINT_PREFIX = "limit:";
39816
39962
  LIMIT_RESUME_GRACE_MS = 6e4;
@@ -40226,7 +40372,7 @@ var init_codex_app_server_diagnostics = __esm({
40226
40372
  });
40227
40373
 
40228
40374
  // packages/server/src/backend/stale-socket-sweep.ts
40229
- import { execFile as execFile7 } from "node:child_process";
40375
+ import { execFile as execFile8 } from "node:child_process";
40230
40376
  import { readdirSync as readdirSync8, unlinkSync as unlinkSync4 } from "node:fs";
40231
40377
  import { connect as connectSocket } from "node:net";
40232
40378
  import { join as join32 } from "node:path";
@@ -40273,7 +40419,7 @@ var init_stale_socket_sweep = __esm({
40273
40419
  "packages/server/src/backend/stale-socket-sweep.ts"() {
40274
40420
  "use strict";
40275
40421
  defaultListReferenced = (prefix, done) => {
40276
- execFile7("lsof", ["-U", "-F", "n"], { timeout: 3e4, maxBuffer: 16 * 1024 * 1024 }, (error, stdout) => {
40422
+ execFile8("lsof", ["-U", "-F", "n"], { timeout: 3e4, maxBuffer: 16 * 1024 * 1024 }, (error, stdout) => {
40277
40423
  if (!stdout) return done(null);
40278
40424
  if (error && !stdout.includes(prefix)) return done(null);
40279
40425
  done(parseLsofSocketNames(stdout));
@@ -40295,9 +40441,9 @@ var init_stale_socket_sweep = __esm({
40295
40441
  });
40296
40442
 
40297
40443
  // packages/server/src/orphan-reaper.ts
40298
- import { execFileSync as execFileSync5 } from "node:child_process";
40444
+ import { execFileSync as execFileSync4 } from "node:child_process";
40299
40445
  import { readFileSync as readFileSync19 } from "node:fs";
40300
- import { dirname as dirname12 } from "node:path";
40446
+ import { dirname as dirname13 } from "node:path";
40301
40447
  function firstTokenBasename(command) {
40302
40448
  const first = command.trimStart().split(/\s+/, 1)[0] ?? "";
40303
40449
  const slash = first.lastIndexOf("/");
@@ -40524,7 +40670,7 @@ function sweepOrphansOnce(deps = {}) {
40524
40670
  }
40525
40671
  function sweepStaleBrokerSockets() {
40526
40672
  try {
40527
- sweepStaleSockets({ dir: dirname12(claudeBrokerSocketPath("", "")), prefix: CLAUDE_BROKER_SOCKET_PREFIX });
40673
+ sweepStaleSockets({ dir: dirname13(claudeBrokerSocketPath("", "")), prefix: CLAUDE_BROKER_SOCKET_PREFIX });
40528
40674
  } catch {
40529
40675
  }
40530
40676
  }
@@ -40560,7 +40706,7 @@ var init_orphan_reaper = __esm({
40560
40706
  ORPHAN_REAP_INTERVAL_MS = 6e4;
40561
40707
  ORPHAN_MIN_AGE_MS = 12e4;
40562
40708
  SLUG_RE = /FRIZZ_THREAD=([A-Za-z0-9._-]+)/;
40563
- defaultExec = (file, args) => execFileSync5(file, args, { encoding: "utf8", maxBuffer: 16 * 1024 * 1024, timeout: 1e4 });
40709
+ defaultExec = (file, args) => execFileSync4(file, args, { encoding: "utf8", maxBuffer: 16 * 1024 * 1024, timeout: 1e4 });
40564
40710
  defaultReadEnv = (pid) => {
40565
40711
  try {
40566
40712
  return readFileSync19(`/proc/${pid}/environ`, "utf8");
@@ -43914,7 +44060,7 @@ var init_server = __esm({
43914
44060
 
43915
44061
  // packages/server/src/repair.ts
43916
44062
  import { existsSync as existsSync11, readFileSync as readFileSync20, writeFileSync as writeFileSync11 } from "node:fs";
43917
- import { basename as basename7, dirname as dirname13, resolve as resolve7 } from "node:path";
44063
+ import { basename as basename7, dirname as dirname14, resolve as resolve7 } from "node:path";
43918
44064
  function quoteValue(v) {
43919
44065
  if (/^[\w./#:+-]+$/.test(v)) return v;
43920
44066
  return `"${v.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
@@ -43926,7 +44072,7 @@ function deriveTitle(body, slug) {
43926
44072
  function repairThreadFile(frizzDir, file) {
43927
44073
  const root = resolve7(frizzDir);
43928
44074
  const abs = resolve7(root, file);
43929
- if (dirname13(abs) !== root) throw new RepairError(`refusing to repair "${file}": not directly under .frizz/`);
44075
+ if (dirname14(abs) !== root) throw new RepairError(`refusing to repair "${file}": not directly under .frizz/`);
43930
44076
  if (!abs.endsWith(".md")) throw new RepairError(`refusing to repair "${file}": not a .md thread file`);
43931
44077
  if (!existsSync11(abs)) throw new RepairError(`no thread file to repair: ${basename7(abs)}`);
43932
44078
  const content = readFileSync20(abs, "utf8");
@@ -46661,13 +46807,13 @@ var init_open_external = __esm({
46661
46807
 
46662
46808
  // packages/server/src/local-file.ts
46663
46809
  import { spawn as spawn6 } from "node:child_process";
46664
- import { readFileSync as readFileSync23, realpathSync as realpathSync8, statSync as statSync15 } from "node:fs";
46810
+ import { readFileSync as readFileSync23, realpathSync as realpathSync9, statSync as statSync15 } from "node:fs";
46665
46811
  import { homedir as homedir16 } from "node:os";
46666
46812
  import { isAbsolute as isAbsolute4, join as join35, resolve as resolve8, sep as sep2 } from "node:path";
46667
46813
  function isUnder(real, root) {
46668
46814
  let rootReal;
46669
46815
  try {
46670
- rootReal = realpathSync8(root);
46816
+ rootReal = realpathSync9(root);
46671
46817
  } catch {
46672
46818
  return false;
46673
46819
  }
@@ -46677,7 +46823,7 @@ function resolveLocalFile(rawPath, roots) {
46677
46823
  if (!isAbsolute4(rawPath)) throw new Error("Local path must be absolute");
46678
46824
  let real;
46679
46825
  try {
46680
- real = realpathSync8(rawPath);
46826
+ real = realpathSync9(rawPath);
46681
46827
  } catch {
46682
46828
  throw new Error("Local file was not found");
46683
46829
  }
@@ -46719,12 +46865,12 @@ function readLocalMarkdown(rawPath, roots) {
46719
46865
  const lastBreak = head.lastIndexOf(10);
46720
46866
  return { path, markdown: head.subarray(0, lastBreak > 0 ? lastBreak : head.length).toString("utf8"), truncated: true };
46721
46867
  }
46722
- function resolveWatchableLocalFile(rawPath, projectDir, openRoots) {
46723
- if (MARKDOWN_FILE_EXT.test(rawPath.trim())) {
46724
- const path = resolveLocalFile(rawPath, openRoots);
46725
- if (MARKDOWN_FILE_EXT.test(path)) return path;
46868
+ function resolveWatchableLocalFile(rawPath, roots) {
46869
+ const path = resolveLocalFile(rawPath, roots);
46870
+ if (MARKDOWN_FILE_EXT.test(rawPath.trim()) && !MARKDOWN_FILE_EXT.test(path)) {
46871
+ throw new Error("Local file is not a Markdown file");
46726
46872
  }
46727
- return resolveLocalFile(rawPath, [projectDir]);
46873
+ return path;
46728
46874
  }
46729
46875
  function defaultSpawn(command, args, options) {
46730
46876
  return spawn6(command, [...args], options);
@@ -47027,8 +47173,8 @@ var init_github_hovercard = __esm({
47027
47173
  });
47028
47174
 
47029
47175
  // packages/server/src/backend/account-actions.ts
47030
- import { execFile as execFile8 } from "node:child_process";
47031
- import { promisify as promisify7 } from "node:util";
47176
+ import { execFile as execFile9 } from "node:child_process";
47177
+ import { promisify as promisify8 } from "node:util";
47032
47178
  function liveThreadsForBackend(threads, backend) {
47033
47179
  let count = 0;
47034
47180
  for (const thread of threads) {
@@ -47047,7 +47193,7 @@ async function runProviderLogout(opts) {
47047
47193
  const args = opts.backend === "codex" ? ["logout"] : ["auth", "logout"];
47048
47194
  let failure;
47049
47195
  try {
47050
- await execFileAsync5(bin, args, { encoding: "utf8", timeout: opts.timeoutMs ?? 15e3 });
47196
+ await execFileAsync6(bin, args, { encoding: "utf8", timeout: opts.timeoutMs ?? 15e3 });
47051
47197
  } catch (err) {
47052
47198
  const e = err;
47053
47199
  const stderr = typeof e.stderr === "string" ? e.stderr.trim() : "";
@@ -47057,12 +47203,12 @@ async function runProviderLogout(opts) {
47057
47203
  if (failure && auth !== "signed-out") return { status: "failed", detail: failure, auth };
47058
47204
  return { status: "done", auth };
47059
47205
  }
47060
- var execFileAsync5, LIVE_RUNTIMES;
47206
+ var execFileAsync6, LIVE_RUNTIMES;
47061
47207
  var init_account_actions = __esm({
47062
47208
  "packages/server/src/backend/account-actions.ts"() {
47063
47209
  "use strict";
47064
47210
  init_auth_status();
47065
- execFileAsync5 = promisify7(execFile8);
47211
+ execFileAsync6 = promisify8(execFile9);
47066
47212
  LIVE_RUNTIMES = /* @__PURE__ */ new Set(["spawning", "running", "perm-prompt"]);
47067
47213
  }
47068
47214
  });
@@ -47330,8 +47476,8 @@ var init_image_header = __esm({
47330
47476
  });
47331
47477
 
47332
47478
  // packages/server/src/directory-picker.ts
47333
- import { execFile as execFile9 } from "node:child_process";
47334
- import { promisify as promisify8 } from "node:util";
47479
+ import { execFile as execFile10 } from "node:child_process";
47480
+ import { promisify as promisify9 } from "node:util";
47335
47481
  async function pickImageFile(startIn, prompt = "Choose an image for this project", platform3 = process.platform) {
47336
47482
  if (platform3 === "darwin") {
47337
47483
  const location = startIn ? ` default location POSIX file ${JSON.stringify(startIn)}` : "";
@@ -47412,7 +47558,7 @@ var run2, PICKER_TIMEOUT_MS, OSASCRIPT;
47412
47558
  var init_directory_picker = __esm({
47413
47559
  "packages/server/src/directory-picker.ts"() {
47414
47560
  "use strict";
47415
- run2 = promisify8(execFile9);
47561
+ run2 = promisify9(execFile10);
47416
47562
  PICKER_TIMEOUT_MS = 5 * 6e4;
47417
47563
  OSASCRIPT = (prompt) => `POSIX path of (choose folder with prompt ${JSON.stringify(prompt)})`;
47418
47564
  }
@@ -47422,7 +47568,7 @@ var init_directory_picker = __esm({
47422
47568
  import { readFileSync as readFileSync24, statSync as statSync17 } from "node:fs";
47423
47569
  import { join as join36, resolve as resolve9 } from "node:path";
47424
47570
  import { randomUUID as randomUUID16 } from "node:crypto";
47425
- import { basename as basename9, dirname as dirname14 } from "node:path";
47571
+ import { basename as basename9, dirname as dirname15 } from "node:path";
47426
47572
  import { existsSync as existsSync13, mkdirSync as mkdirSync16, rmSync as rmSync10, writeFileSync as writeFileSync13 } from "node:fs";
47427
47573
  import { homedir as homedir17 } from "node:os";
47428
47574
  function validateGithubDispatchProfile(input) {
@@ -47616,7 +47762,7 @@ function storeProjectIcon(id, name, bytes) {
47616
47762
  if (!entry) throw new Error("No such project.");
47617
47763
  if (bytes.length === 0) throw new Error("That file is empty.");
47618
47764
  const path = customIconPath(id, `.${extension2}`);
47619
- mkdirSync16(dirname14(path), { recursive: true });
47765
+ mkdirSync16(dirname15(path), { recursive: true });
47620
47766
  writeFileSync13(path, bytes);
47621
47767
  if (!imageDimensions(path)) {
47622
47768
  rmSync10(path, { force: true });
@@ -49208,12 +49354,13 @@ Say which way you went and why in your write-up, so the human can course-correct
49208
49354
  output: external_exports.object({ path: external_exports.string(), markdown: external_exports.string(), truncated: external_exports.boolean() }),
49209
49355
  handler: async ({ input }) => readLocalMarkdown(input.path, openRoots)
49210
49356
  }),
49211
- // A project file's SOURCE, for the fullscreen page's file viewer. Rooted at the project directory
49212
- // ONLY — see readLocalTextFile for why this gate is narrower than openRoots.
49357
+ // A file's SOURCE, for the fullscreen page's file viewer. The SAME openable roots as the Markdown
49358
+ // reader — see readLocalTextFile for why the project-directory-only gate this replaced refused 41%
49359
+ // of the rail's own rows (a worker's checkout is very often a worktree outside the project dir).
49213
49360
  localFile: query({
49214
49361
  input: external_exports.object({ path: external_exports.string().max(4096) }).strict(),
49215
49362
  output: external_exports.object({ path: external_exports.string(), text: external_exports.string(), truncated: external_exports.boolean() }),
49216
- handler: async ({ input }) => readLocalTextFile(input.path, [ctx.project.dir])
49363
+ handler: async ({ input }) => readLocalTextFile(input.path, openRoots)
49217
49364
  }),
49218
49365
  // Batch-classify path REFERENCES (as they appear in inline code) → their canonical openable path, or
49219
49366
  // null when a candidate doesn't resolve to a real file under the openable roots. The client renders
@@ -49994,7 +50141,7 @@ var init_compression = __esm({
49994
50141
  });
49995
50142
 
49996
50143
  // packages/server/src/local-image.ts
49997
- import { readFileSync as readFileSync25, realpathSync as realpathSync9, statSync as statSync18 } from "node:fs";
50144
+ import { readFileSync as readFileSync25, realpathSync as realpathSync10, statSync as statSync18 } from "node:fs";
49998
50145
  import { extname as extname2, isAbsolute as isAbsolute5 } from "node:path";
49999
50146
  function resolveLocalImage(rawPath) {
50000
50147
  if (!rawPath || !isAbsolute5(rawPath)) return { status: 400 };
@@ -50002,7 +50149,7 @@ function resolveLocalImage(rawPath) {
50002
50149
  if (!contentType) return { status: 400 };
50003
50150
  let real;
50004
50151
  try {
50005
- real = realpathSync9(rawPath);
50152
+ real = realpathSync10(rawPath);
50006
50153
  } catch {
50007
50154
  return { status: 404 };
50008
50155
  }
@@ -50028,9 +50175,9 @@ var init_local_image = __esm({
50028
50175
  });
50029
50176
 
50030
50177
  // packages/server/src/project-icon.ts
50031
- import { readFileSync as readFileSync26, readdirSync as readdirSync10, realpathSync as realpathSync10, statSync as statSync19 } from "node:fs";
50178
+ import { readFileSync as readFileSync26, readdirSync as readdirSync10, realpathSync as realpathSync11, statSync as statSync19 } from "node:fs";
50032
50179
  import { homedir as homedir18 } from "node:os";
50033
- import { basename as basename10, dirname as dirname15, extname as extname3, join as join37, relative as relative2, sep as sep3 } from "node:path";
50180
+ import { basename as basename10, dirname as dirname16, extname as extname3, join as join37, relative as relative2, sep as sep3 } from "node:path";
50034
50181
  function normalizeStem(stem) {
50035
50182
  const sized = stem.toLowerCase().replace(/[@-]\d+(\.\d+)?x(\d+)?$/u, "").replace(/[-_]\d{2,4}$/u, "");
50036
50183
  const normalized = sized.replace(VARIANT_SUFFIX, "");
@@ -50095,7 +50242,7 @@ function manifestIcons(manifestPath) {
50095
50242
  return [];
50096
50243
  }
50097
50244
  if (!Array.isArray(parsed?.icons)) return [];
50098
- const directory = dirname15(manifestPath);
50245
+ const directory = dirname16(manifestPath);
50099
50246
  return parsed.icons.map((icon) => typeof icon?.src === "string" ? icon.src : void 0).filter((src) => !!src && !/^(https?:)?\/\//u.test(src) && !src.startsWith("data:")).map((src) => join37(directory, src.replace(/[?#].*$/u, "").replace(/^\//u, "")));
50100
50247
  }
50101
50248
  function projectIconCandidates(root) {
@@ -50118,7 +50265,7 @@ function projectIconCandidates(root) {
50118
50265
  for (const icon of manifestIcons(join37(directory, name))) {
50119
50266
  if (MEASURABLE_IMAGE_EXTENSIONS.has(extname3(icon).toLowerCase())) {
50120
50267
  fromManifest.add(icon);
50121
- files.push({ path: icon, directory: dirname15(icon) });
50268
+ files.push({ path: icon, directory: dirname16(icon) });
50122
50269
  }
50123
50270
  }
50124
50271
  continue;
@@ -50177,14 +50324,14 @@ function resolveProjectIconResponse(id, options = {}) {
50177
50324
  if (!contentType) return { status: 404 };
50178
50325
  let real;
50179
50326
  try {
50180
- real = realpathSync10(path);
50327
+ real = realpathSync11(path);
50181
50328
  if (!statSync19(real).isFile()) return { status: 404 };
50182
50329
  } catch {
50183
50330
  return { status: 404 };
50184
50331
  }
50185
50332
  const roots = [entry.path, projectStateDir(id, home)].map((root) => {
50186
50333
  try {
50187
- return realpathSync10(root);
50334
+ return realpathSync11(root);
50188
50335
  } catch {
50189
50336
  return root;
50190
50337
  }
@@ -50303,7 +50450,7 @@ var init_project_icon = __esm({
50303
50450
  });
50304
50451
 
50305
50452
  // packages/server/src/local-visualization.ts
50306
- import { readdirSync as readdirSync11, readFileSync as readFileSync27, realpathSync as realpathSync11, statSync as statSync20 } from "node:fs";
50453
+ import { readdirSync as readdirSync11, readFileSync as readFileSync27, realpathSync as realpathSync12, statSync as statSync20 } from "node:fs";
50307
50454
  import { join as join38, sep as sep4 } from "node:path";
50308
50455
  function children(path, pattern) {
50309
50456
  try {
@@ -50320,8 +50467,8 @@ function resolveFragment(projectDir, sessionId, file) {
50320
50467
  let projectReal;
50321
50468
  let baseReal;
50322
50469
  try {
50323
- projectReal = realpathSync11(projectDir);
50324
- baseReal = realpathSync11(base);
50470
+ projectReal = realpathSync12(projectDir);
50471
+ baseReal = realpathSync12(base);
50325
50472
  } catch {
50326
50473
  return null;
50327
50474
  }
@@ -50334,7 +50481,7 @@ function resolveFragment(projectDir, sessionId, file) {
50334
50481
  const sessionRoot = join38(baseReal, year, month, day, sessionId);
50335
50482
  const candidate = join38(monthDir, day, sessionId, file);
50336
50483
  try {
50337
- const real = realpathSync11(candidate);
50484
+ const real = realpathSync12(candidate);
50338
50485
  if (isUnder2(real, sessionRoot) && statSync20(real).isFile()) return real;
50339
50486
  } catch {
50340
50487
  }
@@ -51041,7 +51188,11 @@ function makeTranscriptReader(project, storage, backendFor, lifecycleFor, peerNa
51041
51188
  };
51042
51189
  }
51043
51190
  function createAppSocketServer(deps) {
51044
- const wss = new import_websocket_server.default({ noServer: true, maxPayload: APP_SOCKET_MAX_MESSAGE_BYTES });
51191
+ const wss = new import_websocket_server.default({
51192
+ noServer: true,
51193
+ maxPayload: APP_SOCKET_MAX_MESSAGE_BYTES,
51194
+ perMessageDeflate: APP_SOCKET_DEFLATE
51195
+ });
51045
51196
  const registry = new SubscriptionRegistry();
51046
51197
  const boundedCount = (value, fallback) => {
51047
51198
  const candidate = value ?? fallback;
@@ -51771,7 +51922,7 @@ function createAppSocketServer(deps) {
51771
51922
  }
51772
51923
  };
51773
51924
  }
51774
- var WS_PATH, SubscriptionRegistry, HEARTBEAT_MS, APP_SOCKET_MAX_MESSAGE_BYTES, APP_SOCKET_MAX_LOGICAL_FRAME_BYTES, APP_SOCKET_MAX_OUTPUT_BUFFER_BYTES, APP_SOCKET_MAX_CONNECTIONS, APP_SOCKET_MAX_SUBSCRIPTIONS, APP_SOCKET_MAX_FILE_WATCHES, APP_SOCKET_MAX_MESSAGES_PER_WINDOW, APP_SOCKET_MESSAGE_WINDOW_MS, APP_SOCKET_MAX_BUFFERED_KEYFRAME_EVENTS, APP_SOCKET_MAX_TRANSCRIPT_READS_PER_ORIGIN, APP_SOCKET_MAX_TRANSCRIPT_READS_OVERALL, APP_SOCKET_TRANSCRIPT_READ_WINDOW_MS, APP_SOCKET_MAX_TRANSCRIPT_CACHE_ENTRIES, APP_SOCKET_MAX_TRANSCRIPT_CACHE_BYTES;
51925
+ var WS_PATH, SubscriptionRegistry, HEARTBEAT_MS, APP_SOCKET_MAX_MESSAGE_BYTES, APP_SOCKET_MAX_LOGICAL_FRAME_BYTES, APP_SOCKET_MAX_OUTPUT_BUFFER_BYTES, APP_SOCKET_MAX_CONNECTIONS, APP_SOCKET_MAX_SUBSCRIPTIONS, APP_SOCKET_MAX_FILE_WATCHES, APP_SOCKET_MAX_MESSAGES_PER_WINDOW, APP_SOCKET_MESSAGE_WINDOW_MS, APP_SOCKET_MAX_BUFFERED_KEYFRAME_EVENTS, APP_SOCKET_MAX_TRANSCRIPT_READS_PER_ORIGIN, APP_SOCKET_MAX_TRANSCRIPT_READS_OVERALL, APP_SOCKET_TRANSCRIPT_READ_WINDOW_MS, APP_SOCKET_MAX_TRANSCRIPT_CACHE_ENTRIES, APP_SOCKET_MAX_TRANSCRIPT_CACHE_BYTES, APP_SOCKET_DEFLATE;
51775
51926
  var init_app_socket = __esm({
51776
51927
  "packages/server/src/app-socket.ts"() {
51777
51928
  "use strict";
@@ -51863,12 +52014,21 @@ var init_app_socket = __esm({
51863
52014
  APP_SOCKET_TRANSCRIPT_READ_WINDOW_MS = 1e3;
51864
52015
  APP_SOCKET_MAX_TRANSCRIPT_CACHE_ENTRIES = 128;
51865
52016
  APP_SOCKET_MAX_TRANSCRIPT_CACHE_BYTES = 32 * 1024 * 1024;
52017
+ APP_SOCKET_DEFLATE = {
52018
+ threshold: 8 * 1024,
52019
+ concurrencyLimit: 10,
52020
+ zlibDeflateOptions: { level: 6, memLevel: 8 },
52021
+ // A sliding window is negotiated per connection and costs memory on both ends for the whole
52022
+ // connection's life; these frames are independently compressible, so decline the context takeover.
52023
+ serverNoContextTakeover: true,
52024
+ clientNoContextTakeover: true
52025
+ };
51866
52026
  }
51867
52027
  });
51868
52028
 
51869
52029
  // packages/server/src/local-file-watch.ts
51870
52030
  import { watch } from "node:fs";
51871
- import { basename as basename11, dirname as dirname16 } from "node:path";
52031
+ import { basename as basename11, dirname as dirname17 } from "node:path";
51872
52032
  function close(path) {
51873
52033
  const entry = entries.get(path);
51874
52034
  if (!entry) return;
@@ -51883,7 +52043,7 @@ function watchLocalFile(path, onChange) {
51883
52043
  let entry = entries.get(path);
51884
52044
  if (!entry) {
51885
52045
  const name = basename11(path);
51886
- const watcher2 = watch(dirname16(path), { persistent: false }, (_event, changed) => {
52046
+ const watcher2 = watch(dirname17(path), { persistent: false }, (_event, changed) => {
51887
52047
  if (changed !== null && changed !== void 0 && changed.toString() !== name) return;
51888
52048
  const current = entries.get(path);
51889
52049
  if (!current) return;
@@ -51917,7 +52077,7 @@ var init_local_file_watch = __esm({
51917
52077
 
51918
52078
  // packages/server/src/boot-progress.ts
51919
52079
  import { mkdirSync as mkdirSync18, readFileSync as readFileSync28, renameSync as renameSync10, rmSync as rmSync11, writeFileSync as writeFileSync15 } from "node:fs";
51920
- import { basename as basename12, dirname as dirname17, join as join40 } from "node:path";
52080
+ import { basename as basename12, dirname as dirname18, join as join40 } from "node:path";
51921
52081
  function bootProgressPath(stateDir) {
51922
52082
  return join40(stateDir, BOOT_PROGRESS_NAME);
51923
52083
  }
@@ -51939,8 +52099,8 @@ function createBootProgressPublisher(stateDir, minIntervalMs = 200) {
51939
52099
  lastAt = now;
51940
52100
  step++;
51941
52101
  try {
51942
- mkdirSync18(dirname17(path), { recursive: true, mode: 448 });
51943
- const temp = join40(dirname17(path), `.${basename12(path)}.${process.pid}.tmp`);
52102
+ mkdirSync18(dirname18(path), { recursive: true, mode: 448 });
52103
+ const temp = join40(dirname18(path), `.${basename12(path)}.${process.pid}.tmp`);
51944
52104
  writeFileSync15(temp, `${JSON.stringify({ pid: process.pid, step, phase, at: new Date(now).toISOString() })}
51945
52105
  `, "utf8");
51946
52106
  renameSync10(temp, path);
@@ -52493,12 +52653,12 @@ var init_legacy_project_db = __esm({
52493
52653
 
52494
52654
  // packages/server/src/frizz-db.ts
52495
52655
  import { existsSync as existsSync14, mkdirSync as mkdirSync19, readdirSync as readdirSync12, renameSync as renameSync11, statSync as statSync21 } from "node:fs";
52496
- import { basename as basename13, dirname as dirname18, join as join41 } from "node:path";
52656
+ import { basename as basename13, dirname as dirname19, join as join41 } from "node:path";
52497
52657
  function frizzDatabaseLocation(options) {
52498
52658
  if (options.stateDir !== void 0) {
52499
- const projectsDir = dirname18(options.stateDir);
52659
+ const projectsDir = dirname19(options.stateDir);
52500
52660
  if (basename13(projectsDir) === "projects") {
52501
- return { path: options.path ?? join41(dirname18(projectsDir), "ui.db"), projectsDir };
52661
+ return { path: options.path ?? join41(dirname19(projectsDir), "ui.db"), projectsDir };
52502
52662
  }
52503
52663
  return { path: options.path ?? join41(options.stateDir, "ui.db"), projectsDir: void 0 };
52504
52664
  }
@@ -52522,7 +52682,7 @@ function ensureFrizzSchema(db) {
52522
52682
  }
52523
52683
  function openFrizzDatabase(options = {}) {
52524
52684
  const { path, projectsDir } = frizzDatabaseLocation(options);
52525
- mkdirSync19(dirname18(path), { recursive: true });
52685
+ mkdirSync19(dirname19(path), { recursive: true });
52526
52686
  const db = new sqlite_default(path);
52527
52687
  db.pragma("busy_timeout = 5000");
52528
52688
  db.pragma("journal_mode = WAL");
@@ -52681,6 +52841,7 @@ function startTenantPrime(deps) {
52681
52841
  result.skipped.push(entry.id);
52682
52842
  continue;
52683
52843
  }
52844
+ const resolveStartedAt = deps.monotonicNow?.() ?? performance.now();
52684
52845
  let project;
52685
52846
  try {
52686
52847
  project = deps.toProject(entry);
@@ -52695,12 +52856,13 @@ function startTenantPrime(deps) {
52695
52856
  log3(`${project.name} is served by another Frizz (pid ${other}) \u2014 leaving it closed here`);
52696
52857
  continue;
52697
52858
  }
52859
+ const resolveMs = (deps.monotonicNow?.() ?? performance.now()) - resolveStartedAt;
52698
52860
  if (lastTookMs !== void 0) await delay2(deps.gapMs ?? gapAfter(lastTookMs));
52699
52861
  if (stopped) break;
52700
52862
  try {
52701
52863
  const startedAt = deps.monotonicNow?.() ?? performance.now();
52702
52864
  const opened = await deps.activate(project);
52703
- const tookMs = Math.round((deps.monotonicNow?.() ?? performance.now()) - startedAt);
52865
+ const tookMs = Math.round(resolveMs + ((deps.monotonicNow?.() ?? performance.now()) - startedAt));
52704
52866
  lastTookMs = tookMs;
52705
52867
  if (opened === void 0) result.failed.push(entry.id);
52706
52868
  else {
@@ -52737,14 +52899,14 @@ var init_tenant_prime = __esm({
52737
52899
  init_logging();
52738
52900
  PRIME_START_DELAY_MS = 250;
52739
52901
  PRIME_MIN_GAP_MS = 25;
52740
- PRIME_MAX_GAP_MS = 250;
52902
+ PRIME_MAX_GAP_MS = 1500;
52741
52903
  }
52742
52904
  });
52743
52905
 
52744
52906
  // packages/server/src/project-teardown.ts
52745
52907
  import { rmSync as rmSync12 } from "node:fs";
52746
52908
  import { homedir as homedir19 } from "node:os";
52747
- import { dirname as dirname19, resolve as resolve10 } from "node:path";
52909
+ import { dirname as dirname20, resolve as resolve10 } from "node:path";
52748
52910
  async function stopProjectWorkers(ctx) {
52749
52911
  let stopped = 0;
52750
52912
  for (const row of ctx.storage.allSessions()) {
@@ -52764,7 +52926,7 @@ function deleteProjectState(projectId, home = homedir19()) {
52764
52926
  if (!/^[\w.-]+$/u.test(projectId) || projectId === "." || projectId === "..") {
52765
52927
  throw new Error(`Refusing to delete state for a malformed project id: ${projectId}`);
52766
52928
  }
52767
- if (dirname19(resolve10(target)) !== resolve10(dirname19(projectStateDir("x", home)))) {
52929
+ if (dirname20(resolve10(target)) !== resolve10(dirname20(projectStateDir("x", home)))) {
52768
52930
  throw new Error(`Refusing to delete ${target} \u2014 it is not a project state directory`);
52769
52931
  }
52770
52932
  rmSync12(target, { recursive: true, force: true });
@@ -52787,13 +52949,14 @@ __export(index_exports, {
52787
52949
  createShutdownSignalHandler: () => createShutdownSignalHandler,
52788
52950
  pipeToApp: () => pipeToApp,
52789
52951
  registeredTenantHealth: () => registeredTenantHealth,
52952
+ serveStatic: () => serveStatic,
52790
52953
  splitTenantRequest: () => splitTenantRequest,
52791
52954
  startServer: () => startServer,
52792
52955
  unknownProjectPage: () => unknownProjectPage
52793
52956
  });
52794
52957
  import { createServer } from "node:http";
52795
- import { readFileSync as readFileSync29, existsSync as existsSync15 } from "node:fs";
52796
- import { dirname as dirname20, join as join42, resolve as resolve11, extname as extname4, normalize } from "node:path";
52958
+ import { readFileSync as readFileSync29, existsSync as existsSync15, statSync as statSync22 } from "node:fs";
52959
+ import { dirname as dirname21, join as join42, resolve as resolve11, extname as extname4, normalize, sep as sep5 } from "node:path";
52797
52960
  function readServerAddressHolder(path) {
52798
52961
  try {
52799
52962
  const value = JSON.parse(readFileSync29(path, "utf8"));
@@ -52894,14 +53057,63 @@ function createShutdownSignalHandler(options) {
52894
53057
  );
52895
53058
  };
52896
53059
  }
53060
+ function encodedStatic(key, encoding, raw2) {
53061
+ const hit = staticEncodedCache.get(key);
53062
+ if (hit) return hit;
53063
+ const out = compress(raw2, encoding);
53064
+ if (staticEncodedCacheBytes + out.byteLength > STATIC_ENCODED_CACHE_MAX_BYTES) {
53065
+ staticEncodedCache.clear();
53066
+ staticEncodedCacheBytes = 0;
53067
+ }
53068
+ staticEncodedCache.set(key, out);
53069
+ staticEncodedCacheBytes += out.byteLength;
53070
+ return out;
53071
+ }
53072
+ function staticIsFresh(req, etag, mtimeMs) {
53073
+ const ifNoneMatch = req.headers["if-none-match"];
53074
+ if (ifNoneMatch) {
53075
+ return ifNoneMatch.split(",").some((candidate) => {
53076
+ const tag = candidate.trim();
53077
+ return tag === "*" || tag.replace(/^W\//, "") === etag;
53078
+ });
53079
+ }
53080
+ const ifModifiedSince = req.headers["if-modified-since"];
53081
+ if (!ifModifiedSince) return false;
53082
+ const since = Date.parse(ifModifiedSince);
53083
+ return Number.isFinite(since) && Math.floor(mtimeMs / 1e3) <= Math.floor(since / 1e3);
53084
+ }
52897
53085
  function serveStatic(distDir, req, res) {
52898
53086
  const rel = normalize((req.url ?? "/").split("?")[0]).replace(/^(\.\.[/\\])+/, "");
52899
53087
  let file = join42(distDir, rel === "/" ? "index.html" : rel);
52900
53088
  if (!file.startsWith(distDir)) file = join42(distDir, "index.html");
52901
53089
  if (!existsSync15(file)) file = join42(distDir, "index.html");
52902
53090
  try {
52903
- const body = readFileSync29(file);
52904
- res.writeHead(200, { "content-type": MIME[extname4(file)] ?? "application/octet-stream" });
53091
+ const stats = statSync22(file);
53092
+ const cacheControl = file.startsWith(join42(distDir, "assets") + sep5) ? STATIC_CACHE_IMMUTABLE : STATIC_CACHE_REVALIDATE;
53093
+ const etag = `"${stats.size.toString(16)}-${Math.trunc(stats.mtimeMs).toString(16)}"`;
53094
+ const headers = {
53095
+ "content-type": MIME[extname4(file)] ?? "application/octet-stream",
53096
+ "cache-control": cacheControl,
53097
+ etag,
53098
+ "last-modified": stats.mtime.toUTCString(),
53099
+ // Sent on every static response, not just the compressed ones: a shared cache in front of a
53100
+ // tunnelled Frizz must not hand a brotli body to a client that asked for identity.
53101
+ vary: "Accept-Encoding"
53102
+ };
53103
+ if (staticIsFresh(req, etag, stats.mtimeMs)) {
53104
+ res.writeHead(304, headers);
53105
+ res.end();
53106
+ return;
53107
+ }
53108
+ let body = readFileSync29(file);
53109
+ const accept = req.headers["accept-encoding"];
53110
+ const encoding = negotiateEncoding(Array.isArray(accept) ? accept.join(",") : accept);
53111
+ if (encoding && shouldCompress(new Headers({ "content-type": headers["content-type"] }), body.byteLength)) {
53112
+ body = encodedStatic(`${encoding}:${file}:${etag}`, encoding, body);
53113
+ headers["content-encoding"] = encoding;
53114
+ }
53115
+ headers["content-length"] = String(body.byteLength);
53116
+ res.writeHead(200, headers);
52905
53117
  res.end(body);
52906
53118
  } catch {
52907
53119
  res.writeHead(404);
@@ -53003,10 +53215,10 @@ async function startServer(opts = {}) {
53003
53215
  // too — projecting only the RPC is the exact half-fix the × already had to correct once.
53004
53216
  (slug) => c.tailer.ownerGone?.(slug) ?? false
53005
53217
  ),
53006
- // A reader's live watch on the file it shows. Gated as the read is (Markdown through the reader
53007
- // roots, anything else through the project directory alone) and watched by CANONICAL path, so a
53008
- // symlinked `.md` and its target are one watch.
53009
- watchFile: (path, onChange) => watchLocalFile(resolveWatchableLocalFile(path, c.project.dir, openableFileRoots(c.project)), onChange)
53218
+ // A reader's live watch on the file it shows. Gated as the read is (one set of openable roots for
53219
+ // both readers, plus the Markdown reader's canonical-extension check) and watched by CANONICAL
53220
+ // path, so a symlinked `.md` and its target are one watch.
53221
+ watchFile: (path, onChange) => watchLocalFile(resolveWatchableLocalFile(path, openableFileRoots(c.project)), onChange)
53010
53222
  });
53011
53223
  let githubInit;
53012
53224
  let terminal;
@@ -53150,7 +53362,7 @@ async function startServer(opts = {}) {
53150
53362
  if (statusPath && statusIdentity) runtime.removeStatus(statusPath, statusIdentity);
53151
53363
  if (statusPath && statusIdentity) {
53152
53364
  try {
53153
- runtime.removeStatus(serverAddressPathForStateDir(dirname20(statusPath)), statusIdentity);
53365
+ runtime.removeStatus(serverAddressPathForStateDir(dirname21(statusPath)), statusIdentity);
53154
53366
  } catch {
53155
53367
  }
53156
53368
  }
@@ -53498,13 +53710,14 @@ async function startServer(opts = {}) {
53498
53710
  });
53499
53711
  }
53500
53712
  }
53501
- var SERVER_SHUTDOWN_TIMEOUT_MS, SERVER_FORCE_EXIT_MS, defaultStartServerRuntime, ServerStartupError, isApiUrl, serverLockPathFor, MIME;
53713
+ var SERVER_SHUTDOWN_TIMEOUT_MS, SERVER_FORCE_EXIT_MS, defaultStartServerRuntime, ServerStartupError, isApiUrl, serverLockPathFor, MIME, STATIC_CACHE_IMMUTABLE, STATIC_CACHE_REVALIDATE, staticEncodedCache, STATIC_ENCODED_CACHE_MAX_BYTES, staticEncodedCacheBytes;
53502
53714
  var init_index = __esm({
53503
53715
  "packages/server/src/index.ts"() {
53504
53716
  "use strict";
53505
53717
  init_src();
53506
53718
  init_context();
53507
53719
  init_app();
53720
+ init_compression();
53508
53721
  init_terminal();
53509
53722
  init_app_socket();
53510
53723
  init_shutdown();
@@ -53572,6 +53785,11 @@ var init_index = __esm({
53572
53785
  ".ico": "image/x-icon",
53573
53786
  ".woff2": "font/woff2"
53574
53787
  };
53788
+ STATIC_CACHE_IMMUTABLE = "public, max-age=31536000, immutable";
53789
+ STATIC_CACHE_REVALIDATE = "no-cache";
53790
+ staticEncodedCache = /* @__PURE__ */ new Map();
53791
+ STATIC_ENCODED_CACHE_MAX_BYTES = 32 * 1024 * 1024;
53792
+ staticEncodedCacheBytes = 0;
53575
53793
  }
53576
53794
  });
53577
53795