beads-kanban-ui 0.1.0 → 0.1.1
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/README.md +16 -222
- package/package.json +18 -55
- package/.designs/beads-kanban-ui-bj0.md +0 -73
- package/.designs/beads-kanban-ui-qxq.md +0 -144
- package/.designs/epic-support.md +0 -282
- package/.env.local.example +0 -2
- package/.eslintrc.json +0 -3
- package/.gitattributes +0 -3
- package/.github/workflows/release.yml +0 -123
- package/.history/README_20260121193710.md +0 -227
- package/.history/README_20260121193918.md +0 -227
- package/.history/README_20260121193921.md +0 -227
- package/.history/README_20260121193933.md +0 -227
- package/.history/README_20260121193934.md +0 -227
- package/.history/README_20260121193944.md +0 -227
- package/.history/README_20260121193953.md +0 -227
- package/.history/src/app/page_20260121133429.tsx +0 -134
- package/.history/src/app/page_20260121133928.tsx +0 -134
- package/.history/src/app/page_20260121144850.tsx +0 -138
- package/.history/src/app/page_20260121144854.tsx +0 -138
- package/.history/src/app/page_20260121144858.tsx +0 -138
- package/.history/src/app/page_20260121144902.tsx +0 -138
- package/.history/src/app/page_20260121144906.tsx +0 -138
- package/.history/src/app/page_20260121144911.tsx +0 -138
- package/.history/src/app/page_20260121144928.tsx +0 -138
- package/.playwright-mcp/.playwright-mcp/morphing-dialog-wheel-scroll-fix.png +0 -0
- package/.playwright-mcp/beams-test.png +0 -0
- package/.playwright-mcp/card-verification.png +0 -0
- package/.playwright-mcp/design-doc-dialog-fix-verification.png +0 -0
- package/.playwright-mcp/dialog-width-test.png +0 -0
- package/.playwright-mcp/homepage.png +0 -0
- package/.playwright-mcp/morphing-dialog-expanded.png +0 -0
- package/.playwright-mcp/morphing-dialog-fixes-final.png +0 -0
- package/.playwright-mcp/morphing-dialog-open.png +0 -0
- package/.playwright-mcp/page-2026-01-21T14-08-31-529Z.png +0 -0
- package/.playwright-mcp/page-2026-01-21T14-09-23-431Z.png +0 -0
- package/.playwright-mcp/page-2026-01-21T14-10-28-773Z.png +0 -0
- package/.playwright-mcp/page-2026-01-21T14-10-47-432Z.png +0 -0
- package/.playwright-mcp/page-2026-01-21T14-11-12-350Z.png +0 -0
- package/.playwright-mcp/screenshot-after-click.png +0 -0
- package/.playwright-mcp/screenshot-after-dialog-click.png +0 -0
- package/.playwright-mcp/sheet-restored-after-dialog-close.png +0 -0
- package/.playwright-mcp/test-1-sheet-open-with-overlay.png +0 -0
- package/.playwright-mcp/test-2-morphing-dialog-with-overlay.png +0 -0
- package/.playwright-mcp/test-3-sheet-open-dark-overlay.png +0 -0
- package/.playwright-mcp/test-4-morphing-dialog-with-dark-overlay.png +0 -0
- package/.playwright-mcp/test-5-morphing-dialog-scrolled.png +0 -0
- package/.playwright-mcp/test-6-sheet-restored-after-dialog-close.png +0 -0
- package/.playwright-mcp/wheel-scroll-fixed.png +0 -0
- package/Screenshots/bead-detail.png +0 -0
- package/Screenshots/dashboard.png +0 -0
- package/Screenshots/kanban-board.png +0 -0
- package/components.json +0 -27
- package/logo/logo.svg +0 -1
- package/next.config.js +0 -9
- package/npm/README.md +0 -37
- package/npm/package.json +0 -20
- package/postcss.config.js +0 -6
- package/public/logo.svg +0 -1
- package/restart.sh +0 -5
- package/server/Cargo.lock +0 -1685
- package/server/Cargo.toml +0 -24
- package/server/src/db.rs +0 -570
- package/server/src/main.rs +0 -141
- package/server/src/routes/beads.rs +0 -413
- package/server/src/routes/cli.rs +0 -150
- package/server/src/routes/fs.rs +0 -360
- package/server/src/routes/git.rs +0 -169
- package/server/src/routes/mod.rs +0 -107
- package/server/src/routes/projects.rs +0 -177
- package/server/src/routes/watch.rs +0 -211
- package/src/app/globals.css +0 -101
- package/src/app/layout.tsx +0 -36
- package/src/app/page.tsx +0 -348
- package/src/app/project/kanban-board.tsx +0 -356
- package/src/app/project/page.tsx +0 -18
- package/src/app/settings/page.tsx +0 -224
- package/src/components/Beams.css +0 -5
- package/src/components/Beams.jsx +0 -307
- package/src/components/Galaxy.css +0 -5
- package/src/components/Galaxy.jsx +0 -333
- package/src/components/activity-timeline.tsx +0 -172
- package/src/components/add-project-dialog.tsx +0 -219
- package/src/components/bead-card.tsx +0 -196
- package/src/components/bead-detail.tsx +0 -306
- package/src/components/color-picker.tsx +0 -101
- package/src/components/comment-input.tsx +0 -155
- package/src/components/comment-list.tsx +0 -147
- package/src/components/dependency-badge.tsx +0 -106
- package/src/components/design-doc-dialog.tsx +0 -58
- package/src/components/design-doc-preview.tsx +0 -97
- package/src/components/design-doc-viewer.tsx +0 -199
- package/src/components/editable-project-name.tsx +0 -178
- package/src/components/epic-card.tsx +0 -263
- package/src/components/folder-browser.tsx +0 -273
- package/src/components/footer.tsx +0 -27
- package/src/components/kanban/default.tsx +0 -184
- package/src/components/kanban-column.tsx +0 -167
- package/src/components/project-card.tsx +0 -191
- package/src/components/quick-filter-bar.tsx +0 -279
- package/src/components/scan-directory-dialog.tsx +0 -368
- package/src/components/status-donut.tsx +0 -197
- package/src/components/subtask-list.tsx +0 -128
- package/src/components/tag-picker.tsx +0 -252
- package/src/components/ui/.gitkeep +0 -0
- package/src/components/ui/alert-dialog.tsx +0 -141
- package/src/components/ui/avatar.tsx +0 -67
- package/src/components/ui/badge.tsx +0 -230
- package/src/components/ui/button.tsx +0 -433
- package/src/components/ui/card/index.tsx +0 -24
- package/src/components/ui/card/roiui-card.module.css +0 -197
- package/src/components/ui/card/roiui-card.tsx +0 -154
- package/src/components/ui/card/shadcn-card.tsx +0 -76
- package/src/components/ui/chart.tsx +0 -369
- package/src/components/ui/dialog.tsx +0 -122
- package/src/components/ui/dropdown-menu.tsx +0 -201
- package/src/components/ui/input.tsx +0 -22
- package/src/components/ui/kanban.tsx +0 -522
- package/src/components/ui/morphing-dialog.tsx +0 -457
- package/src/components/ui/popover.tsx +0 -33
- package/src/components/ui/progress.tsx +0 -28
- package/src/components/ui/scroll-area.tsx +0 -48
- package/src/components/ui/select.tsx +0 -159
- package/src/components/ui/separator.tsx +0 -31
- package/src/components/ui/sheet.tsx +0 -142
- package/src/components/ui/skeleton.tsx +0 -15
- package/src/components/ui/toast.tsx +0 -129
- package/src/components/ui/toaster.tsx +0 -35
- package/src/components/ui/tooltip.tsx +0 -30
- package/src/hooks/.gitkeep +0 -0
- package/src/hooks/use-bead-filters.ts +0 -261
- package/src/hooks/use-beads.ts +0 -162
- package/src/hooks/use-branch-statuses.ts +0 -161
- package/src/hooks/use-epics.ts +0 -173
- package/src/hooks/use-file-watcher.ts +0 -111
- package/src/hooks/use-keyboard-navigation.ts +0 -282
- package/src/hooks/use-project.ts +0 -61
- package/src/hooks/use-projects.ts +0 -93
- package/src/hooks/use-toast.ts +0 -194
- package/src/hooks/useClickOutside.tsx +0 -26
- package/src/lib/.gitkeep +0 -0
- package/src/lib/api.ts +0 -186
- package/src/lib/beads-parser.ts +0 -252
- package/src/lib/cli.ts +0 -193
- package/src/lib/db.ts +0 -145
- package/src/lib/design-doc.ts +0 -74
- package/src/lib/epic-parser.ts +0 -242
- package/src/lib/git.ts +0 -102
- package/src/lib/utils.ts +0 -12
- package/src/types/index.ts +0 -107
- package/tailwind.config.ts +0 -85
- package/tsconfig.json +0 -26
- /package/{npm/bin → bin}/cli.js +0 -0
- /package/{npm/scripts → scripts}/postinstall.js +0 -0
package/src/lib/epic-parser.ts
DELETED
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Epic parser utility for beads kanban
|
|
3
|
-
*
|
|
4
|
-
* Provides functions to separate epics from tasks, build epic trees,
|
|
5
|
-
* compute progress metrics, and identify blocking relationships.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { Bead, Epic, EpicProgress } from "@/types";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Separates epics from standalone tasks
|
|
12
|
-
*
|
|
13
|
-
* @param beads - Array of all beads
|
|
14
|
-
* @returns Object with separate arrays for epics and standalone tasks
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```typescript
|
|
18
|
-
* const { epics, tasks } = parseEpicsAndTasks(allBeads);
|
|
19
|
-
* console.log(`Found ${epics.length} epics and ${tasks.length} standalone tasks`);
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
export function parseEpicsAndTasks(beads: Bead[]): {
|
|
23
|
-
epics: Epic[];
|
|
24
|
-
tasks: Bead[];
|
|
25
|
-
} {
|
|
26
|
-
if (!beads || beads.length === 0) {
|
|
27
|
-
return { epics: [], tasks: [] };
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const epics: Epic[] = [];
|
|
31
|
-
const tasks: Bead[] = [];
|
|
32
|
-
|
|
33
|
-
for (const bead of beads) {
|
|
34
|
-
// Bead is an epic if issue_type is 'epic' OR if it has children
|
|
35
|
-
if (bead.issue_type === 'epic' || (bead.children && bead.children.length > 0)) {
|
|
36
|
-
epics.push({
|
|
37
|
-
...bead,
|
|
38
|
-
issue_type: 'epic',
|
|
39
|
-
children: bead.children ?? [],
|
|
40
|
-
} as Epic);
|
|
41
|
-
} else if (!bead.parent_id) {
|
|
42
|
-
// Only include tasks that are NOT children of epics (standalone tasks)
|
|
43
|
-
tasks.push(bead);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return { epics, tasks };
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Attaches child beads to their parent epics
|
|
52
|
-
*
|
|
53
|
-
* @param epics - Array of epic beads
|
|
54
|
-
* @param allBeads - Array of all beads (including children)
|
|
55
|
-
* @returns Array of epics with resolved children attached
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* ```typescript
|
|
59
|
-
* const epicsWithChildren = buildEpicTree(epics, allBeads);
|
|
60
|
-
* epicsWithChildren.forEach(epic => {
|
|
61
|
-
* console.log(`Epic ${epic.id} has ${epic.children.length} children`);
|
|
62
|
-
* });
|
|
63
|
-
* ```
|
|
64
|
-
*/
|
|
65
|
-
export function buildEpicTree(epics: Epic[], allBeads: Bead[]): Epic[] {
|
|
66
|
-
if (!epics || epics.length === 0) {
|
|
67
|
-
return [];
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (!allBeads || allBeads.length === 0) {
|
|
71
|
-
return epics;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Create a lookup map for fast child access
|
|
75
|
-
const beadMap = new Map<string, Bead>();
|
|
76
|
-
for (const bead of allBeads) {
|
|
77
|
-
beadMap.set(bead.id, bead);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Build epic tree with resolved children
|
|
81
|
-
return epics.map((epic) => {
|
|
82
|
-
const children = (epic.children ?? [])
|
|
83
|
-
.map((childId) => beadMap.get(childId))
|
|
84
|
-
.filter((child): child is Bead => child !== undefined);
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
...epic,
|
|
88
|
-
children: children.map((c) => c.id),
|
|
89
|
-
};
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Computes progress metrics for an epic based on its children
|
|
95
|
-
*
|
|
96
|
-
* @param epic - Epic bead with children
|
|
97
|
-
* @param allBeads - Array of all beads to resolve children from
|
|
98
|
-
* @returns EpicProgress object with computed metrics
|
|
99
|
-
*
|
|
100
|
-
* @example
|
|
101
|
-
* ```typescript
|
|
102
|
-
* const progress = computeEpicProgress(epic, allBeads);
|
|
103
|
-
* console.log(`${progress.completed}/${progress.total} children completed`);
|
|
104
|
-
* console.log(`${progress.blocked} children blocked`);
|
|
105
|
-
* ```
|
|
106
|
-
*/
|
|
107
|
-
export function computeEpicProgress(epic: Epic, allBeads: Bead[]): EpicProgress {
|
|
108
|
-
if (!epic.children || epic.children.length === 0) {
|
|
109
|
-
return {
|
|
110
|
-
total: 0,
|
|
111
|
-
completed: 0,
|
|
112
|
-
inProgress: 0,
|
|
113
|
-
blocked: 0,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (!allBeads || allBeads.length === 0) {
|
|
118
|
-
return {
|
|
119
|
-
total: epic.children.length,
|
|
120
|
-
completed: 0,
|
|
121
|
-
inProgress: 0,
|
|
122
|
-
blocked: 0,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Create lookup map for children
|
|
127
|
-
const beadMap = new Map<string, Bead>();
|
|
128
|
-
for (const bead of allBeads) {
|
|
129
|
-
beadMap.set(bead.id, bead);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Resolve child beads
|
|
133
|
-
const children = epic.children
|
|
134
|
-
.map((childId) => beadMap.get(childId))
|
|
135
|
-
.filter((child): child is Bead => child !== undefined);
|
|
136
|
-
|
|
137
|
-
// Count statuses
|
|
138
|
-
const completed = children.filter((c) => c.status === 'closed').length;
|
|
139
|
-
const inProgress = children.filter((c) => c.status === 'in_progress').length;
|
|
140
|
-
|
|
141
|
-
// Count blocked children (those with unresolved deps)
|
|
142
|
-
const blocked = children.filter((child) => {
|
|
143
|
-
if (!child.deps || child.deps.length === 0) {
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Check if any dependency is not yet completed
|
|
148
|
-
return child.deps.some((depId) => {
|
|
149
|
-
const depBead = beadMap.get(depId);
|
|
150
|
-
return depBead && depBead.status !== 'closed';
|
|
151
|
-
});
|
|
152
|
-
}).length;
|
|
153
|
-
|
|
154
|
-
return {
|
|
155
|
-
total: children.length,
|
|
156
|
-
completed,
|
|
157
|
-
inProgress,
|
|
158
|
-
blocked,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Identifies tasks that are blocked by unresolved dependencies
|
|
164
|
-
*
|
|
165
|
-
* @param beads - Array of all beads to check
|
|
166
|
-
* @returns Array of beads that have blocking dependencies
|
|
167
|
-
*
|
|
168
|
-
* @example
|
|
169
|
-
* ```typescript
|
|
170
|
-
* const blockedTasks = getBlockedTasks(allBeads);
|
|
171
|
-
* console.log(`${blockedTasks.length} tasks are currently blocked`);
|
|
172
|
-
* blockedTasks.forEach(task => {
|
|
173
|
-
* console.log(`${task.id} blocked by: ${task.deps?.join(', ')}`);
|
|
174
|
-
* });
|
|
175
|
-
* ```
|
|
176
|
-
*/
|
|
177
|
-
export function getBlockedTasks(beads: Bead[]): Bead[] {
|
|
178
|
-
if (!beads || beads.length === 0) {
|
|
179
|
-
return [];
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Create lookup map for fast access
|
|
183
|
-
const beadMap = new Map<string, Bead>();
|
|
184
|
-
for (const bead of beads) {
|
|
185
|
-
beadMap.set(bead.id, bead);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Filter beads with unresolved dependencies
|
|
189
|
-
return beads.filter((bead) => {
|
|
190
|
-
if (!bead.deps || bead.deps.length === 0) {
|
|
191
|
-
return false;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Check if any dependency is not yet completed
|
|
195
|
-
return bead.deps.some((depId) => {
|
|
196
|
-
const depBead = beadMap.get(depId);
|
|
197
|
-
// Blocked if dependency exists and is not closed
|
|
198
|
-
return depBead && depBead.status !== 'closed';
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Computes which beads the given bead blocks (inverse of deps)
|
|
205
|
-
*
|
|
206
|
-
* @param bead - The bead to check
|
|
207
|
-
* @param allBeads - Array of all beads to search for dependents
|
|
208
|
-
* @returns Array of bead IDs that depend on this bead
|
|
209
|
-
*
|
|
210
|
-
* @example
|
|
211
|
-
* ```typescript
|
|
212
|
-
* const blockers = computeBlockers(someBead, allBeads);
|
|
213
|
-
* if (blockers.length > 0) {
|
|
214
|
-
* console.log(`Completing this task will unblock: ${blockers.join(', ')}`);
|
|
215
|
-
* }
|
|
216
|
-
* ```
|
|
217
|
-
*/
|
|
218
|
-
export function computeBlockers(bead: Bead, allBeads: Bead[]): string[] {
|
|
219
|
-
if (!bead || !bead.id) {
|
|
220
|
-
return [];
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
if (!allBeads || allBeads.length === 0) {
|
|
224
|
-
return [];
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// Find all beads that list this bead in their deps array
|
|
228
|
-
const blockers: string[] = [];
|
|
229
|
-
|
|
230
|
-
for (const otherBead of allBeads) {
|
|
231
|
-
if (!otherBead.deps || otherBead.deps.length === 0) {
|
|
232
|
-
continue;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// If this bead is in the other bead's deps, then this bead blocks it
|
|
236
|
-
if (otherBead.deps.includes(bead.id)) {
|
|
237
|
-
blockers.push(otherBead.id);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
return blockers;
|
|
242
|
-
}
|
package/src/lib/git.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Git utilities for branch status via HTTP API
|
|
3
|
-
*
|
|
4
|
-
* Provides functions to check branch existence and ahead/behind status
|
|
5
|
-
* relative to the main branch.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import * as api from './api';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Branch status relative to main
|
|
12
|
-
*/
|
|
13
|
-
export interface BranchStatus {
|
|
14
|
-
/** Whether the branch exists locally */
|
|
15
|
-
exists: boolean;
|
|
16
|
-
/** Number of commits ahead of main */
|
|
17
|
-
ahead: number;
|
|
18
|
-
/** Number of commits behind main */
|
|
19
|
-
behind: number;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Get branch status (exists, ahead, behind) relative to main
|
|
24
|
-
*
|
|
25
|
-
* @param projectPath - Absolute path to the git repository
|
|
26
|
-
* @param branchName - Name of the branch to check status for
|
|
27
|
-
* @returns Promise resolving to BranchStatus
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* ```typescript
|
|
31
|
-
* const status = await getBranchStatus('/path/to/repo', 'bd-BD-001');
|
|
32
|
-
* if (status.exists) {
|
|
33
|
-
* console.log(`Branch is ${status.ahead} ahead, ${status.behind} behind main`);
|
|
34
|
-
* }
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
|
-
export async function getBranchStatus(
|
|
38
|
-
projectPath: string,
|
|
39
|
-
branchName: string
|
|
40
|
-
): Promise<BranchStatus> {
|
|
41
|
-
return api.git.branchStatus(projectPath, branchName);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Check if a branch exists locally
|
|
46
|
-
*
|
|
47
|
-
* @param projectPath - Absolute path to the git repository
|
|
48
|
-
* @param branchName - Name of the branch to check
|
|
49
|
-
* @returns Promise resolving to true if branch exists
|
|
50
|
-
*
|
|
51
|
-
* @example
|
|
52
|
-
* ```typescript
|
|
53
|
-
* const exists = await branchExists('/path/to/repo', 'bd-BD-001');
|
|
54
|
-
* ```
|
|
55
|
-
*/
|
|
56
|
-
export async function branchExists(
|
|
57
|
-
projectPath: string,
|
|
58
|
-
branchName: string
|
|
59
|
-
): Promise<boolean> {
|
|
60
|
-
const status = await getBranchStatus(projectPath, branchName);
|
|
61
|
-
return status.exists;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Get branch statuses for multiple branches in batch
|
|
66
|
-
*
|
|
67
|
-
* Runs checks in parallel for efficiency.
|
|
68
|
-
*
|
|
69
|
-
* @param projectPath - Absolute path to the git repository
|
|
70
|
-
* @param branchNames - Array of branch names to check
|
|
71
|
-
* @returns Promise resolving to a map of branch name to status
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
|
-
* ```typescript
|
|
75
|
-
* const statuses = await getBatchBranchStatus('/path/to/repo', [
|
|
76
|
-
* 'bd-BD-001',
|
|
77
|
-
* 'bd-BD-002',
|
|
78
|
-
* 'bd-BD-003'
|
|
79
|
-
* ]);
|
|
80
|
-
* ```
|
|
81
|
-
*/
|
|
82
|
-
export async function getBatchBranchStatus(
|
|
83
|
-
projectPath: string,
|
|
84
|
-
branchNames: string[]
|
|
85
|
-
): Promise<Record<string, BranchStatus>> {
|
|
86
|
-
const results: Record<string, BranchStatus> = {};
|
|
87
|
-
|
|
88
|
-
// Run all checks in parallel
|
|
89
|
-
const promises = branchNames.map(async (branchName) => {
|
|
90
|
-
try {
|
|
91
|
-
const status = await getBranchStatus(projectPath, branchName);
|
|
92
|
-
results[branchName] = status;
|
|
93
|
-
} catch {
|
|
94
|
-
// If there's an error, assume branch doesn't exist
|
|
95
|
-
results[branchName] = { exists: false, ahead: 0, behind: 0 };
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
await Promise.all(promises);
|
|
100
|
-
|
|
101
|
-
return results;
|
|
102
|
-
}
|
package/src/lib/utils.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { clsx, type ClassValue } from 'clsx';
|
|
2
|
-
import { twMerge } from 'tailwind-merge';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Merges Tailwind class names, resolving any conflicts.
|
|
6
|
-
*
|
|
7
|
-
* @param inputs - An array of class names to merge.
|
|
8
|
-
* @returns A string of merged and optimized class names.
|
|
9
|
-
*/
|
|
10
|
-
export function cn(...inputs: ClassValue[]): string {
|
|
11
|
-
return twMerge(clsx(inputs));
|
|
12
|
-
}
|
package/src/types/index.ts
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bead counts by status for a project
|
|
3
|
-
*/
|
|
4
|
-
export interface BeadCounts {
|
|
5
|
-
open: number;
|
|
6
|
-
in_progress: number;
|
|
7
|
-
inreview: number;
|
|
8
|
-
closed: number;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Project stored in local SQLite
|
|
13
|
-
*/
|
|
14
|
-
export interface Project {
|
|
15
|
-
id: string;
|
|
16
|
-
name: string;
|
|
17
|
-
path: string;
|
|
18
|
-
tags: Tag[];
|
|
19
|
-
lastOpened: string;
|
|
20
|
-
createdAt: string;
|
|
21
|
-
beadCounts?: BeadCounts;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Tag stored in local SQLite
|
|
26
|
-
*/
|
|
27
|
-
export interface Tag {
|
|
28
|
-
id: string;
|
|
29
|
-
name: string;
|
|
30
|
-
color: string;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Bead status types
|
|
35
|
-
*/
|
|
36
|
-
export type BeadStatus = 'open' | 'in_progress' | 'inreview' | 'closed';
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Bead from .beads/issues.jsonl
|
|
40
|
-
*/
|
|
41
|
-
export interface Bead {
|
|
42
|
-
id: string;
|
|
43
|
-
title: string;
|
|
44
|
-
description?: string;
|
|
45
|
-
status: BeadStatus;
|
|
46
|
-
priority: number;
|
|
47
|
-
issue_type: string;
|
|
48
|
-
owner: string;
|
|
49
|
-
created_at: string;
|
|
50
|
-
updated_at: string;
|
|
51
|
-
comments: Comment[];
|
|
52
|
-
// Epic support fields
|
|
53
|
-
parent_id?: string; // ID of parent epic (for child tasks)
|
|
54
|
-
children?: string[]; // IDs of child tasks (for epics)
|
|
55
|
-
design_doc?: string; // Path like ".designs/{EPIC_ID}.md"
|
|
56
|
-
deps?: string[]; // Dependency IDs (blocking this task)
|
|
57
|
-
blockers?: string[]; // COMPUTED: Tasks this blocks (derived from deps relationships)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Comment from .beads/issues.jsonl
|
|
62
|
-
*/
|
|
63
|
-
export interface Comment {
|
|
64
|
-
id: number;
|
|
65
|
-
issue_id: string;
|
|
66
|
-
author: string;
|
|
67
|
-
text: string;
|
|
68
|
-
created_at: string;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Kanban column configuration
|
|
73
|
-
*/
|
|
74
|
-
export interface KanbanColumn {
|
|
75
|
-
id: BeadStatus;
|
|
76
|
-
title: string;
|
|
77
|
-
beads: Bead[];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* GitHub PR info (for future integration)
|
|
82
|
-
*/
|
|
83
|
-
export interface PRInfo {
|
|
84
|
-
url: string;
|
|
85
|
-
state: 'OPEN' | 'MERGED' | 'CLOSED';
|
|
86
|
-
reviewDecision: 'APPROVED' | 'CHANGES_REQUESTED' | 'REVIEW_REQUIRED' | null;
|
|
87
|
-
statusCheckRollup: { state: 'SUCCESS' | 'FAILURE' | 'PENDING' } | null;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Epic progress metrics (computed from children)
|
|
92
|
-
*/
|
|
93
|
-
export interface EpicProgress {
|
|
94
|
-
total: number; // Total number of child tasks
|
|
95
|
-
completed: number; // Number of children with status 'closed'
|
|
96
|
-
inProgress: number; // Number of children with status 'in_progress'
|
|
97
|
-
blocked: number; // Number of children with unresolved dependencies
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Epic-specific bead type
|
|
102
|
-
*/
|
|
103
|
-
export interface Epic extends Bead {
|
|
104
|
-
issue_type: 'epic';
|
|
105
|
-
children: string[]; // Epics always have children (required, not optional)
|
|
106
|
-
progress?: EpicProgress; // Computed progress metrics
|
|
107
|
-
}
|
package/tailwind.config.ts
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import type { Config } from 'tailwindcss';
|
|
2
|
-
|
|
3
|
-
const config: Config = {
|
|
4
|
-
darkMode: ['class'],
|
|
5
|
-
content: [
|
|
6
|
-
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
|
|
7
|
-
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
|
|
8
|
-
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
|
|
9
|
-
],
|
|
10
|
-
theme: {
|
|
11
|
-
extend: {
|
|
12
|
-
colors: {
|
|
13
|
-
background: 'hsl(var(--background))',
|
|
14
|
-
foreground: 'hsl(var(--foreground))',
|
|
15
|
-
card: {
|
|
16
|
-
DEFAULT: 'hsl(var(--card))',
|
|
17
|
-
foreground: 'hsl(var(--card-foreground))',
|
|
18
|
-
},
|
|
19
|
-
popover: {
|
|
20
|
-
DEFAULT: 'hsl(var(--popover))',
|
|
21
|
-
foreground: 'hsl(var(--popover-foreground))',
|
|
22
|
-
},
|
|
23
|
-
primary: {
|
|
24
|
-
DEFAULT: 'hsl(var(--primary))',
|
|
25
|
-
foreground: 'hsl(var(--primary-foreground))',
|
|
26
|
-
},
|
|
27
|
-
secondary: {
|
|
28
|
-
DEFAULT: 'hsl(var(--secondary))',
|
|
29
|
-
foreground: 'hsl(var(--secondary-foreground))',
|
|
30
|
-
},
|
|
31
|
-
muted: {
|
|
32
|
-
DEFAULT: 'hsl(var(--muted))',
|
|
33
|
-
foreground: 'hsl(var(--muted-foreground))',
|
|
34
|
-
},
|
|
35
|
-
accent: {
|
|
36
|
-
DEFAULT: 'hsl(var(--accent))',
|
|
37
|
-
foreground: 'hsl(var(--accent-foreground))',
|
|
38
|
-
},
|
|
39
|
-
destructive: {
|
|
40
|
-
DEFAULT: 'hsl(var(--destructive))',
|
|
41
|
-
foreground: 'hsl(var(--destructive-foreground))',
|
|
42
|
-
},
|
|
43
|
-
border: 'hsl(var(--border))',
|
|
44
|
-
input: 'hsl(var(--input))',
|
|
45
|
-
ring: 'hsl(var(--ring))',
|
|
46
|
-
chart: {
|
|
47
|
-
'1': 'hsl(var(--chart-1))',
|
|
48
|
-
'2': 'hsl(var(--chart-2))',
|
|
49
|
-
'3': 'hsl(var(--chart-3))',
|
|
50
|
-
'4': 'hsl(var(--chart-4))',
|
|
51
|
-
'5': 'hsl(var(--chart-5))',
|
|
52
|
-
},
|
|
53
|
-
// Beads Status colors
|
|
54
|
-
status: {
|
|
55
|
-
open: 'hsl(var(--status-open))',
|
|
56
|
-
inprogress: 'hsl(var(--status-inprogress))',
|
|
57
|
-
inreview: 'hsl(var(--status-inreview))',
|
|
58
|
-
done: 'hsl(var(--status-done))',
|
|
59
|
-
},
|
|
60
|
-
// Beads Priority colors
|
|
61
|
-
priority: {
|
|
62
|
-
p0: 'hsl(var(--priority-p0))',
|
|
63
|
-
p1: 'hsl(var(--priority-p1))',
|
|
64
|
-
p2: 'hsl(var(--priority-p2))',
|
|
65
|
-
p3: 'hsl(var(--priority-p3))',
|
|
66
|
-
p4: 'hsl(var(--priority-p4))',
|
|
67
|
-
},
|
|
68
|
-
// Beads Accents
|
|
69
|
-
blocked: 'hsl(var(--blocked))',
|
|
70
|
-
branch: 'hsl(var(--branch))',
|
|
71
|
-
},
|
|
72
|
-
borderRadius: {
|
|
73
|
-
lg: 'var(--radius)',
|
|
74
|
-
md: 'calc(var(--radius) - 2px)',
|
|
75
|
-
sm: 'calc(var(--radius) - 4px)',
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
plugins: [
|
|
80
|
-
require('tailwindcss-animate'),
|
|
81
|
-
require('@tailwindcss/typography'),
|
|
82
|
-
],
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
export default config;
|
package/tsconfig.json
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"lib": ["dom", "dom.iterable", "esnext"],
|
|
4
|
-
"allowJs": true,
|
|
5
|
-
"skipLibCheck": true,
|
|
6
|
-
"strict": true,
|
|
7
|
-
"noEmit": true,
|
|
8
|
-
"esModuleInterop": true,
|
|
9
|
-
"module": "esnext",
|
|
10
|
-
"moduleResolution": "bundler",
|
|
11
|
-
"resolveJsonModule": true,
|
|
12
|
-
"isolatedModules": true,
|
|
13
|
-
"jsx": "preserve",
|
|
14
|
-
"incremental": true,
|
|
15
|
-
"plugins": [
|
|
16
|
-
{
|
|
17
|
-
"name": "next"
|
|
18
|
-
}
|
|
19
|
-
],
|
|
20
|
-
"paths": {
|
|
21
|
-
"@/*": ["./src/*"]
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
25
|
-
"exclude": ["node_modules"]
|
|
26
|
-
}
|
/package/{npm/bin → bin}/cli.js
RENAMED
|
File without changes
|
|
File without changes
|