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,317 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
const DEFAULT_TAXONOMY_FILE = 'docs/agent-runtime/failure-taxonomy-baseline.json';
|
|
8
|
+
|
|
9
|
+
function parseArgs(argv = []) {
|
|
10
|
+
const options = {
|
|
11
|
+
error: '',
|
|
12
|
+
errorFile: '',
|
|
13
|
+
taxonomyFile: DEFAULT_TAXONOMY_FILE,
|
|
14
|
+
testFailures: 0,
|
|
15
|
+
attemptedPasses: 0,
|
|
16
|
+
maxRepairPasses: 1,
|
|
17
|
+
tests: [],
|
|
18
|
+
json: false
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
22
|
+
const token = argv[index];
|
|
23
|
+
const next = argv[index + 1];
|
|
24
|
+
if (token === '--error' && next) {
|
|
25
|
+
options.error = next;
|
|
26
|
+
index += 1;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (token === '--error-file' && next) {
|
|
30
|
+
options.errorFile = next;
|
|
31
|
+
index += 1;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (token === '--taxonomy-file' && next) {
|
|
35
|
+
options.taxonomyFile = next;
|
|
36
|
+
index += 1;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (token === '--test-failures' && next) {
|
|
40
|
+
options.testFailures = Number(next);
|
|
41
|
+
index += 1;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (token === '--attempted-passes' && next) {
|
|
45
|
+
options.attemptedPasses = Number(next);
|
|
46
|
+
index += 1;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (token === '--max-repair-passes' && next) {
|
|
50
|
+
options.maxRepairPasses = Number(next);
|
|
51
|
+
index += 1;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (token === '--tests' && next) {
|
|
55
|
+
options.tests = next
|
|
56
|
+
.split(',')
|
|
57
|
+
.map((item) => item.trim())
|
|
58
|
+
.filter(Boolean);
|
|
59
|
+
index += 1;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (token === '--json') {
|
|
63
|
+
options.json = true;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (token === '--help' || token === '-h') {
|
|
67
|
+
printHelpAndExit(0);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!Number.isFinite(options.testFailures) || options.testFailures < 0) {
|
|
72
|
+
throw new Error('--test-failures must be a non-negative number.');
|
|
73
|
+
}
|
|
74
|
+
if (!Number.isFinite(options.attemptedPasses) || options.attemptedPasses < 0) {
|
|
75
|
+
throw new Error('--attempted-passes must be a non-negative number.');
|
|
76
|
+
}
|
|
77
|
+
if (!Number.isFinite(options.maxRepairPasses) || options.maxRepairPasses < 0) {
|
|
78
|
+
throw new Error('--max-repair-passes must be a non-negative number.');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return options;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function printHelpAndExit(code) {
|
|
85
|
+
const lines = [
|
|
86
|
+
'Usage: node scripts/failure-attribution-repair.js [options]',
|
|
87
|
+
'',
|
|
88
|
+
'Options:',
|
|
89
|
+
' --error <text> Failure text to classify',
|
|
90
|
+
' --error-file <path> Read failure text from file',
|
|
91
|
+
` --taxonomy-file <path> Failure taxonomy JSON path (default: ${DEFAULT_TAXONOMY_FILE})`,
|
|
92
|
+
' --test-failures <n> Number of failing tests (default: 0)',
|
|
93
|
+
' --attempted-passes <n> Repair passes already consumed (default: 0)',
|
|
94
|
+
' --max-repair-passes <n> Max repair passes (default: 1)',
|
|
95
|
+
' --tests <csv> Targeted test commands for re-run',
|
|
96
|
+
' --json Print JSON payload',
|
|
97
|
+
' -h, --help Show this help'
|
|
98
|
+
];
|
|
99
|
+
console.log(lines.join('\n'));
|
|
100
|
+
process.exit(code);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function loadTextError(options) {
|
|
104
|
+
if (typeof options.error === 'string' && options.error.trim()) {
|
|
105
|
+
return options.error.trim();
|
|
106
|
+
}
|
|
107
|
+
if (typeof options.errorFile === 'string' && options.errorFile.trim()) {
|
|
108
|
+
const resolvedFile = path.resolve(process.cwd(), options.errorFile);
|
|
109
|
+
if (!fs.existsSync(resolvedFile)) {
|
|
110
|
+
throw new Error(`error file not found: ${options.errorFile}`);
|
|
111
|
+
}
|
|
112
|
+
const content = fs.readFileSync(resolvedFile, 'utf8').trim();
|
|
113
|
+
if (content) {
|
|
114
|
+
return content;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return '';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function loadTaxonomy(taxonomyFile) {
|
|
121
|
+
const resolved = path.resolve(process.cwd(), taxonomyFile);
|
|
122
|
+
if (!fs.existsSync(resolved)) {
|
|
123
|
+
throw new Error(`taxonomy file not found: ${taxonomyFile}`);
|
|
124
|
+
}
|
|
125
|
+
const payload = JSON.parse(fs.readFileSync(resolved, 'utf8'));
|
|
126
|
+
const categories = Array.isArray(payload.categories) ? payload.categories : [];
|
|
127
|
+
return {
|
|
128
|
+
version: payload.version || 'unknown',
|
|
129
|
+
default_category: payload.default_category || 'unknown',
|
|
130
|
+
categories
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function normalizePattern(pattern) {
|
|
135
|
+
return `${pattern || ''}`.trim().toLowerCase();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function classifyFailure(errorText, taxonomy) {
|
|
139
|
+
const message = `${errorText || ''}`.toLowerCase();
|
|
140
|
+
let bestMatch = null;
|
|
141
|
+
|
|
142
|
+
for (const category of taxonomy.categories) {
|
|
143
|
+
const patterns = Array.isArray(category.patterns) ? category.patterns : [];
|
|
144
|
+
const matchedPatterns = patterns
|
|
145
|
+
.map(normalizePattern)
|
|
146
|
+
.filter((pattern) => pattern && message.includes(pattern));
|
|
147
|
+
if (matchedPatterns.length === 0) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const score = matchedPatterns.length;
|
|
151
|
+
if (!bestMatch || score > bestMatch.score) {
|
|
152
|
+
bestMatch = {
|
|
153
|
+
category,
|
|
154
|
+
matchedPatterns,
|
|
155
|
+
score
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (!bestMatch) {
|
|
161
|
+
const fallback = taxonomy.categories.find((category) => category.id === taxonomy.default_category)
|
|
162
|
+
|| taxonomy.categories.find((category) => category.id === 'unknown')
|
|
163
|
+
|| {
|
|
164
|
+
id: taxonomy.default_category || 'unknown',
|
|
165
|
+
repairable: false,
|
|
166
|
+
default_actions: ['collect diagnostics']
|
|
167
|
+
};
|
|
168
|
+
return {
|
|
169
|
+
category: fallback.id || 'unknown',
|
|
170
|
+
confidence: 'low',
|
|
171
|
+
repairable: fallback.repairable === true,
|
|
172
|
+
matched_patterns: [],
|
|
173
|
+
default_actions: Array.isArray(fallback.default_actions) ? fallback.default_actions : []
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const confidence = bestMatch.matchedPatterns.length >= 2 ? 'high' : 'medium';
|
|
178
|
+
return {
|
|
179
|
+
category: bestMatch.category.id || taxonomy.default_category || 'unknown',
|
|
180
|
+
confidence,
|
|
181
|
+
repairable: bestMatch.category.repairable === true,
|
|
182
|
+
matched_patterns: bestMatch.matchedPatterns,
|
|
183
|
+
default_actions: Array.isArray(bestMatch.category.default_actions)
|
|
184
|
+
? bestMatch.category.default_actions
|
|
185
|
+
: []
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function buildRepairPlan({ attribution, testFailures, attemptedPasses, maxRepairPasses, tests }) {
|
|
190
|
+
const remainingPasses = Math.max(0, Math.floor(maxRepairPasses) - Math.floor(attemptedPasses));
|
|
191
|
+
const canRepair = attribution.repairable === true && remainingPasses > 0;
|
|
192
|
+
|
|
193
|
+
if (!canRepair) {
|
|
194
|
+
const reason = attribution.repairable !== true
|
|
195
|
+
? `category '${attribution.category}' is non-repairable in bounded mode`
|
|
196
|
+
: `repair pass budget exhausted (${attemptedPasses}/${maxRepairPasses})`;
|
|
197
|
+
return {
|
|
198
|
+
decision: 'stop',
|
|
199
|
+
reason,
|
|
200
|
+
actions: [
|
|
201
|
+
'emit failure summary and stop automatic retries',
|
|
202
|
+
'escalate to manual review or authorization flow'
|
|
203
|
+
],
|
|
204
|
+
retest: {
|
|
205
|
+
required: false,
|
|
206
|
+
commands: []
|
|
207
|
+
},
|
|
208
|
+
terminal_summary: {
|
|
209
|
+
status: 'stopped',
|
|
210
|
+
stop_reason: reason,
|
|
211
|
+
attempted_passes: attemptedPasses,
|
|
212
|
+
max_repair_passes: maxRepairPasses
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const actionSet = new Set(attribution.default_actions || []);
|
|
218
|
+
actionSet.add('apply one minimal scoped patch');
|
|
219
|
+
const retestCommands = Array.isArray(tests) && tests.length > 0
|
|
220
|
+
? tests
|
|
221
|
+
: (
|
|
222
|
+
testFailures > 0
|
|
223
|
+
? ['run failing test subset']
|
|
224
|
+
: ['run targeted verification tests']
|
|
225
|
+
);
|
|
226
|
+
actionSet.add('re-run targeted tests after repair pass');
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
decision: 'run_repair_pass',
|
|
230
|
+
reason: `category '${attribution.category}' is repairable with remaining budget`,
|
|
231
|
+
actions: [...actionSet],
|
|
232
|
+
retest: {
|
|
233
|
+
required: true,
|
|
234
|
+
commands: retestCommands
|
|
235
|
+
},
|
|
236
|
+
terminal_summary: {
|
|
237
|
+
status: 'repair-scheduled',
|
|
238
|
+
stop_reason: null,
|
|
239
|
+
attempted_passes: attemptedPasses,
|
|
240
|
+
max_repair_passes: maxRepairPasses,
|
|
241
|
+
remaining_after_this_pass: Math.max(0, remainingPasses - 1)
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function buildReport(options, errorText, taxonomy, attribution, repairPlan) {
|
|
247
|
+
return {
|
|
248
|
+
mode: 'failure-attribution-repair',
|
|
249
|
+
generated_at: new Date().toISOString(),
|
|
250
|
+
input: {
|
|
251
|
+
error: errorText,
|
|
252
|
+
test_failures: options.testFailures,
|
|
253
|
+
attempted_passes: options.attemptedPasses,
|
|
254
|
+
max_repair_passes: options.maxRepairPasses,
|
|
255
|
+
tests: options.tests
|
|
256
|
+
},
|
|
257
|
+
taxonomy: {
|
|
258
|
+
version: taxonomy.version,
|
|
259
|
+
default_category: taxonomy.default_category
|
|
260
|
+
},
|
|
261
|
+
attribution,
|
|
262
|
+
repair_policy: {
|
|
263
|
+
bounded: true,
|
|
264
|
+
attempted_passes: options.attemptedPasses,
|
|
265
|
+
max_repair_passes: options.maxRepairPasses
|
|
266
|
+
},
|
|
267
|
+
repair_pass: {
|
|
268
|
+
decision: repairPlan.decision,
|
|
269
|
+
reason: repairPlan.reason,
|
|
270
|
+
actions: repairPlan.actions
|
|
271
|
+
},
|
|
272
|
+
retest_plan: repairPlan.retest,
|
|
273
|
+
terminal_summary: repairPlan.terminal_summary
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function main() {
|
|
278
|
+
const options = parseArgs(process.argv.slice(2));
|
|
279
|
+
const errorText = loadTextError(options);
|
|
280
|
+
const taxonomy = loadTaxonomy(options.taxonomyFile);
|
|
281
|
+
const attribution = classifyFailure(errorText, taxonomy);
|
|
282
|
+
const repairPlan = buildRepairPlan({
|
|
283
|
+
attribution,
|
|
284
|
+
testFailures: options.testFailures,
|
|
285
|
+
attemptedPasses: options.attemptedPasses,
|
|
286
|
+
maxRepairPasses: options.maxRepairPasses,
|
|
287
|
+
tests: options.tests
|
|
288
|
+
});
|
|
289
|
+
const payload = buildReport(options, errorText, taxonomy, attribution, repairPlan);
|
|
290
|
+
|
|
291
|
+
if (options.json) {
|
|
292
|
+
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
293
|
+
} else {
|
|
294
|
+
process.stdout.write(`failure category=${payload.attribution.category}\n`);
|
|
295
|
+
process.stdout.write(`repair decision=${payload.repair_pass.decision}\n`);
|
|
296
|
+
process.stdout.write(`terminal status=${payload.terminal_summary.status}\n`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (require.main === module) {
|
|
301
|
+
try {
|
|
302
|
+
main();
|
|
303
|
+
} catch (error) {
|
|
304
|
+
console.error(`failure-attribution-repair failed: ${error.message}`);
|
|
305
|
+
process.exit(1);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
module.exports = {
|
|
310
|
+
DEFAULT_TAXONOMY_FILE,
|
|
311
|
+
parseArgs,
|
|
312
|
+
loadTextError,
|
|
313
|
+
loadTaxonomy,
|
|
314
|
+
classifyFailure,
|
|
315
|
+
buildRepairPlan,
|
|
316
|
+
buildReport
|
|
317
|
+
};
|