@jonit-dev/night-watch-cli 1.5.1 → 1.5.2

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/cli.js CHANGED
@@ -15,6 +15,7 @@ import { dashboardCommand } from './commands/dashboard.js';
15
15
  import { doctorCommand } from './commands/doctor.js';
16
16
  import { serveCommand } from './commands/serve.js';
17
17
  import { historyCommand } from './commands/history.js';
18
+ import { updateCommand } from './commands/update.js';
18
19
  // Get package.json version
19
20
  const __filename = fileURLToPath(import.meta.url);
20
21
  const __dirname = dirname(__filename);
@@ -46,5 +47,7 @@ dashboardCommand(program);
46
47
  serveCommand(program);
47
48
  // Register history command (used by bash scripts for cooldown tracking)
48
49
  historyCommand(program);
50
+ // Register update command
51
+ updateCommand(program);
49
52
  program.parse();
50
53
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,2BAA2B;AAC3B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;AAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;AAEvE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,kDAAkD,CAAC;KAC/D,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAEhC,wBAAwB;AACxB,WAAW,CAAC,OAAO,CAAC,CAAC;AAErB,uBAAuB;AACvB,UAAU,CAAC,OAAO,CAAC,CAAC;AAEpB,0BAA0B;AAC1B,aAAa,CAAC,OAAO,CAAC,CAAC;AAEvB,4BAA4B;AAC5B,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAC1B,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,WAAW,CAAC,OAAO,CAAC,CAAC;AAErB,uBAAuB;AACvB,UAAU,CAAC,OAAO,CAAC,CAAC;AAEpB,0BAA0B;AAC1B,aAAa,CAAC,OAAO,CAAC,CAAC;AAEvB,6BAA6B;AAC7B,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAE1B,yBAAyB;AACzB,YAAY,CAAC,OAAO,CAAC,CAAC;AAEtB,wEAAwE;AACxE,cAAc,CAAC,OAAO,CAAC,CAAC;AAExB,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,2BAA2B;AAC3B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;AAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;AAEvE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,kDAAkD,CAAC;KAC/D,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAEhC,wBAAwB;AACxB,WAAW,CAAC,OAAO,CAAC,CAAC;AAErB,uBAAuB;AACvB,UAAU,CAAC,OAAO,CAAC,CAAC;AAEpB,0BAA0B;AAC1B,aAAa,CAAC,OAAO,CAAC,CAAC;AAEvB,4BAA4B;AAC5B,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAC1B,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,WAAW,CAAC,OAAO,CAAC,CAAC;AAErB,uBAAuB;AACvB,UAAU,CAAC,OAAO,CAAC,CAAC;AAEpB,0BAA0B;AAC1B,aAAa,CAAC,OAAO,CAAC,CAAC;AAEvB,6BAA6B;AAC7B,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAE1B,yBAAyB;AACzB,YAAY,CAAC,OAAO,CAAC,CAAC;AAEtB,wEAAwE;AACxE,cAAc,CAAC,OAAO,CAAC,CAAC;AAExB,0BAA0B;AAC1B,aAAa,CAAC,OAAO,CAAC,CAAC;AAEvB,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Cancel command for Night Watch CLI
3
+ * Gracefully stops a running executor or reviewer process
4
+ */
5
+ import { Command } from "commander";
6
+ export interface ICancelOptions {
7
+ type: "run" | "review" | "all";
8
+ force?: boolean;
9
+ }
10
+ /**
11
+ * Get lock file paths for a project
12
+ */
13
+ export declare function getLockFilePaths(projectName: string): {
14
+ executor: string;
15
+ reviewer: string;
16
+ };
17
+ /**
18
+ * Prompt user for confirmation
19
+ */
20
+ export declare function promptConfirmation(prompt: string): Promise<boolean>;
21
+ /**
22
+ * Wait for specified milliseconds
23
+ */
24
+ export declare function sleep(ms: number): Promise<void>;
25
+ /**
26
+ * Check if a process is still running
27
+ */
28
+ export declare function isProcessRunning(pid: number): boolean;
29
+ export interface ICancelResult {
30
+ success: boolean;
31
+ message: string;
32
+ cleanedUp?: boolean;
33
+ }
34
+ /**
35
+ * Attempt to cancel a single process
36
+ */
37
+ export declare function cancelProcess(processType: "executor" | "reviewer", lockPath: string, force?: boolean): Promise<ICancelResult>;
38
+ /**
39
+ * Cancel running execution
40
+ */
41
+ export declare function performCancel(projectDir: string, options: ICancelOptions): Promise<ICancelResult[]>;
42
+ /**
43
+ * Cancel command implementation
44
+ */
45
+ export declare function cancelCommand(program: Command): void;
46
+ //# sourceMappingURL=cancel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cancel.d.ts","sourceRoot":"","sources":["../../src/commands/cancel.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAKA;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAazE;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,UAAU,GAAG,UAAU,EACpC,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,OAAe,GACrB,OAAO,CAAC,aAAa,CAAC,CA+HxB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,EAAE,CAAC,CAiB1B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkDpD"}
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Cancel command for Night Watch CLI
3
+ * Gracefully stops a running executor or reviewer process
4
+ */
5
+ import * as fs from "fs";
6
+ import * as path from "path";
7
+ import * as readline from "readline";
8
+ import { LOCK_FILE_PREFIX } from "../constants.js";
9
+ import { checkLockFile } from "../utils/status-data.js";
10
+ import { dim, info, success, error as uiError, warn, } from "../utils/ui.js";
11
+ /**
12
+ * Get lock file paths for a project
13
+ */
14
+ export function getLockFilePaths(projectName) {
15
+ return {
16
+ executor: `${LOCK_FILE_PREFIX}${projectName}.lock`,
17
+ reviewer: `${LOCK_FILE_PREFIX}pr-reviewer-${projectName}.lock`,
18
+ };
19
+ }
20
+ /**
21
+ * Prompt user for confirmation
22
+ */
23
+ export async function promptConfirmation(prompt) {
24
+ const rl = readline.createInterface({
25
+ input: process.stdin,
26
+ output: process.stdout,
27
+ });
28
+ return new Promise((resolve) => {
29
+ rl.question(`${prompt} `, (answer) => {
30
+ rl.close();
31
+ const normalized = answer.toLowerCase().trim();
32
+ resolve(normalized === "y" || normalized === "yes");
33
+ });
34
+ });
35
+ }
36
+ /**
37
+ * Wait for specified milliseconds
38
+ */
39
+ export function sleep(ms) {
40
+ return new Promise((resolve) => setTimeout(resolve, ms));
41
+ }
42
+ /**
43
+ * Check if a process is still running
44
+ */
45
+ export function isProcessRunning(pid) {
46
+ try {
47
+ process.kill(pid, 0);
48
+ return true;
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ }
54
+ /**
55
+ * Attempt to cancel a single process
56
+ */
57
+ export async function cancelProcess(processType, lockPath, force = false) {
58
+ const lockStatus = checkLockFile(lockPath);
59
+ // No lock file exists
60
+ if (!lockStatus.pid) {
61
+ return {
62
+ success: true,
63
+ message: `${processType} is not running (no lock file)`,
64
+ };
65
+ }
66
+ const pid = lockStatus.pid;
67
+ // Lock file exists but process is not running (stale)
68
+ if (!lockStatus.running) {
69
+ // Clean up stale lock file
70
+ try {
71
+ fs.unlinkSync(lockPath);
72
+ return {
73
+ success: true,
74
+ message: `${processType} is not running (cleaned up stale lock file for PID ${pid})`,
75
+ cleanedUp: true,
76
+ };
77
+ }
78
+ catch {
79
+ return {
80
+ success: true,
81
+ message: `${processType} is not running (stale lock file exists but could not be removed)`,
82
+ };
83
+ }
84
+ }
85
+ // Process is running - prompt for confirmation
86
+ const confirmPrompt = `Kill ${processType} (PID ${pid})? [y/N]`;
87
+ if (!force) {
88
+ const confirmed = await promptConfirmation(confirmPrompt);
89
+ if (!confirmed) {
90
+ return {
91
+ success: false,
92
+ message: `Cancelled - ${processType} (PID ${pid}) left running`,
93
+ };
94
+ }
95
+ }
96
+ else {
97
+ dim(confirmPrompt + " y (forced)");
98
+ }
99
+ // Send SIGTERM
100
+ try {
101
+ process.kill(pid, "SIGTERM");
102
+ }
103
+ catch (err) {
104
+ const errorMessage = err instanceof Error ? err.message : String(err);
105
+ return {
106
+ success: false,
107
+ message: `Failed to send SIGTERM to ${processType} (PID ${pid}): ${errorMessage}`,
108
+ };
109
+ }
110
+ info(`Sent SIGTERM to ${processType} (PID ${pid}), waiting 3 seconds...`);
111
+ // Wait 3 seconds
112
+ await sleep(3000);
113
+ // Check if process is still running
114
+ if (!isProcessRunning(pid)) {
115
+ // Clean up lock file
116
+ try {
117
+ fs.unlinkSync(lockPath);
118
+ }
119
+ catch {
120
+ // Ignore cleanup errors
121
+ }
122
+ return {
123
+ success: true,
124
+ message: `${processType} (PID ${pid}) terminated successfully`,
125
+ };
126
+ }
127
+ // Process still running after SIGTERM
128
+ warn(`${processType} (PID ${pid}) is still running after SIGTERM`);
129
+ // Offer to send SIGKILL
130
+ const killPrompt = `Send SIGKILL to ${processType} (PID ${pid})? [y/N]`;
131
+ let shouldKill;
132
+ if (!force) {
133
+ shouldKill = await promptConfirmation(killPrompt);
134
+ }
135
+ else {
136
+ dim(killPrompt + " y (forced)");
137
+ shouldKill = true;
138
+ }
139
+ if (!shouldKill) {
140
+ return {
141
+ success: false,
142
+ message: `${processType} (PID ${pid}) still running - SIGTERM sent but process did not terminate`,
143
+ };
144
+ }
145
+ // Send SIGKILL
146
+ try {
147
+ process.kill(pid, "SIGKILL");
148
+ }
149
+ catch (err) {
150
+ const errorMessage = err instanceof Error ? err.message : String(err);
151
+ return {
152
+ success: false,
153
+ message: `Failed to send SIGKILL to ${processType} (PID ${pid}): ${errorMessage}`,
154
+ };
155
+ }
156
+ // Wait briefly for SIGKILL to take effect
157
+ await sleep(500);
158
+ // Final check
159
+ if (!isProcessRunning(pid)) {
160
+ // Clean up lock file
161
+ try {
162
+ fs.unlinkSync(lockPath);
163
+ }
164
+ catch {
165
+ // Ignore cleanup errors
166
+ }
167
+ return {
168
+ success: true,
169
+ message: `${processType} (PID ${pid}) killed successfully`,
170
+ };
171
+ }
172
+ return {
173
+ success: false,
174
+ message: `${processType} (PID ${pid}) could not be terminated even with SIGKILL`,
175
+ };
176
+ }
177
+ /**
178
+ * Cancel running execution
179
+ */
180
+ export async function performCancel(projectDir, options) {
181
+ const projectName = path.basename(projectDir);
182
+ const lockPaths = getLockFilePaths(projectName);
183
+ const results = [];
184
+ const force = options.force ?? false;
185
+ if (options.type === "run" || options.type === "all") {
186
+ const result = await cancelProcess("executor", lockPaths.executor, force);
187
+ results.push(result);
188
+ }
189
+ if (options.type === "review" || options.type === "all") {
190
+ const result = await cancelProcess("reviewer", lockPaths.reviewer, force);
191
+ results.push(result);
192
+ }
193
+ return results;
194
+ }
195
+ /**
196
+ * Cancel command implementation
197
+ */
198
+ export function cancelCommand(program) {
199
+ program
200
+ .command("cancel")
201
+ .description("Cancel running executor or reviewer processes")
202
+ .option("-t, --type <type>", "Process type to cancel: 'run', 'review', or 'all'", "all")
203
+ .option("-f, --force", "Skip confirmation prompts")
204
+ .action(async (options) => {
205
+ try {
206
+ // Validate type option
207
+ const validTypes = ["run", "review", "all"];
208
+ if (!validTypes.includes(options.type)) {
209
+ uiError(`Invalid type '${options.type}'. Must be one of: ${validTypes.join(", ")}`);
210
+ process.exit(1);
211
+ }
212
+ const cancelOptions = {
213
+ type: options.type,
214
+ force: options.force,
215
+ };
216
+ const projectDir = process.cwd();
217
+ const results = await performCancel(projectDir, cancelOptions);
218
+ // Output results
219
+ for (const result of results) {
220
+ if (result.success) {
221
+ success(result.message);
222
+ }
223
+ else {
224
+ uiError(result.message);
225
+ }
226
+ }
227
+ // Exit with error code if any cancel failed
228
+ const hasFailure = results.some((r) => !r.success);
229
+ if (hasFailure) {
230
+ process.exit(1);
231
+ }
232
+ }
233
+ catch (err) {
234
+ uiError(`Error cancelling processes: ${err instanceof Error ? err.message : String(err)}`);
235
+ process.exit(1);
236
+ }
237
+ });
238
+ }
239
+ //# sourceMappingURL=cancel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cancel.js","sourceRoot":"","sources":["../../src/commands/cancel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * PRDs command for Night Watch CLI
3
+ * Lists all PRDs with their status (ready/blocked/in-progress/done) and dependencies
4
+ */
5
+ import { Command } from "commander";
6
+ export interface IPrdsOptions {
7
+ json?: boolean;
8
+ }
9
+ /**
10
+ * PRDs command implementation
11
+ */
12
+ export declare function prdsCommand(program: Command): void;
13
+ //# sourceMappingURL=prds.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prds.d.ts","sourceRoot":"","sources":["../../src/commands/prds.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAqHD;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiGlD"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * PRDs command for Night Watch CLI
3
+ * Lists all PRDs with their status (ready/blocked/in-progress/done) and dependencies
4
+ */
5
+ import chalk from "chalk";
6
+ import { loadConfig } from "../config.js";
7
+ import { collectPrdInfo, } from "../utils/status-data.js";
8
+ import { createTable, dim, header, } from "../utils/ui.js";
9
+ import { execSync } from "child_process";
10
+ /**
11
+ * Get open PR branch names using gh CLI
12
+ */
13
+ function getOpenPrBranches(projectDir) {
14
+ try {
15
+ execSync("git rev-parse --git-dir", {
16
+ cwd: projectDir,
17
+ encoding: "utf-8",
18
+ stdio: ["pipe", "pipe", "pipe"],
19
+ });
20
+ }
21
+ catch {
22
+ return new Set();
23
+ }
24
+ try {
25
+ execSync("which gh", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
26
+ }
27
+ catch {
28
+ return new Set();
29
+ }
30
+ try {
31
+ const output = execSync("gh pr list --state open --json headRefName", {
32
+ cwd: projectDir,
33
+ encoding: "utf-8",
34
+ stdio: ["pipe", "pipe", "pipe"],
35
+ });
36
+ const prs = JSON.parse(output);
37
+ return new Set(prs.map((pr) => pr.headRefName));
38
+ }
39
+ catch {
40
+ return new Set();
41
+ }
42
+ }
43
+ /**
44
+ * Derive a branch name from a PRD name
45
+ * Converts "01-feature-name.md" or "01-feature-name" to potential branch patterns
46
+ */
47
+ function deriveBranchPatterns(prdName, branchPrefix) {
48
+ // Remove .md extension if present
49
+ const baseName = prdName.replace(/\.md$/, "");
50
+ // Common patterns:
51
+ // 1. night-watch/01-feature-name
52
+ // 2. feat/01-feature-name
53
+ // 3. feature/01-feature-name
54
+ return [
55
+ `${branchPrefix}${baseName}`,
56
+ `feat/${baseName}`,
57
+ `feature/${baseName}`,
58
+ ];
59
+ }
60
+ /**
61
+ * Find matching PR for a PRD
62
+ */
63
+ function findMatchingPr(prdName, openPrBranches, branchPrefix) {
64
+ const patterns = deriveBranchPatterns(prdName, branchPrefix);
65
+ for (const pattern of patterns) {
66
+ // Check for exact match
67
+ if (openPrBranches.has(pattern)) {
68
+ return pattern;
69
+ }
70
+ // Check for partial match (branch might have additional suffix)
71
+ for (const branch of openPrBranches) {
72
+ if (branch === pattern || branch.startsWith(`${pattern}-`) || branch.startsWith(`${pattern}/`)) {
73
+ return branch;
74
+ }
75
+ }
76
+ }
77
+ return null;
78
+ }
79
+ /**
80
+ * Format status with color
81
+ */
82
+ function formatStatus(status) {
83
+ switch (status) {
84
+ case "ready":
85
+ return chalk.green("ready");
86
+ case "blocked":
87
+ return chalk.yellow("blocked");
88
+ case "in-progress":
89
+ return chalk.cyan("in-progress");
90
+ case "done":
91
+ return chalk.dim("done");
92
+ default:
93
+ return status;
94
+ }
95
+ }
96
+ /**
97
+ * Format dependencies list
98
+ */
99
+ function formatDependencies(dependencies, unmetDependencies) {
100
+ if (dependencies.length === 0) {
101
+ return chalk.dim("-");
102
+ }
103
+ return dependencies.map((dep) => {
104
+ const isUnmet = unmetDependencies.includes(dep);
105
+ return isUnmet ? chalk.red(dep) : chalk.green(dep);
106
+ }).join(", ");
107
+ }
108
+ /**
109
+ * PRDs command implementation
110
+ */
111
+ export function prdsCommand(program) {
112
+ program
113
+ .command("prds")
114
+ .description("List all PRDs with their status and dependencies")
115
+ .option("--json", "Output as JSON")
116
+ .action(async (options) => {
117
+ try {
118
+ const projectDir = process.cwd();
119
+ const config = loadConfig(projectDir);
120
+ // Collect PRD info using existing utility
121
+ const prds = collectPrdInfo(projectDir, config.prdDir, config.maxRuntime);
122
+ // Get open PR branches for in-progress detection
123
+ const openPrBranches = getOpenPrBranches(projectDir);
124
+ // Filter out summary file and update in-progress status based on open PRs
125
+ const filteredPrds = prds.filter((prd) => !prd.name.toLowerCase().includes("night-watch-summary"));
126
+ // Update status based on open PRs
127
+ for (const prd of filteredPrds) {
128
+ if (prd.status !== "done") {
129
+ const matchingPr = findMatchingPr(prd.name, openPrBranches, config.branchPrefix);
130
+ if (matchingPr) {
131
+ prd.status = "in-progress";
132
+ prd.prBranch = matchingPr;
133
+ }
134
+ }
135
+ }
136
+ // Sort: ready first, then blocked, then in-progress, then done
137
+ const statusOrder = {
138
+ "ready": 0,
139
+ "blocked": 1,
140
+ "in-progress": 2,
141
+ "done": 3,
142
+ };
143
+ filteredPrds.sort((a, b) => statusOrder[a.status] - statusOrder[b.status]);
144
+ // Output as JSON if requested
145
+ if (options.json) {
146
+ const jsonOutput = filteredPrds.map((prd) => ({
147
+ name: prd.name,
148
+ status: prd.status,
149
+ dependencies: prd.dependencies,
150
+ unmetDependencies: prd.unmetDependencies,
151
+ pr: prd.prBranch || null,
152
+ }));
153
+ console.log(JSON.stringify(jsonOutput, null, 2));
154
+ return;
155
+ }
156
+ // Display header
157
+ header("PRD Status");
158
+ if (filteredPrds.length === 0) {
159
+ dim("No PRDs found.");
160
+ return;
161
+ }
162
+ // Create and populate table
163
+ const table = createTable({
164
+ head: ["Name", "Status", "Dependencies", "PR"],
165
+ colWidths: [35, 12, 40, 30],
166
+ });
167
+ for (const prd of filteredPrds) {
168
+ const prBranch = prd.prBranch;
169
+ table.push([
170
+ prd.status === "done" ? chalk.dim(prd.name) : prd.name,
171
+ formatStatus(prd.status),
172
+ formatDependencies(prd.dependencies, prd.unmetDependencies),
173
+ prBranch ? chalk.cyan(prBranch) : chalk.dim("-"),
174
+ ]);
175
+ }
176
+ console.log(table.toString());
177
+ // Summary counts
178
+ const ready = filteredPrds.filter((p) => p.status === "ready").length;
179
+ const blocked = filteredPrds.filter((p) => p.status === "blocked").length;
180
+ const inProgress = filteredPrds.filter((p) => p.status === "in-progress").length;
181
+ const done = filteredPrds.filter((p) => p.status === "done").length;
182
+ console.log();
183
+ dim(` Ready: ${ready} | Blocked: ${blocked} | In Progress: ${inProgress} | Done: ${done}`);
184
+ console.log();
185
+ }
186
+ catch (error) {
187
+ console.error(`Error listing PRDs: ${error instanceof Error ? error.message : String(error)}`);
188
+ process.exit(1);
189
+ }
190
+ });
191
+ }
192
+ //# sourceMappingURL=prds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prds.js","sourceRoot":"","sources":["../../src/commands/prds.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * PRs command for Night Watch CLI
3
+ * Lists matching PRs with their CI status and review scores
4
+ */
5
+ import { Command } from "commander";
6
+ export interface IPrsOptions {
7
+ json?: boolean;
8
+ }
9
+ /**
10
+ * PRs command implementation
11
+ */
12
+ export declare function prsCommand(program: Command): void;
13
+ //# sourceMappingURL=prs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prs.d.ts","sourceRoot":"","sources":["../../src/commands/prs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA0CD;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmEjD"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * PRs command for Night Watch CLI
3
+ * Lists matching PRs with their CI status and review scores
4
+ */
5
+ import chalk from "chalk";
6
+ import { loadConfig } from "../config.js";
7
+ import { collectPrInfo } from "../utils/status-data.js";
8
+ import { createTable, dim, header, info } from "../utils/ui.js";
9
+ /**
10
+ * Format CI status with color coding
11
+ */
12
+ function formatCiStatus(status) {
13
+ switch (status) {
14
+ case "pass":
15
+ return chalk.green("pass");
16
+ case "fail":
17
+ return chalk.red("fail");
18
+ case "pending":
19
+ return chalk.yellow("pending");
20
+ default:
21
+ return chalk.dim("unknown");
22
+ }
23
+ }
24
+ /**
25
+ * Format review score with color coding
26
+ */
27
+ function formatReviewScore(score) {
28
+ if (score === null) {
29
+ return chalk.dim("-");
30
+ }
31
+ if (score >= 80) {
32
+ return chalk.green(String(score));
33
+ }
34
+ if (score >= 60) {
35
+ return chalk.yellow(String(score));
36
+ }
37
+ return chalk.red(String(score));
38
+ }
39
+ /**
40
+ * PRs command implementation
41
+ */
42
+ export function prsCommand(program) {
43
+ program
44
+ .command("prs")
45
+ .description("List matching PRs with CI status and review scores")
46
+ .option("--json", "Output PRs as JSON")
47
+ .action(async (options) => {
48
+ try {
49
+ const projectDir = process.cwd();
50
+ const config = loadConfig(projectDir);
51
+ const prs = collectPrInfo(projectDir, config.branchPatterns);
52
+ // Output as JSON if requested
53
+ if (options.json) {
54
+ const output = {
55
+ prs,
56
+ count: prs.length,
57
+ };
58
+ console.log(JSON.stringify(output, null, 2));
59
+ return;
60
+ }
61
+ // Print header
62
+ console.log();
63
+ console.log(chalk.bold.cyan("Night Watch PRs"));
64
+ console.log(chalk.dim("-".repeat(40)));
65
+ console.log();
66
+ if (prs.length === 0) {
67
+ info("No open PRs matching configured branch patterns found.");
68
+ dim(`Branch patterns: ${config.branchPatterns.join(", ")}`);
69
+ console.log();
70
+ return;
71
+ }
72
+ header(`Open PRs (${prs.length})`);
73
+ // Create and populate table
74
+ const table = createTable({
75
+ head: ["#", "Title", "Branch", "CI", "Score", "URL"],
76
+ colWidths: [6, 30, 25, 10, 8, 50],
77
+ });
78
+ for (const pr of prs) {
79
+ // Truncate title if too long
80
+ const title = pr.title.length > 27 ? pr.title.substring(0, 24) + "..." : pr.title;
81
+ // Truncate branch if too long
82
+ const branch = pr.branch.length > 22 ? pr.branch.substring(0, 19) + "..." : pr.branch;
83
+ table.push([
84
+ String(pr.number),
85
+ title,
86
+ branch,
87
+ formatCiStatus(pr.ciStatus),
88
+ formatReviewScore(pr.reviewScore),
89
+ pr.url,
90
+ ]);
91
+ }
92
+ console.log(table.toString());
93
+ console.log();
94
+ }
95
+ catch (error) {
96
+ console.error(`Error listing PRs: ${error instanceof Error ? error.message : String(error)}`);
97
+ process.exit(1);
98
+ }
99
+ });
100
+ }
101
+ //# sourceMappingURL=prs.js.map