@dylanpiercey/work 0.0.5 → 0.0.6

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 (155) hide show
  1. package/bin/work.mjs +63 -16
  2. package/dist/index.mjs +312 -218
  3. package/dist/public/assets/{_G2euCJ5s2.js → _17ixsFjl2.js} +2 -2
  4. package/dist/public/assets/{_G2euCJ5s2.js.map → _17ixsFjl2.js.map} +1 -1
  5. package/dist/public/assets/{_BmLItN7n.js → _38qjx0VE.js} +2 -2
  6. package/dist/public/assets/{_BmLItN7n.js.map → _38qjx0VE.js.map} +1 -1
  7. package/dist/public/assets/{_UUjPxQzk.js → _B01vNcBH.js} +2 -2
  8. package/dist/public/assets/{_UUjPxQzk.js.map → _B01vNcBH.js.map} +1 -1
  9. package/dist/public/assets/{_Ck_58QRD.js → _B5_K4U35.js} +2 -2
  10. package/dist/public/assets/{_Ck_58QRD.js.map → _B5_K4U35.js.map} +1 -1
  11. package/dist/public/assets/{_CGEJqu1l.js → _B7WJMKdz.js} +2 -2
  12. package/dist/public/assets/{_CGEJqu1l.js.map → _B7WJMKdz.js.map} +1 -1
  13. package/dist/public/assets/{_MSZeR7tc.js → _BCmJwCZ4.js} +2 -2
  14. package/dist/public/assets/{_MSZeR7tc.js.map → _BCmJwCZ4.js.map} +1 -1
  15. package/dist/public/assets/{_XySmXsU3.js → _BGfZ-AIc.js} +2 -2
  16. package/dist/public/assets/{_XySmXsU3.js.map → _BGfZ-AIc.js.map} +1 -1
  17. package/dist/public/assets/{_C_AWyxBB.js → _BGjK3KLI.js} +2 -2
  18. package/dist/public/assets/{_C_AWyxBB.js.map → _BGjK3KLI.js.map} +1 -1
  19. package/dist/public/assets/{_Bjvy806u2.js → _BO1auSkL2.js} +2 -2
  20. package/dist/public/assets/{_Bjvy806u2.js.map → _BO1auSkL2.js.map} +1 -1
  21. package/dist/public/assets/{_Dp2I7SvR2.js → _BSe5zjTJ2.js} +2 -2
  22. package/dist/public/assets/{_Dp2I7SvR2.js.map → _BSe5zjTJ2.js.map} +1 -1
  23. package/dist/public/assets/{_DwB4tost2.js → _BV7Qzzwy2.js} +2 -2
  24. package/dist/public/assets/{_DwB4tost2.js.map → _BV7Qzzwy2.js.map} +1 -1
  25. package/dist/public/assets/{_C6fTVhaS.js → _BZgEX-SR.js} +2 -2
  26. package/dist/public/assets/{_C6fTVhaS.js.map → _BZgEX-SR.js.map} +1 -1
  27. package/dist/public/assets/{_B-CqRNtV.js → _Bj_P-is9.js} +2 -2
  28. package/dist/public/assets/{_B-CqRNtV.js.map → _Bj_P-is9.js.map} +1 -1
  29. package/dist/public/assets/{_LMf8ZNAk.js → _BjlFBd9j.js} +2 -2
  30. package/dist/public/assets/{_LMf8ZNAk.js.map → _BjlFBd9j.js.map} +1 -1
  31. package/dist/public/assets/{_DsH6sF8_.js → _BqB9YKHu.js} +2 -2
  32. package/dist/public/assets/{_DsH6sF8_.js.map → _BqB9YKHu.js.map} +1 -1
  33. package/dist/public/assets/{_CSxCkWdX2.js → _Bs-d5a142.js} +2 -2
  34. package/dist/public/assets/{_CSxCkWdX2.js.map → _Bs-d5a142.js.map} +1 -1
  35. package/dist/public/assets/{_f31sxhc9.js → _Bt1hNExm.js} +2 -2
  36. package/dist/public/assets/{_f31sxhc9.js.map → _Bt1hNExm.js.map} +1 -1
  37. package/dist/public/assets/{_lZmV1DmL.js → _BvkUWaoR.js} +2 -2
  38. package/dist/public/assets/{_lZmV1DmL.js.map → _BvkUWaoR.js.map} +1 -1
  39. package/dist/public/assets/{_DR7HMLdt.js → _C0fM-yEd.js} +2 -2
  40. package/dist/public/assets/{_DR7HMLdt.js.map → _C0fM-yEd.js.map} +1 -1
  41. package/dist/public/assets/{_BO52x4nD2.js → _C52df4172.js} +2 -2
  42. package/dist/public/assets/{_BO52x4nD2.js.map → _C52df4172.js.map} +1 -1
  43. package/dist/public/assets/{_DVqaReFM2.js → _CATT-8QU2.js} +2 -2
  44. package/dist/public/assets/{_DVqaReFM2.js.map → _CATT-8QU2.js.map} +1 -1
  45. package/dist/public/assets/{_Fpix3N3i.js → _CDUUTPIa.js} +2 -2
  46. package/dist/public/assets/{_Fpix3N3i.js.map → _CDUUTPIa.js.map} +1 -1
  47. package/dist/public/assets/{_CMH9CsQN.js → _CIE37fGr.js} +2 -2
  48. package/dist/public/assets/{_CMH9CsQN.js.map → _CIE37fGr.js.map} +1 -1
  49. package/dist/public/assets/{_A4VtPfAb.js → _CLjg6iH5.js} +2 -2
  50. package/dist/public/assets/{_A4VtPfAb.js.map → _CLjg6iH5.js.map} +1 -1
  51. package/dist/public/assets/{_DjF3hk4N.js → _CPMq9qKD.js} +2 -2
  52. package/dist/public/assets/{_DjF3hk4N.js.map → _CPMq9qKD.js.map} +1 -1
  53. package/dist/public/assets/{_BQnjw6qe.js → _CUCwB86v.js} +2 -2
  54. package/dist/public/assets/{_BQnjw6qe.js.map → _CUCwB86v.js.map} +1 -1
  55. package/dist/public/assets/{_CZJ6f1W42.js → _CUdHfuKf2.js} +2 -2
  56. package/dist/public/assets/{_CZJ6f1W42.js.map → _CUdHfuKf2.js.map} +1 -1
  57. package/dist/public/assets/{_D4G4BzdU2.js → _CVvMxylB2.js} +2 -2
  58. package/dist/public/assets/{_D4G4BzdU2.js.map → _CVvMxylB2.js.map} +1 -1
  59. package/dist/public/assets/{_Cxre_eVs2.js → _CeDXSlq_2.js} +2 -2
  60. package/dist/public/assets/{_Cxre_eVs2.js.map → _CeDXSlq_2.js.map} +1 -1
  61. package/dist/public/assets/{_BMIj0szP.js → _CgK4NAc5.js} +2 -2
  62. package/dist/public/assets/{_BMIj0szP.js.map → _CgK4NAc5.js.map} +1 -1
  63. package/dist/public/assets/{_DFdBRroy.js → _ChbGErmQ.js} +2 -2
  64. package/dist/public/assets/{_DFdBRroy.js.map → _ChbGErmQ.js.map} +1 -1
  65. package/dist/public/assets/{_Dj5K_vdY.js → _CjoA9dbQ.js} +2 -2
  66. package/dist/public/assets/{_Dj5K_vdY.js.map → _CjoA9dbQ.js.map} +1 -1
  67. package/dist/public/assets/{_C7WwEVpI.js → _Cm0oW23H.js} +2 -2
  68. package/dist/public/assets/{_C7WwEVpI.js.map → _Cm0oW23H.js.map} +1 -1
  69. package/dist/public/assets/{_Cp2dVuf7.js → _CscsJi7i.js} +2 -2
  70. package/dist/public/assets/{_Cp2dVuf7.js.map → _CscsJi7i.js.map} +1 -1
  71. package/dist/public/assets/{_C_RO1bIU.js → _Czy_Rmr8.js} +2 -2
  72. package/dist/public/assets/{_C_RO1bIU.js.map → _Czy_Rmr8.js.map} +1 -1
  73. package/dist/public/assets/{_Dg0ufwJw.js → _D-u1ssE0.js} +2 -2
  74. package/dist/public/assets/{_Dg0ufwJw.js.map → _D-u1ssE0.js.map} +1 -1
  75. package/dist/public/assets/{_DThwiCYf.js → _D1AvypB0.js} +2 -2
  76. package/dist/public/assets/{_DThwiCYf.js.map → _D1AvypB0.js.map} +1 -1
  77. package/dist/public/assets/{_De1qIUYL2.js → _D4Z_UM_B2.js} +2 -2
  78. package/dist/public/assets/{_De1qIUYL2.js.map → _D4Z_UM_B2.js.map} +1 -1
  79. package/dist/public/assets/{_DWh6hcFb.js → _D7AQAhlo.js} +2 -2
  80. package/dist/public/assets/{_DWh6hcFb.js.map → _D7AQAhlo.js.map} +1 -1
  81. package/dist/public/assets/{_BxHj_AmV.js → _D8RDRYsV.js} +2 -2
  82. package/dist/public/assets/{_BxHj_AmV.js.map → _D8RDRYsV.js.map} +1 -1
  83. package/dist/public/assets/{_BtEwCzLt.js → _D9oMqxHc.js} +2 -2
  84. package/dist/public/assets/{_BtEwCzLt.js.map → _D9oMqxHc.js.map} +1 -1
  85. package/dist/public/assets/{_BKWC43v9.js → _DDDACu2e.js} +2 -2
  86. package/dist/public/assets/{_BKWC43v9.js.map → _DDDACu2e.js.map} +1 -1
  87. package/dist/public/assets/{_BPAMsQ-Y2.js → _DFLlSEDh2.js} +2 -2
  88. package/dist/public/assets/{_BPAMsQ-Y2.js.map → _DFLlSEDh2.js.map} +1 -1
  89. package/dist/public/assets/{_C55X2_br.js → _DOeCLKRd.js} +2 -2
  90. package/dist/public/assets/{_C55X2_br.js.map → _DOeCLKRd.js.map} +1 -1
  91. package/dist/public/assets/{_BksA_4pq.js → _DWSSCCOX.js} +2 -2
  92. package/dist/public/assets/{_BksA_4pq.js.map → _DWSSCCOX.js.map} +1 -1
  93. package/dist/public/assets/{_CPt59YK-2.js → _DcCF4p4b2.js} +2 -2
  94. package/dist/public/assets/{_CPt59YK-2.js.map → _DcCF4p4b2.js.map} +1 -1
  95. package/dist/public/assets/{_D25eFvus.js → _Dfi8Atag.js} +2 -2
  96. package/dist/public/assets/{_D25eFvus.js.map → _Dfi8Atag.js.map} +1 -1
  97. package/dist/public/assets/{_CZjGo4EJ2.js → _Dg2FAYj_2.js} +2 -2
  98. package/dist/public/assets/{_CZjGo4EJ2.js.map → _Dg2FAYj_2.js.map} +1 -1
  99. package/dist/public/assets/{_DwvTHP0H.js → _Dlbc7SgI.js} +2 -2
  100. package/dist/public/assets/{_DwvTHP0H.js.map → _Dlbc7SgI.js.map} +1 -1
  101. package/dist/public/assets/{_DdXxywnu.js → _DoTuVtdo.js} +2 -2
  102. package/dist/public/assets/{_DdXxywnu.js.map → _DoTuVtdo.js.map} +1 -1
  103. package/dist/public/assets/{_DWBu1oTd.js → _DpRvij_q.js} +2 -2
  104. package/dist/public/assets/{_DWBu1oTd.js.map → _DpRvij_q.js.map} +1 -1
  105. package/dist/public/assets/{_m6OqtXq5.js → _DpdFHjlT.js} +2 -2
  106. package/dist/public/assets/{_m6OqtXq5.js.map → _DpdFHjlT.js.map} +1 -1
  107. package/dist/public/assets/{_DkAxFIdj2.js → _DsK9qp5z2.js} +2 -2
  108. package/dist/public/assets/{_DkAxFIdj2.js.map → _DsK9qp5z2.js.map} +1 -1
  109. package/dist/public/assets/{_BF4oeZAs2.js → _DtkPfG0P2.js} +2 -2
  110. package/dist/public/assets/{_BF4oeZAs2.js.map → _DtkPfG0P2.js.map} +1 -1
  111. package/dist/public/assets/{_DgS0ehtc.js → _DtpDQy9c.js} +2 -2
  112. package/dist/public/assets/{_DgS0ehtc.js.map → _DtpDQy9c.js.map} +1 -1
  113. package/dist/public/assets/{_2JdtdC0N.js → _DvigaXuY.js} +2 -2
  114. package/dist/public/assets/{_2JdtdC0N.js.map → _DvigaXuY.js.map} +1 -1
  115. package/dist/public/assets/{_BacHRrKm2.js → _PBOdFezG2.js} +2 -2
  116. package/dist/public/assets/{_BacHRrKm2.js.map → _PBOdFezG2.js.map} +1 -1
  117. package/dist/public/assets/{_sQkp9ieF.js → _Q7i-xAMZ.js} +2 -2
  118. package/dist/public/assets/{_sQkp9ieF.js.map → _Q7i-xAMZ.js.map} +1 -1
  119. package/dist/public/assets/{_g24DOTM6.js → _T-HpFRXH.js} +2 -2
  120. package/dist/public/assets/{_g24DOTM6.js.map → _T-HpFRXH.js.map} +1 -1
  121. package/dist/public/assets/{_DaxEJQAG2.js → _U-btoBCb2.js} +2 -2
  122. package/dist/public/assets/{_DaxEJQAG2.js.map → _U-btoBCb2.js.map} +1 -1
  123. package/dist/public/assets/{_B7BQvLFA2.js → _VVnpWsa-2.js} +2 -2
  124. package/dist/public/assets/{_B7BQvLFA2.js.map → _VVnpWsa-2.js.map} +1 -1
  125. package/dist/public/assets/{_3LSnPXE-2.js → _kN8jmSEy2.js} +2 -2
  126. package/dist/public/assets/{_3LSnPXE-2.js.map → _kN8jmSEy2.js.map} +1 -1
  127. package/dist/public/assets/{_BbQjjMLb2.js → _kf1lUDoU2.js} +2 -2
  128. package/dist/public/assets/{_BbQjjMLb2.js.map → _kf1lUDoU2.js.map} +1 -1
  129. package/dist/public/assets/{_MSjbYDCb.js → _kzd-9LxV.js} +2 -2
  130. package/dist/public/assets/{_MSjbYDCb.js.map → _kzd-9LxV.js.map} +1 -1
  131. package/dist/public/assets/{_L0QEXXRu.js → _lENTdKos.js} +2 -2
  132. package/dist/public/assets/{_L0QEXXRu.js.map → _lENTdKos.js.map} +1 -1
  133. package/dist/public/assets/{_DwWKKIbx.js → _lO429-VP.js} +2 -2
  134. package/dist/public/assets/{_DwWKKIbx.js.map → _lO429-VP.js.map} +1 -1
  135. package/dist/public/assets/{_BWobArGx2.js → _nfuFU9Un2.js} +2 -2
  136. package/dist/public/assets/{_BWobArGx2.js.map → _nfuFU9Un2.js.map} +1 -1
  137. package/dist/public/assets/{_dbpNK3ti.js → _nv0goT4Z.js} +2 -2
  138. package/dist/public/assets/{_dbpNK3ti.js.map → _nv0goT4Z.js.map} +1 -1
  139. package/dist/public/assets/{_5XJqee1K2.js → _o_JLlSoU2.js} +2 -2
  140. package/dist/public/assets/{_5XJqee1K2.js.map → _o_JLlSoU2.js.map} +1 -1
  141. package/dist/public/assets/{_B7ycuWnF.js → _rDdCnzAf.js} +2 -2
  142. package/dist/public/assets/{_B7ycuWnF.js.map → _rDdCnzAf.js.map} +1 -1
  143. package/dist/public/assets/{_qGiUFV1r.js → _tf4220G9.js} +2 -2
  144. package/dist/public/assets/{_qGiUFV1r.js.map → _tf4220G9.js.map} +1 -1
  145. package/dist/public/assets/{_Dc3WoyCf.js → _uhGymT-L.js} +2 -2
  146. package/dist/public/assets/{_Dc3WoyCf.js.map → _uhGymT-L.js.map} +1 -1
  147. package/dist/public/assets/{_CFYld88W.js → _vd_LQrD6.js} +2 -2
  148. package/dist/public/assets/{_CFYld88W.js.map → _vd_LQrD6.js.map} +1 -1
  149. package/dist/public/assets/{_AAkZyuUo2.js → _xikqPUw52.js} +2 -2
  150. package/dist/public/assets/{_AAkZyuUo2.js.map → _xikqPUw52.js.map} +1 -1
  151. package/dist/public/assets/{index-BAGH9WA4.js → index-BwlA-lgI.js} +59 -59
  152. package/dist/public/assets/index-BwlA-lgI.js.map +1 -0
  153. package/install.sh +4 -1
  154. package/package.json +1 -1
  155. package/dist/public/assets/index-BAGH9WA4.js.map +0 -1
package/dist/index.mjs CHANGED
@@ -3481,7 +3481,7 @@ var palette_default = _template("h", (input) => {
3481
3481
  const $input_status__closures = /* @__PURE__ */ new Set();
3482
3482
  const $input_settings_agents__closures = /* @__PURE__ */ new Set();
3483
3483
  let query = "";
3484
- let hi = 0;
3484
+ let hiRaw = 0;
3485
3485
  let showArchived = false;
3486
3486
  const active = input.workspaces.filter((ws) => ws.status === "active");
3487
3487
  const archived = input.workspaces.filter((ws) => ws.status === "archived");
@@ -3517,6 +3517,7 @@ var palette_default = _template("h", (input) => {
3517
3517
  ...commands,
3518
3518
  { kind: "new" }
3519
3519
  ];
3520
+ const hi = Math.min(hiRaw, rows.length - 1);
3520
3521
  const pick = _resume((row) => {
3521
3522
  if (!row) return;
3522
3523
  if (row.kind === "new") input.onNew();
@@ -3543,7 +3544,7 @@ var palette_default = _template("h", (input) => {
3543
3544
  }, $scope0_id, "c", $sg__input_inline__OR__input_workspaces_length, $sg__input_inline__OR__input_workspaces_length, 1, 0, 1);
3544
3545
  _html(`<input${_attr_input_value($scope0_id, "d", query, _resume(function(v) {
3545
3546
  query = v;
3546
- hi = 0;
3547
+ hiRaw = 0;
3547
3548
  }, "h0", $scope0_id))} autofocus placeholder="Jump to workspace…" aria-label="Filter workspaces">${_el_resume($scope0_id, "d")}<ul class=rows>`);
3548
3549
  _for_of(rows, (row, i) => {
3549
3550
  const $scope2_id = _scope_id();
@@ -3740,7 +3741,7 @@ var palette_default = _template("h", (input) => {
3740
3741
  z: input.settings?.agents,
3741
3742
  a0: input.onSettings,
3742
3743
  a1: query,
3743
- a2: hi,
3744
+ a2: hiRaw,
3744
3745
  a3: showArchived,
3745
3746
  a4: active,
3746
3747
  a5: archived,
@@ -3749,10 +3750,12 @@ var palette_default = _template("h", (input) => {
3749
3750
  a9: currentWs,
3750
3751
  ab: commands,
3751
3752
  ad: rows,
3752
- af: pick,
3753
- ag: $si__input_selectedId && $input_selectedId__closures,
3754
- ai: $si__input_status && $input_status__closures,
3755
- aj: $si__input_settings_agents && $input_settings_agents__closures
3753
+ af: rows.length,
3754
+ ah: hi,
3755
+ ai: pick,
3756
+ aj: $si__input_selectedId && $input_selectedId__closures,
3757
+ al: $si__input_status && $input_status__closures,
3758
+ am: $si__input_settings_agents && $input_settings_agents__closures
3756
3759
  });
3757
3760
  _resume_branch($scope0_id);
3758
3761
  });
@@ -4647,10 +4650,12 @@ var new_workspace_default = _template("g", (input) => {
4647
4650
  * first render on it); getters return defaults during a server render.
4648
4651
  * Writes update the map immediately and post fire-and-forget. */
4649
4652
  var prefs$1 = /* @__PURE__ */ new Map();
4653
+ var written = /* @__PURE__ */ new Set();
4650
4654
  function get$1(key) {
4651
4655
  return prefs$1.get(key) ?? null;
4652
4656
  }
4653
4657
  function set(key, value) {
4658
+ written.add(key);
4654
4659
  if (value === null) prefs$1.delete(key);
4655
4660
  else prefs$1.set(key, value);
4656
4661
  post(key, value);
@@ -5483,7 +5488,7 @@ _template("c", (input) => {
5483
5488
  //#endregion
5484
5489
  //#region src/tags/prompt-dialog.marko
5485
5490
  var prompt_dialog_default = _template("i", (input) => {
5486
- const $scope0_reason = _scope_reason(), $sg__input_label = _serialize_guard($scope0_reason, 2), $sg__input_onCancel = _serialize_guard($scope0_reason, 3), $si__input_submitLabel = _serialize_if($scope0_reason, 4), $si__input_label = _serialize_if($scope0_reason, 2), $si__input_placeholder = _serialize_if($scope0_reason, 5);
5491
+ const $scope0_reason = _scope_reason(), $sg__input_label = _serialize_guard($scope0_reason, 1), $sg__input_onCancel = _serialize_guard($scope0_reason, 2), $si__input_submitLabel = _serialize_if($scope0_reason, 3), $si__input_label = _serialize_if($scope0_reason, 1), $si__input_placeholder = _serialize_if($scope0_reason, 4);
5487
5492
  const $scope0_id = _scope_id();
5488
5493
  const $modalview_content__subscribers = /* @__PURE__ */ new Set();
5489
5494
  const $input_submitLabel__closures = /* @__PURE__ */ new Set();
@@ -5510,7 +5515,7 @@ var prompt_dialog_default = _template("i", (input) => {
5510
5515
  footer: attrTag({ content: _content_resume("i5", () => {
5511
5516
  _scope_reason();
5512
5517
  const $scope1_id = _scope_id();
5513
- _html(`<button class="btn primary"${_attr("disabled", !value.trim())}>${_escape(input.submitLabel || "OK")}${_el_resume($scope1_id, "b", _serialize_guard($scope0_reason, 4))}</button>${_el_resume($scope1_id, "a")}<div class=spacer></div><button class=btn>Cancel</button>${_el_resume($scope1_id, "c")}`);
5518
+ _html(`<button class="btn primary"${_attr("disabled", !value.trim())}>${_escape(input.submitLabel || "OK")}${_el_resume($scope1_id, "b", _serialize_guard($scope0_reason, 3))}</button>${_el_resume($scope1_id, "a")}<div class=spacer></div><button class=btn>Cancel</button>${_el_resume($scope1_id, "c")}`);
5514
5519
  _script($scope1_id, "i3");
5515
5520
  _subscribe($value__closures, _subscribe($si__input_submitLabel && $input_submitLabel__closures, writeScope($scope1_id, { _: _scope_with_id($scope0_id) })));
5516
5521
  _resume_branch($scope1_id);
@@ -5768,7 +5773,7 @@ var diff_view_default = _template("d", (input) => {
5768
5773
  const $scope22_id = _scope_id();
5769
5774
  _html(`<button class=${collapsedDirs.has(dirKey(row.path)) ? "\"tree-dir dim mono closed\"" : "\"tree-dir dim mono\""}${_attr("title", row.path)}${_attr_style(`padding-left:${.35 + row.depth * .75}rem`)}><span class=tree-chev>${collapsedDirs.has(dirKey(row.path)) ? "▸" : "▾"}${_el_resume($scope22_id, "b")}</span>${_escape(row.label)}${_el_resume($scope22_id, "c")}/</button>${_el_resume($scope22_id, "a")}`);
5770
5775
  _script($scope22_id, "d26");
5771
- _subscribe($if_content4__dirKey__closures, _subscribe($collapsedDirs__closures, writeScope($scope22_id, { Cc9: 1 })));
5776
+ _subscribe($if_content4__dirKey__closures, _subscribe($collapsedDirs__closures, writeScope($scope22_id, { Cca: 1 })));
5772
5777
  return 0;
5773
5778
  } else if (!hiddenByCollapse(row) && row.kind !== "dir") {
5774
5779
  const $scope8_id = _scope_id();
@@ -5852,7 +5857,7 @@ var diff_view_default = _template("d", (input) => {
5852
5857
  _script($scope4_id, "d31");
5853
5858
  _subscribe($sendTarget__closures, _subscribe($sending__closures, _subscribe($si__input_sessions && $input_sessions__closures, writeScope($scope4_id, {
5854
5859
  _: _scope_with_id($scope2_id),
5855
- Cc5: 1
5860
+ Cc6: 1
5856
5861
  }))));
5857
5862
  return 1;
5858
5863
  }
@@ -5907,14 +5912,19 @@ var diff_view_default = _template("d", (input) => {
5907
5912
  return 0;
5908
5913
  }
5909
5914
  }, $scope0_id, "u", 1, 1, 1, 0, 1);
5915
+ _for_of(repoList.filter((r) => r.baseMissing), (repo) => {
5916
+ const $scope29_id = _scope_id();
5917
+ _html(`<p class=toast-error>${_escape(repo.worktree)}${_el_resume($scope29_id, "a")}: base <!>${_escape(repo.base)}${_el_resume($scope29_id, "b")} not found — showing uncommitted changes only.</p>`);
5918
+ writeScope($scope29_id, {});
5919
+ }, "worktree", $scope0_id, "v", 1, 1, 1, 0, 1);
5910
5920
  _if(() => {
5911
5921
  if (!repos && loading) {
5912
- const $scope29_id = _scope_id();
5922
+ const $scope30_id = _scope_id();
5913
5923
  _html("<div class=diff-skel><p class=dim><span class=spin></span>Loading diff…</p><div class=skel-row></div><div class=skel-row></div><div class=skel-row></div></div>");
5914
- writeScope($scope29_id, {});
5924
+ writeScope($scope30_id, {});
5915
5925
  return 0;
5916
5926
  }
5917
- }, $scope0_id, "v", 1, 1, 1, 0, 1);
5927
+ }, $scope0_id, "w", 1, 1, 1, 0, 1);
5918
5928
  _if(() => {
5919
5929
  if (repos && !allFiles.length) {
5920
5930
  const $scope20_id = _scope_id();
@@ -5927,7 +5937,7 @@ var diff_view_default = _template("d", (input) => {
5927
5937
  writeScope($scope18_id, {});
5928
5938
  return 1;
5929
5939
  }
5930
- }, $scope0_id, "w", 1, 1, 1, 0, 1);
5940
+ }, $scope0_id, "x", 1, 1, 1, 0, 1);
5931
5941
  _for_of(repoList, (repo) => {
5932
5942
  const $scope9_id = _scope_id();
5933
5943
  const $for_content3__repo_worktree__closures = /* @__PURE__ */ new Set();
@@ -5944,7 +5954,7 @@ var diff_view_default = _template("d", (input) => {
5944
5954
  const $scope23_id = _scope_id();
5945
5955
  _html(`<button class=${collapsedRepos.has(repo.worktree) ? "\"repo-sep closed\"" : "repo-sep"}><span class=tree-chev>${collapsedRepos.has(repo.worktree) ? "▸" : "▾"}${_el_resume($scope23_id, "b")}</span><span class=mono>${_escape(repo.worktree)}${_el_resume($scope23_id, "c")}</span><span class=dim>${_escape(repo.full_name)}${_el_resume($scope23_id, "d")}</span><span class=chip>vs <!>${_escape(repo.base)}${_el_resume($scope23_id, "e")}</span></button>${_el_resume($scope23_id, "a")}`);
5946
5956
  _script($scope23_id, "d34");
5947
- _subscribe($for_content3__repo_base__closures, _subscribe($for_content3__repo_full_name__closures, _subscribe($for_content3__repo_worktree__closures, _subscribe($collapsedRepos__closures, writeScope($scope23_id, { Cca: 1 })))));
5957
+ _subscribe($for_content3__repo_base__closures, _subscribe($for_content3__repo_full_name__closures, _subscribe($for_content3__repo_worktree__closures, _subscribe($collapsedRepos__closures, writeScope($scope23_id, { Ccb: 1 })))));
5948
5958
  return 0;
5949
5959
  }
5950
5960
  }, $scope10_id, "a", 1, 1, 1, 0, 1);
@@ -5962,9 +5972,9 @@ var diff_view_default = _template("d", (input) => {
5962
5972
  _html(`<details${_attr_details_or_dialog_open($scope12_id, "a", expanded)} class=file${_attr("data-key", file.key)}><summary><span${_attr_class(["status", file.status])}>${_escape(file.status)}${_el_resume($scope12_id, "c")}</span>${_el_resume($scope12_id, "b")}<span class=path${_attr("title", file.path)}><bdi>${_escape(file.path)}${_el_resume($scope12_id, "e")}</bdi></span>${_el_resume($scope12_id, "d")}`);
5963
5973
  _if(() => {
5964
5974
  if (fileComments.length) {
5965
- const $scope30_id = _scope_id();
5966
- _html(`<span class=chip>💬 <!>${_escape(fileComments.length)}${_el_resume($scope30_id, "a")}</span>`);
5967
- writeScope($scope30_id, {});
5975
+ const $scope31_id = _scope_id();
5976
+ _html(`<span class=chip>💬 <!>${_escape(fileComments.length)}${_el_resume($scope31_id, "a")}</span>`);
5977
+ writeScope($scope31_id, {});
5968
5978
  return 0;
5969
5979
  }
5970
5980
  }, $scope12_id, "f", 1, 1, 1, 0, 1);
@@ -5973,15 +5983,20 @@ var diff_view_default = _template("d", (input) => {
5973
5983
  }, "d3", $scope12_id))} type=checkbox>${_el_resume($scope12_id, "h")}<span class=dim>viewed</span></label>${_el_resume($scope12_id, "g")}</summary>`);
5974
5984
  _if(() => {
5975
5985
  if (file.binary) {
5976
- const $scope31_id = _scope_id();
5986
+ const $scope32_id = _scope_id();
5977
5987
  _html("<p class=\"dim diff-pad\">binary file</p>");
5978
- writeScope($scope31_id, {});
5988
+ writeScope($scope32_id, {});
5979
5989
  return 0;
5980
5990
  } else if (file.tooLarge) {
5981
- const $scope32_id = _scope_id();
5991
+ const $scope33_id = _scope_id();
5982
5992
  _html("<p class=\"dim diff-pad\">file too large to display</p>");
5983
- writeScope($scope32_id, {});
5993
+ writeScope($scope33_id, {});
5984
5994
  return 1;
5995
+ } else if (file.old == null && file.new == null) {
5996
+ const $scope34_id = _scope_id();
5997
+ _html("<p class=\"dim diff-pad\">file could not be read</p>");
5998
+ writeScope($scope34_id, {});
5999
+ return 2;
5985
6000
  } else if (expanded) {
5986
6001
  const $scope15_id = _scope_id();
5987
6002
  _if(() => {
@@ -5994,7 +6009,7 @@ var diff_view_default = _template("d", (input) => {
5994
6009
  }
5995
6010
  }, $scope15_id, "a", 1, 1, 1, 0, 1);
5996
6011
  writeScope($scope15_id, {});
5997
- return 2;
6012
+ return 3;
5998
6013
  }
5999
6014
  }, $scope12_id, "i");
6000
6015
  _html(`</details>${_el_resume($scope12_id, "a")}`);
@@ -6004,14 +6019,16 @@ var diff_view_default = _template("d", (input) => {
6004
6019
  l: file?.key,
6005
6020
  r: file?.binary,
6006
6021
  s: file?.tooLarge,
6007
- t: fileComments,
6008
- u: fileComments.length,
6009
- v: expanded,
6010
- x: $for_content4__file__closures,
6011
- y: $for_content4__file_key__closures,
6012
- z: $for_content4__fileComments__closures,
6013
- Cc0: 1,
6014
- Ccg: 1
6022
+ t: file?.old,
6023
+ u: file?.new,
6024
+ v: fileComments,
6025
+ w: fileComments.length,
6026
+ x: expanded,
6027
+ z: $for_content4__file__closures,
6028
+ a0: $for_content4__file_key__closures,
6029
+ a1: $for_content4__fileComments__closures,
6030
+ Cc1: 1,
6031
+ Cch: 1
6015
6032
  }))));
6016
6033
  }, "key", $scope11_id, "a", 1, 1, 1, "</div>", 1);
6017
6034
  _subscribe($for_content3__repoFiles__closures, writeScope($scope11_id, {}));
@@ -6033,14 +6050,13 @@ var diff_view_default = _template("d", (input) => {
6033
6050
  l: $for_content3__repo_base__closures,
6034
6051
  m: $for_content3__repoFiles__closures
6035
6052
  });
6036
- }, "worktree", $scope0_id, "x");
6053
+ }, "worktree", $scope0_id, "y");
6037
6054
  _html(`</div>${_el_resume($scope0_id, "t")}</div>`);
6038
- _if(() => {}, $scope0_id, "y");
6055
+ _if(() => {}, $scope0_id, "z");
6039
6056
  _html("</div>");
6040
6057
  _if(() => {
6041
6058
  if (askBase) {
6042
6059
  const $scope21_id = _scope_id();
6043
- _set_serialize_reason(4);
6044
6060
  const $childScope2 = _peek_scope_id();
6045
6061
  prompt_dialog_default({
6046
6062
  label: "Compare against ref",
@@ -6058,71 +6074,71 @@ var diff_view_default = _template("d", (input) => {
6058
6074
  writeScope($scope21_id, { a: _existing_scope($childScope2) });
6059
6075
  return 0;
6060
6076
  }
6061
- }, $scope0_id, "z");
6077
+ }, $scope0_id, "a0");
6062
6078
  _script($scope0_id, "d39");
6063
6079
  _script($scope0_id, "d40");
6064
6080
  writeScope($scope0_id, {
6065
- a2: input.workspaceId,
6066
- a3: input.active,
6067
- a4: input.sessions,
6068
- a6: input.onSent,
6069
- a7: input.onExit,
6070
- a8: input.sessions?.[0]?.title,
6071
- a9: input.sessions?.[0]?.agent,
6072
- aa: repos,
6073
- ab: comments,
6074
- ad: viewed,
6075
- af: viewed?.size,
6076
- ag: draft,
6077
- ai: error,
6078
- aj: loading,
6079
- al: copied,
6080
- am: sending,
6081
- an: sendTarget,
6082
- ap: fileFilter,
6083
- aq: baseRef,
6084
- as: treeOpen,
6085
- av: collapsedDirs,
6086
- aw: collapsedRepos,
6087
- ax: toggleRepo,
6088
- az: nearBox.cbs,
6089
- b0: nearBox.io,
6090
- b2: observeNear,
6091
- b3: load,
6092
- b4: loadReview,
6093
- b6: repoList,
6094
- b7: repoList.length,
6095
- b8: allFiles,
6096
- b9: allFiles?.length,
6097
- ba: fileMatch,
6098
- bc: shownFiles,
6099
- bg: filesByRepo,
6100
- bi: commentsByFile,
6101
- bj: defaultBranches,
6102
- bl: sendPick,
6103
- bm: setBase,
6104
- bo: toggleViewed,
6105
- bp: saveComment,
6106
- bq: removeComment,
6107
- br: clearComments,
6108
- bu: copyMarkdown,
6109
- bv: sendTo,
6110
- bw: jumpTo,
6111
- c9: $collapsedDirs__closures,
6112
- c0: $viewed__closures,
6113
- cg: $commentsByFile__closures,
6114
- cf: $filesByRepo__closures,
6115
- by: $si__input_sessions_0_title && $input_sessions_0_title__closures,
6116
- bz: $si__input_sessions_0_agent && $input_sessions_0_agent__closures,
6117
- c5: $sending__closures,
6118
- bx: $si__input_sessions && $input_sessions__closures,
6119
- c6: $sendTarget__closures,
6120
- ca: $collapsedRepos__closures,
6121
- c2: $draft__closures,
6122
- cj: $saveComment2__closures,
6123
- ck: $removeComment2__closures,
6124
- ci: $toggleViewed2__closures,
6125
- cc: $repoList_length__closures
6081
+ a3: input.workspaceId,
6082
+ a4: input.active,
6083
+ a5: input.sessions,
6084
+ a7: input.onSent,
6085
+ a8: input.onExit,
6086
+ a9: input.sessions?.[0]?.title,
6087
+ aa: input.sessions?.[0]?.agent,
6088
+ ab: repos,
6089
+ ac: comments,
6090
+ ae: viewed,
6091
+ ag: viewed?.size,
6092
+ ah: draft,
6093
+ aj: error,
6094
+ ak: loading,
6095
+ am: copied,
6096
+ an: sending,
6097
+ ao: sendTarget,
6098
+ aq: fileFilter,
6099
+ ar: baseRef,
6100
+ at: treeOpen,
6101
+ aw: collapsedDirs,
6102
+ ax: collapsedRepos,
6103
+ ay: toggleRepo,
6104
+ b0: nearBox.cbs,
6105
+ b1: nearBox.io,
6106
+ b3: observeNear,
6107
+ b4: load,
6108
+ b5: loadReview,
6109
+ b7: repoList,
6110
+ b8: repoList.length,
6111
+ b9: allFiles,
6112
+ ba: allFiles?.length,
6113
+ bb: fileMatch,
6114
+ bd: shownFiles,
6115
+ bh: filesByRepo,
6116
+ bj: commentsByFile,
6117
+ bk: defaultBranches,
6118
+ bm: sendPick,
6119
+ bn: setBase,
6120
+ bp: toggleViewed,
6121
+ bq: saveComment,
6122
+ br: removeComment,
6123
+ bs: clearComments,
6124
+ bv: copyMarkdown,
6125
+ bw: sendTo,
6126
+ bx: jumpTo,
6127
+ ca: $collapsedDirs__closures,
6128
+ c1: $viewed__closures,
6129
+ ch: $commentsByFile__closures,
6130
+ cg: $filesByRepo__closures,
6131
+ bz: $si__input_sessions_0_title && $input_sessions_0_title__closures,
6132
+ c0: $si__input_sessions_0_agent && $input_sessions_0_agent__closures,
6133
+ c6: $sending__closures,
6134
+ by: $si__input_sessions && $input_sessions__closures,
6135
+ c7: $sendTarget__closures,
6136
+ cb: $collapsedRepos__closures,
6137
+ c3: $draft__closures,
6138
+ ck: $saveComment2__closures,
6139
+ cl: $removeComment2__closures,
6140
+ cj: $toggleViewed2__closures,
6141
+ cd: $repoList_length__closures
6126
6142
  });
6127
6143
  _resume_branch($scope0_id);
6128
6144
  });
@@ -6500,7 +6516,7 @@ var usage_stats_default = _template("n", (input) => {
6500
6516
  //#region src/tags/work-view.marko
6501
6517
  var api$1;
6502
6518
  var work_view_default = _template("o", (input) => {
6503
- const $scope0_reason = _scope_reason(), $sg__input_agents = _serialize_guard($scope0_reason, 8), $sg__input_workspace = _serialize_guard($scope0_reason, 2), $si__input_workspace = _serialize_if($scope0_reason, 2), $sg__input_preferred = _serialize_guard($scope0_reason, 5), $si__input_active = _serialize_if($scope0_reason, 4), $si__input_agents = _serialize_if($scope0_reason, 8), $si__input_preferred = _serialize_if($scope0_reason, 5);
6519
+ const $scope0_reason = _scope_reason(), $sg__input_agents = _serialize_guard($scope0_reason, 8), $sg__input_workspace = _serialize_guard($scope0_reason, 2), $si__input_workspace = _serialize_if($scope0_reason, 2), $si__input_active = _serialize_if($scope0_reason, 4), $si__input_agents = _serialize_if($scope0_reason, 8), $si__input_preferred = _serialize_if($scope0_reason, 5);
6504
6520
  const $scope0_id = _scope_id();
6505
6521
  const $input_active__closures = /* @__PURE__ */ new Set();
6506
6522
  const $input_agents__closures = /* @__PURE__ */ new Set();
@@ -6512,12 +6528,14 @@ var work_view_default = _template("o", (input) => {
6512
6528
  const $closeSession2__closures = /* @__PURE__ */ new Set();
6513
6529
  const $newSession2__closures = /* @__PURE__ */ new Set();
6514
6530
  const $input_preferred__closures = /* @__PURE__ */ new Set();
6531
+ const $spawning__closures = /* @__PURE__ */ new Set();
6515
6532
  let sessions = null;
6516
6533
  let tab = null;
6517
6534
  let view = "term";
6518
6535
  let drawerOpen = false;
6519
6536
  let usageOpen = false;
6520
6537
  let error = null;
6538
+ let spawning = false;
6521
6539
  let renaming = null;
6522
6540
  const ws = input.workspace;
6523
6541
  const shownSessions = sessions ?? input.allStatus?.[ws.id]?.sessions ?? null;
@@ -6528,6 +6546,7 @@ var work_view_default = _template("o", (input) => {
6528
6546
  return shownSessions?.[0]?.id ?? null;
6529
6547
  })();
6530
6548
  const createSession = _resume(async (agent, select) => {
6549
+ spawning = true;
6531
6550
  try {
6532
6551
  const session = await api$1(`/api/workspaces/${ws.id}/sessions`, {
6533
6552
  method: "POST",
@@ -6542,6 +6561,8 @@ var work_view_default = _template("o", (input) => {
6542
6561
  } catch (err) {
6543
6562
  error = String(err.message || err);
6544
6563
  return null;
6564
+ } finally {
6565
+ spawning = false;
6545
6566
  }
6546
6567
  }, "o0", $scope0_id);
6547
6568
  const loadMem = {
@@ -6767,9 +6788,9 @@ var work_view_default = _template("o", (input) => {
6767
6788
  _if(() => {
6768
6789
  if (!shownSessions.length) {
6769
6790
  const $scope3_id = _scope_id();
6770
- _html(`<div class=empty-sess><p class=dim>No sessions in this workspace.</p><button class="btn primary">Start ${_sep($sg__input_preferred)}${_escape(input.preferred || "claude")}${_el_resume($scope3_id, "b", $sg__input_preferred)}</button>${_el_resume($scope3_id, "a")}</div>`);
6791
+ _html(`<div class=empty-sess><p class=dim>No sessions in this workspace.</p><button class="btn primary"${_attr("disabled", spawning)}>${spawning ? "Starting…" : `Start ${_escape(`${input.preferred || "claude"}`)}`}${_el_resume($scope3_id, "b")}</button>${_el_resume($scope3_id, "a")}</div>`);
6771
6792
  _script($scope3_id, "o29");
6772
- _subscribe($si__input_preferred && $input_preferred__closures, writeScope($scope3_id, {}));
6793
+ _subscribe($spawning__closures, _subscribe($si__input_preferred && $input_preferred__closures, writeScope($scope3_id, {})));
6773
6794
  return 0;
6774
6795
  }
6775
6796
  }, $scope1_id, "b", 1, 1, 1, 0, 1);
@@ -6796,7 +6817,6 @@ var work_view_default = _template("o", (input) => {
6796
6817
  _if(() => {
6797
6818
  if (renaming) {
6798
6819
  const $scope6_id = _scope_id();
6799
- _set_serialize_reason(4);
6800
6820
  const $childScope4 = _peek_scope_id();
6801
6821
  prompt_dialog_default({
6802
6822
  label: "Rename session",
@@ -6832,36 +6852,38 @@ var work_view_default = _template("o", (input) => {
6832
6852
  y: view,
6833
6853
  a0: drawerOpen,
6834
6854
  a2: error,
6835
- a4: renaming?.title,
6836
- a5: renaming?.agent,
6837
- a6: renaming?.id,
6838
- a8: ws?.id,
6839
- ad: ws?.status,
6840
- ae: ws?.name,
6841
- af: shownSessions,
6842
- ah: shownSessions?.length,
6843
- ai: curTab,
6844
- ak: createSession,
6845
- an: loadMem.wanted,
6846
- ap: loadMem.run,
6847
- aq: loadBody,
6848
- as: loadSessions,
6849
- au: closeSession,
6850
- av: renameSession,
6851
- aw: newSession,
6852
- ax: promptRename,
6855
+ a3: spawning,
6856
+ a5: renaming?.title,
6857
+ a6: renaming?.agent,
6858
+ a7: renaming?.id,
6859
+ a9: ws?.id,
6860
+ ae: ws?.status,
6861
+ af: ws?.name,
6862
+ ag: shownSessions,
6863
+ ai: shownSessions?.length,
6864
+ aj: curTab,
6865
+ al: createSession,
6866
+ ao: loadMem.wanted,
6867
+ aq: loadMem.run,
6868
+ ar: loadBody,
6869
+ at: loadSessions,
6870
+ av: closeSession,
6871
+ aw: renameSession,
6872
+ ax: newSession,
6873
+ ay: promptRename,
6853
6874
  a: _existing_scope($childScope),
6854
6875
  d: _existing_scope($childScope2),
6855
- ay: $si__input_active && $input_active__closures,
6856
- b0: $si__input_agents && $input_agents__closures,
6857
- b1: $view__closures,
6858
- b6: $si__input_workspace && $ws_id__closures,
6859
- b7: $si__input_workspace && $ws_name__closures,
6860
- b8: $shownSessions__closures,
6861
- ba: $curTab__closures,
6862
- bb: $closeSession2__closures,
6863
- bd: $newSession2__closures,
6864
- az: $si__input_preferred && $input_preferred__closures
6876
+ az: $si__input_active && $input_active__closures,
6877
+ b1: $si__input_agents && $input_agents__closures,
6878
+ b2: $view__closures,
6879
+ b8: $si__input_workspace && $ws_id__closures,
6880
+ b9: $si__input_workspace && $ws_name__closures,
6881
+ ba: $shownSessions__closures,
6882
+ bc: $curTab__closures,
6883
+ bd: $closeSession2__closures,
6884
+ bf: $newSession2__closures,
6885
+ b0: $si__input_preferred && $input_preferred__closures,
6886
+ b4: $spawning__closures
6865
6887
  });
6866
6888
  _resume_branch($scope0_id);
6867
6889
  });
@@ -6873,6 +6895,7 @@ var prefs;
6873
6895
  var _page_default = _template("b", (input) => {
6874
6896
  _scope_reason();
6875
6897
  const $scope0_id = _scope_id();
6898
+ const $error__closures = /* @__PURE__ */ new Set();
6876
6899
  const $workspaces__closures = /* @__PURE__ */ new Set();
6877
6900
  const $status__closures = /* @__PURE__ */ new Set();
6878
6901
  const $settings__closures = /* @__PURE__ */ new Set();
@@ -6891,23 +6914,27 @@ var _page_default = _template("b", (input) => {
6891
6914
  let paletteOpen = false;
6892
6915
  let error = null;
6893
6916
  const load = _resume(async () => {
6894
- const [list] = await Promise.all([api("/api/workspaces"), prefs.sync()]);
6895
- workspaces = list;
6896
- if (!loaded) {
6897
- const last = prefs.lastWorkspace();
6898
- if (last && list.some((ws) => ws.id === last)) {
6899
- selectedId = last;
6900
- openIds = [last];
6901
- }
6902
- } else {
6903
- const activeIds = new Set(list.filter((ws) => ws.status === "active").map((ws) => ws.id));
6904
- openIds = openIds.filter((id) => activeIds.has(id));
6905
- if (selectedId && !activeIds.has(selectedId)) {
6906
- selectedId = openIds[openIds.length - 1] || null;
6907
- prefs.setLastWorkspace(selectedId);
6917
+ try {
6918
+ const [list] = await Promise.all([api("/api/workspaces"), prefs.sync()]);
6919
+ workspaces = list;
6920
+ if (!loaded) {
6921
+ const last = prefs.lastWorkspace();
6922
+ if (last && list.some((ws) => ws.id === last)) {
6923
+ selectedId = last;
6924
+ openIds = [last];
6925
+ }
6926
+ } else {
6927
+ const activeIds = new Set(list.filter((ws) => ws.status === "active").map((ws) => ws.id));
6928
+ openIds = openIds.filter((id) => activeIds.has(id));
6929
+ if (selectedId && !activeIds.has(selectedId)) {
6930
+ selectedId = openIds[openIds.length - 1] || null;
6931
+ prefs.setLastWorkspace(selectedId);
6932
+ }
6908
6933
  }
6934
+ loaded = true;
6935
+ } catch (err) {
6936
+ error = `Loading workspaces failed: ${err.message || String(err)}`;
6909
6937
  }
6910
- loaded = true;
6911
6938
  }, "b0", $scope0_id);
6912
6939
  const statusMem = {
6913
6940
  run: void 0,
@@ -6945,7 +6972,7 @@ var _page_default = _template("b", (input) => {
6945
6972
  const showInlinePalette = !creating && !selected && loaded;
6946
6973
  _html("<main>");
6947
6974
  _if(() => {
6948
- if (error) {
6975
+ if (error && loaded) {
6949
6976
  const $scope6_id = _scope_id();
6950
6977
  _html(`<p class=toast-error>${_escape(error)}${_el_resume($scope6_id, "a")} <button>×</button>${_el_resume($scope6_id, "b")}</p>`);
6951
6978
  _script($scope6_id, "b18");
@@ -6956,7 +6983,21 @@ var _page_default = _template("b", (input) => {
6956
6983
  _if(() => {
6957
6984
  if (!loaded) {
6958
6985
  const $scope7_id = _scope_id();
6959
- _html("<div class=\"boot dim\"><span class=spin></span>Loading workspaces…</div>");
6986
+ _html("<div class=\"boot dim\">");
6987
+ _if(() => {
6988
+ if (error) {
6989
+ const $scope8_id = _scope_id();
6990
+ _html(`<p>${_escape(error)}${_el_resume($scope8_id, "a")}</p><button class=btn>Retry</button>${_el_resume($scope8_id, "b")}`);
6991
+ _script($scope8_id, "b19");
6992
+ _subscribe($error__closures, writeScope($scope8_id, {}));
6993
+ return 0;
6994
+ } else {
6995
+ const $scope9_id = _scope_id();
6996
+ _html("<span class=spin></span>Loading workspaces…");
6997
+ writeScope($scope9_id, {});
6998
+ return 1;
6999
+ }
7000
+ }, $scope7_id, "a", 1, 1, 1, "</div>");
6960
7001
  writeScope($scope7_id, {});
6961
7002
  return 0;
6962
7003
  }
@@ -6983,6 +7024,7 @@ var _page_default = _template("b", (input) => {
6983
7024
  openWorkspace(ws.id);
6984
7025
  }, "b5", $scope1_id),
6985
7026
  onNewSession: _resume(function(ws, agent) {
7027
+ paletteOpen = false;
6986
7028
  api(`/api/workspaces/${ws.id}/sessions`, {
6987
7029
  method: "POST",
6988
7030
  headers: { "content-type": "application/json" },
@@ -7091,7 +7133,7 @@ var _page_default = _template("b", (input) => {
7091
7133
  });
7092
7134
  }, (id) => id, $scope0_id, "f");
7093
7135
  _html("</main>");
7094
- _script($scope0_id, "b19");
7136
+ _script($scope0_id, "b20");
7095
7137
  writeScope($scope0_id, {
7096
7138
  g: workspaces,
7097
7139
  h: status,
@@ -7103,21 +7145,22 @@ var _page_default = _template("b", (input) => {
7103
7145
  q: managingId,
7104
7146
  s: paletteOpen,
7105
7147
  t: error,
7106
- u: load,
7107
- w: statusMem.fresh,
7108
- x: statusMem.run,
7109
- z: loadStatus,
7110
- a0: openWorkspace,
7111
- a2: selected,
7112
- a4: managing,
7113
- a5: showInlinePalette,
7114
- a7: $workspaces__closures,
7115
- a8: $status__closures,
7116
- a9: $settings__closures,
7117
- aa: $selectedId__closures,
7118
- ab: $creating__closures,
7119
- ae: $openWorkspace2__closures,
7120
- af: $managing__closures
7148
+ v: load,
7149
+ x: statusMem.fresh,
7150
+ y: statusMem.run,
7151
+ a0: loadStatus,
7152
+ a1: openWorkspace,
7153
+ a3: selected,
7154
+ a5: managing,
7155
+ a6: showInlinePalette,
7156
+ ae: $error__closures,
7157
+ a8: $workspaces__closures,
7158
+ a9: $status__closures,
7159
+ aa: $settings__closures,
7160
+ ab: $selectedId__closures,
7161
+ ac: $creating__closures,
7162
+ af: $openWorkspace2__closures,
7163
+ ag: $managing__closures
7121
7164
  });
7122
7165
  _resume_branch($scope0_id);
7123
7166
  });
@@ -13078,8 +13121,14 @@ function setScrapedPhase(sessionId, phase, blockerText) {
13078
13121
  reasons.set(sessionId, "attention");
13079
13122
  if (blockerText) scrapedSummaries.set(sessionId, blockerText);
13080
13123
  } else scrapedSummaries.delete(sessionId);
13081
- if (scraped.get(sessionId) === phase) return;
13124
+ const stalePin = phase === "working" && phases.get(sessionId) === "waiting" && (reasons.get(sessionId) === "done" || scraped.get(sessionId) === "waiting");
13125
+ if (scraped.get(sessionId) === phase && !stalePin) return;
13082
13126
  applyChange(sessionId, () => {
13127
+ if (stalePin) {
13128
+ phases.delete(sessionId);
13129
+ summaries.delete(sessionId);
13130
+ reasons.delete(sessionId);
13131
+ }
13083
13132
  if (phase) scraped.set(sessionId, phase);
13084
13133
  else scraped.delete(sessionId);
13085
13134
  });
@@ -13726,8 +13775,8 @@ function hydrate(ws) {
13726
13775
  return ws;
13727
13776
  }
13728
13777
  async function createWorkspace(name, repos) {
13778
+ if (!name.trim()) throw new Error("workspace name required");
13729
13779
  const slug = slugify(name);
13730
- if (!slug) throw new Error("workspace name required");
13731
13780
  const id = randomId();
13732
13781
  const dir = path.join(config.workRoot, `${slug}-${id}`);
13733
13782
  const branch = `${config.branchPrefix}-${slug}-${id}`;
@@ -13836,9 +13885,14 @@ async function removeRepo(workspaceId, worktree) {
13836
13885
  ], bare).catch(() => {});
13837
13886
  });
13838
13887
  db.prepare("DELETE FROM repos WHERE workspace_id = ? AND worktree = ?").run(workspaceId, worktree);
13888
+ db.prepare("DELETE FROM review_comments WHERE workspace_id = ? AND worktree = ?").run(workspaceId, worktree);
13889
+ db.prepare("DELETE FROM review_viewed WHERE workspace_id = ? AND key GLOB ? || '/*'").run(workspaceId, worktree);
13839
13890
  const updated = getWorkspace(workspaceId);
13840
- writeAgentsMd(ws.path, ws.branch, updated.repos);
13891
+ try {
13892
+ writeAgentsMd(ws.path, ws.branch, updated.repos);
13893
+ } catch {}
13841
13894
  publish("workspaces.changed");
13895
+ publish("review.changed", { workspaceId });
13842
13896
  return updated;
13843
13897
  }
13844
13898
  async function setWorkspaceStatus(id, status) {
@@ -13986,8 +14040,12 @@ async function workspaceBranches(bare, branch, exclude) {
13986
14040
  const owns = (ref, b) => ref === b || ref.startsWith(`${b}-`);
13987
14041
  return out.split("\n").filter((b) => owns(b, branch) && !exclude.some((x) => owns(b, x)));
13988
14042
  }
14043
+ /** Directory/branch-safe prefix for a workspace name. Decomposing first keeps
14044
+ * accented Latin readable (é → e); a name with nothing ASCII left (another
14045
+ * script, emoji) falls back to a generic prefix — the random id is what makes
14046
+ * the name unique, so the slug never has to be rejected. */
13989
14047
  function slugify(name) {
13990
- return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
14048
+ return name.normalize("NFKD").replace(/\p{M}+/gu, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "ws";
13991
14049
  }
13992
14050
  function randomId() {
13993
14051
  return Math.random().toString(36).slice(2, 8);
@@ -15385,16 +15443,18 @@ async function scan() {
15385
15443
  "-a",
15386
15444
  "-F",
15387
15445
  "#{session_name} #{pane_title}"
15388
- ]).catch(() => "");
15446
+ ]).catch(() => null);
15447
+ if (out === null) return false;
15389
15448
  for (const line of out.split("\n")) {
15390
15449
  const [name, ...title] = line.split(" ");
15391
15450
  if (name?.startsWith("wk-")) panes.set(name.slice(3), title.join(" "));
15392
15451
  }
15393
- await Promise.all(sessions.map(async (session) => {
15394
- if (!panes.has(session.id)) {
15395
- setScrapedPhase(session.id, void 0);
15396
- return;
15397
- }
15452
+ for (const session of sessions) {
15453
+ if (panes.has(session.id)) continue;
15454
+ clearAgentPhase(session.id);
15455
+ }
15456
+ const live = sessions.filter((session) => panes.has(session.id));
15457
+ await Promise.all(live.map(async (session) => {
15398
15458
  const screen = await tmux([
15399
15459
  "capture-pane",
15400
15460
  "-p",
@@ -15409,7 +15469,7 @@ async function scan() {
15409
15469
  if (result.skip) return;
15410
15470
  setScrapedPhase(session.id, result.state === "working" ? "working" : result.state === "blocked" ? "waiting" : void 0, result.blockerText && blockerSummary(result.blockerText));
15411
15471
  }));
15412
- return true;
15472
+ return live.length > 0;
15413
15473
  }
15414
15474
  /** Human-readable line(s) from a blocker region: the question the agent is
15415
15475
  * asking, with box borders, option lists, and hint bars stripped. */
@@ -15559,7 +15619,10 @@ async function refreshPrsBatch(fullNames, force = false) {
15559
15619
  const [owner, name] = fullName.split("/");
15560
15620
  return `r${i}: repository(owner: ${JSON.stringify(owner)}, name: ${JSON.stringify(name)}) { pullRequests(first: 50, orderBy: {field: UPDATED_AT, direction: DESC}) { nodes { number title url headRefName isDraft state reviewDecision } } }`;
15561
15621
  }).join(" ") + "}"}`
15562
- ]);
15622
+ ]).catch((err) => {
15623
+ if (!err.stdout) throw err;
15624
+ return err.stdout;
15625
+ });
15563
15626
  const data = JSON.parse(out).data;
15564
15627
  if (!data) throw new Error("graphql response without data");
15565
15628
  names.forEach((fullName, i) => {
@@ -15606,7 +15669,11 @@ async function freshenBaseRefs(dir, fullName, refs) {
15606
15669
  "origin",
15607
15670
  ref
15608
15671
  ], dir).catch(() => {}));
15609
- await Promise.race([Promise.all(fetches), new Promise((resolve) => setTimeout(resolve, FETCH_WAIT_MS))]);
15672
+ let timer;
15673
+ await Promise.race([Promise.all(fetches), new Promise((resolve) => {
15674
+ timer = setTimeout(resolve, FETCH_WAIT_MS);
15675
+ })]);
15676
+ clearTimeout(timer);
15610
15677
  }
15611
15678
  /** The ref the working tree is compared against by default, best first:
15612
15679
  * the workspace branch's remote (a lane worktree then shows its whole
@@ -15639,7 +15706,8 @@ async function resolveBase(dir, wsBranch, baseBranch, baseRef) {
15639
15706
  } catch {}
15640
15707
  return {
15641
15708
  mergeBase: "HEAD",
15642
- label: baseRef || baseBranch
15709
+ label: baseRef || baseBranch,
15710
+ missing: true
15643
15711
  };
15644
15712
  }
15645
15713
  /** Changed files per repo: merge-base of a base ref vs the working tree.
@@ -15657,7 +15725,7 @@ async function workspaceDiff(ws, baseRef) {
15657
15725
  ...branch !== "HEAD" ? [branch] : [],
15658
15726
  ...baseRef ? [baseRef] : [repo.base_branch]
15659
15727
  ]);
15660
- const { mergeBase, label } = await resolveBase(dir, ws.branch, repo.base_branch, baseRef);
15728
+ const { mergeBase, label, missing } = await resolveBase(dir, ws.branch, repo.base_branch, baseRef);
15661
15729
  const [nameStatus, untracked] = await Promise.all([git([
15662
15730
  "diff",
15663
15731
  "--name-status",
@@ -15688,6 +15756,7 @@ async function workspaceDiff(ws, baseRef) {
15688
15756
  full_name: repo.full_name,
15689
15757
  base: label,
15690
15758
  default_branch: repo.default_branch,
15759
+ ...missing && { baseMissing: true },
15691
15760
  files
15692
15761
  };
15693
15762
  }));
@@ -15695,8 +15764,8 @@ async function workspaceDiff(ws, baseRef) {
15695
15764
  /** Count of changed files vs the default base's merge-base (incl.
15696
15765
  * untracked) — same notion of "changed" as the diff view's default. */
15697
15766
  async function changedFileCount(dir, wsBranch, baseBranch) {
15698
- const { mergeBase } = await resolveBase(dir, wsBranch, baseBranch);
15699
- if (mergeBase === "HEAD") return 0;
15767
+ const { mergeBase, missing } = await resolveBase(dir, wsBranch, baseBranch);
15768
+ if (missing) return 0;
15700
15769
  const [changed, untracked] = await Promise.all([git([
15701
15770
  "diff",
15702
15771
  "--name-only",
@@ -15873,22 +15942,21 @@ async function computeStatus() {
15873
15942
  const workspaces = listWorkspaces().filter((ws) => ws.status === "active");
15874
15943
  const paths = new Map(workspaces.map((ws) => [ws.id, ws.path]));
15875
15944
  const [ports, states] = await Promise.all([portsByWorkspace(paths), sessionStates()]);
15876
- const result = {};
15877
15945
  const allBranches = listWorkspaces().map((w) => ({
15878
15946
  id: w.id,
15879
15947
  branch: w.branch
15880
15948
  }));
15881
- await Promise.all(workspaces.map(async (ws) => {
15949
+ const entries = await Promise.all(workspaces.map(async (ws) => {
15882
15950
  const foreign = allBranches.filter((w) => w.id !== ws.id).map((w) => w.branch);
15883
15951
  const statuses = await Promise.all(ws.repos.map((repo) => repoStatus(ws, repo, foreign)));
15884
- result[ws.id] = {
15952
+ return [ws.id, {
15885
15953
  ports: ports.get(ws.id) || [],
15886
15954
  repos: statuses.map((s) => s.status),
15887
15955
  ...sessionCounts(ws.id, states),
15888
15956
  changes: statuses.reduce((sum, s) => sum + s.changed, 0)
15889
- };
15957
+ }];
15890
15958
  }));
15891
- return result;
15959
+ return Object.fromEntries(entries);
15892
15960
  }
15893
15961
  async function repoStatus(ws, repo, foreign) {
15894
15962
  const dir = path.join(ws.path, repo.worktree);
@@ -15945,39 +16013,50 @@ var PADDING = `: ${" ".repeat(2048)}\n\n`;
15945
16013
  /** Heartbeat cadence: keeps intermediaries from idling the stream out and
15946
16014
  * lets the client detect a dead/buffered stream and fall back to polling. */
15947
16015
  var PING_MS = 15e3;
16016
+ var SSE_HEADERS = {
16017
+ "content-type": "text/event-stream",
16018
+ "cache-control": "no-store, no-transform",
16019
+ "x-accel-buffering": "no"
16020
+ };
15948
16021
  //#endregion
15949
16022
  //#region __marko-run__api.events.js
15950
16023
  var getHandler$14 = normalizeHandler(Run.GET((ctx) => {
16024
+ if (ctx.request.method === "HEAD") return new Response(null, { headers: SSE_HEADERS });
15951
16025
  const encoder = new TextEncoder();
15952
- const stream = new ReadableStream({ start(controller) {
15953
- controller.enqueue(encoder.encode(`retry: 3000\n${PADDING}event: hello\ndata: ${JSON.stringify({ boot: BOOT_ID })}\n\n`));
15954
- const ping = setInterval(() => {
15955
- try {
15956
- controller.enqueue(encoder.encode(`event: ping\ndata: 1\n\n`));
15957
- } catch {
15958
- clearInterval(ping);
15959
- }
15960
- }, PING_MS);
15961
- const unsubscribe = subscribe((event) => {
15962
- try {
15963
- controller.enqueue(encoder.encode(`event: ${event.type}\ndata: ${JSON.stringify(event.data ?? null)}\n\n`));
15964
- } catch {
16026
+ let cleanup = () => {};
16027
+ const stream = new ReadableStream({
16028
+ start(controller) {
16029
+ controller.enqueue(encoder.encode(`retry: 3000\n${PADDING}event: hello\ndata: ${JSON.stringify({ boot: BOOT_ID })}\n\n`));
16030
+ const ping = setInterval(() => {
16031
+ try {
16032
+ controller.enqueue(encoder.encode(`event: ping\ndata: 1\n\n`));
16033
+ } catch {
16034
+ clearInterval(ping);
16035
+ }
16036
+ }, PING_MS);
16037
+ const unsubscribe = subscribe((event) => {
16038
+ try {
16039
+ controller.enqueue(encoder.encode(`event: ${event.type}\ndata: ${JSON.stringify(event.data ?? null)}\n\n`));
16040
+ } catch {
16041
+ unsubscribe();
16042
+ }
16043
+ });
16044
+ cleanup = () => {
15965
16045
  unsubscribe();
15966
- }
15967
- });
15968
- ctx.request.signal.addEventListener("abort", () => {
15969
- unsubscribe();
15970
- clearInterval(ping);
15971
- try {
15972
- controller.close();
15973
- } catch {}
15974
- });
15975
- } });
15976
- return new Response(stream, { headers: {
15977
- "content-type": "text/event-stream",
15978
- "cache-control": "no-store, no-transform",
15979
- "x-accel-buffering": "no"
15980
- } });
16046
+ clearInterval(ping);
16047
+ };
16048
+ ctx.request.signal.addEventListener("abort", () => {
16049
+ cleanup();
16050
+ try {
16051
+ controller.close();
16052
+ } catch {}
16053
+ });
16054
+ },
16055
+ cancel() {
16056
+ cleanup();
16057
+ }
16058
+ });
16059
+ return new Response(stream, { headers: SSE_HEADERS });
15981
16060
  }), "GET");
15982
16061
  var get4_options = mergeOptions(mware3, getHandler$14);
15983
16062
  var head4_options = mergeOptions(mware3);
@@ -16133,12 +16212,16 @@ function readDiskCache() {
16133
16212
  }
16134
16213
  }
16135
16214
  async function fetchCatalog() {
16215
+ let partial = false;
16136
16216
  const orgs = (await gh([
16137
16217
  "api",
16138
16218
  "user/orgs",
16139
16219
  "--jq",
16140
16220
  ".[].login"
16141
- ]).catch(() => "")).split("\n").filter(Boolean);
16221
+ ]).catch(() => {
16222
+ partial = true;
16223
+ return "";
16224
+ })).split("\n").filter(Boolean);
16142
16225
  const lists = await Promise.all([void 0, ...orgs].map((owner) => gh([
16143
16226
  "repo",
16144
16227
  "list",
@@ -16147,7 +16230,10 @@ async function fetchCatalog() {
16147
16230
  "500",
16148
16231
  "--json",
16149
16232
  "nameWithOwner,defaultBranchRef,isArchived"
16150
- ]).catch(() => "[]")));
16233
+ ]).catch(() => {
16234
+ partial = true;
16235
+ return "[]";
16236
+ })));
16151
16237
  const byName = /* @__PURE__ */ new Map();
16152
16238
  for (const out of lists) for (const r of JSON.parse(out)) byName.set(r.nameWithOwner, {
16153
16239
  nameWithOwner: r.nameWithOwner,
@@ -16159,6 +16245,10 @@ async function fetchCatalog() {
16159
16245
  fetchedAt: Date.now(),
16160
16246
  repos
16161
16247
  };
16248
+ if (partial) {
16249
+ if (readDiskCache()) throw new Error("gh repo listing failed");
16250
+ return catalog;
16251
+ }
16162
16252
  const tmp = cachePath() + ".tmp";
16163
16253
  fs.writeFileSync(tmp, JSON.stringify(catalog));
16164
16254
  fs.renameSync(tmp, cachePath());
@@ -20916,6 +21006,7 @@ function attachTermServer(server) {
20916
21006
  if (!wsPath) return ws.close(4004, "unknown workspace");
20917
21007
  const cols = Number(url.searchParams.get("cols")) || 80;
20918
21008
  const rows = Number(url.searchParams.get("rows")) || 24;
21009
+ const connectedVisible = url.searchParams.get("visible") !== "0";
20919
21010
  const proc = pty.spawn("tmux", [
20920
21011
  "-L",
20921
21012
  TMUX_SOCKET,
@@ -20961,10 +21052,11 @@ function attachTermServer(server) {
20961
21052
  flushTimer = setTimeout(flush, Date.now() - lastSend >= FLUSH_MS ? 1 : FLUSH_MS);
20962
21053
  });
20963
21054
  proc.onExit(() => ws.close());
20964
- let visible = true;
20965
- trackViewer(session.id, 1);
21055
+ let visible = connectedVisible;
21056
+ if (visible) trackViewer(session.id, 1);
20966
21057
  let dims = [cols, rows];
20967
21058
  const forceWindowSize = () => {
21059
+ if (!visible) return;
20968
21060
  lastForced.set(session.id, `${dims[0]}x${dims[1]}`);
20969
21061
  tmux([
20970
21062
  "resize-window",
@@ -20986,7 +21078,9 @@ function attachTermServer(server) {
20986
21078
  const resize = parseResize(text);
20987
21079
  if (resize) {
20988
21080
  dims = resize;
20989
- proc.resize(resize[0], resize[1]);
21081
+ try {
21082
+ proc.resize(resize[0], resize[1]);
21083
+ } catch {}
20990
21084
  forceWindowSize();
20991
21085
  }
20992
21086
  const vis = parseVisible(text);
@@ -21072,4 +21166,4 @@ server.listen(port, () => {
21072
21166
  //#endregion
21073
21167
  export {};
21074
21168
 
21075
- ;var __MARKO_MANIFEST__={"esfPH6H":{"block":[2,"stylesheet#/assets/index-KIy0rCx1.css",6,"<link",0," rel=\"stylesheet\" crossorigin href=\"",1,"assets/index-KIy0rCx1.css\"",">"],"defer":[2,"/assets/index-BAGH9WA4.js",6,"<script",0," async type=\"module\" crossorigin src=\"",1,"assets/index-BAGH9WA4.js\"","></script>"]}};
21169
+ ;var __MARKO_MANIFEST__={"esfPH6H":{"block":[2,"stylesheet#/assets/index-KIy0rCx1.css",6,"<link",0," rel=\"stylesheet\" crossorigin href=\"",1,"assets/index-KIy0rCx1.css\"",">"],"defer":[2,"/assets/index-BwlA-lgI.js",6,"<script",0," async type=\"module\" crossorigin src=\"",1,"assets/index-BwlA-lgI.js\"","></script>"]}};