release-skill 0.7.6 → 0.7.8
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codebuddy-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +2 -2
- package/.kimi-plugin/plugin.json +1 -1
- package/CHANGELOG.md +40 -0
- package/INSTALL.md +2 -2
- package/INSTALL.zh-CN.md +2 -2
- package/README.md +14 -11
- package/README.zh-CN.md +13 -10
- package/adapters/claude/.claude-plugin/marketplace.json +1 -1
- package/adapters/claude/.claude-plugin/plugin.json +1 -1
- package/adapters/claude/bin/release-skill.bundle.mjs +1728 -1155
- package/adapters/claude/schemas/.render-manifest.json +6 -6
- package/adapters/claude/schemas/release-plan.schema.json +47 -0
- package/adapters/claude/schemas/release-project.schema.json +24 -0
- package/adapters/claude/schemas/release-run.schema.json +41 -1
- package/adapters/claude/skills/release-prepare/SKILL.md +4 -0
- package/adapters/codex/.codex-plugin/plugin.json +2 -2
- package/adapters/codex/bin/release-skill.bundle.mjs +1728 -1155
- package/adapters/codex/schemas/.render-manifest.json +6 -6
- package/adapters/codex/schemas/release-plan.schema.json +47 -0
- package/adapters/codex/schemas/release-project.schema.json +24 -0
- package/adapters/codex/schemas/release-run.schema.json +41 -1
- package/adapters/codex/skills/release-prepare/SKILL.md +4 -0
- package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
- package/adapters/kimi/bin/release-skill.bundle.mjs +1728 -1155
- package/adapters/kimi/schemas/.render-manifest.json +6 -6
- package/adapters/kimi/schemas/release-plan.schema.json +47 -0
- package/adapters/kimi/schemas/release-project.schema.json +24 -0
- package/adapters/kimi/schemas/release-run.schema.json +41 -1
- package/adapters/kimi/skills/release-prepare/SKILL.md +4 -0
- package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
- package/adapters/workbuddy/bin/release-skill.bundle.mjs +1728 -1155
- package/adapters/workbuddy/schemas/.render-manifest.json +6 -6
- package/adapters/workbuddy/schemas/release-plan.schema.json +47 -0
- package/adapters/workbuddy/schemas/release-project.schema.json +24 -0
- package/adapters/workbuddy/schemas/release-run.schema.json +41 -1
- package/adapters/workbuddy/skills/release-prepare/SKILL.md +4 -0
- package/bin/release-skill-cli.mjs +116 -47
- package/bin/release-skill.bundle.mjs +1728 -1155
- package/package.json +1 -1
- package/platform-manifest.json +4 -4
- package/references/.render-manifest.json +6 -6
- package/references/01-state-machine.md +2 -2
- package/references/02-project-config.md +18 -0
- package/references/06-adapter-contract.md +4 -3
- package/schemas/.render-manifest.json +6 -6
- package/schemas/release-plan.schema.json +47 -0
- package/schemas/release-project.schema.json +24 -0
- package/schemas/release-run.schema.json +41 -1
- package/skills/release-prepare/SKILL.md +4 -0
- package/skills-src/release-prepare/SKILL.md +4 -0
- package/src/adapters/git-github.mjs +139 -26
- package/src/commands/prepare.mjs +72 -3
- package/src/commands/publish.mjs +51 -0
- package/src/commands/verify.mjs +53 -1
- package/src/core/config.mjs +31 -0
- package/src/core/plan.mjs +78 -0
- package/src/core/release-assets.mjs +54 -0
- package/src/core/source-authority.mjs +127 -3
|
@@ -26,16 +26,16 @@
|
|
|
26
26
|
"bytes": 1744
|
|
27
27
|
},
|
|
28
28
|
"release-plan.schema.json": {
|
|
29
|
-
"digest": "
|
|
30
|
-
"bytes":
|
|
29
|
+
"digest": "3d24cb908cdfbfd5d89551b7c6fed5140f6f1448b9920f114264291ca4cf1c52",
|
|
30
|
+
"bytes": 55905
|
|
31
31
|
},
|
|
32
32
|
"release-project.schema.json": {
|
|
33
|
-
"digest": "
|
|
34
|
-
"bytes":
|
|
33
|
+
"digest": "b0ba3c46692622f734a80d3f4e3904180bbfd1096ca2d9b6d6fd957917e96f73",
|
|
34
|
+
"bytes": 47688
|
|
35
35
|
},
|
|
36
36
|
"release-run.schema.json": {
|
|
37
|
-
"digest": "
|
|
38
|
-
"bytes":
|
|
37
|
+
"digest": "4a041b8f6488e7d61b7eb271ebdbc2e043731df41c4437783ef63e77f664c192",
|
|
38
|
+
"bytes": 19002
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -53,6 +53,53 @@
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
},
|
|
56
|
+
"publicSourceAuthorityReceipt": {
|
|
57
|
+
"type": "object",
|
|
58
|
+
"required": [
|
|
59
|
+
"coordinatorUnitId",
|
|
60
|
+
"subjectUnitIds",
|
|
61
|
+
"asset"
|
|
62
|
+
],
|
|
63
|
+
"additionalProperties": false,
|
|
64
|
+
"properties": {
|
|
65
|
+
"coordinatorUnitId": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"pattern": "^(?!\\.{1,2}$)[A-Za-z0-9][A-Za-z0-9._-]*$"
|
|
68
|
+
},
|
|
69
|
+
"subjectUnitIds": {
|
|
70
|
+
"type": "array",
|
|
71
|
+
"minItems": 1,
|
|
72
|
+
"uniqueItems": true,
|
|
73
|
+
"items": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"pattern": "^(?!\\.{1,2}$)[A-Za-z0-9][A-Za-z0-9._-]*$"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"asset": {
|
|
79
|
+
"type": "object",
|
|
80
|
+
"required": [
|
|
81
|
+
"name",
|
|
82
|
+
"path",
|
|
83
|
+
"sha256"
|
|
84
|
+
],
|
|
85
|
+
"additionalProperties": false,
|
|
86
|
+
"properties": {
|
|
87
|
+
"name": {
|
|
88
|
+
"const": "source-authority-receipt.json"
|
|
89
|
+
},
|
|
90
|
+
"path": {
|
|
91
|
+
"type": "string",
|
|
92
|
+
"minLength": 1,
|
|
93
|
+
"pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\\\).+$"
|
|
94
|
+
},
|
|
95
|
+
"sha256": {
|
|
96
|
+
"type": "string",
|
|
97
|
+
"pattern": "^[a-f0-9]{64}$"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
56
103
|
"baseline": {
|
|
57
104
|
"type": "object",
|
|
58
105
|
"required": [
|
|
@@ -44,6 +44,30 @@
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
|
+
"publicSourceAuthorityReceipt": {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"description": "Optional public source-authority receipt uploaded to one coordinator GitHub Release after all subject npm tarballs are frozen.",
|
|
50
|
+
"required": [
|
|
51
|
+
"coordinatorUnitId",
|
|
52
|
+
"subjectUnitIds"
|
|
53
|
+
],
|
|
54
|
+
"additionalProperties": false,
|
|
55
|
+
"properties": {
|
|
56
|
+
"coordinatorUnitId": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"pattern": "^(?!\\.{1,2}$)[A-Za-z0-9][A-Za-z0-9._-]*$"
|
|
59
|
+
},
|
|
60
|
+
"subjectUnitIds": {
|
|
61
|
+
"type": "array",
|
|
62
|
+
"minItems": 1,
|
|
63
|
+
"uniqueItems": true,
|
|
64
|
+
"items": {
|
|
65
|
+
"type": "string",
|
|
66
|
+
"pattern": "^(?!\\.{1,2}$)[A-Za-z0-9][A-Za-z0-9._-]*$"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
47
71
|
"releaseUnits": {
|
|
48
72
|
"type": "array",
|
|
49
73
|
"minItems": 1,
|
|
@@ -199,6 +199,11 @@
|
|
|
199
199
|
},
|
|
200
200
|
"url": {
|
|
201
201
|
"type": "string"
|
|
202
|
+
},
|
|
203
|
+
"integrity": {
|
|
204
|
+
"type": "string",
|
|
205
|
+
"pattern": "^sha512-[A-Za-z0-9+/]{86}==$",
|
|
206
|
+
"description": "Observed npm dist.integrity when an already-consistent npm publish is skipped"
|
|
202
207
|
}
|
|
203
208
|
}
|
|
204
209
|
},
|
|
@@ -280,7 +285,42 @@
|
|
|
280
285
|
"minimum": 0,
|
|
281
286
|
"description": "写入目标的载荷文件数"
|
|
282
287
|
}
|
|
283
|
-
}
|
|
288
|
+
},
|
|
289
|
+
"allOf": [
|
|
290
|
+
{
|
|
291
|
+
"if": {
|
|
292
|
+
"properties": {
|
|
293
|
+
"remoteRef": {
|
|
294
|
+
"type": "object",
|
|
295
|
+
"required": [
|
|
296
|
+
"integrity"
|
|
297
|
+
]
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
"required": [
|
|
301
|
+
"remoteRef"
|
|
302
|
+
]
|
|
303
|
+
},
|
|
304
|
+
"then": {
|
|
305
|
+
"properties": {
|
|
306
|
+
"actionType": {
|
|
307
|
+
"const": "npm-publish"
|
|
308
|
+
},
|
|
309
|
+
"status": {
|
|
310
|
+
"const": "skipped"
|
|
311
|
+
},
|
|
312
|
+
"preObserve": {
|
|
313
|
+
"const": "CONSISTENT"
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
"required": [
|
|
317
|
+
"actionType",
|
|
318
|
+
"status",
|
|
319
|
+
"preObserve"
|
|
320
|
+
]
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
]
|
|
284
324
|
}
|
|
285
325
|
},
|
|
286
326
|
"sourceAuthorityReceipts": {
|
|
@@ -33,6 +33,10 @@ description: Freeze an immutable release plan with local configuration, document
|
|
|
33
33
|
|
|
34
34
|
若用户明确要求 GitHub+npm 生产发布,加入 `--production`。该模式还会封存独立
|
|
35
35
|
Git commit/tree 和 npm tarball,并把路径、SHA/integrity、branch/tag 写入计划。
|
|
36
|
+
配置声明 `publicSourceAuthorityReceipt` 时,prepare 必须在所有 subject npm tarball
|
|
37
|
+
冻结后生成 `source-authority-receipt.json`,并把该文件的路径与 SHA-256 绑定到
|
|
38
|
+
coordinator unit 的 `github-release` action。该能力不支持非生产 prepare;不得手工
|
|
39
|
+
补写 receipt 或把私有 plan/run 字段复制进公开文件。
|
|
36
40
|
每个 npm tarball 在计划落盘前必须静态验证 `package.json` 的具体
|
|
37
41
|
`bin`/`main`/`module`/`types`/`typings`/`exports` 入口均为 tarball 内普通文件;
|
|
38
42
|
该门禁不依赖项目是否配置 `requiredPublicFiles` 或 `smokeBin`。通配符 exports 不做
|
|
@@ -7,6 +7,23 @@ import { parseNodeMajor, meetsMinimum, computeReadinessStatus } from '../src/cor
|
|
|
7
7
|
import { registerPathRedactor } from '../src/core/errors.mjs';
|
|
8
8
|
import { redactSensitivePaths } from '../src/core/redact.mjs';
|
|
9
9
|
|
|
10
|
+
// Process output errors can be emitted immediately after a large console
|
|
11
|
+
// write, before command routing reaches its exit path. Guard both streams at
|
|
12
|
+
// module initialization so EPIPE and other destination failures cannot become
|
|
13
|
+
// uncaught exceptions that replace the command's selected business exit code.
|
|
14
|
+
const outputStreamStates = new WeakMap();
|
|
15
|
+
|
|
16
|
+
function guardOutputStream(stream) {
|
|
17
|
+
const state = { failed: false };
|
|
18
|
+
outputStreamStates.set(stream, state);
|
|
19
|
+
stream.on('error', () => {
|
|
20
|
+
state.failed = true;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
guardOutputStream(process.stdout);
|
|
25
|
+
guardOutputStream(process.stderr);
|
|
26
|
+
|
|
10
27
|
// Install the path-redaction choke point eagerly and synchronously (static
|
|
11
28
|
// imports, no top-level await) so every ReleaseError constructed on any
|
|
12
29
|
// command path is redacted from the very first statement — in source mode and
|
|
@@ -21,6 +38,58 @@ const execFile = promisify(execFileCb);
|
|
|
21
38
|
|
|
22
39
|
const COMMANDS = new Set(['help', 'setup', 'assess', 'prepare', 'approve', 'publish', 'reconcile', 'verify', 'ship', 'attest', 'hooks', 'artifacts', 'docs', 'distribute', 'route', 'lineage']);
|
|
23
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Wait until writes already queued on a process output stream have reached
|
|
43
|
+
* the underlying destination. Stream failures do not replace the command's
|
|
44
|
+
* previously selected exit code.
|
|
45
|
+
*
|
|
46
|
+
* @param {NodeJS.WriteStream} stream
|
|
47
|
+
* @returns {Promise<void>}
|
|
48
|
+
*/
|
|
49
|
+
function flushOutputStream(stream) {
|
|
50
|
+
if (
|
|
51
|
+
!stream?.writable
|
|
52
|
+
|| stream.destroyed
|
|
53
|
+
|| stream.writableEnded
|
|
54
|
+
|| outputStreamStates.get(stream)?.failed
|
|
55
|
+
) {
|
|
56
|
+
return Promise.resolve();
|
|
57
|
+
}
|
|
58
|
+
return new Promise((resolveFlush) => {
|
|
59
|
+
let settled = false;
|
|
60
|
+
const finish = () => {
|
|
61
|
+
if (settled) return;
|
|
62
|
+
settled = true;
|
|
63
|
+
stream.off('error', finish);
|
|
64
|
+
resolveFlush();
|
|
65
|
+
};
|
|
66
|
+
stream.once('error', finish);
|
|
67
|
+
try {
|
|
68
|
+
// The callback runs after this empty write and every earlier console
|
|
69
|
+
// write have been flushed. This also covers a stream waiting for drain.
|
|
70
|
+
stream.write('', finish);
|
|
71
|
+
} catch {
|
|
72
|
+
finish();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Preserve CLI exit semantics while preventing buffered stdout/stderr from
|
|
79
|
+
* being discarded by process.exit().
|
|
80
|
+
*
|
|
81
|
+
* @param {number} exitCode
|
|
82
|
+
* @returns {Promise<never>}
|
|
83
|
+
*/
|
|
84
|
+
async function exitAfterFlush(exitCode) {
|
|
85
|
+
process.exitCode = exitCode;
|
|
86
|
+
await Promise.all([
|
|
87
|
+
flushOutputStream(process.stdout),
|
|
88
|
+
flushOutputStream(process.stderr),
|
|
89
|
+
]);
|
|
90
|
+
process.exit(exitCode);
|
|
91
|
+
}
|
|
92
|
+
|
|
24
93
|
/**
|
|
25
94
|
* Check if a command is available and get its version.
|
|
26
95
|
*
|
|
@@ -346,7 +415,7 @@ if (!command && (args.includes('--version') || args.includes('-v'))) {
|
|
|
346
415
|
} else {
|
|
347
416
|
console.log(pkg.version);
|
|
348
417
|
}
|
|
349
|
-
|
|
418
|
+
await exitAfterFlush(0);
|
|
350
419
|
}
|
|
351
420
|
|
|
352
421
|
if (!command || command === 'help') {
|
|
@@ -442,10 +511,10 @@ if (!command || command === 'help') {
|
|
|
442
511
|
// availability is informational and never blocks release readiness.
|
|
443
512
|
|
|
444
513
|
console.log(JSON.stringify(output, null, 2));
|
|
445
|
-
|
|
514
|
+
await exitAfterFlush(readiness.status === 'READY' ? 0 : 1);
|
|
446
515
|
} else {
|
|
447
516
|
printHelp();
|
|
448
|
-
|
|
517
|
+
await exitAfterFlush(0);
|
|
449
518
|
}
|
|
450
519
|
}
|
|
451
520
|
|
|
@@ -461,7 +530,7 @@ if (!COMMANDS.has(command)) {
|
|
|
461
530
|
console.error(`Error: Unknown command '${command}'`);
|
|
462
531
|
console.error('Run "release-skill help" for available commands.');
|
|
463
532
|
}
|
|
464
|
-
|
|
533
|
+
await exitAfterFlush(2);
|
|
465
534
|
}
|
|
466
535
|
|
|
467
536
|
// --- Setup command routing ---
|
|
@@ -513,7 +582,7 @@ if (command === 'setup') {
|
|
|
513
582
|
if (report.next) console.log(`Next: ${report.next}`);
|
|
514
583
|
}
|
|
515
584
|
const okStatuses = ['HOOKS_PROPOSAL_READY', 'HOOKS_APPENDED', 'HOOKS_NO_CHANGE', 'postpublish-discovery'];
|
|
516
|
-
|
|
585
|
+
await exitAfterFlush(okStatuses.includes(report.status ?? report.mode) ? 0 : 2);
|
|
517
586
|
} catch (err) {
|
|
518
587
|
if (hasJson) {
|
|
519
588
|
console.log(JSON.stringify({
|
|
@@ -525,7 +594,7 @@ if (command === 'setup') {
|
|
|
525
594
|
} else {
|
|
526
595
|
console.error(`Error: ${err.message}`);
|
|
527
596
|
}
|
|
528
|
-
|
|
597
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
529
598
|
}
|
|
530
599
|
}
|
|
531
600
|
|
|
@@ -540,7 +609,7 @@ if (command === 'setup') {
|
|
|
540
609
|
if (report.configPath) console.log(`Config: ${report.configPath}`);
|
|
541
610
|
if (report.next) console.log(`Next: ${report.next}`);
|
|
542
611
|
}
|
|
543
|
-
|
|
612
|
+
await exitAfterFlush(['READY_TO_WRITE', 'CONFIG_CREATED', 'ALREADY_CONFIGURED'].includes(report.status) ? 0 : 2);
|
|
544
613
|
} catch (err) {
|
|
545
614
|
if (hasJson) {
|
|
546
615
|
console.log(JSON.stringify({
|
|
@@ -552,7 +621,7 @@ if (command === 'setup') {
|
|
|
552
621
|
} else {
|
|
553
622
|
console.error(`Error: ${err.message}`);
|
|
554
623
|
}
|
|
555
|
-
|
|
624
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
556
625
|
}
|
|
557
626
|
}
|
|
558
627
|
|
|
@@ -575,7 +644,7 @@ if (command === 'assess') {
|
|
|
575
644
|
console.log(report.summary);
|
|
576
645
|
}
|
|
577
646
|
|
|
578
|
-
|
|
647
|
+
await exitAfterFlush(report.status === 'ASSESSED' ? 0 : 1);
|
|
579
648
|
} catch (err) {
|
|
580
649
|
if (hasJson) {
|
|
581
650
|
const errOutput = {
|
|
@@ -588,7 +657,7 @@ if (command === 'assess') {
|
|
|
588
657
|
} else {
|
|
589
658
|
console.error(`Error: ${err.message}`);
|
|
590
659
|
}
|
|
591
|
-
|
|
660
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
592
661
|
}
|
|
593
662
|
}
|
|
594
663
|
|
|
@@ -601,7 +670,7 @@ if (command === 'hooks') {
|
|
|
601
670
|
const message = 'hooks requires subcommand: hooks validate';
|
|
602
671
|
if (hasJson) console.log(JSON.stringify({ error: 'MISSING_PARAMETERS', message }));
|
|
603
672
|
else console.error(`Error: ${message}`);
|
|
604
|
-
|
|
673
|
+
await exitAfterFlush(1);
|
|
605
674
|
}
|
|
606
675
|
try {
|
|
607
676
|
const { validateDeclaredHooks } = await import('../src/commands/hooks.mjs');
|
|
@@ -616,7 +685,7 @@ if (command === 'hooks') {
|
|
|
616
685
|
console.log(`Declared hooks: ${result.status}`);
|
|
617
686
|
console.log(`Reusable receipt evidence: ${result.evidenceDir}`);
|
|
618
687
|
}
|
|
619
|
-
|
|
688
|
+
await exitAfterFlush(0);
|
|
620
689
|
} catch (err) {
|
|
621
690
|
if (hasJson) {
|
|
622
691
|
console.log(JSON.stringify({
|
|
@@ -626,7 +695,7 @@ if (command === 'hooks') {
|
|
|
626
695
|
exitCode: err.exitCode ?? 1,
|
|
627
696
|
}));
|
|
628
697
|
} else console.error(`Error: ${err.message}`);
|
|
629
|
-
|
|
698
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
630
699
|
}
|
|
631
700
|
}
|
|
632
701
|
|
|
@@ -710,7 +779,7 @@ if (command === 'ship') {
|
|
|
710
779
|
console.log(`Manual requirement [${requirement.platform}]: ${requirement.requirementPath}`);
|
|
711
780
|
}
|
|
712
781
|
}
|
|
713
|
-
|
|
782
|
+
await exitAfterFlush(0);
|
|
714
783
|
} catch (err) {
|
|
715
784
|
if (hasJson) {
|
|
716
785
|
console.log(JSON.stringify({
|
|
@@ -722,7 +791,7 @@ if (command === 'ship') {
|
|
|
722
791
|
} else {
|
|
723
792
|
console.error(`Error: ${err.message}`);
|
|
724
793
|
}
|
|
725
|
-
|
|
794
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
726
795
|
}
|
|
727
796
|
}
|
|
728
797
|
|
|
@@ -752,7 +821,7 @@ if (command === 'attest') {
|
|
|
752
821
|
console.log(`Bound plan digest: ${result.planDigest}`);
|
|
753
822
|
console.log(`Receipt: ${result.attestationPath}`);
|
|
754
823
|
}
|
|
755
|
-
|
|
824
|
+
await exitAfterFlush(0);
|
|
756
825
|
} catch (err) {
|
|
757
826
|
if (hasJson) {
|
|
758
827
|
console.log(JSON.stringify({
|
|
@@ -764,7 +833,7 @@ if (command === 'attest') {
|
|
|
764
833
|
} else {
|
|
765
834
|
console.error(`Error: ${err.message}`);
|
|
766
835
|
}
|
|
767
|
-
|
|
836
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
768
837
|
}
|
|
769
838
|
}
|
|
770
839
|
|
|
@@ -869,7 +938,7 @@ if (command === 'prepare') {
|
|
|
869
938
|
}
|
|
870
939
|
}
|
|
871
940
|
|
|
872
|
-
|
|
941
|
+
await exitAfterFlush(0);
|
|
873
942
|
} catch (err) {
|
|
874
943
|
if (hasJson) {
|
|
875
944
|
const errOutput = {
|
|
@@ -882,7 +951,7 @@ if (command === 'prepare') {
|
|
|
882
951
|
} else {
|
|
883
952
|
console.error(`Error: ${err.message}`);
|
|
884
953
|
}
|
|
885
|
-
|
|
954
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
886
955
|
}
|
|
887
956
|
}
|
|
888
957
|
|
|
@@ -909,7 +978,7 @@ if (command === 'approve') {
|
|
|
909
978
|
} else {
|
|
910
979
|
console.error(`Error: ${msg}`);
|
|
911
980
|
}
|
|
912
|
-
|
|
981
|
+
await exitAfterFlush(1);
|
|
913
982
|
}
|
|
914
983
|
|
|
915
984
|
// --- Checkpoint-level postPublish hook approval (v0.6.3 R1, review N-6) ---
|
|
@@ -935,7 +1004,7 @@ if (command === 'approve') {
|
|
|
935
1004
|
console.log(` ${key}: ${typeof value === 'object' ? JSON.stringify(value) : value}`);
|
|
936
1005
|
}
|
|
937
1006
|
}
|
|
938
|
-
|
|
1007
|
+
await exitAfterFlush(0);
|
|
939
1008
|
} catch (err) {
|
|
940
1009
|
if (hasJson) {
|
|
941
1010
|
console.log(JSON.stringify({
|
|
@@ -946,7 +1015,7 @@ if (command === 'approve') {
|
|
|
946
1015
|
} else {
|
|
947
1016
|
console.error(`Error: ${err.message}`);
|
|
948
1017
|
}
|
|
949
|
-
|
|
1018
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
950
1019
|
}
|
|
951
1020
|
}
|
|
952
1021
|
|
|
@@ -979,7 +1048,7 @@ if (command === 'approve') {
|
|
|
979
1048
|
console.log(`Expires at: ${record.expiresAt}`);
|
|
980
1049
|
}
|
|
981
1050
|
|
|
982
|
-
|
|
1051
|
+
await exitAfterFlush(0);
|
|
983
1052
|
} catch (err) {
|
|
984
1053
|
if (hasJson) {
|
|
985
1054
|
const errOutput = {
|
|
@@ -991,7 +1060,7 @@ if (command === 'approve') {
|
|
|
991
1060
|
} else {
|
|
992
1061
|
console.error(`Error: ${err.message}`);
|
|
993
1062
|
}
|
|
994
|
-
|
|
1063
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
995
1064
|
}
|
|
996
1065
|
}
|
|
997
1066
|
|
|
@@ -1015,7 +1084,7 @@ if (command === 'reconcile') {
|
|
|
1015
1084
|
} else {
|
|
1016
1085
|
console.error(`Error: ${msg}`);
|
|
1017
1086
|
}
|
|
1018
|
-
|
|
1087
|
+
await exitAfterFlush(1);
|
|
1019
1088
|
}
|
|
1020
1089
|
|
|
1021
1090
|
try {
|
|
@@ -1050,7 +1119,7 @@ if (command === 'reconcile') {
|
|
|
1050
1119
|
}
|
|
1051
1120
|
}
|
|
1052
1121
|
|
|
1053
|
-
|
|
1122
|
+
await exitAfterFlush(result.status === 'PUBLISHED' ? 0 : 1);
|
|
1054
1123
|
} catch (err) {
|
|
1055
1124
|
if (hasJson) {
|
|
1056
1125
|
const errOutput = {
|
|
@@ -1062,7 +1131,7 @@ if (command === 'reconcile') {
|
|
|
1062
1131
|
} else {
|
|
1063
1132
|
console.error(`Error: ${err.message}`);
|
|
1064
1133
|
}
|
|
1065
|
-
|
|
1134
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
1066
1135
|
}
|
|
1067
1136
|
}
|
|
1068
1137
|
|
|
@@ -1085,7 +1154,7 @@ if (command === 'verify') {
|
|
|
1085
1154
|
} else {
|
|
1086
1155
|
console.error(`Error: ${msg}`);
|
|
1087
1156
|
}
|
|
1088
|
-
|
|
1157
|
+
await exitAfterFlush(1);
|
|
1089
1158
|
}
|
|
1090
1159
|
|
|
1091
1160
|
try {
|
|
@@ -1127,7 +1196,7 @@ if (command === 'verify') {
|
|
|
1127
1196
|
}
|
|
1128
1197
|
}
|
|
1129
1198
|
|
|
1130
|
-
|
|
1199
|
+
await exitAfterFlush(result.status === 'VERIFIED' ? 0 : 1);
|
|
1131
1200
|
} catch (err) {
|
|
1132
1201
|
if (hasJson) {
|
|
1133
1202
|
const errOutput = {
|
|
@@ -1139,7 +1208,7 @@ if (command === 'verify') {
|
|
|
1139
1208
|
} else {
|
|
1140
1209
|
console.error(`Error: ${err.message}`);
|
|
1141
1210
|
}
|
|
1142
|
-
|
|
1211
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
1143
1212
|
}
|
|
1144
1213
|
}
|
|
1145
1214
|
|
|
@@ -1161,7 +1230,7 @@ if (command === 'publish') {
|
|
|
1161
1230
|
} else {
|
|
1162
1231
|
console.error(`Error: ${msg}`);
|
|
1163
1232
|
}
|
|
1164
|
-
|
|
1233
|
+
await exitAfterFlush(1);
|
|
1165
1234
|
}
|
|
1166
1235
|
|
|
1167
1236
|
try {
|
|
@@ -1196,7 +1265,7 @@ if (command === 'publish') {
|
|
|
1196
1265
|
}
|
|
1197
1266
|
}
|
|
1198
1267
|
|
|
1199
|
-
|
|
1268
|
+
await exitAfterFlush(result.status === 'PUBLISHED' ? 0 : 1);
|
|
1200
1269
|
} catch (err) {
|
|
1201
1270
|
if (hasJson) {
|
|
1202
1271
|
const errOutput = {
|
|
@@ -1208,7 +1277,7 @@ if (command === 'publish') {
|
|
|
1208
1277
|
} else {
|
|
1209
1278
|
console.error(`Error: ${err.message}`);
|
|
1210
1279
|
}
|
|
1211
|
-
|
|
1280
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
1212
1281
|
}
|
|
1213
1282
|
}
|
|
1214
1283
|
|
|
@@ -1242,7 +1311,7 @@ if (command === 'artifacts') {
|
|
|
1242
1311
|
'BASE_UNAVAILABLE', 'POLICY_INVALID', 'PATH_UNSAFE',
|
|
1243
1312
|
'CONFLICT', 'DIRTY_SCOPE_CONFLICT',
|
|
1244
1313
|
]);
|
|
1245
|
-
|
|
1314
|
+
await exitAfterFlush(blockingStatuses.has(result.status) ? 1 : 0);
|
|
1246
1315
|
} catch (err) {
|
|
1247
1316
|
if (hasJson) {
|
|
1248
1317
|
const errOutput = {
|
|
@@ -1259,7 +1328,7 @@ if (command === 'artifacts') {
|
|
|
1259
1328
|
} else {
|
|
1260
1329
|
console.error(`Error: ${err.message}`);
|
|
1261
1330
|
}
|
|
1262
|
-
|
|
1331
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
1263
1332
|
}
|
|
1264
1333
|
}
|
|
1265
1334
|
|
|
@@ -1369,7 +1438,7 @@ if (command === 'docs') {
|
|
|
1369
1438
|
}
|
|
1370
1439
|
}
|
|
1371
1440
|
|
|
1372
|
-
|
|
1441
|
+
await exitAfterFlush(0);
|
|
1373
1442
|
} catch (err) {
|
|
1374
1443
|
// docs parameter errors must surface the stable JSON error shape even in
|
|
1375
1444
|
// text mode (CLI parameter validation precedes any service I/O).
|
|
@@ -1379,7 +1448,7 @@ if (command === 'docs') {
|
|
|
1379
1448
|
details: err.details ?? {},
|
|
1380
1449
|
exitCode: err.exitCode ?? 1,
|
|
1381
1450
|
}));
|
|
1382
|
-
|
|
1451
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
1383
1452
|
}
|
|
1384
1453
|
}
|
|
1385
1454
|
|
|
@@ -1426,7 +1495,7 @@ if (command === 'distribute') {
|
|
|
1426
1495
|
console.log(` write-downstream: ${preset.writeDownstream}; target optional: ${preset.targetOptional}; status: ${status}`);
|
|
1427
1496
|
}
|
|
1428
1497
|
}
|
|
1429
|
-
|
|
1498
|
+
await exitAfterFlush(0);
|
|
1430
1499
|
}
|
|
1431
1500
|
|
|
1432
1501
|
// Handle --help explicitly
|
|
@@ -1468,7 +1537,7 @@ Description:
|
|
|
1468
1537
|
} else {
|
|
1469
1538
|
console.log(helpText);
|
|
1470
1539
|
}
|
|
1471
|
-
|
|
1540
|
+
await exitAfterFlush(0);
|
|
1472
1541
|
}
|
|
1473
1542
|
|
|
1474
1543
|
if (!planPath || !runPath || !approvalPath) {
|
|
@@ -1478,7 +1547,7 @@ Description:
|
|
|
1478
1547
|
} else {
|
|
1479
1548
|
console.error(`Error: ${msg}`);
|
|
1480
1549
|
}
|
|
1481
|
-
|
|
1550
|
+
await exitAfterFlush(1);
|
|
1482
1551
|
}
|
|
1483
1552
|
|
|
1484
1553
|
try {
|
|
@@ -1522,7 +1591,7 @@ Description:
|
|
|
1522
1591
|
}
|
|
1523
1592
|
}
|
|
1524
1593
|
|
|
1525
|
-
|
|
1594
|
+
await exitAfterFlush(result.status === 'DISTRIBUTED' ? 0 : 1);
|
|
1526
1595
|
} catch (err) {
|
|
1527
1596
|
if (hasJson) {
|
|
1528
1597
|
const errOutput = {
|
|
@@ -1535,7 +1604,7 @@ Description:
|
|
|
1535
1604
|
} else {
|
|
1536
1605
|
console.error(`Error: ${err.message}`);
|
|
1537
1606
|
}
|
|
1538
|
-
|
|
1607
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
1539
1608
|
}
|
|
1540
1609
|
}
|
|
1541
1610
|
|
|
@@ -1558,7 +1627,7 @@ if (command === 'route') {
|
|
|
1558
1627
|
}
|
|
1559
1628
|
}
|
|
1560
1629
|
|
|
1561
|
-
|
|
1630
|
+
await exitAfterFlush(result.exitCode ?? 0);
|
|
1562
1631
|
} catch (err) {
|
|
1563
1632
|
if (hasJson) {
|
|
1564
1633
|
console.log(JSON.stringify({
|
|
@@ -1570,7 +1639,7 @@ if (command === 'route') {
|
|
|
1570
1639
|
} else {
|
|
1571
1640
|
console.error(`Error: ${err.message}`);
|
|
1572
1641
|
}
|
|
1573
|
-
|
|
1642
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
1574
1643
|
}
|
|
1575
1644
|
}
|
|
1576
1645
|
|
|
@@ -1592,7 +1661,7 @@ if (command === 'lineage') {
|
|
|
1592
1661
|
}
|
|
1593
1662
|
}
|
|
1594
1663
|
|
|
1595
|
-
|
|
1664
|
+
await exitAfterFlush(result.status === 'ERROR' ? 1 : 0);
|
|
1596
1665
|
} catch (err) {
|
|
1597
1666
|
if (hasJson) {
|
|
1598
1667
|
console.log(JSON.stringify({
|
|
@@ -1604,10 +1673,10 @@ if (command === 'lineage') {
|
|
|
1604
1673
|
} else {
|
|
1605
1674
|
console.error(`Error: ${err.message}`);
|
|
1606
1675
|
}
|
|
1607
|
-
|
|
1676
|
+
await exitAfterFlush(err.exitCode ?? 1);
|
|
1608
1677
|
}
|
|
1609
1678
|
}
|
|
1610
1679
|
|
|
1611
1680
|
// Placeholder: remaining commands will be wired in later commands
|
|
1612
1681
|
console.error(`Command '${command}' is not yet implemented.`);
|
|
1613
|
-
|
|
1682
|
+
await exitAfterFlush(1);
|