@jonit-dev/night-watch-cli 1.2.0 → 1.4.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/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/dashboard/tab-actions.d.ts +10 -0
- package/dist/commands/dashboard/tab-actions.d.ts.map +1 -0
- package/dist/commands/dashboard/tab-actions.js +245 -0
- package/dist/commands/dashboard/tab-actions.js.map +1 -0
- package/dist/commands/dashboard/tab-config.d.ts +21 -0
- package/dist/commands/dashboard/tab-config.d.ts.map +1 -0
- package/dist/commands/dashboard/tab-config.js +821 -0
- package/dist/commands/dashboard/tab-config.js.map +1 -0
- package/dist/commands/dashboard/tab-logs.d.ts +10 -0
- package/dist/commands/dashboard/tab-logs.d.ts.map +1 -0
- package/dist/commands/dashboard/tab-logs.js +178 -0
- package/dist/commands/dashboard/tab-logs.js.map +1 -0
- package/dist/commands/dashboard/tab-schedules.d.ts +21 -0
- package/dist/commands/dashboard/tab-schedules.d.ts.map +1 -0
- package/dist/commands/dashboard/tab-schedules.js +304 -0
- package/dist/commands/dashboard/tab-schedules.js.map +1 -0
- package/dist/commands/dashboard/tab-status.d.ts +32 -0
- package/dist/commands/dashboard/tab-status.d.ts.map +1 -0
- package/dist/commands/dashboard/tab-status.js +416 -0
- package/dist/commands/dashboard/tab-status.js.map +1 -0
- package/dist/commands/dashboard/types.d.ts +43 -0
- package/dist/commands/dashboard/types.d.ts.map +1 -0
- package/dist/commands/dashboard/types.js +5 -0
- package/dist/commands/dashboard/types.js.map +1 -0
- package/dist/commands/dashboard.d.ts +2 -20
- package/dist/commands/dashboard.d.ts.map +1 -1
- package/dist/commands/dashboard.js +166 -224
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +21 -10
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install.d.ts +16 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +54 -0
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +4 -0
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/serve.d.ts +7 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +27 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/uninstall.d.ts +12 -0
- package/dist/commands/uninstall.d.ts.map +1 -1
- package/dist/commands/uninstall.js +44 -0
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +5 -0
- package/dist/constants.js.map +1 -1
- package/dist/server/index.d.ts +23 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +470 -0
- package/dist/server/index.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/checks.d.ts +55 -0
- package/dist/utils/checks.d.ts.map +1 -0
- package/dist/utils/checks.js +246 -0
- package/dist/utils/checks.js.map +1 -0
- package/dist/utils/config-writer.d.ts +16 -0
- package/dist/utils/config-writer.d.ts.map +1 -0
- package/dist/utils/config-writer.js +45 -0
- package/dist/utils/config-writer.js.map +1 -0
- package/dist/utils/registry.d.ts +39 -0
- package/dist/utils/registry.d.ts.map +1 -0
- package/dist/utils/registry.js +97 -0
- package/dist/utils/registry.js.map +1 -0
- package/package.json +13 -3
- package/scripts/night-watch-helpers.sh +20 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared validation utilities for Night Watch CLI
|
|
3
|
+
* Used by init, doctor, and other commands that need to verify environment
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import { execSync } from "child_process";
|
|
8
|
+
import { CONFIG_FILE_NAME, LOG_DIR, VALID_PROVIDERS } from "../constants.js";
|
|
9
|
+
/**
|
|
10
|
+
* Check if directory is a git repository
|
|
11
|
+
*/
|
|
12
|
+
export function checkGitRepo(cwd) {
|
|
13
|
+
const isRepo = fs.existsSync(path.join(cwd, ".git"));
|
|
14
|
+
return {
|
|
15
|
+
passed: isRepo,
|
|
16
|
+
message: isRepo ? "Git repository found" : "Not a git repository",
|
|
17
|
+
fixable: false,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Check if GitHub CLI is authenticated
|
|
22
|
+
*/
|
|
23
|
+
export function checkGhCli() {
|
|
24
|
+
try {
|
|
25
|
+
execSync("gh auth status", {
|
|
26
|
+
encoding: "utf-8",
|
|
27
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
28
|
+
});
|
|
29
|
+
return {
|
|
30
|
+
passed: true,
|
|
31
|
+
message: "GitHub CLI authenticated",
|
|
32
|
+
fixable: false,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return {
|
|
37
|
+
passed: false,
|
|
38
|
+
message: "GitHub CLI not authenticated (run: gh auth login)",
|
|
39
|
+
fixable: false,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if a specific provider CLI is available
|
|
45
|
+
*/
|
|
46
|
+
export function checkProviderCli(provider) {
|
|
47
|
+
try {
|
|
48
|
+
execSync(`which ${provider}`, {
|
|
49
|
+
encoding: "utf-8",
|
|
50
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
51
|
+
});
|
|
52
|
+
return {
|
|
53
|
+
passed: true,
|
|
54
|
+
message: `Provider CLI found: ${provider}`,
|
|
55
|
+
fixable: false,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return {
|
|
60
|
+
passed: false,
|
|
61
|
+
message: `Provider CLI not found: ${provider}`,
|
|
62
|
+
fixable: false,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Detect which AI provider CLIs are installed
|
|
68
|
+
*/
|
|
69
|
+
export function detectProviders() {
|
|
70
|
+
const providers = [];
|
|
71
|
+
for (const provider of VALID_PROVIDERS) {
|
|
72
|
+
try {
|
|
73
|
+
execSync(`which ${provider}`, {
|
|
74
|
+
encoding: "utf-8",
|
|
75
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
76
|
+
});
|
|
77
|
+
providers.push(provider);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Provider not available
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return providers;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Check if Node.js version meets minimum requirement
|
|
87
|
+
*/
|
|
88
|
+
export function checkNodeVersion(minMajor) {
|
|
89
|
+
const nodeVersion = process.version;
|
|
90
|
+
const match = nodeVersion.match(/^v?(\d+)/);
|
|
91
|
+
if (!match) {
|
|
92
|
+
return {
|
|
93
|
+
passed: false,
|
|
94
|
+
message: `Could not determine Node.js version (got: ${nodeVersion})`,
|
|
95
|
+
fixable: false,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const major = parseInt(match[1], 10);
|
|
99
|
+
const passed = major >= minMajor;
|
|
100
|
+
return {
|
|
101
|
+
passed,
|
|
102
|
+
message: passed
|
|
103
|
+
? `Node.js version ${nodeVersion} (>= ${minMajor}.0.0)`
|
|
104
|
+
: `Node.js version ${nodeVersion} is too old (minimum: ${minMajor}.0.0)`,
|
|
105
|
+
fixable: false,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check if config file exists and is valid JSON
|
|
110
|
+
*/
|
|
111
|
+
export function checkConfigFile(projectDir) {
|
|
112
|
+
const configPath = path.join(projectDir, CONFIG_FILE_NAME);
|
|
113
|
+
if (!fs.existsSync(configPath)) {
|
|
114
|
+
return {
|
|
115
|
+
passed: false,
|
|
116
|
+
message: `Config file not found: ${CONFIG_FILE_NAME} (run: night-watch init)`,
|
|
117
|
+
fixable: false,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
122
|
+
JSON.parse(content);
|
|
123
|
+
return {
|
|
124
|
+
passed: true,
|
|
125
|
+
message: `Config file valid: ${CONFIG_FILE_NAME}`,
|
|
126
|
+
fixable: false,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
131
|
+
return {
|
|
132
|
+
passed: false,
|
|
133
|
+
message: `Config file has invalid JSON: ${errorMsg}`,
|
|
134
|
+
fixable: false,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Check if PRD directory exists
|
|
140
|
+
*/
|
|
141
|
+
export function checkPrdDirectory(projectDir, prdDir) {
|
|
142
|
+
const prdPath = path.join(projectDir, prdDir);
|
|
143
|
+
if (!fs.existsSync(prdPath)) {
|
|
144
|
+
return {
|
|
145
|
+
passed: false,
|
|
146
|
+
message: `PRD directory not found: ${prdDir}`,
|
|
147
|
+
fixable: true,
|
|
148
|
+
fix: () => {
|
|
149
|
+
fs.mkdirSync(prdPath, { recursive: true });
|
|
150
|
+
// Also create the done subdirectory
|
|
151
|
+
fs.mkdirSync(path.join(prdPath, "done"), { recursive: true });
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// Count PRD files (exclude summary and files in done/)
|
|
156
|
+
const prds = fs
|
|
157
|
+
.readdirSync(prdPath)
|
|
158
|
+
.filter((f) => f.endsWith(".md") && f !== "NIGHT-WATCH-SUMMARY.md");
|
|
159
|
+
return {
|
|
160
|
+
passed: true,
|
|
161
|
+
message: `PRD directory found: ${prdDir} (${prds.length} PRDs)`,
|
|
162
|
+
fixable: false,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Check if logs directory exists
|
|
167
|
+
*/
|
|
168
|
+
export function checkLogsDirectory(projectDir) {
|
|
169
|
+
const logsPath = path.join(projectDir, LOG_DIR);
|
|
170
|
+
if (!fs.existsSync(logsPath)) {
|
|
171
|
+
return {
|
|
172
|
+
passed: false,
|
|
173
|
+
message: `Logs directory not found: ${LOG_DIR}`,
|
|
174
|
+
fixable: true,
|
|
175
|
+
fix: () => {
|
|
176
|
+
fs.mkdirSync(logsPath, { recursive: true });
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
passed: true,
|
|
182
|
+
message: `Logs directory found: ${LOG_DIR}`,
|
|
183
|
+
fixable: false,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Check if crontab is accessible
|
|
188
|
+
*/
|
|
189
|
+
export function checkCrontabAccess() {
|
|
190
|
+
try {
|
|
191
|
+
execSync("crontab -l", {
|
|
192
|
+
encoding: "utf-8",
|
|
193
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
194
|
+
});
|
|
195
|
+
return {
|
|
196
|
+
passed: true,
|
|
197
|
+
message: "Crontab accessible",
|
|
198
|
+
fixable: false,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
// crontab -l returns error if no crontab exists, but that's still "accessible"
|
|
203
|
+
// We check if the error is about access or just "no crontab"
|
|
204
|
+
return {
|
|
205
|
+
passed: true,
|
|
206
|
+
message: "Crontab accessible (empty)",
|
|
207
|
+
fixable: false,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Run all environment checks and return results
|
|
213
|
+
*/
|
|
214
|
+
export function runAllChecks(projectDir, prdDir) {
|
|
215
|
+
const results = [];
|
|
216
|
+
// Check Node version
|
|
217
|
+
results.push(checkNodeVersion(18));
|
|
218
|
+
// Check git repo
|
|
219
|
+
results.push(checkGitRepo(projectDir));
|
|
220
|
+
// Check GitHub CLI
|
|
221
|
+
results.push(checkGhCli());
|
|
222
|
+
// Check provider CLIs
|
|
223
|
+
const providers = detectProviders();
|
|
224
|
+
if (providers.length === 0) {
|
|
225
|
+
results.push({
|
|
226
|
+
passed: false,
|
|
227
|
+
message: "No AI provider CLI found (install claude or codex)",
|
|
228
|
+
fixable: false,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
for (const provider of providers) {
|
|
233
|
+
results.push(checkProviderCli(provider));
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// Check config file
|
|
237
|
+
results.push(checkConfigFile(projectDir));
|
|
238
|
+
// Check PRD directory
|
|
239
|
+
results.push(checkPrdDirectory(projectDir, prdDir));
|
|
240
|
+
// Check logs directory
|
|
241
|
+
results.push(checkLogsDirectory(projectDir));
|
|
242
|
+
// Check crontab access
|
|
243
|
+
results.push(checkCrontabAccess());
|
|
244
|
+
return results;
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checks.js","sourceRoot":"","sources":["../../src/utils/checks.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAY7E;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,MAAM,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD,OAAO;QACL,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,sBAAsB;QACjE,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,QAAQ,CAAC,gBAAgB,EAAE;YACzB,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,0BAA0B;YACnC,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,mDAAmD;YAC5D,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAkB;IACjD,IAAI,CAAC;QACH,QAAQ,CAAC,SAAS,QAAQ,EAAE,EAAE;YAC5B,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,uBAAuB,QAAQ,EAAE;YAC1C,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,2BAA2B,QAAQ,EAAE;YAC9C,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,SAAS,GAAe,EAAE,CAAC;IACjC,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;QACvC,IAAI,CAAC;YACH,QAAQ,CAAC,SAAS,QAAQ,EAAE,EAAE;gBAC5B,QAAQ,EAAE,OAAO;gBACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;aAChC,CAAC,CAAC;YACH,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IACpC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAE5C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,6CAA6C,WAAW,GAAG;YACpE,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,KAAK,IAAI,QAAQ,CAAC;IAEjC,OAAO;QACL,MAAM;QACN,OAAO,EAAE,MAAM;YACb,CAAC,CAAC,mBAAmB,WAAW,QAAQ,QAAQ,OAAO;YACvD,CAAC,CAAC,mBAAmB,WAAW,yBAAyB,QAAQ,OAAO;QAC1E,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,UAAkB;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;IAE3D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO;YACL,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,0BAA0B,gBAAgB,0BAA0B;YAC7E,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACrD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpB,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,sBAAsB,gBAAgB,EAAE;YACjD,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,QAAQ,GACZ,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnD,OAAO;YACL,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,iCAAiC,QAAQ,EAAE;YACpD,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,UAAkB,EAClB,MAAc;IAEd,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAE9C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO;YACL,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,4BAA4B,MAAM,EAAE;YAC7C,OAAO,EAAE,IAAI;YACb,GAAG,EAAE,GAAG,EAAE;gBACR,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC3C,oCAAoC;gBACpC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAChE,CAAC;SACF,CAAC;IACJ,CAAC;IAED,uDAAuD;IACvD,MAAM,IAAI,GAAG,EAAE;SACZ,WAAW,CAAC,OAAO,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,wBAAwB,CAAC,CAAC;IAEtE,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,wBAAwB,MAAM,KAAK,IAAI,CAAC,MAAM,QAAQ;QAC/D,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAEhD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO;YACL,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,6BAA6B,OAAO,EAAE;YAC/C,OAAO,EAAE,IAAI;YACb,GAAG,EAAE,GAAG,EAAE;gBACR,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,CAAC;SACF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,yBAAyB,OAAO,EAAE;QAC3C,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC;QACH,QAAQ,CAAC,YAAY,EAAE;YACrB,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,oBAAoB;YAC7B,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,+EAA+E;QAC/E,6DAA6D;QAC7D,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,4BAA4B;YACrC,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,UAAkB,EAClB,MAAc;IAEd,MAAM,OAAO,GAAmB,EAAE,CAAC;IAEnC,qBAAqB;IACrB,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC;IAEnC,iBAAiB;IACjB,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC;IAEvC,mBAAmB;IACnB,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IAE3B,sBAAsB;IACtB,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC;IACpC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC;YACX,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,oDAAoD;YAC7D,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,oBAAoB;IACpB,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC;IAE1C,sBAAsB;IACtB,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IAEpD,uBAAuB;IACvB,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC;IAE7C,uBAAuB;IACvB,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAEnC,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config writer utility for Night Watch CLI
|
|
3
|
+
* Saves partial config changes to night-watch.config.json while preserving unknown keys
|
|
4
|
+
*/
|
|
5
|
+
import { INightWatchConfig } from "../types.js";
|
|
6
|
+
export interface ISaveConfigResult {
|
|
7
|
+
success: boolean;
|
|
8
|
+
error?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Save partial config changes to the night-watch.config.json file.
|
|
12
|
+
* Reads the existing file, merges changes, and writes back.
|
|
13
|
+
* Preserves unknown keys (like $schema, projectName).
|
|
14
|
+
*/
|
|
15
|
+
export declare function saveConfig(projectDir: string, changes: Partial<INightWatchConfig>): ISaveConfigResult;
|
|
16
|
+
//# sourceMappingURL=config-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-writer.d.ts","sourceRoot":"","sources":["../../src/utils/config-writer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAClC,iBAAiB,CAiCnB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config writer utility for Night Watch CLI
|
|
3
|
+
* Saves partial config changes to night-watch.config.json while preserving unknown keys
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import { CONFIG_FILE_NAME } from "../constants.js";
|
|
8
|
+
/**
|
|
9
|
+
* Save partial config changes to the night-watch.config.json file.
|
|
10
|
+
* Reads the existing file, merges changes, and writes back.
|
|
11
|
+
* Preserves unknown keys (like $schema, projectName).
|
|
12
|
+
*/
|
|
13
|
+
export function saveConfig(projectDir, changes) {
|
|
14
|
+
const configPath = path.join(projectDir, CONFIG_FILE_NAME);
|
|
15
|
+
try {
|
|
16
|
+
// Read existing file
|
|
17
|
+
let existing = {};
|
|
18
|
+
if (fs.existsSync(configPath)) {
|
|
19
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
20
|
+
existing = JSON.parse(content);
|
|
21
|
+
}
|
|
22
|
+
// Merge changes (shallow merge for top-level keys, deep merge for notifications)
|
|
23
|
+
const merged = { ...existing };
|
|
24
|
+
for (const [key, value] of Object.entries(changes)) {
|
|
25
|
+
if (value !== undefined) {
|
|
26
|
+
if (key === "notifications" && existing.notifications && typeof existing.notifications === "object") {
|
|
27
|
+
merged.notifications = { ...existing.notifications, ...value };
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
merged[key] = value;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// Write back with consistent formatting
|
|
35
|
+
fs.writeFileSync(configPath, JSON.stringify(merged, null, 2) + "\n");
|
|
36
|
+
return { success: true };
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
return {
|
|
40
|
+
success: false,
|
|
41
|
+
error: err instanceof Error ? err.message : String(err),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=config-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-writer.js","sourceRoot":"","sources":["../../src/utils/config-writer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAQnD;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACxB,UAAkB,EAClB,OAAmC;IAEnC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;IAE3D,IAAI,CAAC;QACH,qBAAqB;QACrB,IAAI,QAAQ,GAA4B,EAAE,CAAC;QAC3C,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACrD,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;QAC5D,CAAC;QAED,iFAAiF;QACjF,MAAM,MAAM,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC/B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,IAAI,GAAG,KAAK,eAAe,IAAI,QAAQ,CAAC,aAAa,IAAI,OAAO,QAAQ,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;oBACpG,MAAM,CAAC,aAAa,GAAG,EAAE,GAAI,QAAQ,CAAC,aAAyC,EAAE,GAAG,KAAgC,EAAE,CAAC;gBACzH,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBACtB,CAAC;YACH,CAAC;QACH,CAAC;QAED,wCAAwC;QACxC,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAErE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global project registry for Night Watch CLI
|
|
3
|
+
* Manages ~/.night-watch/projects.json to track all registered projects
|
|
4
|
+
*/
|
|
5
|
+
export interface IRegistryEntry {
|
|
6
|
+
name: string;
|
|
7
|
+
path: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Get the path to the global registry file
|
|
11
|
+
*/
|
|
12
|
+
export declare function getRegistryPath(): string;
|
|
13
|
+
/**
|
|
14
|
+
* Load the global registry, returning [] if the file does not exist
|
|
15
|
+
*/
|
|
16
|
+
export declare function loadRegistry(): IRegistryEntry[];
|
|
17
|
+
/**
|
|
18
|
+
* Save the registry (full replace)
|
|
19
|
+
*/
|
|
20
|
+
export declare function saveRegistry(entries: IRegistryEntry[]): void;
|
|
21
|
+
/**
|
|
22
|
+
* Register a project in the global registry.
|
|
23
|
+
* No-op if already registered by path. Returns the entry.
|
|
24
|
+
*/
|
|
25
|
+
export declare function registerProject(projectDir: string): IRegistryEntry;
|
|
26
|
+
/**
|
|
27
|
+
* Remove a project from the registry by path.
|
|
28
|
+
* Returns true if it was found and removed.
|
|
29
|
+
*/
|
|
30
|
+
export declare function unregisterProject(projectDir: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Validate all registry entries.
|
|
33
|
+
* Returns entries split into valid (path + config exist) and invalid.
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateRegistry(): {
|
|
36
|
+
valid: IRegistryEntry[];
|
|
37
|
+
invalid: IRegistryEntry[];
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/utils/registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,cAAc,EAAE,CAe/C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,IAAI,CAK5D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CAmBlE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAS7D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI;IAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IAAC,OAAO,EAAE,cAAc,EAAE,CAAA;CAAE,CAczF"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global project registry for Night Watch CLI
|
|
3
|
+
* Manages ~/.night-watch/projects.json to track all registered projects
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import * as os from "os";
|
|
7
|
+
import * as path from "path";
|
|
8
|
+
import { CONFIG_FILE_NAME, GLOBAL_CONFIG_DIR, REGISTRY_FILE_NAME } from "../constants.js";
|
|
9
|
+
import { getProjectName } from "./status-data.js";
|
|
10
|
+
/**
|
|
11
|
+
* Get the path to the global registry file
|
|
12
|
+
*/
|
|
13
|
+
export function getRegistryPath() {
|
|
14
|
+
return path.join(os.homedir(), GLOBAL_CONFIG_DIR, REGISTRY_FILE_NAME);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Load the global registry, returning [] if the file does not exist
|
|
18
|
+
*/
|
|
19
|
+
export function loadRegistry() {
|
|
20
|
+
const registryPath = getRegistryPath();
|
|
21
|
+
if (!fs.existsSync(registryPath)) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const content = fs.readFileSync(registryPath, "utf-8");
|
|
26
|
+
const parsed = JSON.parse(content);
|
|
27
|
+
if (!Array.isArray(parsed)) {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
return parsed;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Save the registry (full replace)
|
|
38
|
+
*/
|
|
39
|
+
export function saveRegistry(entries) {
|
|
40
|
+
const registryPath = getRegistryPath();
|
|
41
|
+
const dir = path.dirname(registryPath);
|
|
42
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
43
|
+
fs.writeFileSync(registryPath, JSON.stringify(entries, null, 2) + "\n");
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Register a project in the global registry.
|
|
47
|
+
* No-op if already registered by path. Returns the entry.
|
|
48
|
+
*/
|
|
49
|
+
export function registerProject(projectDir) {
|
|
50
|
+
const resolvedPath = path.resolve(projectDir);
|
|
51
|
+
const entries = loadRegistry();
|
|
52
|
+
const existing = entries.find((e) => e.path === resolvedPath);
|
|
53
|
+
if (existing) {
|
|
54
|
+
return existing;
|
|
55
|
+
}
|
|
56
|
+
const name = getProjectName(resolvedPath);
|
|
57
|
+
// Handle name collisions by appending directory basename
|
|
58
|
+
const nameExists = entries.some((e) => e.name === name);
|
|
59
|
+
const finalName = nameExists ? `${name}-${path.basename(resolvedPath)}` : name;
|
|
60
|
+
const entry = { name: finalName, path: resolvedPath };
|
|
61
|
+
entries.push(entry);
|
|
62
|
+
saveRegistry(entries);
|
|
63
|
+
return entry;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Remove a project from the registry by path.
|
|
67
|
+
* Returns true if it was found and removed.
|
|
68
|
+
*/
|
|
69
|
+
export function unregisterProject(projectDir) {
|
|
70
|
+
const resolvedPath = path.resolve(projectDir);
|
|
71
|
+
const entries = loadRegistry();
|
|
72
|
+
const filtered = entries.filter((e) => e.path !== resolvedPath);
|
|
73
|
+
if (filtered.length === entries.length) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
saveRegistry(filtered);
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Validate all registry entries.
|
|
81
|
+
* Returns entries split into valid (path + config exist) and invalid.
|
|
82
|
+
*/
|
|
83
|
+
export function validateRegistry() {
|
|
84
|
+
const entries = loadRegistry();
|
|
85
|
+
const valid = [];
|
|
86
|
+
const invalid = [];
|
|
87
|
+
for (const entry of entries) {
|
|
88
|
+
if (fs.existsSync(entry.path) && fs.existsSync(path.join(entry.path, CONFIG_FILE_NAME))) {
|
|
89
|
+
valid.push(entry);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
invalid.push(entry);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return { valid, invalid };
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/utils/registry.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.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Autonomous PRD execution using AI Provider CLIs + cron",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
|
-
"build": "
|
|
17
|
+
"build": "yarn build:cli && yarn build:web",
|
|
18
|
+
"build:web": "cd web && yarn install && yarn build",
|
|
19
|
+
"build:cli": "tsc",
|
|
18
20
|
"test": "vitest run",
|
|
19
21
|
"dev": "tsx src/cli.ts",
|
|
20
22
|
"prepublishOnly": "npm run build && npm test",
|
|
@@ -27,7 +29,8 @@
|
|
|
27
29
|
"dist/",
|
|
28
30
|
"bin/",
|
|
29
31
|
"scripts/",
|
|
30
|
-
"templates/"
|
|
32
|
+
"templates/",
|
|
33
|
+
"web/dist/"
|
|
31
34
|
],
|
|
32
35
|
"keywords": [
|
|
33
36
|
"claude",
|
|
@@ -54,13 +57,20 @@
|
|
|
54
57
|
"chalk": "^5.6.2",
|
|
55
58
|
"cli-table3": "^0.6.5",
|
|
56
59
|
"commander": "^12.0.0",
|
|
60
|
+
"cors": "^2.8.6",
|
|
61
|
+
"cronstrue": "^3.12.0",
|
|
62
|
+
"express": "^5.2.1",
|
|
57
63
|
"ora": "^9.3.0"
|
|
58
64
|
},
|
|
59
65
|
"devDependencies": {
|
|
60
66
|
"@eslint/js": "^10.0.1",
|
|
61
67
|
"@types/blessed": "^0.1.27",
|
|
68
|
+
"@types/cors": "^2.8.19",
|
|
69
|
+
"@types/express": "^5.0.6",
|
|
62
70
|
"@types/node": "^20.11.0",
|
|
71
|
+
"@types/supertest": "^6.0.3",
|
|
63
72
|
"eslint": "^10.0.0",
|
|
73
|
+
"supertest": "^7.2.2",
|
|
64
74
|
"tsx": "^4.7.0",
|
|
65
75
|
"typescript": "^5.3.0",
|
|
66
76
|
"typescript-eslint": "^8.56.0",
|
|
@@ -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
|
|