tribunal-kit 9.2.6 → 9.2.7
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/.agent/ARCHITECTURE.md +2 -2
- package/.agent/history/architecture-intelligence.html +1487 -401
- package/.agent/history/architecture-model.json +9365 -5697
- package/.agent/history/architecture-verification.json +37 -9
- package/.agent/routing_index.json +2069 -3340
- package/.agent/rules/GEMINI.md +1 -1
- package/.agent/scripts/adaptive_execution.js +511 -0
- package/.agent/scripts/architecture_diff.js +303 -260
- package/.agent/scripts/architecture_extractor.js +792 -753
- package/.agent/scripts/architecture_health.js +293 -256
- package/.agent/scripts/architecture_intelligence.js +3100 -0
- package/.agent/scripts/architecture_verifier.js +303 -270
- package/.agent/scripts/architecture_visualizer.js +880 -873
- package/.agent/scripts/blast_radius_engine.js +274 -234
- package/.agent/scripts/capability_evolution.js +453 -0
- package/.agent/scripts/concept_extractor.js +240 -0
- package/.agent/scripts/consideration_engine.js +284 -0
- package/.agent/scripts/coverage_engine.js +102 -0
- package/.agent/scripts/cross_domain_engine.js +1883 -0
- package/.agent/scripts/engineering_memory.js +1313 -0
- package/.agent/scripts/integrity_manifest.js +1 -5
- package/.agent/scripts/judgment_engine.js +790 -0
- package/.agent/scripts/materiality_engine.js +251 -0
- package/.agent/scripts/outcome_engine.js +624 -0
- package/.agent/scripts/outcome_optimization_engine.js +1632 -0
- package/.agent/scripts/simulation_engine.js +1478 -0
- package/.agent/scripts/skill_intelligence.js +1371 -0
- package/.agent/scripts/validation_engine.js +236 -236
- package/.agent/scripts/verification_auditor.js +266 -0
- package/.agent/skill-intelligence/taxonomy/engineering-concepts.json +555 -0
- package/.agent/skill_topic_map.json +301 -341
- package/.agent/skills_inventory.json +4272 -6922
- package/.agent/workflows/arch.md +96 -80
- package/.agent/workflows/skill-intelligence.md +216 -0
- package/CONTRIBUTING.md +2 -2
- package/README.md +24 -24
- package/bin/adapter-install.js +1 -1
- package/package.json +8 -9
- package/plugins/core-plugin.json +1 -1
- package/plugins/gemini/extension.json +1 -1
- package/src/browser/index.js +2 -1
- package/src/browser/launcher.js +41 -1
- package/src/cli.js +3 -1
- package/src/commands/arch.js +261 -172
- package/src/commands/context.js +27 -8
- package/src/commands/learn.js +21 -6
- package/src/commands/memory.js +10 -1
- package/src/commands/native.js +12 -3
- package/src/commands/skill-intelligence.js +1165 -0
- package/src/commands/system1.js +105 -4
- package/src/context/ranker.js +337 -339
- package/src/evolution/engine.js +296 -295
- package/src/synthesis/claim_check_separator.js +294 -271
- package/src/system1/browser_intelligence.js +300 -0
- package/src/system1/constants.js +49 -0
- package/src/system1/decision_engine.js +498 -0
- package/src/system1/evidence_engine.js +602 -0
- package/src/system1/evolution_pipeline.js +581 -0
- package/src/system1/index.d.ts +114 -0
- package/src/system1/index.js +102 -0
- package/src/system1/reviewer_orchestrator.js +477 -0
- package/src/tui/banner.js +1 -1
- package/src/utils/fs.js +27 -0
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* decision_engine.js — System-1 Capability 2: Cross-Capability Decision Engine
|
|
5
|
+
* ============================================================================
|
|
6
|
+
* Unified System-1 decision layer that combines:
|
|
7
|
+
* - Impact (Laya ONNX + change volume heuristic)
|
|
8
|
+
* - Risk (diff patterns, sensitive file types, credential leaks)
|
|
9
|
+
* - Evidence Intelligence (relevance, coverage, confidence L1-L4)
|
|
10
|
+
* - Browser / Interaction Intelligence (UI risk, route impact, CDP availability)
|
|
11
|
+
* - Adaptive Reviewer Orchestration (minimal covering reviewer set)
|
|
12
|
+
*
|
|
13
|
+
* Core Directives:
|
|
14
|
+
* 1. Monotonic Safety: Uncertainty maintains or increases scrutiny; never silently reduces scrutiny.
|
|
15
|
+
* 2. Precedence: High-risk signals can never be downgraded by low-confidence capabilities.
|
|
16
|
+
* 3. Explainability: Every decision contains an explicit audit trail of why the tier was chosen,
|
|
17
|
+
* which signals fired, which capabilities were consulted or unavailable, and whether fallback was used.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const crypto = require('crypto');
|
|
21
|
+
const {
|
|
22
|
+
HIGH_RISK_PATTERNS,
|
|
23
|
+
HIGH_RISK_EXTENSIONS,
|
|
24
|
+
TIER_NAMES,
|
|
25
|
+
ROUTING_NAMES,
|
|
26
|
+
} = require('./constants');
|
|
27
|
+
const { collectAndRankEvidence } = require('./evidence_engine');
|
|
28
|
+
const { evaluateBrowserRequirement } = require('./browser_intelligence');
|
|
29
|
+
const { orchestrateReviewers } = require('./reviewer_orchestrator');
|
|
30
|
+
|
|
31
|
+
function resolveMonotonicImpactTier(options = {}) {
|
|
32
|
+
const opts = options && typeof options === 'object' ? options : {};
|
|
33
|
+
const rawFiles = opts.files;
|
|
34
|
+
const files = (
|
|
35
|
+
Array.isArray(rawFiles) ? rawFiles : typeof rawFiles === 'string' ? rawFiles.split(',') : []
|
|
36
|
+
)
|
|
37
|
+
.map(f =>
|
|
38
|
+
typeof f === 'string'
|
|
39
|
+
? f
|
|
40
|
+
.replace(/[\u200B-\u200D\uFEFF]/g, '')
|
|
41
|
+
.trim()
|
|
42
|
+
.replace(/\\/g, '/')
|
|
43
|
+
: '',
|
|
44
|
+
)
|
|
45
|
+
.filter(Boolean);
|
|
46
|
+
const rawLines =
|
|
47
|
+
typeof opts.lines === 'number' && !isNaN(opts.lines)
|
|
48
|
+
? opts.lines
|
|
49
|
+
: parseInt(opts.lines, 10) || 0;
|
|
50
|
+
const lines = Math.max(0, rawLines);
|
|
51
|
+
const task = typeof opts.task === 'string' ? opts.task.replace(/[\u200B-\u200D\uFEFF]/g, '') : '';
|
|
52
|
+
const diff = typeof opts.diff === 'string' ? opts.diff.replace(/[\u200B-\u200D\uFEFF]/g, '') : '';
|
|
53
|
+
const layaTier = opts.layaTier;
|
|
54
|
+
|
|
55
|
+
const fileCount = files.length;
|
|
56
|
+
|
|
57
|
+
// 1. Base tier from change volume
|
|
58
|
+
const isFastPass =
|
|
59
|
+
fileCount <= 2 &&
|
|
60
|
+
lines <= 10 &&
|
|
61
|
+
files.length > 0 &&
|
|
62
|
+
files.every(f => /\.(css|scss|less|md|txt|svg|png|jpg)$/i.test(f));
|
|
63
|
+
|
|
64
|
+
let baseTier = 0;
|
|
65
|
+
if (isFastPass || (fileCount === 0 && lines <= 5)) baseTier = 0;
|
|
66
|
+
else if (fileCount <= 1 && lines <= 50) baseTier = 1;
|
|
67
|
+
else if (fileCount <= 5 && lines <= 200) baseTier = 2;
|
|
68
|
+
else baseTier = 3;
|
|
69
|
+
|
|
70
|
+
// 2. Concrete risk evidence analysis
|
|
71
|
+
const isPureDocFiles =
|
|
72
|
+
fileCount > 0 &&
|
|
73
|
+
files.every(f => /\.(md|txt|markdown|rst|adoc)$/i.test(f) || f.includes('docs/'));
|
|
74
|
+
|
|
75
|
+
// Concrete secret or code patterns that make even documentation dangerous
|
|
76
|
+
const secretOrExecPatterns =
|
|
77
|
+
/(?:-----BEGIN [A-Z ]+KEY-----|eyJ[A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+|AKIA[0-9A-Z]{16}|(?:aws[_-]?)?(?:api[_-]?key|secret(?:[_-]?key)?|password|bearer|auth[_-]?token|access[_-]?key(?:[_-]?id)?)\s*[:=]\s*['"]?[^'"\s\n]{6,}['"]?)/i;
|
|
78
|
+
|
|
79
|
+
const diffHasCode =
|
|
80
|
+
/^\+[ \t]*(?:const|let|var|function|def|import|require|class|export|db\.|SELECT|UPDATE|DELETE|INSERT|jwt\.|auth\.)/im.test(
|
|
81
|
+
diff,
|
|
82
|
+
);
|
|
83
|
+
const diffMatchesHighRiskCode = diffHasCode && HIGH_RISK_PATTERNS.test(diff);
|
|
84
|
+
|
|
85
|
+
const diffHasHighRisk =
|
|
86
|
+
HIGH_RISK_EXTENSIONS.test(diff) ||
|
|
87
|
+
diffMatchesHighRiskCode ||
|
|
88
|
+
(!isPureDocFiles && HIGH_RISK_PATTERNS.test(diff)) ||
|
|
89
|
+
secretOrExecPatterns.test(diff);
|
|
90
|
+
|
|
91
|
+
const fileHasHighRisk = files.some(
|
|
92
|
+
f =>
|
|
93
|
+
HIGH_RISK_EXTENSIONS.test(f) ||
|
|
94
|
+
(!isPureDocFiles && HIGH_RISK_PATTERNS.test(f)) ||
|
|
95
|
+
f.includes('docker') ||
|
|
96
|
+
f.includes('.github/'),
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
let riskEvidenceTier = 0;
|
|
100
|
+
if (diffHasHighRisk || fileHasHighRisk) {
|
|
101
|
+
riskEvidenceTier = 3;
|
|
102
|
+
} else if (!isPureDocFiles && HIGH_RISK_PATTERNS.test(task + ' ' + files.join(' '))) {
|
|
103
|
+
riskEvidenceTier = 3;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 3. Negative controls (Documentation changes)
|
|
107
|
+
// A doc change remains low risk (Tier 0) UNLESS concrete high-risk implementation evidence exists in files or diff
|
|
108
|
+
if (isPureDocFiles && !diffHasHighRisk && !fileHasHighRisk) {
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// 4. Ambiguity tier: short vague tasks (<= 2 words) touching non-doc code files
|
|
113
|
+
let ambiguityTier = 0;
|
|
114
|
+
const wordCount = task.trim().length > 0 ? task.trim().split(/\s+/).length : 0;
|
|
115
|
+
if (wordCount > 0 && wordCount <= 2 && fileCount > 0 && !isPureDocFiles) {
|
|
116
|
+
ambiguityTier = 2;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// 5. Monotonic aggregation: finalTier = max(baseTier, layaTier, riskEvidenceTier, ambiguityTier)
|
|
120
|
+
const candidateTiers = [baseTier, riskEvidenceTier, ambiguityTier];
|
|
121
|
+
if (typeof layaTier === 'number' && !isNaN(layaTier) && layaTier >= 0 && layaTier <= 3) {
|
|
122
|
+
candidateTiers.push(layaTier);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return Math.max(...candidateTiers);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Evaluate cross-capability System-1 decision
|
|
130
|
+
* @param {Object} options
|
|
131
|
+
* @param {string} [options.task]
|
|
132
|
+
* @param {string} [options.diff]
|
|
133
|
+
* @param {string[]|string} [options.files]
|
|
134
|
+
* @param {number} [options.lines]
|
|
135
|
+
* @param {Object} [options.evidence] - Optional pre-computed evidence
|
|
136
|
+
* @param {Object} [options.browserSignal] - Optional pre-computed browser signal
|
|
137
|
+
* @param {number|null} [options.layaTier] - Optional Laya inference output
|
|
138
|
+
* @param {string} [options.repoRoot] - Optional repository root
|
|
139
|
+
* @param {Array} [options.memory] - Optional memory items
|
|
140
|
+
* @param {Array} [options.previousFindings] - Optional previous findings
|
|
141
|
+
* @param {Object} [options.environment] - Optional environment overrides (e.g. browserFound)
|
|
142
|
+
* @returns {Object} Comprehensive Decision Payload
|
|
143
|
+
*/
|
|
144
|
+
function evaluateDecision(options = {}) {
|
|
145
|
+
const rawTask = typeof options.task === 'string' ? options.task : '';
|
|
146
|
+
const task = rawTask.replace(/[\u200B-\u200D\uFEFF]/g, '');
|
|
147
|
+
const rawDiff = typeof options.diff === 'string' ? options.diff : '';
|
|
148
|
+
const diff = rawDiff.replace(/[\u200B-\u200D\uFEFF]/g, '');
|
|
149
|
+
const rawFiles = options.files;
|
|
150
|
+
const files = (
|
|
151
|
+
Array.isArray(rawFiles) ? rawFiles : typeof rawFiles === 'string' ? rawFiles.split(',') : []
|
|
152
|
+
)
|
|
153
|
+
.map(f =>
|
|
154
|
+
typeof f === 'string'
|
|
155
|
+
? f
|
|
156
|
+
.replace(/[\u200B-\u200D\uFEFF]/g, '')
|
|
157
|
+
.trim()
|
|
158
|
+
.replace(/\\/g, '/')
|
|
159
|
+
: '',
|
|
160
|
+
)
|
|
161
|
+
.filter(Boolean);
|
|
162
|
+
const rawLines =
|
|
163
|
+
typeof options.lines === 'number' && !isNaN(options.lines)
|
|
164
|
+
? options.lines
|
|
165
|
+
: parseInt(options.lines, 10) || (diff ? diff.split('\n').length : 0);
|
|
166
|
+
const lines = Math.max(0, rawLines);
|
|
167
|
+
const repoRoot = options.repoRoot || process.cwd();
|
|
168
|
+
const layaTier = options.layaTier ?? null;
|
|
169
|
+
|
|
170
|
+
const capabilitiesConsulted = [];
|
|
171
|
+
const capabilitiesUnavailable = [];
|
|
172
|
+
const firedRiskSignals = [];
|
|
173
|
+
const monotonicSafeguards = [];
|
|
174
|
+
let fallbackUsed = false;
|
|
175
|
+
|
|
176
|
+
// 1. Evidence Intelligence Consultation
|
|
177
|
+
let evidenceResult = options.evidence;
|
|
178
|
+
if (!evidenceResult) {
|
|
179
|
+
try {
|
|
180
|
+
evidenceResult = collectAndRankEvidence({
|
|
181
|
+
task,
|
|
182
|
+
diff,
|
|
183
|
+
files,
|
|
184
|
+
repoRoot,
|
|
185
|
+
memory: options.memory,
|
|
186
|
+
previousFindings: options.previousFindings,
|
|
187
|
+
});
|
|
188
|
+
capabilitiesConsulted.push('evidence_engine');
|
|
189
|
+
} catch (_) {
|
|
190
|
+
capabilitiesUnavailable.push('evidence_engine');
|
|
191
|
+
evidenceResult = {
|
|
192
|
+
evidence: [],
|
|
193
|
+
summary: { confidence: 'L4', critical_evidence_count: 0, has_security_boundary: false },
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
} else {
|
|
197
|
+
capabilitiesConsulted.push('evidence_engine (provided)');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// 2. Browser Intelligence Consultation
|
|
201
|
+
let browserSignal = options.browserSignal;
|
|
202
|
+
if (!browserSignal) {
|
|
203
|
+
try {
|
|
204
|
+
browserSignal = evaluateBrowserRequirement({
|
|
205
|
+
files,
|
|
206
|
+
diff,
|
|
207
|
+
task,
|
|
208
|
+
environment: options.environment,
|
|
209
|
+
});
|
|
210
|
+
capabilitiesConsulted.push('browser_intelligence');
|
|
211
|
+
if (browserSignal.browser_available === 'UNAVAILABLE') {
|
|
212
|
+
capabilitiesUnavailable.push('browser_cdp');
|
|
213
|
+
}
|
|
214
|
+
} catch (_) {
|
|
215
|
+
capabilitiesUnavailable.push('browser_intelligence');
|
|
216
|
+
browserSignal = {
|
|
217
|
+
requires_browser_verification: false,
|
|
218
|
+
validation_level: 'NONE',
|
|
219
|
+
browser_available: 'UNAVAILABLE',
|
|
220
|
+
escalate: false,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
} else {
|
|
224
|
+
capabilitiesConsulted.push('browser_intelligence (provided)');
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// 3. Impact & Risk Analysis
|
|
228
|
+
if (layaTier !== null && typeof layaTier === 'number') {
|
|
229
|
+
capabilitiesConsulted.push('laya_onnx');
|
|
230
|
+
} else {
|
|
231
|
+
capabilitiesConsulted.push('deterministic_heuristic');
|
|
232
|
+
capabilitiesUnavailable.push('laya_onnx');
|
|
233
|
+
fallbackUsed = true;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Scan concrete risk signals
|
|
237
|
+
const combinedContext = `${task}\n${diff}\n${files.join('\n')}`;
|
|
238
|
+
if (HIGH_RISK_PATTERNS.test(combinedContext)) {
|
|
239
|
+
firedRiskSignals.push('HIGH_RISK_PATTERNS (auth/crypto/secrets/tokens/database)');
|
|
240
|
+
}
|
|
241
|
+
if (files.some(f => HIGH_RISK_EXTENSIONS.test(f)) || HIGH_RISK_EXTENSIONS.test(diff)) {
|
|
242
|
+
firedRiskSignals.push('HIGH_RISK_EXTENSIONS (.sql, .prisma, .tf)');
|
|
243
|
+
}
|
|
244
|
+
if (
|
|
245
|
+
/(?:-----BEGIN [A-Z ]+KEY-----|eyJ[A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+|(?:api[_-]?key|secret|password)\s*[:=])/i.test(
|
|
246
|
+
diff,
|
|
247
|
+
)
|
|
248
|
+
) {
|
|
249
|
+
firedRiskSignals.push('SECRET_OR_KEY_PATTERN (possible exposed credentials)');
|
|
250
|
+
}
|
|
251
|
+
if (evidenceResult.summary?.has_security_boundary) {
|
|
252
|
+
firedRiskSignals.push(
|
|
253
|
+
'SECURITY_BOUNDARY_EVIDENCE (direct touch of security policy / boundary)',
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Calculate baseline monotonic tier with fail-closed production safeguard
|
|
258
|
+
let calculatedTier = 3;
|
|
259
|
+
try {
|
|
260
|
+
const resolver =
|
|
261
|
+
typeof options.tierResolver === 'function'
|
|
262
|
+
? options.tierResolver
|
|
263
|
+
: resolveMonotonicImpactTier;
|
|
264
|
+
calculatedTier = resolver({
|
|
265
|
+
files,
|
|
266
|
+
lines,
|
|
267
|
+
task,
|
|
268
|
+
diff,
|
|
269
|
+
layaTier,
|
|
270
|
+
});
|
|
271
|
+
} catch (err) {
|
|
272
|
+
calculatedTier = 3;
|
|
273
|
+
monotonicSafeguards.push(
|
|
274
|
+
`Tier calculation fallback to Tier 3 due to exception: ${err.message}`,
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (
|
|
279
|
+
typeof calculatedTier !== 'number' ||
|
|
280
|
+
isNaN(calculatedTier) ||
|
|
281
|
+
calculatedTier < 0 ||
|
|
282
|
+
calculatedTier > 3
|
|
283
|
+
) {
|
|
284
|
+
calculatedTier = 3;
|
|
285
|
+
monotonicSafeguards.push(
|
|
286
|
+
`Tier calculation fallback to Tier 3 due to invalid output from resolver`,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
let finalTier = calculatedTier;
|
|
291
|
+
let escalated = false;
|
|
292
|
+
let escalationReason = null;
|
|
293
|
+
|
|
294
|
+
// 4. Cross-Capability Monotonic Rules & Conflict Resolution
|
|
295
|
+
// Base tier strictly from change volume (ignoring risk for safeguard comparison)
|
|
296
|
+
const isFastPassVol =
|
|
297
|
+
files.length <= 2 &&
|
|
298
|
+
lines <= 10 &&
|
|
299
|
+
files.every(f => /\.(css|scss|less|md|txt|svg|png|jpg)$/i.test(f));
|
|
300
|
+
const baseVolumeTier =
|
|
301
|
+
isFastPassVol || (files.length === 0 && lines <= 5)
|
|
302
|
+
? 0
|
|
303
|
+
: files.length <= 1 && lines <= 50
|
|
304
|
+
? 1
|
|
305
|
+
: files.length <= 5 && lines <= 200
|
|
306
|
+
? 2
|
|
307
|
+
: 3;
|
|
308
|
+
|
|
309
|
+
// Rule A: High Risk + Low Base Tier -> Enforce Tier 3
|
|
310
|
+
if (firedRiskSignals.length > 0) {
|
|
311
|
+
const isPureDoc = files.length > 0 && files.every(f => /\.(md|txt)$/i.test(f));
|
|
312
|
+
const hasDiffRisk = firedRiskSignals.some(
|
|
313
|
+
s =>
|
|
314
|
+
s.includes('SECRET') ||
|
|
315
|
+
s.includes('HIGH_RISK_EXTENSIONS') ||
|
|
316
|
+
s.includes('SECURITY_BOUNDARY') ||
|
|
317
|
+
diff.includes('jwt') ||
|
|
318
|
+
diff.includes('auth'),
|
|
319
|
+
);
|
|
320
|
+
if (!isPureDoc || hasDiffRisk) {
|
|
321
|
+
if (finalTier < 3) {
|
|
322
|
+
finalTier = 3;
|
|
323
|
+
}
|
|
324
|
+
if (baseVolumeTier < 3) {
|
|
325
|
+
monotonicSafeguards.push(
|
|
326
|
+
'Enforced Tier 3: Concrete risk signals detected despite low change volume',
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Rule B: Low Evidence Confidence (L4 / unavailable) forbids Fast-Pass (Tier 0)
|
|
333
|
+
const evidenceConfidence = evidenceResult.summary?.confidence || 'L4';
|
|
334
|
+
if ((evidenceConfidence === 'L4' || evidenceResult.evidence.length === 0) && finalTier === 0) {
|
|
335
|
+
const isTrivialDoc = files.length > 0 && files.every(f => /\.(md|txt)$/i.test(f)) && lines <= 5;
|
|
336
|
+
if (!isTrivialDoc) {
|
|
337
|
+
finalTier = 1; // Cannot fast-pass when evidence is unavailable/unverified
|
|
338
|
+
monotonicSafeguards.push(
|
|
339
|
+
'Elevated from Tier 0 to Tier 1: Low evidence confidence forbids Fast-Pass assumption',
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Rule C: Laya Downgrade Prevention
|
|
345
|
+
if (layaTier !== null && layaTier < finalTier) {
|
|
346
|
+
monotonicSafeguards.push(
|
|
347
|
+
`Prevented Laya downgrade: Laya suggested Tier ${layaTier}, but deterministic evidence mandated Tier ${finalTier}`,
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Rule D: Browser Intelligence Escalation
|
|
352
|
+
// If browser validation is required (SMOKE/FUNCTIONAL/HIGH_RISK) but browser is UNAVAILABLE, escalate
|
|
353
|
+
if (browserSignal.requires_browser_verification && browserSignal.escalate) {
|
|
354
|
+
escalated = true;
|
|
355
|
+
escalationReason =
|
|
356
|
+
browserSignal.safety_notice ||
|
|
357
|
+
'Browser verification is required but browser runtime is unavailable.';
|
|
358
|
+
monotonicSafeguards.push(
|
|
359
|
+
'Escalation triggered: Missing browser execution capability for UI change',
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// If browser risk is HIGH_RISK, elevate tier to at least Tier 2
|
|
364
|
+
if (browserSignal.validation_level === 'HIGH_RISK' && finalTier < 2) {
|
|
365
|
+
finalTier = 2;
|
|
366
|
+
monotonicSafeguards.push(
|
|
367
|
+
'Elevated to Tier 2: High-risk browser verification (payment/auth UI)',
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// If Tier 2 and Browser risk is HIGH_RISK + browser unavailable -> Escalate to human gate
|
|
372
|
+
if (
|
|
373
|
+
finalTier >= 2 &&
|
|
374
|
+
browserSignal.validation_level === 'HIGH_RISK' &&
|
|
375
|
+
browserSignal.browser_available === 'UNAVAILABLE'
|
|
376
|
+
) {
|
|
377
|
+
escalated = true;
|
|
378
|
+
escalationReason =
|
|
379
|
+
'High-risk payment/auth browser verification required but browser environment is unavailable.';
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// 5. Adaptive Reviewer Orchestration
|
|
383
|
+
let reviewerResult;
|
|
384
|
+
try {
|
|
385
|
+
reviewerResult = orchestrateReviewers({
|
|
386
|
+
tier: finalTier,
|
|
387
|
+
files,
|
|
388
|
+
diff,
|
|
389
|
+
task,
|
|
390
|
+
evidence: evidenceResult.evidence,
|
|
391
|
+
previousFindings: options.previousFindings,
|
|
392
|
+
});
|
|
393
|
+
capabilitiesConsulted.push('reviewer_orchestrator');
|
|
394
|
+
} catch (_) {
|
|
395
|
+
capabilitiesUnavailable.push('reviewer_orchestrator');
|
|
396
|
+
reviewerResult = {
|
|
397
|
+
selected: [],
|
|
398
|
+
rejected: [],
|
|
399
|
+
total_selected: 0,
|
|
400
|
+
coverage: { all_risks_covered: false },
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// 6. Routing Decision & Socratic Gate
|
|
405
|
+
const routing = escalated ? 'ESCALATE' : ROUTING_NAMES[finalTier] || 'TARGETED_REVIEW';
|
|
406
|
+
|
|
407
|
+
const socraticGate = escalated
|
|
408
|
+
? 'required'
|
|
409
|
+
: finalTier >= 3
|
|
410
|
+
? 'required'
|
|
411
|
+
: finalTier >= 2
|
|
412
|
+
? 'conditional'
|
|
413
|
+
: 'bypass';
|
|
414
|
+
|
|
415
|
+
// 7. Explanations & Provenance
|
|
416
|
+
const influencingEvidence = evidenceResult.evidence
|
|
417
|
+
.filter(e => e.score >= 0.8 || e.is_mandatory)
|
|
418
|
+
.map(e => `${e.id} (score: ${e.score})`);
|
|
419
|
+
|
|
420
|
+
let whyTierSelected = `Classified as ${TIER_NAMES[finalTier]} (Tier ${finalTier}). `;
|
|
421
|
+
if (firedRiskSignals.length > 0) {
|
|
422
|
+
whyTierSelected += `Risk signals fired: [${firedRiskSignals.join(', ')}]. `;
|
|
423
|
+
} else if (finalTier === 0) {
|
|
424
|
+
whyTierSelected +=
|
|
425
|
+
'Change is low-volume styling/documentation with zero risk signals (Fast-Pass eligible). ';
|
|
426
|
+
} else if (finalTier === 1) {
|
|
427
|
+
whyTierSelected +=
|
|
428
|
+
'Single-file or bounded component edit with isolated impact (Express Pass). ';
|
|
429
|
+
} else if (finalTier === 2) {
|
|
430
|
+
whyTierSelected += 'Multi-file feature edit requiring targeted domain verification. ';
|
|
431
|
+
} else {
|
|
432
|
+
whyTierSelected +=
|
|
433
|
+
'High-impact architectural or security change requiring full gauntlet review. ';
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (escalated) {
|
|
437
|
+
whyTierSelected += `ESCALATED: ${escalationReason}`;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Overall Decision Confidence
|
|
441
|
+
let decisionConfidence = 'L1';
|
|
442
|
+
if (fallbackUsed && evidenceConfidence !== 'L1') {
|
|
443
|
+
decisionConfidence = 'L2';
|
|
444
|
+
} else if (evidenceConfidence === 'L3' || evidenceConfidence === 'L4') {
|
|
445
|
+
decisionConfidence = evidenceConfidence;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return {
|
|
449
|
+
decision_id: `DEC-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`,
|
|
450
|
+
timestamp: new Date().toISOString(),
|
|
451
|
+
tier: finalTier,
|
|
452
|
+
tier_name: TIER_NAMES[finalTier],
|
|
453
|
+
routing,
|
|
454
|
+
socratic_gate: socraticGate,
|
|
455
|
+
escalated,
|
|
456
|
+
escalation_reason: escalationReason,
|
|
457
|
+
confidence: decisionConfidence,
|
|
458
|
+
explanation: {
|
|
459
|
+
why_tier_selected: whyTierSelected.trim(),
|
|
460
|
+
influencing_evidence: influencingEvidence,
|
|
461
|
+
fired_risk_signals: firedRiskSignals,
|
|
462
|
+
capabilities_consulted: capabilitiesConsulted,
|
|
463
|
+
capabilities_unavailable: capabilitiesUnavailable,
|
|
464
|
+
fallback_used: fallbackUsed,
|
|
465
|
+
monotonic_safeguards_applied: monotonicSafeguards,
|
|
466
|
+
},
|
|
467
|
+
signals: {
|
|
468
|
+
change_lines: lines,
|
|
469
|
+
change_files_count: files.length,
|
|
470
|
+
impact_tier_raw: calculatedTier,
|
|
471
|
+
laya_tier: layaTier,
|
|
472
|
+
evidence_confidence: evidenceConfidence,
|
|
473
|
+
browser_validation_level: browserSignal.validation_level,
|
|
474
|
+
browser_available: browserSignal.browser_available,
|
|
475
|
+
},
|
|
476
|
+
evidence_summary: {
|
|
477
|
+
total_evaluated: evidenceResult.summary?.total_items_evaluated || 0,
|
|
478
|
+
total_selected: evidenceResult.summary?.total_items_selected || 0,
|
|
479
|
+
critical_count: evidenceResult.summary?.critical_evidence_count || 0,
|
|
480
|
+
confidence: evidenceConfidence,
|
|
481
|
+
},
|
|
482
|
+
reviewers: {
|
|
483
|
+
selected: reviewerResult.selected,
|
|
484
|
+
rejected: reviewerResult.rejected,
|
|
485
|
+
total_selected: reviewerResult.total_selected,
|
|
486
|
+
all_risks_covered: reviewerResult.coverage?.all_risks_covered ?? true,
|
|
487
|
+
},
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
module.exports = {
|
|
492
|
+
evaluateDecision,
|
|
493
|
+
resolveMonotonicImpactTier,
|
|
494
|
+
HIGH_RISK_PATTERNS,
|
|
495
|
+
HIGH_RISK_EXTENSIONS,
|
|
496
|
+
TIER_NAMES,
|
|
497
|
+
ROUTING_NAMES,
|
|
498
|
+
};
|