@produck/agent-toolkit 0.1.5 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -24
- package/bin/agent-toolkit.mjs +51 -459
- package/bin/build-publish-assets.mjs +105 -0
- package/bin/command/main/index.mjs +11 -0
- package/bin/command/preflight/index.mjs +58 -0
- package/bin/command/run-capture/index.mjs +100 -0
- package/bin/command/shared/args.mjs +45 -0
- package/bin/command/shared/text-resource.mjs +19 -0
- package/bin/command/summarize-log/index.mjs +64 -0
- package/bin/command/sync-instructions/help.txt +11 -0
- package/bin/command/sync-instructions/index.mjs +272 -0
- package/bin/command/sync-instructions/user-space-bootstrap.md +14 -0
- package/bin/command/validate-commit-msg/help.txt +8 -0
- package/bin/command/validate-commit-msg/index.mjs +152 -0
- package/package.json +7 -3
- package/publish-assets/instructions/produck/00-produck-base.instructions.md +331 -0
- package/publish-assets/instructions/produck/10-produck-node.instructions.md +152 -0
- package/publish-assets/instructions/produck/15-produck-workspace.instructions.md +299 -0
- package/publish-assets/instructions/produck/20-produck-commit.instructions.md +178 -0
- package/templates/default.instructions.md +0 -21
- package/templates/help/sync-instructions.txt +0 -8
- package/templates/help/validate-commit-msg.txt +0 -7
- /package/{templates/help/main.txt → bin/command/main/help.txt} +0 -0
- /package/{templates/help/preflight.txt → bin/command/preflight/help.txt} +0 -0
- /package/{templates/help/run-capture.txt → bin/command/run-capture/help.txt} +0 -0
- /package/{templates/help/summarize-log.txt → bin/command/summarize-log/help.txt} +0 -0
package/README.md
CHANGED
|
@@ -14,51 +14,66 @@ Central CLI toolkit for organization-level AI execution workflows.
|
|
|
14
14
|
|
|
15
15
|
Run preflight checks:
|
|
16
16
|
|
|
17
|
-
```
|
|
18
|
-
npm exec --package=@produck/agent-toolkit@latest
|
|
19
|
-
agent-toolkit preflight --cwd . --require package.json --ensure-dir logs
|
|
17
|
+
```
|
|
18
|
+
npm exec --package=@produck/agent-toolkit@latest -- agent-toolkit preflight --cwd . --require package.json --ensure-dir logs
|
|
20
19
|
```
|
|
21
20
|
|
|
22
21
|
Capture long output safely:
|
|
23
22
|
|
|
24
|
-
```
|
|
25
|
-
npm exec --package=@produck/agent-toolkit@latest
|
|
26
|
-
agent-toolkit run-capture --cwd . --cmd "npm run test" --out logs/test.log
|
|
23
|
+
```
|
|
24
|
+
npm exec --package=@produck/agent-toolkit@latest -- agent-toolkit run-capture --cwd . --cmd "npm run test" --out logs/test.log
|
|
27
25
|
```
|
|
28
26
|
|
|
29
27
|
Summarize captured output:
|
|
30
28
|
|
|
31
|
-
```
|
|
32
|
-
npm exec --package=@produck/agent-toolkit@latest
|
|
33
|
-
agent-toolkit summarize-log --file logs/test.log --match "FAIL|ERROR"
|
|
29
|
+
```
|
|
30
|
+
npm exec --package=@produck/agent-toolkit@latest -- agent-toolkit summarize-log --file logs/test.log --match "FAIL|ERROR"
|
|
34
31
|
```
|
|
35
32
|
|
|
36
33
|
Validate commit message format:
|
|
37
34
|
|
|
38
|
-
```
|
|
39
|
-
npm exec --package=@produck/agent-toolkit@latest
|
|
40
|
-
agent-toolkit validate-commit-msg --file .git/COMMIT_EDITMSG
|
|
35
|
+
```
|
|
36
|
+
npm exec --package=@produck/agent-toolkit@latest -- agent-toolkit validate-commit-msg --file .git/COMMIT_EDITMSG
|
|
41
37
|
```
|
|
42
38
|
|
|
43
|
-
Manual per-repository instruction distribution (write .instructions.md):
|
|
39
|
+
Manual per-repository instruction distribution (write .github/instructions/produck/\*.instructions.md):
|
|
44
40
|
|
|
45
|
-
```
|
|
46
|
-
npm exec --package=@produck/agent-toolkit@latest
|
|
47
|
-
agent-toolkit sync-instructions --cwd .
|
|
41
|
+
```
|
|
42
|
+
npm exec --package=@produck/agent-toolkit@latest -- agent-toolkit sync-instructions --cwd .
|
|
48
43
|
```
|
|
49
44
|
|
|
50
|
-
|
|
45
|
+
Legacy repository bootstrap behavior:
|
|
46
|
+
|
|
47
|
+
- If `.github/copilot-instructions.md` is missing, sync-instructions initializes it.
|
|
48
|
+
- The initialized file guides repository owners to keep organization baseline in
|
|
49
|
+
`.github/instructions/produck/*.instructions.md` and put local-only rules in
|
|
50
|
+
`.github/copilot-instructions.md`.
|
|
51
|
+
|
|
52
|
+
Use organization source directory instead of built-in assets:
|
|
51
53
|
|
|
52
|
-
```bash
|
|
53
|
-
npm exec --package=@produck/agent-toolkit@latest \
|
|
54
|
-
agent-toolkit sync-instructions --cwd . \
|
|
55
|
-
--source path/to/org/.instructions.md --force
|
|
56
54
|
```
|
|
55
|
+
npm exec --package=@produck/agent-toolkit@latest -- agent-toolkit sync-instructions --cwd . --source path/to/org/.github/distribution/produck --force --prune
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Built-in command-local resource locations (for review and updates):
|
|
59
|
+
|
|
60
|
+
- `bin/command/*/help.txt`
|
|
61
|
+
- `bin/command/sync-instructions/user-space-bootstrap.md`
|
|
62
|
+
|
|
63
|
+
Publish-time generated instruction assets:
|
|
64
|
+
|
|
65
|
+
- `publish-assets/instructions/produck/*.instructions.md`
|
|
66
|
+
- Generated from `.github/distribution/produck/*.instructions.md` via
|
|
67
|
+
`prepack`
|
|
68
|
+
- Included in npm package, ignored in git working tree
|
|
69
|
+
|
|
70
|
+
Downstream source maintenance in policy repository:
|
|
71
|
+
|
|
72
|
+
- Maintain source files directly under `.github/distribution/produck/*.instructions.md`
|
|
57
73
|
|
|
58
|
-
|
|
74
|
+
Organization-only instruction source (not published):
|
|
59
75
|
|
|
60
|
-
-
|
|
61
|
-
- `templates/help/*.txt`
|
|
76
|
+
- `.github/instructions/produck/*.instructions.md`
|
|
62
77
|
|
|
63
78
|
## Local verification
|
|
64
79
|
|
package/bin/agent-toolkit.mjs
CHANGED
|
@@ -1,418 +1,48 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
} else {
|
|
45
|
-
if (!options[token]) {
|
|
46
|
-
options[token] = [];
|
|
47
|
-
}
|
|
48
|
-
options[token].push(next);
|
|
49
|
-
i += 1;
|
|
50
|
-
}
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
positional.push(token);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return { positional, options };
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function getSingle(options, key, fallback = '') {
|
|
60
|
-
if (!options[key] || options[key].length === 0) {
|
|
61
|
-
return fallback;
|
|
62
|
-
}
|
|
63
|
-
return String(options[key][options[key].length - 1]);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function getMulti(options, key) {
|
|
67
|
-
if (!options[key]) {
|
|
68
|
-
return [];
|
|
69
|
-
}
|
|
70
|
-
return options[key].map((v) => String(v));
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function hasFlag(options, key) {
|
|
74
|
-
return Boolean(options[key]);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function printMainHelp() {
|
|
78
|
-
printTemplate('help/main.txt');
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function printPreflightHelp() {
|
|
82
|
-
printTemplate('help/preflight.txt');
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function printRunCaptureHelp() {
|
|
86
|
-
printTemplate('help/run-capture.txt');
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function printSummarizeHelp() {
|
|
90
|
-
printTemplate('help/summarize-log.txt');
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function printValidateHelp() {
|
|
94
|
-
printTemplate('help/validate-commit-msg.txt');
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function printSyncInstructionsHelp() {
|
|
98
|
-
printTemplate('help/sync-instructions.txt');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function loadDefaultInstructionsTemplate() {
|
|
102
|
-
let content = loadTemplateFile('default.instructions.md');
|
|
103
|
-
if (!content.endsWith('\n')) {
|
|
104
|
-
content = `${content}\n`;
|
|
105
|
-
}
|
|
106
|
-
return content;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function runPreflight(options) {
|
|
110
|
-
const cwd = path.resolve(getSingle(options, '--cwd', process.cwd()));
|
|
111
|
-
const required = getMulti(options, '--require');
|
|
112
|
-
const ensureDir = getMulti(options, '--ensure-dir');
|
|
113
|
-
const jsonFile = getSingle(options, '--json', '');
|
|
114
|
-
|
|
115
|
-
if (!fs.existsSync(cwd)) {
|
|
116
|
-
console.error(`CWD does not exist: ${cwd}`);
|
|
117
|
-
process.exit(2);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const report = {
|
|
121
|
-
cwd,
|
|
122
|
-
required: [],
|
|
123
|
-
ensuredDirectories: [],
|
|
124
|
-
ok: true,
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
for (const rel of required) {
|
|
128
|
-
const resolved = path.resolve(cwd, rel);
|
|
129
|
-
const exists = fs.existsSync(resolved);
|
|
130
|
-
report.required.push({ path: rel, resolved, exists });
|
|
131
|
-
if (!exists) {
|
|
132
|
-
report.ok = false;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
for (const rel of ensureDir) {
|
|
137
|
-
const resolved = path.resolve(cwd, rel);
|
|
138
|
-
fs.mkdirSync(resolved, { recursive: true });
|
|
139
|
-
report.ensuredDirectories.push({ path: rel, resolved, created: true });
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (jsonFile) {
|
|
143
|
-
const out = path.resolve(cwd, jsonFile);
|
|
144
|
-
fs.mkdirSync(path.dirname(out), { recursive: true });
|
|
145
|
-
fs.writeFileSync(out, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
149
|
-
if (!report.ok) {
|
|
150
|
-
process.exit(2);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function runCapture(options) {
|
|
155
|
-
const out = getSingle(options, '--out', '');
|
|
156
|
-
const cmd = getSingle(options, '--cmd', '');
|
|
157
|
-
const cwd = path.resolve(getSingle(options, '--cwd', process.cwd()));
|
|
158
|
-
const meta = getSingle(options, '--meta', '');
|
|
159
|
-
const allowPipe = hasFlag(options, '--allow-pipe');
|
|
160
|
-
|
|
161
|
-
if (!out || !cmd) {
|
|
162
|
-
printRunCaptureHelp();
|
|
163
|
-
process.exit(2);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (!allowPipe && cmd.includes('|')) {
|
|
167
|
-
console.error('Blocked command containing pipe. Use --allow-pipe if needed.');
|
|
168
|
-
process.exit(2);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const outPath = path.resolve(out);
|
|
172
|
-
const metaPath = meta ? path.resolve(meta) : `${outPath}.meta.json`;
|
|
173
|
-
|
|
174
|
-
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
175
|
-
fs.mkdirSync(path.dirname(metaPath), { recursive: true });
|
|
176
|
-
|
|
177
|
-
const startAt = Date.now();
|
|
178
|
-
const outStream = fs.createWriteStream(outPath, { encoding: 'utf8' });
|
|
179
|
-
|
|
180
|
-
outStream.write(`# command: ${cmd}\n`);
|
|
181
|
-
outStream.write(`# cwd: ${cwd}\n`);
|
|
182
|
-
outStream.write(`# startedAt: ${new Date(startAt).toISOString()}\n\n`);
|
|
183
|
-
|
|
184
|
-
const child = spawn(cmd, {
|
|
185
|
-
cwd,
|
|
186
|
-
shell: true,
|
|
187
|
-
env: process.env,
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
let stdoutBytes = 0;
|
|
191
|
-
let stderrBytes = 0;
|
|
192
|
-
|
|
193
|
-
child.stdout.on('data', (chunk) => {
|
|
194
|
-
stdoutBytes += chunk.length;
|
|
195
|
-
outStream.write(chunk);
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
child.stderr.on('data', (chunk) => {
|
|
199
|
-
stderrBytes += chunk.length;
|
|
200
|
-
outStream.write(chunk);
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
child.on('error', (error) => {
|
|
204
|
-
outStream.write(`\n[agent-toolkit] spawn error: ${error.message}\n`);
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
child.on('close', (code, signal) => {
|
|
208
|
-
const endAt = Date.now();
|
|
209
|
-
const durationMs = endAt - startAt;
|
|
210
|
-
|
|
211
|
-
outStream.write('\n');
|
|
212
|
-
outStream.write(`# finishedAt: ${new Date(endAt).toISOString()}\n`);
|
|
213
|
-
outStream.write(`# exitCode: ${String(code)}\n`);
|
|
214
|
-
outStream.write(`# signal: ${signal ? String(signal) : 'none'}\n`);
|
|
215
|
-
outStream.end();
|
|
216
|
-
|
|
217
|
-
const report = {
|
|
218
|
-
command: cmd,
|
|
219
|
-
cwd,
|
|
220
|
-
startedAt: new Date(startAt).toISOString(),
|
|
221
|
-
finishedAt: new Date(endAt).toISOString(),
|
|
222
|
-
durationMs,
|
|
223
|
-
exitCode: code,
|
|
224
|
-
signal,
|
|
225
|
-
stdoutBytes,
|
|
226
|
-
stderrBytes,
|
|
227
|
-
outputFile: outPath,
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
fs.writeFileSync(metaPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
|
|
231
|
-
|
|
232
|
-
if (typeof code === 'number') {
|
|
233
|
-
process.exit(code);
|
|
234
|
-
}
|
|
235
|
-
process.exit(1);
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
function runSummarize(options) {
|
|
240
|
-
const file = getSingle(options, '--file', '');
|
|
241
|
-
const last = Number(getSingle(options, '--last', '0')) || 0;
|
|
242
|
-
const match = getSingle(options, '--match', '');
|
|
243
|
-
const max = Number(getSingle(options, '--max', '200')) || 200;
|
|
244
|
-
|
|
245
|
-
if (!file) {
|
|
246
|
-
printSummarizeHelp();
|
|
247
|
-
process.exit(2);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const filePath = path.resolve(file);
|
|
251
|
-
if (!fs.existsSync(filePath)) {
|
|
252
|
-
console.error(`Log file does not exist: ${filePath}`);
|
|
253
|
-
process.exit(2);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const raw = fs.readFileSync(filePath, 'utf8');
|
|
257
|
-
const allLines = raw.split(/\r?\n/);
|
|
258
|
-
|
|
259
|
-
let lines = allLines;
|
|
260
|
-
let mode = 'all';
|
|
261
|
-
|
|
262
|
-
if (match) {
|
|
263
|
-
const pattern = new RegExp(match, 'i');
|
|
264
|
-
lines = allLines.filter((line) => pattern.test(line));
|
|
265
|
-
mode = 'match';
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (last > 0) {
|
|
269
|
-
lines = lines.slice(-last);
|
|
270
|
-
mode = mode === 'match' ? 'match+last' : 'last';
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
if (max > 0 && lines.length > max) {
|
|
274
|
-
lines = lines.slice(0, max);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
const header = [
|
|
278
|
-
`# file: ${filePath}`,
|
|
279
|
-
`# totalLines: ${allLines.length}`,
|
|
280
|
-
`# selectedLines: ${lines.length}`,
|
|
281
|
-
`# mode: ${mode}`,
|
|
282
|
-
'',
|
|
283
|
-
].join('\n');
|
|
284
|
-
|
|
285
|
-
process.stdout.write(header);
|
|
286
|
-
process.stdout.write(lines.join('\n'));
|
|
287
|
-
process.stdout.write('\n');
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
function validateCommitLine(line, lineNo) {
|
|
291
|
-
if (line.trim() === '') {
|
|
292
|
-
return `Line ${lineNo}: empty line is not allowed`;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const head = line.match(/^\[([A-Z]+)\]\s+/);
|
|
296
|
-
if (!head) {
|
|
297
|
-
return `Line ${lineNo}: must start with [TAG] followed by a space`;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
const tag = head[1];
|
|
301
|
-
if (!ALLOWED_TAGS.includes(tag)) {
|
|
302
|
-
return `Line ${lineNo}: tag [${tag}] is not allowed`;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
const rest = line.slice(head[0].length);
|
|
306
|
-
if (rest.trim() === '') {
|
|
307
|
-
return `Line ${lineNo}: summary is required after tag`;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
const targetMatch = rest.match(/^<([^>]+)>:\s+(.+)$/);
|
|
311
|
-
if (targetMatch) {
|
|
312
|
-
const target = targetMatch[1];
|
|
313
|
-
const summary = targetMatch[2];
|
|
314
|
-
if (!ALLOWED_TARGETS.includes(target)) {
|
|
315
|
-
return `Line ${lineNo}: target <${target}> is not allowed`;
|
|
316
|
-
}
|
|
317
|
-
if (summary.trim() === '') {
|
|
318
|
-
return `Line ${lineNo}: summary is required after target`;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
return null;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
function runValidateCommitMsg(options) {
|
|
326
|
-
const file = getSingle(options, '--file', '');
|
|
327
|
-
if (!file) {
|
|
328
|
-
printValidateHelp();
|
|
329
|
-
process.exit(2);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
const filePath = path.resolve(file);
|
|
333
|
-
if (!fs.existsSync(filePath)) {
|
|
334
|
-
console.error(`Message file not found: ${filePath}`);
|
|
335
|
-
process.exit(2);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
const raw = fs.readFileSync(filePath, 'utf8').replace(/\r\n/g, '\n');
|
|
339
|
-
const lines = raw.endsWith('\n') ? raw.slice(0, -1).split('\n') : raw.split('\n');
|
|
340
|
-
|
|
341
|
-
if (lines.length === 0 || (lines.length === 1 && lines[0].trim() === '')) {
|
|
342
|
-
console.error('Commit message is empty');
|
|
343
|
-
process.exit(2);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
const errors = [];
|
|
347
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
348
|
-
const err = validateCommitLine(lines[i], i + 1);
|
|
349
|
-
if (err) {
|
|
350
|
-
errors.push(err);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
if (errors.length > 0) {
|
|
355
|
-
console.error('Commit message validation failed:');
|
|
356
|
-
for (const err of errors) {
|
|
357
|
-
console.error(`- ${err}`);
|
|
358
|
-
}
|
|
359
|
-
process.exit(1);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
console.log('Commit message validation passed');
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
function runSyncInstructions(options) {
|
|
366
|
-
const cwd = path.resolve(getSingle(options, '--cwd', process.cwd()));
|
|
367
|
-
const outArg = getSingle(options, '--out', '.instructions.md');
|
|
368
|
-
const sourceArg = getSingle(options, '--source', '');
|
|
369
|
-
const force = hasFlag(options, '--force');
|
|
370
|
-
const dryRun = hasFlag(options, '--dry-run');
|
|
371
|
-
|
|
372
|
-
if (!fs.existsSync(cwd)) {
|
|
373
|
-
console.error(`CWD does not exist: ${cwd}`);
|
|
374
|
-
process.exit(2);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
const outPath = path.resolve(cwd, outArg);
|
|
378
|
-
let content = loadDefaultInstructionsTemplate();
|
|
379
|
-
|
|
380
|
-
if (sourceArg) {
|
|
381
|
-
const sourcePath = path.resolve(cwd, sourceArg);
|
|
382
|
-
if (!fs.existsSync(sourcePath)) {
|
|
383
|
-
console.error(`Source file does not exist: ${sourcePath}`);
|
|
384
|
-
process.exit(2);
|
|
385
|
-
}
|
|
386
|
-
content = fs.readFileSync(sourcePath, 'utf8');
|
|
387
|
-
if (!content.endsWith('\n')) {
|
|
388
|
-
content = `${content}\n`;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
const exists = fs.existsSync(outPath);
|
|
393
|
-
if (exists && !force) {
|
|
394
|
-
console.error(`Target already exists: ${outPath}`);
|
|
395
|
-
console.error('Use --force to overwrite.');
|
|
396
|
-
process.exit(2);
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
const report = {
|
|
400
|
-
cwd,
|
|
401
|
-
outPath,
|
|
402
|
-
source: sourceArg ? path.resolve(cwd, sourceArg) : DEFAULT_INSTRUCTIONS_TEMPLATE_PATH,
|
|
403
|
-
exists,
|
|
404
|
-
overwritten: exists && force,
|
|
405
|
-
dryRun,
|
|
406
|
-
};
|
|
407
|
-
|
|
408
|
-
if (dryRun) {
|
|
409
|
-
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
410
|
-
process.exit(0);
|
|
2
|
+
import { printMainHelp } from './command/main/index.mjs';
|
|
3
|
+
import { printPreflightHelp, runPreflight } from './command/preflight/index.mjs';
|
|
4
|
+
import { printRunCaptureHelp, runCapture } from './command/run-capture/index.mjs';
|
|
5
|
+
import { printSummarizeHelp, runSummarize } from './command/summarize-log/index.mjs';
|
|
6
|
+
import {
|
|
7
|
+
printSyncInstructionsHelp,
|
|
8
|
+
runSyncInstructions,
|
|
9
|
+
} from './command/sync-instructions/index.mjs';
|
|
10
|
+
import { hasFlag, parseCommonArgs } from './command/shared/args.mjs';
|
|
11
|
+
import {
|
|
12
|
+
printValidateCommitMsgHelp,
|
|
13
|
+
runValidateCommitMsg,
|
|
14
|
+
} from './command/validate-commit-msg/index.mjs';
|
|
15
|
+
|
|
16
|
+
const COMMANDS = {
|
|
17
|
+
preflight: {
|
|
18
|
+
printHelp: printPreflightHelp,
|
|
19
|
+
run: runPreflight,
|
|
20
|
+
},
|
|
21
|
+
'run-capture': {
|
|
22
|
+
printHelp: printRunCaptureHelp,
|
|
23
|
+
run: runCapture,
|
|
24
|
+
},
|
|
25
|
+
'summarize-log': {
|
|
26
|
+
printHelp: printSummarizeHelp,
|
|
27
|
+
run: runSummarize,
|
|
28
|
+
},
|
|
29
|
+
'validate-commit-msg': {
|
|
30
|
+
printHelp: printValidateCommitMsgHelp,
|
|
31
|
+
run: runValidateCommitMsg,
|
|
32
|
+
},
|
|
33
|
+
'sync-instructions': {
|
|
34
|
+
printHelp: printSyncInstructionsHelp,
|
|
35
|
+
run: runSyncInstructions,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
function printCommandHelp(command) {
|
|
40
|
+
const entry = COMMANDS[command];
|
|
41
|
+
if (!entry) {
|
|
42
|
+
printMainHelp();
|
|
43
|
+
return;
|
|
411
44
|
}
|
|
412
|
-
|
|
413
|
-
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
414
|
-
fs.writeFileSync(outPath, content, 'utf8');
|
|
415
|
-
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
45
|
+
entry.printHelp();
|
|
416
46
|
}
|
|
417
47
|
|
|
418
48
|
function main() {
|
|
@@ -426,56 +56,18 @@ function main() {
|
|
|
426
56
|
}
|
|
427
57
|
|
|
428
58
|
if (hasFlag(options, '--help') || hasFlag(options, '-h')) {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
process.exit(0);
|
|
432
|
-
}
|
|
433
|
-
if (command === 'run-capture') {
|
|
434
|
-
printRunCaptureHelp();
|
|
435
|
-
process.exit(0);
|
|
436
|
-
}
|
|
437
|
-
if (command === 'summarize-log') {
|
|
438
|
-
printSummarizeHelp();
|
|
439
|
-
process.exit(0);
|
|
440
|
-
}
|
|
441
|
-
if (command === 'validate-commit-msg') {
|
|
442
|
-
printValidateHelp();
|
|
443
|
-
process.exit(0);
|
|
444
|
-
}
|
|
445
|
-
if (command === 'sync-instructions') {
|
|
446
|
-
printSyncInstructionsHelp();
|
|
447
|
-
process.exit(0);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
if (command === 'preflight') {
|
|
452
|
-
runPreflight(options);
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
if (command === 'run-capture') {
|
|
457
|
-
runCapture(options);
|
|
458
|
-
return;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
if (command === 'summarize-log') {
|
|
462
|
-
runSummarize(options);
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
if (command === 'validate-commit-msg') {
|
|
467
|
-
runValidateCommitMsg(options);
|
|
468
|
-
return;
|
|
59
|
+
printCommandHelp(command);
|
|
60
|
+
process.exit(0);
|
|
469
61
|
}
|
|
470
62
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
63
|
+
const entry = COMMANDS[command];
|
|
64
|
+
if (!entry) {
|
|
65
|
+
console.error(`Unknown command: ${command}`);
|
|
66
|
+
printMainHelp();
|
|
67
|
+
process.exit(2);
|
|
474
68
|
}
|
|
475
69
|
|
|
476
|
-
|
|
477
|
-
printMainHelp();
|
|
478
|
-
process.exit(2);
|
|
70
|
+
entry.run(options);
|
|
479
71
|
}
|
|
480
72
|
|
|
481
73
|
main();
|