@jonit-dev/night-watch-cli 1.1.5 → 1.3.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.
Files changed (96) hide show
  1. package/README.md +1 -0
  2. package/dist/cli.js +3 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/dashboard/tab-actions.d.ts +10 -0
  5. package/dist/commands/dashboard/tab-actions.d.ts.map +1 -0
  6. package/dist/commands/dashboard/tab-actions.js +245 -0
  7. package/dist/commands/dashboard/tab-actions.js.map +1 -0
  8. package/dist/commands/dashboard/tab-config.d.ts +21 -0
  9. package/dist/commands/dashboard/tab-config.d.ts.map +1 -0
  10. package/dist/commands/dashboard/tab-config.js +821 -0
  11. package/dist/commands/dashboard/tab-config.js.map +1 -0
  12. package/dist/commands/dashboard/tab-logs.d.ts +10 -0
  13. package/dist/commands/dashboard/tab-logs.d.ts.map +1 -0
  14. package/dist/commands/dashboard/tab-logs.js +178 -0
  15. package/dist/commands/dashboard/tab-logs.js.map +1 -0
  16. package/dist/commands/dashboard/tab-schedules.d.ts +21 -0
  17. package/dist/commands/dashboard/tab-schedules.d.ts.map +1 -0
  18. package/dist/commands/dashboard/tab-schedules.js +304 -0
  19. package/dist/commands/dashboard/tab-schedules.js.map +1 -0
  20. package/dist/commands/dashboard/tab-status.d.ts +32 -0
  21. package/dist/commands/dashboard/tab-status.d.ts.map +1 -0
  22. package/dist/commands/dashboard/tab-status.js +416 -0
  23. package/dist/commands/dashboard/tab-status.js.map +1 -0
  24. package/dist/commands/dashboard/types.d.ts +43 -0
  25. package/dist/commands/dashboard/types.d.ts.map +1 -0
  26. package/dist/commands/dashboard/types.js +5 -0
  27. package/dist/commands/dashboard/types.js.map +1 -0
  28. package/dist/commands/dashboard.d.ts +11 -0
  29. package/dist/commands/dashboard.d.ts.map +1 -0
  30. package/dist/commands/dashboard.js +239 -0
  31. package/dist/commands/dashboard.js.map +1 -0
  32. package/dist/commands/doctor.d.ts +2 -2
  33. package/dist/commands/doctor.d.ts.map +1 -1
  34. package/dist/commands/doctor.js +1 -1
  35. package/dist/commands/doctor.js.map +1 -1
  36. package/dist/commands/init.d.ts.map +1 -1
  37. package/dist/commands/init.js +8 -8
  38. package/dist/commands/init.js.map +1 -1
  39. package/dist/commands/install.d.ts +17 -1
  40. package/dist/commands/install.d.ts.map +1 -1
  41. package/dist/commands/install.js +56 -2
  42. package/dist/commands/install.js.map +1 -1
  43. package/dist/commands/logs.d.ts +1 -1
  44. package/dist/commands/logs.d.ts.map +1 -1
  45. package/dist/commands/logs.js +1 -1
  46. package/dist/commands/logs.js.map +1 -1
  47. package/dist/commands/prd.d.ts +1 -1
  48. package/dist/commands/prd.d.ts.map +1 -1
  49. package/dist/commands/prd.js +2 -2
  50. package/dist/commands/prd.js.map +1 -1
  51. package/dist/commands/review.d.ts +3 -3
  52. package/dist/commands/review.d.ts.map +1 -1
  53. package/dist/commands/review.js +2 -2
  54. package/dist/commands/review.js.map +1 -1
  55. package/dist/commands/run.d.ts +5 -5
  56. package/dist/commands/run.d.ts.map +1 -1
  57. package/dist/commands/run.js +7 -3
  58. package/dist/commands/run.js.map +1 -1
  59. package/dist/commands/status.d.ts +1 -1
  60. package/dist/commands/status.d.ts.map +1 -1
  61. package/dist/commands/status.js +20 -202
  62. package/dist/commands/status.js.map +1 -1
  63. package/dist/commands/uninstall.d.ts +13 -1
  64. package/dist/commands/uninstall.d.ts.map +1 -1
  65. package/dist/commands/uninstall.js +46 -2
  66. package/dist/commands/uninstall.js.map +1 -1
  67. package/dist/config.d.ts.map +1 -1
  68. package/dist/config.js +9 -1
  69. package/dist/config.js.map +1 -1
  70. package/dist/constants.d.ts +3 -2
  71. package/dist/constants.d.ts.map +1 -1
  72. package/dist/constants.js +2 -0
  73. package/dist/constants.js.map +1 -1
  74. package/dist/templates/prd-template.d.ts +2 -2
  75. package/dist/templates/prd-template.d.ts.map +1 -1
  76. package/dist/templates/prd-template.js.map +1 -1
  77. package/dist/types.d.ts +6 -4
  78. package/dist/types.d.ts.map +1 -1
  79. package/dist/utils/config-writer.d.ts +16 -0
  80. package/dist/utils/config-writer.d.ts.map +1 -0
  81. package/dist/utils/config-writer.js +45 -0
  82. package/dist/utils/config-writer.js.map +1 -0
  83. package/dist/utils/crontab.js +1 -1
  84. package/dist/utils/crontab.js.map +1 -1
  85. package/dist/utils/github.d.ts +3 -3
  86. package/dist/utils/github.d.ts.map +1 -1
  87. package/dist/utils/notify.d.ts +8 -8
  88. package/dist/utils/notify.d.ts.map +1 -1
  89. package/dist/utils/notify.js +1 -1
  90. package/dist/utils/notify.js.map +1 -1
  91. package/dist/utils/status-data.d.ts +128 -0
  92. package/dist/utils/status-data.d.ts.map +1 -0
  93. package/dist/utils/status-data.js +403 -0
  94. package/dist/utils/status-data.js.map +1 -0
  95. package/package.json +11 -2
  96. package/scripts/night-watch-helpers.sh +20 -0
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Status data layer for Night Watch CLI
3
+ * Provides data-fetching functions used by both the status command and the dashboard TUI.
4
+ */
5
+ import { INightWatchConfig } from "../types.js";
6
+ /**
7
+ * Information about a single PRD file
8
+ */
9
+ export interface IPrdInfo {
10
+ name: string;
11
+ status: "ready" | "blocked" | "in-progress" | "done";
12
+ dependencies: string[];
13
+ unmetDependencies: string[];
14
+ }
15
+ /**
16
+ * Information about a running process
17
+ */
18
+ export interface IProcessInfo {
19
+ name: string;
20
+ running: boolean;
21
+ pid: number | null;
22
+ }
23
+ /**
24
+ * Information about a pull request
25
+ */
26
+ export interface IPrInfo {
27
+ number: number;
28
+ title: string;
29
+ branch: string;
30
+ ciStatus: "pass" | "fail" | "pending" | "unknown";
31
+ reviewScore: number | null;
32
+ }
33
+ /**
34
+ * Information about a log file
35
+ */
36
+ export interface ILogInfo {
37
+ name: string;
38
+ path: string;
39
+ exists: boolean;
40
+ size: number;
41
+ lastLines: string[];
42
+ }
43
+ /**
44
+ * Complete status snapshot of the project
45
+ */
46
+ export interface IStatusSnapshot {
47
+ projectName: string;
48
+ projectDir: string;
49
+ config: INightWatchConfig;
50
+ prds: IPrdInfo[];
51
+ processes: IProcessInfo[];
52
+ prs: IPrInfo[];
53
+ logs: ILogInfo[];
54
+ crontab: {
55
+ installed: boolean;
56
+ entries: string[];
57
+ };
58
+ timestamp: Date;
59
+ }
60
+ /**
61
+ * Get the project name from directory or package.json
62
+ */
63
+ export declare function getProjectName(projectDir: string): string;
64
+ /**
65
+ * Check if a process with the given PID is running
66
+ */
67
+ export declare function isProcessRunning(pid: number): boolean;
68
+ /**
69
+ * Read PID from lock file and check if process is running
70
+ */
71
+ export declare function checkLockFile(lockPath: string): {
72
+ running: boolean;
73
+ pid: number | null;
74
+ };
75
+ /**
76
+ * Count PRDs in the PRD directory and return counts
77
+ */
78
+ export declare function countPRDs(projectDir: string, prdDir: string, maxRuntime: number): {
79
+ pending: number;
80
+ claimed: number;
81
+ done: number;
82
+ };
83
+ /**
84
+ * Parse dependency references from a PRD file.
85
+ * Looks for a line matching "depends on: `name1`, `name2`" (case-insensitive).
86
+ */
87
+ export declare function parsePrdDependencies(prdPath: string): string[];
88
+ /**
89
+ * Collect PRD info items from the PRD directory
90
+ */
91
+ export declare function collectPrdInfo(projectDir: string, prdDir: string, maxRuntime: number): IPrdInfo[];
92
+ /**
93
+ * Count open PRs on night-watch/ or feat/ branches using gh CLI
94
+ */
95
+ export declare function countOpenPRs(projectDir: string, branchPatterns: string[]): number;
96
+ /**
97
+ * Collect open PR info using gh CLI
98
+ */
99
+ export declare function collectPrInfo(projectDir: string, branchPatterns: string[]): IPrInfo[];
100
+ /**
101
+ * Get last N lines from a log file
102
+ */
103
+ export declare function getLastLogLines(logPath: string, lines: number): string[];
104
+ /**
105
+ * Get log file info
106
+ */
107
+ export declare function getLogInfo(logPath: string, lastLines?: number): {
108
+ path: string;
109
+ lastLines: string[];
110
+ exists: boolean;
111
+ size: number;
112
+ };
113
+ /**
114
+ * Collect log info as ILogInfo items
115
+ */
116
+ export declare function collectLogInfo(projectDir: string): ILogInfo[];
117
+ /**
118
+ * Get crontab information for a project
119
+ */
120
+ export declare function getCrontabInfo(projectName: string, projectDir: string): {
121
+ installed: boolean;
122
+ entries: string[];
123
+ };
124
+ /**
125
+ * Fetch a complete status snapshot for the given project
126
+ */
127
+ export declare function fetchStatusSnapshot(projectDir: string, config: INightWatchConfig): IStatusSnapshot;
128
+ //# sourceMappingURL=status-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-data.d.ts","sourceRoot":"","sources":["../../src/utils/status-data.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGhD;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,CAAC;IACrD,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IAClD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,GAAG,EAAE,OAAO,EAAE,CAAC;IACf,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,OAAO,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACnD,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAczD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAoBxF;AAED;;GAEG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAyDpD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAY9D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,QAAQ,EAAE,CAiFZ;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,CA6BjF;AAuCD;;GAEG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CA8CrF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAYxE;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAAU,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAQtE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,EAAE,CAa7D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAS3C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,iBAAiB,GACxB,eAAe,CA4BjB"}
@@ -0,0 +1,403 @@
1
+ /**
2
+ * Status data layer for Night Watch CLI
3
+ * Provides data-fetching functions used by both the status command and the dashboard TUI.
4
+ */
5
+ import { execSync } from "child_process";
6
+ import * as fs from "fs";
7
+ import * as path from "path";
8
+ import { CLAIM_FILE_EXTENSION, LOCK_FILE_PREFIX, LOG_DIR } from "../constants.js";
9
+ import { generateMarker, getEntries, getProjectEntries } from "./crontab.js";
10
+ /**
11
+ * Get the project name from directory or package.json
12
+ */
13
+ export function getProjectName(projectDir) {
14
+ const packageJsonPath = path.join(projectDir, "package.json");
15
+ if (fs.existsSync(packageJsonPath)) {
16
+ try {
17
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
18
+ if (packageJson.name) {
19
+ return packageJson.name;
20
+ }
21
+ }
22
+ catch {
23
+ // Ignore parse errors
24
+ }
25
+ }
26
+ return path.basename(projectDir);
27
+ }
28
+ /**
29
+ * Check if a process with the given PID is running
30
+ */
31
+ export function isProcessRunning(pid) {
32
+ try {
33
+ process.kill(pid, 0);
34
+ return true;
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ }
40
+ /**
41
+ * Read PID from lock file and check if process is running
42
+ */
43
+ export function checkLockFile(lockPath) {
44
+ if (!fs.existsSync(lockPath)) {
45
+ return { running: false, pid: null };
46
+ }
47
+ try {
48
+ const pidStr = fs.readFileSync(lockPath, "utf-8").trim();
49
+ const pid = parseInt(pidStr, 10);
50
+ if (isNaN(pid)) {
51
+ return { running: false, pid: null };
52
+ }
53
+ return {
54
+ running: isProcessRunning(pid),
55
+ pid,
56
+ };
57
+ }
58
+ catch {
59
+ return { running: false, pid: null };
60
+ }
61
+ }
62
+ /**
63
+ * Count PRDs in the PRD directory and return counts
64
+ */
65
+ export function countPRDs(projectDir, prdDir, maxRuntime) {
66
+ const fullPrdPath = path.join(projectDir, prdDir);
67
+ if (!fs.existsSync(fullPrdPath)) {
68
+ return { pending: 0, claimed: 0, done: 0 };
69
+ }
70
+ let pending = 0;
71
+ let claimed = 0;
72
+ let done = 0;
73
+ const countInDir = (dir) => {
74
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
75
+ for (const entry of entries) {
76
+ const fullPath = path.join(dir, entry.name);
77
+ if (entry.isDirectory()) {
78
+ if (entry.name === "done") {
79
+ try {
80
+ const doneEntries = fs.readdirSync(fullPath);
81
+ done += doneEntries.filter((e) => e.endsWith(".md")).length;
82
+ }
83
+ catch {
84
+ // Ignore errors
85
+ }
86
+ }
87
+ else {
88
+ countInDir(fullPath);
89
+ }
90
+ }
91
+ else if (entry.name.endsWith(".md")) {
92
+ const claimPath = path.join(dir, entry.name + CLAIM_FILE_EXTENSION);
93
+ if (fs.existsSync(claimPath)) {
94
+ try {
95
+ const content = fs.readFileSync(claimPath, "utf-8");
96
+ const claimData = JSON.parse(content);
97
+ const age = Math.floor(Date.now() / 1000) - claimData.timestamp;
98
+ if (age < maxRuntime) {
99
+ claimed++;
100
+ }
101
+ else {
102
+ pending++;
103
+ }
104
+ }
105
+ catch {
106
+ pending++;
107
+ }
108
+ }
109
+ else {
110
+ pending++;
111
+ }
112
+ }
113
+ }
114
+ };
115
+ try {
116
+ countInDir(fullPrdPath);
117
+ }
118
+ catch {
119
+ // Ignore errors
120
+ }
121
+ return { pending, claimed, done };
122
+ }
123
+ /**
124
+ * Parse dependency references from a PRD file.
125
+ * Looks for a line matching "depends on: `name1`, `name2`" (case-insensitive).
126
+ */
127
+ export function parsePrdDependencies(prdPath) {
128
+ try {
129
+ const content = fs.readFileSync(prdPath, "utf-8");
130
+ const match = content.match(/depends on[:\s]*([^\n]+)/i);
131
+ if (!match)
132
+ return [];
133
+ return match[1]
134
+ .split(",")
135
+ .map((d) => d.trim().replace(/`/g, ""))
136
+ .filter((d) => d.length > 0);
137
+ }
138
+ catch {
139
+ return [];
140
+ }
141
+ }
142
+ /**
143
+ * Collect PRD info items from the PRD directory
144
+ */
145
+ export function collectPrdInfo(projectDir, prdDir, maxRuntime) {
146
+ const fullPrdPath = path.join(projectDir, prdDir);
147
+ const prds = [];
148
+ if (!fs.existsSync(fullPrdPath)) {
149
+ return prds;
150
+ }
151
+ const collectInDir = (dir) => {
152
+ let entries;
153
+ try {
154
+ entries = fs.readdirSync(dir, { withFileTypes: true });
155
+ }
156
+ catch {
157
+ return;
158
+ }
159
+ for (const entry of entries) {
160
+ const fullPath = path.join(dir, entry.name);
161
+ if (entry.isDirectory()) {
162
+ if (entry.name === "done") {
163
+ try {
164
+ const doneEntries = fs.readdirSync(fullPath);
165
+ for (const doneEntry of doneEntries) {
166
+ if (doneEntry.endsWith(".md")) {
167
+ prds.push({
168
+ name: doneEntry.replace(/\.md$/, ""),
169
+ status: "done",
170
+ dependencies: [],
171
+ unmetDependencies: [],
172
+ });
173
+ }
174
+ }
175
+ }
176
+ catch {
177
+ // Ignore errors
178
+ }
179
+ }
180
+ else {
181
+ collectInDir(fullPath);
182
+ }
183
+ }
184
+ else if (entry.name.endsWith(".md")) {
185
+ const claimPath = path.join(dir, entry.name + CLAIM_FILE_EXTENSION);
186
+ let status = "ready";
187
+ if (fs.existsSync(claimPath)) {
188
+ try {
189
+ const content = fs.readFileSync(claimPath, "utf-8");
190
+ const claimData = JSON.parse(content);
191
+ const age = Math.floor(Date.now() / 1000) - claimData.timestamp;
192
+ status = age < maxRuntime ? "in-progress" : "ready";
193
+ }
194
+ catch {
195
+ status = "ready";
196
+ }
197
+ }
198
+ const dependencies = parsePrdDependencies(fullPath);
199
+ prds.push({
200
+ name: entry.name.replace(/\.md$/, ""),
201
+ status,
202
+ dependencies,
203
+ unmetDependencies: [],
204
+ });
205
+ }
206
+ }
207
+ };
208
+ collectInDir(fullPrdPath);
209
+ // Compute unmet dependencies: a dependency is unmet if there's no "done" PRD with that name
210
+ const doneNames = new Set(prds.filter((p) => p.status === "done").map((p) => p.name));
211
+ for (const prd of prds) {
212
+ if (prd.dependencies.length > 0) {
213
+ prd.unmetDependencies = prd.dependencies.filter((dep) => !doneNames.has(dep));
214
+ // Mark PRDs with unmet dependencies as blocked (unless already done or in-progress)
215
+ if (prd.unmetDependencies.length > 0 && prd.status === "ready") {
216
+ prd.status = "blocked";
217
+ }
218
+ }
219
+ }
220
+ return prds;
221
+ }
222
+ /**
223
+ * Count open PRs on night-watch/ or feat/ branches using gh CLI
224
+ */
225
+ export function countOpenPRs(projectDir, branchPatterns) {
226
+ try {
227
+ execSync("git rev-parse --git-dir", {
228
+ cwd: projectDir,
229
+ encoding: "utf-8",
230
+ stdio: ["pipe", "pipe", "pipe"],
231
+ });
232
+ try {
233
+ execSync("which gh", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
234
+ }
235
+ catch {
236
+ return 0;
237
+ }
238
+ const output = execSync("gh pr list --state open --json headRefName,number", {
239
+ cwd: projectDir,
240
+ encoding: "utf-8",
241
+ stdio: ["pipe", "pipe", "pipe"],
242
+ });
243
+ const prs = JSON.parse(output);
244
+ const matchingPRs = prs.filter((pr) => branchPatterns.some((pattern) => pr.headRefName.startsWith(pattern)));
245
+ return matchingPRs.length;
246
+ }
247
+ catch {
248
+ return 0;
249
+ }
250
+ }
251
+ /**
252
+ * Derive CI status from gh statusCheckRollup data
253
+ */
254
+ function deriveCiStatus(checks) {
255
+ if (!checks || checks.length === 0)
256
+ return "unknown";
257
+ const hasFailure = checks.some((c) => c.conclusion === "FAILURE" || c.conclusion === "ERROR" || c.conclusion === "CANCELLED");
258
+ if (hasFailure)
259
+ return "fail";
260
+ const allComplete = checks.every((c) => c.state === "COMPLETED");
261
+ if (allComplete)
262
+ return "pass";
263
+ return "pending";
264
+ }
265
+ /**
266
+ * Derive review score from gh reviewDecision field
267
+ * Maps GitHub review decisions to a numeric score (0-100)
268
+ */
269
+ function deriveReviewScore(reviewDecision) {
270
+ if (!reviewDecision)
271
+ return null;
272
+ switch (reviewDecision) {
273
+ case "APPROVED":
274
+ return 100;
275
+ case "CHANGES_REQUESTED":
276
+ return 0;
277
+ case "REVIEW_REQUIRED":
278
+ return null;
279
+ default:
280
+ return null;
281
+ }
282
+ }
283
+ /**
284
+ * Collect open PR info using gh CLI
285
+ */
286
+ export function collectPrInfo(projectDir, branchPatterns) {
287
+ try {
288
+ execSync("git rev-parse --git-dir", {
289
+ cwd: projectDir,
290
+ encoding: "utf-8",
291
+ stdio: ["pipe", "pipe", "pipe"],
292
+ });
293
+ try {
294
+ execSync("which gh", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
295
+ }
296
+ catch {
297
+ return [];
298
+ }
299
+ const output = execSync("gh pr list --state open --json headRefName,number,title,statusCheckRollup,reviewDecision", {
300
+ cwd: projectDir,
301
+ encoding: "utf-8",
302
+ stdio: ["pipe", "pipe", "pipe"],
303
+ });
304
+ const prs = JSON.parse(output);
305
+ return prs
306
+ .filter((pr) => branchPatterns.some((pattern) => pr.headRefName.startsWith(pattern)))
307
+ .map((pr) => ({
308
+ number: pr.number,
309
+ title: pr.title,
310
+ branch: pr.headRefName,
311
+ ciStatus: deriveCiStatus(pr.statusCheckRollup),
312
+ reviewScore: deriveReviewScore(pr.reviewDecision),
313
+ }));
314
+ }
315
+ catch {
316
+ return [];
317
+ }
318
+ }
319
+ /**
320
+ * Get last N lines from a log file
321
+ */
322
+ export function getLastLogLines(logPath, lines) {
323
+ if (!fs.existsSync(logPath)) {
324
+ return [];
325
+ }
326
+ try {
327
+ const content = fs.readFileSync(logPath, "utf-8");
328
+ const allLines = content.trim().split("\n");
329
+ return allLines.slice(-lines);
330
+ }
331
+ catch {
332
+ return [];
333
+ }
334
+ }
335
+ /**
336
+ * Get log file info
337
+ */
338
+ export function getLogInfo(logPath, lastLines = 5) {
339
+ const exists = fs.existsSync(logPath);
340
+ return {
341
+ path: logPath,
342
+ lastLines: exists ? getLastLogLines(logPath, lastLines) : [],
343
+ exists,
344
+ size: exists ? fs.statSync(logPath).size : 0,
345
+ };
346
+ }
347
+ /**
348
+ * Collect log info as ILogInfo items
349
+ */
350
+ export function collectLogInfo(projectDir) {
351
+ const logNames = ["executor", "reviewer"];
352
+ return logNames.map((name) => {
353
+ const logPath = path.join(projectDir, LOG_DIR, `${name}.log`);
354
+ const exists = fs.existsSync(logPath);
355
+ return {
356
+ name,
357
+ path: logPath,
358
+ exists,
359
+ size: exists ? fs.statSync(logPath).size : 0,
360
+ lastLines: exists ? getLastLogLines(logPath, 5) : [],
361
+ };
362
+ });
363
+ }
364
+ /**
365
+ * Get crontab information for a project
366
+ */
367
+ export function getCrontabInfo(projectName, projectDir) {
368
+ const marker = generateMarker(projectName);
369
+ const crontabEntries = Array.from(new Set([...getEntries(marker), ...getProjectEntries(projectDir)]));
370
+ return {
371
+ installed: crontabEntries.length > 0,
372
+ entries: crontabEntries,
373
+ };
374
+ }
375
+ /**
376
+ * Fetch a complete status snapshot for the given project
377
+ */
378
+ export function fetchStatusSnapshot(projectDir, config) {
379
+ const projectName = getProjectName(projectDir);
380
+ const lockProjectName = path.basename(projectDir);
381
+ const executorLock = checkLockFile(`${LOCK_FILE_PREFIX}${lockProjectName}.lock`);
382
+ const reviewerLock = checkLockFile(`${LOCK_FILE_PREFIX}pr-reviewer-${lockProjectName}.lock`);
383
+ const processes = [
384
+ { name: "executor", running: executorLock.running, pid: executorLock.pid },
385
+ { name: "reviewer", running: reviewerLock.running, pid: reviewerLock.pid },
386
+ ];
387
+ const prds = collectPrdInfo(projectDir, config.prdDir, config.maxRuntime);
388
+ const prs = collectPrInfo(projectDir, config.branchPatterns);
389
+ const logs = collectLogInfo(projectDir);
390
+ const crontab = getCrontabInfo(projectName, projectDir);
391
+ return {
392
+ projectName,
393
+ projectDir,
394
+ config,
395
+ prds,
396
+ processes,
397
+ prs,
398
+ logs,
399
+ crontab,
400
+ timestamp: new Date(),
401
+ };
402
+ }
403
+ //# sourceMappingURL=status-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-data.js","sourceRoot":"","sources":["../../src/utils/status-data.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jonit-dev/night-watch-cli",
3
- "version": "1.1.5",
3
+ "version": "1.3.0",
4
4
  "description": "Autonomous PRD execution using AI Provider CLIs + cron",
5
5
  "type": "module",
6
6
  "bin": {
@@ -18,7 +18,10 @@
18
18
  "test": "vitest run",
19
19
  "dev": "tsx src/cli.ts",
20
20
  "prepublishOnly": "npm run build && npm test",
21
- "publish:npm": "npm publish --access public"
21
+ "publish:npm": "npm publish --access public",
22
+ "lint": "eslint src/",
23
+ "verify": "tsc --noEmit && eslint src/",
24
+ "local": "tsc && yarn link"
22
25
  },
23
26
  "files": [
24
27
  "dist/",
@@ -47,15 +50,21 @@
47
50
  "url": "https://github.com/jonit-dev/night-watch-cli/issues"
48
51
  },
49
52
  "dependencies": {
53
+ "blessed": "^0.1.81",
50
54
  "chalk": "^5.6.2",
51
55
  "cli-table3": "^0.6.5",
52
56
  "commander": "^12.0.0",
57
+ "cronstrue": "^3.12.0",
53
58
  "ora": "^9.3.0"
54
59
  },
55
60
  "devDependencies": {
61
+ "@eslint/js": "^10.0.1",
62
+ "@types/blessed": "^0.1.27",
56
63
  "@types/node": "^20.11.0",
64
+ "eslint": "^10.0.0",
57
65
  "tsx": "^4.7.0",
58
66
  "typescript": "^5.3.0",
67
+ "typescript-eslint": "^8.56.0",
59
68
  "vitest": "^1.2.0"
60
69
  },
61
70
  "engines": {
@@ -176,6 +176,26 @@ find_eligible_prd() {
176
176
  return 0
177
177
  fi
178
178
 
179
+ # Apply priority ordering if NW_PRD_PRIORITY is set (colon-separated PRD names)
180
+ if [ -n "${NW_PRD_PRIORITY:-}" ]; then
181
+ local ordered=""
182
+ IFS=':' read -ra prio_list <<< "${NW_PRD_PRIORITY}"
183
+ for pname in "${prio_list[@]}"; do
184
+ local match
185
+ match=$(echo "${prd_files}" | grep "/${pname}\.md$" || true)
186
+ if [ -n "${match}" ]; then
187
+ ordered="${ordered}${match}"$'\n'
188
+ fi
189
+ done
190
+ # Append remaining files not in priority list
191
+ while IFS= read -r pf; do
192
+ if [ -n "${pf}" ] && ! echo "${ordered}" | grep -qF "${pf}"; then
193
+ ordered="${ordered}${pf}"$'\n'
194
+ fi
195
+ done <<< "${prd_files}"
196
+ prd_files=$(echo "${ordered}" | sed '/^$/d')
197
+ fi
198
+
179
199
  local open_branches
180
200
  open_branches=$(gh pr list --state open --json headRefName --jq '.[].headRefName' 2>/dev/null || echo "")
181
201