@bretwardjames/ghp-cli 0.12.0 → 0.14.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/commands/dashboard-pipeline.d.ts +13 -0
- package/dist/commands/dashboard-pipeline.d.ts.map +1 -0
- package/dist/commands/dashboard-pipeline.js +475 -0
- package/dist/commands/dashboard-pipeline.js.map +1 -0
- package/dist/commands/pipeline-commands.d.ts +11 -0
- package/dist/commands/pipeline-commands.d.ts.map +1 -0
- package/dist/commands/pipeline-commands.js +101 -0
- package/dist/commands/pipeline-commands.js.map +1 -0
- package/dist/commands/review.d.ts +6 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +177 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/start.d.ts +2 -0
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +31 -9
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/status.d.ts +28 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +90 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/tmux.d.ts +24 -0
- package/dist/commands/tmux.d.ts.map +1 -0
- package/dist/commands/tmux.js +197 -0
- package/dist/commands/tmux.js.map +1 -0
- package/dist/commands/worktree-swap-state.d.ts +19 -0
- package/dist/commands/worktree-swap-state.d.ts.map +1 -0
- package/dist/commands/worktree-swap-state.js +29 -0
- package/dist/commands/worktree-swap-state.js.map +1 -0
- package/dist/commands/worktree-swap.d.ts +48 -0
- package/dist/commands/worktree-swap.d.ts.map +1 -0
- package/dist/commands/worktree-swap.js +456 -0
- package/dist/commands/worktree-swap.js.map +1 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/exit.d.ts +5 -0
- package/dist/exit.d.ts.map +1 -1
- package/dist/exit.js +7 -0
- package/dist/exit.js.map +1 -1
- package/dist/git-utils.d.ts +9 -0
- package/dist/git-utils.d.ts.map +1 -1
- package/dist/git-utils.js +19 -0
- package/dist/git-utils.js.map +1 -1
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline-registry.d.ts +50 -0
- package/dist/pipeline-registry.d.ts.map +1 -0
- package/dist/pipeline-registry.js +186 -0
- package/dist/pipeline-registry.js.map +1 -0
- package/dist/terminal-utils.d.ts +20 -8
- package/dist/terminal-utils.d.ts.map +1 -1
- package/dist/terminal-utils.js +47 -33
- package/dist/terminal-utils.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline dashboard — kanban view of all worktrees with interactive controls.
|
|
3
|
+
*
|
|
4
|
+
* Detects tmux layout mode at startup:
|
|
5
|
+
* - pane mode: agents are panes in the same window. [1-9] zooms the agent pane.
|
|
6
|
+
* - window mode: agents are in separate windows. [1-9] pulls pane into dashboard window.
|
|
7
|
+
*/
|
|
8
|
+
interface DashboardOptions {
|
|
9
|
+
interval?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function pipelineDashboardCommand(options?: DashboardOptions): Promise<void>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=dashboard-pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-pipeline.d.ts","sourceRoot":"","sources":["../../src/commands/dashboard-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAsDH,UAAU,gBAAgB;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAgQD,wBAAsB,wBAAwB,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmO5F"}
|
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline dashboard — kanban view of all worktrees with interactive controls.
|
|
3
|
+
*
|
|
4
|
+
* Detects tmux layout mode at startup:
|
|
5
|
+
* - pane mode: agents are panes in the same window. [1-9] zooms the agent pane.
|
|
6
|
+
* - window mode: agents are in separate windows. [1-9] pulls pane into dashboard window.
|
|
7
|
+
*/
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import { execFile } from 'child_process';
|
|
10
|
+
import { promisify } from 'util';
|
|
11
|
+
import { getAgentSummaries } from '@bretwardjames/ghp-core';
|
|
12
|
+
import { getMainWorktreeRoot } from '../git-utils.js';
|
|
13
|
+
import { getConfig } from '../config.js';
|
|
14
|
+
import { getAllPipelineEntries, getIntegrationTriggerStage, getStageEmoji } from '../pipeline-registry.js';
|
|
15
|
+
import { readSwapState } from './worktree-swap-state.js';
|
|
16
|
+
import { worktreeCleanCommand, worktreeNextCommand } from './worktree-swap.js';
|
|
17
|
+
import { registerCleanupHandler, resetExitState } from '../exit.js';
|
|
18
|
+
// Guard: when true, the dashboard cleanup handler is a no-op
|
|
19
|
+
let suppressCleanup = false;
|
|
20
|
+
/**
|
|
21
|
+
* Run a command that might call exit() without killing the dashboard.
|
|
22
|
+
* Temporarily overrides process.exit, suppresses cleanup, and resets exit state.
|
|
23
|
+
*/
|
|
24
|
+
async function safeExec(fn) {
|
|
25
|
+
const realExit = process.exit;
|
|
26
|
+
process.exit = (() => { });
|
|
27
|
+
suppressCleanup = true;
|
|
28
|
+
try {
|
|
29
|
+
await fn();
|
|
30
|
+
}
|
|
31
|
+
catch { /* swallow ExitPendingError */ }
|
|
32
|
+
finally {
|
|
33
|
+
// Wait a tick for any cleanup handlers to run (they'll be no-ops)
|
|
34
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
35
|
+
process.exit = realExit;
|
|
36
|
+
suppressCleanup = false;
|
|
37
|
+
resetExitState();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const execFileAsync = promisify(execFile);
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// tmux helpers — window mode (join-pane pull/release)
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
async function getCurrentWindowTarget() {
|
|
45
|
+
try {
|
|
46
|
+
const { stdout } = await execFileAsync('tmux', ['display-message', '-p', '#{session_name}:#{window_index}']);
|
|
47
|
+
return stdout.trim() || null;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function pullPaneFromWindow(sourceWindowName, targetPaneId) {
|
|
54
|
+
try {
|
|
55
|
+
const { stdout: paneIdOut } = await execFileAsync('tmux', [
|
|
56
|
+
'display-message', '-t', sourceWindowName, '-p', '#{pane_id}',
|
|
57
|
+
]);
|
|
58
|
+
const paneId = paneIdOut.trim();
|
|
59
|
+
if (!paneId)
|
|
60
|
+
return null;
|
|
61
|
+
// Split the dashboard pane vertically: dashboard stays on top, agent gets bottom 50%
|
|
62
|
+
await execFileAsync('tmux', ['join-pane', '-v', '-l', '50%', '-t', targetPaneId, '-s', paneId]);
|
|
63
|
+
return { paneId, sourceWindowName };
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function releasePaneToWindow(attached) {
|
|
70
|
+
try {
|
|
71
|
+
// break-pane -s = source pane to break out, -d = don't switch to it
|
|
72
|
+
await execFileAsync('tmux', ['break-pane', '-s', attached.paneId, '-d']);
|
|
73
|
+
// Restore the original window name (e.g., ghp-271)
|
|
74
|
+
const { stdout } = await execFileAsync('tmux', [
|
|
75
|
+
'display-message', '-t', attached.paneId, '-p', '#{window_id}',
|
|
76
|
+
]);
|
|
77
|
+
const windowId = stdout.trim();
|
|
78
|
+
if (windowId) {
|
|
79
|
+
await execFileAsync('tmux', ['rename-window', '-t', windowId, attached.sourceWindowName]);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch { /* best effort */ }
|
|
83
|
+
}
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
// tmux helpers — pane mode (zoom/select)
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
/** Find the pane ID that contains a process whose cwd matches the worktree path. */
|
|
88
|
+
async function findPaneForWorktree(worktreePath) {
|
|
89
|
+
try {
|
|
90
|
+
const { stdout } = await execFileAsync('tmux', [
|
|
91
|
+
'list-panes', '-F', '#{pane_id} #{pane_current_path}',
|
|
92
|
+
]);
|
|
93
|
+
for (const line of stdout.trim().split('\n')) {
|
|
94
|
+
const [paneId, panePath] = line.split(' ', 2);
|
|
95
|
+
if (panePath && panePath.startsWith(worktreePath)) {
|
|
96
|
+
return paneId;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch { /* ignore */ }
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
/** Select (focus) a pane. */
|
|
104
|
+
async function selectPane(paneId) {
|
|
105
|
+
try {
|
|
106
|
+
await execFileAsync('tmux', ['select-pane', '-t', paneId]);
|
|
107
|
+
}
|
|
108
|
+
catch { /* ignore */ }
|
|
109
|
+
}
|
|
110
|
+
/** Get the pane ID of the dashboard itself (this process). */
|
|
111
|
+
function getDashboardPaneId() {
|
|
112
|
+
// TMUX_PANE is set by tmux for each pane's process — unlike display-message
|
|
113
|
+
// which returns the *active* pane, this reliably identifies our own pane.
|
|
114
|
+
return process.env.TMUX_PANE || null;
|
|
115
|
+
}
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// Coordinator pane detection
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
async function findCoordinatorPane() {
|
|
120
|
+
const candidates = ['ghp-root', 'ghp-coordinator', 'ghp-main'];
|
|
121
|
+
for (const name of candidates) {
|
|
122
|
+
try {
|
|
123
|
+
const { stdout } = await execFileAsync('tmux', ['display-message', '-t', name, '-p', '#{window_name}']);
|
|
124
|
+
if (stdout.trim())
|
|
125
|
+
return name;
|
|
126
|
+
}
|
|
127
|
+
catch { /* not found */ }
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
// Git helpers
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
async function isMainRepoDirty(repoRoot) {
|
|
135
|
+
try {
|
|
136
|
+
const { stdout } = await execFileAsync('git', ['-C', repoRoot, 'status', '--porcelain']);
|
|
137
|
+
return stdout.trim().length > 0;
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
// Rendering
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
function formatAge(isoTimestamp) {
|
|
147
|
+
if (!isoTimestamp)
|
|
148
|
+
return '';
|
|
149
|
+
const ms = Date.now() - new Date(isoTimestamp).getTime();
|
|
150
|
+
const minutes = Math.floor(ms / 60000);
|
|
151
|
+
if (minutes < 60)
|
|
152
|
+
return `${minutes}m ago`;
|
|
153
|
+
return `${Math.floor(minutes / 60)}h ago`;
|
|
154
|
+
}
|
|
155
|
+
function issueLabel(entry) {
|
|
156
|
+
return `${chalk.cyan(`#${entry.pipeline.issueNumber}`)} ${entry.pipeline.issueTitle.substring(0, 38)}`;
|
|
157
|
+
}
|
|
158
|
+
function stageLine(entry) {
|
|
159
|
+
const emoji = getStageEmoji(entry.pipeline.stage);
|
|
160
|
+
const prefix = emoji ? `${emoji} ` : '';
|
|
161
|
+
const stage = chalk.dim(`${prefix}${entry.pipeline.stage}`);
|
|
162
|
+
const uptime = entry.agent?.uptime ? chalk.dim(` · ${entry.agent.uptime}`) : '';
|
|
163
|
+
const port = entry.agent?.port ? chalk.dim(` :${entry.agent.port}`) : '';
|
|
164
|
+
return `${stage}${uptime}${port}`;
|
|
165
|
+
}
|
|
166
|
+
function isAttached(entry, attached) {
|
|
167
|
+
return attached !== null && attached.issueNumber === entry.pipeline.issueNumber;
|
|
168
|
+
}
|
|
169
|
+
function renderEntry(e, prefix, attached, showAction) {
|
|
170
|
+
const active = isAttached(e, attached);
|
|
171
|
+
const label = active
|
|
172
|
+
? chalk.bgCyan.black(` #${e.pipeline.issueNumber} `) + ' ' + chalk.bold(e.pipeline.issueTitle.substring(0, 35))
|
|
173
|
+
: issueLabel(e);
|
|
174
|
+
const marker = active ? chalk.cyan('►') : ' ';
|
|
175
|
+
console.log(` ${marker}${prefix} ${label} ${stageLine(e)}`);
|
|
176
|
+
if (showAction && e.agent?.currentAction) {
|
|
177
|
+
console.log(` ${chalk.dim(`└─ ${e.agent.currentAction.substring(0, 55)}`)}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function renderDashboard(entries, tmuxMode, attached, now, mainDirty) {
|
|
181
|
+
process.stdout.write('\x1b[2J\x1b[H'); // clear
|
|
182
|
+
const triggerStage = getIntegrationTriggerStage();
|
|
183
|
+
const waiting = entries.filter(e => e.agent?.waitingForInput);
|
|
184
|
+
const ready = entries.filter(e => e.pipeline.stage === triggerStage && !e.inMainRepo);
|
|
185
|
+
const testing = entries.filter(e => e.inMainRepo);
|
|
186
|
+
const working = entries.filter(e => !e.agent?.waitingForInput &&
|
|
187
|
+
e.pipeline.stage !== triggerStage &&
|
|
188
|
+
!e.inMainRepo);
|
|
189
|
+
// Number all entries for keypress selection (attention first, then working)
|
|
190
|
+
const numbered = [...waiting, ...working];
|
|
191
|
+
numbered.forEach((e, i) => { e.attentionIndex = i + 1; });
|
|
192
|
+
const attachedLabel = attached
|
|
193
|
+
? chalk.bgCyan.black(` VIEWING: #${attached.issueNumber} `)
|
|
194
|
+
: '';
|
|
195
|
+
console.log(chalk.bold('GHP Pipeline'), chalk.dim(`[${now}]`), attachedLabel);
|
|
196
|
+
console.log(chalk.dim('─'.repeat(70)));
|
|
197
|
+
if (waiting.length > 0) {
|
|
198
|
+
console.log(chalk.yellow.bold(' NEEDS ATTENTION'));
|
|
199
|
+
for (const e of waiting) {
|
|
200
|
+
const key = chalk.yellow(`[${e.attentionIndex}]`);
|
|
201
|
+
renderEntry(e, key, attached, true);
|
|
202
|
+
}
|
|
203
|
+
console.log();
|
|
204
|
+
}
|
|
205
|
+
if (ready.length > 0) {
|
|
206
|
+
const blocked = mainDirty ? chalk.red.bold(' BLOCKED') + chalk.red(' — main repo has uncommitted changes') : '';
|
|
207
|
+
console.log(chalk.green.bold(' READY FOR INTEGRATION') + blocked);
|
|
208
|
+
for (const e of ready) {
|
|
209
|
+
const age = formatAge(e.pipeline.stageEnteredAt);
|
|
210
|
+
const active = isAttached(e, attached);
|
|
211
|
+
const marker = active ? chalk.cyan('►') : ' ';
|
|
212
|
+
const label = active
|
|
213
|
+
? chalk.bgCyan.black(` #${e.pipeline.issueNumber} `) + ' ' + chalk.bold(e.pipeline.issueTitle.substring(0, 35))
|
|
214
|
+
: issueLabel(e);
|
|
215
|
+
console.log(` ${marker}${chalk.green('✓')} ${label} ${chalk.dim(age)}`);
|
|
216
|
+
}
|
|
217
|
+
console.log();
|
|
218
|
+
}
|
|
219
|
+
if (testing.length > 0) {
|
|
220
|
+
console.log(chalk.blue.bold(' IN TESTING (main repo)'));
|
|
221
|
+
for (const e of testing) {
|
|
222
|
+
const active = isAttached(e, attached);
|
|
223
|
+
const marker = active ? chalk.cyan('►') : ' ';
|
|
224
|
+
const label = active
|
|
225
|
+
? chalk.bgCyan.black(` #${e.pipeline.issueNumber} `) + ' ' + chalk.bold(e.pipeline.issueTitle.substring(0, 35))
|
|
226
|
+
: issueLabel(e);
|
|
227
|
+
console.log(` ${marker}${chalk.blue('⟳')} ${label}`);
|
|
228
|
+
}
|
|
229
|
+
console.log();
|
|
230
|
+
}
|
|
231
|
+
if (working.length > 0) {
|
|
232
|
+
console.log(chalk.white.bold(' WORKING'));
|
|
233
|
+
for (const e of working) {
|
|
234
|
+
const sym = e.agent?.status === 'running' ? chalk.green('●') : chalk.dim('○');
|
|
235
|
+
const key = e.attentionIndex ? chalk.dim(`[${e.attentionIndex}]`) : ' ';
|
|
236
|
+
renderEntry(e, `${key} ${sym}`, attached, true);
|
|
237
|
+
}
|
|
238
|
+
console.log();
|
|
239
|
+
}
|
|
240
|
+
if (entries.length === 0) {
|
|
241
|
+
console.log(chalk.dim(' No worktrees in pipeline.'));
|
|
242
|
+
console.log(chalk.dim(' ghp start <issue> --parallel'));
|
|
243
|
+
console.log();
|
|
244
|
+
}
|
|
245
|
+
console.log(chalk.dim('─'.repeat(70)));
|
|
246
|
+
if (tmuxMode === 'pane') {
|
|
247
|
+
console.log(chalk.dim('[1-9] focus agent [i] next integration [x] clean [q] quit'));
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
if (attached) {
|
|
251
|
+
console.log(chalk.dim('[1-9] swap [esc] send back [c] coordinator [q] quit'));
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
console.log(chalk.dim('[1-9] pull pane [i] next integration [x] clean [c] coordinator [q] quit'));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// ---------------------------------------------------------------------------
|
|
259
|
+
// Main command
|
|
260
|
+
// ---------------------------------------------------------------------------
|
|
261
|
+
export async function pipelineDashboardCommand(options = {}) {
|
|
262
|
+
const intervalSec = parseInt(options.interval || '2', 10);
|
|
263
|
+
const intervalMs = intervalSec * 1000;
|
|
264
|
+
// Detect tmux mode from config
|
|
265
|
+
const parallelConfig = getConfig('parallelWork');
|
|
266
|
+
const tmuxMode = parallelConfig?.tmux?.mode ?? 'window';
|
|
267
|
+
if (!process.env.TMUX) {
|
|
268
|
+
console.log(chalk.yellow('Warning:'), 'Not inside tmux — interactive features disabled.');
|
|
269
|
+
console.log(chalk.dim('Showing read-only status. Ctrl+C to exit.'));
|
|
270
|
+
console.log();
|
|
271
|
+
}
|
|
272
|
+
let attached = null;
|
|
273
|
+
// zoomedIssue removed — pane mode uses select-pane (focus) instead of zoom
|
|
274
|
+
let dashboardPaneId = null;
|
|
275
|
+
let coordinatorWindow = null;
|
|
276
|
+
let refreshTimer = null;
|
|
277
|
+
if (process.env.TMUX) {
|
|
278
|
+
dashboardPaneId = getDashboardPaneId();
|
|
279
|
+
if (tmuxMode === 'window') {
|
|
280
|
+
coordinatorWindow = await findCoordinatorPane();
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
async function buildEntries() {
|
|
284
|
+
const repoRoot = await getMainWorktreeRoot();
|
|
285
|
+
if (!repoRoot)
|
|
286
|
+
return [];
|
|
287
|
+
const pipeline = getAllPipelineEntries(repoRoot);
|
|
288
|
+
const agents = getAgentSummaries();
|
|
289
|
+
const swapState = readSwapState(repoRoot);
|
|
290
|
+
const agentByIssue = new Map();
|
|
291
|
+
for (const a of agents)
|
|
292
|
+
agentByIssue.set(a.issueNumber, a);
|
|
293
|
+
return pipeline.map(p => ({
|
|
294
|
+
pipeline: p,
|
|
295
|
+
agent: agentByIssue.get(p.issueNumber),
|
|
296
|
+
inMainRepo: swapState?.worktreeBranch === p.branch,
|
|
297
|
+
}));
|
|
298
|
+
}
|
|
299
|
+
async function refresh() {
|
|
300
|
+
const repoRoot = await getMainWorktreeRoot();
|
|
301
|
+
const entries = await buildEntries();
|
|
302
|
+
const dirty = repoRoot ? await isMainRepoDirty(repoRoot) : false;
|
|
303
|
+
renderDashboard(entries, tmuxMode, attached, new Date().toLocaleTimeString(), dirty);
|
|
304
|
+
}
|
|
305
|
+
function getNumberedEntry(entries, digit) {
|
|
306
|
+
const triggerStage = getIntegrationTriggerStage();
|
|
307
|
+
const waiting = entries.filter(e => e.agent?.waitingForInput);
|
|
308
|
+
const working = entries.filter(e => !e.agent?.waitingForInput &&
|
|
309
|
+
e.pipeline.stage !== triggerStage &&
|
|
310
|
+
!e.inMainRepo);
|
|
311
|
+
const numbered = [...waiting, ...working];
|
|
312
|
+
return numbered[digit - 1];
|
|
313
|
+
}
|
|
314
|
+
// ---------------------------------------------------------------------------
|
|
315
|
+
// Pane mode: select (focus) agent pane
|
|
316
|
+
// ---------------------------------------------------------------------------
|
|
317
|
+
async function focusAgent(issueNumber) {
|
|
318
|
+
const repoRoot = await getMainWorktreeRoot();
|
|
319
|
+
if (!repoRoot)
|
|
320
|
+
return;
|
|
321
|
+
const entry = getAllPipelineEntries(repoRoot).find(e => e.issueNumber === issueNumber);
|
|
322
|
+
if (!entry)
|
|
323
|
+
return;
|
|
324
|
+
const paneId = await findPaneForWorktree(entry.worktreePath);
|
|
325
|
+
if (paneId) {
|
|
326
|
+
await selectPane(paneId);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
// ---------------------------------------------------------------------------
|
|
330
|
+
// Window mode: pull/release
|
|
331
|
+
// ---------------------------------------------------------------------------
|
|
332
|
+
async function pullAgentPane(issueNumber) {
|
|
333
|
+
// Hot-swap: release current pane before pulling the new one
|
|
334
|
+
if (attached) {
|
|
335
|
+
if (attached.issueNumber === issueNumber)
|
|
336
|
+
return; // already showing this one
|
|
337
|
+
await sendPaneBack();
|
|
338
|
+
}
|
|
339
|
+
const windowName = `ghp-${issueNumber}`;
|
|
340
|
+
if (!dashboardPaneId)
|
|
341
|
+
return;
|
|
342
|
+
const result = await pullPaneFromWindow(windowName, dashboardPaneId);
|
|
343
|
+
if (!result)
|
|
344
|
+
return;
|
|
345
|
+
// Set pane border title so it's visually clear which agent is shown
|
|
346
|
+
try {
|
|
347
|
+
await execFileAsync('tmux', ['select-pane', '-t', result.paneId, '-T', `Agent #${issueNumber}`]);
|
|
348
|
+
}
|
|
349
|
+
catch { /* best effort */ }
|
|
350
|
+
attached = { issueNumber, paneId: result.paneId, sourceWindowName: result.sourceWindowName };
|
|
351
|
+
await refresh();
|
|
352
|
+
}
|
|
353
|
+
async function sendPaneBack() {
|
|
354
|
+
if (!attached)
|
|
355
|
+
return;
|
|
356
|
+
await releasePaneToWindow(attached);
|
|
357
|
+
attached = null;
|
|
358
|
+
await refresh();
|
|
359
|
+
}
|
|
360
|
+
// ---------------------------------------------------------------------------
|
|
361
|
+
// Keypress handler
|
|
362
|
+
// ---------------------------------------------------------------------------
|
|
363
|
+
async function handleKey(key) {
|
|
364
|
+
// esc — send pane back (window mode) or refocus dashboard (pane mode)
|
|
365
|
+
if (key === '\x1b') {
|
|
366
|
+
if (tmuxMode === 'pane' && dashboardPaneId) {
|
|
367
|
+
await selectPane(dashboardPaneId);
|
|
368
|
+
}
|
|
369
|
+
else if (tmuxMode === 'window' && attached) {
|
|
370
|
+
await sendPaneBack();
|
|
371
|
+
}
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
// q — quit
|
|
375
|
+
if (key === 'q' || key === 'Q') {
|
|
376
|
+
if (attached)
|
|
377
|
+
await sendPaneBack();
|
|
378
|
+
if (refreshTimer)
|
|
379
|
+
clearInterval(refreshTimer);
|
|
380
|
+
if (process.stdin.isTTY) {
|
|
381
|
+
process.stdin.setRawMode(false);
|
|
382
|
+
process.stdin.pause();
|
|
383
|
+
}
|
|
384
|
+
console.log();
|
|
385
|
+
process.exit(0);
|
|
386
|
+
}
|
|
387
|
+
// c — coordinator (window mode only)
|
|
388
|
+
if ((key === 'c' || key === 'C') && tmuxMode === 'window') {
|
|
389
|
+
if (attached) {
|
|
390
|
+
await sendPaneBack();
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
if (!coordinatorWindow)
|
|
394
|
+
coordinatorWindow = await findCoordinatorPane();
|
|
395
|
+
if (!coordinatorWindow) {
|
|
396
|
+
process.stdout.write('\x1b[2J\x1b[H');
|
|
397
|
+
console.log(chalk.yellow('No coordinator window found'));
|
|
398
|
+
setTimeout(() => refresh(), 1500);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
if (!dashboardPaneId)
|
|
402
|
+
return;
|
|
403
|
+
const result = await pullPaneFromWindow(coordinatorWindow, dashboardPaneId);
|
|
404
|
+
if (result) {
|
|
405
|
+
attached = { issueNumber: 0, paneId: result.paneId, sourceWindowName: result.sourceWindowName };
|
|
406
|
+
await refresh();
|
|
407
|
+
}
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
// i or n — swap next ready worktree
|
|
411
|
+
if (key === 'i' || key === 'I' || key === 'n' || key === 'N') {
|
|
412
|
+
await safeExec(() => worktreeNextCommand(undefined));
|
|
413
|
+
await refresh();
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
// x — clean
|
|
417
|
+
if (key === 'x' || key === 'X') {
|
|
418
|
+
await safeExec(() => worktreeCleanCommand({}));
|
|
419
|
+
await refresh();
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
// 1-9 — zoom (pane mode) or pull (window mode)
|
|
423
|
+
const digit = parseInt(key, 10);
|
|
424
|
+
if (!isNaN(digit) && digit >= 1 && digit <= 9) {
|
|
425
|
+
const entries = await buildEntries();
|
|
426
|
+
const entry = getNumberedEntry(entries, digit);
|
|
427
|
+
if (!entry)
|
|
428
|
+
return;
|
|
429
|
+
if (tmuxMode === 'pane') {
|
|
430
|
+
await focusAgent(entry.pipeline.issueNumber);
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
await pullAgentPane(entry.pipeline.issueNumber);
|
|
434
|
+
}
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
// ---------------------------------------------------------------------------
|
|
439
|
+
// Start
|
|
440
|
+
// ---------------------------------------------------------------------------
|
|
441
|
+
await refresh();
|
|
442
|
+
refreshTimer = setInterval(() => {
|
|
443
|
+
refresh().catch(() => { });
|
|
444
|
+
}, intervalMs);
|
|
445
|
+
registerCleanupHandler(() => {
|
|
446
|
+
if (suppressCleanup)
|
|
447
|
+
return;
|
|
448
|
+
if (refreshTimer)
|
|
449
|
+
clearInterval(refreshTimer);
|
|
450
|
+
if (attached)
|
|
451
|
+
releasePaneToWindow(attached).catch(() => { });
|
|
452
|
+
process.stdin.setRawMode?.(false);
|
|
453
|
+
process.stdin.pause();
|
|
454
|
+
});
|
|
455
|
+
if (process.stdin.isTTY) {
|
|
456
|
+
process.stdin.setRawMode(true);
|
|
457
|
+
process.stdin.resume();
|
|
458
|
+
process.stdin.setEncoding('utf-8');
|
|
459
|
+
process.stdin.on('data', (key) => {
|
|
460
|
+
if (key === '\u0003') {
|
|
461
|
+
if (attached)
|
|
462
|
+
releasePaneToWindow(attached).catch(() => { });
|
|
463
|
+
if (refreshTimer)
|
|
464
|
+
clearInterval(refreshTimer);
|
|
465
|
+
process.stdin.setRawMode(false);
|
|
466
|
+
process.stdin.pause();
|
|
467
|
+
console.log();
|
|
468
|
+
process.exit(0);
|
|
469
|
+
}
|
|
470
|
+
handleKey(key).catch(() => { });
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
await new Promise(() => { });
|
|
474
|
+
}
|
|
475
|
+
//# sourceMappingURL=dashboard-pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-pipeline.js","sourceRoot":"","sources":["../../src/commands/dashboard-pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline stage management commands.
|
|
3
|
+
*
|
|
4
|
+
* ghp pipeline advance [issue] — advance to next stage
|
|
5
|
+
* ghp pipeline set <stage> [issue] — jump to specific stage
|
|
6
|
+
* ghp pipeline stages — list configured stages
|
|
7
|
+
*/
|
|
8
|
+
export declare function pipelineAdvanceCommand(issueArg?: string): Promise<void>;
|
|
9
|
+
export declare function pipelineSetCommand(stage: string, issueArg?: string): Promise<void>;
|
|
10
|
+
export declare function pipelineStagesCommand(): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=pipeline-commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-commands.d.ts","sourceRoot":"","sources":["../../src/commands/pipeline-commands.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkCH,wBAAsB,sBAAsB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6B7E;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BxF;AAED,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAgB3D"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline stage management commands.
|
|
3
|
+
*
|
|
4
|
+
* ghp pipeline advance [issue] — advance to next stage
|
|
5
|
+
* ghp pipeline set <stage> [issue] — jump to specific stage
|
|
6
|
+
* ghp pipeline stages — list configured stages
|
|
7
|
+
*/
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import { execFileSync } from 'child_process';
|
|
10
|
+
import { getMainWorktreeRoot } from '../git-utils.js';
|
|
11
|
+
import { advanceWorktreeStage, setWorktreeStage, getPipelineEntry, getPipelineStages, getIntegrationTriggerStage, getStageEmoji, } from '../pipeline-registry.js';
|
|
12
|
+
import { exit } from '../exit.js';
|
|
13
|
+
function extractIssueFromBranch(branch) {
|
|
14
|
+
const match = branch.match(/\/(\d+)-/);
|
|
15
|
+
return match ? parseInt(match[1], 10) : null;
|
|
16
|
+
}
|
|
17
|
+
async function resolveIssueNumber(issueArg) {
|
|
18
|
+
if (issueArg) {
|
|
19
|
+
const num = parseInt(issueArg, 10);
|
|
20
|
+
return isNaN(num) ? null : num;
|
|
21
|
+
}
|
|
22
|
+
// Auto-detect from current branch
|
|
23
|
+
try {
|
|
24
|
+
const branch = execFileSync('git', ['branch', '--show-current'], { encoding: 'utf-8' }).trim();
|
|
25
|
+
return extractIssueFromBranch(branch);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export async function pipelineAdvanceCommand(issueArg) {
|
|
32
|
+
const repoRoot = await getMainWorktreeRoot();
|
|
33
|
+
if (!repoRoot) {
|
|
34
|
+
console.error(chalk.red('Error:'), 'Could not determine repository root');
|
|
35
|
+
exit(1);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const issueNumber = await resolveIssueNumber(issueArg);
|
|
39
|
+
if (!issueNumber) {
|
|
40
|
+
console.error(chalk.red('Error:'), 'Could not determine issue number. Pass it explicitly: ghp pipeline advance <issue>');
|
|
41
|
+
exit(1);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const before = getPipelineEntry(repoRoot, issueNumber);
|
|
45
|
+
if (!before) {
|
|
46
|
+
console.error(chalk.red('Error:'), `Issue #${issueNumber} is not in the pipeline.`);
|
|
47
|
+
exit(1);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const after = advanceWorktreeStage(repoRoot, issueNumber);
|
|
51
|
+
if (!after || after.stage === before.stage) {
|
|
52
|
+
console.log(chalk.yellow('Already at last stage:'), chalk.dim(before.stage));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
console.log(chalk.green('✓'), `#${issueNumber}: ${chalk.dim(before.stage)} → ${chalk.cyan(after.stage)}`);
|
|
56
|
+
}
|
|
57
|
+
export async function pipelineSetCommand(stage, issueArg) {
|
|
58
|
+
const repoRoot = await getMainWorktreeRoot();
|
|
59
|
+
if (!repoRoot) {
|
|
60
|
+
console.error(chalk.red('Error:'), 'Could not determine repository root');
|
|
61
|
+
exit(1);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const issueNumber = await resolveIssueNumber(issueArg);
|
|
65
|
+
if (!issueNumber) {
|
|
66
|
+
console.error(chalk.red('Error:'), 'Could not determine issue number. Pass it explicitly: ghp pipeline set <stage> <issue>');
|
|
67
|
+
exit(1);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const stages = getPipelineStages();
|
|
71
|
+
if (!stages.includes(stage)) {
|
|
72
|
+
console.error(chalk.red('Error:'), `Unknown stage: ${stage}`);
|
|
73
|
+
console.error('Available stages:', stages.join(', '));
|
|
74
|
+
exit(1);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const entry = setWorktreeStage(repoRoot, issueNumber, stage);
|
|
78
|
+
if (!entry) {
|
|
79
|
+
console.error(chalk.red('Error:'), `Issue #${issueNumber} is not in the pipeline.`);
|
|
80
|
+
exit(1);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
console.log(chalk.green('✓'), `#${issueNumber} → ${chalk.cyan(stage)}`);
|
|
84
|
+
}
|
|
85
|
+
export async function pipelineStagesCommand() {
|
|
86
|
+
const stages = getPipelineStages();
|
|
87
|
+
const triggerStage = getIntegrationTriggerStage();
|
|
88
|
+
console.log(chalk.bold('Pipeline Stages'));
|
|
89
|
+
console.log();
|
|
90
|
+
for (let i = 0; i < stages.length; i++) {
|
|
91
|
+
const name = stages[i];
|
|
92
|
+
const emoji = getStageEmoji(name);
|
|
93
|
+
const prefix = emoji ? `${emoji} ` : ' ';
|
|
94
|
+
const marker = name === triggerStage ? chalk.green(' ← integration trigger') : '';
|
|
95
|
+
console.log(` ${chalk.dim(`${i + 1}.`)} ${prefix}${name}${marker}`);
|
|
96
|
+
}
|
|
97
|
+
console.log();
|
|
98
|
+
console.log(chalk.dim('Configure with: ghp config pipeline.stages \'["stage1", "stage2", ...]\''));
|
|
99
|
+
console.log(chalk.dim('Integration trigger: ghp config pipeline.integrationAfter "<stage>"'));
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=pipeline-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-commands.js","sourceRoot":"","sources":["../../src/commands/pipeline-commands.ts"],"names":[],"mappings":"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"}
|