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.
- package/CHANGELOG.md +11 -0
- package/docs/releases/README.md +1 -0
- package/docs/releases/v3.6.46.md +23 -0
- package/docs/zh/releases/README.md +1 -0
- package/docs/zh/releases/v3.6.46.md +23 -0
- package/package.json +4 -2
- package/scripts/auto-strategy-router.js +231 -0
- package/scripts/capability-mapping-report.js +339 -0
- package/scripts/check-branding-consistency.js +140 -0
- package/scripts/check-sce-tracking.js +54 -0
- package/scripts/check-skip-allowlist.js +94 -0
- package/scripts/errorbook-registry-health-gate.js +172 -0
- package/scripts/errorbook-release-gate.js +132 -0
- package/scripts/failure-attribution-repair.js +317 -0
- package/scripts/git-managed-gate.js +464 -0
- package/scripts/interactive-approval-event-projection.js +400 -0
- package/scripts/interactive-approval-workflow.js +829 -0
- package/scripts/interactive-authorization-tier-evaluate.js +413 -0
- package/scripts/interactive-change-plan-gate.js +225 -0
- package/scripts/interactive-context-bridge.js +617 -0
- package/scripts/interactive-customization-loop.js +1690 -0
- package/scripts/interactive-dialogue-governance.js +842 -0
- package/scripts/interactive-feedback-log.js +253 -0
- package/scripts/interactive-flow-smoke.js +238 -0
- package/scripts/interactive-flow.js +1059 -0
- package/scripts/interactive-governance-report.js +1112 -0
- package/scripts/interactive-intent-build.js +707 -0
- package/scripts/interactive-loop-smoke.js +215 -0
- package/scripts/interactive-moqui-adapter.js +304 -0
- package/scripts/interactive-plan-build.js +426 -0
- package/scripts/interactive-runtime-policy-evaluate.js +495 -0
- package/scripts/interactive-work-order-build.js +552 -0
- package/scripts/matrix-regression-gate.js +167 -0
- package/scripts/moqui-core-regression-suite.js +397 -0
- package/scripts/moqui-lexicon-audit.js +651 -0
- package/scripts/moqui-matrix-remediation-phased-runner.js +865 -0
- package/scripts/moqui-matrix-remediation-queue.js +852 -0
- package/scripts/moqui-metadata-extract.js +1340 -0
- package/scripts/moqui-rebuild-gate.js +167 -0
- package/scripts/moqui-release-summary.js +729 -0
- package/scripts/moqui-standard-rebuild.js +1370 -0
- package/scripts/moqui-template-baseline-report.js +682 -0
- package/scripts/npm-package-runtime-asset-check.js +221 -0
- package/scripts/problem-closure-gate.js +441 -0
- package/scripts/release-asset-integrity-check.js +216 -0
- package/scripts/release-asset-nonempty-normalize.js +166 -0
- package/scripts/release-drift-evaluate.js +223 -0
- package/scripts/release-drift-signals.js +255 -0
- package/scripts/release-governance-snapshot-export.js +132 -0
- package/scripts/release-ops-weekly-summary.js +934 -0
- package/scripts/release-risk-remediation-bundle.js +315 -0
- package/scripts/release-weekly-ops-gate.js +423 -0
- package/scripts/state-migration-reconciliation-gate.js +110 -0
- package/scripts/state-storage-tiering-audit.js +337 -0
- package/scripts/steering-content-audit.js +393 -0
- package/scripts/symbol-evidence-locate.js +366 -0
|
@@ -0,0 +1,729 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const fs = require('fs-extra');
|
|
6
|
+
const { buildMoquiRegressionRecoverySequenceLines } = require('../lib/auto/moqui-recovery-sequence');
|
|
7
|
+
|
|
8
|
+
const DEFAULT_EVIDENCE = '.sce/reports/release-evidence/handoff-runs.json';
|
|
9
|
+
const DEFAULT_BASELINE = '.sce/reports/release-evidence/moqui-template-baseline.json';
|
|
10
|
+
const DEFAULT_LEXICON = '.sce/reports/release-evidence/moqui-lexicon-audit.json';
|
|
11
|
+
const DEFAULT_CAPABILITY_MATRIX = '.sce/reports/handoff-capability-matrix.json';
|
|
12
|
+
const DEFAULT_INTERACTIVE_GOVERNANCE = '.sce/reports/interactive-governance-report.json';
|
|
13
|
+
const DEFAULT_MATRIX_REMEDIATION_PLAN = '.sce/reports/release-evidence/matrix-remediation-plan.json';
|
|
14
|
+
const DEFAULT_OUT = '.sce/reports/release-evidence/moqui-release-summary.json';
|
|
15
|
+
const DEFAULT_MARKDOWN_OUT = '.sce/reports/release-evidence/moqui-release-summary.md';
|
|
16
|
+
|
|
17
|
+
function parseArgs(argv) {
|
|
18
|
+
const options = {
|
|
19
|
+
evidence: DEFAULT_EVIDENCE,
|
|
20
|
+
baseline: DEFAULT_BASELINE,
|
|
21
|
+
lexicon: DEFAULT_LEXICON,
|
|
22
|
+
capabilityMatrix: DEFAULT_CAPABILITY_MATRIX,
|
|
23
|
+
interactiveGovernance: DEFAULT_INTERACTIVE_GOVERNANCE,
|
|
24
|
+
matrixRemediationPlan: DEFAULT_MATRIX_REMEDIATION_PLAN,
|
|
25
|
+
out: DEFAULT_OUT,
|
|
26
|
+
markdownOut: DEFAULT_MARKDOWN_OUT,
|
|
27
|
+
failOnGateFail: false,
|
|
28
|
+
json: false
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
32
|
+
const token = argv[i];
|
|
33
|
+
const next = argv[i + 1];
|
|
34
|
+
if (token === '--evidence' && next) {
|
|
35
|
+
options.evidence = next;
|
|
36
|
+
i += 1;
|
|
37
|
+
} else if (token === '--baseline' && next) {
|
|
38
|
+
options.baseline = next;
|
|
39
|
+
i += 1;
|
|
40
|
+
} else if (token === '--lexicon' && next) {
|
|
41
|
+
options.lexicon = next;
|
|
42
|
+
i += 1;
|
|
43
|
+
} else if (token === '--capability-matrix' && next) {
|
|
44
|
+
options.capabilityMatrix = next;
|
|
45
|
+
i += 1;
|
|
46
|
+
} else if (token === '--interactive-governance' && next) {
|
|
47
|
+
options.interactiveGovernance = next;
|
|
48
|
+
i += 1;
|
|
49
|
+
} else if (token === '--matrix-remediation-plan' && next) {
|
|
50
|
+
options.matrixRemediationPlan = next;
|
|
51
|
+
i += 1;
|
|
52
|
+
} else if (token === '--out' && next) {
|
|
53
|
+
options.out = next;
|
|
54
|
+
i += 1;
|
|
55
|
+
} else if (token === '--markdown-out' && next) {
|
|
56
|
+
options.markdownOut = next;
|
|
57
|
+
i += 1;
|
|
58
|
+
} else if (token === '--fail-on-gate-fail') {
|
|
59
|
+
options.failOnGateFail = true;
|
|
60
|
+
} else if (token === '--json') {
|
|
61
|
+
options.json = true;
|
|
62
|
+
} else if (token === '--help' || token === '-h') {
|
|
63
|
+
printHelpAndExit(0);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return options;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function printHelpAndExit(code) {
|
|
71
|
+
const lines = [
|
|
72
|
+
'Usage: node scripts/moqui-release-summary.js [options]',
|
|
73
|
+
'',
|
|
74
|
+
'Options:',
|
|
75
|
+
` --evidence <path> Handoff release evidence JSON (default: ${DEFAULT_EVIDENCE})`,
|
|
76
|
+
` --baseline <path> Moqui baseline JSON (default: ${DEFAULT_BASELINE})`,
|
|
77
|
+
` --lexicon <path> Moqui lexicon audit JSON (default: ${DEFAULT_LEXICON})`,
|
|
78
|
+
` --capability-matrix <path> Capability matrix JSON (default: ${DEFAULT_CAPABILITY_MATRIX})`,
|
|
79
|
+
` --interactive-governance <path> Interactive governance report JSON (default: ${DEFAULT_INTERACTIVE_GOVERNANCE})`,
|
|
80
|
+
` --matrix-remediation-plan <path> Matrix remediation plan JSON (default: ${DEFAULT_MATRIX_REMEDIATION_PLAN})`,
|
|
81
|
+
` --out <path> Summary JSON output path (default: ${DEFAULT_OUT})`,
|
|
82
|
+
` --markdown-out <path> Summary markdown output path (default: ${DEFAULT_MARKDOWN_OUT})`,
|
|
83
|
+
' --fail-on-gate-fail Exit non-zero when summary gate status is failed',
|
|
84
|
+
' --json Print summary JSON to stdout',
|
|
85
|
+
' -h, --help Show this help'
|
|
86
|
+
];
|
|
87
|
+
console.log(lines.join('\n'));
|
|
88
|
+
process.exit(code);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function normalizeBoolean(value) {
|
|
92
|
+
if (value === true) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
if (value === false) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function normalizeNumber(value) {
|
|
102
|
+
const parsed = Number(value);
|
|
103
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function safeReadJson(cwd, candidatePath) {
|
|
107
|
+
const absolutePath = path.isAbsolute(candidatePath)
|
|
108
|
+
? candidatePath
|
|
109
|
+
: path.resolve(cwd, candidatePath);
|
|
110
|
+
const relativePath = path.relative(cwd, absolutePath) || '.';
|
|
111
|
+
const exists = await fs.pathExists(absolutePath);
|
|
112
|
+
if (!exists) {
|
|
113
|
+
return {
|
|
114
|
+
path: relativePath,
|
|
115
|
+
exists: false,
|
|
116
|
+
parse_error: null,
|
|
117
|
+
payload: null
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const payload = await fs.readJson(absolutePath);
|
|
123
|
+
return {
|
|
124
|
+
path: relativePath,
|
|
125
|
+
exists: true,
|
|
126
|
+
parse_error: null,
|
|
127
|
+
payload
|
|
128
|
+
};
|
|
129
|
+
} catch (error) {
|
|
130
|
+
return {
|
|
131
|
+
path: relativePath,
|
|
132
|
+
exists: true,
|
|
133
|
+
parse_error: error.message,
|
|
134
|
+
payload: null
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function pickLatestSession(evidencePayload) {
|
|
140
|
+
const sessions = Array.isArray(evidencePayload && evidencePayload.sessions)
|
|
141
|
+
? evidencePayload.sessions
|
|
142
|
+
: [];
|
|
143
|
+
if (sessions.length === 0) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const latestSessionId = typeof evidencePayload.latest_session_id === 'string'
|
|
148
|
+
? evidencePayload.latest_session_id.trim()
|
|
149
|
+
: '';
|
|
150
|
+
if (latestSessionId) {
|
|
151
|
+
const matched = sessions.find(item => item && item.session_id === latestSessionId);
|
|
152
|
+
if (matched) {
|
|
153
|
+
return matched;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return sessions[0];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function extractBaseline(payload) {
|
|
161
|
+
const summary = payload && payload.summary && typeof payload.summary === 'object'
|
|
162
|
+
? payload.summary
|
|
163
|
+
: {};
|
|
164
|
+
const compare = payload && payload.compare && typeof payload.compare === 'object'
|
|
165
|
+
? payload.compare
|
|
166
|
+
: {};
|
|
167
|
+
const regressions = Array.isArray(compare.regressions)
|
|
168
|
+
? compare.regressions
|
|
169
|
+
: [];
|
|
170
|
+
return {
|
|
171
|
+
status: payload && typeof payload.status === 'string' ? payload.status : null,
|
|
172
|
+
portfolio_passed: normalizeBoolean(summary.portfolio_passed),
|
|
173
|
+
avg_score: normalizeNumber(summary.avg_score),
|
|
174
|
+
valid_rate_percent: normalizeNumber(summary.valid_rate_percent),
|
|
175
|
+
baseline_failed: normalizeNumber(summary.baseline_failed),
|
|
176
|
+
regressions_count: regressions.length
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function extractLexicon(payload) {
|
|
181
|
+
const summary = payload && payload.summary && typeof payload.summary === 'object'
|
|
182
|
+
? payload.summary
|
|
183
|
+
: {};
|
|
184
|
+
return {
|
|
185
|
+
passed: normalizeBoolean(summary.passed),
|
|
186
|
+
expected_unknown_count: normalizeNumber(summary.expected_unknown_count),
|
|
187
|
+
provided_unknown_count: normalizeNumber(summary.provided_unknown_count),
|
|
188
|
+
uncovered_expected_count: normalizeNumber(summary.uncovered_expected_count),
|
|
189
|
+
coverage_percent: normalizeNumber(summary.coverage_percent)
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function extractCapabilityCoverage(payload) {
|
|
194
|
+
const summary = payload && payload.summary && typeof payload.summary === 'object'
|
|
195
|
+
? payload.summary
|
|
196
|
+
: {};
|
|
197
|
+
return {
|
|
198
|
+
passed: normalizeBoolean(summary.passed),
|
|
199
|
+
semantic_passed: normalizeBoolean(summary.semantic_passed),
|
|
200
|
+
coverage_percent: normalizeNumber(summary.coverage_percent),
|
|
201
|
+
semantic_complete_percent: normalizeNumber(summary.semantic_complete_percent),
|
|
202
|
+
covered_capabilities: normalizeNumber(summary.covered_capabilities),
|
|
203
|
+
uncovered_capabilities: normalizeNumber(summary.uncovered_capabilities)
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function extractScenePackageBatch(payload) {
|
|
208
|
+
const summary = payload && payload.summary && typeof payload.summary === 'object'
|
|
209
|
+
? payload.summary
|
|
210
|
+
: {};
|
|
211
|
+
const batchGate = payload && payload.batch_ontology_gate && typeof payload.batch_ontology_gate === 'object'
|
|
212
|
+
? payload.batch_ontology_gate
|
|
213
|
+
: {};
|
|
214
|
+
return {
|
|
215
|
+
status: payload && typeof payload.status === 'string' ? payload.status : null,
|
|
216
|
+
batch_gate_passed: normalizeBoolean(
|
|
217
|
+
summary.batch_gate_passed !== undefined
|
|
218
|
+
? summary.batch_gate_passed
|
|
219
|
+
: batchGate.passed
|
|
220
|
+
),
|
|
221
|
+
failed: normalizeNumber(summary.failed),
|
|
222
|
+
selected: normalizeNumber(summary.selected)
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function extractHandoffGate(sessionPayload) {
|
|
227
|
+
const gate = sessionPayload && sessionPayload.gate && typeof sessionPayload.gate === 'object'
|
|
228
|
+
? sessionPayload.gate
|
|
229
|
+
: {};
|
|
230
|
+
const releasePreflight = sessionPayload && sessionPayload.release_gate_preflight
|
|
231
|
+
&& typeof sessionPayload.release_gate_preflight === 'object'
|
|
232
|
+
? sessionPayload.release_gate_preflight
|
|
233
|
+
: {};
|
|
234
|
+
const policy = sessionPayload && sessionPayload.policy && typeof sessionPayload.policy === 'object'
|
|
235
|
+
? sessionPayload.policy
|
|
236
|
+
: {};
|
|
237
|
+
return {
|
|
238
|
+
session_id: sessionPayload && sessionPayload.session_id ? sessionPayload.session_id : null,
|
|
239
|
+
status: sessionPayload && sessionPayload.status ? sessionPayload.status : null,
|
|
240
|
+
merged_at: sessionPayload && sessionPayload.merged_at ? sessionPayload.merged_at : null,
|
|
241
|
+
gate_passed: normalizeBoolean(gate.passed),
|
|
242
|
+
spec_success_rate_percent: normalizeNumber(gate && gate.actual && gate.actual.spec_success_rate_percent),
|
|
243
|
+
risk_level: gate && gate.actual && typeof gate.actual.risk_level === 'string'
|
|
244
|
+
? gate.actual.risk_level
|
|
245
|
+
: null,
|
|
246
|
+
release_preflight_unblocked: releasePreflight.blocked === true
|
|
247
|
+
? false
|
|
248
|
+
: (releasePreflight.blocked === false ? true : null),
|
|
249
|
+
max_moqui_matrix_regressions: normalizeNumber(policy.max_moqui_matrix_regressions)
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function extractCapabilityMatrix(payload) {
|
|
254
|
+
const gates = payload && payload.gates && typeof payload.gates === 'object'
|
|
255
|
+
? payload.gates
|
|
256
|
+
: {};
|
|
257
|
+
const coverage = payload && payload.capability_coverage && typeof payload.capability_coverage === 'object'
|
|
258
|
+
? payload.capability_coverage
|
|
259
|
+
: {};
|
|
260
|
+
const summary = coverage && coverage.summary && typeof coverage.summary === 'object'
|
|
261
|
+
? coverage.summary
|
|
262
|
+
: {};
|
|
263
|
+
return {
|
|
264
|
+
status: payload && typeof payload.status === 'string' ? payload.status : null,
|
|
265
|
+
gate_passed: normalizeBoolean(gates.passed),
|
|
266
|
+
coverage_passed: normalizeBoolean(
|
|
267
|
+
gates.capability_coverage && gates.capability_coverage.passed
|
|
268
|
+
),
|
|
269
|
+
semantic_passed: normalizeBoolean(
|
|
270
|
+
gates.capability_semantic && gates.capability_semantic.passed
|
|
271
|
+
),
|
|
272
|
+
lexicon_passed: normalizeBoolean(
|
|
273
|
+
gates.capability_lexicon && gates.capability_lexicon.passed
|
|
274
|
+
),
|
|
275
|
+
coverage_percent: normalizeNumber(summary.coverage_percent),
|
|
276
|
+
semantic_complete_percent: normalizeNumber(summary.semantic_complete_percent)
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function extractInteractiveGovernance(payload) {
|
|
281
|
+
const summary = payload && payload.summary && typeof payload.summary === 'object'
|
|
282
|
+
? payload.summary
|
|
283
|
+
: {};
|
|
284
|
+
const metrics = payload && payload.metrics && typeof payload.metrics === 'object'
|
|
285
|
+
? payload.metrics
|
|
286
|
+
: {};
|
|
287
|
+
return {
|
|
288
|
+
status: typeof summary.status === 'string' ? summary.status : null,
|
|
289
|
+
breaches: normalizeNumber(summary.breaches),
|
|
290
|
+
warnings: normalizeNumber(summary.warnings),
|
|
291
|
+
matrix_signal_total: normalizeNumber(metrics.matrix_signal_total),
|
|
292
|
+
matrix_portfolio_pass_rate_percent: normalizeNumber(metrics.matrix_portfolio_pass_rate_percent),
|
|
293
|
+
matrix_regression_positive_rate_percent: normalizeNumber(metrics.matrix_regression_positive_rate_percent),
|
|
294
|
+
matrix_stage_error_rate_percent: normalizeNumber(metrics.matrix_stage_error_rate_percent)
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function extractMatrixRemediation(payload) {
|
|
299
|
+
const summary = payload && payload.summary && typeof payload.summary === 'object'
|
|
300
|
+
? payload.summary
|
|
301
|
+
: {};
|
|
302
|
+
const templatePriority = Array.isArray(payload && payload.template_priority_matrix)
|
|
303
|
+
? payload.template_priority_matrix
|
|
304
|
+
: [];
|
|
305
|
+
const capabilityClusters = Array.isArray(payload && payload.capability_clusters)
|
|
306
|
+
? payload.capability_clusters
|
|
307
|
+
: [];
|
|
308
|
+
const templatePriorityTop = templatePriority
|
|
309
|
+
.slice(0, 5)
|
|
310
|
+
.map(item => ({
|
|
311
|
+
template_id: item && item.template_id ? item.template_id : null,
|
|
312
|
+
recommended_phase: item && item.recommended_phase ? item.recommended_phase : null,
|
|
313
|
+
priority_score: normalizeNumber(item && item.priority_score)
|
|
314
|
+
}))
|
|
315
|
+
.filter(item => item.template_id);
|
|
316
|
+
const capabilityClustersTop = capabilityClusters
|
|
317
|
+
.slice(0, 5)
|
|
318
|
+
.map(item => ({
|
|
319
|
+
capability: item && item.capability ? item.capability : null,
|
|
320
|
+
priority_score: normalizeNumber(item && item.priority_score),
|
|
321
|
+
template_count: normalizeNumber(item && item.template_count)
|
|
322
|
+
}))
|
|
323
|
+
.filter(item => item.capability);
|
|
324
|
+
return {
|
|
325
|
+
template_priority_count: normalizeNumber(summary.template_priority_count),
|
|
326
|
+
capability_cluster_count: normalizeNumber(summary.capability_cluster_count),
|
|
327
|
+
capability_cluster_goal_count: normalizeNumber(summary.capability_cluster_goal_count),
|
|
328
|
+
template_priority_top: templatePriorityTop,
|
|
329
|
+
capability_clusters_top: capabilityClustersTop
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function normalizeGateStatus(checks, matrixRegressionCheck) {
|
|
334
|
+
const requiredChecks = checks.filter(item => item.required);
|
|
335
|
+
const hasFailed = requiredChecks.some(item => item.value === false) || matrixRegressionCheck === false;
|
|
336
|
+
if (hasFailed) {
|
|
337
|
+
return 'failed';
|
|
338
|
+
}
|
|
339
|
+
const hasUnknown = requiredChecks.some(item => item.value === null) || matrixRegressionCheck === null;
|
|
340
|
+
if (hasUnknown) {
|
|
341
|
+
return 'incomplete';
|
|
342
|
+
}
|
|
343
|
+
return 'passed';
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function buildRecommendations(summary, matrixRemediation = {}) {
|
|
347
|
+
const recommendations = [];
|
|
348
|
+
const push = (value) => {
|
|
349
|
+
const text = `${value || ''}`.trim();
|
|
350
|
+
if (!text || recommendations.includes(text)) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
recommendations.push(text);
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
if (summary.gate_status === 'incomplete') {
|
|
357
|
+
push(
|
|
358
|
+
'Generate baseline release evidence first: `npx sce auto handoff run --manifest docs/handoffs/handoff-manifest.json --dry-run --json`.'
|
|
359
|
+
);
|
|
360
|
+
push(
|
|
361
|
+
'Generate capability matrix evidence: `npx sce auto handoff capability-matrix --manifest docs/handoffs/handoff-manifest.json --fail-on-gap --json`.'
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const map = new Map(summary.checks.map(item => [item.key, item.value]));
|
|
366
|
+
if (map.get('handoff_gate') === false) {
|
|
367
|
+
push(
|
|
368
|
+
'Fix handoff gate failures and rerun: `npx sce auto handoff run --manifest docs/handoffs/handoff-manifest.json --dry-run --json`.'
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
if (map.get('baseline_portfolio') === false) {
|
|
372
|
+
push(
|
|
373
|
+
'Remediate baseline portfolio score/gaps: `npx sce scene moqui-baseline --include-all --fail-on-portfolio-fail --json`.'
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
if (map.get('scene_package_batch') === false) {
|
|
377
|
+
push(
|
|
378
|
+
'Repair scene package batch ontology gate: `npx sce scene package-publish-batch --manifest docs/handoffs/handoff-manifest.json --dry-run --json`.'
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
if (map.get('capability_coverage') === false || map.get('capability_semantic') === false) {
|
|
382
|
+
push(
|
|
383
|
+
'Close capability and semantic gaps: `npx sce auto handoff capability-matrix --manifest docs/handoffs/handoff-manifest.json --fail-on-gap --json`.'
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
if (map.get('lexicon_gate') === false) {
|
|
387
|
+
push(
|
|
388
|
+
'Align manifest/template aliases with canonical lexicon: `node scripts/moqui-lexicon-audit.js --manifest docs/handoffs/handoff-manifest.json --fail-on-gap --json`.'
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
if (map.get('release_preflight') === false) {
|
|
392
|
+
push(
|
|
393
|
+
'Release gate preflight is blocked; resolve governance release-gate blockers and rerun handoff evidence.'
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
if (summary.matrix_regression_check === false) {
|
|
397
|
+
push(
|
|
398
|
+
'Recover matrix regressions to policy limit before release: `npx sce auto handoff run --manifest docs/handoffs/handoff-manifest.json --dry-run --json`.'
|
|
399
|
+
);
|
|
400
|
+
push(
|
|
401
|
+
'Generate phased matrix remediation package: `node scripts/moqui-matrix-remediation-queue.js --baseline .sce/reports/release-evidence/moqui-template-baseline.json --json`.'
|
|
402
|
+
);
|
|
403
|
+
for (const line of buildMoquiRegressionRecoverySequenceLines({
|
|
404
|
+
wrapCommands: true,
|
|
405
|
+
withPeriod: true,
|
|
406
|
+
clusterPhasedCommand: 'npm run run:matrix-remediation-clusters-phased -- --json',
|
|
407
|
+
includeStep1Alias: false,
|
|
408
|
+
baselinePhasedAlias: 'npm run run:matrix-remediation-phased -- --json'
|
|
409
|
+
})) {
|
|
410
|
+
push(line);
|
|
411
|
+
}
|
|
412
|
+
if (Array.isArray(matrixRemediation.template_priority_top) && matrixRemediation.template_priority_top.length > 0) {
|
|
413
|
+
push(
|
|
414
|
+
`Prioritize template recovery order: ${matrixRemediation.template_priority_top
|
|
415
|
+
.slice(0, 3)
|
|
416
|
+
.map(item => `${item.template_id}(${item.recommended_phase || 'n/a'})`)
|
|
417
|
+
.join(' -> ')}.`
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
if (Array.isArray(matrixRemediation.capability_clusters_top) && matrixRemediation.capability_clusters_top.length > 0) {
|
|
421
|
+
push(
|
|
422
|
+
`Prioritize capability closure clusters: ${matrixRemediation.capability_clusters_top
|
|
423
|
+
.slice(0, 3)
|
|
424
|
+
.map(item => `${item.capability}${Number.isFinite(item.priority_score) ? `(${item.priority_score})` : ''}`)
|
|
425
|
+
.join(' -> ')}.`
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
if (map.get('interactive_governance') === false) {
|
|
430
|
+
push(
|
|
431
|
+
'Resolve interactive governance alerts and rerun: `npm run report:interactive-governance -- --period weekly --fail-on-alert --json`.'
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (recommendations.length === 0) {
|
|
436
|
+
push('No blocking issue detected in the available evidence.');
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
return recommendations;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function buildMarkdownReport(report) {
|
|
443
|
+
const lines = [];
|
|
444
|
+
lines.push('# Moqui Release Summary');
|
|
445
|
+
lines.push('');
|
|
446
|
+
lines.push(`- Generated at: ${report.generated_at}`);
|
|
447
|
+
lines.push(`- Gate status: ${report.summary.gate_status}`);
|
|
448
|
+
lines.push(
|
|
449
|
+
`- Gate passed: ${report.summary.gate_passed === null ? 'n/a' : (report.summary.gate_passed ? 'yes' : 'no')}`
|
|
450
|
+
);
|
|
451
|
+
lines.push('');
|
|
452
|
+
lines.push('## Current Session');
|
|
453
|
+
lines.push('');
|
|
454
|
+
lines.push(`- Session ID: ${report.handoff.session_id || 'n/a'}`);
|
|
455
|
+
lines.push(`- Status: ${report.handoff.status || 'n/a'}`);
|
|
456
|
+
lines.push(`- Merged at: ${report.handoff.merged_at || 'n/a'}`);
|
|
457
|
+
lines.push('');
|
|
458
|
+
lines.push('## Gate Checks');
|
|
459
|
+
lines.push('');
|
|
460
|
+
lines.push('| Check | Value | Required |');
|
|
461
|
+
lines.push('| --- | --- | --- |');
|
|
462
|
+
for (const check of report.summary.checks) {
|
|
463
|
+
const valueText = check.value === null ? 'n/a' : (check.value ? 'pass' : 'fail');
|
|
464
|
+
lines.push(`| ${check.key} | ${valueText} | ${check.required ? 'yes' : 'no'} |`);
|
|
465
|
+
}
|
|
466
|
+
lines.push('');
|
|
467
|
+
lines.push('## Signals');
|
|
468
|
+
lines.push('');
|
|
469
|
+
lines.push(`- Baseline portfolio passed: ${report.baseline.portfolio_passed === null ? 'n/a' : (report.baseline.portfolio_passed ? 'yes' : 'no')}`);
|
|
470
|
+
lines.push(`- Baseline avg score: ${report.baseline.avg_score === null ? 'n/a' : report.baseline.avg_score}`);
|
|
471
|
+
lines.push(`- Baseline valid-rate: ${report.baseline.valid_rate_percent === null ? 'n/a' : `${report.baseline.valid_rate_percent}%`}`);
|
|
472
|
+
lines.push(`- Lexicon passed: ${report.lexicon.passed === null ? 'n/a' : (report.lexicon.passed ? 'yes' : 'no')}`);
|
|
473
|
+
lines.push(`- Lexicon coverage: ${report.lexicon.coverage_percent === null ? 'n/a' : `${report.lexicon.coverage_percent}%`}`);
|
|
474
|
+
lines.push(`- Capability coverage passed: ${report.capability_coverage.passed === null ? 'n/a' : (report.capability_coverage.passed ? 'yes' : 'no')}`);
|
|
475
|
+
lines.push(`- Capability semantic passed: ${report.capability_coverage.semantic_passed === null ? 'n/a' : (report.capability_coverage.semantic_passed ? 'yes' : 'no')}`);
|
|
476
|
+
lines.push(`- Capability coverage: ${report.capability_coverage.coverage_percent === null ? 'n/a' : `${report.capability_coverage.coverage_percent}%`}`);
|
|
477
|
+
lines.push(`- Capability semantic completeness: ${report.capability_coverage.semantic_complete_percent === null ? 'n/a' : `${report.capability_coverage.semantic_complete_percent}%`}`);
|
|
478
|
+
lines.push(`- Scene package batch gate passed: ${report.scene_package_batch.batch_gate_passed === null ? 'n/a' : (report.scene_package_batch.batch_gate_passed ? 'yes' : 'no')}`);
|
|
479
|
+
lines.push(`- Interactive governance status: ${report.interactive_governance.status || 'n/a'}`);
|
|
480
|
+
lines.push(`- Interactive governance breaches: ${report.interactive_governance.breaches === null ? 'n/a' : report.interactive_governance.breaches}`);
|
|
481
|
+
lines.push(`- Interactive governance warnings: ${report.interactive_governance.warnings === null ? 'n/a' : report.interactive_governance.warnings}`);
|
|
482
|
+
lines.push(`- Interactive matrix pass-rate: ${report.interactive_governance.matrix_portfolio_pass_rate_percent === null ? 'n/a' : `${report.interactive_governance.matrix_portfolio_pass_rate_percent}%`}`);
|
|
483
|
+
lines.push(`- Interactive matrix regression-positive rate: ${report.interactive_governance.matrix_regression_positive_rate_percent === null ? 'n/a' : `${report.interactive_governance.matrix_regression_positive_rate_percent}%`}`);
|
|
484
|
+
lines.push(
|
|
485
|
+
`- Matrix regressions: ${report.summary.matrix_regressions === null ? 'n/a' : report.summary.matrix_regressions}` +
|
|
486
|
+
` (max=${report.summary.max_matrix_regressions === null ? 'n/a' : report.summary.max_matrix_regressions})`
|
|
487
|
+
);
|
|
488
|
+
lines.push(
|
|
489
|
+
`- Matrix template priority count: ${report.matrix_remediation.template_priority_count === null ? 'n/a' : report.matrix_remediation.template_priority_count}`
|
|
490
|
+
);
|
|
491
|
+
lines.push(
|
|
492
|
+
`- Matrix capability cluster count: ${report.matrix_remediation.capability_cluster_count === null ? 'n/a' : report.matrix_remediation.capability_cluster_count}`
|
|
493
|
+
);
|
|
494
|
+
lines.push(
|
|
495
|
+
`- Matrix capability-cluster goals: ${report.matrix_remediation.capability_cluster_goal_count === null ? 'n/a' : report.matrix_remediation.capability_cluster_goal_count}`
|
|
496
|
+
);
|
|
497
|
+
lines.push('');
|
|
498
|
+
lines.push('## Inputs');
|
|
499
|
+
lines.push('');
|
|
500
|
+
lines.push('| Input | Path | Exists | Parse Error |');
|
|
501
|
+
lines.push('| --- | --- | --- | --- |');
|
|
502
|
+
for (const input of Object.values(report.inputs)) {
|
|
503
|
+
lines.push(
|
|
504
|
+
`| ${input.key} | ${input.path} | ${input.exists ? 'yes' : 'no'} | ${input.parse_error || 'none'} |`
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
if (
|
|
508
|
+
Array.isArray(report.matrix_remediation.template_priority_top) &&
|
|
509
|
+
report.matrix_remediation.template_priority_top.length > 0
|
|
510
|
+
) {
|
|
511
|
+
lines.push('');
|
|
512
|
+
lines.push('## Matrix Template Priorities');
|
|
513
|
+
lines.push('');
|
|
514
|
+
for (const item of report.matrix_remediation.template_priority_top.slice(0, 5)) {
|
|
515
|
+
lines.push(
|
|
516
|
+
`- ${item.template_id} (${item.recommended_phase || 'n/a'}, ` +
|
|
517
|
+
`score=${item.priority_score === null ? 'n/a' : item.priority_score})`
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
if (
|
|
522
|
+
Array.isArray(report.matrix_remediation.capability_clusters_top) &&
|
|
523
|
+
report.matrix_remediation.capability_clusters_top.length > 0
|
|
524
|
+
) {
|
|
525
|
+
lines.push('');
|
|
526
|
+
lines.push('## Matrix Capability Clusters');
|
|
527
|
+
lines.push('');
|
|
528
|
+
for (const item of report.matrix_remediation.capability_clusters_top.slice(0, 5)) {
|
|
529
|
+
lines.push(
|
|
530
|
+
`- ${item.capability} (score=${item.priority_score === null ? 'n/a' : item.priority_score}, ` +
|
|
531
|
+
`templates=${item.template_count === null ? 'n/a' : item.template_count})`
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
lines.push('');
|
|
536
|
+
lines.push('## Recommendations');
|
|
537
|
+
lines.push('');
|
|
538
|
+
for (const item of report.recommendations) {
|
|
539
|
+
lines.push(`- ${item}`);
|
|
540
|
+
}
|
|
541
|
+
return `${lines.join('\n')}\n`;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
async function main() {
|
|
545
|
+
const options = parseArgs(process.argv.slice(2));
|
|
546
|
+
const cwd = process.cwd();
|
|
547
|
+
|
|
548
|
+
const [evidenceInput, baselineInput, lexiconInput, capabilityMatrixInput, interactiveGovernanceInput, matrixRemediationPlanInput] = await Promise.all([
|
|
549
|
+
safeReadJson(cwd, options.evidence),
|
|
550
|
+
safeReadJson(cwd, options.baseline),
|
|
551
|
+
safeReadJson(cwd, options.lexicon),
|
|
552
|
+
safeReadJson(cwd, options.capabilityMatrix),
|
|
553
|
+
safeReadJson(cwd, options.interactiveGovernance),
|
|
554
|
+
safeReadJson(cwd, options.matrixRemediationPlan)
|
|
555
|
+
]);
|
|
556
|
+
|
|
557
|
+
const latestSession = pickLatestSession(evidenceInput.payload);
|
|
558
|
+
const handoff = extractHandoffGate(latestSession || {});
|
|
559
|
+
const baselineFromEvidence = extractBaseline(
|
|
560
|
+
latestSession && latestSession.moqui_baseline && typeof latestSession.moqui_baseline === 'object'
|
|
561
|
+
? latestSession.moqui_baseline
|
|
562
|
+
: {}
|
|
563
|
+
);
|
|
564
|
+
const capabilityFromEvidence = extractCapabilityCoverage(
|
|
565
|
+
latestSession && latestSession.moqui_capability_coverage && typeof latestSession.moqui_capability_coverage === 'object'
|
|
566
|
+
? latestSession.moqui_capability_coverage
|
|
567
|
+
: {}
|
|
568
|
+
);
|
|
569
|
+
const scenePackageBatch = extractScenePackageBatch(
|
|
570
|
+
latestSession && latestSession.scene_package_batch && typeof latestSession.scene_package_batch === 'object'
|
|
571
|
+
? latestSession.scene_package_batch
|
|
572
|
+
: {}
|
|
573
|
+
);
|
|
574
|
+
|
|
575
|
+
const baselineFromFile = extractBaseline(
|
|
576
|
+
baselineInput.payload && typeof baselineInput.payload === 'object'
|
|
577
|
+
? baselineInput.payload
|
|
578
|
+
: {}
|
|
579
|
+
);
|
|
580
|
+
const lexicon = extractLexicon(
|
|
581
|
+
lexiconInput.payload && typeof lexiconInput.payload === 'object'
|
|
582
|
+
? lexiconInput.payload
|
|
583
|
+
: {}
|
|
584
|
+
);
|
|
585
|
+
const capabilityMatrix = extractCapabilityMatrix(
|
|
586
|
+
capabilityMatrixInput.payload && typeof capabilityMatrixInput.payload === 'object'
|
|
587
|
+
? capabilityMatrixInput.payload
|
|
588
|
+
: {}
|
|
589
|
+
);
|
|
590
|
+
const interactiveGovernance = extractInteractiveGovernance(
|
|
591
|
+
interactiveGovernanceInput.payload && typeof interactiveGovernanceInput.payload === 'object'
|
|
592
|
+
? interactiveGovernanceInput.payload
|
|
593
|
+
: {}
|
|
594
|
+
);
|
|
595
|
+
const matrixRemediation = extractMatrixRemediation(
|
|
596
|
+
matrixRemediationPlanInput.payload && typeof matrixRemediationPlanInput.payload === 'object'
|
|
597
|
+
? matrixRemediationPlanInput.payload
|
|
598
|
+
: {}
|
|
599
|
+
);
|
|
600
|
+
|
|
601
|
+
const baseline = {
|
|
602
|
+
status: baselineFromFile.status || baselineFromEvidence.status || null,
|
|
603
|
+
portfolio_passed: baselineFromFile.portfolio_passed !== null
|
|
604
|
+
? baselineFromFile.portfolio_passed
|
|
605
|
+
: baselineFromEvidence.portfolio_passed,
|
|
606
|
+
avg_score: baselineFromFile.avg_score !== null ? baselineFromFile.avg_score : baselineFromEvidence.avg_score,
|
|
607
|
+
valid_rate_percent: baselineFromFile.valid_rate_percent !== null
|
|
608
|
+
? baselineFromFile.valid_rate_percent
|
|
609
|
+
: baselineFromEvidence.valid_rate_percent,
|
|
610
|
+
baseline_failed: baselineFromFile.baseline_failed !== null
|
|
611
|
+
? baselineFromFile.baseline_failed
|
|
612
|
+
: baselineFromEvidence.baseline_failed,
|
|
613
|
+
regressions_count: baselineFromFile.regressions_count > 0
|
|
614
|
+
? baselineFromFile.regressions_count
|
|
615
|
+
: baselineFromEvidence.regressions_count
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
const capabilityCoverage = {
|
|
619
|
+
passed: capabilityMatrix.coverage_passed !== null
|
|
620
|
+
? capabilityMatrix.coverage_passed
|
|
621
|
+
: capabilityFromEvidence.passed,
|
|
622
|
+
semantic_passed: capabilityMatrix.semantic_passed !== null
|
|
623
|
+
? capabilityMatrix.semantic_passed
|
|
624
|
+
: capabilityFromEvidence.semantic_passed,
|
|
625
|
+
coverage_percent: capabilityMatrix.coverage_percent !== null
|
|
626
|
+
? capabilityMatrix.coverage_percent
|
|
627
|
+
: capabilityFromEvidence.coverage_percent,
|
|
628
|
+
semantic_complete_percent: capabilityMatrix.semantic_complete_percent !== null
|
|
629
|
+
? capabilityMatrix.semantic_complete_percent
|
|
630
|
+
: capabilityFromEvidence.semantic_complete_percent,
|
|
631
|
+
covered_capabilities: capabilityFromEvidence.covered_capabilities,
|
|
632
|
+
uncovered_capabilities: capabilityFromEvidence.uncovered_capabilities
|
|
633
|
+
};
|
|
634
|
+
|
|
635
|
+
const matrixRegressions = baseline.regressions_count;
|
|
636
|
+
const maxMatrixRegressions = handoff.max_moqui_matrix_regressions;
|
|
637
|
+
const matrixRegressionCheck = (
|
|
638
|
+
matrixRegressions === null || maxMatrixRegressions === null
|
|
639
|
+
? null
|
|
640
|
+
: matrixRegressions <= maxMatrixRegressions
|
|
641
|
+
);
|
|
642
|
+
|
|
643
|
+
const checks = [
|
|
644
|
+
{ key: 'handoff_gate', value: handoff.gate_passed, required: true },
|
|
645
|
+
{ key: 'baseline_portfolio', value: baseline.portfolio_passed, required: true },
|
|
646
|
+
{ key: 'scene_package_batch', value: scenePackageBatch.batch_gate_passed, required: true },
|
|
647
|
+
{ key: 'capability_coverage', value: capabilityCoverage.passed, required: true },
|
|
648
|
+
{ key: 'capability_semantic', value: capabilityCoverage.semantic_passed, required: true },
|
|
649
|
+
{
|
|
650
|
+
key: 'lexicon_gate',
|
|
651
|
+
value: lexicon.passed !== null ? lexicon.passed : capabilityMatrix.lexicon_passed,
|
|
652
|
+
required: true
|
|
653
|
+
},
|
|
654
|
+
{
|
|
655
|
+
key: 'interactive_governance',
|
|
656
|
+
value: interactiveGovernance.status === 'ok'
|
|
657
|
+
? true
|
|
658
|
+
: (interactiveGovernance.status === 'alert' ? false : null),
|
|
659
|
+
required: false
|
|
660
|
+
},
|
|
661
|
+
{ key: 'release_preflight', value: handoff.release_preflight_unblocked, required: false }
|
|
662
|
+
];
|
|
663
|
+
|
|
664
|
+
const gateStatus = normalizeGateStatus(checks, matrixRegressionCheck);
|
|
665
|
+
const gatePassed = gateStatus === 'passed'
|
|
666
|
+
? true
|
|
667
|
+
: (gateStatus === 'failed' ? false : null);
|
|
668
|
+
const summary = {
|
|
669
|
+
gate_status: gateStatus,
|
|
670
|
+
gate_passed: gatePassed,
|
|
671
|
+
checks,
|
|
672
|
+
matrix_regressions: matrixRegressions,
|
|
673
|
+
max_matrix_regressions: maxMatrixRegressions,
|
|
674
|
+
matrix_regression_check: matrixRegressionCheck
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
const report = {
|
|
678
|
+
mode: 'moqui-release-summary',
|
|
679
|
+
generated_at: new Date().toISOString(),
|
|
680
|
+
inputs: {
|
|
681
|
+
evidence: { key: 'evidence', ...evidenceInput },
|
|
682
|
+
baseline: { key: 'baseline', ...baselineInput },
|
|
683
|
+
lexicon: { key: 'lexicon', ...lexiconInput },
|
|
684
|
+
capability_matrix: { key: 'capability_matrix', ...capabilityMatrixInput },
|
|
685
|
+
interactive_governance: { key: 'interactive_governance', ...interactiveGovernanceInput },
|
|
686
|
+
matrix_remediation_plan: { key: 'matrix_remediation_plan', ...matrixRemediationPlanInput }
|
|
687
|
+
},
|
|
688
|
+
handoff,
|
|
689
|
+
baseline,
|
|
690
|
+
lexicon,
|
|
691
|
+
capability_coverage: capabilityCoverage,
|
|
692
|
+
capability_matrix: capabilityMatrix,
|
|
693
|
+
interactive_governance: interactiveGovernance,
|
|
694
|
+
matrix_remediation: matrixRemediation,
|
|
695
|
+
scene_package_batch: scenePackageBatch,
|
|
696
|
+
summary
|
|
697
|
+
};
|
|
698
|
+
report.recommendations = buildRecommendations(report.summary, report.matrix_remediation);
|
|
699
|
+
|
|
700
|
+
const outPath = path.resolve(cwd, options.out);
|
|
701
|
+
const markdownOutPath = path.resolve(cwd, options.markdownOut);
|
|
702
|
+
await fs.ensureDir(path.dirname(outPath));
|
|
703
|
+
await fs.writeJson(outPath, report, { spaces: 2 });
|
|
704
|
+
await fs.ensureDir(path.dirname(markdownOutPath));
|
|
705
|
+
await fs.writeFile(markdownOutPath, buildMarkdownReport(report), 'utf8');
|
|
706
|
+
|
|
707
|
+
if (options.json) {
|
|
708
|
+
process.stdout.write(`${JSON.stringify({
|
|
709
|
+
...report,
|
|
710
|
+
output: {
|
|
711
|
+
json: path.relative(cwd, outPath) || '.',
|
|
712
|
+
markdown: path.relative(cwd, markdownOutPath) || '.'
|
|
713
|
+
}
|
|
714
|
+
}, null, 2)}\n`);
|
|
715
|
+
} else {
|
|
716
|
+
process.stdout.write(`Moqui release summary generated (${summary.gate_status}).\n`);
|
|
717
|
+
process.stdout.write(`- JSON: ${path.relative(cwd, outPath) || '.'}\n`);
|
|
718
|
+
process.stdout.write(`- Markdown: ${path.relative(cwd, markdownOutPath) || '.'}\n`);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
if (options.failOnGateFail && summary.gate_status === 'failed') {
|
|
722
|
+
process.exitCode = 2;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
main().catch((error) => {
|
|
727
|
+
console.error(`Moqui release summary failed: ${error.message}`);
|
|
728
|
+
process.exit(1);
|
|
729
|
+
});
|