scene-capability-engine 3.6.45 → 3.6.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/docs/releases/README.md +1 -0
  3. package/docs/releases/v3.6.46.md +23 -0
  4. package/docs/zh/releases/README.md +1 -0
  5. package/docs/zh/releases/v3.6.46.md +23 -0
  6. package/package.json +4 -2
  7. package/scripts/auto-strategy-router.js +231 -0
  8. package/scripts/capability-mapping-report.js +339 -0
  9. package/scripts/check-branding-consistency.js +140 -0
  10. package/scripts/check-sce-tracking.js +54 -0
  11. package/scripts/check-skip-allowlist.js +94 -0
  12. package/scripts/errorbook-registry-health-gate.js +172 -0
  13. package/scripts/errorbook-release-gate.js +132 -0
  14. package/scripts/failure-attribution-repair.js +317 -0
  15. package/scripts/git-managed-gate.js +464 -0
  16. package/scripts/interactive-approval-event-projection.js +400 -0
  17. package/scripts/interactive-approval-workflow.js +829 -0
  18. package/scripts/interactive-authorization-tier-evaluate.js +413 -0
  19. package/scripts/interactive-change-plan-gate.js +225 -0
  20. package/scripts/interactive-context-bridge.js +617 -0
  21. package/scripts/interactive-customization-loop.js +1690 -0
  22. package/scripts/interactive-dialogue-governance.js +842 -0
  23. package/scripts/interactive-feedback-log.js +253 -0
  24. package/scripts/interactive-flow-smoke.js +238 -0
  25. package/scripts/interactive-flow.js +1059 -0
  26. package/scripts/interactive-governance-report.js +1112 -0
  27. package/scripts/interactive-intent-build.js +707 -0
  28. package/scripts/interactive-loop-smoke.js +215 -0
  29. package/scripts/interactive-moqui-adapter.js +304 -0
  30. package/scripts/interactive-plan-build.js +426 -0
  31. package/scripts/interactive-runtime-policy-evaluate.js +495 -0
  32. package/scripts/interactive-work-order-build.js +552 -0
  33. package/scripts/matrix-regression-gate.js +167 -0
  34. package/scripts/moqui-core-regression-suite.js +397 -0
  35. package/scripts/moqui-lexicon-audit.js +651 -0
  36. package/scripts/moqui-matrix-remediation-phased-runner.js +865 -0
  37. package/scripts/moqui-matrix-remediation-queue.js +852 -0
  38. package/scripts/moqui-metadata-extract.js +1340 -0
  39. package/scripts/moqui-rebuild-gate.js +167 -0
  40. package/scripts/moqui-release-summary.js +729 -0
  41. package/scripts/moqui-standard-rebuild.js +1370 -0
  42. package/scripts/moqui-template-baseline-report.js +682 -0
  43. package/scripts/npm-package-runtime-asset-check.js +221 -0
  44. package/scripts/problem-closure-gate.js +441 -0
  45. package/scripts/release-asset-integrity-check.js +216 -0
  46. package/scripts/release-asset-nonempty-normalize.js +166 -0
  47. package/scripts/release-drift-evaluate.js +223 -0
  48. package/scripts/release-drift-signals.js +255 -0
  49. package/scripts/release-governance-snapshot-export.js +132 -0
  50. package/scripts/release-ops-weekly-summary.js +934 -0
  51. package/scripts/release-risk-remediation-bundle.js +315 -0
  52. package/scripts/release-weekly-ops-gate.js +423 -0
  53. package/scripts/state-migration-reconciliation-gate.js +110 -0
  54. package/scripts/state-storage-tiering-audit.js +337 -0
  55. package/scripts/steering-content-audit.js +393 -0
  56. package/scripts/symbol-evidence-locate.js +366 -0
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { execSync } = require('child_process');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+
7
+ const LEGACY_PATTERNS = [
8
+ {
9
+ label: 'legacy CLI alias',
10
+ regex: /\bkse\b/gi
11
+ },
12
+ {
13
+ label: 'legacy social handle',
14
+ regex: /@kse_dev/gi
15
+ },
16
+ {
17
+ label: 'legacy GitHub repository URL',
18
+ regex: /https:\/\/github\.com\/heguangyong\/kiro-spec-engine/gi
19
+ },
20
+ {
21
+ label: 'legacy template repository name',
22
+ regex: /\bkse-spec-templates\b/gi
23
+ },
24
+ {
25
+ label: 'legacy product naming',
26
+ regex: /\bKiro Spec Engine\b|\bScene Capability Orchestrator\b|场景能力编排引擎/g
27
+ },
28
+ {
29
+ label: 'legacy Kiro IDE wording',
30
+ regex: /\bKiro IDE\b/gi
31
+ },
32
+ {
33
+ label: 'legacy npm package name',
34
+ regex: /\bsco-engine\b/gi
35
+ }
36
+ ];
37
+
38
+ const EXCLUDE_PREFIXES = [
39
+ '.sce/',
40
+ 'tests/fixtures/',
41
+ 'node_modules/'
42
+ ];
43
+
44
+ const EXCLUDE_FILES = new Set([
45
+ 'scripts/check-branding-consistency.js'
46
+ ]);
47
+
48
+ const HISTORY_ALLOW_PREFIXES = [
49
+ 'docs/releases/',
50
+ 'docs/zh/releases/'
51
+ ];
52
+
53
+ const HISTORY_ALLOW_FILES = new Set([
54
+ 'CHANGELOG.md'
55
+ ]);
56
+
57
+ const TEXT_EXTENSIONS = new Set([
58
+ '.js', '.json', '.md', '.txt', '.yml', '.yaml'
59
+ ]);
60
+
61
+ function getTrackedFiles() {
62
+ const output = execSync('git ls-files', { encoding: 'utf8' });
63
+ return output
64
+ .split(/\r?\n/)
65
+ .map((line) => line.trim())
66
+ .filter(Boolean);
67
+ }
68
+
69
+ function shouldScan(filePath) {
70
+ if (EXCLUDE_FILES.has(filePath)) {
71
+ return false;
72
+ }
73
+
74
+ if (EXCLUDE_PREFIXES.some((prefix) => filePath.startsWith(prefix))) {
75
+ return false;
76
+ }
77
+
78
+ const ext = path.extname(filePath).toLowerCase();
79
+ return TEXT_EXTENSIONS.has(ext);
80
+ }
81
+
82
+ function isHistoryDocument(filePath) {
83
+ return HISTORY_ALLOW_FILES.has(filePath)
84
+ || HISTORY_ALLOW_PREFIXES.some((prefix) => filePath.startsWith(prefix));
85
+ }
86
+
87
+ function scanFile(filePath) {
88
+ let content = '';
89
+ try {
90
+ content = fs.readFileSync(filePath, 'utf8');
91
+ } catch (_error) {
92
+ return [];
93
+ }
94
+
95
+ const hits = [];
96
+
97
+ for (const pattern of LEGACY_PATTERNS) {
98
+ const matches = content.match(pattern.regex);
99
+ if (matches && matches.length > 0) {
100
+ if (isHistoryDocument(filePath)) {
101
+ continue;
102
+ }
103
+ hits.push({
104
+ label: pattern.label,
105
+ count: matches.length
106
+ });
107
+ }
108
+ }
109
+
110
+ return hits;
111
+ }
112
+
113
+ function main() {
114
+ const files = getTrackedFiles().filter(shouldScan);
115
+ const violations = [];
116
+
117
+ for (const filePath of files) {
118
+ const hits = scanFile(filePath);
119
+ if (hits.length > 0) {
120
+ violations.push({ filePath, hits });
121
+ }
122
+ }
123
+
124
+ if (violations.length === 0) {
125
+ console.log('Branding consistency check passed: no legacy naming references found.');
126
+ return;
127
+ }
128
+
129
+ console.error('Branding consistency check failed. Found legacy naming references:');
130
+ for (const violation of violations) {
131
+ const summary = violation.hits
132
+ .map((hit) => `${hit.label} x${hit.count}`)
133
+ .join(', ');
134
+ console.error(`- ${violation.filePath}: ${summary}`);
135
+ }
136
+
137
+ process.exit(1);
138
+ }
139
+
140
+ main();
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { auditSceTracking } = require('../lib/workspace/sce-tracking-audit');
4
+
5
+ function printTextReport(report) {
6
+ if (report.passed) {
7
+ console.log('SCE tracking audit passed.');
8
+ console.log(`Fixture tracked specs: ${report.summary.fixture_spec_files}`);
9
+ console.log(`Fixture tracked templates: ${report.summary.fixture_template_files}`);
10
+ return;
11
+ }
12
+
13
+ console.error('SCE tracking audit failed.');
14
+ if (report.missing_required_files.length > 0) {
15
+ console.error('Missing required tracked files:');
16
+ for (const filePath of report.missing_required_files) {
17
+ console.error(` - ${filePath}`);
18
+ }
19
+ }
20
+ if (report.summary.fixture_spec_files === 0) {
21
+ console.error('No tracked fixture spec files were found under tests/fixtures/.../.sce/specs.');
22
+ }
23
+ if (report.summary.fixture_template_files === 0) {
24
+ console.error('No tracked fixture template files were found under tests/fixtures/.../.sce/templates.');
25
+ }
26
+ if (report.fixture.disallowed_tracked_files.length > 0) {
27
+ console.error('Disallowed tracked fixture runtime files found:');
28
+ for (const filePath of report.fixture.disallowed_tracked_files) {
29
+ console.error(` - ${filePath}`);
30
+ }
31
+ }
32
+ }
33
+
34
+ function main() {
35
+ const json = process.argv.includes('--json');
36
+ const report = auditSceTracking(process.cwd());
37
+
38
+ if (json) {
39
+ console.log(JSON.stringify(report, null, 2));
40
+ } else {
41
+ printTextReport(report);
42
+ }
43
+
44
+ if (!report.passed) {
45
+ process.exit(1);
46
+ }
47
+ }
48
+
49
+ try {
50
+ main();
51
+ } catch (error) {
52
+ console.error(`SCE tracking audit error: ${error.message}`);
53
+ process.exit(1);
54
+ }
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const repoRoot = path.resolve(__dirname, '..');
7
+ const testsRoot = path.join(repoRoot, 'tests');
8
+ const allowlistPath = path.join(repoRoot, 'tests', 'skip-allowlist.txt');
9
+
10
+ function walkFiles(dirPath) {
11
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
12
+ const files = [];
13
+
14
+ for (const entry of entries) {
15
+ const absolutePath = path.join(dirPath, entry.name);
16
+ if (entry.isDirectory()) {
17
+ files.push(...walkFiles(absolutePath));
18
+ continue;
19
+ }
20
+
21
+ if (entry.isFile() && (entry.name.endsWith('.test.js') || entry.name.endsWith('.spec.js'))) {
22
+ files.push(absolutePath);
23
+ }
24
+ }
25
+
26
+ return files;
27
+ }
28
+
29
+ function loadAllowlist(filePath) {
30
+ if (!fs.existsSync(filePath)) {
31
+ throw new Error(`Allowlist file not found: ${filePath}`);
32
+ }
33
+
34
+ return fs.readFileSync(filePath, 'utf8')
35
+ .split(/\r?\n/)
36
+ .map(line => line.trim())
37
+ .filter(line => line.length > 0 && !line.startsWith('#'));
38
+ }
39
+
40
+ function collectSkippedTests() {
41
+ const testFiles = walkFiles(testsRoot);
42
+ const skipPattern = /\b(?:test|it|describe)\.skip\(\s*(['"`])([^'"`]+)\1/g;
43
+ const skipped = [];
44
+
45
+ for (const filePath of testFiles) {
46
+ const content = fs.readFileSync(filePath, 'utf8');
47
+ const relativePath = path.relative(repoRoot, filePath).replace(/\\/g, '/');
48
+ let match = skipPattern.exec(content);
49
+
50
+ while (match) {
51
+ skipped.push(`${relativePath}::${match[2]}`);
52
+ match = skipPattern.exec(content);
53
+ }
54
+ }
55
+
56
+ return skipped.sort();
57
+ }
58
+
59
+ function main() {
60
+ const allowlist = loadAllowlist(allowlistPath);
61
+ const skipped = collectSkippedTests();
62
+
63
+ const allowSet = new Set(allowlist);
64
+ const skippedSet = new Set(skipped);
65
+
66
+ const unexpected = skipped.filter(item => !allowSet.has(item));
67
+ const stale = allowlist.filter(item => !skippedSet.has(item));
68
+
69
+ console.log(`Skip audit: ${skipped.length} skipped tests, ${allowlist.length} allowlisted entries`);
70
+
71
+ if (stale.length > 0) {
72
+ console.log('Stale allowlist entries (safe to remove):');
73
+ for (const item of stale) {
74
+ console.log(` - ${item}`);
75
+ }
76
+ }
77
+
78
+ if (unexpected.length > 0) {
79
+ console.error('Unexpected skipped tests found:');
80
+ for (const item of unexpected) {
81
+ console.error(` - ${item}`);
82
+ }
83
+ process.exit(1);
84
+ }
85
+
86
+ console.log('Skip audit passed.');
87
+ }
88
+
89
+ try {
90
+ main();
91
+ } catch (error) {
92
+ console.error(`Skip audit failed: ${error.message}`);
93
+ process.exit(1);
94
+ }
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const path = require('path');
5
+ const { runErrorbookRegistryHealthCommand } = require('../lib/commands/errorbook');
6
+
7
+ function parseBoolean(value, fallback = false) {
8
+ if (typeof value === 'boolean') {
9
+ return value;
10
+ }
11
+ const normalized = `${value || ''}`.trim().toLowerCase();
12
+ if (!normalized) {
13
+ return fallback;
14
+ }
15
+ if (['1', 'true', 'yes', 'on', 'y'].includes(normalized)) {
16
+ return true;
17
+ }
18
+ if (['0', 'false', 'no', 'off', 'n'].includes(normalized)) {
19
+ return false;
20
+ }
21
+ return fallback;
22
+ }
23
+
24
+ function parseArgs(argv = [], env = process.env) {
25
+ const options = {
26
+ strict: parseBoolean(env.SCE_REGISTRY_HEALTH_STRICT, false),
27
+ json: false,
28
+ projectPath: process.cwd(),
29
+ maxShards: 8,
30
+ shardSample: 2
31
+ };
32
+
33
+ for (let index = 0; index < argv.length; index += 1) {
34
+ const token = argv[index];
35
+ const next = argv[index + 1];
36
+
37
+ if (token === '--strict') {
38
+ options.strict = true;
39
+ } else if (token === '--no-strict') {
40
+ options.strict = false;
41
+ } else if (token === '--json') {
42
+ options.json = true;
43
+ } else if (token === '--project-path' && next) {
44
+ options.projectPath = path.resolve(next);
45
+ index += 1;
46
+ } else if (token === '--config' && next) {
47
+ options.config = next;
48
+ index += 1;
49
+ } else if (token === '--cache' && next) {
50
+ options.cache = next;
51
+ index += 1;
52
+ } else if (token === '--source' && next) {
53
+ options.source = next;
54
+ index += 1;
55
+ } else if (token === '--source-name' && next) {
56
+ options.sourceName = next;
57
+ index += 1;
58
+ } else if (token === '--index' && next) {
59
+ options.index = next;
60
+ index += 1;
61
+ } else if (token === '--max-shards' && next) {
62
+ options.maxShards = Number.parseInt(next, 10);
63
+ index += 1;
64
+ } else if (token === '--shard-sample' && next) {
65
+ options.shardSample = Number.parseInt(next, 10);
66
+ index += 1;
67
+ } else if (token === '--help' || token === '-h') {
68
+ options.help = true;
69
+ }
70
+ }
71
+
72
+ return options;
73
+ }
74
+
75
+ function printHelp() {
76
+ const lines = [
77
+ 'Usage: node scripts/errorbook-registry-health-gate.js [options]',
78
+ '',
79
+ 'Options:',
80
+ ' --strict Exit with code 2 when health check reports errors',
81
+ ' --no-strict Force advisory mode even if env is strict',
82
+ ' --project-path <path> Override project path (default: cwd)',
83
+ ' --config <path> Registry config path override',
84
+ ' --cache <path> Registry cache path override',
85
+ ' --source <url-or-path> Override registry source JSON',
86
+ ' --source-name <name> Override registry source label',
87
+ ' --index <url-or-path> Override registry index JSON',
88
+ ' --max-shards <n> Max index-resolved shards to validate (default: 8)',
89
+ ' --shard-sample <n> Number of shard files to fetch for validation (default: 2)',
90
+ ' --json Print JSON payload',
91
+ ' -h, --help Show this help',
92
+ '',
93
+ 'Environment:',
94
+ ' SCE_REGISTRY_HEALTH_STRICT=1 enables strict mode by default'
95
+ ];
96
+ process.stdout.write(`${lines.join('\n')}\n`);
97
+ }
98
+
99
+ async function runErrorbookRegistryHealthGateScript(options = {}) {
100
+ const health = await runErrorbookRegistryHealthCommand({
101
+ config: options.config,
102
+ cache: options.cache,
103
+ source: options.source,
104
+ sourceName: options.sourceName,
105
+ index: options.index,
106
+ maxShards: options.maxShards,
107
+ shardSample: options.shardSample,
108
+ silent: true
109
+ }, {
110
+ projectPath: options.projectPath
111
+ });
112
+
113
+ if (options.json) {
114
+ process.stdout.write(`${JSON.stringify({
115
+ ...health,
116
+ mode: 'errorbook-registry-health-gate',
117
+ strict: options.strict === true
118
+ }, null, 2)}\n`);
119
+ } else if (health.passed) {
120
+ process.stdout.write('[errorbook-registry-health-gate] passed\n');
121
+ process.stdout.write(
122
+ `[errorbook-registry-health-gate] sources=${health.config.source_count} warnings=${health.warning_count} errors=0\n`
123
+ );
124
+ } else {
125
+ process.stdout.write('[errorbook-registry-health-gate] alert\n');
126
+ process.stdout.write(
127
+ `[errorbook-registry-health-gate] sources=${health.config.source_count} warnings=${health.warning_count} errors=${health.error_count}\n`
128
+ );
129
+ health.errors.slice(0, 20).forEach((message) => {
130
+ process.stdout.write(`[errorbook-registry-health-gate] error=${message}\n`);
131
+ });
132
+ }
133
+
134
+ const exitCode = options.strict && !health.passed ? 2 : 0;
135
+ return {
136
+ ...health,
137
+ mode: 'errorbook-registry-health-gate',
138
+ strict: options.strict === true,
139
+ exit_code: exitCode
140
+ };
141
+ }
142
+
143
+ if (require.main === module) {
144
+ const options = parseArgs(process.argv.slice(2));
145
+ if (options.help) {
146
+ printHelp();
147
+ process.exit(0);
148
+ }
149
+
150
+ runErrorbookRegistryHealthGateScript(options)
151
+ .then((result) => {
152
+ process.exitCode = result.exit_code;
153
+ })
154
+ .catch((error) => {
155
+ const payload = {
156
+ mode: 'errorbook-registry-health-gate',
157
+ passed: false,
158
+ error: error.message
159
+ };
160
+ if (options.json) {
161
+ process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
162
+ } else {
163
+ process.stderr.write(`[errorbook-registry-health-gate] error=${error.message}\n`);
164
+ }
165
+ process.exitCode = 1;
166
+ });
167
+ }
168
+
169
+ module.exports = {
170
+ parseArgs,
171
+ runErrorbookRegistryHealthGateScript
172
+ };
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const path = require('path');
5
+ const { evaluateErrorbookReleaseGate } = require('../lib/commands/errorbook');
6
+
7
+ function parseArgs(argv = []) {
8
+ const options = {
9
+ minRisk: 'high',
10
+ minQuality: 70,
11
+ includeVerified: false,
12
+ failOnBlock: false,
13
+ json: false,
14
+ projectPath: process.cwd()
15
+ };
16
+
17
+ for (let index = 0; index < argv.length; index += 1) {
18
+ const token = argv[index];
19
+ const next = argv[index + 1];
20
+
21
+ if (token === '--min-risk' && next) {
22
+ options.minRisk = `${next}`.trim().toLowerCase();
23
+ index += 1;
24
+ } else if (token === '--min-quality' && next) {
25
+ const parsed = Number.parseInt(`${next}`, 10);
26
+ if (Number.isFinite(parsed)) {
27
+ options.minQuality = Math.max(0, Math.min(100, parsed));
28
+ }
29
+ index += 1;
30
+ } else if (token === '--include-verified') {
31
+ options.includeVerified = true;
32
+ } else if (token === '--fail-on-block') {
33
+ options.failOnBlock = true;
34
+ } else if (token === '--json') {
35
+ options.json = true;
36
+ } else if (token === '--project-path' && next) {
37
+ options.projectPath = path.resolve(next);
38
+ index += 1;
39
+ } else if (token === '--help' || token === '-h') {
40
+ options.help = true;
41
+ }
42
+ }
43
+
44
+ return options;
45
+ }
46
+
47
+ function printHelp() {
48
+ const lines = [
49
+ 'Usage: node scripts/errorbook-release-gate.js [options]',
50
+ '',
51
+ 'Options:',
52
+ ' --min-risk <level> Risk threshold to block release (low|medium|high, default: high)',
53
+ ' --min-quality <0-100> Minimum curation quality for unresolved entries (default: 70)',
54
+ ' --include-verified Also inspect verified (non-promoted) entries for risk threshold',
55
+ ' (temporary mitigation policy is always enforced for active entries)',
56
+ ' --fail-on-block Exit with code 2 when gate is blocked',
57
+ ' --project-path <path> Override project path (default: cwd)',
58
+ ' --json Print JSON payload',
59
+ ' -h, --help Show this help'
60
+ ];
61
+ process.stdout.write(`${lines.join('\n')}\n`);
62
+ }
63
+
64
+ async function runErrorbookReleaseGateScript(options = {}) {
65
+ const payload = await evaluateErrorbookReleaseGate({
66
+ minRisk: options.minRisk,
67
+ minQuality: options.minQuality,
68
+ includeVerified: options.includeVerified
69
+ }, {
70
+ projectPath: options.projectPath
71
+ });
72
+
73
+ if (options.json) {
74
+ process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
75
+ } else if (payload.passed) {
76
+ process.stdout.write('[errorbook-release-gate] passed\n');
77
+ process.stdout.write(`[errorbook-release-gate] inspected=${payload.inspected_count} blocked=0\n`);
78
+ } else {
79
+ process.stdout.write('[errorbook-release-gate] blocked\n');
80
+ process.stdout.write(
81
+ `[errorbook-release-gate] inspected=${payload.inspected_count} blocked=${payload.blocked_count} min-risk=${payload.gate.min_risk} min-quality=${payload.gate.min_quality}\n`
82
+ );
83
+ process.stdout.write(
84
+ `[errorbook-release-gate] risk-blocked=${payload.risk_blocked_count || 0} curation-blocked=${payload.curation_blocked_count || 0} mitigation-blocked=${payload.mitigation_blocked_count || 0}\n`
85
+ );
86
+ payload.blocked_entries.slice(0, 20).forEach((item) => {
87
+ const policy = Array.isArray(item.policy_violations) && item.policy_violations.length > 0
88
+ ? ` policy=${item.policy_violations.join('|')}`
89
+ : '';
90
+ process.stdout.write(
91
+ `[errorbook-release-gate] entry=${item.id} risk=${item.risk} status=${item.status} quality=${item.quality_score}${policy}\n`
92
+ );
93
+ });
94
+ }
95
+
96
+ const exitCode = options.failOnBlock && !payload.passed ? 2 : 0;
97
+ return {
98
+ ...payload,
99
+ exit_code: exitCode
100
+ };
101
+ }
102
+
103
+ if (require.main === module) {
104
+ const options = parseArgs(process.argv.slice(2));
105
+ if (options.help) {
106
+ printHelp();
107
+ process.exit(0);
108
+ }
109
+
110
+ runErrorbookReleaseGateScript(options)
111
+ .then((result) => {
112
+ process.exitCode = result.exit_code;
113
+ })
114
+ .catch((error) => {
115
+ const payload = {
116
+ mode: 'errorbook-release-gate',
117
+ passed: false,
118
+ error: error.message
119
+ };
120
+ if (options.json) {
121
+ process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
122
+ } else {
123
+ process.stderr.write(`[errorbook-release-gate] error=${error.message}\n`);
124
+ }
125
+ process.exitCode = 1;
126
+ });
127
+ }
128
+
129
+ module.exports = {
130
+ parseArgs,
131
+ runErrorbookReleaseGateScript
132
+ };