@longzai-intelligence-issues/cli 0.0.1 → 0.0.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/.turbo/turbo-build.log +7 -0
- package/.turbo/turbo-lint.log +7 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/CHANGELOG.md +21 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/main.d.ts +4 -0
- package/dist/main.js +2 -0
- package/lzi-builder.config.ts +6 -2
- package/package.json +14 -17
- package/src/__tests__/commands.known-flags.test.ts +243 -0
- package/src/commands/close.commands.ts +175 -32
- package/src/commands/context.utils.ts +13 -3
- package/src/commands/gate.commands.ts +257 -44
- package/src/commands/index.ts +3 -0
- package/src/commands/issue.commands.ts +102 -38
- package/src/commands/migrate.commands.ts +113 -0
- package/src/commands/scaffold.commands.ts +57 -17
- package/src/main.ts +19 -0
- package/tsconfig/.cache/build.tsbuildinfo +1 -1
- package/tsconfig/.cache/node.tsbuildinfo +1 -1
- package/tsconfig/.cache/test.tsbuildinfo +1 -1
|
@@ -7,9 +7,11 @@ import {
|
|
|
7
7
|
listPrompts,
|
|
8
8
|
normalizeHeaderFile,
|
|
9
9
|
rerunCloseFlow,
|
|
10
|
+
scanRegistryDir,
|
|
10
11
|
showPrompt,
|
|
11
12
|
unfreezeIssue,
|
|
12
13
|
} from '@longzai-intelligence-issues/ledger';
|
|
14
|
+
import { join } from 'node:path';
|
|
13
15
|
import * as z from 'zod';
|
|
14
16
|
|
|
15
17
|
import { fail, info, loadConfigOrExit, ok, repoRoot, violation } from './context.utils.js';
|
|
@@ -18,8 +20,15 @@ import { fail, info, loadConfigOrExit, ok, repoRoot, violation } from './context
|
|
|
18
20
|
* 收口与冻结命令组:verify-close / freeze / unfreeze / normalize-header / prompts
|
|
19
21
|
*
|
|
20
22
|
* 判据口径:exit 0 过 / 1 违规 / 2 门禁拦截零执行。
|
|
23
|
+
*
|
|
24
|
+
* @param program - CLI 程序实例
|
|
21
25
|
*/
|
|
22
|
-
|
|
26
|
+
/**
|
|
27
|
+
* issue 收口命令(缺省零执行证据收口;--rerun 证书化真跑)
|
|
28
|
+
*
|
|
29
|
+
* @param program - CLI 程序实例
|
|
30
|
+
*/
|
|
31
|
+
function registerVerifyCloseCommand(program: Command): void {
|
|
23
32
|
defineCommand(program, {
|
|
24
33
|
name: 'verify-close',
|
|
25
34
|
description: 'issue 收口(缺省零执行证据收口;--rerun 证书化真跑)',
|
|
@@ -28,33 +37,42 @@ export function registerCloseCommands(program: Command): void {
|
|
|
28
37
|
{ flags: '--summary <summary>', description: '收口概要(批量禁用)' },
|
|
29
38
|
{ flags: '--dry-run', description: '只呈现不落盘/不执行' },
|
|
30
39
|
{ flags: '--rerun', description: '证书化真跑(重度命令,仅人类明令)' },
|
|
31
|
-
{
|
|
40
|
+
{
|
|
41
|
+
flags: '--criterion <criterion>',
|
|
42
|
+
description: '显式判据 label|channel|cwd|command(可重复)',
|
|
43
|
+
},
|
|
32
44
|
{ flags: '--criteria-from-issue', description: '从各案 criteria 块取判据' },
|
|
33
45
|
{ flags: '--confirm-heavy', description: '重度命令确认' },
|
|
34
46
|
{ flags: '--allow-full-criterion', description: '全量判据豁免(须留痕)' },
|
|
35
47
|
{ flags: '--config <path>', description: '显式配置路径' },
|
|
36
48
|
],
|
|
37
|
-
schema: z
|
|
38
|
-
.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
})
|
|
49
|
-
.passthrough(),
|
|
49
|
+
schema: z.looseObject({
|
|
50
|
+
issue: z.union([z.string(), z.array(z.string())]).optional(),
|
|
51
|
+
summary: z.string().optional(),
|
|
52
|
+
dryRun: z.boolean().optional(),
|
|
53
|
+
rerun: z.boolean().optional(),
|
|
54
|
+
criterion: z.union([z.string(), z.array(z.string())]).optional(),
|
|
55
|
+
criteriaFromIssue: z.boolean().optional(),
|
|
56
|
+
confirmHeavy: z.boolean().optional(),
|
|
57
|
+
allowFullCriterion: z.boolean().optional(),
|
|
58
|
+
config: z.string().optional(),
|
|
59
|
+
}),
|
|
50
60
|
action: async (opts) => {
|
|
61
|
+
/**
|
|
62
|
+
* 仓库根
|
|
63
|
+
*/
|
|
51
64
|
const root = repoRoot();
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 解析后配置
|
|
68
|
+
*/
|
|
52
69
|
const { config } = await loadConfigOrExit(opts.config);
|
|
53
70
|
|
|
54
71
|
/**
|
|
55
72
|
* 目标文件归一
|
|
56
73
|
*/
|
|
57
|
-
const files =
|
|
74
|
+
const files =
|
|
75
|
+
opts.issue === undefined ? [] : Array.isArray(opts.issue) ? opts.issue : [opts.issue];
|
|
58
76
|
|
|
59
77
|
if (files.length === 0) {
|
|
60
78
|
fail('缺少 --issue <路径>(可重复指定批量)');
|
|
@@ -63,7 +81,12 @@ export function registerCloseCommands(program: Command): void {
|
|
|
63
81
|
/**
|
|
64
82
|
* 显式判据归一
|
|
65
83
|
*/
|
|
66
|
-
const criteria =
|
|
84
|
+
const criteria =
|
|
85
|
+
opts.criterion === undefined
|
|
86
|
+
? []
|
|
87
|
+
: Array.isArray(opts.criterion)
|
|
88
|
+
? opts.criterion
|
|
89
|
+
: [opts.criterion];
|
|
67
90
|
|
|
68
91
|
if (opts.rerun === true) {
|
|
69
92
|
/**
|
|
@@ -102,10 +125,20 @@ export function registerCloseCommands(program: Command): void {
|
|
|
102
125
|
/**
|
|
103
126
|
* 缺省证据收口(零执行)
|
|
104
127
|
*/
|
|
105
|
-
if (
|
|
106
|
-
|
|
128
|
+
if (
|
|
129
|
+
criteria.length > 0 ||
|
|
130
|
+
opts.criteriaFromIssue === true ||
|
|
131
|
+
opts.confirmHeavy === true ||
|
|
132
|
+
opts.allowFullCriterion === true
|
|
133
|
+
) {
|
|
134
|
+
fail(
|
|
135
|
+
'证据收口(缺省模式)不接受 --criterion/--criteria-from-issue/--confirm-heavy/--allow-full-criterion(属 --rerun 真跑旗标)',
|
|
136
|
+
);
|
|
107
137
|
}
|
|
108
138
|
|
|
139
|
+
/**
|
|
140
|
+
* 零执行证据收口批次结果
|
|
141
|
+
*/
|
|
109
142
|
const result = evidenceCloseFlow({
|
|
110
143
|
root,
|
|
111
144
|
config,
|
|
@@ -125,7 +158,14 @@ export function registerCloseCommands(program: Command): void {
|
|
|
125
158
|
}
|
|
126
159
|
},
|
|
127
160
|
});
|
|
161
|
+
}
|
|
128
162
|
|
|
163
|
+
/**
|
|
164
|
+
* 冻结命令(freeze:--reason 须含「用户裁定」)
|
|
165
|
+
*
|
|
166
|
+
* @param program - CLI 程序实例
|
|
167
|
+
*/
|
|
168
|
+
function registerFreezeCommand(program: Command): void {
|
|
129
169
|
defineCommand(program, {
|
|
130
170
|
name: 'freeze',
|
|
131
171
|
description: '冻结 issue(--reason 须含「用户裁定」)',
|
|
@@ -134,8 +174,15 @@ export function registerCloseCommands(program: Command): void {
|
|
|
134
174
|
{ flags: '--reason <reason>', description: '裁定理由(须含「用户裁定」)' },
|
|
135
175
|
{ flags: '--config <path>', description: '显式配置路径' },
|
|
136
176
|
],
|
|
137
|
-
schema: z.
|
|
177
|
+
schema: z.looseObject({
|
|
178
|
+
issue: z.string().optional(),
|
|
179
|
+
reason: z.string().optional(),
|
|
180
|
+
config: z.string().optional(),
|
|
181
|
+
}),
|
|
138
182
|
action: async (opts) => {
|
|
183
|
+
/**
|
|
184
|
+
* 仓库根
|
|
185
|
+
*/
|
|
139
186
|
const root = repoRoot();
|
|
140
187
|
await loadConfigOrExit(opts.config);
|
|
141
188
|
|
|
@@ -143,6 +190,9 @@ export function registerCloseCommands(program: Command): void {
|
|
|
143
190
|
fail('freeze 须 --issue <路径> 与 --reason <裁定理由>');
|
|
144
191
|
}
|
|
145
192
|
|
|
193
|
+
/**
|
|
194
|
+
* 冻结写入结果
|
|
195
|
+
*/
|
|
146
196
|
const result = freezeIssue({ root, file: opts.issue, reason: opts.reason });
|
|
147
197
|
|
|
148
198
|
if (!result.ok) {
|
|
@@ -152,7 +202,14 @@ export function registerCloseCommands(program: Command): void {
|
|
|
152
202
|
ok(`${opts.issue}: ${result.message}`);
|
|
153
203
|
},
|
|
154
204
|
});
|
|
205
|
+
}
|
|
155
206
|
|
|
207
|
+
/**
|
|
208
|
+
* 解冻命令(unfreeze:--note 须含「用户裁定」;恢复 🔴)
|
|
209
|
+
*
|
|
210
|
+
* @param program - CLI 程序实例
|
|
211
|
+
*/
|
|
212
|
+
function registerUnfreezeCommand(program: Command): void {
|
|
156
213
|
defineCommand(program, {
|
|
157
214
|
name: 'unfreeze',
|
|
158
215
|
description: '解冻 issue(--note 须含「用户裁定」;恢复 🔴)',
|
|
@@ -161,8 +218,15 @@ export function registerCloseCommands(program: Command): void {
|
|
|
161
218
|
{ flags: '--note <note>', description: '解冻注记(须含「用户裁定」)' },
|
|
162
219
|
{ flags: '--config <path>', description: '显式配置路径' },
|
|
163
220
|
],
|
|
164
|
-
schema: z.
|
|
221
|
+
schema: z.looseObject({
|
|
222
|
+
issue: z.string().optional(),
|
|
223
|
+
note: z.string().optional(),
|
|
224
|
+
config: z.string().optional(),
|
|
225
|
+
}),
|
|
165
226
|
action: async (opts) => {
|
|
227
|
+
/**
|
|
228
|
+
* 仓库根
|
|
229
|
+
*/
|
|
166
230
|
const root = repoRoot();
|
|
167
231
|
await loadConfigOrExit(opts.config);
|
|
168
232
|
|
|
@@ -170,6 +234,9 @@ export function registerCloseCommands(program: Command): void {
|
|
|
170
234
|
fail('unfreeze 须 --issue <路径> 与 --note <解冻注记>');
|
|
171
235
|
}
|
|
172
236
|
|
|
237
|
+
/**
|
|
238
|
+
* 解冻写入结果
|
|
239
|
+
*/
|
|
173
240
|
const result = unfreezeIssue({ root, file: opts.issue, note: opts.note });
|
|
174
241
|
|
|
175
242
|
if (!result.ok) {
|
|
@@ -179,26 +246,60 @@ export function registerCloseCommands(program: Command): void {
|
|
|
179
246
|
ok(`${opts.issue}: ${result.message}`);
|
|
180
247
|
},
|
|
181
248
|
});
|
|
249
|
+
}
|
|
182
250
|
|
|
251
|
+
/**
|
|
252
|
+
* 方言头部迁移命令(normalize-header:字段规范序 / 零丢失守卫 / 幂等)
|
|
253
|
+
*
|
|
254
|
+
* @param program - CLI 程序实例
|
|
255
|
+
*/
|
|
256
|
+
function registerNormalizeHeaderCommand(program: Command): void {
|
|
183
257
|
defineCommand(program, {
|
|
184
258
|
name: 'normalize-header',
|
|
185
259
|
description: '方言头部迁移(字段规范序 / 零丢失守卫 / 幂等)',
|
|
186
260
|
options: [
|
|
187
|
-
{ flags: '--issue <issue>', description: 'issue
|
|
261
|
+
{ flags: '--issue <issue>', description: 'issue 文件路径(可重复,与 --dir 互斥)' },
|
|
262
|
+
{
|
|
263
|
+
flags: '--dir <dir>',
|
|
264
|
+
description: '注册表目录批量(目录内全部编号文件,与 --issue 互斥)',
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
flags: '--status <status>',
|
|
268
|
+
description: '无可识别状态行时的显式灯位 red|yellow|green|canceled(frozen 须经 freeze)',
|
|
269
|
+
},
|
|
188
270
|
{ flags: '--config <path>', description: '显式配置路径' },
|
|
189
271
|
],
|
|
190
|
-
schema: z.
|
|
272
|
+
schema: z.looseObject({
|
|
273
|
+
issue: z.union([z.string(), z.array(z.string())]).optional(),
|
|
274
|
+
dir: z.string().optional(),
|
|
275
|
+
status: z.enum(['red', 'yellow', 'green', 'canceled']).optional(),
|
|
276
|
+
config: z.string().optional(),
|
|
277
|
+
}),
|
|
191
278
|
action: async (opts) => {
|
|
279
|
+
/**
|
|
280
|
+
* 仓库根
|
|
281
|
+
*/
|
|
192
282
|
const root = repoRoot();
|
|
193
283
|
await loadConfigOrExit(opts.config);
|
|
194
284
|
|
|
285
|
+
if (opts.issue !== undefined && opts.dir !== undefined) {
|
|
286
|
+
fail('--issue 与 --dir 互斥(单文件指定或目录批量二选一)');
|
|
287
|
+
}
|
|
288
|
+
|
|
195
289
|
/**
|
|
196
|
-
*
|
|
290
|
+
* 目标文件清单(--dir 展开为注册表编号文件)
|
|
197
291
|
*/
|
|
198
|
-
const files =
|
|
292
|
+
const files =
|
|
293
|
+
opts.dir !== undefined
|
|
294
|
+
? scanRegistryDir(join(root, opts.dir)).map((record) => `${opts.dir}/${record.file}`)
|
|
295
|
+
: opts.issue === undefined
|
|
296
|
+
? []
|
|
297
|
+
: Array.isArray(opts.issue)
|
|
298
|
+
? opts.issue
|
|
299
|
+
: [opts.issue];
|
|
199
300
|
|
|
200
301
|
if (files.length === 0) {
|
|
201
|
-
fail('缺少 --issue
|
|
302
|
+
fail('缺少 --issue <路径>(可重复)或 --dir <注册表目录>');
|
|
202
303
|
}
|
|
203
304
|
|
|
204
305
|
/**
|
|
@@ -207,7 +308,10 @@ export function registerCloseCommands(program: Command): void {
|
|
|
207
308
|
let failed = 0;
|
|
208
309
|
|
|
209
310
|
for (const file of files) {
|
|
210
|
-
|
|
311
|
+
/**
|
|
312
|
+
* 单文件头部迁移结果
|
|
313
|
+
*/
|
|
314
|
+
const result = normalizeHeaderFile({ root, file, status: opts.status });
|
|
211
315
|
violation(`${file}: ${result.outcome}(${result.message})`);
|
|
212
316
|
failed += result.outcome === 'failed' ? 1 : 0;
|
|
213
317
|
}
|
|
@@ -217,7 +321,14 @@ export function registerCloseCommands(program: Command): void {
|
|
|
217
321
|
}
|
|
218
322
|
},
|
|
219
323
|
});
|
|
324
|
+
}
|
|
220
325
|
|
|
326
|
+
/**
|
|
327
|
+
* 推荐提示词命令(prompts:list / show <id>)
|
|
328
|
+
*
|
|
329
|
+
* @param program - CLI 程序实例
|
|
330
|
+
*/
|
|
331
|
+
function registerPromptsCommand(program: Command): void {
|
|
221
332
|
defineCommand(program, {
|
|
222
333
|
name: 'prompts',
|
|
223
334
|
description: '推荐提示词(list / show <id>)',
|
|
@@ -226,8 +337,11 @@ export function registerCloseCommands(program: Command): void {
|
|
|
226
337
|
{ flags: '--id <id>', description: '提示词 id(show 用)' },
|
|
227
338
|
{ flags: '--config <path>', description: '显式配置路径' },
|
|
228
339
|
],
|
|
229
|
-
schema: z.
|
|
230
|
-
action: async (opts) => {
|
|
340
|
+
schema: z.looseObject({ id: z.string().optional(), config: z.string().optional() }),
|
|
341
|
+
action: async (opts, positionals) => {
|
|
342
|
+
/**
|
|
343
|
+
* 解析后配置
|
|
344
|
+
*/
|
|
231
345
|
const { config } = await loadConfigOrExit(opts.config);
|
|
232
346
|
|
|
233
347
|
/**
|
|
@@ -235,15 +349,29 @@ export function registerCloseCommands(program: Command): void {
|
|
|
235
349
|
*/
|
|
236
350
|
const options = {
|
|
237
351
|
builtin: config.prompts.builtin,
|
|
238
|
-
extraDir:
|
|
352
|
+
extraDir:
|
|
353
|
+
config.prompts.extraDir === undefined
|
|
354
|
+
? undefined
|
|
355
|
+
: `${repoRoot()}/${config.prompts.extraDir}`,
|
|
239
356
|
};
|
|
240
357
|
|
|
241
|
-
|
|
358
|
+
/**
|
|
359
|
+
* 子动作(defineCommand 位置参数第二通道;缺省 list)
|
|
360
|
+
*/
|
|
361
|
+
const action = positionals[0] ?? 'list';
|
|
242
362
|
|
|
243
363
|
if (action === 'show') {
|
|
364
|
+
/**
|
|
365
|
+
* 目标提示词 id
|
|
366
|
+
*/
|
|
244
367
|
const id = opts.id ?? fail('show 须 --id <提示词 id>');
|
|
245
368
|
|
|
246
|
-
|
|
369
|
+
/**
|
|
370
|
+
* 命中的提示词条目
|
|
371
|
+
*/
|
|
372
|
+
const entry =
|
|
373
|
+
showPrompt(id, options) ??
|
|
374
|
+
fail(`提示词「${id}」未命中(lzi-issues prompts list 查看全部)`);
|
|
247
375
|
|
|
248
376
|
process.stdout.write(`${entry.content}\n`);
|
|
249
377
|
return;
|
|
@@ -255,3 +383,18 @@ export function registerCloseCommands(program: Command): void {
|
|
|
255
383
|
},
|
|
256
384
|
});
|
|
257
385
|
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* 收口与冻结命令组:verify-close / freeze / unfreeze / normalize-header / prompts
|
|
389
|
+
*
|
|
390
|
+
* 判据口径:exit 0 过 / 1 违规 / 2 门禁拦截零执行。
|
|
391
|
+
*
|
|
392
|
+
* @param program - CLI 程序实例
|
|
393
|
+
*/
|
|
394
|
+
export function registerCloseCommands(program: Command): void {
|
|
395
|
+
registerVerifyCloseCommand(program);
|
|
396
|
+
registerFreezeCommand(program);
|
|
397
|
+
registerUnfreezeCommand(program);
|
|
398
|
+
registerNormalizeHeaderCommand(program);
|
|
399
|
+
registerPromptsCommand(program);
|
|
400
|
+
}
|
|
@@ -5,12 +5,17 @@
|
|
|
5
5
|
* 信息走 stdout([INFO]/[SUCCESS] 前缀);exit 2 = 门禁拦截零执行。
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
|
|
8
|
+
import {
|
|
9
|
+
loadLziIssuesConfig,
|
|
10
|
+
type LoadLziIssuesConfigResult,
|
|
11
|
+
type LziIssuesConfig,
|
|
12
|
+
} from '@longzai-intelligence-issues/config';
|
|
10
13
|
import { resolve } from 'node:path';
|
|
11
14
|
|
|
12
15
|
/**
|
|
13
16
|
* 仓库根绝对路径(cwd 锚定;配置查找亦自 cwd 向上)
|
|
17
|
+
*
|
|
18
|
+
* @returns 仓库根绝对路径
|
|
14
19
|
*/
|
|
15
20
|
export function repoRoot(): string {
|
|
16
21
|
return resolve(process.cwd());
|
|
@@ -22,7 +27,9 @@ export function repoRoot(): string {
|
|
|
22
27
|
* @param configPath - 显式配置路径(--config)
|
|
23
28
|
* @returns 解析后配置与命中路径
|
|
24
29
|
*/
|
|
25
|
-
export async function loadConfigOrExit(
|
|
30
|
+
export async function loadConfigOrExit(
|
|
31
|
+
configPath?: string,
|
|
32
|
+
): Promise<{ config: LziIssuesConfig; configFilePath: string }> {
|
|
26
33
|
/**
|
|
27
34
|
* 加载结果
|
|
28
35
|
*/
|
|
@@ -88,6 +95,9 @@ export function resolveScopeFromCwd(config: LziIssuesConfig, cwdRel: string): st
|
|
|
88
95
|
*/
|
|
89
96
|
let bestKey: string | null = null;
|
|
90
97
|
|
|
98
|
+
/**
|
|
99
|
+
* 当前最长命中 path 的长度('.' 全仓命中按 -1 起步,任意具体 path 更长)
|
|
100
|
+
*/
|
|
91
101
|
let bestLen = -1;
|
|
92
102
|
|
|
93
103
|
for (const scope of config.scopes) {
|