@ondrej-svec/hog 1.21.1 → 1.22.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.
package/dist/cli.js CHANGED
@@ -2896,7 +2896,8 @@ function useKeyboard({
2896
2896
  onRepoEnter,
2897
2897
  onStatusEnter,
2898
2898
  onActivityEnter,
2899
- showDetailPanel
2899
+ showDetailPanel,
2900
+ leftPanelHidden
2900
2901
  }) {
2901
2902
  const {
2902
2903
  exit,
@@ -2918,7 +2919,9 @@ function useKeyboard({
2918
2919
  handleToggleLog,
2919
2920
  handleLaunchClaude,
2920
2921
  handleEnterWorkflow,
2921
- handleEnterTriage
2922
+ handleEnterTriage,
2923
+ handleToggleLeftPanel,
2924
+ handleToggleZen
2922
2925
  } = actions;
2923
2926
  const handleInput = useCallback6(
2924
2927
  (input2, key) => {
@@ -2926,6 +2929,29 @@ function useKeyboard({
2926
2929
  ui.toggleHelp();
2927
2930
  return;
2928
2931
  }
2932
+ if (ui.state.mode === "zen") {
2933
+ if (input2 === "Z" || key.escape) {
2934
+ handleToggleZen();
2935
+ return;
2936
+ }
2937
+ if (input2 === "j" || key.downArrow) {
2938
+ nav.moveDown();
2939
+ return;
2940
+ }
2941
+ if (input2 === "k" || key.upArrow) {
2942
+ nav.moveUp();
2943
+ return;
2944
+ }
2945
+ if (input2 === "C") {
2946
+ handleLaunchClaude();
2947
+ return;
2948
+ }
2949
+ if (input2 === "q") {
2950
+ exit();
2951
+ return;
2952
+ }
2953
+ return;
2954
+ }
2929
2955
  if (key.escape && ui.state.mode !== "focus") {
2930
2956
  if (ui.state.mode === "multiSelect") {
2931
2957
  multiSelect.clear();
@@ -3039,6 +3065,9 @@ function useKeyboard({
3039
3065
  if (ui.canAct) {
3040
3066
  const digit = parseInt(input2, 10);
3041
3067
  if (!Number.isNaN(digit) && digit >= 0 && digit <= 4) {
3068
+ if (leftPanelHidden && (digit === 1 || digit === 2)) {
3069
+ return;
3070
+ }
3042
3071
  if (digit === 0 && !showDetailPanel) {
3043
3072
  ui.enterDetail();
3044
3073
  } else {
@@ -3113,6 +3142,14 @@ function useKeyboard({
3113
3142
  handleEnterFuzzyPicker();
3114
3143
  return;
3115
3144
  }
3145
+ if (input2 === "H") {
3146
+ handleToggleLeftPanel();
3147
+ return;
3148
+ }
3149
+ if (input2 === "Z") {
3150
+ handleToggleZen();
3151
+ return;
3152
+ }
3116
3153
  if (input2 === " ") {
3117
3154
  const id = nav.selectedId;
3118
3155
  if (id) {
@@ -3180,10 +3217,13 @@ function useKeyboard({
3180
3217
  handleLaunchClaude,
3181
3218
  handleEnterWorkflow,
3182
3219
  handleEnterTriage,
3183
- showDetailPanel
3220
+ handleToggleLeftPanel,
3221
+ handleToggleZen,
3222
+ showDetailPanel,
3223
+ leftPanelHidden
3184
3224
  ]
3185
3225
  );
3186
- const inputActive = ui.state.mode === "normal" || ui.state.mode === "multiSelect" || ui.state.mode === "focus" || ui.state.mode === "overlay:detail";
3226
+ const inputActive = ui.state.mode === "normal" || ui.state.mode === "multiSelect" || ui.state.mode === "focus" || ui.state.mode === "overlay:detail" || ui.state.mode === "zen";
3187
3227
  useInput(handleInput, { isActive: inputActive });
3188
3228
  const handleSearchEscape = useCallback6(
3189
3229
  (_input, key) => {
@@ -3815,6 +3855,12 @@ function uiReducer(state, action) {
3815
3855
  case "ENTER_TRIAGE":
3816
3856
  if (state.mode !== "normal") return state;
3817
3857
  return { ...state, mode: "overlay:triage", previousMode: "normal" };
3858
+ case "ENTER_ZEN":
3859
+ if (state.mode !== "normal") return state;
3860
+ return { ...state, mode: "zen", previousMode: "normal" };
3861
+ case "EXIT_ZEN":
3862
+ if (state.mode !== "zen") return state;
3863
+ return { ...state, mode: "normal", previousMode: "normal" };
3818
3864
  case "TOGGLE_HELP":
3819
3865
  return { ...state, helpVisible: !state.helpVisible };
3820
3866
  case "EXIT_OVERLAY":
@@ -3835,7 +3881,7 @@ function uiReducer(state, action) {
3835
3881
  }
3836
3882
  function canNavigate(state) {
3837
3883
  const { mode } = state;
3838
- return mode === "normal" || mode === "multiSelect" || mode === "focus";
3884
+ return mode === "normal" || mode === "multiSelect" || mode === "focus" || mode === "zen";
3839
3885
  }
3840
3886
  function canAct(state) {
3841
3887
  return state.mode === "normal";
@@ -3863,6 +3909,8 @@ function useUIState() {
3863
3909
  enterWorkflow: useCallback11(() => dispatch({ type: "ENTER_WORKFLOW" }), []),
3864
3910
  enterNudge: useCallback11(() => dispatch({ type: "ENTER_NUDGE" }), []),
3865
3911
  enterTriage: useCallback11(() => dispatch({ type: "ENTER_TRIAGE" }), []),
3912
+ enterZen: useCallback11(() => dispatch({ type: "ENTER_ZEN" }), []),
3913
+ exitZen: useCallback11(() => dispatch({ type: "EXIT_ZEN" }), []),
3866
3914
  toggleHelp: useCallback11(() => dispatch({ type: "TOGGLE_HELP" }), []),
3867
3915
  exitOverlay: useCallback11(() => dispatch({ type: "EXIT_OVERLAY" }), []),
3868
3916
  exitToNormal: useCallback11(() => dispatch({ type: "EXIT_TO_NORMAL" }), []),
@@ -3971,9 +4019,255 @@ var init_use_workflow_state = __esm({
3971
4019
  }
3972
4020
  });
3973
4021
 
4022
+ // src/board/tmux-pane.ts
4023
+ import { execFileSync as execFileSync3 } from "child_process";
4024
+ function agentWindowName(issueNumber) {
4025
+ return `claude-${issueNumber}`;
4026
+ }
4027
+ function windowExists(windowName) {
4028
+ try {
4029
+ const output = execFileSync3("tmux", ["list-windows", "-F", "#{window_name}"], {
4030
+ encoding: "utf-8",
4031
+ stdio: ["ignore", "pipe", "ignore"]
4032
+ });
4033
+ return output.split("\n").some((line) => line.trim() === windowName);
4034
+ } catch {
4035
+ return false;
4036
+ }
4037
+ }
4038
+ function joinAgentPane(windowName, widthPercent) {
4039
+ try {
4040
+ const paneId = execFileSync3(
4041
+ "tmux",
4042
+ [
4043
+ "join-pane",
4044
+ "-h",
4045
+ "-s",
4046
+ `${windowName}.0`,
4047
+ "-t",
4048
+ ".",
4049
+ "-l",
4050
+ `${widthPercent}%`,
4051
+ "-P",
4052
+ "-F",
4053
+ "#{pane_id}"
4054
+ ],
4055
+ {
4056
+ encoding: "utf-8",
4057
+ stdio: ["ignore", "pipe", "ignore"]
4058
+ }
4059
+ );
4060
+ return paneId.trim() || null;
4061
+ } catch {
4062
+ return null;
4063
+ }
4064
+ }
4065
+ function breakPane(paneId) {
4066
+ try {
4067
+ execFileSync3("tmux", ["break-pane", "-d", "-s", paneId], {
4068
+ stdio: "ignore"
4069
+ });
4070
+ } catch {
4071
+ }
4072
+ }
4073
+ function isPaneAlive(paneId) {
4074
+ try {
4075
+ const output = execFileSync3("tmux", ["list-panes", "-a", "-F", "#{pane_id}"], {
4076
+ encoding: "utf-8",
4077
+ stdio: ["ignore", "pipe", "ignore"]
4078
+ });
4079
+ return output.split("\n").some((line) => line.trim() === paneId);
4080
+ } catch {
4081
+ return false;
4082
+ }
4083
+ }
4084
+ function splitWithInfo(info, widthPercent) {
4085
+ try {
4086
+ const paneId = execFileSync3(
4087
+ "tmux",
4088
+ [
4089
+ "split-window",
4090
+ "-h",
4091
+ "-l",
4092
+ `${widthPercent}%`,
4093
+ "-d",
4094
+ "-P",
4095
+ "-F",
4096
+ "#{pane_id}",
4097
+ "printf",
4098
+ "Issue: %s\\n\\nURL: %s\\n\\nNo Claude Code session active.\\nPress C to launch one.\\n",
4099
+ info.title,
4100
+ info.url
4101
+ ],
4102
+ {
4103
+ encoding: "utf-8",
4104
+ stdio: ["ignore", "pipe", "ignore"]
4105
+ }
4106
+ );
4107
+ return paneId.trim() || null;
4108
+ } catch {
4109
+ return null;
4110
+ }
4111
+ }
4112
+ function killPane(paneId) {
4113
+ try {
4114
+ execFileSync3("tmux", ["kill-pane", "-t", paneId], {
4115
+ stdio: "ignore"
4116
+ });
4117
+ } catch {
4118
+ }
4119
+ }
4120
+ var init_tmux_pane = __esm({
4121
+ "src/board/tmux-pane.ts"() {
4122
+ "use strict";
4123
+ }
4124
+ });
4125
+
4126
+ // src/board/hooks/use-zen-mode.ts
4127
+ import { useCallback as useCallback13, useEffect as useEffect5, useRef as useRef11, useState as useState7 } from "react";
4128
+ function findIssue(repos, selectedId) {
4129
+ if (!selectedId?.startsWith("gh:")) return null;
4130
+ for (const rd of repos) {
4131
+ for (const issue of rd.issues) {
4132
+ if (`gh:${rd.repo.name}:${issue.number}` === selectedId)
4133
+ return { issue, repoName: rd.repo.name };
4134
+ }
4135
+ }
4136
+ return null;
4137
+ }
4138
+ function cleanupPane(paneId, isAgent) {
4139
+ if (isAgent) {
4140
+ breakPane(paneId);
4141
+ } else {
4142
+ killPane(paneId);
4143
+ }
4144
+ }
4145
+ function openOrSplitPane(issue) {
4146
+ const winName = agentWindowName(issue.number);
4147
+ const hasAgent = windowExists(winName);
4148
+ if (hasAgent) {
4149
+ const paneId2 = joinAgentPane(winName, ZEN_PANE_WIDTH_PERCENT);
4150
+ return paneId2 ? { paneId: paneId2, isAgent: true } : null;
4151
+ }
4152
+ const paneId = splitWithInfo({ title: issue.title, url: issue.url }, ZEN_PANE_WIDTH_PERCENT);
4153
+ return paneId ? { paneId, isAgent: false } : null;
4154
+ }
4155
+ function useZenMode({
4156
+ ui,
4157
+ toast,
4158
+ termCols,
4159
+ repos,
4160
+ selectedId
4161
+ }) {
4162
+ const [zenPaneId, setZenPaneId] = useState7(null);
4163
+ const [zenIsAgentPane, setZenIsAgentPane] = useState7(false);
4164
+ const paneRef = useRef11({
4165
+ id: null,
4166
+ isAgent: false
4167
+ });
4168
+ paneRef.current = { id: zenPaneId, isAgent: zenIsAgentPane };
4169
+ const exitZen = useCallback13(() => {
4170
+ const { id, isAgent } = paneRef.current;
4171
+ if (id) {
4172
+ cleanupPane(id, isAgent);
4173
+ setZenPaneId(null);
4174
+ setZenIsAgentPane(false);
4175
+ }
4176
+ ui.exitZen();
4177
+ }, [ui]);
4178
+ const handleToggleZen = useCallback13(() => {
4179
+ if (ui.state.mode === "zen") {
4180
+ exitZen();
4181
+ return;
4182
+ }
4183
+ if (!process.env["TMUX"]) {
4184
+ toast.error("Zen mode requires tmux");
4185
+ return;
4186
+ }
4187
+ if (termCols < ZEN_MIN_COLS) {
4188
+ toast.error("Terminal too narrow for Zen mode");
4189
+ return;
4190
+ }
4191
+ const found = findIssue(repos, selectedId);
4192
+ const result = found ? openOrSplitPane(found.issue) : null;
4193
+ if (!result) {
4194
+ toast.error("Failed to create tmux pane");
4195
+ return;
4196
+ }
4197
+ setZenPaneId(result.paneId);
4198
+ setZenIsAgentPane(result.isAgent);
4199
+ ui.enterZen();
4200
+ }, [ui, toast, termCols, exitZen, repos, selectedId]);
4201
+ const swapToAgent = useCallback13(
4202
+ (issueNumber) => {
4203
+ const { id, isAgent } = paneRef.current;
4204
+ if (ui.state.mode !== "zen" || !id) return;
4205
+ cleanupPane(id, isAgent);
4206
+ setTimeout(() => {
4207
+ const winName = agentWindowName(issueNumber);
4208
+ if (windowExists(winName)) {
4209
+ const newPaneId = joinAgentPane(winName, ZEN_PANE_WIDTH_PERCENT);
4210
+ setZenPaneId(newPaneId);
4211
+ setZenIsAgentPane(true);
4212
+ }
4213
+ }, 500);
4214
+ },
4215
+ [ui.state.mode]
4216
+ );
4217
+ const prevSelectedRef = useRef11(null);
4218
+ useEffect5(() => {
4219
+ if (ui.state.mode !== "zen" || !zenPaneId) {
4220
+ prevSelectedRef.current = selectedId;
4221
+ return;
4222
+ }
4223
+ if (selectedId === prevSelectedRef.current) return;
4224
+ prevSelectedRef.current = selectedId;
4225
+ const timer = setTimeout(() => {
4226
+ const { id, isAgent } = paneRef.current;
4227
+ if (!id) return;
4228
+ const found = findIssue(repos, selectedId);
4229
+ if (!found) return;
4230
+ cleanupPane(id, isAgent);
4231
+ const result = openOrSplitPane(found.issue);
4232
+ if (!result) {
4233
+ setZenPaneId(null);
4234
+ setZenIsAgentPane(false);
4235
+ ui.exitZen();
4236
+ toast.error("Zen pane lost \u2014 exiting zen mode");
4237
+ return;
4238
+ }
4239
+ setZenPaneId(result.paneId);
4240
+ setZenIsAgentPane(result.isAgent);
4241
+ }, CURSOR_FOLLOW_DEBOUNCE_MS);
4242
+ return () => clearTimeout(timer);
4243
+ }, [ui.state.mode, zenPaneId, selectedId, repos, ui, toast]);
4244
+ useEffect5(() => {
4245
+ if (ui.state.mode !== "zen" || !zenPaneId) return;
4246
+ const interval = setInterval(() => {
4247
+ if (!isPaneAlive(zenPaneId)) {
4248
+ exitZen();
4249
+ toast.info("Zen pane closed");
4250
+ }
4251
+ }, DEAD_PANE_CHECK_MS);
4252
+ return () => clearInterval(interval);
4253
+ }, [ui.state.mode, zenPaneId, exitZen, toast]);
4254
+ return { zenPaneId, zenIsAgentPane, handleToggleZen, swapToAgent };
4255
+ }
4256
+ var ZEN_PANE_WIDTH_PERCENT, ZEN_MIN_COLS, CURSOR_FOLLOW_DEBOUNCE_MS, DEAD_PANE_CHECK_MS;
4257
+ var init_use_zen_mode = __esm({
4258
+ "src/board/hooks/use-zen-mode.ts"() {
4259
+ "use strict";
4260
+ init_tmux_pane();
4261
+ ZEN_PANE_WIDTH_PERCENT = 65;
4262
+ ZEN_MIN_COLS = 100;
4263
+ CURSOR_FOLLOW_DEBOUNCE_MS = 150;
4264
+ DEAD_PANE_CHECK_MS = 2e3;
4265
+ }
4266
+ });
4267
+
3974
4268
  // src/board/components/action-log.tsx
3975
4269
  import { Box, Text } from "ink";
3976
- import { useEffect as useEffect5, useState as useState7 } from "react";
4270
+ import { useEffect as useEffect6, useState as useState8 } from "react";
3977
4271
  import { jsx, jsxs } from "react/jsx-runtime";
3978
4272
  function relativeTime(ago) {
3979
4273
  const seconds = Math.floor((Date.now() - ago) / 1e3);
@@ -3994,8 +4288,8 @@ function statusColor(status) {
3994
4288
  return "yellow";
3995
4289
  }
3996
4290
  function ActionLog({ entries }) {
3997
- const [, setTick] = useState7(0);
3998
- useEffect5(() => {
4291
+ const [, setTick] = useState8(0);
4292
+ useEffect6(() => {
3999
4293
  const id = setInterval(() => setTick((t) => t + 1), 5e3);
4000
4294
  return () => clearInterval(id);
4001
4295
  }, []);
@@ -4159,7 +4453,7 @@ var init_agent_activity_panel = __esm({
4159
4453
 
4160
4454
  // src/board/components/detail-panel.tsx
4161
4455
  import { Box as Box5, Text as Text5 } from "ink";
4162
- import { useEffect as useEffect6 } from "react";
4456
+ import { useEffect as useEffect7 } from "react";
4163
4457
  import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
4164
4458
  function stripMarkdown(text) {
4165
4459
  return text.replace(/^#{1,6}\s+/gm, "").replace(/\*\*(.+?)\*\*/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/__(.+?)__/g, "$1").replace(/_(.+?)_/g, "$1").replace(/~~(.+?)~~/g, "$1").replace(/`{1,3}[^`]*`{1,3}/g, (m) => m.replace(/`/g, "")).replace(/^\s*[-*+]\s+/gm, " - ").replace(/^\s*\d+\.\s+/gm, " ").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/!\[([^\]]*)\]\([^)]+\)/g, "[$1]").replace(/^>\s+/gm, " ").replace(/---+/g, "").replace(/\n{3,}/g, "\n\n").trim();
@@ -4211,7 +4505,7 @@ function DetailPanel({
4211
4505
  fetchComments,
4212
4506
  issueRepo
4213
4507
  }) {
4214
- useEffect6(() => {
4508
+ useEffect7(() => {
4215
4509
  if (!(issue && fetchComments && issueRepo)) return;
4216
4510
  if (commentsState !== null && commentsState !== void 0) return;
4217
4511
  fetchComments(issueRepo, issue.number);
@@ -4310,6 +4604,12 @@ function HintBar({
4310
4604
  /* @__PURE__ */ jsx6(Text6, { color: "gray", children: " Space:toggle Enter:actions Esc:cancel" })
4311
4605
  ] });
4312
4606
  }
4607
+ if (uiMode === "zen") {
4608
+ return /* @__PURE__ */ jsxs6(Box6, { children: [
4609
+ /* @__PURE__ */ jsx6(Text6, { color: "green", bold: true, children: "[ZEN]" }),
4610
+ /* @__PURE__ */ jsx6(Text6, { color: "gray", children: " j/k:nav C:claude Z/Esc:exit q:quit" })
4611
+ ] });
4612
+ }
4313
4613
  if (uiMode === "focus") {
4314
4614
  return /* @__PURE__ */ jsx6(Box6, { children: /* @__PURE__ */ jsx6(Text6, { color: "magenta", bold: true, children: "[FOCUS] Focus mode \u2014 Esc to exit" }) });
4315
4615
  }
@@ -4340,7 +4640,7 @@ function HintBar({
4340
4640
  0: "j/k:scroll Esc:close ? help",
4341
4641
  1: "j/k:move Enter:filter 0-4:panel ? help",
4342
4642
  2: "j/k:move Enter:filter Esc:clear 0-4:panel ? help",
4343
- 3: `j/k:move Enter:detail g:open p:pick m:status c:comment C:claude /:search n:new 0-4:panel${hasUndoable ? " u:undo" : ""} ? help q:quit`,
4643
+ 3: `j/k:move Enter:detail g:open p:pick m:status c:comment C:claude /:search n:new H:hide-panel Z:zen 0-4:panel${hasUndoable ? " u:undo" : ""} ? help q:quit`,
4344
4644
  4: "j/k:scroll Enter:jump r:refresh 0-4:panel ? help"
4345
4645
  };
4346
4646
  return /* @__PURE__ */ jsxs6(Box6, { children: [
@@ -4361,7 +4661,7 @@ var init_hint_bar = __esm({
4361
4661
 
4362
4662
  // src/board/components/bulk-action-menu.tsx
4363
4663
  import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
4364
- import { useState as useState8 } from "react";
4664
+ import { useState as useState9 } from "react";
4365
4665
  import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
4366
4666
  function getMenuItems(selectionType) {
4367
4667
  if (selectionType === "github") {
@@ -4375,7 +4675,7 @@ function getMenuItems(selectionType) {
4375
4675
  }
4376
4676
  function BulkActionMenu({ count, selectionType, onSelect, onCancel }) {
4377
4677
  const items = getMenuItems(selectionType);
4378
- const [selectedIdx, setSelectedIdx] = useState8(0);
4678
+ const [selectedIdx, setSelectedIdx] = useState9(0);
4379
4679
  useInput2((input2, key) => {
4380
4680
  if (key.escape) return onCancel();
4381
4681
  if (key.return) {
@@ -4478,7 +4778,7 @@ import { tmpdir } from "os";
4478
4778
  import { join as join5 } from "path";
4479
4779
  import { TextInput } from "@inkjs/ui";
4480
4780
  import { Box as Box8, Text as Text8, useInput as useInput3, useStdin } from "ink";
4481
- import { useEffect as useEffect7, useRef as useRef11, useState as useState9 } from "react";
4781
+ import { useEffect as useEffect8, useRef as useRef12, useState as useState10 } from "react";
4482
4782
  import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
4483
4783
  function CommentInput({
4484
4784
  issueNumber,
@@ -4487,13 +4787,13 @@ function CommentInput({
4487
4787
  onPauseRefresh,
4488
4788
  onResumeRefresh
4489
4789
  }) {
4490
- const [value, setValue] = useState9("");
4491
- const [editing, setEditing] = useState9(false);
4790
+ const [value, setValue] = useState10("");
4791
+ const [editing, setEditing] = useState10(false);
4492
4792
  const { setRawMode } = useStdin();
4493
- const onSubmitRef = useRef11(onSubmit);
4494
- const onCancelRef = useRef11(onCancel);
4495
- const onPauseRef = useRef11(onPauseRefresh);
4496
- const onResumeRef = useRef11(onResumeRefresh);
4793
+ const onSubmitRef = useRef12(onSubmit);
4794
+ const onCancelRef = useRef12(onCancel);
4795
+ const onPauseRef = useRef12(onPauseRefresh);
4796
+ const onResumeRef = useRef12(onResumeRefresh);
4497
4797
  onSubmitRef.current = onSubmit;
4498
4798
  onCancelRef.current = onCancel;
4499
4799
  onPauseRef.current = onPauseRefresh;
@@ -4508,7 +4808,7 @@ function CommentInput({
4508
4808
  setEditing(true);
4509
4809
  }
4510
4810
  });
4511
- useEffect7(() => {
4811
+ useEffect8(() => {
4512
4812
  if (!editing) return;
4513
4813
  const editor = resolveEditor();
4514
4814
  if (!editor) {
@@ -4601,7 +4901,7 @@ var init_confirm_prompt = __esm({
4601
4901
  // src/board/components/label-picker.tsx
4602
4902
  import { Spinner } from "@inkjs/ui";
4603
4903
  import { Box as Box10, Text as Text10, useInput as useInput5 } from "ink";
4604
- import { useEffect as useEffect8, useRef as useRef12, useState as useState10 } from "react";
4904
+ import { useEffect as useEffect9, useRef as useRef13, useState as useState11 } from "react";
4605
4905
  import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
4606
4906
  function LabelPicker({
4607
4907
  repo,
@@ -4611,13 +4911,13 @@ function LabelPicker({
4611
4911
  onCancel,
4612
4912
  onError
4613
4913
  }) {
4614
- const [labels, setLabels] = useState10(labelCache[repo] ?? null);
4615
- const [loading, setLoading] = useState10(labels === null);
4616
- const [fetchAttempted, setFetchAttempted] = useState10(false);
4617
- const [selected, setSelected] = useState10(new Set(currentLabels));
4618
- const [cursor, setCursor] = useState10(0);
4619
- const submittedRef = useRef12(false);
4620
- useEffect8(() => {
4914
+ const [labels, setLabels] = useState11(labelCache[repo] ?? null);
4915
+ const [loading, setLoading] = useState11(labels === null);
4916
+ const [fetchAttempted, setFetchAttempted] = useState11(false);
4917
+ const [selected, setSelected] = useState11(new Set(currentLabels));
4918
+ const [cursor, setCursor] = useState11(0);
4919
+ const submittedRef = useRef13(false);
4920
+ useEffect9(() => {
4621
4921
  if (labels !== null || fetchAttempted) return;
4622
4922
  setFetchAttempted(true);
4623
4923
  setLoading(true);
@@ -4720,7 +5020,7 @@ var init_label_picker = __esm({
4720
5020
  // src/board/components/create-issue-form.tsx
4721
5021
  import { TextInput as TextInput2 } from "@inkjs/ui";
4722
5022
  import { Box as Box11, Text as Text11, useInput as useInput6 } from "ink";
4723
- import { useState as useState11 } from "react";
5023
+ import { useState as useState12 } from "react";
4724
5024
  import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
4725
5025
  function CreateIssueForm({
4726
5026
  repos,
@@ -4733,9 +5033,9 @@ function CreateIssueForm({
4733
5033
  0,
4734
5034
  repos.findIndex((r) => r.name === defaultRepo)
4735
5035
  ) : 0;
4736
- const [repoIdx, setRepoIdx] = useState11(defaultRepoIdx);
4737
- const [title, setTitle] = useState11("");
4738
- const [field, setField] = useState11("title");
5036
+ const [repoIdx, setRepoIdx] = useState12(defaultRepoIdx);
5037
+ const [title, setTitle] = useState12("");
5038
+ const [field, setField] = useState12("title");
4739
5039
  useInput6((input2, key) => {
4740
5040
  if (field === "labels") return;
4741
5041
  if (key.escape) return onCancel();
@@ -4837,7 +5137,7 @@ import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync7, rmSync as r
4837
5137
  import { tmpdir as tmpdir2 } from "os";
4838
5138
  import { join as join6 } from "path";
4839
5139
  import { Box as Box12, Text as Text12, useStdin as useStdin2 } from "ink";
4840
- import { useEffect as useEffect9, useRef as useRef13, useState as useState12 } from "react";
5140
+ import { useEffect as useEffect10, useRef as useRef14, useState as useState13 } from "react";
4841
5141
  import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
4842
5142
  function buildEditorFile(issue, repoName, statusOptions, repoLabels) {
4843
5143
  const statusNames = statusOptions.map((o) => o.name).join(", ");
@@ -4921,15 +5221,15 @@ function EditIssueOverlay({
4921
5221
  onToastError,
4922
5222
  onPushEntry
4923
5223
  }) {
4924
- const [editing, setEditing] = useState12(true);
5224
+ const [editing, setEditing] = useState13(true);
4925
5225
  const { setRawMode } = useStdin2();
4926
- const onDoneRef = useRef13(onDone);
4927
- const onPauseRef = useRef13(onPauseRefresh);
4928
- const onResumeRef = useRef13(onResumeRefresh);
5226
+ const onDoneRef = useRef14(onDone);
5227
+ const onPauseRef = useRef14(onPauseRefresh);
5228
+ const onResumeRef = useRef14(onResumeRefresh);
4929
5229
  onDoneRef.current = onDone;
4930
5230
  onPauseRef.current = onPauseRefresh;
4931
5231
  onResumeRef.current = onResumeRefresh;
4932
- useEffect9(() => {
5232
+ useEffect10(() => {
4933
5233
  if (!editing) return;
4934
5234
  const editor = resolveEditor();
4935
5235
  if (!editor) {
@@ -5097,7 +5397,7 @@ var init_edit_issue_overlay = __esm({
5097
5397
 
5098
5398
  // src/board/components/focus-mode.tsx
5099
5399
  import { Box as Box13, Text as Text13, useInput as useInput7 } from "ink";
5100
- import { useCallback as useCallback13, useEffect as useEffect10, useRef as useRef14, useState as useState13 } from "react";
5400
+ import { useCallback as useCallback14, useEffect as useEffect11, useRef as useRef15, useState as useState14 } from "react";
5101
5401
  import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
5102
5402
  function formatTime(secs) {
5103
5403
  const m = Math.floor(secs / 60);
@@ -5105,10 +5405,10 @@ function formatTime(secs) {
5105
5405
  return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
5106
5406
  }
5107
5407
  function FocusMode({ label, durationSec, onExit, onEndAction }) {
5108
- const [remaining, setRemaining] = useState13(durationSec);
5109
- const [timerDone, setTimerDone] = useState13(false);
5110
- const bellSentRef = useRef14(false);
5111
- useEffect10(() => {
5408
+ const [remaining, setRemaining] = useState14(durationSec);
5409
+ const [timerDone, setTimerDone] = useState14(false);
5410
+ const bellSentRef = useRef15(false);
5411
+ useEffect11(() => {
5112
5412
  if (timerDone) return;
5113
5413
  const interval = setInterval(() => {
5114
5414
  setRemaining((prev) => {
@@ -5122,13 +5422,13 @@ function FocusMode({ label, durationSec, onExit, onEndAction }) {
5122
5422
  }, 1e3);
5123
5423
  return () => clearInterval(interval);
5124
5424
  }, [timerDone]);
5125
- useEffect10(() => {
5425
+ useEffect11(() => {
5126
5426
  if (timerDone && !bellSentRef.current) {
5127
5427
  bellSentRef.current = true;
5128
5428
  process.stdout.write("\x07");
5129
5429
  }
5130
5430
  }, [timerDone]);
5131
- const handleInput = useCallback13(
5431
+ const handleInput = useCallback14(
5132
5432
  (input2, key) => {
5133
5433
  if (key.escape) {
5134
5434
  if (timerDone) {
@@ -5206,7 +5506,7 @@ var init_focus_mode = __esm({
5206
5506
  import { TextInput as TextInput3 } from "@inkjs/ui";
5207
5507
  import { Fzf } from "fzf";
5208
5508
  import { Box as Box14, Text as Text14, useInput as useInput8 } from "ink";
5209
- import { useMemo as useMemo4, useState as useState14 } from "react";
5509
+ import { useMemo as useMemo4, useState as useState15 } from "react";
5210
5510
  import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
5211
5511
  function keepCursorVisible(cursor, offset, visible) {
5212
5512
  if (cursor < offset) return cursor;
@@ -5214,9 +5514,9 @@ function keepCursorVisible(cursor, offset, visible) {
5214
5514
  return offset;
5215
5515
  }
5216
5516
  function FuzzyPicker({ repos, onSelect, onClose }) {
5217
- const [query, setQuery] = useState14("");
5218
- const [cursor, setCursor] = useState14(0);
5219
- const [scrollOffset, setScrollOffset] = useState14(0);
5517
+ const [query, setQuery] = useState15("");
5518
+ const [cursor, setCursor] = useState15(0);
5519
+ const [scrollOffset, setScrollOffset] = useState15(0);
5220
5520
  const allIssues = useMemo4(() => {
5221
5521
  const items = [];
5222
5522
  for (const rd of repos) {
@@ -5437,6 +5737,8 @@ var init_help_overlay = __esm({
5437
5737
  { key: "F", desc: "Fuzzy find issue (telescope-style)" },
5438
5738
  { key: "t", desc: "Toggle @me filter (my issues only)" },
5439
5739
  { key: "f", desc: "Focus mode" },
5740
+ { key: "Z", desc: "Zen mode (tmux split with Claude Code)" },
5741
+ { key: "H", desc: "Toggle left panel (repos/statuses)" },
5440
5742
  { key: "?", desc: "Toggle help" },
5441
5743
  { key: "Esc", desc: "Close overlay / Back to normal" }
5442
5744
  ]
@@ -5480,7 +5782,7 @@ import { tmpdir as tmpdir3 } from "os";
5480
5782
  import { join as join7 } from "path";
5481
5783
  import { Spinner as Spinner2, TextInput as TextInput4 } from "@inkjs/ui";
5482
5784
  import { Box as Box16, Text as Text16, useInput as useInput10, useStdin as useStdin3 } from "ink";
5483
- import { useCallback as useCallback14, useEffect as useEffect11, useRef as useRef15, useState as useState15 } from "react";
5785
+ import { useCallback as useCallback15, useEffect as useEffect12, useRef as useRef16, useState as useState16 } from "react";
5484
5786
  import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
5485
5787
  function NlCreateOverlay({
5486
5788
  repos,
@@ -5492,19 +5794,19 @@ function NlCreateOverlay({
5492
5794
  onResumeRefresh,
5493
5795
  onLlmFallback
5494
5796
  }) {
5495
- const [, setInput] = useState15("");
5496
- const [isParsing, setIsParsing] = useState15(false);
5497
- const [parsed, setParsed] = useState15(null);
5498
- const [parseError, setParseError] = useState15(null);
5499
- const [step, setStep] = useState15("input");
5500
- const [body, setBody] = useState15("");
5501
- const [editingBody, setEditingBody] = useState15(false);
5502
- const submittedRef = useRef15(false);
5503
- const parseParamsRef = useRef15(null);
5504
- const onSubmitRef = useRef15(onSubmit);
5505
- const onCancelRef = useRef15(onCancel);
5506
- const onPauseRef = useRef15(onPauseRefresh);
5507
- const onResumeRef = useRef15(onResumeRefresh);
5797
+ const [, setInput] = useState16("");
5798
+ const [isParsing, setIsParsing] = useState16(false);
5799
+ const [parsed, setParsed] = useState16(null);
5800
+ const [parseError, setParseError] = useState16(null);
5801
+ const [step, setStep] = useState16("input");
5802
+ const [body, setBody] = useState16("");
5803
+ const [editingBody, setEditingBody] = useState16(false);
5804
+ const submittedRef = useRef16(false);
5805
+ const parseParamsRef = useRef16(null);
5806
+ const onSubmitRef = useRef16(onSubmit);
5807
+ const onCancelRef = useRef16(onCancel);
5808
+ const onPauseRef = useRef16(onPauseRefresh);
5809
+ const onResumeRef = useRef16(onResumeRefresh);
5508
5810
  onSubmitRef.current = onSubmit;
5509
5811
  onCancelRef.current = onCancel;
5510
5812
  onPauseRef.current = onPauseRefresh;
@@ -5514,7 +5816,7 @@ function NlCreateOverlay({
5514
5816
  0,
5515
5817
  repos.findIndex((r) => r.name === defaultRepoName)
5516
5818
  ) : 0;
5517
- const [repoIdx, setRepoIdx] = useState15(defaultRepoIdx);
5819
+ const [repoIdx, setRepoIdx] = useState16(defaultRepoIdx);
5518
5820
  const selectedRepo = repos[repoIdx];
5519
5821
  useInput10((inputChar, key) => {
5520
5822
  if (isParsing || editingBody) return;
@@ -5541,7 +5843,7 @@ function NlCreateOverlay({
5541
5843
  setEditingBody(true);
5542
5844
  }
5543
5845
  });
5544
- useEffect11(() => {
5846
+ useEffect12(() => {
5545
5847
  if (!editingBody) return;
5546
5848
  const editor = resolveEditor();
5547
5849
  if (!editor) {
@@ -5573,7 +5875,7 @@ function NlCreateOverlay({
5573
5875
  setEditingBody(false);
5574
5876
  }
5575
5877
  }, [editingBody, body, setRawMode]);
5576
- const handleInputSubmit = useCallback14(
5878
+ const handleInputSubmit = useCallback15(
5577
5879
  (text) => {
5578
5880
  const trimmed = text.trim();
5579
5881
  if (!trimmed) return;
@@ -5585,7 +5887,7 @@ function NlCreateOverlay({
5585
5887
  },
5586
5888
  [selectedRepo, labelCache]
5587
5889
  );
5588
- useEffect11(() => {
5890
+ useEffect12(() => {
5589
5891
  if (!(isParsing && parseParamsRef.current)) return;
5590
5892
  const { input: capturedInput, validLabels } = parseParamsRef.current;
5591
5893
  extractIssueFields(capturedInput, {
@@ -5717,10 +6019,10 @@ var init_nl_create_overlay = __esm({
5717
6019
 
5718
6020
  // src/board/components/nudge-overlay.tsx
5719
6021
  import { Box as Box17, Text as Text17, useInput as useInput11 } from "ink";
5720
- import { useState as useState16 } from "react";
6022
+ import { useState as useState17 } from "react";
5721
6023
  import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
5722
6024
  function NudgeOverlay({ candidates, onAction, onCancel }) {
5723
- const [selectedIdx, setSelectedIdx] = useState16(0);
6025
+ const [selectedIdx, setSelectedIdx] = useState17(0);
5724
6026
  useInput11((input2, key) => {
5725
6027
  if (key.escape) {
5726
6028
  onAction({ type: "dismiss" });
@@ -5841,7 +6143,7 @@ var init_search_bar = __esm({
5841
6143
 
5842
6144
  // src/board/components/status-picker.tsx
5843
6145
  import { Box as Box19, Text as Text19, useInput as useInput12 } from "ink";
5844
- import { useRef as useRef16, useState as useState17 } from "react";
6146
+ import { useRef as useRef17, useState as useState18 } from "react";
5845
6147
  import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
5846
6148
  function isTerminal(name) {
5847
6149
  return TERMINAL_STATUS_RE.test(name);
@@ -5889,12 +6191,12 @@ function StatusPicker({
5889
6191
  onCancel,
5890
6192
  showTerminalStatuses = true
5891
6193
  }) {
5892
- const [selectedIdx, setSelectedIdx] = useState17(() => {
6194
+ const [selectedIdx, setSelectedIdx] = useState18(() => {
5893
6195
  const idx = options.findIndex((o) => o.name === currentStatus);
5894
6196
  return idx >= 0 ? idx : 0;
5895
6197
  });
5896
- const [confirmingTerminal, setConfirmingTerminal] = useState17(false);
5897
- const submittedRef = useRef16(false);
6198
+ const [confirmingTerminal, setConfirmingTerminal] = useState18(false);
6199
+ const submittedRef = useRef17(false);
5898
6200
  useInput12((input2, key) => {
5899
6201
  if (confirmingTerminal) {
5900
6202
  handleConfirmInput(input2, key, {
@@ -5962,12 +6264,12 @@ var init_status_picker = __esm({
5962
6264
 
5963
6265
  // src/board/components/triage-overlay.tsx
5964
6266
  import { Box as Box20, Text as Text20, useInput as useInput13 } from "ink";
5965
- import { useState as useState18 } from "react";
6267
+ import { useState as useState19 } from "react";
5966
6268
  import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
5967
6269
  function TriageOverlay({ candidates, phases, onAction, onCancel }) {
5968
- const [selected, setSelected] = useState18(() => /* @__PURE__ */ new Set());
5969
- const [cursorIdx, setCursorIdx] = useState18(0);
5970
- const [phaseIdx, setPhaseIdx] = useState18(0);
6270
+ const [selected, setSelected] = useState19(() => /* @__PURE__ */ new Set());
6271
+ const [cursorIdx, setCursorIdx] = useState19(0);
6272
+ const [phaseIdx, setPhaseIdx] = useState19(0);
5971
6273
  useInput13((input2, key) => {
5972
6274
  if (key.escape) {
5973
6275
  onCancel();
@@ -6105,7 +6407,7 @@ var init_triage_overlay = __esm({
6105
6407
 
6106
6408
  // src/board/components/workflow-overlay.tsx
6107
6409
  import { Box as Box21, Text as Text21, useInput as useInput14 } from "ink";
6108
- import { useState as useState19 } from "react";
6410
+ import { useState as useState20 } from "react";
6109
6411
  import { jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
6110
6412
  function phaseIcon(state) {
6111
6413
  switch (state) {
@@ -6135,7 +6437,7 @@ function WorkflowOverlay({
6135
6437
  onAction,
6136
6438
  onCancel
6137
6439
  }) {
6138
- const [selectedIdx, setSelectedIdx] = useState19(0);
6440
+ const [selectedIdx, setSelectedIdx] = useState20(0);
6139
6441
  useInput14((input2, key) => {
6140
6442
  if (key.escape) {
6141
6443
  onCancel();
@@ -6413,7 +6715,7 @@ var init_overlay_renderer = __esm({
6413
6715
 
6414
6716
  // src/board/components/panel-layout.tsx
6415
6717
  import { Box as Box22 } from "ink";
6416
- import { jsx as jsx23, jsxs as jsxs23 } from "react/jsx-runtime";
6718
+ import { Fragment as Fragment3, jsx as jsx23, jsxs as jsxs23 } from "react/jsx-runtime";
6417
6719
  function getLayoutMode(cols) {
6418
6720
  if (cols >= WIDE_THRESHOLD) return "wide";
6419
6721
  if (cols >= MEDIUM_THRESHOLD) return "medium";
@@ -6429,17 +6731,18 @@ function PanelLayout({
6429
6731
  statusesPanel,
6430
6732
  issuesPanel,
6431
6733
  detailPanel,
6432
- activityPanel
6734
+ activityPanel,
6735
+ hideLeftPanel
6433
6736
  }) {
6434
6737
  const mode = getLayoutMode(cols);
6435
6738
  if (mode === "wide") {
6436
6739
  const detailWidth = getDetailWidth(cols);
6437
6740
  return /* @__PURE__ */ jsxs23(Box22, { flexDirection: "column", children: [
6438
6741
  /* @__PURE__ */ jsxs23(Box22, { height: issuesPanelHeight, children: [
6439
- /* @__PURE__ */ jsxs23(Box22, { flexDirection: "column", width: LEFT_COL_WIDTH, children: [
6742
+ !hideLeftPanel ? /* @__PURE__ */ jsxs23(Box22, { flexDirection: "column", width: LEFT_COL_WIDTH, children: [
6440
6743
  reposPanel,
6441
6744
  statusesPanel
6442
- ] }),
6745
+ ] }) : null,
6443
6746
  /* @__PURE__ */ jsx23(Box22, { flexGrow: 1, flexDirection: "column", children: issuesPanel }),
6444
6747
  /* @__PURE__ */ jsx23(Box22, { width: detailWidth, flexDirection: "column", children: detailPanel })
6445
6748
  ] }),
@@ -6449,18 +6752,20 @@ function PanelLayout({
6449
6752
  if (mode === "medium") {
6450
6753
  return /* @__PURE__ */ jsxs23(Box22, { flexDirection: "column", children: [
6451
6754
  /* @__PURE__ */ jsxs23(Box22, { height: issuesPanelHeight, children: [
6452
- /* @__PURE__ */ jsxs23(Box22, { flexDirection: "column", width: LEFT_COL_WIDTH, children: [
6755
+ !hideLeftPanel ? /* @__PURE__ */ jsxs23(Box22, { flexDirection: "column", width: LEFT_COL_WIDTH, children: [
6453
6756
  reposPanel,
6454
6757
  statusesPanel
6455
- ] }),
6758
+ ] }) : null,
6456
6759
  /* @__PURE__ */ jsx23(Box22, { flexGrow: 1, flexDirection: "column", children: issuesPanel })
6457
6760
  ] }),
6458
6761
  /* @__PURE__ */ jsx23(Box22, { height: ACTIVITY_HEIGHT, children: activityPanel })
6459
6762
  ] });
6460
6763
  }
6461
6764
  return /* @__PURE__ */ jsxs23(Box22, { flexDirection: "column", children: [
6462
- reposPanel,
6463
- statusesPanel,
6765
+ !hideLeftPanel ? /* @__PURE__ */ jsxs23(Fragment3, { children: [
6766
+ reposPanel,
6767
+ statusesPanel
6768
+ ] }) : null,
6464
6769
  /* @__PURE__ */ jsx23(Box22, { flexGrow: 1, flexDirection: "column", children: issuesPanel }),
6465
6770
  /* @__PURE__ */ jsx23(Box22, { height: ACTIVITY_HEIGHT, children: activityPanel })
6466
6771
  ] });
@@ -6806,10 +7111,10 @@ var init_statuses_panel = __esm({
6806
7111
  // src/board/components/toast-container.tsx
6807
7112
  import { Spinner as Spinner3 } from "@inkjs/ui";
6808
7113
  import { Box as Box27, Text as Text26 } from "ink";
6809
- import { Fragment as Fragment3, jsx as jsx28, jsxs as jsxs28 } from "react/jsx-runtime";
7114
+ import { Fragment as Fragment4, jsx as jsx28, jsxs as jsxs28 } from "react/jsx-runtime";
6810
7115
  function ToastContainer({ toasts }) {
6811
7116
  if (toasts.length === 0) return null;
6812
- return /* @__PURE__ */ jsx28(Box27, { flexDirection: "column", children: toasts.map((t) => /* @__PURE__ */ jsx28(Box27, { children: t.type === "loading" ? /* @__PURE__ */ jsxs28(Fragment3, { children: [
7117
+ return /* @__PURE__ */ jsx28(Box27, { flexDirection: "column", children: toasts.map((t) => /* @__PURE__ */ jsx28(Box27, { children: t.type === "loading" ? /* @__PURE__ */ jsxs28(Fragment4, { children: [
6813
7118
  /* @__PURE__ */ jsx28(Spinner3, { label: "" }),
6814
7119
  /* @__PURE__ */ jsxs28(Text26, { color: "cyan", children: [
6815
7120
  " ",
@@ -6844,8 +7149,8 @@ var init_toast_container = __esm({
6844
7149
  import { execFile as execFile2, spawn as spawn4 } from "child_process";
6845
7150
  import { Spinner as Spinner4 } from "@inkjs/ui";
6846
7151
  import { Box as Box28, Text as Text27, useApp, useStdout } from "ink";
6847
- import { useCallback as useCallback15, useEffect as useEffect12, useMemo as useMemo5, useRef as useRef17, useState as useState20 } from "react";
6848
- import { Fragment as Fragment4, jsx as jsx29, jsxs as jsxs29 } from "react/jsx-runtime";
7152
+ import { useCallback as useCallback16, useEffect as useEffect13, useMemo as useMemo5, useRef as useRef18, useState as useState21 } from "react";
7153
+ import { Fragment as Fragment5, jsx as jsx29, jsxs as jsxs29 } from "react/jsx-runtime";
6849
7154
  function resolvePhaseConfig(rc, config2, issueTitle, phase) {
6850
7155
  const phasePrompts = rc.workflow?.phasePrompts ?? config2.board.workflow?.phasePrompts ?? {};
6851
7156
  const template = phasePrompts[phase] ?? DEFAULT_PHASE_PROMPTS[phase];
@@ -6999,8 +7304,8 @@ function findSelectedIssueWithRepo(repos, selectedId) {
6999
7304
  return null;
7000
7305
  }
7001
7306
  function RefreshAge({ lastRefresh }) {
7002
- const [, setTick] = useState20(0);
7003
- useEffect12(() => {
7307
+ const [, setTick] = useState21(0);
7308
+ useEffect13(() => {
7004
7309
  const id = setInterval(() => setTick((t) => t + 1), 3e4);
7005
7310
  return () => clearInterval(id);
7006
7311
  }, []);
@@ -7059,15 +7364,20 @@ function Dashboard({ config: config2, options, activeProfile }) {
7059
7364
  const workflowState = useWorkflowState(config2);
7060
7365
  const { toasts, toast, handleErrorAction } = useToast();
7061
7366
  const agentSessions = useAgentSessions(config2, workflowState, toast);
7062
- const [activePanelId, setActivePanelId] = useState20(3);
7063
- const focusPanel = useCallback15((id) => setActivePanelId(id), []);
7367
+ const [activePanelId, setActivePanelId] = useState21(3);
7368
+ const focusPanel = useCallback16((id) => setActivePanelId(id), []);
7064
7369
  const panelFocus = useMemo5(() => ({ activePanelId, focusPanel }), [activePanelId, focusPanel]);
7065
- const [searchQuery, setSearchQuery] = useState20("");
7066
- const [mineOnly, setMineOnly] = useState20(false);
7067
- const handleToggleMine = useCallback15(() => {
7370
+ const [searchQuery, setSearchQuery] = useState21("");
7371
+ const [mineOnly, setMineOnly] = useState21(false);
7372
+ const handleToggleMine = useCallback16(() => {
7068
7373
  setMineOnly((prev) => !prev);
7069
7374
  }, []);
7070
- const [logVisible, setLogVisible] = useState20(false);
7375
+ const [leftPanelHidden, setLeftPanelHidden] = useState21(false);
7376
+ const handleToggleLeftPanel = useCallback16(() => {
7377
+ setLeftPanelHidden((v) => !v);
7378
+ setActivePanelId((id) => id === 1 || id === 2 ? 3 : id);
7379
+ }, []);
7380
+ const [logVisible, setLogVisible] = useState21(false);
7071
7381
  const { entries: logEntries, pushEntry, undoLast, hasUndoable } = useActionLog(toast, refresh);
7072
7382
  useAutoStatus({
7073
7383
  config: config2,
@@ -7077,7 +7387,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7077
7387
  pushEntry,
7078
7388
  registerPendingMutation
7079
7389
  });
7080
- const handleEnrichmentChange = useCallback15(
7390
+ const handleEnrichmentChange = useCallback16(
7081
7391
  (data2) => {
7082
7392
  workflowState.updateEnrichment(data2);
7083
7393
  },
@@ -7089,7 +7399,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7089
7399
  enrichment: workflowState.enrichment,
7090
7400
  onEnrichmentChange: handleEnrichmentChange
7091
7401
  });
7092
- useEffect12(() => {
7402
+ useEffect13(() => {
7093
7403
  const last = logEntries[logEntries.length - 1];
7094
7404
  if (last?.status === "error") setLogVisible(true);
7095
7405
  }, [logEntries]);
@@ -7106,38 +7416,38 @@ function Dashboard({ config: config2, options, activeProfile }) {
7106
7416
  return filtered.map((rd) => ({ ...rd, issues: rd.issues.filter((i) => matchesSearch(i, searchQuery)) })).filter((rd) => rd.issues.length > 0);
7107
7417
  }, [allRepos, searchQuery, mineOnly, config2.board.assignee]);
7108
7418
  const boardTree = useMemo5(() => buildBoardTree(repos, allActivity), [repos, allActivity]);
7109
- const [selectedRepoIdx, setSelectedRepoIdx] = useState20(0);
7419
+ const [selectedRepoIdx, setSelectedRepoIdx] = useState21(0);
7110
7420
  const clampedRepoIdx = Math.min(selectedRepoIdx, Math.max(0, boardTree.sections.length - 1));
7111
7421
  const reposNav = {
7112
- moveUp: useCallback15(() => setSelectedRepoIdx((i) => Math.max(0, i - 1)), []),
7113
- moveDown: useCallback15(
7422
+ moveUp: useCallback16(() => setSelectedRepoIdx((i) => Math.max(0, i - 1)), []),
7423
+ moveDown: useCallback16(
7114
7424
  () => setSelectedRepoIdx((i) => Math.min(Math.max(0, boardTree.sections.length - 1), i + 1)),
7115
7425
  [boardTree.sections.length]
7116
7426
  )
7117
7427
  };
7118
- const [selectedStatusIdx, setSelectedStatusIdx] = useState20(0);
7428
+ const [selectedStatusIdx, setSelectedStatusIdx] = useState21(0);
7119
7429
  const selectedSection = boardTree.sections[clampedRepoIdx] ?? null;
7120
7430
  const clampedStatusIdx = Math.min(
7121
7431
  selectedStatusIdx,
7122
7432
  Math.max(0, (selectedSection?.groups.length ?? 1) - 1)
7123
7433
  );
7124
7434
  const statusesNav = {
7125
- moveUp: useCallback15(() => setSelectedStatusIdx((i) => Math.max(0, i - 1)), []),
7126
- moveDown: useCallback15(
7435
+ moveUp: useCallback16(() => setSelectedStatusIdx((i) => Math.max(0, i - 1)), []),
7436
+ moveDown: useCallback16(
7127
7437
  () => setSelectedStatusIdx(
7128
7438
  (i) => Math.min(Math.max(0, (selectedSection?.groups.length ?? 1) - 1), i + 1)
7129
7439
  ),
7130
7440
  [selectedSection?.groups.length]
7131
7441
  )
7132
7442
  };
7133
- const [activitySelectedIdx, setActivitySelectedIdx] = useState20(0);
7443
+ const [activitySelectedIdx, setActivitySelectedIdx] = useState21(0);
7134
7444
  const clampedActivityIdx = Math.min(
7135
7445
  activitySelectedIdx,
7136
7446
  Math.max(0, boardTree.activity.length - 1)
7137
7447
  );
7138
7448
  const activityNav = {
7139
- moveUp: useCallback15(() => setActivitySelectedIdx((i) => Math.max(0, i - 1)), []),
7140
- moveDown: useCallback15(
7449
+ moveUp: useCallback16(() => setActivitySelectedIdx((i) => Math.max(0, i - 1)), []),
7450
+ moveDown: useCallback16(
7141
7451
  () => setActivitySelectedIdx((i) => Math.min(Math.max(0, boardTree.activity.length - 1), i + 1)),
7142
7452
  [boardTree.activity.length]
7143
7453
  )
@@ -7145,14 +7455,14 @@ function Dashboard({ config: config2, options, activeProfile }) {
7145
7455
  const selectedRepoName = selectedSection?.sectionId ?? null;
7146
7456
  const selectedStatusGroup = selectedSection?.groups[clampedStatusIdx] ?? null;
7147
7457
  const selectedStatusGroupId = selectedStatusGroup?.subId ?? null;
7148
- const onRepoEnter = useCallback15(() => {
7458
+ const onRepoEnter = useCallback16(() => {
7149
7459
  setSelectedStatusIdx(0);
7150
7460
  panelFocus.focusPanel(3);
7151
7461
  }, [panelFocus]);
7152
- const onStatusEnter = useCallback15(() => {
7462
+ const onStatusEnter = useCallback16(() => {
7153
7463
  panelFocus.focusPanel(3);
7154
7464
  }, [panelFocus]);
7155
- const onActivityEnter = useCallback15(() => {
7465
+ const onActivityEnter = useCallback16(() => {
7156
7466
  const event = boardTree.activity[clampedActivityIdx];
7157
7467
  if (!event) return;
7158
7468
  const repoIdx = boardTree.sections.findIndex(
@@ -7169,7 +7479,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7169
7479
  [boardTree.sections, selectedRepoName, selectedStatusGroupId]
7170
7480
  );
7171
7481
  const nav = useNavigation(navItems);
7172
- const getRepoForId = useCallback15((id) => {
7482
+ const getRepoForId = useCallback16((id) => {
7173
7483
  if (id.startsWith("gh:")) {
7174
7484
  const parts = id.split(":");
7175
7485
  return parts.length >= 3 ? `${parts[1]}` : null;
@@ -7177,7 +7487,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7177
7487
  return null;
7178
7488
  }, []);
7179
7489
  const multiSelect = useMultiSelect(getRepoForId);
7180
- useEffect12(() => {
7490
+ useEffect13(() => {
7181
7491
  if (multiSelect.count === 0) return;
7182
7492
  const validIds = new Set(navItems.map((i) => i.id));
7183
7493
  multiSelect.prune(validIds);
@@ -7194,11 +7504,11 @@ function Dashboard({ config: config2, options, activeProfile }) {
7194
7504
  registerPendingMutation,
7195
7505
  clearPendingMutation
7196
7506
  });
7197
- const pendingPickRef = useRef17(null);
7198
- const labelCacheRef = useRef17({});
7199
- const commentCacheRef = useRef17({});
7200
- const [commentTick, setCommentTick] = useState20(0);
7201
- const handleFetchComments = useCallback15((repo, issueNumber) => {
7507
+ const pendingPickRef = useRef18(null);
7508
+ const labelCacheRef = useRef18({});
7509
+ const commentCacheRef = useRef18({});
7510
+ const [commentTick, setCommentTick] = useState21(0);
7511
+ const handleFetchComments = useCallback16((repo, issueNumber) => {
7202
7512
  const key = `${repo}:${issueNumber}`;
7203
7513
  if (commentCacheRef.current[key] !== void 0) return;
7204
7514
  commentCacheRef.current[key] = "loading";
@@ -7211,7 +7521,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7211
7521
  setCommentTick((t) => t + 1);
7212
7522
  });
7213
7523
  }, []);
7214
- const handleCreateIssueWithPrompt = useCallback15(
7524
+ const handleCreateIssueWithPrompt = useCallback16(
7215
7525
  (repo, title, body, dueDate, labels) => {
7216
7526
  actions.handleCreateIssue(repo, title, body, dueDate, labels).then((result) => {
7217
7527
  if (result) {
@@ -7222,7 +7532,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7222
7532
  },
7223
7533
  [actions, ui]
7224
7534
  );
7225
- const handleConfirmPick = useCallback15(() => {
7535
+ const handleConfirmPick = useCallback16(() => {
7226
7536
  const pending = pendingPickRef.current;
7227
7537
  pendingPickRef.current = null;
7228
7538
  ui.exitOverlay();
@@ -7240,12 +7550,12 @@ function Dashboard({ config: config2, options, activeProfile }) {
7240
7550
  })
7241
7551
  );
7242
7552
  }, [config2, toast, refresh, ui]);
7243
- const handleCancelPick = useCallback15(() => {
7553
+ const handleCancelPick = useCallback16(() => {
7244
7554
  pendingPickRef.current = null;
7245
7555
  ui.exitOverlay();
7246
7556
  }, [ui]);
7247
- const [focusLabel, setFocusLabel] = useState20(null);
7248
- const handleEnterFocus = useCallback15(() => {
7557
+ const [focusLabel, setFocusLabel] = useState21(null);
7558
+ const handleEnterFocus = useCallback16(() => {
7249
7559
  const id = nav.selectedId;
7250
7560
  if (!id || isHeaderId(id)) return;
7251
7561
  let label = "";
@@ -7260,11 +7570,11 @@ function Dashboard({ config: config2, options, activeProfile }) {
7260
7570
  setFocusLabel(label);
7261
7571
  ui.enterFocus();
7262
7572
  }, [nav.selectedId, repos, config2.repos, ui]);
7263
- const handleFocusExit = useCallback15(() => {
7573
+ const handleFocusExit = useCallback16(() => {
7264
7574
  setFocusLabel(null);
7265
7575
  ui.exitToNormal();
7266
7576
  }, [ui]);
7267
- const handleFocusEndAction = useCallback15(
7577
+ const handleFocusEndAction = useCallback16(
7268
7578
  (action) => {
7269
7579
  switch (action) {
7270
7580
  case "restart":
@@ -7290,13 +7600,13 @@ function Dashboard({ config: config2, options, activeProfile }) {
7290
7600
  },
7291
7601
  [toast, ui]
7292
7602
  );
7293
- const [focusKey, setFocusKey] = useState20(0);
7603
+ const [focusKey, setFocusKey] = useState21(0);
7294
7604
  const { stdout } = useStdout();
7295
- const [termSize, setTermSize] = useState20({
7605
+ const [termSize, setTermSize] = useState21({
7296
7606
  cols: stdout?.columns ?? 80,
7297
7607
  rows: stdout?.rows ?? 24
7298
7608
  });
7299
- useEffect12(() => {
7609
+ useEffect13(() => {
7300
7610
  if (!stdout) return;
7301
7611
  const onResize = () => setTermSize({ cols: stdout.columns, rows: stdout.rows });
7302
7612
  stdout.on("resize", onResize);
@@ -7304,13 +7614,21 @@ function Dashboard({ config: config2, options, activeProfile }) {
7304
7614
  stdout.off("resize", onResize);
7305
7615
  };
7306
7616
  }, [stdout]);
7617
+ const zen = useZenMode({
7618
+ ui,
7619
+ toast,
7620
+ termCols: termSize.cols,
7621
+ repos,
7622
+ selectedId: nav.selectedId
7623
+ });
7307
7624
  const layoutMode = getLayoutMode(termSize.cols);
7308
7625
  const detailPanelWidth = layoutMode === "wide" ? getDetailWidth(termSize.cols) : Math.floor(termSize.cols * 0.35);
7309
7626
  const showDetailPanel = layoutMode === "wide";
7310
7627
  const usableWidth = termSize.cols - 2;
7628
+ const effectiveLeftWidth = leftPanelHidden ? 0 : LEFT_COL_WIDTH;
7311
7629
  const issuesPanelWidth = Math.max(
7312
7630
  20,
7313
- layoutMode === "wide" ? usableWidth - LEFT_COL_WIDTH - getDetailWidth(termSize.cols) : layoutMode === "medium" ? usableWidth - LEFT_COL_WIDTH : usableWidth
7631
+ layoutMode === "wide" ? usableWidth - effectiveLeftWidth - getDetailWidth(termSize.cols) : layoutMode === "medium" ? usableWidth - effectiveLeftWidth : usableWidth
7314
7632
  );
7315
7633
  const activityPanelWidth = usableWidth;
7316
7634
  const overlayBarRows = ui.state.mode === "search" || ui.state.mode === "overlay:comment" ? 1 : 0;
@@ -7339,9 +7657,9 @@ function Dashboard({ config: config2, options, activeProfile }) {
7339
7657
  return { ...row, phaseIndicator, statusAgeDays };
7340
7658
  });
7341
7659
  }, [boardTree.sections, selectedRepoName, selectedStatusGroupId, workflowState, config2.repos]);
7342
- const scrollRef = useRef17(0);
7343
- const prevRepoRef = useRef17(null);
7344
- const prevStatusRef = useRef17(null);
7660
+ const scrollRef = useRef18(0);
7661
+ const prevRepoRef = useRef18(null);
7662
+ const prevStatusRef = useRef18(null);
7345
7663
  if (selectedRepoName !== prevRepoRef.current || selectedStatusGroupId !== prevStatusRef.current) {
7346
7664
  prevRepoRef.current = selectedRepoName;
7347
7665
  prevStatusRef.current = selectedStatusGroupId;
@@ -7386,7 +7704,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7386
7704
  return config2.repos.find((r) => r.name === selectedItem.repoName) ?? null;
7387
7705
  }, [selectedItem.repoName, config2.repos]);
7388
7706
  const selectedIssueWorkflow = useMemo5(() => {
7389
- if (!selectedItem.issue || !selectedItem.repoName) return null;
7707
+ if (!(selectedItem.issue && selectedItem.repoName)) return null;
7390
7708
  return workflowState.getIssueWorkflow(
7391
7709
  selectedItem.repoName,
7392
7710
  selectedItem.issue.number,
@@ -7399,16 +7717,16 @@ function Dashboard({ config: config2, options, activeProfile }) {
7399
7717
  const rd = repos.find((r) => r.repo.name === repoName);
7400
7718
  return rd?.statusOptions ?? [];
7401
7719
  }, [selectedItem.repoName, repos, multiSelect.count, multiSelect.constrainedRepo]);
7402
- const handleOpen = useCallback15(() => {
7720
+ const handleOpen = useCallback16(() => {
7403
7721
  const found = findSelectedIssueWithRepo(repos, nav.selectedId);
7404
7722
  if (found) openInBrowser(found.issue.url);
7405
7723
  }, [repos, nav.selectedId]);
7406
- const handleSlack = useCallback15(() => {
7724
+ const handleSlack = useCallback16(() => {
7407
7725
  const found = findSelectedIssueWithRepo(repos, nav.selectedId);
7408
7726
  if (!found?.issue.slackThreadUrl) return;
7409
7727
  openInBrowser(found.issue.slackThreadUrl);
7410
7728
  }, [repos, nav.selectedId]);
7411
- const handleCopyLink = useCallback15(() => {
7729
+ const handleCopyLink = useCallback16(() => {
7412
7730
  const found = findSelectedIssueWithRepo(repos, nav.selectedId);
7413
7731
  if (!found) return;
7414
7732
  const rc = config2.repos.find((r) => r.name === found.repoName);
@@ -7433,7 +7751,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7433
7751
  toast.info(`${label} \u2014 ${found.issue.url}`);
7434
7752
  }
7435
7753
  }, [repos, nav.selectedId, config2.repos, toast]);
7436
- const handleLaunchClaude = useCallback15(() => {
7754
+ const handleLaunchClaude = useCallback16(() => {
7437
7755
  const found = findSelectedIssueWithRepo(repos, nav.selectedId);
7438
7756
  if (!found) return;
7439
7757
  const rc = config2.repos.find((r) => r.name === found.repoName);
@@ -7459,13 +7777,14 @@ function Dashboard({ config: config2, options, activeProfile }) {
7459
7777
  return;
7460
7778
  }
7461
7779
  toast.info(`Claude Code session opened in ${rc.shortName ?? found.repoName}`);
7462
- }, [repos, nav.selectedId, config2.repos, config2.board, toast]);
7463
- const handleEnterWorkflow = useCallback15(() => {
7780
+ zen.swapToAgent(found.issue.number);
7781
+ }, [repos, nav.selectedId, config2.repos, config2.board, toast, zen]);
7782
+ const handleEnterWorkflow = useCallback16(() => {
7464
7783
  const found = findSelectedIssueWithRepo(repos, nav.selectedId);
7465
7784
  if (!found) return;
7466
7785
  ui.enterWorkflow();
7467
7786
  }, [repos, nav.selectedId, ui]);
7468
- const handleWorkflowAction = useCallback15(
7787
+ const handleWorkflowAction = useCallback16(
7469
7788
  (action) => {
7470
7789
  const found = findSelectedIssueWithRepo(repos, nav.selectedId);
7471
7790
  if (!found) return;
@@ -7589,7 +7908,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7589
7908
  },
7590
7909
  [repos, nav.selectedId, config2, ui, toast, workflowState, agentSessions]
7591
7910
  );
7592
- const handleNudgeAction = useCallback15(
7911
+ const handleNudgeAction = useCallback16(
7593
7912
  (action) => {
7594
7913
  if (action.type === "snooze") {
7595
7914
  nudges.snooze(action.repo, action.issueNumber, action.days);
@@ -7600,7 +7919,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7600
7919
  },
7601
7920
  [nudges, toast]
7602
7921
  );
7603
- const handleTriageAction = useCallback15(
7922
+ const handleTriageAction = useCallback16(
7604
7923
  (action) => {
7605
7924
  if (action.type === "snooze") {
7606
7925
  nudges.snooze(action.repo, action.issueNumber, action.days);
@@ -7665,7 +7984,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7665
7984
  },
7666
7985
  [config2, agentSessions, workflowState, nudges, toast, ui]
7667
7986
  );
7668
- const handleEnterTriage = useCallback15(() => {
7987
+ const handleEnterTriage = useCallback16(() => {
7669
7988
  if (nudges.candidates.length === 0) {
7670
7989
  toast.info("No stale issues to triage");
7671
7990
  return;
@@ -7673,7 +7992,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7673
7992
  ui.enterTriage();
7674
7993
  }, [nudges.candidates.length, toast, ui]);
7675
7994
  const multiSelectType = "github";
7676
- const handleBulkAction = useCallback15(
7995
+ const handleBulkAction = useCallback16(
7677
7996
  (action) => {
7678
7997
  const ids = multiSelect.selected;
7679
7998
  switch (action.type) {
@@ -7716,7 +8035,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7716
8035
  },
7717
8036
  [multiSelect, actions, ui, toast]
7718
8037
  );
7719
- const handleBulkStatusSelect = useCallback15(
8038
+ const handleBulkStatusSelect = useCallback16(
7720
8039
  (optionId) => {
7721
8040
  const ids = multiSelect.selected;
7722
8041
  ui.exitOverlay();
@@ -7732,7 +8051,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7732
8051
  },
7733
8052
  [multiSelect, actions, ui]
7734
8053
  );
7735
- const handleFuzzySelect = useCallback15(
8054
+ const handleFuzzySelect = useCallback16(
7736
8055
  (navId) => {
7737
8056
  nav.select(navId);
7738
8057
  if (navId.startsWith("gh:")) {
@@ -7753,7 +8072,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
7753
8072
  },
7754
8073
  [nav, ui, boardTree]
7755
8074
  );
7756
- const onSearchEscape = useCallback15(() => {
8075
+ const onSearchEscape = useCallback16(() => {
7757
8076
  ui.exitOverlay();
7758
8077
  setSearchQuery("");
7759
8078
  }, [ui]);
@@ -7783,7 +8102,9 @@ function Dashboard({ config: config2, options, activeProfile }) {
7783
8102
  handleToggleLog: () => setLogVisible((v) => !v),
7784
8103
  handleLaunchClaude,
7785
8104
  handleEnterWorkflow,
7786
- handleEnterTriage
8105
+ handleEnterTriage,
8106
+ handleToggleLeftPanel,
8107
+ handleToggleZen: zen.handleToggleZen
7787
8108
  },
7788
8109
  onSearchEscape,
7789
8110
  panelFocus,
@@ -7793,7 +8114,8 @@ function Dashboard({ config: config2, options, activeProfile }) {
7793
8114
  onRepoEnter,
7794
8115
  onStatusEnter,
7795
8116
  onActivityEnter,
7796
- showDetailPanel
8117
+ showDetailPanel,
8118
+ leftPanelHidden
7797
8119
  });
7798
8120
  if (status === "loading" && !data) {
7799
8121
  return /* @__PURE__ */ jsx29(Box28, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx29(Spinner4, { label: "Loading dashboard..." }) });
@@ -7909,10 +8231,10 @@ function Dashboard({ config: config2, options, activeProfile }) {
7909
8231
  dateStr
7910
8232
  ] }),
7911
8233
  /* @__PURE__ */ jsx29(Text27, { children: " " }),
7912
- isRefreshing ? /* @__PURE__ */ jsxs29(Fragment4, { children: [
8234
+ isRefreshing ? /* @__PURE__ */ jsxs29(Fragment5, { children: [
7913
8235
  /* @__PURE__ */ jsx29(Spinner4, { label: "" }),
7914
8236
  /* @__PURE__ */ jsx29(Text27, { color: "cyan", children: " Refreshing..." })
7915
- ] }) : /* @__PURE__ */ jsxs29(Fragment4, { children: [
8237
+ ] }) : /* @__PURE__ */ jsxs29(Fragment5, { children: [
7916
8238
  /* @__PURE__ */ jsx29(RefreshAge, { lastRefresh }),
7917
8239
  consecutiveFailures > 0 ? /* @__PURE__ */ jsx29(Text27, { color: "red", children: " (!)" }) : null
7918
8240
  ] }),
@@ -7991,7 +8313,18 @@ function Dashboard({ config: config2, options, activeProfile }) {
7991
8313
  commentsState: currentCommentsState
7992
8314
  }
7993
8315
  ) : null,
7994
- !ui.state.helpVisible && ui.state.mode !== "overlay:status" && ui.state.mode !== "overlay:create" && ui.state.mode !== "overlay:createNl" && ui.state.mode !== "overlay:bulkAction" && ui.state.mode !== "overlay:confirmPick" && ui.state.mode !== "overlay:detail" && ui.state.mode !== "overlay:nudge" && ui.state.mode !== "overlay:triage" && ui.state.mode !== "focus" ? /* @__PURE__ */ jsx29(
8316
+ ui.state.mode === "zen" ? /* @__PURE__ */ jsx29(Box28, { flexDirection: "column", height: issuesPanelHeight + ACTIVITY_HEIGHT, children: /* @__PURE__ */ jsx29(Panel, { title: "Issues (Zen)", isActive: true, width: usableWidth, children: visibleRows.map((row) => /* @__PURE__ */ jsx29(
8317
+ RowRenderer,
8318
+ {
8319
+ row,
8320
+ selectedId: nav.selectedId,
8321
+ selfLogin: config2.board.assignee,
8322
+ panelWidth: usableWidth,
8323
+ stalenessConfig: config2.board.workflow?.staleness
8324
+ },
8325
+ row.key
8326
+ )) }) }) : null,
8327
+ !ui.state.helpVisible && ui.state.mode !== "overlay:status" && ui.state.mode !== "overlay:create" && ui.state.mode !== "overlay:createNl" && ui.state.mode !== "overlay:bulkAction" && ui.state.mode !== "overlay:confirmPick" && ui.state.mode !== "overlay:detail" && ui.state.mode !== "overlay:nudge" && ui.state.mode !== "overlay:triage" && ui.state.mode !== "focus" && ui.state.mode !== "zen" ? /* @__PURE__ */ jsx29(
7995
8328
  PanelLayout,
7996
8329
  {
7997
8330
  cols: termSize.cols,
@@ -8000,7 +8333,8 @@ function Dashboard({ config: config2, options, activeProfile }) {
8000
8333
  statusesPanel,
8001
8334
  issuesPanel,
8002
8335
  detailPanel,
8003
- activityPanel
8336
+ activityPanel,
8337
+ hideLeftPanel: leftPanelHidden
8004
8338
  }
8005
8339
  ) : null,
8006
8340
  /* @__PURE__ */ jsx29(ToastContainer, { toasts }),
@@ -8037,6 +8371,7 @@ var init_dashboard = __esm({
8037
8371
  init_use_toast();
8038
8372
  init_use_ui_state();
8039
8373
  init_use_workflow_state();
8374
+ init_use_zen_mode();
8040
8375
  init_launch_claude();
8041
8376
  init_action_log();
8042
8377
  init_activity_panel();
@@ -8108,7 +8443,7 @@ __export(fetch_exports, {
8108
8443
  fetchDashboard: () => fetchDashboard,
8109
8444
  fetchRecentActivity: () => fetchRecentActivity
8110
8445
  });
8111
- import { execFileSync as execFileSync3 } from "child_process";
8446
+ import { execFileSync as execFileSync4 } from "child_process";
8112
8447
  function extractSlackUrl(body) {
8113
8448
  if (!body) return void 0;
8114
8449
  const match = body.match(SLACK_URL_RE2);
@@ -8127,7 +8462,7 @@ function extractLinkedIssueNumbers(title, body) {
8127
8462
  }
8128
8463
  function fetchRecentActivity(repoName, shortName2) {
8129
8464
  try {
8130
- const output = execFileSync3(
8465
+ const output = execFileSync4(
8131
8466
  "gh",
8132
8467
  [
8133
8468
  "api",
@@ -8469,7 +8804,7 @@ var init_format_static = __esm({
8469
8804
  // src/cli.ts
8470
8805
  init_ai();
8471
8806
  init_config();
8472
- import { execFile as execFile3, execFileSync as execFileSync4 } from "child_process";
8807
+ import { execFile as execFile3, execFileSync as execFileSync5 } from "child_process";
8473
8808
  import { promisify as promisify2 } from "util";
8474
8809
  import { Command } from "commander";
8475
8810
 
@@ -9081,7 +9416,7 @@ async function resolveRef(ref, config2) {
9081
9416
  }
9082
9417
  }
9083
9418
  var program = new Command();
9084
- program.name("hog").description("Personal command deck \u2014 GitHub Projects dashboard with workflow orchestration").version("1.21.1").option("--json", "Force JSON output").option("--human", "Force human-readable output").hook("preAction", (thisCommand) => {
9419
+ program.name("hog").description("Personal command deck \u2014 GitHub Projects dashboard with workflow orchestration").version("1.22.0").option("--json", "Force JSON output").option("--human", "Force human-readable output").hook("preAction", (thisCommand) => {
9085
9420
  const opts = thisCommand.opts();
9086
9421
  if (opts.json) setFormat("json");
9087
9422
  if (opts.human) setFormat("human");
@@ -9473,7 +9808,7 @@ issueCommand.command("create <text>").description("Create a GitHub issue from na
9473
9808
  const issueNumber = Number.parseInt(url.split("/").pop() ?? "0", 10);
9474
9809
  jsonOut({ ok: true, data: { url, issueNumber, repo } });
9475
9810
  } else {
9476
- execFileSync4("gh", ghArgs, { stdio: "inherit" });
9811
+ execFileSync5("gh", ghArgs, { stdio: "inherit" });
9477
9812
  }
9478
9813
  } catch (err) {
9479
9814
  errorOut(`gh issue create failed: ${err instanceof Error ? err.message : String(err)}`);
@@ -9696,7 +10031,7 @@ issueCommand.command("edit <issueRef>").description("Edit issue fields (title, b
9696
10031
  await execFileAsync2("gh", ghArgs, { encoding: "utf-8", timeout: 3e4 });
9697
10032
  jsonOut({ ok: true, data: { issue: ref.issueNumber, changes } });
9698
10033
  } else {
9699
- execFileSync4("gh", ghArgs, { stdio: "inherit" });
10034
+ execFileSync5("gh", ghArgs, { stdio: "inherit" });
9700
10035
  console.log(`Updated ${ref.repo.shortName}#${ref.issueNumber}: ${changes.join("; ")}`);
9701
10036
  }
9702
10037
  });