@arvorco/relentless 0.1.16 → 0.1.18
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/package.json +1 -1
- package/src/tui/App.tsx +4 -3
- package/src/tui/TUIRunner.tsx +17 -1
- package/src/tui/components/AgentOutput.tsx +8 -8
- package/src/tui/components/AgentStatus.tsx +1 -2
- package/src/tui/components/CurrentStory.tsx +2 -2
- package/src/tui/components/Header.tsx +1 -2
- package/src/tui/components/StoryGrid.tsx +45 -8
- package/src/tui/types.ts +4 -0
package/package.json
CHANGED
package/src/tui/App.tsx
CHANGED
|
@@ -29,12 +29,12 @@ export function App({ state }: AppProps): React.ReactElement {
|
|
|
29
29
|
<Header agent={state.currentAgent} />
|
|
30
30
|
|
|
31
31
|
{/* Feature info and progress */}
|
|
32
|
-
<Box flexDirection="column" paddingX={1} paddingY={
|
|
32
|
+
<Box flexDirection="column" paddingX={1} paddingY={0}>
|
|
33
33
|
<Box>
|
|
34
34
|
<Text color={colors.dim}>Feature: </Text>
|
|
35
35
|
<Text bold>{state.feature}</Text>
|
|
36
36
|
</Box>
|
|
37
|
-
<Box
|
|
37
|
+
<Box>
|
|
38
38
|
<Text color={colors.dim}>Progress: </Text>
|
|
39
39
|
<ProgressBar completed={completedCount} total={totalCount} />
|
|
40
40
|
</Box>
|
|
@@ -50,12 +50,13 @@ export function App({ state }: AppProps): React.ReactElement {
|
|
|
50
50
|
</Box>
|
|
51
51
|
|
|
52
52
|
{/* Agent output */}
|
|
53
|
-
<AgentOutput lines={state.outputLines} />
|
|
53
|
+
<AgentOutput lines={state.outputLines} maxLines={8} />
|
|
54
54
|
|
|
55
55
|
{/* Story grid */}
|
|
56
56
|
<StoryGrid
|
|
57
57
|
stories={state.stories}
|
|
58
58
|
currentStoryId={state.currentStory?.id}
|
|
59
|
+
maxRows={8}
|
|
59
60
|
/>
|
|
60
61
|
|
|
61
62
|
{/* Agent status footer */}
|
package/src/tui/TUIRunner.tsx
CHANGED
|
@@ -113,6 +113,10 @@ function TUIRunnerComponent({
|
|
|
113
113
|
id: s.id,
|
|
114
114
|
title: s.title,
|
|
115
115
|
passes: s.passes,
|
|
116
|
+
priority: s.priority,
|
|
117
|
+
criteriaCount: s.acceptanceCriteria.length,
|
|
118
|
+
research: s.research,
|
|
119
|
+
phase: s.phase,
|
|
116
120
|
})),
|
|
117
121
|
agents: agentStates,
|
|
118
122
|
}));
|
|
@@ -153,7 +157,15 @@ function TUIRunnerComponent({
|
|
|
153
157
|
// Update current story
|
|
154
158
|
setState((prev) => ({
|
|
155
159
|
...prev,
|
|
156
|
-
currentStory: {
|
|
160
|
+
currentStory: {
|
|
161
|
+
id: story.id,
|
|
162
|
+
title: story.title,
|
|
163
|
+
passes: story.passes,
|
|
164
|
+
priority: story.priority,
|
|
165
|
+
criteriaCount: story.acceptanceCriteria.length,
|
|
166
|
+
research: story.research,
|
|
167
|
+
phase: story.phase,
|
|
168
|
+
},
|
|
157
169
|
elapsedSeconds: 0,
|
|
158
170
|
}));
|
|
159
171
|
|
|
@@ -334,6 +346,10 @@ function TUIRunnerComponent({
|
|
|
334
346
|
id: s.id,
|
|
335
347
|
title: s.title,
|
|
336
348
|
passes: s.passes,
|
|
349
|
+
priority: s.priority,
|
|
350
|
+
criteriaCount: s.acceptanceCriteria.length,
|
|
351
|
+
research: s.research,
|
|
352
|
+
phase: s.phase,
|
|
337
353
|
})),
|
|
338
354
|
}));
|
|
339
355
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import React from "react";
|
|
8
8
|
import { Box, Text } from "ink";
|
|
9
|
-
import { colors
|
|
9
|
+
import { colors } from "../theme.js";
|
|
10
10
|
|
|
11
11
|
interface AgentOutputProps {
|
|
12
12
|
lines: string[];
|
|
@@ -17,19 +17,19 @@ export function AgentOutput({
|
|
|
17
17
|
lines,
|
|
18
18
|
maxLines = 8,
|
|
19
19
|
}: AgentOutputProps): React.ReactElement {
|
|
20
|
-
|
|
21
|
-
const displayLines = lines.slice(-
|
|
20
|
+
const clampedMaxLines = Math.max(0, maxLines);
|
|
21
|
+
const displayLines = clampedMaxLines > 0 ? lines.slice(-clampedMaxLines) : [];
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
|
-
<Box flexDirection="column"
|
|
25
|
-
<Box paddingX={1}
|
|
24
|
+
<Box flexDirection="column" paddingY={1}>
|
|
25
|
+
<Box paddingX={1}>
|
|
26
26
|
<Text color={colors.dim} bold>
|
|
27
|
-
Agent Output
|
|
27
|
+
── Agent Output ──
|
|
28
28
|
</Text>
|
|
29
29
|
</Box>
|
|
30
|
-
<Box flexDirection="column" paddingX={1}
|
|
30
|
+
<Box flexDirection="column" paddingX={1}>
|
|
31
31
|
{displayLines.length > 0 ? (
|
|
32
|
-
displayLines.map((line, i) => (
|
|
32
|
+
displayLines.slice(0, clampedMaxLines).map((line, i) => (
|
|
33
33
|
<Text key={i} color={colors.dim} wrap="truncate">
|
|
34
34
|
{line}
|
|
35
35
|
</Text>
|
|
@@ -32,14 +32,14 @@ export function CurrentStory({
|
|
|
32
32
|
}: CurrentStoryProps): React.ReactElement {
|
|
33
33
|
if (!story) {
|
|
34
34
|
return (
|
|
35
|
-
<Box
|
|
35
|
+
<Box>
|
|
36
36
|
<Text color={colors.dim}>No story in progress</Text>
|
|
37
37
|
</Box>
|
|
38
38
|
);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
return (
|
|
42
|
-
<Box flexDirection="column"
|
|
42
|
+
<Box flexDirection="column">
|
|
43
43
|
<Box>
|
|
44
44
|
<Text color={colors.dim}>Current Story: </Text>
|
|
45
45
|
<Text color={colors.warning} bold>
|
|
@@ -16,9 +16,8 @@ interface HeaderProps {
|
|
|
16
16
|
export function Header({ agent }: HeaderProps): React.ReactElement {
|
|
17
17
|
return (
|
|
18
18
|
<Box
|
|
19
|
-
borderStyle="single"
|
|
20
|
-
borderColor={colors.primary}
|
|
21
19
|
paddingX={1}
|
|
20
|
+
paddingY={1}
|
|
22
21
|
flexDirection="row"
|
|
23
22
|
justifyContent="space-between"
|
|
24
23
|
>
|
|
@@ -13,12 +13,14 @@ interface StoryGridProps {
|
|
|
13
13
|
stories: Story[];
|
|
14
14
|
currentStoryId?: string;
|
|
15
15
|
columns?: number;
|
|
16
|
+
maxRows?: number;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export function StoryGrid({
|
|
19
20
|
stories,
|
|
20
21
|
currentStoryId,
|
|
21
22
|
columns = 2,
|
|
23
|
+
maxRows,
|
|
22
24
|
}: StoryGridProps): React.ReactElement {
|
|
23
25
|
// Split stories into columns
|
|
24
26
|
const rows: Story[][] = [];
|
|
@@ -35,15 +37,18 @@ export function StoryGrid({
|
|
|
35
37
|
rows.push(row);
|
|
36
38
|
}
|
|
37
39
|
|
|
40
|
+
// Constrain to maxRows
|
|
41
|
+
const visibleRows = maxRows ? rows.slice(0, maxRows) : rows;
|
|
42
|
+
|
|
38
43
|
return (
|
|
39
|
-
<Box flexDirection="column"
|
|
40
|
-
<Box paddingX={1}
|
|
44
|
+
<Box flexDirection="column" paddingY={1}>
|
|
45
|
+
<Box paddingX={1}>
|
|
41
46
|
<Text color={colors.dim} bold>
|
|
42
|
-
Stories
|
|
47
|
+
── Stories ({stories.length}) ──
|
|
43
48
|
</Text>
|
|
44
49
|
</Box>
|
|
45
|
-
<Box flexDirection="column" paddingX={1}
|
|
46
|
-
{
|
|
50
|
+
<Box flexDirection="column" paddingX={1}>
|
|
51
|
+
{visibleRows.map((row, rowIdx) => (
|
|
47
52
|
<Box key={rowIdx} flexDirection="row">
|
|
48
53
|
{row.map((story, colIdx) => {
|
|
49
54
|
const isCurrent = story.id === currentStoryId;
|
|
@@ -58,23 +63,55 @@ export function StoryGrid({
|
|
|
58
63
|
? colors.success
|
|
59
64
|
: colors.dim;
|
|
60
65
|
|
|
66
|
+
const priorityColor =
|
|
67
|
+
story.priority <= 2 ? colors.error : story.priority <= 5 ? colors.warning : colors.dim;
|
|
68
|
+
|
|
61
69
|
return (
|
|
62
70
|
<Box key={colIdx} width="50%">
|
|
71
|
+
{/* Status symbol */}
|
|
63
72
|
<Text color={symbolColor}>{symbol} </Text>
|
|
73
|
+
|
|
74
|
+
{/* Story ID */}
|
|
64
75
|
<Text
|
|
65
76
|
color={story.passes ? colors.success : isCurrent ? colors.warning : undefined}
|
|
66
77
|
dimColor={story.passes}
|
|
67
78
|
>
|
|
68
|
-
{story.id.padEnd(
|
|
79
|
+
{story.id.padEnd(9)}
|
|
80
|
+
</Text>
|
|
81
|
+
|
|
82
|
+
{/* Priority badge */}
|
|
83
|
+
<Text color={priorityColor} bold={story.priority <= 3}>
|
|
84
|
+
P{story.priority}{" "}
|
|
69
85
|
</Text>
|
|
86
|
+
|
|
87
|
+
{/* Title (longer) */}
|
|
70
88
|
<Text
|
|
71
|
-
color={colors.dim}
|
|
89
|
+
color={story.passes ? colors.dim : undefined}
|
|
72
90
|
dimColor={story.passes}
|
|
73
91
|
strikethrough={story.passes}
|
|
74
92
|
wrap="truncate"
|
|
75
93
|
>
|
|
76
|
-
{story.title.substring(0,
|
|
94
|
+
{story.title.substring(0, 40)}
|
|
95
|
+
</Text>
|
|
96
|
+
|
|
97
|
+
{/* Acceptance criteria count */}
|
|
98
|
+
<Text color={colors.dim} dimColor>
|
|
99
|
+
{" "}
|
|
100
|
+
({story.criteriaCount}c)
|
|
77
101
|
</Text>
|
|
102
|
+
|
|
103
|
+
{/* Research indicator */}
|
|
104
|
+
{story.research && (
|
|
105
|
+
<Text color={colors.dim}> 🔍</Text>
|
|
106
|
+
)}
|
|
107
|
+
|
|
108
|
+
{/* Phase badge */}
|
|
109
|
+
{story.phase && (
|
|
110
|
+
<Text color={colors.dim} dimColor>
|
|
111
|
+
{" "}
|
|
112
|
+
[{story.phase}]
|
|
113
|
+
</Text>
|
|
114
|
+
)}
|
|
78
115
|
</Box>
|
|
79
116
|
);
|
|
80
117
|
})}
|