ralphctl 0.4.1 → 0.4.3

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 (36) hide show
  1. package/README.md +13 -11
  2. package/dist/{add-CIM72NE3.mjs → add-MG26JWBP.mjs} +6 -6
  3. package/dist/{add-GX7P7XTT.mjs → add-ZZYL4BSF.mjs} +5 -4
  4. package/dist/chunk-2FT37OZX.mjs +1071 -0
  5. package/dist/{chunk-CTP2A436.mjs → chunk-D2HWXEHH.mjs} +9 -2
  6. package/dist/{chunk-JOQO4HMM.mjs → chunk-EGUFQNRB.mjs} +10 -10
  7. package/dist/{chunk-3HJNVQ7N.mjs → chunk-LCY32RW4.mjs} +621 -976
  8. package/dist/{chunk-NUYQK5MN.mjs → chunk-LDSG7G2T.mjs} +1 -1
  9. package/dist/{chunk-7JLZQICD.mjs → chunk-MDE6KPJQ.mjs} +6 -6
  10. package/dist/{chunk-3QBEBKMZ.mjs → chunk-Q4AVHUZL.mjs} +7 -7
  11. package/dist/{chunk-YCDUVPRT.mjs → chunk-RQGD5WS6.mjs} +4 -72
  12. package/dist/{chunk-D2YGPLIV.mjs → chunk-TDBEEHTS.mjs} +213 -8
  13. package/dist/{chunk-SM4GGZSU.mjs → chunk-WOMGKKZY.mjs} +152 -179
  14. package/dist/{chunk-FKMKOWLA.mjs → chunk-WZTY77GY.mjs} +75 -1
  15. package/dist/cli.mjs +68 -19
  16. package/dist/{create-7WFSCMP4.mjs → create-PQK6KKRD.mjs} +5 -5
  17. package/dist/{handle-BBAZJ44Y.mjs → handle-SYVCFI6Y.mjs} +1 -1
  18. package/dist/{mount-2N6H5CWA.mjs → mount-2ANLHHQE.mjs} +556 -318
  19. package/dist/{project-2IE7VWDB.mjs → project-JF47ZWMF.mjs} +2 -2
  20. package/dist/prompts/check-script-discover.md +69 -0
  21. package/dist/prompts/ideate-auto.md +26 -1
  22. package/dist/prompts/ideate.md +5 -1
  23. package/dist/prompts/plan-auto.md +30 -2
  24. package/dist/prompts/plan-common-examples.md +82 -0
  25. package/dist/prompts/plan-common.md +26 -78
  26. package/dist/prompts/plan-interactive.md +6 -2
  27. package/dist/prompts/repo-onboard.md +111 -0
  28. package/dist/prompts/sprint-feedback.md +6 -2
  29. package/dist/prompts/task-evaluation.md +25 -10
  30. package/dist/prompts/task-execution.md +13 -13
  31. package/dist/prompts/ticket-refine.md +4 -0
  32. package/dist/prompts/validation-checklist.md +4 -0
  33. package/dist/{resolver-EOE5WUMV.mjs → resolver-PG2DZEBX.mjs} +3 -3
  34. package/dist/{sprint-OGOFEJJH.mjs → sprint-54DOSIJK.mjs} +3 -3
  35. package/dist/{start-IUDCXIEA.mjs → start-2SZTBKGF.mjs} +7 -5
  36. package/package.json +6 -6
@@ -14,18 +14,17 @@ import {
14
14
  checkGlabInstalled,
15
15
  checkNodeVersion,
16
16
  checkProjectPaths,
17
+ checkRepoOnboarding,
17
18
  cliMetadata,
18
19
  configSetCommand,
19
20
  configShowCommand,
20
21
  createSharedDeps,
21
22
  doctorCommand,
22
23
  exportRequirementsToMarkdown,
23
- getAllSchemaEntries,
24
24
  getNextAction,
25
25
  glyphs,
26
26
  inkColors,
27
27
  loadDashboardData,
28
- parseConfigValue,
29
28
  progressLogCommand,
30
29
  progressShowCommand,
31
30
  projectListCommand,
@@ -60,56 +59,54 @@ import {
60
59
  ticketRefineCommand,
61
60
  ticketRemoveCommand,
62
61
  ticketShowCommand,
63
- useCurrentPrompt,
64
- validateConfigValue
65
- } from "./chunk-SM4GGZSU.mjs";
62
+ useCurrentPrompt
63
+ } from "./chunk-WOMGKKZY.mjs";
66
64
  import {
67
65
  PromptCancelledError,
68
- projectAddCommand
69
- } from "./chunk-D2YGPLIV.mjs";
66
+ detectCheckScriptCandidates,
67
+ discoverCheckScriptWithAi,
68
+ getAllSchemaEntries,
69
+ getConfigDefaultValue,
70
+ parseConfigValue,
71
+ projectAddCommand,
72
+ suggestCheckScript,
73
+ validateConfigValue
74
+ } from "./chunk-TDBEEHTS.mjs";
70
75
  import {
71
76
  sprintCreateCommand
72
- } from "./chunk-3QBEBKMZ.mjs";
77
+ } from "./chunk-Q4AVHUZL.mjs";
73
78
  import {
74
79
  ticketAddCommand
75
- } from "./chunk-7JLZQICD.mjs";
76
- import {
77
- addProjectRepo,
78
- createProject,
79
- getProject,
80
- getProjectById,
81
- getRepoById,
82
- listProjects,
83
- projectExists,
84
- removeProject,
85
- removeProjectRepo,
86
- resolveRepoPath,
87
- updateProject
88
- } from "./chunk-NUYQK5MN.mjs";
80
+ } from "./chunk-MDE6KPJQ.mjs";
89
81
  import {
90
82
  addTask,
91
83
  areAllTasksDone,
92
84
  branchExists,
93
85
  createExecuteSprintPipeline,
94
86
  createIdeatePipeline,
87
+ createOnboardPipeline,
95
88
  createPlanPipeline,
96
89
  createRefinePipeline,
97
- enterAltScreen,
98
90
  executePipeline,
99
- exitAltScreen,
100
91
  getDefaultBranch,
101
92
  getNextTask,
102
93
  getTask,
103
94
  getTasks,
104
95
  isGhAvailable,
105
96
  listTasks,
106
- registerTuiInstance,
107
97
  removeTask,
108
98
  reorderTask,
109
99
  sprintStartCommand,
110
- updateTaskStatus,
100
+ updateTaskStatus
101
+ } from "./chunk-LCY32RW4.mjs";
102
+ import {
103
+ ProviderAiSessionAdapter,
104
+ SignalParser,
105
+ enterAltScreen,
106
+ exitAltScreen,
107
+ registerTuiInstance,
111
108
  withSuspendedTui
112
- } from "./chunk-3HJNVQ7N.mjs";
109
+ } from "./chunk-2FT37OZX.mjs";
113
110
  import {
114
111
  addTicket,
115
112
  allRequirementsApproved,
@@ -121,38 +118,51 @@ import {
121
118
  removeTicket,
122
119
  truncate,
123
120
  updateTicket
124
- } from "./chunk-JOQO4HMM.mjs";
121
+ } from "./chunk-EGUFQNRB.mjs";
125
122
  import "./chunk-CFUVE2BP.mjs";
126
123
  import {
127
124
  getPrompt,
128
125
  getSharedDeps,
129
126
  setSharedDeps
130
127
  } from "./chunk-747KW2RW.mjs";
128
+ import {
129
+ addProjectRepo,
130
+ createProject,
131
+ getProject,
132
+ getProjectById,
133
+ getRepoById,
134
+ listProjects,
135
+ projectExists,
136
+ removeProject,
137
+ removeProjectRepo,
138
+ resolveRepoPath,
139
+ updateProject
140
+ } from "./chunk-LDSG7G2T.mjs";
131
141
  import {
132
142
  closeSprint,
133
143
  createSprint,
134
144
  deleteSprint,
135
- getAiProvider,
136
- getConfig,
137
- getCurrentSprint,
138
145
  getCurrentSprintOrThrow,
139
- getEditor,
140
- getEvaluationIterations,
141
146
  getProgress,
142
147
  getSprint,
143
148
  listSprints,
144
149
  logProgress,
145
150
  resolveSprintId,
146
- saveSprint,
147
- setAiProvider,
148
- setCurrentSprint
149
- } from "./chunk-YCDUVPRT.mjs";
151
+ saveSprint
152
+ } from "./chunk-RQGD5WS6.mjs";
150
153
  import {
151
154
  banner,
152
155
  colors,
156
+ getAiProvider,
157
+ getConfig,
158
+ getCurrentSprint,
159
+ getEditor,
160
+ getEvaluationIterations,
153
161
  getRandomQuote,
154
- gradients
155
- } from "./chunk-FKMKOWLA.mjs";
162
+ gradients,
163
+ setAiProvider,
164
+ setCurrentSprint
165
+ } from "./chunk-WZTY77GY.mjs";
156
166
  import {
157
167
  ensureError,
158
168
  wrapAsync
@@ -167,7 +177,7 @@ import {
167
177
  getTasksFilePath,
168
178
  readTextFile,
169
179
  readValidatedJson
170
- } from "./chunk-CTP2A436.mjs";
180
+ } from "./chunk-D2HWXEHH.mjs";
171
181
  import "./chunk-57UWLHRH.mjs";
172
182
 
173
183
  // src/integration/ui/tui/runtime/mount.tsx
@@ -320,11 +330,11 @@ var InkSink = class _InkSink {
320
330
  };
321
331
 
322
332
  // src/integration/ui/tui/views/app.tsx
323
- import { useEffect as useEffect28, useState as useState30 } from "react";
333
+ import { useEffect as useEffect29, useState as useState30 } from "react";
324
334
  import { Box as Box35, useStdout } from "ink";
325
335
 
326
336
  // src/integration/ui/tui/views/view-router.tsx
327
- import { useCallback as useCallback10, useMemo as useMemo35, useRef as useRef3, useState as useState29 } from "react";
337
+ import { useCallback as useCallback11, useMemo as useMemo36, useRef as useRef4, useState as useState29 } from "react";
328
338
  import { Box as Box34, useApp, useInput as useInput19 } from "ink";
329
339
 
330
340
  // src/integration/ui/tui/components/banner.tsx
@@ -581,6 +591,11 @@ function buildProjectSubMenu() {
581
591
  description: "Add repository to project"
582
592
  });
583
593
  items.push({ name: "Remove Repository", value: "repo remove", description: "Remove repository" });
594
+ items.push({
595
+ name: "Onboard repo for agentic work",
596
+ value: "onboard",
597
+ description: "AI-assisted project context file + check script"
598
+ });
584
599
  items.push(line());
585
600
  items.push({ name: "Remove", value: "remove", description: "Remove a project" });
586
601
  items.push({ name: "Back", value: "back", description: "Return to main menu" });
@@ -1169,7 +1184,8 @@ var WORKFLOW_VIEWS = {
1169
1184
  remove: "project-remove",
1170
1185
  "repo add": "project-repo-add",
1171
1186
  "repo remove": "project-repo-remove",
1172
- edit: "project-edit"
1187
+ edit: "project-edit",
1188
+ onboard: "project-onboard"
1173
1189
  },
1174
1190
  progress: {
1175
1191
  log: "progress-log",
@@ -2238,9 +2254,9 @@ import { Box as Box19, Text as Text18 } from "ink";
2238
2254
  import "react";
2239
2255
  import { Box as Box18, Text as Text17 } from "ink";
2240
2256
  import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
2241
- function FieldList({ fields, labelWidth = FIELD_LABEL_WIDTH }) {
2257
+ function FieldList({ fields, labelWidth: labelWidth2 = FIELD_LABEL_WIDTH }) {
2242
2258
  return /* @__PURE__ */ jsx19(Box18, { flexDirection: "column", children: fields.map(([label, value]) => /* @__PURE__ */ jsxs17(Box18, { children: [
2243
- /* @__PURE__ */ jsx19(Text17, { dimColor: true, children: (label + ":").padEnd(labelWidth) }),
2259
+ /* @__PURE__ */ jsx19(Text17, { dimColor: true, children: (label + ":").padEnd(labelWidth2) }),
2244
2260
  /* @__PURE__ */ jsx19(Text17, { children: ` ${value}` })
2245
2261
  ] }, label)) });
2246
2262
  }
@@ -4411,6 +4427,50 @@ function renderBody15(phase) {
4411
4427
  // src/integration/ui/tui/views/workflows/project-add-view.tsx
4412
4428
  import { resolve } from "path";
4413
4429
  import { useMemo as useMemo22 } from "react";
4430
+
4431
+ // src/integration/ui/tui/views/workflows/collect-check-script.ts
4432
+ async function collectCheckScript(repoPath, setStep) {
4433
+ const prompt = getPrompt();
4434
+ setStep("check-script");
4435
+ let detection;
4436
+ try {
4437
+ detection = detectCheckScriptCandidates(repoPath);
4438
+ } catch {
4439
+ detection = null;
4440
+ }
4441
+ let suggested = detection ? suggestCheckScript(repoPath) : null;
4442
+ if (suggested === null) {
4443
+ const config = await getConfig();
4444
+ const enabled = config.aiCheckScriptDiscovery ?? getConfigDefaultValue("aiCheckScriptDiscovery");
4445
+ if (enabled && config.aiProvider) {
4446
+ const wantAi = await prompt.confirm({
4447
+ message: "No ecosystem detected. Ask AI to inspect the repo and suggest a check script?",
4448
+ default: true
4449
+ });
4450
+ if (wantAi) {
4451
+ setStep("discovering");
4452
+ const aiSession = new ProviderAiSessionAdapter();
4453
+ const signalParser = new SignalParser();
4454
+ const discoverR = await wrapAsync(async () => {
4455
+ await aiSession.ensureReady();
4456
+ return discoverCheckScriptWithAi(repoPath, aiSession, signalParser);
4457
+ }, ensureError);
4458
+ if (discoverR.ok && discoverR.value) {
4459
+ suggested = discoverR.value;
4460
+ }
4461
+ setStep("check-script");
4462
+ }
4463
+ }
4464
+ }
4465
+ const value = await prompt.input({
4466
+ message: "Check script (optional):",
4467
+ default: suggested ?? void 0
4468
+ });
4469
+ const trimmed = value.trim();
4470
+ return trimmed.length > 0 ? trimmed : void 0;
4471
+ }
4472
+
4473
+ // src/integration/ui/tui/views/workflows/project-add-view.tsx
4414
4474
  import { jsx as jsx41 } from "react/jsx-runtime";
4415
4475
  var TITLE16 = "Add Project";
4416
4476
  var HINTS_RUNNING16 = [{ key: "Esc", action: "cancel" }];
@@ -4448,11 +4508,14 @@ function ProjectAddView() {
4448
4508
  });
4449
4509
  const absolute = resolve(repoPath.trim().replace(/^~(\/|$)/, `${process.env["HOME"] ?? ""}$1`));
4450
4510
  const repoName = absolute.split(/[\\/]/).pop() ?? "repo";
4511
+ const checkScript = await collectCheckScript(absolute, (next) => {
4512
+ setPhase({ kind: "running", step: next });
4513
+ });
4451
4514
  setPhase({ kind: "running", step: "saving" });
4452
4515
  const project = await createProject({
4453
4516
  name: name.trim(),
4454
4517
  displayName: display.trim(),
4455
- repositories: [{ name: repoName, path: absolute }]
4518
+ repositories: [{ name: repoName, path: absolute, ...checkScript ? { checkScript } : {} }]
4456
4519
  });
4457
4520
  setPhase({ kind: "done", project });
4458
4521
  }
@@ -4494,6 +4557,8 @@ function stepLabel7(step) {
4494
4557
  if (step === "name") return "Awaiting project slug\u2026";
4495
4558
  if (step === "display") return "Awaiting display name\u2026";
4496
4559
  if (step === "repo-path") return "Awaiting repository path\u2026";
4560
+ if (step === "check-script") return "Awaiting check-script confirmation\u2026";
4561
+ if (step === "discovering") return "Discovering check script with AI\u2026";
4497
4562
  return "Saving project\u2026";
4498
4563
  }
4499
4564
 
@@ -4597,8 +4662,15 @@ function ProjectRepoAddView() {
4597
4662
  });
4598
4663
  const absolute = resolve2(repoPath.trim().replace(/^~(\/|$)/, `${process.env["HOME"] ?? ""}$1`));
4599
4664
  const repoName = absolute.split(/[\\/]/).pop() ?? "repo";
4665
+ const checkScript = await collectCheckScript(absolute, (next) => {
4666
+ setPhase({ kind: "running", step: next });
4667
+ });
4600
4668
  setPhase({ kind: "running", step: "saving" });
4601
- const project = await addProjectRepo(projectName, { name: repoName, path: absolute });
4669
+ const project = await addProjectRepo(projectName, {
4670
+ name: repoName,
4671
+ path: absolute,
4672
+ ...checkScript ? { checkScript } : {}
4673
+ });
4602
4674
  setPhase({ kind: "done", project, repoName });
4603
4675
  }
4604
4676
  });
@@ -4632,6 +4704,8 @@ function renderBody18(phase) {
4632
4704
  function stepLabel9(step) {
4633
4705
  if (step === "project") return "Awaiting project selection\u2026";
4634
4706
  if (step === "path") return "Awaiting repository path\u2026";
4707
+ if (step === "check-script") return "Awaiting check-script confirmation\u2026";
4708
+ if (step === "discovering") return "Discovering check script with AI\u2026";
4635
4709
  return "Saving repository\u2026";
4636
4710
  }
4637
4711
 
@@ -4804,14 +4878,109 @@ function stepLabel11(step) {
4804
4878
  return "Saving project\u2026";
4805
4879
  }
4806
4880
 
4881
+ // src/integration/ui/tui/views/workflows/project-onboard-view.tsx
4882
+ import { useMemo as useMemo27 } from "react";
4883
+ import { jsx as jsx46 } from "react/jsx-runtime";
4884
+ var TITLE21 = "Onboard Repository";
4885
+ var HINTS_RUNNING21 = [{ key: "Esc", action: "cancel" }];
4886
+ var HINTS_DONE21 = [
4887
+ { key: "Enter", action: "home" },
4888
+ { key: "Esc", action: "back" }
4889
+ ];
4890
+ function ProjectOnboardView({
4891
+ projectName: preselectedProject,
4892
+ repo: preselectedRepo
4893
+ } = {}) {
4894
+ const { phase } = useWorkflow({
4895
+ initial: preselectedProject ? { kind: "running", step: "onboarding" } : { kind: "running", step: "select-project" },
4896
+ onError: (message) => ({ kind: "error", message }),
4897
+ run: async ({ setPhase }) => {
4898
+ const shared = getSharedDeps();
4899
+ const prompt = shared.prompt;
4900
+ const projects = await listProjects();
4901
+ if (projects.length === 0) {
4902
+ setPhase({ kind: "no-projects" });
4903
+ return;
4904
+ }
4905
+ let projectName;
4906
+ if (preselectedProject) {
4907
+ projectName = preselectedProject;
4908
+ } else {
4909
+ setPhase({ kind: "running", step: "select-project" });
4910
+ projectName = await prompt.select({
4911
+ message: "Select a project to onboard:",
4912
+ choices: projects.map((p) => ({
4913
+ label: `${p.displayName} (${p.name})`,
4914
+ value: p.name,
4915
+ description: `${String(p.repositories.length)} repo${p.repositories.length === 1 ? "" : "s"}`
4916
+ }))
4917
+ });
4918
+ }
4919
+ setPhase({ kind: "running", step: "onboarding" });
4920
+ const options = preselectedRepo ? { repo: preselectedRepo } : {};
4921
+ const pipeline = createOnboardPipeline(shared, options);
4922
+ const initialContext = { sprintId: "", projectName };
4923
+ const result = await executePipeline(pipeline, initialContext);
4924
+ if (!result.ok) {
4925
+ setPhase({ kind: "error", message: result.error.message });
4926
+ return;
4927
+ }
4928
+ const ctx = result.value.context;
4929
+ const agentsMd = ctx.agentsMdFinal ?? ctx.agentsMdDraft ?? "";
4930
+ setPhase({
4931
+ kind: "done",
4932
+ projectName,
4933
+ writtenPath: ctx.writtenPath,
4934
+ checkScript: ctx.checkScriptFinal ?? null,
4935
+ driftWarnings: ctx.driftWarnings ?? [],
4936
+ lowConfidence: agentsMd.includes("LOW-CONFIDENCE:"),
4937
+ alreadyCurrent: ctx.alreadyCurrent
4938
+ });
4939
+ }
4940
+ });
4941
+ const hints = useMemo27(() => phase.kind === "running" ? HINTS_RUNNING21 : HINTS_DONE21, [phase.kind]);
4942
+ useViewHints(hints);
4943
+ return /* @__PURE__ */ jsx46(ViewShell, { title: TITLE21, children: renderBody21(phase) });
4944
+ }
4945
+ function renderBody21(phase) {
4946
+ switch (phase.kind) {
4947
+ case "running":
4948
+ return /* @__PURE__ */ jsx46(Spinner, { label: stepLabel12(phase.step) });
4949
+ case "no-projects":
4950
+ return /* @__PURE__ */ jsx46(ResultCard, { kind: "info", title: "No projects registered" });
4951
+ case "error":
4952
+ return /* @__PURE__ */ jsx46(ResultCard, { kind: "error", title: "Onboarding failed", lines: [phase.message] });
4953
+ case "done": {
4954
+ const fields = [["Project", phase.projectName]];
4955
+ if (phase.writtenPath) fields.push(["Project context file", phase.writtenPath]);
4956
+ if (phase.checkScript) fields.push(["Check script", phase.checkScript]);
4957
+ if (phase.driftWarnings && phase.driftWarnings.length > 0) {
4958
+ fields.push(["Warnings", phase.driftWarnings.join("; ")]);
4959
+ }
4960
+ if (phase.lowConfidence) {
4961
+ fields.push(["Review", "Low-confidence sections present \u2014 re-run interactively to tighten"]);
4962
+ }
4963
+ if (phase.alreadyCurrent) {
4964
+ return /* @__PURE__ */ jsx46(ResultCard, { kind: "info", title: "Already current", fields });
4965
+ }
4966
+ const nextSteps = phase.lowConfidence ? [{ action: "Open the project context file and replace LOW-CONFIDENCE lines with concrete facts." }] : void 0;
4967
+ return /* @__PURE__ */ jsx46(ResultCard, { kind: "success", title: "Repository onboarded", fields, nextSteps });
4968
+ }
4969
+ }
4970
+ }
4971
+ function stepLabel12(step) {
4972
+ if (step === "select-project") return "Awaiting project selection\u2026";
4973
+ return "Inventorying repository and reviewing proposal\u2026";
4974
+ }
4975
+
4807
4976
  // src/integration/ui/tui/views/browse/sprint-list-view.tsx
4808
- import { useEffect as useEffect14, useMemo as useMemo28, useState as useState15 } from "react";
4977
+ import { useEffect as useEffect15, useMemo as useMemo29, useState as useState15 } from "react";
4809
4978
  import { useInput as useInput11 } from "ink";
4810
4979
 
4811
4980
  // src/integration/ui/tui/components/list-view.tsx
4812
- import React47, { useMemo as useMemo27, useState as useState14 } from "react";
4981
+ import React48, { useEffect as useEffect14, useMemo as useMemo28, useState as useState14 } from "react";
4813
4982
  import { Box as Box25, Text as Text24, useInput as useInput10 } from "ink";
4814
- import { jsx as jsx46, jsxs as jsxs24 } from "react/jsx-runtime";
4983
+ import { jsx as jsx47, jsxs as jsxs24 } from "react/jsx-runtime";
4815
4984
  var DEFAULT_PAGE_SIZE = 12;
4816
4985
  function computeWidths(columns, rows, totalWidth) {
4817
4986
  const widths = columns.map((col) => {
@@ -4840,10 +5009,16 @@ function ListView({
4840
5009
  emptyLabel = "(empty)",
4841
5010
  pageSize = DEFAULT_PAGE_SIZE,
4842
5011
  initialCursor = 0,
4843
- disabled = false
5012
+ disabled = false,
5013
+ onCursorChange
4844
5014
  }) {
4845
5015
  const [cursor, setCursor] = useState14(() => Math.max(0, Math.min(initialCursor, rows.length - 1)));
4846
- const widths = useMemo27(() => computeWidths(columns, rows, 72), [columns, rows]);
5016
+ useEffect14(() => {
5017
+ if (!onCursorChange) return;
5018
+ const row = rows[cursor];
5019
+ if (row !== void 0) onCursorChange(row, cursor);
5020
+ }, [cursor, rows, onCursorChange]);
5021
+ const widths = useMemo28(() => computeWidths(columns, rows, 72), [columns, rows]);
4847
5022
  useInput10(
4848
5023
  (_input, key) => {
4849
5024
  if (rows.length === 0) return;
@@ -4859,17 +5034,17 @@ function ListView({
4859
5034
  { isActive: !disabled }
4860
5035
  );
4861
5036
  if (rows.length === 0) {
4862
- return /* @__PURE__ */ jsx46(Box25, { children: /* @__PURE__ */ jsx46(Text24, { dimColor: true, children: emptyLabel }) });
5037
+ return /* @__PURE__ */ jsx47(Box25, { children: /* @__PURE__ */ jsx47(Text24, { dimColor: true, children: emptyLabel }) });
4863
5038
  }
4864
5039
  const windowStart = Math.max(0, Math.min(cursor - Math.floor(pageSize / 2), rows.length - pageSize));
4865
5040
  const windowEnd = Math.min(rows.length, windowStart + pageSize);
4866
5041
  const visible = rows.slice(windowStart, windowEnd);
4867
5042
  return /* @__PURE__ */ jsxs24(Box25, { flexDirection: "column", children: [
4868
5043
  /* @__PURE__ */ jsxs24(Box25, { children: [
4869
- /* @__PURE__ */ jsx46(Text24, { color: inkColors.muted, bold: true, children: " " }),
4870
- columns.map((col, i) => /* @__PURE__ */ jsxs24(React47.Fragment, { children: [
4871
- /* @__PURE__ */ jsx46(Text24, { color: inkColors.muted, bold: true, children: pad(col.header.toUpperCase(), widths[i] ?? col.header.length, col.align) }),
4872
- i < columns.length - 1 ? /* @__PURE__ */ jsx46(Text24, { color: inkColors.muted, children: " " }) : null
5044
+ /* @__PURE__ */ jsx47(Text24, { color: inkColors.muted, bold: true, children: " " }),
5045
+ columns.map((col, i) => /* @__PURE__ */ jsxs24(React48.Fragment, { children: [
5046
+ /* @__PURE__ */ jsx47(Text24, { color: inkColors.muted, bold: true, children: pad(col.header.toUpperCase(), widths[i] ?? col.header.length, col.align) }),
5047
+ i < columns.length - 1 ? /* @__PURE__ */ jsx47(Text24, { color: inkColors.muted, children: " " }) : null
4873
5048
  ] }, col.header))
4874
5049
  ] }),
4875
5050
  visible.map((row, i) => {
@@ -4877,18 +5052,18 @@ function ListView({
4877
5052
  const selected = absoluteIdx === cursor;
4878
5053
  const indicatorColor = selected ? inkColors.highlight : void 0;
4879
5054
  return /* @__PURE__ */ jsxs24(Box25, { children: [
4880
- /* @__PURE__ */ jsx46(Text24, { color: indicatorColor, bold: selected, children: selected ? glyphs.actionCursor : " " }),
5055
+ /* @__PURE__ */ jsx47(Text24, { color: indicatorColor, bold: selected, children: selected ? glyphs.actionCursor : " " }),
4881
5056
  columns.map((col, ci) => {
4882
5057
  const text = pad(col.cell(row), widths[ci] ?? col.cell(row).length, col.align);
4883
5058
  const cellColor = col.color?.(row) ?? (selected ? inkColors.highlight : void 0);
4884
- return /* @__PURE__ */ jsxs24(React47.Fragment, { children: [
4885
- /* @__PURE__ */ jsx46(Text24, { color: cellColor, bold: selected && ci === 0, children: text }),
4886
- ci < columns.length - 1 ? /* @__PURE__ */ jsx46(Text24, { children: " " }) : null
5059
+ return /* @__PURE__ */ jsxs24(React48.Fragment, { children: [
5060
+ /* @__PURE__ */ jsx47(Text24, { color: cellColor, bold: selected && ci === 0, children: text }),
5061
+ ci < columns.length - 1 ? /* @__PURE__ */ jsx47(Text24, { children: " " }) : null
4887
5062
  ] }, col.header);
4888
5063
  })
4889
5064
  ] }, absoluteIdx);
4890
5065
  }),
4891
- rows.length > pageSize ? /* @__PURE__ */ jsx46(Box25, { marginTop: spacing.section, children: /* @__PURE__ */ jsxs24(Text24, { dimColor: true, children: [
5066
+ rows.length > pageSize ? /* @__PURE__ */ jsx47(Box25, { marginTop: spacing.section, children: /* @__PURE__ */ jsxs24(Text24, { dimColor: true, children: [
4892
5067
  String(cursor + 1),
4893
5068
  " / ",
4894
5069
  String(rows.length),
@@ -4929,7 +5104,7 @@ function StatusChip({ label, kind = "info" }) {
4929
5104
  }
4930
5105
 
4931
5106
  // src/integration/ui/tui/views/browse/sprint-list-view.tsx
4932
- import { jsx as jsx47 } from "react/jsx-runtime";
5107
+ import { jsx as jsx48 } from "react/jsx-runtime";
4933
5108
  function statusChipText(status) {
4934
5109
  return `[${status.toUpperCase()}]`;
4935
5110
  }
@@ -5000,7 +5175,7 @@ function SprintListView() {
5000
5175
  const [state, setState] = useState15({ kind: "loading" });
5001
5176
  const [filter, setFilter] = useState15("all");
5002
5177
  useViewHints(state.kind === "ready" ? HINTS_READY2 : HINTS_EMPTY);
5003
- useEffect14(() => {
5178
+ useEffect15(() => {
5004
5179
  const ctl = { cancelled: false };
5005
5180
  void (async () => {
5006
5181
  try {
@@ -5056,12 +5231,12 @@ function SprintListView() {
5056
5231
  }
5057
5232
  });
5058
5233
  const title = filter === "all" ? TITLE_BASE : `${TITLE_BASE} \xB7 filter: ${filter}`;
5059
- const filtered = useMemo28(() => {
5234
+ const filtered = useMemo29(() => {
5060
5235
  if (state.kind !== "ready") return [];
5061
5236
  if (filter === "all") return state.sprints;
5062
5237
  return state.sprints.filter((s) => s.status === filter);
5063
5238
  }, [state, filter]);
5064
- return /* @__PURE__ */ jsx47(ViewShell, { title, children: state.kind === "loading" ? /* @__PURE__ */ jsx47(Spinner, { label: "Loading sprints\u2026" }) : state.kind === "empty" ? /* @__PURE__ */ jsx47(ResultCard, { kind: "info", title: "No sprints yet", lines: ["Press `n` to create one."] }) : state.kind === "error" ? /* @__PURE__ */ jsx47(ResultCard, { kind: "error", title: "Could not load sprints", lines: [state.message] }) : filtered.length === 0 ? /* @__PURE__ */ jsx47(ResultCard, { kind: "info", title: `No sprints with status '${filter}'`, lines: ["Press f to cycle the filter."] }) : /* @__PURE__ */ jsx47(
5239
+ return /* @__PURE__ */ jsx48(ViewShell, { title, children: state.kind === "loading" ? /* @__PURE__ */ jsx48(Spinner, { label: "Loading sprints\u2026" }) : state.kind === "empty" ? /* @__PURE__ */ jsx48(ResultCard, { kind: "info", title: "No sprints yet", lines: ["Press `n` to create one."] }) : state.kind === "error" ? /* @__PURE__ */ jsx48(ResultCard, { kind: "error", title: "Could not load sprints", lines: [state.message] }) : filtered.length === 0 ? /* @__PURE__ */ jsx48(ResultCard, { kind: "info", title: `No sprints with status '${filter}'`, lines: ["Press f to cycle the filter."] }) : /* @__PURE__ */ jsx48(
5065
5240
  ListView,
5066
5241
  {
5067
5242
  rows: filtered,
@@ -5075,10 +5250,10 @@ function SprintListView() {
5075
5250
  }
5076
5251
 
5077
5252
  // src/integration/ui/tui/views/browse/sprint-show-view.tsx
5078
- import { useEffect as useEffect15, useMemo as useMemo29, useState as useState16 } from "react";
5253
+ import { useEffect as useEffect16, useMemo as useMemo30, useState as useState16 } from "react";
5079
5254
  import { Box as Box26, Text as Text26, useInput as useInput12 } from "ink";
5080
- import { jsx as jsx48, jsxs as jsxs26 } from "react/jsx-runtime";
5081
- var TITLE21 = "Sprint Details";
5255
+ import { jsx as jsx49, jsxs as jsxs26 } from "react/jsx-runtime";
5256
+ var TITLE22 = "Sprint Details";
5082
5257
  var HINTS = [
5083
5258
  { key: "\u2191/\u2193", action: "move" },
5084
5259
  { key: "Enter", action: "open" }
@@ -5087,7 +5262,7 @@ function SprintShowView({ sprintId }) {
5087
5262
  const router = useRouter();
5088
5263
  const [state, setState] = useState16({ kind: "loading" });
5089
5264
  useViewHints(HINTS);
5090
- useEffect15(() => {
5265
+ useEffect16(() => {
5091
5266
  const ctl = { cancelled: false };
5092
5267
  void (async () => {
5093
5268
  try {
@@ -5103,11 +5278,11 @@ function SprintShowView({ sprintId }) {
5103
5278
  ctl.cancelled = true;
5104
5279
  };
5105
5280
  }, [sprintId]);
5106
- const rows = useMemo29(() => {
5281
+ const rows = useMemo30(() => {
5107
5282
  if (state.kind !== "ready") return [];
5108
5283
  return buildRows2(state.sprint, state.tasks);
5109
5284
  }, [state]);
5110
- const sections = useMemo29(() => rows.filter((r) => r.separator !== true), [rows]);
5285
+ const sections = useMemo30(() => rows.filter((r) => r.separator !== true), [rows]);
5111
5286
  const [cursor, setCursor] = useState16(0);
5112
5287
  useInput12(
5113
5288
  (_input, key) => {
@@ -5121,11 +5296,11 @@ function SprintShowView({ sprintId }) {
5121
5296
  },
5122
5297
  { isActive: state.kind === "ready" && sections.length > 0 }
5123
5298
  );
5124
- return /* @__PURE__ */ jsx48(ViewShell, { title: TITLE21, children: renderBody21(state, rows, sections, cursor) });
5299
+ return /* @__PURE__ */ jsx49(ViewShell, { title: TITLE22, children: renderBody22(state, rows, sections, cursor) });
5125
5300
  }
5126
- function renderBody21(state, rows, sections, cursor) {
5127
- if (state.kind === "loading") return /* @__PURE__ */ jsx48(Spinner, { label: "Loading sprint\u2026" });
5128
- if (state.kind === "error") return /* @__PURE__ */ jsx48(ResultCard, { kind: "error", title: "Could not load sprint", lines: [state.message] });
5301
+ function renderBody22(state, rows, sections, cursor) {
5302
+ if (state.kind === "loading") return /* @__PURE__ */ jsx49(Spinner, { label: "Loading sprint\u2026" });
5303
+ if (state.kind === "error") return /* @__PURE__ */ jsx49(ResultCard, { kind: "error", title: "Could not load sprint", lines: [state.message] });
5129
5304
  const { sprint, tasks, project } = state;
5130
5305
  const projectLabel = project ? `${project.displayName} (${project.name})` : sprint.projectId;
5131
5306
  const approved = sprint.tickets.filter((t) => t.requirementStatus === "approved").length;
@@ -5133,11 +5308,11 @@ function renderBody21(state, rows, sections, cursor) {
5133
5308
  const activeSectionId = sections[cursor]?.destination.id;
5134
5309
  return /* @__PURE__ */ jsxs26(Box26, { flexDirection: "column", children: [
5135
5310
  /* @__PURE__ */ jsxs26(Box26, { children: [
5136
- /* @__PURE__ */ jsx48(Text26, { bold: true, children: sprint.name }),
5137
- /* @__PURE__ */ jsx48(Text26, { children: " " }),
5138
- /* @__PURE__ */ jsx48(StatusChip, { label: sprint.status, kind: chipKindForSprintStatus(sprint.status) })
5311
+ /* @__PURE__ */ jsx49(Text26, { bold: true, children: sprint.name }),
5312
+ /* @__PURE__ */ jsx49(Text26, { children: " " }),
5313
+ /* @__PURE__ */ jsx49(StatusChip, { label: sprint.status, kind: chipKindForSprintStatus(sprint.status) })
5139
5314
  ] }),
5140
- /* @__PURE__ */ jsx48(Box26, { marginTop: spacing.section, children: /* @__PURE__ */ jsx48(
5315
+ /* @__PURE__ */ jsx49(Box26, { marginTop: spacing.section, children: /* @__PURE__ */ jsx49(
5141
5316
  FieldList,
5142
5317
  {
5143
5318
  fields: [
@@ -5153,22 +5328,22 @@ function renderBody21(state, rows, sections, cursor) {
5153
5328
  }
5154
5329
  ) }),
5155
5330
  /* @__PURE__ */ jsxs26(Box26, { marginTop: spacing.section, flexDirection: "column", children: [
5156
- /* @__PURE__ */ jsx48(Text26, { color: inkColors.muted, bold: true, children: "Sections" }),
5157
- rows.map((row, i) => /* @__PURE__ */ jsx48(RowRenderer, { row, isActive: row.separator !== true && row.destination.id === activeSectionId }, i))
5331
+ /* @__PURE__ */ jsx49(Text26, { color: inkColors.muted, bold: true, children: "Sections" }),
5332
+ rows.map((row, i) => /* @__PURE__ */ jsx49(RowRenderer, { row, isActive: row.separator !== true && row.destination.id === activeSectionId }, i))
5158
5333
  ] })
5159
5334
  ] });
5160
5335
  }
5161
5336
  function RowRenderer({ row, isActive }) {
5162
5337
  if (row.separator === true) {
5163
- return /* @__PURE__ */ jsx48(Box26, { paddingLeft: spacing.indent, children: /* @__PURE__ */ jsx48(Text26, { color: inkColors.muted, dimColor: true, children: glyphs.sectionRule.repeat(2) }) });
5338
+ return /* @__PURE__ */ jsx49(Box26, { paddingLeft: spacing.indent, children: /* @__PURE__ */ jsx49(Text26, { color: inkColors.muted, dimColor: true, children: glyphs.sectionRule.repeat(2) }) });
5164
5339
  }
5165
5340
  return /* @__PURE__ */ jsxs26(Box26, { paddingLeft: spacing.indent, children: [
5166
- /* @__PURE__ */ jsx48(Text26, { color: isActive ? inkColors.highlight : void 0, bold: isActive, children: isActive ? glyphs.actionCursor : " " }),
5341
+ /* @__PURE__ */ jsx49(Text26, { color: isActive ? inkColors.highlight : void 0, bold: isActive, children: isActive ? glyphs.actionCursor : " " }),
5167
5342
  /* @__PURE__ */ jsxs26(Text26, { color: isActive ? inkColors.highlight : void 0, bold: isActive, children: [
5168
5343
  " ",
5169
5344
  row.label
5170
5345
  ] }),
5171
- /* @__PURE__ */ jsx48(Text26, { dimColor: true, children: ` ${glyphs.emDash} ${row.description}` })
5346
+ /* @__PURE__ */ jsx49(Text26, { dimColor: true, children: ` ${glyphs.emDash} ${row.description}` })
5172
5347
  ] });
5173
5348
  }
5174
5349
  function buildRows2(sprint, tasks) {
@@ -5229,9 +5404,9 @@ function buildRows2(sprint, tasks) {
5229
5404
  }
5230
5405
 
5231
5406
  // src/integration/ui/tui/views/browse/ticket-list-view.tsx
5232
- import { useCallback as useCallback9, useEffect as useEffect16, useState as useState17 } from "react";
5407
+ import { useCallback as useCallback9, useEffect as useEffect17, useState as useState17 } from "react";
5233
5408
  import { useInput as useInput13 } from "ink";
5234
- import { jsx as jsx49 } from "react/jsx-runtime";
5409
+ import { jsx as jsx50 } from "react/jsx-runtime";
5235
5410
  function requirementColor(status) {
5236
5411
  return status === "approved" ? inkColors.success : inkColors.warning;
5237
5412
  }
@@ -5255,7 +5430,7 @@ function buildColumns2(repoNamesById) {
5255
5430
  }
5256
5431
  ];
5257
5432
  }
5258
- var TITLE22 = "Tickets";
5433
+ var TITLE23 = "Tickets";
5259
5434
  var HINTS_READY3 = [
5260
5435
  { key: "\u2191/\u2193", action: "navigate" },
5261
5436
  { key: "Enter", action: "open" },
@@ -5284,7 +5459,7 @@ function TicketListView({ sprintId }) {
5284
5459
  setState({ kind: "error", message: err instanceof Error ? err.message : String(err) });
5285
5460
  }
5286
5461
  }, [sprintId]);
5287
- useEffect16(() => {
5462
+ useEffect17(() => {
5288
5463
  const ctl = { cancelled: false };
5289
5464
  void (async () => {
5290
5465
  if (!ctl.cancelled) await load();
@@ -5309,7 +5484,7 @@ function TicketListView({ sprintId }) {
5309
5484
  }
5310
5485
  });
5311
5486
  useViewHints(state.kind === "ready" ? HINTS_READY3 : HINTS_EMPTY2);
5312
- return /* @__PURE__ */ jsx49(ViewShell, { title: TITLE22, children: state.kind === "loading" ? /* @__PURE__ */ jsx49(Spinner, { label: "Loading tickets\u2026" }) : state.kind === "empty" ? /* @__PURE__ */ jsx49(ResultCard, { kind: "info", title: "No tickets in this sprint", lines: ["Press `a` to add a ticket."] }) : state.kind === "error" ? /* @__PURE__ */ jsx49(ResultCard, { kind: "error", title: "Could not load tickets", lines: [state.message] }) : /* @__PURE__ */ jsx49(
5487
+ return /* @__PURE__ */ jsx50(ViewShell, { title: TITLE23, children: state.kind === "loading" ? /* @__PURE__ */ jsx50(Spinner, { label: "Loading tickets\u2026" }) : state.kind === "empty" ? /* @__PURE__ */ jsx50(ResultCard, { kind: "info", title: "No tickets in this sprint", lines: ["Press `a` to add a ticket."] }) : state.kind === "error" ? /* @__PURE__ */ jsx50(ResultCard, { kind: "error", title: "Could not load tickets", lines: [state.message] }) : /* @__PURE__ */ jsx50(
5313
5488
  ListView,
5314
5489
  {
5315
5490
  rows: state.tickets,
@@ -5322,16 +5497,16 @@ function TicketListView({ sprintId }) {
5322
5497
  }
5323
5498
 
5324
5499
  // src/integration/ui/tui/views/browse/ticket-show-view.tsx
5325
- import { useEffect as useEffect17, useState as useState18 } from "react";
5500
+ import { useEffect as useEffect18, useState as useState18 } from "react";
5326
5501
  import { Box as Box27, Text as Text27, useInput as useInput14 } from "ink";
5327
- import { jsx as jsx50, jsxs as jsxs27 } from "react/jsx-runtime";
5328
- var TITLE23 = "Ticket Details";
5502
+ import { jsx as jsx51, jsxs as jsxs27 } from "react/jsx-runtime";
5503
+ var TITLE24 = "Ticket Details";
5329
5504
  var HINTS_READ_ONLY = [];
5330
5505
  var HINTS_EDITABLE = [{ key: "e", action: "edit" }];
5331
5506
  function TicketShowView({ ticketId }) {
5332
5507
  const router = useRouter();
5333
5508
  const [state, setState] = useState18({ kind: "loading" });
5334
- useEffect17(() => {
5509
+ useEffect18(() => {
5335
5510
  const ctl = { cancelled: false };
5336
5511
  void (async () => {
5337
5512
  if (!ticketId) {
@@ -5364,17 +5539,17 @@ function TicketShowView({ ticketId }) {
5364
5539
  }
5365
5540
  });
5366
5541
  useViewHints(state.kind === "ready" && state.editable ? HINTS_EDITABLE : HINTS_READ_ONLY);
5367
- return /* @__PURE__ */ jsx50(ViewShell, { title: TITLE23, children: renderBody22(state) });
5542
+ return /* @__PURE__ */ jsx51(ViewShell, { title: TITLE24, children: renderBody23(state) });
5368
5543
  }
5369
- function renderBody22(state) {
5370
- if (state.kind === "loading") return /* @__PURE__ */ jsx50(Spinner, { label: "Loading ticket\u2026" });
5371
- if (state.kind === "error") return /* @__PURE__ */ jsx50(ResultCard, { kind: "error", title: "Could not load ticket", lines: [state.message] });
5544
+ function renderBody23(state) {
5545
+ if (state.kind === "loading") return /* @__PURE__ */ jsx51(Spinner, { label: "Loading ticket\u2026" });
5546
+ if (state.kind === "error") return /* @__PURE__ */ jsx51(ResultCard, { kind: "error", title: "Could not load ticket", lines: [state.message] });
5372
5547
  const { ticket } = state;
5373
5548
  return /* @__PURE__ */ jsxs27(Box27, { flexDirection: "column", children: [
5374
5549
  /* @__PURE__ */ jsxs27(Box27, { children: [
5375
- /* @__PURE__ */ jsx50(Text27, { bold: true, children: ticket.title }),
5376
- /* @__PURE__ */ jsx50(Text27, { children: " " }),
5377
- /* @__PURE__ */ jsx50(
5550
+ /* @__PURE__ */ jsx51(Text27, { bold: true, children: ticket.title }),
5551
+ /* @__PURE__ */ jsx51(Text27, { children: " " }),
5552
+ /* @__PURE__ */ jsx51(
5378
5553
  StatusChip,
5379
5554
  {
5380
5555
  label: ticket.requirementStatus,
@@ -5382,7 +5557,7 @@ function renderBody22(state) {
5382
5557
  }
5383
5558
  )
5384
5559
  ] }),
5385
- /* @__PURE__ */ jsx50(Box27, { marginTop: spacing.section, children: /* @__PURE__ */ jsx50(
5560
+ /* @__PURE__ */ jsx51(Box27, { marginTop: spacing.section, children: /* @__PURE__ */ jsx51(
5386
5561
  FieldList,
5387
5562
  {
5388
5563
  fields: [
@@ -5393,20 +5568,20 @@ function renderBody22(state) {
5393
5568
  }
5394
5569
  ) }),
5395
5570
  ticket.description ? /* @__PURE__ */ jsxs27(Box27, { marginTop: spacing.section, flexDirection: "column", children: [
5396
- /* @__PURE__ */ jsx50(Text27, { color: inkColors.muted, bold: true, children: "Description" }),
5397
- /* @__PURE__ */ jsx50(Box27, { paddingLeft: spacing.indent, children: /* @__PURE__ */ jsx50(Text27, { children: ticket.description }) })
5571
+ /* @__PURE__ */ jsx51(Text27, { color: inkColors.muted, bold: true, children: "Description" }),
5572
+ /* @__PURE__ */ jsx51(Box27, { paddingLeft: spacing.indent, children: /* @__PURE__ */ jsx51(Text27, { children: ticket.description }) })
5398
5573
  ] }) : null,
5399
5574
  ticket.requirements ? /* @__PURE__ */ jsxs27(Box27, { marginTop: spacing.section, flexDirection: "column", children: [
5400
- /* @__PURE__ */ jsx50(Text27, { color: inkColors.muted, bold: true, children: "Requirements" }),
5401
- /* @__PURE__ */ jsx50(Box27, { paddingLeft: spacing.indent, children: /* @__PURE__ */ jsx50(Text27, { children: ticket.requirements }) })
5575
+ /* @__PURE__ */ jsx51(Text27, { color: inkColors.muted, bold: true, children: "Requirements" }),
5576
+ /* @__PURE__ */ jsx51(Box27, { paddingLeft: spacing.indent, children: /* @__PURE__ */ jsx51(Text27, { children: ticket.requirements }) })
5402
5577
  ] }) : null
5403
5578
  ] });
5404
5579
  }
5405
5580
 
5406
5581
  // src/integration/ui/tui/views/browse/task-list-view.tsx
5407
- import { useEffect as useEffect18, useMemo as useMemo30, useState as useState19 } from "react";
5582
+ import { useEffect as useEffect19, useMemo as useMemo31, useState as useState19 } from "react";
5408
5583
  import { useInput as useInput15 } from "ink";
5409
- import { jsx as jsx51 } from "react/jsx-runtime";
5584
+ import { jsx as jsx52 } from "react/jsx-runtime";
5410
5585
  var FILTER_CYCLE2 = ["all", "todo", "active", "done"];
5411
5586
  function nextFilter2(f) {
5412
5587
  const i = FILTER_CYCLE2.indexOf(f);
@@ -5481,7 +5656,7 @@ function TaskListView({ sprintId }) {
5481
5656
  const [state, setState] = useState19({ kind: "loading" });
5482
5657
  const [filter, setFilter] = useState19("all");
5483
5658
  useViewHints(state.kind === "ready" ? HINTS_READY4 : HINTS_EMPTY3);
5484
- useEffect18(() => {
5659
+ useEffect19(() => {
5485
5660
  const ctl = { cancelled: false };
5486
5661
  void (async () => {
5487
5662
  try {
@@ -5529,13 +5704,13 @@ function TaskListView({ sprintId }) {
5529
5704
  router.push({ id: "task-remove" });
5530
5705
  }
5531
5706
  });
5532
- const filtered = useMemo30(() => {
5707
+ const filtered = useMemo31(() => {
5533
5708
  if (state.kind !== "ready") return [];
5534
5709
  if (filter === "all") return state.tasks;
5535
5710
  return state.tasks.filter((t) => matches(t, filter));
5536
5711
  }, [state, filter]);
5537
5712
  const title = filter === "all" ? TITLE_BASE2 : `${TITLE_BASE2} \xB7 filter: ${filter}`;
5538
- return /* @__PURE__ */ jsx51(ViewShell, { title, children: state.kind === "loading" ? /* @__PURE__ */ jsx51(Spinner, { label: "Loading tasks\u2026" }) : state.kind === "empty" ? /* @__PURE__ */ jsx51(ResultCard, { kind: "info", title: "No tasks in this sprint" }) : state.kind === "error" ? /* @__PURE__ */ jsx51(ResultCard, { kind: "error", title: "Could not load tasks", lines: [state.message] }) : filtered.length === 0 ? /* @__PURE__ */ jsx51(ResultCard, { kind: "info", title: `No tasks with filter '${filter}'`, lines: ["Press f to cycle the filter."] }) : /* @__PURE__ */ jsx51(
5713
+ return /* @__PURE__ */ jsx52(ViewShell, { title, children: state.kind === "loading" ? /* @__PURE__ */ jsx52(Spinner, { label: "Loading tasks\u2026" }) : state.kind === "empty" ? /* @__PURE__ */ jsx52(ResultCard, { kind: "info", title: "No tasks in this sprint" }) : state.kind === "error" ? /* @__PURE__ */ jsx52(ResultCard, { kind: "error", title: "Could not load tasks", lines: [state.message] }) : filtered.length === 0 ? /* @__PURE__ */ jsx52(ResultCard, { kind: "info", title: `No tasks with filter '${filter}'`, lines: ["Press f to cycle the filter."] }) : /* @__PURE__ */ jsx52(
5539
5714
  ListView,
5540
5715
  {
5541
5716
  rows: filtered,
@@ -5548,10 +5723,10 @@ function TaskListView({ sprintId }) {
5548
5723
  }
5549
5724
 
5550
5725
  // src/integration/ui/tui/views/browse/task-show-view.tsx
5551
- import { useEffect as useEffect19, useState as useState20 } from "react";
5726
+ import { useEffect as useEffect20, useState as useState20 } from "react";
5552
5727
  import { Box as Box28, Text as Text28, useInput as useInput16 } from "ink";
5553
- import { jsx as jsx52, jsxs as jsxs28 } from "react/jsx-runtime";
5554
- var TITLE24 = "Task Details";
5728
+ import { jsx as jsx53, jsxs as jsxs28 } from "react/jsx-runtime";
5729
+ var TITLE25 = "Task Details";
5555
5730
  var HINTS_READY5 = [
5556
5731
  { key: "t", action: "status" },
5557
5732
  { key: "r", action: "remove" }
@@ -5571,7 +5746,7 @@ function TaskShowView({ taskId }) {
5571
5746
  router.push({ id: "task-remove" });
5572
5747
  }
5573
5748
  });
5574
- useEffect19(() => {
5749
+ useEffect20(() => {
5575
5750
  const ctl = { cancelled: false };
5576
5751
  void (async () => {
5577
5752
  if (!taskId) {
@@ -5589,19 +5764,19 @@ function TaskShowView({ taskId }) {
5589
5764
  ctl.cancelled = true;
5590
5765
  };
5591
5766
  }, [taskId]);
5592
- return /* @__PURE__ */ jsx52(ViewShell, { title: TITLE24, children: renderBody23(state) });
5767
+ return /* @__PURE__ */ jsx53(ViewShell, { title: TITLE25, children: renderBody24(state) });
5593
5768
  }
5594
- function renderBody23(state) {
5595
- if (state.kind === "loading") return /* @__PURE__ */ jsx52(Spinner, { label: "Loading task\u2026" });
5596
- if (state.kind === "error") return /* @__PURE__ */ jsx52(ResultCard, { kind: "error", title: "Could not load task", lines: [state.message] });
5769
+ function renderBody24(state) {
5770
+ if (state.kind === "loading") return /* @__PURE__ */ jsx53(Spinner, { label: "Loading task\u2026" });
5771
+ if (state.kind === "error") return /* @__PURE__ */ jsx53(ResultCard, { kind: "error", title: "Could not load task", lines: [state.message] });
5597
5772
  const { task } = state;
5598
5773
  return /* @__PURE__ */ jsxs28(Box28, { flexDirection: "column", children: [
5599
5774
  /* @__PURE__ */ jsxs28(Box28, { children: [
5600
- /* @__PURE__ */ jsx52(Text28, { bold: true, children: task.name }),
5601
- /* @__PURE__ */ jsx52(Text28, { children: " " }),
5602
- /* @__PURE__ */ jsx52(StatusChip, { label: task.status, kind: chipKindForTaskStatus(task.status) })
5775
+ /* @__PURE__ */ jsx53(Text28, { bold: true, children: task.name }),
5776
+ /* @__PURE__ */ jsx53(Text28, { children: " " }),
5777
+ /* @__PURE__ */ jsx53(StatusChip, { label: task.status, kind: chipKindForTaskStatus(task.status) })
5603
5778
  ] }),
5604
- /* @__PURE__ */ jsx52(Box28, { marginTop: spacing.section, children: /* @__PURE__ */ jsx52(
5779
+ /* @__PURE__ */ jsx53(Box28, { marginTop: spacing.section, children: /* @__PURE__ */ jsx53(
5605
5780
  FieldList,
5606
5781
  {
5607
5782
  fields: [
@@ -5616,54 +5791,59 @@ function renderBody23(state) {
5616
5791
  }
5617
5792
  ) }),
5618
5793
  task.description ? /* @__PURE__ */ jsxs28(Box28, { marginTop: spacing.section, flexDirection: "column", children: [
5619
- /* @__PURE__ */ jsx52(Text28, { color: inkColors.muted, bold: true, children: "Description" }),
5620
- /* @__PURE__ */ jsx52(Box28, { paddingLeft: spacing.indent, children: /* @__PURE__ */ jsx52(Text28, { children: task.description }) })
5794
+ /* @__PURE__ */ jsx53(Text28, { color: inkColors.muted, bold: true, children: "Description" }),
5795
+ /* @__PURE__ */ jsx53(Box28, { paddingLeft: spacing.indent, children: /* @__PURE__ */ jsx53(Text28, { children: task.description }) })
5621
5796
  ] }) : null,
5622
5797
  task.steps.length > 0 ? /* @__PURE__ */ jsxs28(Box28, { marginTop: spacing.section, flexDirection: "column", children: [
5623
- /* @__PURE__ */ jsx52(Text28, { color: inkColors.muted, bold: true, children: "Steps" }),
5798
+ /* @__PURE__ */ jsx53(Text28, { color: inkColors.muted, bold: true, children: "Steps" }),
5624
5799
  task.steps.map((step, i) => /* @__PURE__ */ jsxs28(Box28, { paddingLeft: spacing.indent, children: [
5625
5800
  /* @__PURE__ */ jsxs28(Text28, { dimColor: true, children: [
5626
5801
  String(i + 1).padStart(2, " "),
5627
5802
  ". "
5628
5803
  ] }),
5629
- /* @__PURE__ */ jsx52(Text28, { children: step })
5804
+ /* @__PURE__ */ jsx53(Text28, { children: step })
5630
5805
  ] }, i))
5631
5806
  ] }) : null,
5632
5807
  task.verificationCriteria.length > 0 ? /* @__PURE__ */ jsxs28(Box28, { marginTop: spacing.section, flexDirection: "column", children: [
5633
- /* @__PURE__ */ jsx52(Text28, { color: inkColors.muted, bold: true, children: "Verification" }),
5808
+ /* @__PURE__ */ jsx53(Text28, { color: inkColors.muted, bold: true, children: "Verification" }),
5634
5809
  task.verificationCriteria.map((v, i) => /* @__PURE__ */ jsxs28(Box28, { paddingLeft: spacing.indent, children: [
5635
5810
  /* @__PURE__ */ jsxs28(Text28, { dimColor: true, children: [
5636
5811
  glyphs.bulletListItem,
5637
5812
  " "
5638
5813
  ] }),
5639
- /* @__PURE__ */ jsx52(Text28, { children: v })
5814
+ /* @__PURE__ */ jsx53(Text28, { children: v })
5640
5815
  ] }, i))
5641
5816
  ] }) : null
5642
5817
  ] });
5643
5818
  }
5644
5819
 
5645
5820
  // src/integration/ui/tui/views/browse/project-list-view.tsx
5646
- import { useEffect as useEffect20, useState as useState21 } from "react";
5821
+ import { useCallback as useCallback10, useEffect as useEffect21, useRef as useRef3, useState as useState21 } from "react";
5647
5822
  import { useInput as useInput17 } from "ink";
5648
- import { jsx as jsx53 } from "react/jsx-runtime";
5823
+ import { jsx as jsx54 } from "react/jsx-runtime";
5649
5824
  var COLUMNS = [
5650
5825
  { header: "Name", cell: (p) => p.name, width: 16 },
5651
5826
  { header: "Display", cell: (p) => p.displayName, flex: true },
5652
5827
  { header: "Repos", cell: (p) => String(p.repositories.length), align: "right", width: 6 }
5653
5828
  ];
5654
- var TITLE25 = "Projects";
5829
+ var TITLE26 = "Projects";
5655
5830
  var HINTS_READY6 = [
5656
5831
  { key: "\u2191/\u2193", action: "navigate" },
5657
5832
  { key: "Enter", action: "open" },
5658
5833
  { key: "a", action: "add" },
5659
5834
  { key: "e", action: "edit" },
5835
+ { key: "o", action: "onboard" },
5660
5836
  { key: "r", action: "remove" }
5661
5837
  ];
5662
5838
  var HINTS_EMPTY5 = [{ key: "a", action: "add" }];
5663
5839
  function ProjectListView() {
5664
5840
  const router = useRouter();
5665
5841
  const [state, setState] = useState21({ kind: "loading" });
5666
- useEffect20(() => {
5842
+ const highlightedRef = useRef3(null);
5843
+ const handleCursorChange = useCallback10((row) => {
5844
+ highlightedRef.current = row;
5845
+ }, []);
5846
+ useEffect21(() => {
5667
5847
  const ctl = { cancelled: false };
5668
5848
  void (async () => {
5669
5849
  try {
@@ -5691,16 +5871,24 @@ function ProjectListView() {
5691
5871
  router.push({ id: "project-edit" });
5692
5872
  return;
5693
5873
  }
5874
+ if (input === "o") {
5875
+ const target = highlightedRef.current ?? state.projects[0];
5876
+ if (target) {
5877
+ router.push({ id: "project-onboard", props: { projectName: target.name } });
5878
+ }
5879
+ return;
5880
+ }
5694
5881
  if (input === "r") {
5695
5882
  router.push({ id: "project-remove" });
5696
5883
  }
5697
5884
  });
5698
5885
  useViewHints(state.kind === "ready" ? HINTS_READY6 : HINTS_EMPTY5);
5699
- return /* @__PURE__ */ jsx53(ViewShell, { title: TITLE25, children: state.kind === "loading" ? /* @__PURE__ */ jsx53(Spinner, { label: "Loading projects\u2026" }) : state.kind === "empty" ? /* @__PURE__ */ jsx53(ResultCard, { kind: "info", title: "No projects registered", lines: ["Press `a` to add one."] }) : state.kind === "error" ? /* @__PURE__ */ jsx53(ResultCard, { kind: "error", title: "Could not load projects", lines: [state.message] }) : /* @__PURE__ */ jsx53(
5886
+ return /* @__PURE__ */ jsx54(ViewShell, { title: TITLE26, children: state.kind === "loading" ? /* @__PURE__ */ jsx54(Spinner, { label: "Loading projects\u2026" }) : state.kind === "empty" ? /* @__PURE__ */ jsx54(ResultCard, { kind: "info", title: "No projects registered", lines: ["Press `a` to add one."] }) : state.kind === "error" ? /* @__PURE__ */ jsx54(ResultCard, { kind: "error", title: "Could not load projects", lines: [state.message] }) : /* @__PURE__ */ jsx54(
5700
5887
  ListView,
5701
5888
  {
5702
5889
  rows: state.projects,
5703
5890
  columns: COLUMNS,
5891
+ onCursorChange: handleCursorChange,
5704
5892
  onSelect: (p) => {
5705
5893
  router.push({ id: "project-show", props: { projectName: p.name } });
5706
5894
  }
@@ -5709,13 +5897,14 @@ function ProjectListView() {
5709
5897
  }
5710
5898
 
5711
5899
  // src/integration/ui/tui/views/browse/project-show-view.tsx
5712
- import { useEffect as useEffect21, useState as useState22 } from "react";
5900
+ import { useEffect as useEffect22, useState as useState22 } from "react";
5713
5901
  import { Box as Box29, Text as Text29, useInput as useInput18 } from "ink";
5714
- import { jsx as jsx54, jsxs as jsxs29 } from "react/jsx-runtime";
5715
- var TITLE26 = "Project Details";
5902
+ import { jsx as jsx55, jsxs as jsxs29 } from "react/jsx-runtime";
5903
+ var TITLE27 = "Project Details";
5716
5904
  var HINTS_READY7 = [
5717
5905
  { key: "e", action: "edit" },
5718
5906
  { key: "a", action: "add repo" },
5907
+ { key: "o", action: "onboard" },
5719
5908
  { key: "r", action: "remove repo" }
5720
5909
  ];
5721
5910
  var HINTS_EMPTY6 = [];
@@ -5733,11 +5922,15 @@ function ProjectShowView({ projectName }) {
5733
5922
  router.push({ id: "project-repo-add" });
5734
5923
  return;
5735
5924
  }
5925
+ if (input === "o") {
5926
+ router.push({ id: "project-onboard", props: { projectName: state.project.name } });
5927
+ return;
5928
+ }
5736
5929
  if (input === "r") {
5737
5930
  router.push({ id: "project-repo-remove" });
5738
5931
  }
5739
5932
  });
5740
- useEffect21(() => {
5933
+ useEffect22(() => {
5741
5934
  const ctl = { cancelled: false };
5742
5935
  void (async () => {
5743
5936
  if (!projectName) {
@@ -5755,18 +5948,18 @@ function ProjectShowView({ projectName }) {
5755
5948
  ctl.cancelled = true;
5756
5949
  };
5757
5950
  }, [projectName]);
5758
- return /* @__PURE__ */ jsx54(ViewShell, { title: TITLE26, children: renderBody24(state) });
5951
+ return /* @__PURE__ */ jsx55(ViewShell, { title: TITLE27, children: renderBody25(state) });
5759
5952
  }
5760
- function renderBody24(state) {
5761
- if (state.kind === "loading") return /* @__PURE__ */ jsx54(Spinner, { label: "Loading project\u2026" });
5762
- if (state.kind === "error") return /* @__PURE__ */ jsx54(ResultCard, { kind: "error", title: "Could not load project", lines: [state.message] });
5953
+ function renderBody25(state) {
5954
+ if (state.kind === "loading") return /* @__PURE__ */ jsx55(Spinner, { label: "Loading project\u2026" });
5955
+ if (state.kind === "error") return /* @__PURE__ */ jsx55(ResultCard, { kind: "error", title: "Could not load project", lines: [state.message] });
5763
5956
  const { project } = state;
5764
5957
  return /* @__PURE__ */ jsxs29(Box29, { flexDirection: "column", children: [
5765
5958
  /* @__PURE__ */ jsxs29(Box29, { children: [
5766
- /* @__PURE__ */ jsx54(Text29, { bold: true, children: project.displayName }),
5767
- /* @__PURE__ */ jsx54(Text29, { dimColor: true, children: ` (${project.name})` })
5959
+ /* @__PURE__ */ jsx55(Text29, { bold: true, children: project.displayName }),
5960
+ /* @__PURE__ */ jsx55(Text29, { dimColor: true, children: ` (${project.name})` })
5768
5961
  ] }),
5769
- /* @__PURE__ */ jsx54(Box29, { marginTop: spacing.section, children: /* @__PURE__ */ jsx54(
5962
+ /* @__PURE__ */ jsx55(Box29, { marginTop: spacing.section, children: /* @__PURE__ */ jsx55(
5770
5963
  FieldList,
5771
5964
  {
5772
5965
  fields: [
@@ -5778,28 +5971,29 @@ function renderBody24(state) {
5778
5971
  }
5779
5972
  ) }),
5780
5973
  /* @__PURE__ */ jsxs29(Box29, { marginTop: spacing.section, flexDirection: "column", children: [
5781
- /* @__PURE__ */ jsx54(Text29, { color: inkColors.muted, bold: true, children: "Repositories" }),
5974
+ /* @__PURE__ */ jsx55(Text29, { color: inkColors.muted, bold: true, children: "Repositories" }),
5782
5975
  project.repositories.map((r) => /* @__PURE__ */ jsxs29(Box29, { paddingLeft: spacing.indent, children: [
5783
5976
  /* @__PURE__ */ jsxs29(Text29, { dimColor: true, children: [
5784
5977
  glyphs.bulletListItem,
5785
5978
  " "
5786
5979
  ] }),
5787
- /* @__PURE__ */ jsx54(Text29, { children: r.name }),
5788
- /* @__PURE__ */ jsx54(Text29, { dimColor: true, children: ` ${r.path} ` }),
5789
- /* @__PURE__ */ jsx54(Text29, { dimColor: true, children: `(id: ${r.id})` })
5980
+ /* @__PURE__ */ jsx55(Text29, { children: r.name }),
5981
+ /* @__PURE__ */ jsx55(Text29, { dimColor: true, children: ` ${r.path} ` }),
5982
+ /* @__PURE__ */ jsx55(Text29, { dimColor: true, children: `(id: ${r.id})` })
5790
5983
  ] }, r.id))
5791
5984
  ] })
5792
5985
  ] });
5793
5986
  }
5794
5987
 
5795
5988
  // src/integration/ui/tui/views/browse/doctor-view.tsx
5796
- import { useEffect as useEffect22, useState as useState23 } from "react";
5989
+ import { useEffect as useEffect23, useState as useState23 } from "react";
5797
5990
  import { Box as Box30, Text as Text30 } from "ink";
5798
- import { jsx as jsx55, jsxs as jsxs30 } from "react/jsx-runtime";
5799
- var TITLE27 = "Doctor";
5991
+ import { jsx as jsx56, jsxs as jsxs30 } from "react/jsx-runtime";
5992
+ var TITLE28 = "Doctor";
5800
5993
  var HINTS2 = [];
5994
+ var MIN_LABEL_WIDTH = 20;
5801
5995
  async function runChecks() {
5802
- const checks = [
5996
+ const environment = [
5803
5997
  ["Node.js version", checkNodeVersion()],
5804
5998
  ["git installed", checkGitInstalled()],
5805
5999
  ["git identity", checkGitIdentity()],
@@ -5811,17 +6005,27 @@ async function runChecks() {
5811
6005
  ["Config schema", await checkConfigSchemaValidation()],
5812
6006
  ["Current sprint", await checkCurrentSprint()]
5813
6007
  ];
5814
- return Promise.all(
5815
- checks.map(async ([name, r]) => ({
6008
+ const envRows = await Promise.all(
6009
+ environment.map(async ([name, r]) => ({
5816
6010
  name,
5817
6011
  result: r instanceof Promise ? await r : r
5818
6012
  }))
5819
6013
  );
6014
+ const onboardingResults = await checkRepoOnboarding();
6015
+ const onboardingRows = onboardingResults.map((result) => ({
6016
+ name: result.name.replace(/^Onboarding\s+—\s+/u, ""),
6017
+ result
6018
+ }));
6019
+ const sections = [{ title: "Environment", rows: envRows }];
6020
+ if (onboardingRows.length > 0) {
6021
+ sections.push({ title: "Onboarding", rows: onboardingRows });
6022
+ }
6023
+ return sections;
5820
6024
  }
5821
6025
  function glyph(status) {
5822
6026
  if (status === "pass") return glyphs.check;
5823
- if (status === "warn") return "!";
5824
- if (status === "skip") return glyphs.inlineDot;
6027
+ if (status === "warn") return glyphs.warningGlyph;
6028
+ if (status === "skip") return glyphs.phaseDisabled;
5825
6029
  return glyphs.cross;
5826
6030
  }
5827
6031
  function color(status) {
@@ -5830,38 +6034,64 @@ function color(status) {
5830
6034
  if (status === "skip") return inkColors.muted;
5831
6035
  return inkColors.error;
5832
6036
  }
6037
+ function labelWidth(rows) {
6038
+ return Math.max(MIN_LABEL_WIDTH, ...rows.map((r) => r.name.length));
6039
+ }
6040
+ function Row({ row, width }) {
6041
+ const dim = row.result.status === "skip";
6042
+ return /* @__PURE__ */ jsxs30(Box30, { children: [
6043
+ /* @__PURE__ */ jsx56(Text30, { color: color(row.result.status), bold: true, children: glyph(row.result.status) }),
6044
+ /* @__PURE__ */ jsx56(Text30, { children: ` ` }),
6045
+ /* @__PURE__ */ jsx56(Text30, { bold: true, dimColor: dim, children: row.name.padEnd(width + 2) }),
6046
+ /* @__PURE__ */ jsx56(Text30, { dimColor: true, children: row.result.detail ?? row.result.status.toUpperCase() })
6047
+ ] });
6048
+ }
5833
6049
  function DoctorView() {
5834
6050
  const [state, setState] = useState23({ kind: "running" });
5835
6051
  useViewHints(HINTS2);
5836
- useEffect22(() => {
6052
+ useEffect23(() => {
5837
6053
  const ctl = { cancelled: false };
5838
6054
  void (async () => {
5839
- const checks = await runChecks();
5840
- if (!ctl.cancelled) setState({ kind: "done", checks });
6055
+ const sections = await runChecks();
6056
+ if (!ctl.cancelled) setState({ kind: "done", sections });
5841
6057
  })();
5842
6058
  return () => {
5843
6059
  ctl.cancelled = true;
5844
6060
  };
5845
6061
  }, []);
5846
- return /* @__PURE__ */ jsx55(ViewShell, { title: TITLE27, children: state.kind === "running" ? /* @__PURE__ */ jsx55(Spinner, { label: "Running environment checks\u2026" }) : state.checks.map((c) => /* @__PURE__ */ jsxs30(Box30, { children: [
5847
- /* @__PURE__ */ jsx55(Text30, { color: color(c.result.status), bold: true, children: glyph(c.result.status) }),
5848
- /* @__PURE__ */ jsx55(Text30, { children: ` ` }),
5849
- /* @__PURE__ */ jsx55(Text30, { bold: true, children: c.name.padEnd(20) }),
5850
- /* @__PURE__ */ jsx55(Text30, { dimColor: true, children: c.result.detail ?? c.result.status.toUpperCase() })
5851
- ] }, c.name)) });
6062
+ if (state.kind === "running") {
6063
+ return /* @__PURE__ */ jsx56(ViewShell, { title: TITLE28, children: /* @__PURE__ */ jsx56(Spinner, { label: "Running environment checks\u2026" }) });
6064
+ }
6065
+ return /* @__PURE__ */ jsx56(ViewShell, { title: TITLE28, children: state.sections.map((section, i) => {
6066
+ const width = labelWidth(section.rows);
6067
+ const passed = section.rows.filter((r) => r.result.status === "pass").length;
6068
+ const warned = section.rows.filter((r) => r.result.status === "warn").length;
6069
+ const failed = section.rows.filter((r) => r.result.status === "fail").length;
6070
+ const total = section.rows.filter((r) => r.result.status !== "skip").length;
6071
+ const summary = `${String(passed)}/${String(total)} pass${warned > 0 ? ` \xB7 ${String(warned)} warn` : ""}${failed > 0 ? ` \xB7 ${String(failed)} fail` : ""}`;
6072
+ return /* @__PURE__ */ jsxs30(Box30, { flexDirection: "column", children: [
6073
+ i === 0 ? null : /* @__PURE__ */ jsx56(Box30, { marginTop: spacing.section }),
6074
+ /* @__PURE__ */ jsxs30(Box30, { children: [
6075
+ /* @__PURE__ */ jsx56(Text30, { color: inkColors.primary, bold: true, children: section.title.toUpperCase() }),
6076
+ /* @__PURE__ */ jsx56(Text30, { color: inkColors.muted, children: ` ${glyphs.emDash} ` }),
6077
+ /* @__PURE__ */ jsx56(Text30, { color: inkColors.muted, children: summary })
6078
+ ] }),
6079
+ /* @__PURE__ */ jsx56(Box30, { marginTop: spacing.section, flexDirection: "column", children: section.rows.map((row) => /* @__PURE__ */ jsx56(Row, { row, width }, row.name)) })
6080
+ ] }, section.title);
6081
+ }) });
5852
6082
  }
5853
6083
 
5854
6084
  // src/integration/ui/tui/views/browse/progress-show-view.tsx
5855
- import { useEffect as useEffect23, useState as useState24 } from "react";
6085
+ import { useEffect as useEffect24, useState as useState24 } from "react";
5856
6086
  import { Box as Box31, Text as Text31 } from "ink";
5857
- import { jsx as jsx56, jsxs as jsxs31 } from "react/jsx-runtime";
6087
+ import { jsx as jsx57, jsxs as jsxs31 } from "react/jsx-runtime";
5858
6088
  var MAX_TAIL = 80;
5859
- var TITLE28 = "Progress Log";
6089
+ var TITLE29 = "Progress Log";
5860
6090
  var HINTS3 = [];
5861
6091
  function ProgressShowView({ sprintId } = {}) {
5862
6092
  const [state, setState] = useState24({ kind: "loading" });
5863
6093
  useViewHints(HINTS3);
5864
- useEffect23(() => {
6094
+ useEffect24(() => {
5865
6095
  const ctl = { cancelled: false };
5866
6096
  void (async () => {
5867
6097
  try {
@@ -5877,7 +6107,7 @@ function ProgressShowView({ sprintId } = {}) {
5877
6107
  ctl.cancelled = true;
5878
6108
  };
5879
6109
  }, [sprintId]);
5880
- return /* @__PURE__ */ jsx56(ViewShell, { title: TITLE28, children: state.kind === "loading" ? /* @__PURE__ */ jsx56(Spinner, { label: "Loading progress\u2026" }) : state.kind === "empty" ? /* @__PURE__ */ jsx56(ResultCard, { kind: "info", title: "No progress entries yet" }) : state.kind === "error" ? /* @__PURE__ */ jsx56(ResultCard, { kind: "error", title: "Could not load progress", lines: [state.message] }) : renderContent(state.content) });
6110
+ return /* @__PURE__ */ jsx57(ViewShell, { title: TITLE29, children: state.kind === "loading" ? /* @__PURE__ */ jsx57(Spinner, { label: "Loading progress\u2026" }) : state.kind === "empty" ? /* @__PURE__ */ jsx57(ResultCard, { kind: "info", title: "No progress entries yet" }) : state.kind === "error" ? /* @__PURE__ */ jsx57(ResultCard, { kind: "error", title: "Could not load progress", lines: [state.message] }) : renderContent(state.content) });
5881
6111
  }
5882
6112
  function renderContent(content) {
5883
6113
  const lines = content.split("\n");
@@ -5890,19 +6120,19 @@ function renderContent(content) {
5890
6120
  String(lines.length),
5891
6121
  " total)"
5892
6122
  ] }) : null,
5893
- tail.map((line2, i) => /* @__PURE__ */ jsx56(Text31, { dimColor: line2.trim().length === 0, children: line2.length > 0 ? line2 : " " }, i))
6123
+ tail.map((line2, i) => /* @__PURE__ */ jsx57(Text31, { dimColor: line2.trim().length === 0, children: line2.length > 0 ? line2 : " " }, i))
5894
6124
  ] });
5895
6125
  }
5896
6126
 
5897
6127
  // src/integration/ui/tui/views/workflows/progress-log-view.tsx
5898
- import { useMemo as useMemo31 } from "react";
5899
- import { jsx as jsx57 } from "react/jsx-runtime";
5900
- var TITLE29 = "Log Progress";
5901
- var HINTS_RUNNING21 = [
6128
+ import { useMemo as useMemo32 } from "react";
6129
+ import { jsx as jsx58 } from "react/jsx-runtime";
6130
+ var TITLE30 = "Log Progress";
6131
+ var HINTS_RUNNING22 = [
5902
6132
  { key: "Ctrl+D", action: "submit" },
5903
6133
  { key: "Esc", action: "cancel" }
5904
6134
  ];
5905
- var HINTS_DONE21 = [
6135
+ var HINTS_DONE22 = [
5906
6136
  { key: "Enter", action: "home" },
5907
6137
  { key: "Esc", action: "back" }
5908
6138
  ];
@@ -5925,29 +6155,29 @@ function ProgressLogView() {
5925
6155
  setPhase({ kind: "done" });
5926
6156
  }
5927
6157
  });
5928
- const hints = useMemo31(() => phase.kind === "running" ? HINTS_RUNNING21 : HINTS_DONE21, [phase.kind]);
6158
+ const hints = useMemo32(() => phase.kind === "running" ? HINTS_RUNNING22 : HINTS_DONE22, [phase.kind]);
5929
6159
  useViewHints(hints);
5930
- return /* @__PURE__ */ jsx57(ViewShell, { title: TITLE29, children: renderBody25(phase) });
6160
+ return /* @__PURE__ */ jsx58(ViewShell, { title: TITLE30, children: renderBody26(phase) });
5931
6161
  }
5932
- function renderBody25(phase) {
6162
+ function renderBody26(phase) {
5933
6163
  switch (phase.kind) {
5934
6164
  case "running":
5935
- return /* @__PURE__ */ jsx57(Spinner, { label: phase.step === "message" ? "Awaiting progress note\u2026" : "Saving progress note\u2026" });
6165
+ return /* @__PURE__ */ jsx58(Spinner, { label: phase.step === "message" ? "Awaiting progress note\u2026" : "Saving progress note\u2026" });
5936
6166
  case "cancelled":
5937
- return /* @__PURE__ */ jsx57(ResultCard, { kind: "info", title: "No note recorded" });
6167
+ return /* @__PURE__ */ jsx58(ResultCard, { kind: "info", title: "No note recorded" });
5938
6168
  case "error":
5939
- return /* @__PURE__ */ jsx57(ResultCard, { kind: "error", title: "Could not log progress", lines: [phase.message] });
6169
+ return /* @__PURE__ */ jsx58(ResultCard, { kind: "error", title: "Could not log progress", lines: [phase.message] });
5940
6170
  case "done":
5941
- return /* @__PURE__ */ jsx57(ResultCard, { kind: "success", title: "Progress logged" });
6171
+ return /* @__PURE__ */ jsx58(ResultCard, { kind: "success", title: "Progress logged" });
5942
6172
  }
5943
6173
  }
5944
6174
 
5945
6175
  // src/integration/ui/tui/views/workflows/ideate-view.tsx
5946
- import { useMemo as useMemo32 } from "react";
5947
- import { jsx as jsx58 } from "react/jsx-runtime";
5948
- var TITLE30 = "Ideate";
5949
- var HINTS_RUNNING22 = [{ key: "Esc", action: "cancel" }];
5950
- var HINTS_DONE22 = [
6176
+ import { useMemo as useMemo33 } from "react";
6177
+ import { jsx as jsx59 } from "react/jsx-runtime";
6178
+ var TITLE31 = "Ideate";
6179
+ var HINTS_RUNNING23 = [{ key: "Esc", action: "cancel" }];
6180
+ var HINTS_DONE23 = [
5951
6181
  { key: "Enter", action: "home" },
5952
6182
  { key: "Esc", action: "back" }
5953
6183
  ];
@@ -6001,22 +6231,22 @@ function IdeateView() {
6001
6231
  setPhase({ kind: "done", summary });
6002
6232
  }
6003
6233
  });
6004
- const hints = useMemo32(() => phase.kind === "running" ? HINTS_RUNNING22 : HINTS_DONE22, [phase.kind]);
6234
+ const hints = useMemo33(() => phase.kind === "running" ? HINTS_RUNNING23 : HINTS_DONE23, [phase.kind]);
6005
6235
  useViewHints(hints);
6006
- return /* @__PURE__ */ jsx58(ViewShell, { title: TITLE30, children: renderBody26(phase) });
6236
+ return /* @__PURE__ */ jsx59(ViewShell, { title: TITLE31, children: renderBody27(phase) });
6007
6237
  }
6008
- function renderBody26(phase) {
6238
+ function renderBody27(phase) {
6009
6239
  switch (phase.kind) {
6010
6240
  case "running":
6011
- return /* @__PURE__ */ jsx58(Spinner, { label: stepLabel12(phase.step) });
6241
+ return /* @__PURE__ */ jsx59(Spinner, { label: stepLabel13(phase.step) });
6012
6242
  case "no-projects":
6013
- return /* @__PURE__ */ jsx58(ResultCard, { kind: "warning", title: "Register a project first" });
6243
+ return /* @__PURE__ */ jsx59(ResultCard, { kind: "warning", title: "Register a project first" });
6014
6244
  case "no-draft-sprint":
6015
- return /* @__PURE__ */ jsx58(ResultCard, { kind: "warning", title: "Current sprint is not a draft" });
6245
+ return /* @__PURE__ */ jsx59(ResultCard, { kind: "warning", title: "Current sprint is not a draft" });
6016
6246
  case "error":
6017
- return /* @__PURE__ */ jsx58(ResultCard, { kind: "error", title: "Ideation failed", lines: [phase.message] });
6247
+ return /* @__PURE__ */ jsx59(ResultCard, { kind: "error", title: "Ideation failed", lines: [phase.message] });
6018
6248
  case "done":
6019
- return /* @__PURE__ */ jsx58(
6249
+ return /* @__PURE__ */ jsx59(
6020
6250
  ResultCard,
6021
6251
  {
6022
6252
  kind: "success",
@@ -6030,7 +6260,7 @@ function renderBody26(phase) {
6030
6260
  );
6031
6261
  }
6032
6262
  }
6033
- function stepLabel12(step) {
6263
+ function stepLabel13(step) {
6034
6264
  if (step === "title") return "Awaiting idea title\u2026";
6035
6265
  if (step === "description") return "Awaiting idea description\u2026";
6036
6266
  if (step === "project") return "Awaiting project selection\u2026";
@@ -6038,11 +6268,11 @@ function stepLabel12(step) {
6038
6268
  }
6039
6269
 
6040
6270
  // src/integration/ui/tui/views/onboarding-view.tsx
6041
- import { useMemo as useMemo33 } from "react";
6042
- import { jsx as jsx59 } from "react/jsx-runtime";
6043
- var TITLE31 = "Welcome";
6044
- var HINTS_RUNNING23 = [{ key: "Esc", action: "skip" }];
6045
- var HINTS_DONE23 = [
6271
+ import { useMemo as useMemo34 } from "react";
6272
+ import { jsx as jsx60 } from "react/jsx-runtime";
6273
+ var TITLE32 = "Welcome";
6274
+ var HINTS_RUNNING24 = [{ key: "Esc", action: "skip" }];
6275
+ var HINTS_DONE24 = [
6046
6276
  { key: "Enter", action: "home" },
6047
6277
  { key: "Esc", action: "home" }
6048
6278
  ];
@@ -6089,31 +6319,31 @@ function OnboardingView() {
6089
6319
  }
6090
6320
  }
6091
6321
  });
6092
- const hints = useMemo33(() => phase.kind === "running" ? HINTS_RUNNING23 : HINTS_DONE23, [phase.kind]);
6322
+ const hints = useMemo34(() => phase.kind === "running" ? HINTS_RUNNING24 : HINTS_DONE24, [phase.kind]);
6093
6323
  useViewHints(hints);
6094
- return /* @__PURE__ */ jsx59(ViewShell, { title: TITLE31, children: renderBody27(phase) });
6324
+ return /* @__PURE__ */ jsx60(ViewShell, { title: TITLE32, children: renderBody28(phase) });
6095
6325
  }
6096
- function renderBody27(phase) {
6326
+ function renderBody28(phase) {
6097
6327
  if (phase.kind === "running") {
6098
- return /* @__PURE__ */ jsx59(Spinner, { label: RUNNING_LABEL2[phase.step] });
6328
+ return /* @__PURE__ */ jsx60(Spinner, { label: RUNNING_LABEL2[phase.step] });
6099
6329
  }
6100
6330
  if (phase.kind === "error") {
6101
- return /* @__PURE__ */ jsx59(ResultCard, { kind: "error", title: "Onboarding failed", lines: [phase.message] });
6331
+ return /* @__PURE__ */ jsx60(ResultCard, { kind: "error", title: "Onboarding failed", lines: [phase.message] });
6102
6332
  }
6103
6333
  const providerLabel = phase.provider === "claude" ? "Claude Code" : phase.provider === "copilot" ? "GitHub Copilot" : "Skipped";
6104
6334
  const nextSteps = phase.addingProject ? [{ action: "Finish adding your project", description: "continuing to the project wizard\u2026" }] : [
6105
6335
  { action: "Register a project", description: "Browse \u2192 Projects \u2192 Add" },
6106
6336
  { action: "Create a sprint", description: "once a project exists" }
6107
6337
  ];
6108
- return /* @__PURE__ */ jsx59(ResultCard, { kind: "success", title: "You're set up", fields: [["AI provider", providerLabel]], nextSteps });
6338
+ return /* @__PURE__ */ jsx60(ResultCard, { kind: "success", title: "You're set up", fields: [["AI provider", providerLabel]], nextSteps });
6109
6339
  }
6110
6340
 
6111
6341
  // src/integration/ui/tui/views/workflows/reactivate-sprint-view.tsx
6112
- import { useMemo as useMemo34 } from "react";
6113
- import { jsx as jsx60 } from "react/jsx-runtime";
6114
- var TITLE32 = "Reactivate Sprint";
6115
- var HINTS_RUNNING24 = [{ key: "Esc", action: "cancel" }];
6116
- var HINTS_DONE24 = [
6342
+ import { useMemo as useMemo35 } from "react";
6343
+ import { jsx as jsx61 } from "react/jsx-runtime";
6344
+ var TITLE33 = "Reactivate Sprint";
6345
+ var HINTS_RUNNING25 = [{ key: "Esc", action: "cancel" }];
6346
+ var HINTS_DONE25 = [
6117
6347
  { key: "Enter", action: "back" },
6118
6348
  { key: "Esc", action: "back" }
6119
6349
  ];
@@ -6147,22 +6377,22 @@ function ReactivateSprintView({ sprintId }) {
6147
6377
  }
6148
6378
  });
6149
6379
  const running = phase.kind === "running" || phase.kind === "loading";
6150
- const hints = useMemo34(() => running ? HINTS_RUNNING24 : HINTS_DONE24, [running]);
6380
+ const hints = useMemo35(() => running ? HINTS_RUNNING25 : HINTS_DONE25, [running]);
6151
6381
  useViewHints(hints);
6152
- return /* @__PURE__ */ jsx60(ViewShell, { title: TITLE32, children: renderBody28(phase) });
6382
+ return /* @__PURE__ */ jsx61(ViewShell, { title: TITLE33, children: renderBody29(phase) });
6153
6383
  }
6154
- function renderBody28(phase) {
6384
+ function renderBody29(phase) {
6155
6385
  switch (phase.kind) {
6156
6386
  case "loading":
6157
- return /* @__PURE__ */ jsx60(Spinner, { label: "Loading sprint\u2026" });
6387
+ return /* @__PURE__ */ jsx61(Spinner, { label: "Loading sprint\u2026" });
6158
6388
  case "running":
6159
- return /* @__PURE__ */ jsx60(Spinner, { label: phase.step === "confirm" ? "Awaiting confirmation\u2026" : "Reactivating sprint\u2026" });
6389
+ return /* @__PURE__ */ jsx61(Spinner, { label: phase.step === "confirm" ? "Awaiting confirmation\u2026" : "Reactivating sprint\u2026" });
6160
6390
  case "cancelled":
6161
- return /* @__PURE__ */ jsx60(ResultCard, { kind: "info", title: "Reactivation cancelled" });
6391
+ return /* @__PURE__ */ jsx61(ResultCard, { kind: "info", title: "Reactivation cancelled" });
6162
6392
  case "missing-id":
6163
- return /* @__PURE__ */ jsx60(ResultCard, { kind: "error", title: "No sprint ID provided" });
6393
+ return /* @__PURE__ */ jsx61(ResultCard, { kind: "error", title: "No sprint ID provided" });
6164
6394
  case "not-closed":
6165
- return /* @__PURE__ */ jsx60(
6395
+ return /* @__PURE__ */ jsx61(
6166
6396
  ResultCard,
6167
6397
  {
6168
6398
  kind: "warning",
@@ -6171,9 +6401,9 @@ function renderBody28(phase) {
6171
6401
  }
6172
6402
  );
6173
6403
  case "error":
6174
- return /* @__PURE__ */ jsx60(ResultCard, { kind: "error", title: "Could not reactivate sprint", lines: [phase.message] });
6404
+ return /* @__PURE__ */ jsx61(ResultCard, { kind: "error", title: "Could not reactivate sprint", lines: [phase.message] });
6175
6405
  case "done":
6176
- return /* @__PURE__ */ jsx60(
6406
+ return /* @__PURE__ */ jsx61(
6177
6407
  ResultCard,
6178
6408
  {
6179
6409
  kind: "success",
@@ -6189,9 +6419,9 @@ function renderBody28(phase) {
6189
6419
  }
6190
6420
 
6191
6421
  // src/integration/ui/tui/views/browse/evaluations-view.tsx
6192
- import { useEffect as useEffect24, useState as useState25 } from "react";
6193
- import { jsx as jsx61 } from "react/jsx-runtime";
6194
- var TITLE33 = "Evaluations";
6422
+ import { useEffect as useEffect25, useState as useState25 } from "react";
6423
+ import { jsx as jsx62 } from "react/jsx-runtime";
6424
+ var TITLE34 = "Evaluations";
6195
6425
  var HINTS4 = [
6196
6426
  { key: "\u2191/\u2193", action: "navigate" },
6197
6427
  { key: "Enter", action: "open" }
@@ -6224,7 +6454,7 @@ function EvaluationsView({ sprintId }) {
6224
6454
  const router = useRouter();
6225
6455
  const [state, setState] = useState25({ kind: "loading" });
6226
6456
  useViewHints(HINTS4);
6227
- useEffect24(() => {
6457
+ useEffect25(() => {
6228
6458
  const ctl = { cancelled: false };
6229
6459
  void (async () => {
6230
6460
  try {
@@ -6243,7 +6473,7 @@ function EvaluationsView({ sprintId }) {
6243
6473
  ctl.cancelled = true;
6244
6474
  };
6245
6475
  }, [sprintId]);
6246
- return /* @__PURE__ */ jsx61(ViewShell, { title: TITLE33, children: state.kind === "loading" ? /* @__PURE__ */ jsx61(Spinner, { label: "Loading evaluations\u2026" }) : state.kind === "empty" ? /* @__PURE__ */ jsx61(ResultCard, { kind: "info", title: "No evaluations yet", lines: ["Run the executor to collect evaluator output."] }) : state.kind === "error" ? /* @__PURE__ */ jsx61(ResultCard, { kind: "error", title: "Could not load evaluations", lines: [state.message] }) : /* @__PURE__ */ jsx61(
6476
+ return /* @__PURE__ */ jsx62(ViewShell, { title: TITLE34, children: state.kind === "loading" ? /* @__PURE__ */ jsx62(Spinner, { label: "Loading evaluations\u2026" }) : state.kind === "empty" ? /* @__PURE__ */ jsx62(ResultCard, { kind: "info", title: "No evaluations yet", lines: ["Run the executor to collect evaluator output."] }) : state.kind === "error" ? /* @__PURE__ */ jsx62(ResultCard, { kind: "error", title: "Could not load evaluations", lines: [state.message] }) : /* @__PURE__ */ jsx62(
6247
6477
  ListView,
6248
6478
  {
6249
6479
  rows: state.tasks,
@@ -6256,10 +6486,10 @@ function EvaluationsView({ sprintId }) {
6256
6486
  }
6257
6487
 
6258
6488
  // src/integration/ui/tui/views/browse/evaluation-show-view.tsx
6259
- import { useEffect as useEffect25, useState as useState26 } from "react";
6489
+ import { useEffect as useEffect26, useState as useState26 } from "react";
6260
6490
  import { Box as Box32, Text as Text32 } from "ink";
6261
- import { jsx as jsx62, jsxs as jsxs32 } from "react/jsx-runtime";
6262
- var TITLE34 = "Evaluation";
6491
+ import { jsx as jsx63, jsxs as jsxs32 } from "react/jsx-runtime";
6492
+ var TITLE35 = "Evaluation";
6263
6493
  var HINTS5 = [];
6264
6494
  var MAX_LINES = 200;
6265
6495
  function kindFor(status) {
@@ -6270,7 +6500,7 @@ function kindFor(status) {
6270
6500
  function EvaluationShowView({ sprintId, taskId }) {
6271
6501
  const [state, setState] = useState26({ kind: "loading" });
6272
6502
  useViewHints(HINTS5);
6273
- useEffect25(() => {
6503
+ useEffect26(() => {
6274
6504
  const ctl = { cancelled: false };
6275
6505
  void (async () => {
6276
6506
  try {
@@ -6290,22 +6520,22 @@ function EvaluationShowView({ sprintId, taskId }) {
6290
6520
  ctl.cancelled = true;
6291
6521
  };
6292
6522
  }, [sprintId, taskId]);
6293
- return /* @__PURE__ */ jsx62(ViewShell, { title: TITLE34, children: renderBody29(state) });
6523
+ return /* @__PURE__ */ jsx63(ViewShell, { title: TITLE35, children: renderBody30(state) });
6294
6524
  }
6295
- function renderBody29(state) {
6296
- if (state.kind === "loading") return /* @__PURE__ */ jsx62(Spinner, { label: "Loading evaluation\u2026" });
6525
+ function renderBody30(state) {
6526
+ if (state.kind === "loading") return /* @__PURE__ */ jsx63(Spinner, { label: "Loading evaluation\u2026" });
6297
6527
  if (state.kind === "error")
6298
- return /* @__PURE__ */ jsx62(ResultCard, { kind: "error", title: "Could not load evaluation", lines: [state.message] });
6528
+ return /* @__PURE__ */ jsx63(ResultCard, { kind: "error", title: "Could not load evaluation", lines: [state.message] });
6299
6529
  const { task, content } = state;
6300
6530
  const lines = content.split("\n");
6301
6531
  const tail = lines.length > MAX_LINES ? lines.slice(-MAX_LINES) : lines;
6302
6532
  return /* @__PURE__ */ jsxs32(Box32, { flexDirection: "column", children: [
6303
6533
  /* @__PURE__ */ jsxs32(Box32, { children: [
6304
- /* @__PURE__ */ jsx62(Text32, { bold: true, children: task.name }),
6305
- /* @__PURE__ */ jsx62(Text32, { children: " " }),
6306
- /* @__PURE__ */ jsx62(StatusChip, { label: task.evaluationStatus ?? "unknown", kind: kindFor(task.evaluationStatus) })
6534
+ /* @__PURE__ */ jsx63(Text32, { bold: true, children: task.name }),
6535
+ /* @__PURE__ */ jsx63(Text32, { children: " " }),
6536
+ /* @__PURE__ */ jsx63(StatusChip, { label: task.evaluationStatus ?? "unknown", kind: kindFor(task.evaluationStatus) })
6307
6537
  ] }),
6308
- content.trim().length === 0 ? /* @__PURE__ */ jsx62(Box32, { marginTop: spacing.section, children: /* @__PURE__ */ jsx62(Text32, { color: inkColors.muted, children: "No evaluator output recorded." }) }) : /* @__PURE__ */ jsxs32(Box32, { marginTop: spacing.section, flexDirection: "column", children: [
6538
+ content.trim().length === 0 ? /* @__PURE__ */ jsx63(Box32, { marginTop: spacing.section, children: /* @__PURE__ */ jsx63(Text32, { color: inkColors.muted, children: "No evaluator output recorded." }) }) : /* @__PURE__ */ jsxs32(Box32, { marginTop: spacing.section, flexDirection: "column", children: [
6309
6539
  lines.length > MAX_LINES ? /* @__PURE__ */ jsxs32(Text32, { dimColor: true, children: [
6310
6540
  "Showing last ",
6311
6541
  String(MAX_LINES),
@@ -6313,21 +6543,21 @@ function renderBody29(state) {
6313
6543
  String(lines.length),
6314
6544
  " total)"
6315
6545
  ] }) : null,
6316
- tail.map((line2, i) => /* @__PURE__ */ jsx62(Text32, { dimColor: line2.trim().length === 0, children: line2.length > 0 ? line2 : " " }, i))
6546
+ tail.map((line2, i) => /* @__PURE__ */ jsx63(Text32, { dimColor: line2.trim().length === 0, children: line2.length > 0 ? line2 : " " }, i))
6317
6547
  ] })
6318
6548
  ] });
6319
6549
  }
6320
6550
 
6321
6551
  // src/integration/ui/tui/views/browse/feedback-view.tsx
6322
- import { useEffect as useEffect26, useState as useState27 } from "react";
6552
+ import { useEffect as useEffect27, useState as useState27 } from "react";
6323
6553
  import { Box as Box33, Text as Text33 } from "ink";
6324
- import { jsx as jsx63, jsxs as jsxs33 } from "react/jsx-runtime";
6325
- var TITLE35 = "Feedback";
6554
+ import { jsx as jsx64, jsxs as jsxs33 } from "react/jsx-runtime";
6555
+ var TITLE36 = "Feedback";
6326
6556
  var HINTS6 = [];
6327
6557
  function FeedbackView({ sprintId }) {
6328
6558
  const [state, setState] = useState27({ kind: "loading" });
6329
6559
  useViewHints(HINTS6);
6330
- useEffect26(() => {
6560
+ useEffect27(() => {
6331
6561
  const ctl = { cancelled: false };
6332
6562
  void (async () => {
6333
6563
  try {
@@ -6344,16 +6574,16 @@ function FeedbackView({ sprintId }) {
6344
6574
  ctl.cancelled = true;
6345
6575
  };
6346
6576
  }, [sprintId]);
6347
- return /* @__PURE__ */ jsx63(ViewShell, { title: TITLE35, children: state.kind === "loading" ? /* @__PURE__ */ jsx63(Spinner, { label: "Loading feedback\u2026" }) : state.kind === "empty" ? /* @__PURE__ */ jsx63(
6577
+ return /* @__PURE__ */ jsx64(ViewShell, { title: TITLE36, children: state.kind === "loading" ? /* @__PURE__ */ jsx64(Spinner, { label: "Loading feedback\u2026" }) : state.kind === "empty" ? /* @__PURE__ */ jsx64(
6348
6578
  ResultCard,
6349
6579
  {
6350
6580
  kind: "info",
6351
6581
  title: "No feedback yet",
6352
6582
  lines: ["Feedback is captured during the post-execution loop."]
6353
6583
  }
6354
- ) : state.kind === "error" ? /* @__PURE__ */ jsx63(ResultCard, { kind: "error", title: "Could not load feedback", lines: [state.message] }) : /* @__PURE__ */ jsx63(Box33, { flexDirection: "column", children: state.entries.map((entry, i) => /* @__PURE__ */ jsxs33(Box33, { marginTop: i === 0 ? 0 : spacing.section, flexDirection: "column", children: [
6355
- /* @__PURE__ */ jsx63(Text33, { color: inkColors.muted, bold: true, children: entry.timestamp }),
6356
- /* @__PURE__ */ jsx63(Text33, { children: entry.preview })
6584
+ ) : state.kind === "error" ? /* @__PURE__ */ jsx64(ResultCard, { kind: "error", title: "Could not load feedback", lines: [state.message] }) : /* @__PURE__ */ jsx64(Box33, { flexDirection: "column", children: state.entries.map((entry, i) => /* @__PURE__ */ jsxs33(Box33, { marginTop: i === 0 ? 0 : spacing.section, flexDirection: "column", children: [
6585
+ /* @__PURE__ */ jsx64(Text33, { color: inkColors.muted, bold: true, children: entry.timestamp }),
6586
+ /* @__PURE__ */ jsx64(Text33, { children: entry.preview })
6357
6587
  ] }, i)) }) });
6358
6588
  }
6359
6589
  function extractFeedback(progress) {
@@ -6372,7 +6602,7 @@ function extractFeedback(progress) {
6372
6602
  }
6373
6603
 
6374
6604
  // src/integration/ui/tui/components/version-hint.tsx
6375
- import { useEffect as useEffect27, useState as useState28 } from "react";
6605
+ import { useEffect as useEffect28, useState as useState28 } from "react";
6376
6606
  import { Text as Text34 } from "ink";
6377
6607
 
6378
6608
  // src/integration/external/version-check.ts
@@ -6461,10 +6691,10 @@ async function checkLatestVersion() {
6461
6691
  }
6462
6692
 
6463
6693
  // src/integration/ui/tui/components/version-hint.tsx
6464
- import { jsx as jsx64 } from "react/jsx-runtime";
6694
+ import { jsx as jsx65 } from "react/jsx-runtime";
6465
6695
  function VersionHint() {
6466
6696
  const [check, setCheck] = useState28(null);
6467
- useEffect27(() => {
6697
+ useEffect28(() => {
6468
6698
  let cancelled = false;
6469
6699
  void checkLatestVersion().then((result) => {
6470
6700
  if (!cancelled && result !== null) setCheck(result);
@@ -6474,167 +6704,175 @@ function VersionHint() {
6474
6704
  };
6475
6705
  }, []);
6476
6706
  if (!check?.updateAvailable) return null;
6477
- return /* @__PURE__ */ jsx64(Text34, { dimColor: true, children: `v${check.latest} available \xB7 npm install -g ralphctl` });
6707
+ return /* @__PURE__ */ jsx65(Text34, { dimColor: true, children: `v${check.latest} available \xB7 npm install -g ralphctl` });
6478
6708
  }
6479
6709
 
6480
6710
  // src/integration/ui/tui/views/view-router.tsx
6481
- import { jsx as jsx65, jsxs as jsxs34 } from "react/jsx-runtime";
6711
+ import { jsx as jsx66, jsxs as jsxs34 } from "react/jsx-runtime";
6482
6712
  var views = {
6483
6713
  home: {
6484
6714
  label: "Home",
6485
- render: () => /* @__PURE__ */ jsx65(HomeView, {})
6715
+ render: () => /* @__PURE__ */ jsx66(HomeView, {})
6486
6716
  },
6487
6717
  settings: {
6488
6718
  label: "Settings",
6489
- render: () => /* @__PURE__ */ jsx65(SettingsView, {})
6719
+ render: () => /* @__PURE__ */ jsx66(SettingsView, {})
6490
6720
  },
6491
6721
  execute: {
6492
6722
  label: "Execute",
6493
6723
  render: (props) => {
6494
6724
  const sprintId = typeof props["sprintId"] === "string" ? props["sprintId"] : "";
6495
6725
  const executionOptions = props["executionOptions"];
6496
- return /* @__PURE__ */ jsx65(ExecuteView, { sprintId, executionOptions });
6726
+ return /* @__PURE__ */ jsx66(ExecuteView, { sprintId, executionOptions });
6497
6727
  }
6498
6728
  },
6499
6729
  dashboard: {
6500
6730
  label: "Dashboard",
6501
- render: () => /* @__PURE__ */ jsx65(DashboardView, {})
6731
+ render: () => /* @__PURE__ */ jsx66(DashboardView, {})
6502
6732
  },
6503
6733
  "refine-phase": {
6504
6734
  label: "Refine",
6505
6735
  render: (props) => {
6506
6736
  const sprintId = typeof props["sprintId"] === "string" ? props["sprintId"] : "";
6507
- return /* @__PURE__ */ jsx65(RefinePhaseView, { sprintId });
6737
+ return /* @__PURE__ */ jsx66(RefinePhaseView, { sprintId });
6508
6738
  }
6509
6739
  },
6510
6740
  "plan-phase": {
6511
6741
  label: "Plan",
6512
6742
  render: (props) => {
6513
6743
  const sprintId = typeof props["sprintId"] === "string" ? props["sprintId"] : "";
6514
- return /* @__PURE__ */ jsx65(PlanPhaseView, { sprintId });
6744
+ return /* @__PURE__ */ jsx66(PlanPhaseView, { sprintId });
6515
6745
  }
6516
6746
  },
6517
6747
  "close-phase": {
6518
6748
  label: "Close",
6519
6749
  render: (props) => {
6520
6750
  const sprintId = typeof props["sprintId"] === "string" ? props["sprintId"] : "";
6521
- return /* @__PURE__ */ jsx65(ClosePhaseView, { sprintId });
6751
+ return /* @__PURE__ */ jsx66(ClosePhaseView, { sprintId });
6522
6752
  }
6523
6753
  },
6524
6754
  "sprint-create": {
6525
6755
  label: "Create Sprint",
6526
- render: () => /* @__PURE__ */ jsx65(CreateSprintView, {})
6756
+ render: () => /* @__PURE__ */ jsx66(CreateSprintView, {})
6527
6757
  },
6528
6758
  "sprint-delete": {
6529
6759
  label: "Delete Sprint",
6530
6760
  render: (props) => {
6531
6761
  const sprintId = typeof props["sprintId"] === "string" ? props["sprintId"] : void 0;
6532
- return /* @__PURE__ */ jsx65(DeleteSprintView, { sprintId });
6762
+ return /* @__PURE__ */ jsx66(DeleteSprintView, { sprintId });
6533
6763
  }
6534
6764
  },
6535
6765
  "sprint-set-current": {
6536
6766
  label: "Set Current",
6537
- render: () => /* @__PURE__ */ jsx65(SetCurrentSprintView, {})
6767
+ render: () => /* @__PURE__ */ jsx66(SetCurrentSprintView, {})
6538
6768
  },
6539
6769
  "sprint-requirements-export": {
6540
6770
  label: "Requirements",
6541
6771
  render: (props) => {
6542
6772
  const sprintId = typeof props["sprintId"] === "string" ? props["sprintId"] : void 0;
6543
- return /* @__PURE__ */ jsx65(RequirementsExportView, { sprintId });
6773
+ return /* @__PURE__ */ jsx66(RequirementsExportView, { sprintId });
6544
6774
  }
6545
6775
  },
6546
6776
  "sprint-context-export": {
6547
6777
  label: "Context",
6548
6778
  render: (props) => {
6549
6779
  const sprintId = typeof props["sprintId"] === "string" ? props["sprintId"] : void 0;
6550
- return /* @__PURE__ */ jsx65(ContextExportView, { sprintId });
6780
+ return /* @__PURE__ */ jsx66(ContextExportView, { sprintId });
6551
6781
  }
6552
6782
  },
6553
6783
  "ticket-add": {
6554
6784
  label: "Add Ticket",
6555
- render: () => /* @__PURE__ */ jsx65(TicketAddView, {})
6785
+ render: () => /* @__PURE__ */ jsx66(TicketAddView, {})
6556
6786
  },
6557
6787
  "ticket-edit": {
6558
6788
  label: "Edit Ticket",
6559
6789
  render: (props) => {
6560
6790
  const ticketId = typeof props["ticketId"] === "string" ? props["ticketId"] : void 0;
6561
- return /* @__PURE__ */ jsx65(TicketEditView, { ticketId });
6791
+ return /* @__PURE__ */ jsx66(TicketEditView, { ticketId });
6562
6792
  }
6563
6793
  },
6564
6794
  "ticket-remove": {
6565
6795
  label: "Remove Ticket",
6566
- render: () => /* @__PURE__ */ jsx65(TicketRemoveView, {})
6796
+ render: () => /* @__PURE__ */ jsx66(TicketRemoveView, {})
6567
6797
  },
6568
6798
  "ticket-refine": {
6569
6799
  label: "Re-Refine Ticket",
6570
- render: () => /* @__PURE__ */ jsx65(TicketRefineView, {})
6800
+ render: () => /* @__PURE__ */ jsx66(TicketRefineView, {})
6801
+ },
6802
+ "task-add": { label: "Add Task", render: () => /* @__PURE__ */ jsx66(TaskAddView, {}) },
6803
+ "task-import": { label: "Import Tasks", render: () => /* @__PURE__ */ jsx66(TaskImportView, {}) },
6804
+ "task-status": { label: "Task Status", render: () => /* @__PURE__ */ jsx66(TaskStatusView, {}) },
6805
+ "task-reorder": { label: "Reorder Task", render: () => /* @__PURE__ */ jsx66(TaskReorderView, {}) },
6806
+ "task-remove": { label: "Remove Task", render: () => /* @__PURE__ */ jsx66(TaskRemoveView, {}) },
6807
+ "task-next": { label: "Next Task", render: () => /* @__PURE__ */ jsx66(TaskNextView, {}) },
6808
+ "project-add": { label: "Add Project", render: () => /* @__PURE__ */ jsx66(ProjectAddView, {}) },
6809
+ "project-remove": { label: "Remove Project", render: () => /* @__PURE__ */ jsx66(ProjectRemoveView, {}) },
6810
+ "project-repo-add": { label: "Add Repository", render: () => /* @__PURE__ */ jsx66(ProjectRepoAddView, {}) },
6811
+ "project-repo-remove": { label: "Remove Repository", render: () => /* @__PURE__ */ jsx66(ProjectRepoRemoveView, {}) },
6812
+ "project-edit": { label: "Edit Project", render: () => /* @__PURE__ */ jsx66(ProjectEditView, {}) },
6813
+ "project-onboard": {
6814
+ label: "Onboard Repository",
6815
+ render: (props) => {
6816
+ const projectName = typeof props["projectName"] === "string" ? props["projectName"] : void 0;
6817
+ const repo = typeof props["repo"] === "string" ? props["repo"] : void 0;
6818
+ return /* @__PURE__ */ jsx66(ProjectOnboardView, { projectName, repo });
6819
+ }
6571
6820
  },
6572
- "task-add": { label: "Add Task", render: () => /* @__PURE__ */ jsx65(TaskAddView, {}) },
6573
- "task-import": { label: "Import Tasks", render: () => /* @__PURE__ */ jsx65(TaskImportView, {}) },
6574
- "task-status": { label: "Task Status", render: () => /* @__PURE__ */ jsx65(TaskStatusView, {}) },
6575
- "task-reorder": { label: "Reorder Task", render: () => /* @__PURE__ */ jsx65(TaskReorderView, {}) },
6576
- "task-remove": { label: "Remove Task", render: () => /* @__PURE__ */ jsx65(TaskRemoveView, {}) },
6577
- "task-next": { label: "Next Task", render: () => /* @__PURE__ */ jsx65(TaskNextView, {}) },
6578
- "project-add": { label: "Add Project", render: () => /* @__PURE__ */ jsx65(ProjectAddView, {}) },
6579
- "project-remove": { label: "Remove Project", render: () => /* @__PURE__ */ jsx65(ProjectRemoveView, {}) },
6580
- "project-repo-add": { label: "Add Repository", render: () => /* @__PURE__ */ jsx65(ProjectRepoAddView, {}) },
6581
- "project-repo-remove": { label: "Remove Repository", render: () => /* @__PURE__ */ jsx65(ProjectRepoRemoveView, {}) },
6582
- "project-edit": { label: "Edit Project", render: () => /* @__PURE__ */ jsx65(ProjectEditView, {}) },
6583
- "sprint-list": { label: "Sprints", render: () => /* @__PURE__ */ jsx65(SprintListView, {}) },
6821
+ "sprint-list": { label: "Sprints", render: () => /* @__PURE__ */ jsx66(SprintListView, {}) },
6584
6822
  "sprint-show": {
6585
6823
  label: "Sprint",
6586
6824
  render: (props) => {
6587
6825
  const sprintId = typeof props["sprintId"] === "string" ? props["sprintId"] : void 0;
6588
- return /* @__PURE__ */ jsx65(SprintShowView, { sprintId });
6826
+ return /* @__PURE__ */ jsx66(SprintShowView, { sprintId });
6589
6827
  }
6590
6828
  },
6591
- "ticket-list": { label: "Tickets", render: () => /* @__PURE__ */ jsx65(TicketListView, {}) },
6829
+ "ticket-list": { label: "Tickets", render: () => /* @__PURE__ */ jsx66(TicketListView, {}) },
6592
6830
  "ticket-show": {
6593
6831
  label: "Ticket",
6594
6832
  render: (props) => {
6595
6833
  const ticketId = typeof props["ticketId"] === "string" ? props["ticketId"] : void 0;
6596
- return /* @__PURE__ */ jsx65(TicketShowView, { ticketId });
6834
+ return /* @__PURE__ */ jsx66(TicketShowView, { ticketId });
6597
6835
  }
6598
6836
  },
6599
- "task-list": { label: "Tasks", render: () => /* @__PURE__ */ jsx65(TaskListView, {}) },
6837
+ "task-list": { label: "Tasks", render: () => /* @__PURE__ */ jsx66(TaskListView, {}) },
6600
6838
  "task-show": {
6601
6839
  label: "Task",
6602
6840
  render: (props) => {
6603
6841
  const taskId = typeof props["taskId"] === "string" ? props["taskId"] : void 0;
6604
- return /* @__PURE__ */ jsx65(TaskShowView, { taskId });
6842
+ return /* @__PURE__ */ jsx66(TaskShowView, { taskId });
6605
6843
  }
6606
6844
  },
6607
- "project-list": { label: "Projects", render: () => /* @__PURE__ */ jsx65(ProjectListView, {}) },
6845
+ "project-list": { label: "Projects", render: () => /* @__PURE__ */ jsx66(ProjectListView, {}) },
6608
6846
  "project-show": {
6609
6847
  label: "Project",
6610
6848
  render: (props) => {
6611
6849
  const projectName = typeof props["projectName"] === "string" ? props["projectName"] : void 0;
6612
- return /* @__PURE__ */ jsx65(ProjectShowView, { projectName });
6850
+ return /* @__PURE__ */ jsx66(ProjectShowView, { projectName });
6613
6851
  }
6614
6852
  },
6615
- doctor: { label: "Doctor", render: () => /* @__PURE__ */ jsx65(DoctorView, {}) },
6616
- "progress-log": { label: "Log Progress", render: () => /* @__PURE__ */ jsx65(ProgressLogView, {}) },
6853
+ doctor: { label: "Doctor", render: () => /* @__PURE__ */ jsx66(DoctorView, {}) },
6854
+ "progress-log": { label: "Log Progress", render: () => /* @__PURE__ */ jsx66(ProgressLogView, {}) },
6617
6855
  "progress-show": {
6618
6856
  label: "Progress",
6619
6857
  render: (props) => {
6620
6858
  const sprintId = typeof props["sprintId"] === "string" ? props["sprintId"] : void 0;
6621
- return /* @__PURE__ */ jsx65(ProgressShowView, { sprintId });
6859
+ return /* @__PURE__ */ jsx66(ProgressShowView, { sprintId });
6622
6860
  }
6623
6861
  },
6624
- ideate: { label: "Ideate", render: () => /* @__PURE__ */ jsx65(IdeateView, {}) },
6625
- onboarding: { label: "Welcome", render: () => /* @__PURE__ */ jsx65(OnboardingView, {}) },
6862
+ ideate: { label: "Ideate", render: () => /* @__PURE__ */ jsx66(IdeateView, {}) },
6863
+ onboarding: { label: "Welcome", render: () => /* @__PURE__ */ jsx66(OnboardingView, {}) },
6626
6864
  "sprint-reactivate": {
6627
6865
  label: "Reactivate Sprint",
6628
6866
  render: (props) => {
6629
6867
  const sprintId = typeof props["sprintId"] === "string" ? props["sprintId"] : void 0;
6630
- return /* @__PURE__ */ jsx65(ReactivateSprintView, { sprintId });
6868
+ return /* @__PURE__ */ jsx66(ReactivateSprintView, { sprintId });
6631
6869
  }
6632
6870
  },
6633
6871
  evaluations: {
6634
6872
  label: "Evaluations",
6635
6873
  render: (props) => {
6636
6874
  const sprintId = typeof props["sprintId"] === "string" ? props["sprintId"] : void 0;
6637
- return /* @__PURE__ */ jsx65(EvaluationsView, { sprintId });
6875
+ return /* @__PURE__ */ jsx66(EvaluationsView, { sprintId });
6638
6876
  }
6639
6877
  },
6640
6878
  "evaluation-show": {
@@ -6642,14 +6880,14 @@ var views = {
6642
6880
  render: (props) => {
6643
6881
  const sprintId = typeof props["sprintId"] === "string" ? props["sprintId"] : "";
6644
6882
  const taskId = typeof props["taskId"] === "string" ? props["taskId"] : "";
6645
- return /* @__PURE__ */ jsx65(EvaluationShowView, { sprintId, taskId });
6883
+ return /* @__PURE__ */ jsx66(EvaluationShowView, { sprintId, taskId });
6646
6884
  }
6647
6885
  },
6648
6886
  feedback: {
6649
6887
  label: "Feedback",
6650
6888
  render: (props) => {
6651
6889
  const sprintId = typeof props["sprintId"] === "string" ? props["sprintId"] : void 0;
6652
- return /* @__PURE__ */ jsx65(FeedbackView, { sprintId });
6890
+ return /* @__PURE__ */ jsx66(FeedbackView, { sprintId });
6653
6891
  }
6654
6892
  }
6655
6893
  };
@@ -6661,9 +6899,9 @@ function ViewRouter({ initialStack }) {
6661
6899
  }
6662
6900
  return collapseAdjacentDuplicates(initialStack);
6663
6901
  });
6664
- const stackRef = useRef3(stack);
6902
+ const stackRef = useRef4(stack);
6665
6903
  stackRef.current = stack;
6666
- const push = useCallback10((entry) => {
6904
+ const push = useCallback11((entry) => {
6667
6905
  setStack((s) => {
6668
6906
  const top = s[s.length - 1];
6669
6907
  if (top?.id === entry.id && samePropsBag(top.props, entry.props)) {
@@ -6672,20 +6910,20 @@ function ViewRouter({ initialStack }) {
6672
6910
  return [...s, entry];
6673
6911
  });
6674
6912
  }, []);
6675
- const pop = useCallback10(() => {
6913
+ const pop = useCallback11(() => {
6676
6914
  setStack((s) => s.length > 1 ? s.slice(0, -1) : s);
6677
6915
  }, []);
6678
- const replace = useCallback10((entry) => {
6916
+ const replace = useCallback11((entry) => {
6679
6917
  setStack((s) => s.length === 0 ? [entry] : [...s.slice(0, -1), entry]);
6680
6918
  }, []);
6681
- const reset = useCallback10((entry) => {
6919
+ const reset = useCallback11((entry) => {
6682
6920
  setStack(() => [entry]);
6683
6921
  }, []);
6684
6922
  const current = stack[stack.length - 1];
6685
6923
  if (current === void 0) {
6686
6924
  throw new Error("ViewRouter stack is empty");
6687
6925
  }
6688
- const api = useMemo35(
6926
+ const api = useMemo36(
6689
6927
  () => ({ current, stack, push, pop, replace, reset }),
6690
6928
  [current, stack, push, pop, replace, reset]
6691
6929
  );
@@ -6721,11 +6959,11 @@ function ViewRouter({ initialStack }) {
6721
6959
  );
6722
6960
  const meta = views[current.id];
6723
6961
  const props = current.props ?? {};
6724
- return /* @__PURE__ */ jsx65(RouterProvider, { value: api, children: /* @__PURE__ */ jsx65(ViewHintsProvider, { children: /* @__PURE__ */ jsxs34(Box34, { flexDirection: "column", children: [
6725
- /* @__PURE__ */ jsx65(Banner, {}),
6962
+ return /* @__PURE__ */ jsx66(RouterProvider, { value: api, children: /* @__PURE__ */ jsx66(ViewHintsProvider, { children: /* @__PURE__ */ jsxs34(Box34, { flexDirection: "column", children: [
6963
+ /* @__PURE__ */ jsx66(Banner, {}),
6726
6964
  meta.render(props),
6727
- /* @__PURE__ */ jsx65(PromptHost, {}),
6728
- /* @__PURE__ */ jsx65(Box34, { marginTop: 1, children: /* @__PURE__ */ jsx65(KeyboardHints, {}) }),
6965
+ /* @__PURE__ */ jsx66(PromptHost, {}),
6966
+ /* @__PURE__ */ jsx66(Box34, { marginTop: 1, children: /* @__PURE__ */ jsx66(KeyboardHints, {}) }),
6729
6967
  /* @__PURE__ */ jsxs34(
6730
6968
  Box34,
6731
6969
  {
@@ -6736,8 +6974,8 @@ function ViewRouter({ initialStack }) {
6736
6974
  paddingX: spacing.indent,
6737
6975
  justifyContent: "space-between",
6738
6976
  children: [
6739
- /* @__PURE__ */ jsx65(StatusBar, { breadcrumb: stack.map((e) => views[e.id].label), hints: buildHints(current.id, stack.length) }),
6740
- /* @__PURE__ */ jsx65(VersionHint, {})
6977
+ /* @__PURE__ */ jsx66(StatusBar, { breadcrumb: stack.map((e) => views[e.id].label), hints: buildHints(current.id, stack.length) }),
6978
+ /* @__PURE__ */ jsx66(VersionHint, {})
6741
6979
  ]
6742
6980
  }
6743
6981
  )
@@ -6785,7 +7023,7 @@ function buildHints(currentId, depth) {
6785
7023
  }
6786
7024
 
6787
7025
  // src/integration/ui/tui/views/app.tsx
6788
- import { jsx as jsx66 } from "react/jsx-runtime";
7026
+ import { jsx as jsx67 } from "react/jsx-runtime";
6789
7027
  var MAX_CONTENT_WIDTH = 160;
6790
7028
  async function isFirstRun() {
6791
7029
  try {
@@ -6813,7 +7051,7 @@ function buildInitialStack(initialView, mountOptions) {
6813
7051
  function useTerminalWidth() {
6814
7052
  const { stdout } = useStdout();
6815
7053
  const [width, setWidth] = useState30(stdout.columns);
6816
- useEffect28(() => {
7054
+ useEffect29(() => {
6817
7055
  const onResize = () => {
6818
7056
  setWidth(stdout.columns);
6819
7057
  };
@@ -6828,7 +7066,7 @@ function App({ initialView, mountOptions }) {
6828
7066
  const terminalWidth = useTerminalWidth();
6829
7067
  const contentWidth = Math.min(terminalWidth, MAX_CONTENT_WIDTH);
6830
7068
  const [stack, setStack] = useState30(null);
6831
- useEffect28(() => {
7069
+ useEffect29(() => {
6832
7070
  let cancelled = false;
6833
7071
  const decideInitial = async () => {
6834
7072
  if (initialView === "execute" && mountOptions.sprintId !== void 0) {
@@ -6845,13 +7083,13 @@ function App({ initialView, mountOptions }) {
6845
7083
  };
6846
7084
  }, [initialView, mountOptions]);
6847
7085
  if (stack === null) {
6848
- return /* @__PURE__ */ jsx66(Box35, { width: terminalWidth });
7086
+ return /* @__PURE__ */ jsx67(Box35, { width: terminalWidth });
6849
7087
  }
6850
- return /* @__PURE__ */ jsx66(Box35, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx66(Box35, { flexDirection: "column", width: contentWidth, children: /* @__PURE__ */ jsx66(ViewRouter, { initialStack: stack }) }) });
7088
+ return /* @__PURE__ */ jsx67(Box35, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx67(Box35, { flexDirection: "column", width: contentWidth, children: /* @__PURE__ */ jsx67(ViewRouter, { initialStack: stack }) }) });
6851
7089
  }
6852
7090
 
6853
7091
  // src/integration/ui/tui/runtime/mount.tsx
6854
- import { jsx as jsx67 } from "react/jsx-runtime";
7092
+ import { jsx as jsx68 } from "react/jsx-runtime";
6855
7093
  function canMountInk() {
6856
7094
  if (process.env["RALPHCTL_NO_TUI"]) return false;
6857
7095
  if (process.env["CI"]) return false;
@@ -6870,7 +7108,7 @@ async function mountInkApp(options) {
6870
7108
  setSharedDeps(createSharedDeps({ logger, signalBus, prompt }));
6871
7109
  enterAltScreen();
6872
7110
  const releaseHost = registerExternalHost();
6873
- const app = render(/* @__PURE__ */ jsx67(App, { initialView: options.initialView, mountOptions: options }), {
7111
+ const app = render(/* @__PURE__ */ jsx68(App, { initialView: options.initialView, mountOptions: options }), {
6874
7112
  exitOnCtrlC: false
6875
7113
  // We own Ctrl+C inside the app for prompt cancellation.
6876
7114
  });