ralphctl 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{add-JGUOR4Z5.mjs → add-CIM72NE3.mjs} +2 -2
- package/dist/{chunk-JXMHLW42.mjs → chunk-7JLZQICD.mjs} +4 -3
- package/dist/{chunk-HL4ZMHCQ.mjs → chunk-JOQO4HMM.mjs} +8 -0
- package/dist/{chunk-CDOPLXFK.mjs → chunk-JYCGQA2D.mjs} +156 -61
- package/dist/{chunk-4GHVNKLV.mjs → chunk-MRN3Z2XC.mjs} +227 -60
- package/dist/cli.mjs +105 -10
- package/dist/{mount-XZPBDRPZ.mjs → mount-XMN3S4W6.mjs} +315 -176
- package/dist/prompts/plan-common.md +23 -4
- package/dist/prompts/task-evaluation-resume.md +6 -1
- package/dist/prompts/validation-checklist.md +1 -1
- package/dist/{start-MMWC7QLI.mjs → start-D35SOXMM.mjs} +2 -2
- package/package.json +1 -1
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
taskReorderCommand,
|
|
55
55
|
taskShowCommand,
|
|
56
56
|
taskStatusCommand,
|
|
57
|
+
taskWhyCommand,
|
|
57
58
|
ticketEditCommand,
|
|
58
59
|
ticketListCommand,
|
|
59
60
|
ticketRefineCommand,
|
|
@@ -61,7 +62,7 @@ import {
|
|
|
61
62
|
ticketShowCommand,
|
|
62
63
|
useCurrentPrompt,
|
|
63
64
|
validateConfigValue
|
|
64
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-MRN3Z2XC.mjs";
|
|
65
66
|
import {
|
|
66
67
|
PromptCancelledError,
|
|
67
68
|
projectAddCommand
|
|
@@ -71,7 +72,7 @@ import {
|
|
|
71
72
|
} from "./chunk-3QBEBKMZ.mjs";
|
|
72
73
|
import {
|
|
73
74
|
ticketAddCommand
|
|
74
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-7JLZQICD.mjs";
|
|
75
76
|
import {
|
|
76
77
|
addProjectRepo,
|
|
77
78
|
createProject,
|
|
@@ -108,7 +109,7 @@ import {
|
|
|
108
109
|
sprintStartCommand,
|
|
109
110
|
updateTaskStatus,
|
|
110
111
|
withSuspendedTui
|
|
111
|
-
} from "./chunk-
|
|
112
|
+
} from "./chunk-JYCGQA2D.mjs";
|
|
112
113
|
import {
|
|
113
114
|
addTicket,
|
|
114
115
|
allRequirementsApproved,
|
|
@@ -118,8 +119,9 @@ import {
|
|
|
118
119
|
getTicket,
|
|
119
120
|
listTickets,
|
|
120
121
|
removeTicket,
|
|
122
|
+
truncate,
|
|
121
123
|
updateTicket
|
|
122
|
-
} from "./chunk-
|
|
124
|
+
} from "./chunk-JOQO4HMM.mjs";
|
|
123
125
|
import "./chunk-CFUVE2BP.mjs";
|
|
124
126
|
import {
|
|
125
127
|
getPrompt,
|
|
@@ -322,7 +324,7 @@ import { useEffect as useEffect28, useState as useState30 } from "react";
|
|
|
322
324
|
import { Box as Box35, useStdout } from "ink";
|
|
323
325
|
|
|
324
326
|
// src/integration/ui/tui/views/view-router.tsx
|
|
325
|
-
import { useCallback as useCallback10, useMemo as
|
|
327
|
+
import { useCallback as useCallback10, useMemo as useMemo35, useRef as useRef3, useState as useState29 } from "react";
|
|
326
328
|
import { Box as Box34, useApp, useInput as useInput19 } from "ink";
|
|
327
329
|
|
|
328
330
|
// src/integration/ui/tui/components/banner.tsx
|
|
@@ -553,6 +555,7 @@ function buildTaskSubMenu(ctx) {
|
|
|
553
555
|
items.push(titled("VIEW"));
|
|
554
556
|
items.push({ name: "List", value: "list", description: "List all tasks" });
|
|
555
557
|
items.push({ name: "Next", value: "next", description: "Get next task" });
|
|
558
|
+
items.push({ name: "Why Blocked?", value: "why", description: "Explain why a task is blocked" });
|
|
556
559
|
items.push(blank());
|
|
557
560
|
items.push(titled("MANAGE"));
|
|
558
561
|
items.push({ name: "Add", value: "add", description: "Add a new task" });
|
|
@@ -1034,9 +1037,27 @@ var commandMap = {
|
|
|
1034
1037
|
show: () => sprintShowCommand([]),
|
|
1035
1038
|
context: () => sprintContextCommand([]),
|
|
1036
1039
|
current: () => sprintCurrentCommand(["-"]),
|
|
1037
|
-
refine: () =>
|
|
1040
|
+
refine: async () => {
|
|
1041
|
+
const mode = await getPrompt().select({
|
|
1042
|
+
message: "How should refinement run?",
|
|
1043
|
+
choices: [
|
|
1044
|
+
{ label: "Interactive \u2014 approve requirements for each ticket", value: "interactive" },
|
|
1045
|
+
{ label: "Auto \u2014 AI drafts requirements without prompts", value: "auto" }
|
|
1046
|
+
]
|
|
1047
|
+
});
|
|
1048
|
+
await sprintRefineCommand(mode === "auto" ? ["--auto"] : []);
|
|
1049
|
+
},
|
|
1038
1050
|
ideate: () => sprintIdeateCommand([]),
|
|
1039
|
-
plan: () =>
|
|
1051
|
+
plan: async () => {
|
|
1052
|
+
const mode = await getPrompt().select({
|
|
1053
|
+
message: "How should planning run?",
|
|
1054
|
+
choices: [
|
|
1055
|
+
{ label: "Interactive \u2014 pick affected repos manually", value: "interactive" },
|
|
1056
|
+
{ label: "Auto \u2014 AI explores all repos autonomously", value: "auto" }
|
|
1057
|
+
]
|
|
1058
|
+
});
|
|
1059
|
+
await sprintPlanCommand(mode === "auto" ? ["--auto", "--all-paths"] : []);
|
|
1060
|
+
},
|
|
1040
1061
|
start: () => sprintStartCommand([]),
|
|
1041
1062
|
requirements: () => sprintRequirementsCommand([]),
|
|
1042
1063
|
health: () => sprintHealthCommand(),
|
|
@@ -1061,6 +1082,7 @@ var commandMap = {
|
|
|
1061
1082
|
show: () => taskShowCommand([]),
|
|
1062
1083
|
status: () => taskStatusCommand([]),
|
|
1063
1084
|
next: () => taskNextCommand(),
|
|
1085
|
+
why: () => taskWhyCommand(),
|
|
1064
1086
|
reorder: () => taskReorderCommand([]),
|
|
1065
1087
|
remove: () => taskRemoveCommand([])
|
|
1066
1088
|
},
|
|
@@ -1641,11 +1663,11 @@ function SettingsView() {
|
|
|
1641
1663
|
}
|
|
1642
1664
|
|
|
1643
1665
|
// src/integration/ui/tui/views/execute-view.tsx
|
|
1644
|
-
import { useEffect as
|
|
1645
|
-
import { Box as
|
|
1666
|
+
import { useEffect as useEffect8, useRef as useRef2, useState as useState8 } from "react";
|
|
1667
|
+
import { Box as Box17, Text as Text16, useInput as useInput5 } from "ink";
|
|
1646
1668
|
|
|
1647
1669
|
// src/integration/ui/tui/runtime/hooks.ts
|
|
1648
|
-
import { useCallback as useCallback4, useEffect as useEffect6, useState as useState6 } from "react";
|
|
1670
|
+
import { useCallback as useCallback4, useEffect as useEffect6, useRef, useState as useState6 } from "react";
|
|
1649
1671
|
function useLoggerEvents(limit = 200) {
|
|
1650
1672
|
const [buffer, setBuffer] = useState6([]);
|
|
1651
1673
|
useEffect6(() => {
|
|
@@ -1674,14 +1696,31 @@ function useSignalEvents(bus, limit = 200) {
|
|
|
1674
1696
|
}, [bus, limit]);
|
|
1675
1697
|
return buffer;
|
|
1676
1698
|
}
|
|
1699
|
+
var DASHBOARD_REFRESH_THROTTLE_MS = 500;
|
|
1677
1700
|
function useDashboardData() {
|
|
1678
1701
|
const [data, setData] = useState6(null);
|
|
1679
1702
|
const [loading, setLoading] = useState6(true);
|
|
1680
1703
|
const [error, setError] = useState6(null);
|
|
1681
1704
|
const [counter, setCounter] = useState6(0);
|
|
1705
|
+
const lastRefreshAt = useRef(0);
|
|
1706
|
+
const pendingRefresh = useRef(null);
|
|
1682
1707
|
const refresh = useCallback4(() => {
|
|
1683
1708
|
setCounter((n) => n + 1);
|
|
1684
1709
|
}, []);
|
|
1710
|
+
const scheduleRefresh = useCallback4(() => {
|
|
1711
|
+
const elapsed = Date.now() - lastRefreshAt.current;
|
|
1712
|
+
if (elapsed >= DASHBOARD_REFRESH_THROTTLE_MS) {
|
|
1713
|
+
lastRefreshAt.current = Date.now();
|
|
1714
|
+
setCounter((n) => n + 1);
|
|
1715
|
+
return;
|
|
1716
|
+
}
|
|
1717
|
+
if (pendingRefresh.current) return;
|
|
1718
|
+
pendingRefresh.current = setTimeout(() => {
|
|
1719
|
+
pendingRefresh.current = null;
|
|
1720
|
+
lastRefreshAt.current = Date.now();
|
|
1721
|
+
setCounter((n) => n + 1);
|
|
1722
|
+
}, DASHBOARD_REFRESH_THROTTLE_MS - elapsed);
|
|
1723
|
+
}, []);
|
|
1685
1724
|
useEffect6(() => {
|
|
1686
1725
|
const cancel = { current: false };
|
|
1687
1726
|
setLoading(true);
|
|
@@ -1701,6 +1740,24 @@ function useDashboardData() {
|
|
|
1701
1740
|
cancel.current = true;
|
|
1702
1741
|
};
|
|
1703
1742
|
}, [counter]);
|
|
1743
|
+
useEffect6(() => {
|
|
1744
|
+
let bus;
|
|
1745
|
+
try {
|
|
1746
|
+
bus = getSharedDeps().signalBus;
|
|
1747
|
+
} catch {
|
|
1748
|
+
return;
|
|
1749
|
+
}
|
|
1750
|
+
const unsubscribe = bus.subscribe(() => {
|
|
1751
|
+
scheduleRefresh();
|
|
1752
|
+
});
|
|
1753
|
+
return () => {
|
|
1754
|
+
unsubscribe();
|
|
1755
|
+
if (pendingRefresh.current) {
|
|
1756
|
+
clearTimeout(pendingRefresh.current);
|
|
1757
|
+
pendingRefresh.current = null;
|
|
1758
|
+
}
|
|
1759
|
+
};
|
|
1760
|
+
}, [scheduleRefresh]);
|
|
1704
1761
|
return { data, loading, error, refresh };
|
|
1705
1762
|
}
|
|
1706
1763
|
|
|
@@ -1790,9 +1847,34 @@ function SprintSummary({ tasks, width = 30 }) {
|
|
|
1790
1847
|
}
|
|
1791
1848
|
|
|
1792
1849
|
// src/integration/ui/tui/components/log-tail.tsx
|
|
1793
|
-
import "react";
|
|
1850
|
+
import { useMemo as useMemo5 } from "react";
|
|
1851
|
+
import { Box as Box15, Text as Text14 } from "ink";
|
|
1852
|
+
|
|
1853
|
+
// src/integration/ui/tui/components/spinner.tsx
|
|
1854
|
+
import { useEffect as useEffect7, useState as useState7 } from "react";
|
|
1794
1855
|
import { Box as Box14, Text as Text13 } from "ink";
|
|
1795
1856
|
import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1857
|
+
function Spinner({ label, color: color2 = inkColors.warning, intervalMs = 80 }) {
|
|
1858
|
+
const [frame, setFrame] = useState7(0);
|
|
1859
|
+
const isAwaitingPrompt = label.startsWith("Awaiting");
|
|
1860
|
+
useEffect7(() => {
|
|
1861
|
+
if (isAwaitingPrompt) return;
|
|
1862
|
+
const id = setInterval(() => {
|
|
1863
|
+
setFrame((f) => (f + 1) % glyphs.spinner.length);
|
|
1864
|
+
}, intervalMs);
|
|
1865
|
+
return () => {
|
|
1866
|
+
clearInterval(id);
|
|
1867
|
+
};
|
|
1868
|
+
}, [intervalMs, isAwaitingPrompt]);
|
|
1869
|
+
if (isAwaitingPrompt) return null;
|
|
1870
|
+
return /* @__PURE__ */ jsxs13(Box14, { children: [
|
|
1871
|
+
/* @__PURE__ */ jsx16(Text13, { color: color2, bold: true, children: glyphs.spinner[frame] }),
|
|
1872
|
+
/* @__PURE__ */ jsx16(Text13, { children: ` ${label}` })
|
|
1873
|
+
] });
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
// src/integration/ui/tui/components/log-tail.tsx
|
|
1877
|
+
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1796
1878
|
function levelColor(level) {
|
|
1797
1879
|
switch (level) {
|
|
1798
1880
|
case "error":
|
|
@@ -1812,43 +1894,46 @@ function levelColor(level) {
|
|
|
1812
1894
|
return void 0;
|
|
1813
1895
|
}
|
|
1814
1896
|
}
|
|
1815
|
-
function renderLine(event, index) {
|
|
1897
|
+
function renderLine(event, index, isActiveSpinner) {
|
|
1816
1898
|
switch (event.kind) {
|
|
1817
1899
|
case "log":
|
|
1818
|
-
return /* @__PURE__ */
|
|
1900
|
+
return /* @__PURE__ */ jsx17(Text14, { color: levelColor(event.level), dimColor: event.level === "dim" || event.level === "debug", children: event.message }, index);
|
|
1819
1901
|
case "header":
|
|
1820
|
-
return /* @__PURE__ */
|
|
1902
|
+
return /* @__PURE__ */ jsxs14(Text14, { bold: true, children: [
|
|
1821
1903
|
event.icon ? `${event.icon} ` : "",
|
|
1822
1904
|
event.title
|
|
1823
1905
|
] }, index);
|
|
1824
1906
|
case "separator":
|
|
1825
|
-
return /* @__PURE__ */
|
|
1907
|
+
return /* @__PURE__ */ jsx17(Text14, { dimColor: true, children: "\u2500".repeat(Math.min(event.width, 40)) }, index);
|
|
1826
1908
|
case "field":
|
|
1827
|
-
return /* @__PURE__ */
|
|
1828
|
-
/* @__PURE__ */
|
|
1909
|
+
return /* @__PURE__ */ jsxs14(Text14, { children: [
|
|
1910
|
+
/* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
1829
1911
|
event.label,
|
|
1830
1912
|
": "
|
|
1831
1913
|
] }),
|
|
1832
1914
|
event.value
|
|
1833
1915
|
] }, index);
|
|
1834
1916
|
case "card":
|
|
1835
|
-
return /* @__PURE__ */
|
|
1917
|
+
return /* @__PURE__ */ jsx17(Text14, { bold: true, children: event.title }, index);
|
|
1836
1918
|
case "newline":
|
|
1837
|
-
return /* @__PURE__ */
|
|
1919
|
+
return /* @__PURE__ */ jsx17(Text14, { children: " " }, index);
|
|
1838
1920
|
case "spinner-start":
|
|
1839
|
-
|
|
1921
|
+
if (isActiveSpinner) {
|
|
1922
|
+
return /* @__PURE__ */ jsx17(Box15, { children: /* @__PURE__ */ jsx17(Spinner, { label: event.message, color: inkColors.info }) }, index);
|
|
1923
|
+
}
|
|
1924
|
+
return /* @__PURE__ */ jsxs14(Text14, { color: inkColors.info, children: [
|
|
1840
1925
|
glyphs.phaseDisabled,
|
|
1841
1926
|
" ",
|
|
1842
1927
|
event.message
|
|
1843
1928
|
] }, index);
|
|
1844
1929
|
case "spinner-succeed":
|
|
1845
|
-
return /* @__PURE__ */
|
|
1930
|
+
return /* @__PURE__ */ jsxs14(Text14, { color: inkColors.success, children: [
|
|
1846
1931
|
glyphs.check,
|
|
1847
1932
|
" ",
|
|
1848
1933
|
event.message
|
|
1849
1934
|
] }, index);
|
|
1850
1935
|
case "spinner-fail":
|
|
1851
|
-
return /* @__PURE__ */
|
|
1936
|
+
return /* @__PURE__ */ jsxs14(Text14, { color: inkColors.error, children: [
|
|
1852
1937
|
glyphs.cross,
|
|
1853
1938
|
" ",
|
|
1854
1939
|
event.message
|
|
@@ -1864,25 +1949,37 @@ function renderLine(event, index) {
|
|
|
1864
1949
|
}
|
|
1865
1950
|
function LogTail({ events, limit = 8 }) {
|
|
1866
1951
|
const tail = events.slice(-limit);
|
|
1867
|
-
|
|
1868
|
-
/* @__PURE__ */
|
|
1869
|
-
|
|
1952
|
+
const resolvedIds = useMemo5(() => {
|
|
1953
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1954
|
+
for (const ev of events) {
|
|
1955
|
+
if (ev.kind === "spinner-succeed" || ev.kind === "spinner-fail" || ev.kind === "spinner-stop") {
|
|
1956
|
+
ids.add(ev.id);
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
return ids;
|
|
1960
|
+
}, [events]);
|
|
1961
|
+
return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", children: [
|
|
1962
|
+
/* @__PURE__ */ jsx17(Text14, { dimColor: true, children: "\u2500\u2500 Log \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
|
|
1963
|
+
tail.length === 0 ? /* @__PURE__ */ jsx17(Text14, { dimColor: true, children: "(no activity yet)" }) : tail.map((event, i) => {
|
|
1964
|
+
const active = event.kind === "spinner-start" && !resolvedIds.has(event.id);
|
|
1965
|
+
return renderLine(event, i, active);
|
|
1966
|
+
})
|
|
1870
1967
|
] });
|
|
1871
1968
|
}
|
|
1872
1969
|
|
|
1873
1970
|
// src/integration/ui/tui/components/rate-limit-banner.tsx
|
|
1874
1971
|
import "react";
|
|
1875
|
-
import { Box as
|
|
1876
|
-
import { jsxs as
|
|
1972
|
+
import { Box as Box16, Text as Text15 } from "ink";
|
|
1973
|
+
import { jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1877
1974
|
function RateLimitBanner({ pausedSince, delayMs }) {
|
|
1878
1975
|
if (!pausedSince) return null;
|
|
1879
1976
|
const seconds = Math.max(0, Math.round(delayMs / 1e3));
|
|
1880
|
-
return /* @__PURE__ */
|
|
1881
|
-
/* @__PURE__ */
|
|
1977
|
+
return /* @__PURE__ */ jsxs15(Box16, { borderStyle: "round", borderColor: inkColors.warning, paddingX: spacing.gutter, children: [
|
|
1978
|
+
/* @__PURE__ */ jsxs15(Text15, { color: inkColors.warning, bold: true, children: [
|
|
1882
1979
|
glyphs.warningGlyph,
|
|
1883
1980
|
" Rate limit hit"
|
|
1884
1981
|
] }),
|
|
1885
|
-
/* @__PURE__ */
|
|
1982
|
+
/* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
|
|
1886
1983
|
" \u2014 new tasks paused",
|
|
1887
1984
|
seconds > 0 ? ` (~${String(seconds)}s)` : "",
|
|
1888
1985
|
". Running tasks continue."
|
|
@@ -1891,7 +1988,7 @@ function RateLimitBanner({ pausedSince, delayMs }) {
|
|
|
1891
1988
|
}
|
|
1892
1989
|
|
|
1893
1990
|
// src/integration/ui/tui/views/execute-view.tsx
|
|
1894
|
-
import { jsx as
|
|
1991
|
+
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1895
1992
|
var EXECUTE_HINTS_RUNNING = [];
|
|
1896
1993
|
var EXECUTE_HINTS_DONE = [{ key: "Enter", action: "home" }];
|
|
1897
1994
|
function initialState() {
|
|
@@ -1901,6 +1998,7 @@ function initialState() {
|
|
|
1901
1998
|
running: /* @__PURE__ */ new Set(),
|
|
1902
1999
|
blocked: /* @__PURE__ */ new Set(),
|
|
1903
2000
|
activity: /* @__PURE__ */ new Map(),
|
|
2001
|
+
currentStep: /* @__PURE__ */ new Map(),
|
|
1904
2002
|
summary: null,
|
|
1905
2003
|
error: null,
|
|
1906
2004
|
rateLimit: null
|
|
@@ -1911,10 +2009,10 @@ function ExecuteView({ sprintId, executionOptions }) {
|
|
|
1911
2009
|
const shared = getSharedDeps();
|
|
1912
2010
|
const signalEvents = useSignalEvents(shared.signalBus);
|
|
1913
2011
|
const logEvents = useLoggerEvents(200);
|
|
1914
|
-
const [state, setState] =
|
|
1915
|
-
const [done, setDone] =
|
|
1916
|
-
const processedCountRef =
|
|
1917
|
-
|
|
2012
|
+
const [state, setState] = useState8(initialState);
|
|
2013
|
+
const [done, setDone] = useState8(false);
|
|
2014
|
+
const processedCountRef = useRef2(0);
|
|
2015
|
+
useEffect8(() => {
|
|
1918
2016
|
const cancel = { current: false };
|
|
1919
2017
|
const load = async () => {
|
|
1920
2018
|
try {
|
|
@@ -1932,7 +2030,7 @@ function ExecuteView({ sprintId, executionOptions }) {
|
|
|
1932
2030
|
cancel.current = true;
|
|
1933
2031
|
};
|
|
1934
2032
|
}, [shared, sprintId]);
|
|
1935
|
-
|
|
2033
|
+
useEffect8(() => {
|
|
1936
2034
|
if (state.sprint === null || done) return;
|
|
1937
2035
|
const cancel = { current: false };
|
|
1938
2036
|
const run = async () => {
|
|
@@ -1957,14 +2055,23 @@ function ExecuteView({ sprintId, executionOptions }) {
|
|
|
1957
2055
|
cancel.current = true;
|
|
1958
2056
|
};
|
|
1959
2057
|
}, [state.sprint, shared, sprintId, executionOptions, done]);
|
|
1960
|
-
|
|
2058
|
+
useEffect8(() => {
|
|
1961
2059
|
if (signalEvents.length <= processedCountRef.current) return;
|
|
1962
2060
|
const fresh = signalEvents.slice(processedCountRef.current);
|
|
1963
2061
|
processedCountRef.current = signalEvents.length;
|
|
1964
2062
|
setState((prev) => reduceEvents(prev, fresh));
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
2063
|
+
if (fresh.some((e) => e.type === "task-finished")) {
|
|
2064
|
+
void (async () => {
|
|
2065
|
+
try {
|
|
2066
|
+
const tasks = await shared.persistence.getTasks(sprintId);
|
|
2067
|
+
setState((s) => ({ ...s, tasks }));
|
|
2068
|
+
} catch {
|
|
2069
|
+
}
|
|
2070
|
+
})();
|
|
2071
|
+
}
|
|
2072
|
+
}, [signalEvents, shared, sprintId]);
|
|
2073
|
+
const [closePromptRun, setClosePromptRun] = useState8(false);
|
|
2074
|
+
useEffect8(() => {
|
|
1968
2075
|
if (!done) return;
|
|
1969
2076
|
void (async () => {
|
|
1970
2077
|
try {
|
|
@@ -1995,19 +2102,19 @@ function ExecuteView({ sprintId, executionOptions }) {
|
|
|
1995
2102
|
}
|
|
1996
2103
|
});
|
|
1997
2104
|
useViewHints(done ? EXECUTE_HINTS_DONE : EXECUTE_HINTS_RUNNING);
|
|
1998
|
-
return /* @__PURE__ */
|
|
1999
|
-
/* @__PURE__ */
|
|
2000
|
-
/* @__PURE__ */
|
|
2001
|
-
/* @__PURE__ */
|
|
2105
|
+
return /* @__PURE__ */ jsxs16(ViewShell, { title: "Execute", children: [
|
|
2106
|
+
/* @__PURE__ */ jsxs16(Box17, { children: [
|
|
2107
|
+
/* @__PURE__ */ jsx18(Text16, { bold: true, color: inkColors.primary, children: state.sprint?.name ?? "Sprint" }),
|
|
2108
|
+
/* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
|
|
2002
2109
|
" ",
|
|
2003
2110
|
state.sprint?.branch ? `[${state.sprint.branch}]` : "",
|
|
2004
2111
|
" ",
|
|
2005
2112
|
state.sprint?.status ? `(${state.sprint.status})` : ""
|
|
2006
2113
|
] })
|
|
2007
2114
|
] }),
|
|
2008
|
-
/* @__PURE__ */
|
|
2009
|
-
state.rateLimit ? /* @__PURE__ */
|
|
2010
|
-
/* @__PURE__ */
|
|
2115
|
+
/* @__PURE__ */ jsx18(Box17, { marginTop: spacing.section, children: /* @__PURE__ */ jsx18(SprintSummary, { tasks: state.tasks }) }),
|
|
2116
|
+
state.rateLimit ? /* @__PURE__ */ jsx18(Box17, { marginTop: spacing.section, children: /* @__PURE__ */ jsx18(RateLimitBanner, { pausedSince: state.rateLimit.pausedSince, delayMs: state.rateLimit.delayMs }) }) : null,
|
|
2117
|
+
/* @__PURE__ */ jsx18(Box17, { marginTop: spacing.section, children: /* @__PURE__ */ jsx18(
|
|
2011
2118
|
TaskGrid,
|
|
2012
2119
|
{
|
|
2013
2120
|
tasks: state.tasks,
|
|
@@ -2016,18 +2123,23 @@ function ExecuteView({ sprintId, executionOptions }) {
|
|
|
2016
2123
|
activityByTask: state.activity
|
|
2017
2124
|
}
|
|
2018
2125
|
) }),
|
|
2019
|
-
/* @__PURE__ */
|
|
2020
|
-
|
|
2126
|
+
!done && state.currentStep.size > 0 ? /* @__PURE__ */ jsx18(Box17, { marginTop: spacing.section, flexDirection: "column", children: Array.from(state.currentStep.entries()).map(([taskId, label]) => {
|
|
2127
|
+
const task = state.tasks.find((t) => t.id === taskId);
|
|
2128
|
+
const taskName = task?.name ?? taskId.slice(0, 8);
|
|
2129
|
+
return /* @__PURE__ */ jsx18(Spinner, { label: `${taskName} ${glyphs.emDash} ${label}` }, taskId);
|
|
2130
|
+
}) }) : null,
|
|
2131
|
+
/* @__PURE__ */ jsx18(Box17, { marginTop: spacing.section, children: /* @__PURE__ */ jsx18(LogTail, { events: logEvents }) }),
|
|
2132
|
+
state.error ? /* @__PURE__ */ jsx18(Box17, { marginTop: spacing.section, children: /* @__PURE__ */ jsxs16(Text16, { color: inkColors.error, children: [
|
|
2021
2133
|
glyphs.cross,
|
|
2022
2134
|
" ",
|
|
2023
2135
|
state.error
|
|
2024
2136
|
] }) }) : null,
|
|
2025
|
-
state.summary && done ? /* @__PURE__ */
|
|
2026
|
-
/* @__PURE__ */
|
|
2137
|
+
state.summary && done ? /* @__PURE__ */ jsxs16(Box17, { marginTop: spacing.section, flexDirection: "column", children: [
|
|
2138
|
+
/* @__PURE__ */ jsxs16(Text16, { color: inkColors.success, bold: true, children: [
|
|
2027
2139
|
glyphs.check,
|
|
2028
2140
|
" Execution finished"
|
|
2029
2141
|
] }),
|
|
2030
|
-
/* @__PURE__ */
|
|
2142
|
+
/* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
|
|
2031
2143
|
state.summary.completed,
|
|
2032
2144
|
" completed ",
|
|
2033
2145
|
glyphs.inlineDot,
|
|
@@ -2043,14 +2155,28 @@ function ExecuteView({ sprintId, executionOptions }) {
|
|
|
2043
2155
|
state.summary.stopReason,
|
|
2044
2156
|
")"
|
|
2045
2157
|
] }),
|
|
2046
|
-
/* @__PURE__ */
|
|
2158
|
+
/* @__PURE__ */ jsx18(Box17, { marginTop: spacing.section, children: /* @__PURE__ */ jsx18(Text16, { dimColor: true, children: "Press any key to return home." }) })
|
|
2047
2159
|
] }) : null
|
|
2048
2160
|
] });
|
|
2049
2161
|
}
|
|
2162
|
+
var STEP_LABELS = {
|
|
2163
|
+
"branch-preflight": "Verifying branch\u2026",
|
|
2164
|
+
"contract-negotiate": "Writing contract\u2026",
|
|
2165
|
+
"mark-in-progress": "Starting\u2026",
|
|
2166
|
+
"execute-task": "Running Claude\u2026",
|
|
2167
|
+
"store-verification": "Storing verification\u2026",
|
|
2168
|
+
"post-task-check": "Running post-task check\u2026",
|
|
2169
|
+
"evaluate-task": "Evaluating\u2026",
|
|
2170
|
+
"mark-done": "Finalizing\u2026"
|
|
2171
|
+
};
|
|
2172
|
+
function labelForStep(stepName) {
|
|
2173
|
+
return STEP_LABELS[stepName] ?? stepName;
|
|
2174
|
+
}
|
|
2050
2175
|
function reduceEvents(state, events) {
|
|
2051
2176
|
const running = new Set(state.running);
|
|
2052
2177
|
const blocked = new Set(state.blocked);
|
|
2053
2178
|
const activity = new Map(state.activity);
|
|
2179
|
+
const currentStep = new Map(state.currentStep);
|
|
2054
2180
|
let rateLimit = state.rateLimit;
|
|
2055
2181
|
for (const event of events) {
|
|
2056
2182
|
switch (event.type) {
|
|
@@ -2059,10 +2185,22 @@ function reduceEvents(state, events) {
|
|
|
2059
2185
|
break;
|
|
2060
2186
|
case "task-finished":
|
|
2061
2187
|
running.delete(event.taskId);
|
|
2188
|
+
activity.delete(event.taskId);
|
|
2189
|
+
currentStep.delete(event.taskId);
|
|
2062
2190
|
if (event.status === "blocked" || event.status === "failed") {
|
|
2063
2191
|
blocked.add(event.taskId);
|
|
2064
2192
|
}
|
|
2065
2193
|
break;
|
|
2194
|
+
case "task-step":
|
|
2195
|
+
if (event.phase === "start") {
|
|
2196
|
+
activity.set(event.taskId, labelForStep(event.stepName));
|
|
2197
|
+
currentStep.set(event.taskId, labelForStep(event.stepName));
|
|
2198
|
+
} else {
|
|
2199
|
+
if (currentStep.get(event.taskId) === labelForStep(event.stepName)) {
|
|
2200
|
+
currentStep.delete(event.taskId);
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
break;
|
|
2066
2204
|
case "rate-limit-paused":
|
|
2067
2205
|
rateLimit = { pausedSince: event.timestamp, delayMs: event.delayMs };
|
|
2068
2206
|
break;
|
|
@@ -2085,36 +2223,13 @@ function reduceEvents(state, events) {
|
|
|
2085
2223
|
}
|
|
2086
2224
|
}
|
|
2087
2225
|
}
|
|
2088
|
-
return { ...state, running, blocked, activity, rateLimit };
|
|
2226
|
+
return { ...state, running, blocked, activity, currentStep, rateLimit };
|
|
2089
2227
|
}
|
|
2090
2228
|
|
|
2091
2229
|
// src/integration/ui/tui/views/dashboard-view.tsx
|
|
2092
2230
|
import { useEffect as useEffect9, useState as useState9 } from "react";
|
|
2093
2231
|
import { Box as Box20, Text as Text19 } from "ink";
|
|
2094
2232
|
|
|
2095
|
-
// src/integration/ui/tui/components/spinner.tsx
|
|
2096
|
-
import { useEffect as useEffect8, useState as useState8 } from "react";
|
|
2097
|
-
import { Box as Box17, Text as Text16 } from "ink";
|
|
2098
|
-
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2099
|
-
function Spinner({ label, color: color2 = inkColors.warning, intervalMs = 80 }) {
|
|
2100
|
-
const [frame, setFrame] = useState8(0);
|
|
2101
|
-
const isAwaitingPrompt = label.startsWith("Awaiting");
|
|
2102
|
-
useEffect8(() => {
|
|
2103
|
-
if (isAwaitingPrompt) return;
|
|
2104
|
-
const id = setInterval(() => {
|
|
2105
|
-
setFrame((f) => (f + 1) % glyphs.spinner.length);
|
|
2106
|
-
}, intervalMs);
|
|
2107
|
-
return () => {
|
|
2108
|
-
clearInterval(id);
|
|
2109
|
-
};
|
|
2110
|
-
}, [intervalMs, isAwaitingPrompt]);
|
|
2111
|
-
if (isAwaitingPrompt) return null;
|
|
2112
|
-
return /* @__PURE__ */ jsxs16(Box17, { children: [
|
|
2113
|
-
/* @__PURE__ */ jsx18(Text16, { color: color2, bold: true, children: glyphs.spinner[frame] }),
|
|
2114
|
-
/* @__PURE__ */ jsx18(Text16, { children: ` ${label}` })
|
|
2115
|
-
] });
|
|
2116
|
-
}
|
|
2117
|
-
|
|
2118
2233
|
// src/integration/ui/tui/components/result-card.tsx
|
|
2119
2234
|
import "react";
|
|
2120
2235
|
import { Box as Box19, Text as Text18 } from "ink";
|
|
@@ -2177,7 +2292,7 @@ async function loadRecentProgress(sprintId, limit) {
|
|
|
2177
2292
|
const headerMatch = /^##\s+(.+)$/m.exec(entry);
|
|
2178
2293
|
const header = headerMatch?.[1]?.trim() ?? "Entry";
|
|
2179
2294
|
const body = entry.replace(/^##\s+.+$/gm, "").replace(/^\*\*Project:\*\*.+$/gm, "").replace(/^###\s+.+$/gm, "").replace(/\s+/g, " ").trim();
|
|
2180
|
-
const preview = body
|
|
2295
|
+
const preview = truncate(body, 200);
|
|
2181
2296
|
return { header, preview };
|
|
2182
2297
|
});
|
|
2183
2298
|
} catch {
|
|
@@ -2383,6 +2498,15 @@ function RefinePhaseView({ sprintId }) {
|
|
|
2383
2498
|
useEffect10(() => {
|
|
2384
2499
|
void loadSprint();
|
|
2385
2500
|
}, [loadSprint]);
|
|
2501
|
+
useEffect10(() => {
|
|
2502
|
+
if (!state.running) return;
|
|
2503
|
+
const handle = setInterval(() => {
|
|
2504
|
+
void loadSprint();
|
|
2505
|
+
}, 1e3);
|
|
2506
|
+
return () => {
|
|
2507
|
+
clearInterval(handle);
|
|
2508
|
+
};
|
|
2509
|
+
}, [state.running, loadSprint]);
|
|
2386
2510
|
const runRefine = useCallback5(async () => {
|
|
2387
2511
|
setState((s) => ({ ...s, running: true, error: null, records: [] }));
|
|
2388
2512
|
try {
|
|
@@ -2597,7 +2721,7 @@ function statusColor2(status) {
|
|
|
2597
2721
|
|
|
2598
2722
|
// src/integration/ui/tui/views/phases/close-phase-view.tsx
|
|
2599
2723
|
import { spawnSync } from "child_process";
|
|
2600
|
-
import { useCallback as useCallback7, useEffect as useEffect12, useMemo as
|
|
2724
|
+
import { useCallback as useCallback7, useEffect as useEffect12, useMemo as useMemo6, useState as useState12 } from "react";
|
|
2601
2725
|
import { Box as Box24, Text as Text23, useInput as useInput8 } from "ink";
|
|
2602
2726
|
import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2603
2727
|
var HINTS_READY = [
|
|
@@ -2631,7 +2755,7 @@ function ClosePhaseView({ sprintId }) {
|
|
|
2631
2755
|
useEffect12(() => {
|
|
2632
2756
|
void load();
|
|
2633
2757
|
}, [load]);
|
|
2634
|
-
const actions =
|
|
2758
|
+
const actions = useMemo6(() => {
|
|
2635
2759
|
const sprint2 = state.sprint;
|
|
2636
2760
|
if (sprint2?.status !== "active") return [];
|
|
2637
2761
|
const base = ["close"];
|
|
@@ -2876,7 +3000,7 @@ ID: ${sprintId}`
|
|
|
2876
3000
|
}
|
|
2877
3001
|
|
|
2878
3002
|
// src/integration/ui/tui/views/workflows/create-sprint-view.tsx
|
|
2879
|
-
import { useMemo as
|
|
3003
|
+
import { useMemo as useMemo7 } from "react";
|
|
2880
3004
|
|
|
2881
3005
|
// src/integration/ui/tui/views/workflows/use-workflow.ts
|
|
2882
3006
|
import { useCallback as useCallback8, useEffect as useEffect13, useState as useState13 } from "react";
|
|
@@ -2970,7 +3094,7 @@ function CreateSprintView() {
|
|
|
2970
3094
|
setPhase({ kind: "done", sprint, project, setAsCurrent });
|
|
2971
3095
|
}
|
|
2972
3096
|
});
|
|
2973
|
-
const hints =
|
|
3097
|
+
const hints = useMemo7(() => phase.kind === "running" ? HINTS_RUNNING : HINTS_DONE, [phase.kind]);
|
|
2974
3098
|
useViewHints(hints);
|
|
2975
3099
|
return /* @__PURE__ */ jsx26(ViewShell, { title: TITLE, children: renderBody(phase) });
|
|
2976
3100
|
}
|
|
@@ -3012,7 +3136,7 @@ function renderBody(phase) {
|
|
|
3012
3136
|
}
|
|
3013
3137
|
|
|
3014
3138
|
// src/integration/ui/tui/views/workflows/delete-sprint-view.tsx
|
|
3015
|
-
import { useMemo as
|
|
3139
|
+
import { useMemo as useMemo8 } from "react";
|
|
3016
3140
|
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
3017
3141
|
var TITLE2 = "Delete Sprint";
|
|
3018
3142
|
var HINTS_RUNNING2 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -3074,7 +3198,7 @@ function DeleteSprintView({ sprintId: initial2 }) {
|
|
|
3074
3198
|
}
|
|
3075
3199
|
});
|
|
3076
3200
|
const running = phase.kind === "running" || phase.kind === "loading";
|
|
3077
|
-
const hints =
|
|
3201
|
+
const hints = useMemo8(() => running ? HINTS_RUNNING2 : HINTS_DONE2, [running]);
|
|
3078
3202
|
useViewHints(hints);
|
|
3079
3203
|
return /* @__PURE__ */ jsx27(ViewShell, { title: TITLE2, children: renderBody2(phase) });
|
|
3080
3204
|
}
|
|
@@ -3121,7 +3245,7 @@ function runningLabel(step) {
|
|
|
3121
3245
|
}
|
|
3122
3246
|
|
|
3123
3247
|
// src/integration/ui/tui/views/workflows/set-current-sprint-view.tsx
|
|
3124
|
-
import { useMemo as
|
|
3248
|
+
import { useMemo as useMemo9 } from "react";
|
|
3125
3249
|
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
3126
3250
|
var TITLE3 = "Set Current Sprint";
|
|
3127
3251
|
var HINTS_RUNNING3 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -3154,7 +3278,7 @@ function SetCurrentSprintView() {
|
|
|
3154
3278
|
}
|
|
3155
3279
|
});
|
|
3156
3280
|
const running = phase.kind === "loading" || phase.kind === "running";
|
|
3157
|
-
const hints =
|
|
3281
|
+
const hints = useMemo9(() => running ? HINTS_RUNNING3 : HINTS_DONE3, [running]);
|
|
3158
3282
|
useViewHints(hints);
|
|
3159
3283
|
return /* @__PURE__ */ jsx28(ViewShell, { title: TITLE3, children: renderBody3(phase) });
|
|
3160
3284
|
}
|
|
@@ -3192,7 +3316,7 @@ function renderBody3(phase) {
|
|
|
3192
3316
|
|
|
3193
3317
|
// src/integration/ui/tui/views/workflows/requirements-export-view.tsx
|
|
3194
3318
|
import { join } from "path";
|
|
3195
|
-
import { useMemo as
|
|
3319
|
+
import { useMemo as useMemo10 } from "react";
|
|
3196
3320
|
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
3197
3321
|
var TITLE4 = "Export Requirements";
|
|
3198
3322
|
var HINTS_RUNNING4 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -3227,7 +3351,7 @@ function RequirementsExportView({ sprintId }) {
|
|
|
3227
3351
|
});
|
|
3228
3352
|
}
|
|
3229
3353
|
});
|
|
3230
|
-
const hints =
|
|
3354
|
+
const hints = useMemo10(() => phase.kind === "running" ? HINTS_RUNNING4 : HINTS_DONE4, [phase.kind]);
|
|
3231
3355
|
useViewHints(hints);
|
|
3232
3356
|
return /* @__PURE__ */ jsx29(ViewShell, { title: TITLE4, children: renderBody4(phase) });
|
|
3233
3357
|
}
|
|
@@ -3274,7 +3398,7 @@ function renderBody4(phase) {
|
|
|
3274
3398
|
// src/integration/ui/tui/views/workflows/context-export-view.tsx
|
|
3275
3399
|
import { writeFile } from "fs/promises";
|
|
3276
3400
|
import { join as join2 } from "path";
|
|
3277
|
-
import { useMemo as
|
|
3401
|
+
import { useMemo as useMemo11 } from "react";
|
|
3278
3402
|
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
3279
3403
|
var TITLE5 = "Export Context";
|
|
3280
3404
|
var HINTS_RUNNING5 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -3304,7 +3428,7 @@ function ContextExportView({ sprintId }) {
|
|
|
3304
3428
|
});
|
|
3305
3429
|
}
|
|
3306
3430
|
});
|
|
3307
|
-
const hints =
|
|
3431
|
+
const hints = useMemo11(() => phase.kind === "running" ? HINTS_RUNNING5 : HINTS_DONE5, [phase.kind]);
|
|
3308
3432
|
useViewHints(hints);
|
|
3309
3433
|
return /* @__PURE__ */ jsx30(ViewShell, { title: TITLE5, children: renderBody5(phase) });
|
|
3310
3434
|
}
|
|
@@ -3404,7 +3528,7 @@ async function renderContextMarkdown(sprint, tasks) {
|
|
|
3404
3528
|
}
|
|
3405
3529
|
|
|
3406
3530
|
// src/integration/ui/tui/views/workflows/ticket-add-view.tsx
|
|
3407
|
-
import { useMemo as
|
|
3531
|
+
import { useMemo as useMemo12 } from "react";
|
|
3408
3532
|
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
3409
3533
|
var TITLE6 = "Add Ticket";
|
|
3410
3534
|
var HINTS_RUNNING6 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -3417,7 +3541,8 @@ var STEP_LABEL = {
|
|
|
3417
3541
|
fetching: "Fetching issue data\u2026",
|
|
3418
3542
|
title: "Awaiting ticket title\u2026",
|
|
3419
3543
|
description: "Awaiting ticket description\u2026",
|
|
3420
|
-
saving: "Saving ticket\u2026"
|
|
3544
|
+
saving: "Saving ticket\u2026",
|
|
3545
|
+
another: "Add another ticket?"
|
|
3421
3546
|
};
|
|
3422
3547
|
function isValidUrl(value) {
|
|
3423
3548
|
try {
|
|
@@ -3452,43 +3577,55 @@ function TicketAddView() {
|
|
|
3452
3577
|
setPhase({ kind: "no-project" });
|
|
3453
3578
|
return;
|
|
3454
3579
|
}
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3580
|
+
let count = 0;
|
|
3581
|
+
while (true) {
|
|
3582
|
+
setPhase({ kind: "running", step: "link" });
|
|
3583
|
+
const link = await prompt.input({
|
|
3584
|
+
message: "Issue link (optional):",
|
|
3585
|
+
validate: (v) => {
|
|
3586
|
+
const trimmed = v.trim();
|
|
3587
|
+
if (trimmed.length === 0) return true;
|
|
3588
|
+
return isValidUrl(trimmed) ? true : "Must be a valid URL (or leave blank)";
|
|
3589
|
+
}
|
|
3590
|
+
});
|
|
3591
|
+
const trimmedLink = link.trim();
|
|
3592
|
+
let prefill = null;
|
|
3593
|
+
if (trimmedLink.length > 0) {
|
|
3594
|
+
setPhase({ kind: "running", step: "fetching" });
|
|
3595
|
+
prefill = tryFetchIssue(trimmedLink);
|
|
3596
|
+
}
|
|
3597
|
+
setPhase({ kind: "running", step: "title" });
|
|
3598
|
+
const title = await prompt.input({
|
|
3599
|
+
message: "Title:",
|
|
3600
|
+
default: prefill?.title,
|
|
3601
|
+
validate: (v) => v.trim().length > 0 ? true : "Title is required"
|
|
3602
|
+
});
|
|
3603
|
+
setPhase({ kind: "running", step: "description" });
|
|
3604
|
+
const description = await prompt.editor({
|
|
3605
|
+
message: "Description (recommended)",
|
|
3606
|
+
default: prefill?.body
|
|
3607
|
+
});
|
|
3608
|
+
setPhase({ kind: "running", step: "saving" });
|
|
3609
|
+
const trimmedDescription = description?.trim() ?? "";
|
|
3610
|
+
const ticket = await addTicket({
|
|
3611
|
+
title: title.trim(),
|
|
3612
|
+
description: trimmedDescription.length > 0 ? trimmedDescription : void 0,
|
|
3613
|
+
link: trimmedLink.length > 0 ? trimmedLink : void 0
|
|
3614
|
+
});
|
|
3615
|
+
count++;
|
|
3616
|
+
setPhase({ kind: "running", step: "another" });
|
|
3617
|
+
const another = await prompt.confirm({
|
|
3618
|
+
message: `Add another ticket? (${String(count)} added)`,
|
|
3619
|
+
default: true
|
|
3620
|
+
});
|
|
3621
|
+
if (!another) {
|
|
3622
|
+
setPhase({ kind: "done", ticket, project, prefilled: prefill !== null, count });
|
|
3623
|
+
return;
|
|
3462
3624
|
}
|
|
3463
|
-
});
|
|
3464
|
-
const trimmedLink = link.trim();
|
|
3465
|
-
let prefill = null;
|
|
3466
|
-
if (trimmedLink.length > 0) {
|
|
3467
|
-
setPhase({ kind: "running", step: "fetching" });
|
|
3468
|
-
prefill = tryFetchIssue(trimmedLink);
|
|
3469
3625
|
}
|
|
3470
|
-
setPhase({ kind: "running", step: "title" });
|
|
3471
|
-
const title = await prompt.input({
|
|
3472
|
-
message: "Title:",
|
|
3473
|
-
default: prefill?.title,
|
|
3474
|
-
validate: (v) => v.trim().length > 0 ? true : "Title is required"
|
|
3475
|
-
});
|
|
3476
|
-
setPhase({ kind: "running", step: "description" });
|
|
3477
|
-
const description = await prompt.editor({
|
|
3478
|
-
message: "Description (recommended)",
|
|
3479
|
-
default: prefill?.body
|
|
3480
|
-
});
|
|
3481
|
-
setPhase({ kind: "running", step: "saving" });
|
|
3482
|
-
const trimmedDescription = description?.trim() ?? "";
|
|
3483
|
-
const ticket = await addTicket({
|
|
3484
|
-
title: title.trim(),
|
|
3485
|
-
description: trimmedDescription.length > 0 ? trimmedDescription : void 0,
|
|
3486
|
-
link: trimmedLink.length > 0 ? trimmedLink : void 0
|
|
3487
|
-
});
|
|
3488
|
-
setPhase({ kind: "done", ticket, project, prefilled: prefill !== null });
|
|
3489
3626
|
}
|
|
3490
3627
|
});
|
|
3491
|
-
const hints =
|
|
3628
|
+
const hints = useMemo12(() => phase.kind === "running" ? HINTS_RUNNING6 : HINTS_DONE6, [phase.kind]);
|
|
3492
3629
|
useViewHints(hints);
|
|
3493
3630
|
return /* @__PURE__ */ jsx31(ViewShell, { title: TITLE6, children: renderBody6(phase) });
|
|
3494
3631
|
}
|
|
@@ -3517,26 +3654,28 @@ function renderBody6(phase) {
|
|
|
3517
3654
|
);
|
|
3518
3655
|
case "error":
|
|
3519
3656
|
return /* @__PURE__ */ jsx31(ResultCard, { kind: "error", title: "Could not add ticket", lines: [phase.message] });
|
|
3520
|
-
case "done":
|
|
3657
|
+
case "done": {
|
|
3658
|
+
const title = phase.count > 1 ? `${String(phase.count)} tickets added` : phase.prefilled ? "Ticket added (prefilled from issue)" : "Ticket added";
|
|
3521
3659
|
return /* @__PURE__ */ jsx31(
|
|
3522
3660
|
ResultCard,
|
|
3523
3661
|
{
|
|
3524
3662
|
kind: "success",
|
|
3525
|
-
title
|
|
3663
|
+
title,
|
|
3526
3664
|
fields: [
|
|
3527
|
-
["ID", phase.ticket.id],
|
|
3528
|
-
["
|
|
3665
|
+
["Last ID", phase.ticket.id],
|
|
3666
|
+
["Last title", phase.ticket.title],
|
|
3529
3667
|
["Project", `${phase.project.displayName} (${phase.project.name})`],
|
|
3530
3668
|
["Status", `requirement: ${phase.ticket.requirementStatus}`]
|
|
3531
3669
|
],
|
|
3532
3670
|
nextSteps: [{ action: "Refine requirements", description: "Home \u2192 Next: Refine Requirements" }]
|
|
3533
3671
|
}
|
|
3534
3672
|
);
|
|
3673
|
+
}
|
|
3535
3674
|
}
|
|
3536
3675
|
}
|
|
3537
3676
|
|
|
3538
3677
|
// src/integration/ui/tui/views/workflows/ticket-edit-view.tsx
|
|
3539
|
-
import { useMemo as
|
|
3678
|
+
import { useMemo as useMemo13 } from "react";
|
|
3540
3679
|
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
3541
3680
|
var TITLE7 = "Edit Ticket";
|
|
3542
3681
|
var HINTS_RUNNING7 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -3611,7 +3750,7 @@ function TicketEditView({ ticketId } = {}) {
|
|
|
3611
3750
|
setPhase({ kind: "done", ticket, field });
|
|
3612
3751
|
}
|
|
3613
3752
|
});
|
|
3614
|
-
const hints =
|
|
3753
|
+
const hints = useMemo13(() => phase.kind === "running" ? HINTS_RUNNING7 : HINTS_DONE7, [phase.kind]);
|
|
3615
3754
|
useViewHints(hints);
|
|
3616
3755
|
return /* @__PURE__ */ jsx32(ViewShell, { title: TITLE7, children: renderBody7(phase) });
|
|
3617
3756
|
}
|
|
@@ -3660,7 +3799,7 @@ function stepLabel(step) {
|
|
|
3660
3799
|
}
|
|
3661
3800
|
|
|
3662
3801
|
// src/integration/ui/tui/views/workflows/ticket-remove-view.tsx
|
|
3663
|
-
import { useMemo as
|
|
3802
|
+
import { useMemo as useMemo14 } from "react";
|
|
3664
3803
|
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
3665
3804
|
var TITLE8 = "Remove Ticket";
|
|
3666
3805
|
var HINTS_RUNNING8 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -3709,7 +3848,7 @@ function TicketRemoveView() {
|
|
|
3709
3848
|
setPhase({ kind: "done", id: target.id, title: target.title });
|
|
3710
3849
|
}
|
|
3711
3850
|
});
|
|
3712
|
-
const hints =
|
|
3851
|
+
const hints = useMemo14(() => phase.kind === "running" ? HINTS_RUNNING8 : HINTS_DONE8, [phase.kind]);
|
|
3713
3852
|
useViewHints(hints);
|
|
3714
3853
|
return /* @__PURE__ */ jsx33(ViewShell, { title: TITLE8, children: renderBody8(phase) });
|
|
3715
3854
|
}
|
|
@@ -3746,7 +3885,7 @@ function stepLabel2(step) {
|
|
|
3746
3885
|
}
|
|
3747
3886
|
|
|
3748
3887
|
// src/integration/ui/tui/views/workflows/ticket-refine-view.tsx
|
|
3749
|
-
import { useMemo as
|
|
3888
|
+
import { useMemo as useMemo15 } from "react";
|
|
3750
3889
|
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
3751
3890
|
var TITLE9 = "Re-Refine Ticket";
|
|
3752
3891
|
var HINTS_RUNNING9 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -3782,7 +3921,7 @@ function TicketRefineView() {
|
|
|
3782
3921
|
setPhase({ kind: "done", ticketTitle: target.title });
|
|
3783
3922
|
}
|
|
3784
3923
|
});
|
|
3785
|
-
const hints =
|
|
3924
|
+
const hints = useMemo15(() => phase.kind === "running" ? HINTS_RUNNING9 : HINTS_DONE9, [phase.kind]);
|
|
3786
3925
|
useViewHints(hints);
|
|
3787
3926
|
return /* @__PURE__ */ jsx34(ViewShell, { title: TITLE9, children: renderBody9(phase) });
|
|
3788
3927
|
}
|
|
@@ -3817,7 +3956,7 @@ function renderBody9(phase) {
|
|
|
3817
3956
|
}
|
|
3818
3957
|
|
|
3819
3958
|
// src/integration/ui/tui/views/workflows/task-add-view.tsx
|
|
3820
|
-
import { useMemo as
|
|
3959
|
+
import { useMemo as useMemo16 } from "react";
|
|
3821
3960
|
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
3822
3961
|
var TITLE10 = "Add Task";
|
|
3823
3962
|
var HINTS_RUNNING10 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -3884,7 +4023,7 @@ function TaskAddView() {
|
|
|
3884
4023
|
setPhase({ kind: "done", task, repo });
|
|
3885
4024
|
}
|
|
3886
4025
|
});
|
|
3887
|
-
const hints =
|
|
4026
|
+
const hints = useMemo16(() => phase.kind === "running" ? HINTS_RUNNING10 : HINTS_DONE10, [phase.kind]);
|
|
3888
4027
|
useViewHints(hints);
|
|
3889
4028
|
return /* @__PURE__ */ jsx35(ViewShell, { title: TITLE10, children: renderBody10(phase) });
|
|
3890
4029
|
}
|
|
@@ -3922,7 +4061,7 @@ function stepLabel3(step) {
|
|
|
3922
4061
|
}
|
|
3923
4062
|
|
|
3924
4063
|
// src/integration/ui/tui/views/workflows/task-import-view.tsx
|
|
3925
|
-
import { useMemo as
|
|
4064
|
+
import { useMemo as useMemo17 } from "react";
|
|
3926
4065
|
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
3927
4066
|
var TITLE11 = "Import Tasks";
|
|
3928
4067
|
var HINTS_RUNNING11 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -3946,7 +4085,7 @@ function TaskImportView() {
|
|
|
3946
4085
|
setPhase({ kind: "done" });
|
|
3947
4086
|
}
|
|
3948
4087
|
});
|
|
3949
|
-
const hints =
|
|
4088
|
+
const hints = useMemo17(() => phase.kind === "running" ? HINTS_RUNNING11 : HINTS_DONE11, [phase.kind]);
|
|
3950
4089
|
useViewHints(hints);
|
|
3951
4090
|
return /* @__PURE__ */ jsx36(ViewShell, { title: TITLE11, children: renderBody11(phase) });
|
|
3952
4091
|
}
|
|
@@ -3964,7 +4103,7 @@ function renderBody11(phase) {
|
|
|
3964
4103
|
}
|
|
3965
4104
|
|
|
3966
4105
|
// src/integration/ui/tui/views/workflows/task-status-view.tsx
|
|
3967
|
-
import { useMemo as
|
|
4106
|
+
import { useMemo as useMemo18 } from "react";
|
|
3968
4107
|
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
3969
4108
|
var TITLE12 = "Task Status";
|
|
3970
4109
|
var HINTS_RUNNING12 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -4011,7 +4150,7 @@ function TaskStatusView() {
|
|
|
4011
4150
|
setPhase({ kind: "done", task });
|
|
4012
4151
|
}
|
|
4013
4152
|
});
|
|
4014
|
-
const hints =
|
|
4153
|
+
const hints = useMemo18(() => phase.kind === "running" ? HINTS_RUNNING12 : HINTS_DONE12, [phase.kind]);
|
|
4015
4154
|
useViewHints(hints);
|
|
4016
4155
|
return /* @__PURE__ */ jsx37(ViewShell, { title: TITLE12, children: renderBody12(phase) });
|
|
4017
4156
|
}
|
|
@@ -4053,7 +4192,7 @@ function stepLabel4(step) {
|
|
|
4053
4192
|
}
|
|
4054
4193
|
|
|
4055
4194
|
// src/integration/ui/tui/views/workflows/task-reorder-view.tsx
|
|
4056
|
-
import { useMemo as
|
|
4195
|
+
import { useMemo as useMemo19 } from "react";
|
|
4057
4196
|
import { jsx as jsx38 } from "react/jsx-runtime";
|
|
4058
4197
|
var TITLE13 = "Reorder Task";
|
|
4059
4198
|
var HINTS_RUNNING13 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -4101,7 +4240,7 @@ function TaskReorderView() {
|
|
|
4101
4240
|
setPhase({ kind: "done", task });
|
|
4102
4241
|
}
|
|
4103
4242
|
});
|
|
4104
|
-
const hints =
|
|
4243
|
+
const hints = useMemo19(() => phase.kind === "running" ? HINTS_RUNNING13 : HINTS_DONE13, [phase.kind]);
|
|
4105
4244
|
useViewHints(hints);
|
|
4106
4245
|
return /* @__PURE__ */ jsx38(ViewShell, { title: TITLE13, children: renderBody13(phase) });
|
|
4107
4246
|
}
|
|
@@ -4136,7 +4275,7 @@ function stepLabel5(step) {
|
|
|
4136
4275
|
}
|
|
4137
4276
|
|
|
4138
4277
|
// src/integration/ui/tui/views/workflows/task-remove-view.tsx
|
|
4139
|
-
import { useMemo as
|
|
4278
|
+
import { useMemo as useMemo20 } from "react";
|
|
4140
4279
|
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
4141
4280
|
var TITLE14 = "Remove Task";
|
|
4142
4281
|
var HINTS_RUNNING14 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -4181,7 +4320,7 @@ function TaskRemoveView() {
|
|
|
4181
4320
|
setPhase({ kind: "done", id: target.id, name: target.name });
|
|
4182
4321
|
}
|
|
4183
4322
|
});
|
|
4184
|
-
const hints =
|
|
4323
|
+
const hints = useMemo20(() => phase.kind === "running" ? HINTS_RUNNING14 : HINTS_DONE14, [phase.kind]);
|
|
4185
4324
|
useViewHints(hints);
|
|
4186
4325
|
return /* @__PURE__ */ jsx39(ViewShell, { title: TITLE14, children: renderBody14(phase) });
|
|
4187
4326
|
}
|
|
@@ -4218,7 +4357,7 @@ function stepLabel6(step) {
|
|
|
4218
4357
|
}
|
|
4219
4358
|
|
|
4220
4359
|
// src/integration/ui/tui/views/workflows/task-next-view.tsx
|
|
4221
|
-
import { useMemo as
|
|
4360
|
+
import { useMemo as useMemo21 } from "react";
|
|
4222
4361
|
import { jsx as jsx40 } from "react/jsx-runtime";
|
|
4223
4362
|
var TITLE15 = "Next Task";
|
|
4224
4363
|
var HINTS_RUNNING15 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -4239,7 +4378,7 @@ function TaskNextView() {
|
|
|
4239
4378
|
setPhase({ kind: "ready", task });
|
|
4240
4379
|
}
|
|
4241
4380
|
});
|
|
4242
|
-
const hints =
|
|
4381
|
+
const hints = useMemo21(() => phase.kind === "running" ? HINTS_RUNNING15 : HINTS_DONE15, [phase.kind]);
|
|
4243
4382
|
useViewHints(hints);
|
|
4244
4383
|
return /* @__PURE__ */ jsx40(ViewShell, { title: TITLE15, children: renderBody15(phase) });
|
|
4245
4384
|
}
|
|
@@ -4271,7 +4410,7 @@ function renderBody15(phase) {
|
|
|
4271
4410
|
|
|
4272
4411
|
// src/integration/ui/tui/views/workflows/project-add-view.tsx
|
|
4273
4412
|
import { resolve } from "path";
|
|
4274
|
-
import { useMemo as
|
|
4413
|
+
import { useMemo as useMemo22 } from "react";
|
|
4275
4414
|
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
4276
4415
|
var TITLE16 = "Add Project";
|
|
4277
4416
|
var HINTS_RUNNING16 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -4318,7 +4457,7 @@ function ProjectAddView() {
|
|
|
4318
4457
|
setPhase({ kind: "done", project });
|
|
4319
4458
|
}
|
|
4320
4459
|
});
|
|
4321
|
-
const hints =
|
|
4460
|
+
const hints = useMemo22(() => phase.kind === "running" ? HINTS_RUNNING16 : HINTS_DONE16, [phase.kind]);
|
|
4322
4461
|
useViewHints(hints);
|
|
4323
4462
|
return /* @__PURE__ */ jsx41(ViewShell, { title: TITLE16, children: renderBody16(phase) });
|
|
4324
4463
|
}
|
|
@@ -4359,7 +4498,7 @@ function stepLabel7(step) {
|
|
|
4359
4498
|
}
|
|
4360
4499
|
|
|
4361
4500
|
// src/integration/ui/tui/views/workflows/project-remove-view.tsx
|
|
4362
|
-
import { useMemo as
|
|
4501
|
+
import { useMemo as useMemo23 } from "react";
|
|
4363
4502
|
import { jsx as jsx42 } from "react/jsx-runtime";
|
|
4364
4503
|
var TITLE17 = "Remove Project";
|
|
4365
4504
|
var HINTS_RUNNING17 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -4401,7 +4540,7 @@ function ProjectRemoveView() {
|
|
|
4401
4540
|
setPhase({ kind: "done", name });
|
|
4402
4541
|
}
|
|
4403
4542
|
});
|
|
4404
|
-
const hints =
|
|
4543
|
+
const hints = useMemo23(() => phase.kind === "running" ? HINTS_RUNNING17 : HINTS_DONE17, [phase.kind]);
|
|
4405
4544
|
useViewHints(hints);
|
|
4406
4545
|
return /* @__PURE__ */ jsx42(ViewShell, { title: TITLE17, children: renderBody17(phase) });
|
|
4407
4546
|
}
|
|
@@ -4427,7 +4566,7 @@ function stepLabel8(step) {
|
|
|
4427
4566
|
|
|
4428
4567
|
// src/integration/ui/tui/views/workflows/project-repo-add-view.tsx
|
|
4429
4568
|
import { resolve as resolve2 } from "path";
|
|
4430
|
-
import { useMemo as
|
|
4569
|
+
import { useMemo as useMemo24 } from "react";
|
|
4431
4570
|
import { jsx as jsx43 } from "react/jsx-runtime";
|
|
4432
4571
|
var TITLE18 = "Add Repository";
|
|
4433
4572
|
var HINTS_RUNNING18 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -4463,7 +4602,7 @@ function ProjectRepoAddView() {
|
|
|
4463
4602
|
setPhase({ kind: "done", project, repoName });
|
|
4464
4603
|
}
|
|
4465
4604
|
});
|
|
4466
|
-
const hints =
|
|
4605
|
+
const hints = useMemo24(() => phase.kind === "running" ? HINTS_RUNNING18 : HINTS_DONE18, [phase.kind]);
|
|
4467
4606
|
useViewHints(hints);
|
|
4468
4607
|
return /* @__PURE__ */ jsx43(ViewShell, { title: TITLE18, children: renderBody18(phase) });
|
|
4469
4608
|
}
|
|
@@ -4497,7 +4636,7 @@ function stepLabel9(step) {
|
|
|
4497
4636
|
}
|
|
4498
4637
|
|
|
4499
4638
|
// src/integration/ui/tui/views/workflows/project-repo-remove-view.tsx
|
|
4500
|
-
import { useMemo as
|
|
4639
|
+
import { useMemo as useMemo25 } from "react";
|
|
4501
4640
|
import { jsx as jsx44 } from "react/jsx-runtime";
|
|
4502
4641
|
var TITLE19 = "Remove Repository";
|
|
4503
4642
|
var HINTS_RUNNING19 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -4546,7 +4685,7 @@ function ProjectRepoRemoveView() {
|
|
|
4546
4685
|
setPhase({ kind: "done", project: updated, repoName });
|
|
4547
4686
|
}
|
|
4548
4687
|
});
|
|
4549
|
-
const hints =
|
|
4688
|
+
const hints = useMemo25(() => phase.kind === "running" ? HINTS_RUNNING19 : HINTS_DONE19, [phase.kind]);
|
|
4550
4689
|
useViewHints(hints);
|
|
4551
4690
|
return /* @__PURE__ */ jsx44(ViewShell, { title: TITLE19, children: renderBody19(phase) });
|
|
4552
4691
|
}
|
|
@@ -4585,7 +4724,7 @@ function stepLabel10(step) {
|
|
|
4585
4724
|
}
|
|
4586
4725
|
|
|
4587
4726
|
// src/integration/ui/tui/views/workflows/project-edit-view.tsx
|
|
4588
|
-
import { useMemo as
|
|
4727
|
+
import { useMemo as useMemo26 } from "react";
|
|
4589
4728
|
import { jsx as jsx45 } from "react/jsx-runtime";
|
|
4590
4729
|
var TITLE20 = "Edit Project";
|
|
4591
4730
|
var HINTS_RUNNING20 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -4631,7 +4770,7 @@ function ProjectEditView() {
|
|
|
4631
4770
|
setPhase({ kind: "done", project });
|
|
4632
4771
|
}
|
|
4633
4772
|
});
|
|
4634
|
-
const hints =
|
|
4773
|
+
const hints = useMemo26(() => phase.kind === "running" ? HINTS_RUNNING20 : HINTS_DONE20, [phase.kind]);
|
|
4635
4774
|
useViewHints(hints);
|
|
4636
4775
|
return /* @__PURE__ */ jsx45(ViewShell, { title: TITLE20, children: renderBody20(phase) });
|
|
4637
4776
|
}
|
|
@@ -4666,11 +4805,11 @@ function stepLabel11(step) {
|
|
|
4666
4805
|
}
|
|
4667
4806
|
|
|
4668
4807
|
// src/integration/ui/tui/views/browse/sprint-list-view.tsx
|
|
4669
|
-
import { useEffect as useEffect14, useMemo as
|
|
4808
|
+
import { useEffect as useEffect14, useMemo as useMemo28, useState as useState15 } from "react";
|
|
4670
4809
|
import { useInput as useInput11 } from "ink";
|
|
4671
4810
|
|
|
4672
4811
|
// src/integration/ui/tui/components/list-view.tsx
|
|
4673
|
-
import React47, { useMemo as
|
|
4812
|
+
import React47, { useMemo as useMemo27, useState as useState14 } from "react";
|
|
4674
4813
|
import { Box as Box25, Text as Text24, useInput as useInput10 } from "ink";
|
|
4675
4814
|
import { jsx as jsx46, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
4676
4815
|
var DEFAULT_PAGE_SIZE = 12;
|
|
@@ -4704,7 +4843,7 @@ function ListView({
|
|
|
4704
4843
|
disabled = false
|
|
4705
4844
|
}) {
|
|
4706
4845
|
const [cursor, setCursor] = useState14(() => Math.max(0, Math.min(initialCursor, rows.length - 1)));
|
|
4707
|
-
const widths =
|
|
4846
|
+
const widths = useMemo27(() => computeWidths(columns, rows, 72), [columns, rows]);
|
|
4708
4847
|
useInput10(
|
|
4709
4848
|
(_input, key) => {
|
|
4710
4849
|
if (rows.length === 0) return;
|
|
@@ -4917,7 +5056,7 @@ function SprintListView() {
|
|
|
4917
5056
|
}
|
|
4918
5057
|
});
|
|
4919
5058
|
const title = filter === "all" ? TITLE_BASE : `${TITLE_BASE} \xB7 filter: ${filter}`;
|
|
4920
|
-
const filtered =
|
|
5059
|
+
const filtered = useMemo28(() => {
|
|
4921
5060
|
if (state.kind !== "ready") return [];
|
|
4922
5061
|
if (filter === "all") return state.sprints;
|
|
4923
5062
|
return state.sprints.filter((s) => s.status === filter);
|
|
@@ -4936,7 +5075,7 @@ function SprintListView() {
|
|
|
4936
5075
|
}
|
|
4937
5076
|
|
|
4938
5077
|
// src/integration/ui/tui/views/browse/sprint-show-view.tsx
|
|
4939
|
-
import { useEffect as useEffect15, useMemo as
|
|
5078
|
+
import { useEffect as useEffect15, useMemo as useMemo29, useState as useState16 } from "react";
|
|
4940
5079
|
import { Box as Box26, Text as Text26, useInput as useInput12 } from "ink";
|
|
4941
5080
|
import { jsx as jsx48, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
4942
5081
|
var TITLE21 = "Sprint Details";
|
|
@@ -4964,11 +5103,11 @@ function SprintShowView({ sprintId }) {
|
|
|
4964
5103
|
ctl.cancelled = true;
|
|
4965
5104
|
};
|
|
4966
5105
|
}, [sprintId]);
|
|
4967
|
-
const rows =
|
|
5106
|
+
const rows = useMemo29(() => {
|
|
4968
5107
|
if (state.kind !== "ready") return [];
|
|
4969
5108
|
return buildRows2(state.sprint, state.tasks);
|
|
4970
5109
|
}, [state]);
|
|
4971
|
-
const sections =
|
|
5110
|
+
const sections = useMemo29(() => rows.filter((r) => r.separator !== true), [rows]);
|
|
4972
5111
|
const [cursor, setCursor] = useState16(0);
|
|
4973
5112
|
useInput12(
|
|
4974
5113
|
(_input, key) => {
|
|
@@ -5265,7 +5404,7 @@ function renderBody22(state) {
|
|
|
5265
5404
|
}
|
|
5266
5405
|
|
|
5267
5406
|
// src/integration/ui/tui/views/browse/task-list-view.tsx
|
|
5268
|
-
import { useEffect as useEffect18, useMemo as
|
|
5407
|
+
import { useEffect as useEffect18, useMemo as useMemo30, useState as useState19 } from "react";
|
|
5269
5408
|
import { useInput as useInput15 } from "ink";
|
|
5270
5409
|
import { jsx as jsx51 } from "react/jsx-runtime";
|
|
5271
5410
|
var FILTER_CYCLE2 = ["all", "todo", "active", "done"];
|
|
@@ -5390,7 +5529,7 @@ function TaskListView({ sprintId }) {
|
|
|
5390
5529
|
router.push({ id: "task-remove" });
|
|
5391
5530
|
}
|
|
5392
5531
|
});
|
|
5393
|
-
const filtered =
|
|
5532
|
+
const filtered = useMemo30(() => {
|
|
5394
5533
|
if (state.kind !== "ready") return [];
|
|
5395
5534
|
if (filter === "all") return state.tasks;
|
|
5396
5535
|
return state.tasks.filter((t) => matches(t, filter));
|
|
@@ -5756,7 +5895,7 @@ function renderContent(content) {
|
|
|
5756
5895
|
}
|
|
5757
5896
|
|
|
5758
5897
|
// src/integration/ui/tui/views/workflows/progress-log-view.tsx
|
|
5759
|
-
import { useMemo as
|
|
5898
|
+
import { useMemo as useMemo31 } from "react";
|
|
5760
5899
|
import { jsx as jsx57 } from "react/jsx-runtime";
|
|
5761
5900
|
var TITLE29 = "Log Progress";
|
|
5762
5901
|
var HINTS_RUNNING21 = [
|
|
@@ -5786,7 +5925,7 @@ function ProgressLogView() {
|
|
|
5786
5925
|
setPhase({ kind: "done" });
|
|
5787
5926
|
}
|
|
5788
5927
|
});
|
|
5789
|
-
const hints =
|
|
5928
|
+
const hints = useMemo31(() => phase.kind === "running" ? HINTS_RUNNING21 : HINTS_DONE21, [phase.kind]);
|
|
5790
5929
|
useViewHints(hints);
|
|
5791
5930
|
return /* @__PURE__ */ jsx57(ViewShell, { title: TITLE29, children: renderBody25(phase) });
|
|
5792
5931
|
}
|
|
@@ -5804,7 +5943,7 @@ function renderBody25(phase) {
|
|
|
5804
5943
|
}
|
|
5805
5944
|
|
|
5806
5945
|
// src/integration/ui/tui/views/workflows/ideate-view.tsx
|
|
5807
|
-
import { useMemo as
|
|
5946
|
+
import { useMemo as useMemo32 } from "react";
|
|
5808
5947
|
import { jsx as jsx58 } from "react/jsx-runtime";
|
|
5809
5948
|
var TITLE30 = "Ideate";
|
|
5810
5949
|
var HINTS_RUNNING22 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -5862,7 +6001,7 @@ function IdeateView() {
|
|
|
5862
6001
|
setPhase({ kind: "done", summary });
|
|
5863
6002
|
}
|
|
5864
6003
|
});
|
|
5865
|
-
const hints =
|
|
6004
|
+
const hints = useMemo32(() => phase.kind === "running" ? HINTS_RUNNING22 : HINTS_DONE22, [phase.kind]);
|
|
5866
6005
|
useViewHints(hints);
|
|
5867
6006
|
return /* @__PURE__ */ jsx58(ViewShell, { title: TITLE30, children: renderBody26(phase) });
|
|
5868
6007
|
}
|
|
@@ -5899,7 +6038,7 @@ function stepLabel12(step) {
|
|
|
5899
6038
|
}
|
|
5900
6039
|
|
|
5901
6040
|
// src/integration/ui/tui/views/onboarding-view.tsx
|
|
5902
|
-
import { useMemo as
|
|
6041
|
+
import { useMemo as useMemo33 } from "react";
|
|
5903
6042
|
import { jsx as jsx59 } from "react/jsx-runtime";
|
|
5904
6043
|
var TITLE31 = "Welcome";
|
|
5905
6044
|
var HINTS_RUNNING23 = [{ key: "Esc", action: "skip" }];
|
|
@@ -5950,7 +6089,7 @@ function OnboardingView() {
|
|
|
5950
6089
|
}
|
|
5951
6090
|
}
|
|
5952
6091
|
});
|
|
5953
|
-
const hints =
|
|
6092
|
+
const hints = useMemo33(() => phase.kind === "running" ? HINTS_RUNNING23 : HINTS_DONE23, [phase.kind]);
|
|
5954
6093
|
useViewHints(hints);
|
|
5955
6094
|
return /* @__PURE__ */ jsx59(ViewShell, { title: TITLE31, children: renderBody27(phase) });
|
|
5956
6095
|
}
|
|
@@ -5970,7 +6109,7 @@ function renderBody27(phase) {
|
|
|
5970
6109
|
}
|
|
5971
6110
|
|
|
5972
6111
|
// src/integration/ui/tui/views/workflows/reactivate-sprint-view.tsx
|
|
5973
|
-
import { useMemo as
|
|
6112
|
+
import { useMemo as useMemo34 } from "react";
|
|
5974
6113
|
import { jsx as jsx60 } from "react/jsx-runtime";
|
|
5975
6114
|
var TITLE32 = "Reactivate Sprint";
|
|
5976
6115
|
var HINTS_RUNNING24 = [{ key: "Esc", action: "cancel" }];
|
|
@@ -6008,7 +6147,7 @@ function ReactivateSprintView({ sprintId }) {
|
|
|
6008
6147
|
}
|
|
6009
6148
|
});
|
|
6010
6149
|
const running = phase.kind === "running" || phase.kind === "loading";
|
|
6011
|
-
const hints =
|
|
6150
|
+
const hints = useMemo34(() => running ? HINTS_RUNNING24 : HINTS_DONE24, [running]);
|
|
6012
6151
|
useViewHints(hints);
|
|
6013
6152
|
return /* @__PURE__ */ jsx60(ViewShell, { title: TITLE32, children: renderBody28(phase) });
|
|
6014
6153
|
}
|
|
@@ -6522,7 +6661,7 @@ function ViewRouter({ initialStack }) {
|
|
|
6522
6661
|
}
|
|
6523
6662
|
return collapseAdjacentDuplicates(initialStack);
|
|
6524
6663
|
});
|
|
6525
|
-
const stackRef =
|
|
6664
|
+
const stackRef = useRef3(stack);
|
|
6526
6665
|
stackRef.current = stack;
|
|
6527
6666
|
const push = useCallback10((entry) => {
|
|
6528
6667
|
setStack((s) => {
|
|
@@ -6546,7 +6685,7 @@ function ViewRouter({ initialStack }) {
|
|
|
6546
6685
|
if (current === void 0) {
|
|
6547
6686
|
throw new Error("ViewRouter stack is empty");
|
|
6548
6687
|
}
|
|
6549
|
-
const api =
|
|
6688
|
+
const api = useMemo35(
|
|
6550
6689
|
() => ({ current, stack, push, pop, replace, reset }),
|
|
6551
6690
|
[current, stack, push, pop, replace, reset]
|
|
6552
6691
|
);
|