scene-capability-engine 3.6.32 → 3.6.36
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 +86 -1
- package/README.md +119 -122
- package/README.zh.md +123 -121
- package/bin/scene-capability-engine.js +11 -0
- package/docs/README.md +21 -32
- package/docs/auto-refactor-index.md +384 -0
- package/docs/command-reference.md +94 -2
- package/docs/magicball-adaptation-task-checklist-v1.md +385 -0
- package/docs/magicball-app-bundle-sqlite-and-command-draft.md +539 -0
- package/docs/magicball-capability-iteration-api.md +2 -0
- package/docs/magicball-capability-iteration-ui.md +2 -0
- package/docs/magicball-capability-library.md +2 -0
- package/docs/magicball-cli-invocation-examples.md +336 -0
- package/docs/magicball-frontend-state-and-command-mapping.md +244 -0
- package/docs/magicball-integration-doc-index.md +137 -0
- package/docs/magicball-integration-issue-tracker.md +218 -0
- package/docs/magicball-mode-home-and-ontology-empty-state-playbook.md +249 -0
- package/docs/magicball-sce-adaptation-guide.md +203 -0
- package/docs/magicball-three-mode-alignment-plan.md +551 -0
- package/docs/magicball-ui-surface-checklist.md +126 -0
- package/docs/magicball-write-auth-adaptation-guide.md +328 -0
- package/docs/refactor-completion-roadmap.md +116 -0
- package/docs/zh/README.md +27 -30
- package/docs/zh/refactor-completion-roadmap.md +116 -0
- package/lib/app/registry-config.js +73 -0
- package/lib/app/registry-sync-service.js +228 -0
- package/lib/auto/archive-schema-service.js +276 -0
- package/lib/auto/archive-summary.js +60 -0
- package/lib/auto/batch-goal-input-service.js +543 -0
- package/lib/auto/batch-output.js +201 -0
- package/lib/auto/batch-summary-storage-service.js +110 -0
- package/lib/auto/close-loop-batch-service.js +116 -0
- package/lib/auto/close-loop-controller-service.js +287 -0
- package/lib/auto/close-loop-program-service.js +283 -0
- package/lib/auto/close-loop-recovery-service.js +191 -0
- package/lib/auto/close-loop-session-storage-service.js +50 -0
- package/lib/auto/controller-lock-service.js +55 -0
- package/lib/auto/controller-output.js +32 -0
- package/lib/auto/controller-queue-service.js +127 -0
- package/lib/auto/controller-session-storage-service.js +105 -0
- package/lib/auto/governance-advisory-service.js +208 -0
- package/lib/auto/governance-close-loop-service.js +411 -0
- package/lib/auto/governance-maintenance-presenter.js +162 -0
- package/lib/auto/governance-maintenance-service.js +112 -0
- package/lib/auto/governance-session-presenter.js +70 -0
- package/lib/auto/governance-session-storage-service.js +198 -0
- package/lib/auto/governance-signals.js +139 -0
- package/lib/auto/governance-stats-presenter.js +337 -0
- package/lib/auto/governance-stats-service.js +115 -0
- package/lib/auto/governance-summary.js +703 -0
- package/lib/auto/handoff-capability-matrix-service.js +281 -0
- package/lib/auto/handoff-evidence-review-service.js +251 -0
- package/lib/auto/handoff-release-evidence-service.js +190 -0
- package/lib/auto/handoff-release-gate-history-loaders-service.js +502 -0
- package/lib/auto/handoff-release-gate-history-service.js +257 -0
- package/lib/auto/handoff-reporting-service.js +1407 -0
- package/lib/auto/handoff-run-service.js +486 -0
- package/lib/auto/handoff-snapshots-service.js +645 -0
- package/lib/auto/observability-service.js +132 -0
- package/lib/auto/output-writer.js +34 -0
- package/lib/auto/program-auto-remediation-service.js +130 -0
- package/lib/auto/program-diagnostics.js +138 -0
- package/lib/auto/program-governance-helpers.js +306 -0
- package/lib/auto/program-governance-loop-service.js +413 -0
- package/lib/auto/program-output.js +106 -0
- package/lib/auto/program-summary.js +183 -0
- package/lib/auto/recovery-memory-service.js +684 -0
- package/lib/auto/recovery-selection-service.js +52 -0
- package/lib/auto/retention-policy.js +98 -0
- package/lib/auto/session-persistence-service.js +106 -0
- package/lib/auto/session-presenter.js +105 -0
- package/lib/auto/session-prune-service.js +190 -0
- package/lib/auto/session-query-service.js +249 -0
- package/lib/auto/spec-protection.js +141 -0
- package/lib/commands/app.js +911 -0
- package/lib/commands/assurance.js +212 -0
- package/lib/commands/auto.js +1091 -11063
- package/lib/commands/mode.js +321 -0
- package/lib/commands/ontology.js +415 -0
- package/lib/commands/pm.js +422 -0
- package/lib/ontology/seed-profiles.js +160 -0
- package/lib/state/sce-state-store.js +3369 -1200
- package/package.json +1 -1
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
function normalizeProgramGateFallbackProfile(profileCandidate, dependencies = {}) {
|
|
2
|
+
const PROGRAM_GATE_PROFILE_POLICY = dependencies.PROGRAM_GATE_PROFILE_POLICY || {};
|
|
3
|
+
const normalized = typeof profileCandidate === 'string'
|
|
4
|
+
? profileCandidate.trim().toLowerCase()
|
|
5
|
+
: 'none';
|
|
6
|
+
if (normalized === 'none') {
|
|
7
|
+
return 'none';
|
|
8
|
+
}
|
|
9
|
+
if (!PROGRAM_GATE_PROFILE_POLICY[normalized]) {
|
|
10
|
+
throw new Error('--program-gate-fallback-profile must be one of: none, default, dev, staging, prod.');
|
|
11
|
+
}
|
|
12
|
+
return normalized;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function normalizeProgramGateFallbackChain(chainCandidate, dependencies = {}) {
|
|
16
|
+
const PROGRAM_GATE_PROFILE_POLICY = dependencies.PROGRAM_GATE_PROFILE_POLICY || {};
|
|
17
|
+
if (chainCandidate === undefined || chainCandidate === null) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const raw = `${chainCandidate}`.trim();
|
|
21
|
+
if (!raw) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const tokens = raw
|
|
25
|
+
.split(',')
|
|
26
|
+
.map(item => item.trim().toLowerCase())
|
|
27
|
+
.filter(Boolean);
|
|
28
|
+
if (tokens.length === 0) {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
if (tokens.includes('none')) {
|
|
32
|
+
if (tokens.length > 1) {
|
|
33
|
+
throw new Error('--program-gate-fallback-chain cannot mix "none" with other profiles.');
|
|
34
|
+
}
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
const normalized = [];
|
|
38
|
+
const seen = new Set();
|
|
39
|
+
for (const token of tokens) {
|
|
40
|
+
if (!PROGRAM_GATE_PROFILE_POLICY[token]) {
|
|
41
|
+
throw new Error('--program-gate-fallback-chain must contain only: none, default, dev, staging, prod.');
|
|
42
|
+
}
|
|
43
|
+
if (seen.has(token)) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
seen.add(token);
|
|
47
|
+
normalized.push(token);
|
|
48
|
+
}
|
|
49
|
+
return normalized;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function resolveProgramGateFallbackChain(chainCandidate, fallbackProfileCandidate, dependencies = {}) {
|
|
53
|
+
const parsedChain = normalizeProgramGateFallbackChain(chainCandidate, dependencies);
|
|
54
|
+
if (Array.isArray(parsedChain)) {
|
|
55
|
+
return parsedChain;
|
|
56
|
+
}
|
|
57
|
+
const normalizedSingle = normalizeProgramGateFallbackProfile(fallbackProfileCandidate, dependencies);
|
|
58
|
+
return normalizedSingle === 'none' ? [] : [normalizedSingle];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function resolveProgramGatePolicy(policy = {}, dependencies = {}) {
|
|
62
|
+
const normalizeProgramGateProfile = dependencies.normalizeProgramGateProfile;
|
|
63
|
+
const normalizeProgramMinSuccessRate = dependencies.normalizeProgramMinSuccessRate;
|
|
64
|
+
const normalizeProgramRiskLevel = dependencies.normalizeProgramRiskLevel;
|
|
65
|
+
const normalizeProgramMaxElapsedMinutes = dependencies.normalizeProgramMaxElapsedMinutes;
|
|
66
|
+
const normalizeProgramMaxAgentBudget = dependencies.normalizeProgramMaxAgentBudget;
|
|
67
|
+
const normalizeProgramMaxTotalSubSpecs = dependencies.normalizeProgramMaxTotalSubSpecs;
|
|
68
|
+
const PROGRAM_GATE_PROFILE_POLICY = dependencies.PROGRAM_GATE_PROFILE_POLICY || {};
|
|
69
|
+
|
|
70
|
+
const profile = normalizeProgramGateProfile(policy.profile);
|
|
71
|
+
const profilePolicy = PROGRAM_GATE_PROFILE_POLICY[profile];
|
|
72
|
+
const minSuccessRate = policy.minSuccessRate === undefined || policy.minSuccessRate === null
|
|
73
|
+
? normalizeProgramMinSuccessRate(profilePolicy.minSuccessRate)
|
|
74
|
+
: normalizeProgramMinSuccessRate(policy.minSuccessRate);
|
|
75
|
+
const maxRiskLevel = policy.maxRiskLevel === undefined || policy.maxRiskLevel === null
|
|
76
|
+
? normalizeProgramRiskLevel(profilePolicy.maxRiskLevel)
|
|
77
|
+
: normalizeProgramRiskLevel(policy.maxRiskLevel);
|
|
78
|
+
const maxElapsedMinutes = policy.maxElapsedMinutes === undefined || policy.maxElapsedMinutes === null
|
|
79
|
+
? normalizeProgramMaxElapsedMinutes(profilePolicy.maxElapsedMinutes)
|
|
80
|
+
: normalizeProgramMaxElapsedMinutes(policy.maxElapsedMinutes);
|
|
81
|
+
const maxAgentBudget = policy.maxAgentBudget === undefined || policy.maxAgentBudget === null
|
|
82
|
+
? normalizeProgramMaxAgentBudget(profilePolicy.maxAgentBudget)
|
|
83
|
+
: normalizeProgramMaxAgentBudget(policy.maxAgentBudget);
|
|
84
|
+
const maxTotalSubSpecs = policy.maxTotalSubSpecs === undefined || policy.maxTotalSubSpecs === null
|
|
85
|
+
? normalizeProgramMaxTotalSubSpecs(profilePolicy.maxTotalSubSpecs)
|
|
86
|
+
: normalizeProgramMaxTotalSubSpecs(policy.maxTotalSubSpecs);
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
profile,
|
|
90
|
+
minSuccessRate,
|
|
91
|
+
maxRiskLevel,
|
|
92
|
+
maxElapsedMinutes,
|
|
93
|
+
maxAgentBudget,
|
|
94
|
+
maxTotalSubSpecs
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function evaluateProgramConvergenceGate(summary, policy = {}, dependencies = {}) {
|
|
99
|
+
const buildProgramKpiSnapshot = dependencies.buildProgramKpiSnapshot;
|
|
100
|
+
const resolveProgramGatePolicyFn = dependencies.resolveProgramGatePolicy;
|
|
101
|
+
|
|
102
|
+
const metrics = summary && summary.metrics && typeof summary.metrics === 'object'
|
|
103
|
+
? summary.metrics
|
|
104
|
+
: {};
|
|
105
|
+
const programKpi = summary && summary.program_kpi && typeof summary.program_kpi === 'object'
|
|
106
|
+
? summary.program_kpi
|
|
107
|
+
: buildProgramKpiSnapshot(summary || {});
|
|
108
|
+
const resolvedPolicy = resolveProgramGatePolicyFn(policy);
|
|
109
|
+
const minSuccessRate = resolvedPolicy.minSuccessRate;
|
|
110
|
+
const maxRiskLevel = resolvedPolicy.maxRiskLevel;
|
|
111
|
+
const maxElapsedMinutes = resolvedPolicy.maxElapsedMinutes;
|
|
112
|
+
const maxAgentBudget = resolvedPolicy.maxAgentBudget;
|
|
113
|
+
const maxTotalSubSpecs = resolvedPolicy.maxTotalSubSpecs;
|
|
114
|
+
const completionRateFromKpi = Number(programKpi.completion_rate_percent);
|
|
115
|
+
const successRateFromMetrics = Number(metrics.success_rate_percent);
|
|
116
|
+
const successRate = Number.isFinite(completionRateFromKpi)
|
|
117
|
+
? completionRateFromKpi
|
|
118
|
+
: (Number.isFinite(successRateFromMetrics) ? successRateFromMetrics : null);
|
|
119
|
+
const elapsedMsCandidate = Number(summary && summary.program_elapsed_ms);
|
|
120
|
+
const elapsedMs = Number.isFinite(elapsedMsCandidate) && elapsedMsCandidate >= 0
|
|
121
|
+
? elapsedMsCandidate
|
|
122
|
+
: null;
|
|
123
|
+
const elapsedMinutes = elapsedMs === null
|
|
124
|
+
? null
|
|
125
|
+
: Number((elapsedMs / 60000).toFixed(2));
|
|
126
|
+
const resourcePlan = summary && summary.resource_plan && typeof summary.resource_plan === 'object'
|
|
127
|
+
? summary.resource_plan
|
|
128
|
+
: {};
|
|
129
|
+
const agentBudgetCandidate = Number(resourcePlan.agent_budget);
|
|
130
|
+
const effectiveParallelCandidate = Number(resourcePlan.effective_goal_parallel);
|
|
131
|
+
const batchParallelCandidate = Number(summary && summary.batch_parallel);
|
|
132
|
+
const actualAgentBudget = Number.isFinite(agentBudgetCandidate) && agentBudgetCandidate > 0
|
|
133
|
+
? agentBudgetCandidate
|
|
134
|
+
: Number.isFinite(effectiveParallelCandidate) && effectiveParallelCandidate > 0
|
|
135
|
+
? effectiveParallelCandidate
|
|
136
|
+
: Number.isFinite(batchParallelCandidate) && batchParallelCandidate > 0
|
|
137
|
+
? batchParallelCandidate
|
|
138
|
+
: null;
|
|
139
|
+
const totalSubSpecsFromMetrics = Number(metrics.total_sub_specs);
|
|
140
|
+
const totalSubSpecs = Number.isFinite(totalSubSpecsFromMetrics)
|
|
141
|
+
? totalSubSpecsFromMetrics
|
|
142
|
+
: (
|
|
143
|
+
Array.isArray(summary && summary.results)
|
|
144
|
+
? summary.results.reduce((sum, item) => sum + (Number(item && item.sub_spec_count) || 0), 0)
|
|
145
|
+
: null
|
|
146
|
+
);
|
|
147
|
+
const riskLevel = `${programKpi.risk_level || 'high'}`.trim().toLowerCase();
|
|
148
|
+
const riskRank = { low: 1, medium: 2, high: 3 };
|
|
149
|
+
const reasons = [];
|
|
150
|
+
if (!Number.isFinite(successRate)) {
|
|
151
|
+
reasons.push('success_rate_percent unavailable');
|
|
152
|
+
} else if (successRate < minSuccessRate) {
|
|
153
|
+
reasons.push(`success_rate_percent ${successRate} < required ${minSuccessRate}`);
|
|
154
|
+
}
|
|
155
|
+
if ((riskRank[riskLevel] || 3) > (riskRank[maxRiskLevel] || 3)) {
|
|
156
|
+
reasons.push(`risk_level ${riskLevel} exceeds allowed ${maxRiskLevel}`);
|
|
157
|
+
}
|
|
158
|
+
if (maxElapsedMinutes !== null) {
|
|
159
|
+
if (!Number.isFinite(elapsedMinutes)) {
|
|
160
|
+
reasons.push('program_elapsed_minutes unavailable');
|
|
161
|
+
} else if (elapsedMinutes > maxElapsedMinutes) {
|
|
162
|
+
reasons.push(`program_elapsed_minutes ${elapsedMinutes} exceeds allowed ${maxElapsedMinutes}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (maxAgentBudget !== null) {
|
|
166
|
+
if (!Number.isFinite(actualAgentBudget)) {
|
|
167
|
+
reasons.push('agent_budget unavailable');
|
|
168
|
+
} else if (actualAgentBudget > maxAgentBudget) {
|
|
169
|
+
reasons.push(`agent_budget ${actualAgentBudget} exceeds allowed ${maxAgentBudget}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (maxTotalSubSpecs !== null) {
|
|
173
|
+
if (!Number.isFinite(totalSubSpecs)) {
|
|
174
|
+
reasons.push('total_sub_specs unavailable');
|
|
175
|
+
} else if (totalSubSpecs > maxTotalSubSpecs) {
|
|
176
|
+
reasons.push(`total_sub_specs ${totalSubSpecs} exceeds allowed ${maxTotalSubSpecs}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
passed: reasons.length === 0,
|
|
182
|
+
policy: {
|
|
183
|
+
profile: resolvedPolicy.profile,
|
|
184
|
+
min_success_rate_percent: minSuccessRate,
|
|
185
|
+
max_risk_level: maxRiskLevel,
|
|
186
|
+
max_elapsed_minutes: maxElapsedMinutes,
|
|
187
|
+
max_agent_budget: maxAgentBudget,
|
|
188
|
+
max_total_sub_specs: maxTotalSubSpecs
|
|
189
|
+
},
|
|
190
|
+
actual: {
|
|
191
|
+
success_rate_percent: Number.isFinite(successRate) ? successRate : null,
|
|
192
|
+
risk_level: riskLevel,
|
|
193
|
+
elapsed_minutes: Number.isFinite(elapsedMinutes) ? elapsedMinutes : null,
|
|
194
|
+
agent_budget: Number.isFinite(actualAgentBudget) ? actualAgentBudget : null,
|
|
195
|
+
total_sub_specs: Number.isFinite(totalSubSpecs) ? totalSubSpecs : null
|
|
196
|
+
},
|
|
197
|
+
reasons
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function applyAnomalyBatchConcurrencyReductionPatch(summary, patch, reasons, options, anomalyType, dependencies = {}) {
|
|
202
|
+
const normalizeBatchParallel = dependencies.normalizeBatchParallel;
|
|
203
|
+
const normalizeBatchAgentBudget = dependencies.normalizeBatchAgentBudget;
|
|
204
|
+
|
|
205
|
+
const currentParallelCandidate = patch.batchParallel !== undefined && patch.batchParallel !== null
|
|
206
|
+
? patch.batchParallel
|
|
207
|
+
: (
|
|
208
|
+
options.batchParallel !== undefined && options.batchParallel !== null
|
|
209
|
+
? options.batchParallel
|
|
210
|
+
: (summary && summary.batch_parallel ? summary.batch_parallel : 1)
|
|
211
|
+
);
|
|
212
|
+
const currentParallel = normalizeBatchParallel(currentParallelCandidate);
|
|
213
|
+
if (currentParallel > 1) {
|
|
214
|
+
patch.batchParallel = currentParallel - 1;
|
|
215
|
+
reasons.push(`reduce batch parallel from ${currentParallel} to ${patch.batchParallel} due to ${anomalyType}`);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const currentAgentBudgetCandidate = patch.batchAgentBudget !== undefined && patch.batchAgentBudget !== null
|
|
219
|
+
? patch.batchAgentBudget
|
|
220
|
+
: (
|
|
221
|
+
options.batchAgentBudget !== undefined && options.batchAgentBudget !== null
|
|
222
|
+
? options.batchAgentBudget
|
|
223
|
+
: (summary && summary.resource_plan ? summary.resource_plan.agent_budget : null)
|
|
224
|
+
);
|
|
225
|
+
const currentAgentBudget = normalizeBatchAgentBudget(currentAgentBudgetCandidate);
|
|
226
|
+
if (currentAgentBudget !== null && currentAgentBudget > 1) {
|
|
227
|
+
patch.batchAgentBudget = currentAgentBudget - 1;
|
|
228
|
+
reasons.push(`reduce batch agent budget from ${currentAgentBudget} to ${patch.batchAgentBudget} due to ${anomalyType}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function buildProgramAnomalyGovernancePatch(summary, anomalies, options = {}, dependencies = {}) {
|
|
233
|
+
const normalizeBatchRetryRounds = dependencies.normalizeBatchRetryRounds;
|
|
234
|
+
const normalizeBatchParallel = dependencies.normalizeBatchParallel;
|
|
235
|
+
const normalizeBatchAgentBudget = dependencies.normalizeBatchAgentBudget;
|
|
236
|
+
|
|
237
|
+
const sourceAnomalies = Array.isArray(anomalies) ? anomalies : [];
|
|
238
|
+
const highAnomalies = sourceAnomalies.filter(item => `${item && item.severity ? item.severity : ''}`.trim().toLowerCase() === 'high');
|
|
239
|
+
const patch = {};
|
|
240
|
+
const reasons = [];
|
|
241
|
+
|
|
242
|
+
const anomalyTypes = new Set(highAnomalies.map(item => `${item && item.type ? item.type : ''}`.trim().toLowerCase()));
|
|
243
|
+
if (anomalyTypes.has('success-rate-drop')) {
|
|
244
|
+
const currentRetryRounds = normalizeBatchRetryRounds(options.batchRetryRounds);
|
|
245
|
+
patch.batchRetryRounds = Math.min(5, Math.max(1, currentRetryRounds + 1));
|
|
246
|
+
patch.batchRetryUntilComplete = true;
|
|
247
|
+
reasons.push('increase retry rounds due to success-rate-drop anomaly');
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (anomalyTypes.has('failed-goals-spike')) {
|
|
251
|
+
applyAnomalyBatchConcurrencyReductionPatch(summary, patch, reasons, options, 'failed-goals-spike', {
|
|
252
|
+
normalizeBatchParallel,
|
|
253
|
+
normalizeBatchAgentBudget
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (anomalyTypes.has('rate-limit-spike')) {
|
|
258
|
+
applyAnomalyBatchConcurrencyReductionPatch(summary, patch, reasons, options, 'rate-limit-spike', {
|
|
259
|
+
normalizeBatchParallel,
|
|
260
|
+
normalizeBatchAgentBudget
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (anomalyTypes.has('spec-growth-spike')) {
|
|
265
|
+
patch.specSessionBudgetHardFail = true;
|
|
266
|
+
reasons.push('enable spec-session budget hard-fail due to spec-growth-spike');
|
|
267
|
+
if (options.specSessionMaxCreated === undefined || options.specSessionMaxCreated === null) {
|
|
268
|
+
const estimatedCreated = Number(summary && summary.spec_session_budget && summary.spec_session_budget.estimated_created) || 0;
|
|
269
|
+
patch.specSessionMaxCreated = Math.max(1, Math.ceil(estimatedCreated * 0.8));
|
|
270
|
+
reasons.push(`set specSessionMaxCreated=${patch.specSessionMaxCreated} due to spec-growth-spike`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return {
|
|
275
|
+
patch,
|
|
276
|
+
reasons,
|
|
277
|
+
anomaly_count: highAnomalies.length,
|
|
278
|
+
anomaly_types: [...anomalyTypes]
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function normalizeFailureSignatureFromError(errorMessage) {
|
|
283
|
+
if (typeof errorMessage !== 'string' || !errorMessage.trim()) {
|
|
284
|
+
return 'no-error-details';
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return errorMessage
|
|
288
|
+
.toLowerCase()
|
|
289
|
+
.replace(/[0-9]+/g, '#')
|
|
290
|
+
.replace(/[a-z]:\\[^ ]+/gi, '<path>')
|
|
291
|
+
.replace(/\/[^ ]+/g, '<path>')
|
|
292
|
+
.replace(/["'`]/g, '')
|
|
293
|
+
.replace(/\s+/g, ' ')
|
|
294
|
+
.trim()
|
|
295
|
+
.slice(0, 120);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
module.exports = {
|
|
299
|
+
normalizeProgramGateFallbackProfile,
|
|
300
|
+
normalizeProgramGateFallbackChain,
|
|
301
|
+
resolveProgramGateFallbackChain,
|
|
302
|
+
resolveProgramGatePolicy,
|
|
303
|
+
evaluateProgramConvergenceGate,
|
|
304
|
+
buildProgramAnomalyGovernancePatch,
|
|
305
|
+
normalizeFailureSignatureFromError
|
|
306
|
+
};
|