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.
Files changed (63) hide show
  1. package/.agent/ARCHITECTURE.md +2 -2
  2. package/.agent/history/architecture-intelligence.html +1487 -401
  3. package/.agent/history/architecture-model.json +9365 -5697
  4. package/.agent/history/architecture-verification.json +37 -9
  5. package/.agent/routing_index.json +2069 -3340
  6. package/.agent/rules/GEMINI.md +1 -1
  7. package/.agent/scripts/adaptive_execution.js +511 -0
  8. package/.agent/scripts/architecture_diff.js +303 -260
  9. package/.agent/scripts/architecture_extractor.js +792 -753
  10. package/.agent/scripts/architecture_health.js +293 -256
  11. package/.agent/scripts/architecture_intelligence.js +3100 -0
  12. package/.agent/scripts/architecture_verifier.js +303 -270
  13. package/.agent/scripts/architecture_visualizer.js +880 -873
  14. package/.agent/scripts/blast_radius_engine.js +274 -234
  15. package/.agent/scripts/capability_evolution.js +453 -0
  16. package/.agent/scripts/concept_extractor.js +240 -0
  17. package/.agent/scripts/consideration_engine.js +284 -0
  18. package/.agent/scripts/coverage_engine.js +102 -0
  19. package/.agent/scripts/cross_domain_engine.js +1883 -0
  20. package/.agent/scripts/engineering_memory.js +1313 -0
  21. package/.agent/scripts/integrity_manifest.js +1 -5
  22. package/.agent/scripts/judgment_engine.js +790 -0
  23. package/.agent/scripts/materiality_engine.js +251 -0
  24. package/.agent/scripts/outcome_engine.js +624 -0
  25. package/.agent/scripts/outcome_optimization_engine.js +1632 -0
  26. package/.agent/scripts/simulation_engine.js +1478 -0
  27. package/.agent/scripts/skill_intelligence.js +1371 -0
  28. package/.agent/scripts/validation_engine.js +236 -236
  29. package/.agent/scripts/verification_auditor.js +266 -0
  30. package/.agent/skill-intelligence/taxonomy/engineering-concepts.json +555 -0
  31. package/.agent/skill_topic_map.json +301 -341
  32. package/.agent/skills_inventory.json +4272 -6922
  33. package/.agent/workflows/arch.md +96 -80
  34. package/.agent/workflows/skill-intelligence.md +216 -0
  35. package/CONTRIBUTING.md +2 -2
  36. package/README.md +24 -24
  37. package/bin/adapter-install.js +1 -1
  38. package/package.json +8 -9
  39. package/plugins/core-plugin.json +1 -1
  40. package/plugins/gemini/extension.json +1 -1
  41. package/src/browser/index.js +2 -1
  42. package/src/browser/launcher.js +41 -1
  43. package/src/cli.js +3 -1
  44. package/src/commands/arch.js +261 -172
  45. package/src/commands/context.js +27 -8
  46. package/src/commands/learn.js +21 -6
  47. package/src/commands/memory.js +10 -1
  48. package/src/commands/native.js +12 -3
  49. package/src/commands/skill-intelligence.js +1165 -0
  50. package/src/commands/system1.js +105 -4
  51. package/src/context/ranker.js +337 -339
  52. package/src/evolution/engine.js +296 -295
  53. package/src/synthesis/claim_check_separator.js +294 -271
  54. package/src/system1/browser_intelligence.js +300 -0
  55. package/src/system1/constants.js +49 -0
  56. package/src/system1/decision_engine.js +498 -0
  57. package/src/system1/evidence_engine.js +602 -0
  58. package/src/system1/evolution_pipeline.js +581 -0
  59. package/src/system1/index.d.ts +114 -0
  60. package/src/system1/index.js +102 -0
  61. package/src/system1/reviewer_orchestrator.js +477 -0
  62. package/src/tui/banner.js +1 -1
  63. package/src/utils/fs.js +27 -0
@@ -0,0 +1,102 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * index.js — System-1 Capability Suite for Tribunal Kit
5
+ * =======================================================
6
+ * Unified export interface for all five System-1 capability layers:
7
+ *
8
+ * 1. Evidence Intelligence (`evidence_engine.js`)
9
+ * 2. Cross-Capability Decision Engine (`decision_engine.js`)
10
+ * 3. Adaptive Reviewer Orchestration (`reviewer_orchestrator.js`)
11
+ * 4. Self-Evolution Pipeline (`evolution_pipeline.js`)
12
+ * 5. Browser / Interaction Intelligence (`browser_intelligence.js`)
13
+ * + Laya Local ONNX Provider (`provider.js`)
14
+ */
15
+
16
+ const { System1Provider, getLayaDir, getConfigPath } = require('./provider');
17
+ const {
18
+ collectAndRankEvidence,
19
+ extractChangedSymbols,
20
+ extractBoundedSnippet,
21
+ redactSecrets,
22
+ TYPE_PRIORITY,
23
+ SECURITY_BOUNDARIES,
24
+ } = require('./evidence_engine');
25
+ const {
26
+ evaluateDecision,
27
+ resolveMonotonicImpactTier,
28
+ HIGH_RISK_PATTERNS,
29
+ HIGH_RISK_EXTENSIONS,
30
+ TIER_NAMES,
31
+ ROUTING_NAMES,
32
+ } = require('./decision_engine');
33
+ const {
34
+ orchestrateReviewers,
35
+ detectRequiredDomains,
36
+ REVIEWER_CATALOG,
37
+ } = require('./reviewer_orchestrator');
38
+ const {
39
+ createCandidateFromOutcome,
40
+ validateCandidateAgainstCorpus,
41
+ approveCandidate,
42
+ promoteCandidate,
43
+ rollbackCandidate,
44
+ saveCandidate,
45
+ loadCandidate,
46
+ loadAllCandidates,
47
+ getActiveEvolutionsPath,
48
+ acquireEvolutionLock,
49
+ releaseEvolutionLock,
50
+ writeFileSyncAtomic,
51
+ VALID_SOURCES,
52
+ CANDIDATE_STATES,
53
+ } = require('./evolution_pipeline');
54
+ const { evaluateBrowserRequirement, extractAffectedRoutes } = require('./browser_intelligence');
55
+
56
+ module.exports = {
57
+ // Provider
58
+ System1Provider,
59
+ getLayaDir,
60
+ getConfigPath,
61
+
62
+ // Capability 1: Evidence Intelligence
63
+ collectAndRankEvidence,
64
+ extractChangedSymbols,
65
+ extractBoundedSnippet,
66
+ redactSecrets,
67
+ TYPE_PRIORITY,
68
+ SECURITY_BOUNDARIES,
69
+
70
+ // Capability 2: Decision Engine
71
+ evaluateDecision,
72
+ resolveMonotonicImpactTier,
73
+ HIGH_RISK_PATTERNS,
74
+ HIGH_RISK_EXTENSIONS,
75
+ TIER_NAMES,
76
+ ROUTING_NAMES,
77
+
78
+ // Capability 3: Reviewer Orchestration
79
+ orchestrateReviewers,
80
+ detectRequiredDomains,
81
+ REVIEWER_CATALOG,
82
+
83
+ // Capability 4: Self-Evolution
84
+ createCandidateFromOutcome,
85
+ validateCandidateAgainstCorpus,
86
+ approveCandidate,
87
+ promoteCandidate,
88
+ rollbackCandidate,
89
+ saveCandidate,
90
+ loadCandidate,
91
+ loadAllCandidates,
92
+ getActiveEvolutionsPath,
93
+ acquireEvolutionLock,
94
+ releaseEvolutionLock,
95
+ writeFileSyncAtomic,
96
+ VALID_SOURCES,
97
+ CANDIDATE_STATES,
98
+
99
+ // Capability 5: Browser Intelligence
100
+ evaluateBrowserRequirement,
101
+ extractAffectedRoutes,
102
+ };
@@ -0,0 +1,477 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * reviewer_orchestrator.js — System-1 Capability 3: Adaptive Reviewer Orchestration
5
+ * ==================================================================================
6
+ * Replaces purely static reviewer selection with evidence-driven reviewer selection.
7
+ *
8
+ * Selects the smallest reviewer set capable of covering identified risks:
9
+ * score = required_coverage + specialization + historical_usefulness - overlap_penalty
10
+ *
11
+ * Guarantees:
12
+ * - Maximum unique review coverage with minimum reviewer count
13
+ * - Never optimizes away a reviewer solely for token savings when its domain is independently required
14
+ * - Every selected reviewer has: reason, risk covered, evidence supplied, expected contribution
15
+ * - Every rejected reviewer has: reason not selected
16
+ * - Deterministic, stable ordering
17
+ */
18
+
19
+ const path = require('path');
20
+ const { HIGH_RISK_PATTERNS } = require('./constants');
21
+
22
+ // Standard Reviewer Catalog with domains, priority, and overlap groups
23
+ const REVIEWER_CATALOG = [
24
+ {
25
+ name: 'logic-reviewer',
26
+ primary_domains: ['logic', 'all'],
27
+ secondary_domains: ['api'],
28
+ priority: 'critical',
29
+ overlap_group: 'logic',
30
+ expected_contribution:
31
+ 'Verification of state machines, API contract adherence, control flow integrity, and hallucination prevention.',
32
+ },
33
+ {
34
+ name: 'security-auditor',
35
+ primary_domains: ['security', 'auth'],
36
+ secondary_domains: ['backend', 'frontend'],
37
+ priority: 'critical',
38
+ overlap_group: 'security_general',
39
+ expected_contribution:
40
+ 'OWASP vulnerability scanning: injection, broken access control, token forgery, SSRF, and sensitive data leakage.',
41
+ },
42
+ {
43
+ name: 'sql-reviewer',
44
+ primary_domains: ['database', 'sql'],
45
+ secondary_domains: ['migration', 'performance'],
46
+ priority: 'critical',
47
+ overlap_group: 'database_sql',
48
+ expected_contribution:
49
+ 'Validation of SQL query parameters, schema migrations, table locks, transactional consistency, and missing indexes.',
50
+ },
51
+ {
52
+ name: 'schema-reviewer',
53
+ primary_domains: ['schema', 'validation'],
54
+ secondary_domains: ['backend', 'database'],
55
+ priority: 'high',
56
+ overlap_group: 'schema_validation',
57
+ expected_contribution:
58
+ 'Verification of Zod/Pydantic runtime schemas, DTO boundaries, and request payload validation.',
59
+ },
60
+ {
61
+ name: 'resilience-reviewer',
62
+ primary_domains: ['resilience', 'backend'],
63
+ secondary_domains: ['network'],
64
+ priority: 'high',
65
+ overlap_group: 'resilience_fault_tolerance',
66
+ expected_contribution:
67
+ 'Audit of timeout configurations, circuit breakers, retry policies, and unhandled promise rejections.',
68
+ },
69
+ {
70
+ name: 'dependency-reviewer',
71
+ primary_domains: ['dependency'],
72
+ secondary_domains: ['security', 'devops'],
73
+ priority: 'high',
74
+ overlap_group: 'dependency_management',
75
+ expected_contribution:
76
+ 'Detection of phantom/ghost dependencies, outdated packages, CVE advisories, and lockfile tampering.',
77
+ },
78
+ {
79
+ name: 'type-safety-reviewer',
80
+ primary_domains: ['type_safety', 'typescript'],
81
+ secondary_domains: ['frontend', 'backend'],
82
+ priority: 'high',
83
+ overlap_group: 'type_soundness',
84
+ expected_contribution:
85
+ 'Enforcement of TypeScript strictness, elimination of unsafe "any" casts, and generic constraint correctness.',
86
+ },
87
+ {
88
+ name: 'frontend-reviewer',
89
+ primary_domains: ['frontend', 'ui'],
90
+ secondary_domains: ['performance'],
91
+ priority: 'high',
92
+ overlap_group: 'frontend_architecture',
93
+ expected_contribution:
94
+ 'React/UI lifecycle review: hook dependency completeness, memoization balance, and re-render efficiency.',
95
+ },
96
+ {
97
+ name: 'accessibility-reviewer',
98
+ primary_domains: ['accessibility'],
99
+ secondary_domains: ['frontend', 'ui'],
100
+ priority: 'high',
101
+ overlap_group: 'accessibility_standards',
102
+ expected_contribution:
103
+ 'WCAG 2.2 compliance: semantic HTML elements, ARIA role verification, keyboard accessibility, and contrast ratios.',
104
+ },
105
+ {
106
+ name: 'pipeline-reviewer',
107
+ primary_domains: ['devops', 'ci_cd'],
108
+ secondary_domains: ['security'],
109
+ priority: 'high',
110
+ overlap_group: 'infrastructure_pipeline',
111
+ expected_contribution:
112
+ 'CI/CD pipeline hardening: workflow permissions, step injection defense, secret exposure prevention, and Docker security.',
113
+ },
114
+ {
115
+ name: 'performance-reviewer',
116
+ primary_domains: ['performance'],
117
+ secondary_domains: ['backend', 'frontend'],
118
+ priority: 'medium',
119
+ overlap_group: 'performance_profiling',
120
+ expected_contribution:
121
+ 'Resource efficiency analysis: asymptotic complexity, memory footprint, N+1 query patterns, and bundle weight.',
122
+ },
123
+ {
124
+ name: 'mobile-reviewer',
125
+ primary_domains: ['mobile'],
126
+ secondary_domains: ['frontend'],
127
+ priority: 'high',
128
+ overlap_group: 'mobile_native',
129
+ expected_contribution:
130
+ 'Mobile runtime evaluation: native gesture handlers, memory leaks, offline state, and navigation bridges.',
131
+ },
132
+ {
133
+ name: 'precedence-reviewer',
134
+ primary_domains: ['governance', 'rules'],
135
+ secondary_domains: ['all'],
136
+ priority: 'high',
137
+ overlap_group: 'governance_rules',
138
+ expected_contribution:
139
+ 'Enforcement of architectural rule priorities, agent boundary containment, and compliance with master directives.',
140
+ },
141
+ ];
142
+
143
+ /**
144
+ * Detect required risk domains based on files, diff, task, and evidence
145
+ */
146
+ function detectRequiredDomains({
147
+ files = [],
148
+ diff = '',
149
+ task = '',
150
+ evidence = [],
151
+ previousFindings = [],
152
+ }) {
153
+ const domains = new Set();
154
+ const fileList = (Array.isArray(files) ? files : typeof files === 'string' ? [files] : [])
155
+ .map(f =>
156
+ typeof f === 'string'
157
+ ? f
158
+ .replace(/[\u200B-\u200D\uFEFF]/g, '')
159
+ .trim()
160
+ .replace(/\\/g, '/')
161
+ : '',
162
+ )
163
+ .filter(Boolean);
164
+ const combined = `${task}\n${diff}\n${fileList.join('\n')}`;
165
+
166
+ // 1. File extension heuristics
167
+ for (const f of fileList) {
168
+ const ext = path.extname(f).toLowerCase();
169
+ if (['.sql', '.prisma'].includes(ext)) {
170
+ domains.add('database');
171
+ domains.add('sql');
172
+ }
173
+ if (['.ts', '.tsx'].includes(ext)) {
174
+ domains.add('type_safety');
175
+ }
176
+ if (
177
+ ['.jsx', '.tsx', '.vue', '.svelte', '.css', '.scss'].includes(ext) ||
178
+ f.includes('/components/')
179
+ ) {
180
+ domains.add('frontend');
181
+ }
182
+ if (f.includes('.github/') || f.includes('Dockerfile') || f.includes('docker-compose')) {
183
+ domains.add('devops');
184
+ domains.add('ci_cd');
185
+ }
186
+ if (f.endsWith('package.json') || f.endsWith('package-lock.json') || f.endsWith('Cargo.toml')) {
187
+ domains.add('dependency');
188
+ }
189
+ if (f.includes('/api/') || f.includes('/server/') || f.includes('/controllers/')) {
190
+ domains.add('backend');
191
+ domains.add('api');
192
+ }
193
+ if (f.includes('mobile/') || f.includes('ios/') || f.includes('android/')) {
194
+ domains.add('mobile');
195
+ }
196
+ }
197
+
198
+ // 2. Keyword & pattern heuristics
199
+ if (
200
+ HIGH_RISK_PATTERNS.test(combined) ||
201
+ combined.includes('token') ||
202
+ combined.includes('jwt') ||
203
+ combined.includes('auth')
204
+ ) {
205
+ domains.add('security');
206
+ domains.add('auth');
207
+ }
208
+ if (/\b(schema|zod|pydantic|validate|dto)\b/i.test(combined)) {
209
+ domains.add('schema');
210
+ }
211
+ if (/\b(sql|database|query|migration|table|alter table|create table)\b/i.test(combined)) {
212
+ domains.add('database');
213
+ }
214
+ if (/\b(retry|circuit-breaker|fallback|timeout|graceful|catch|exception)\b/i.test(combined)) {
215
+ domains.add('resilience');
216
+ }
217
+ if (/\b(a11y|aria|accessibility|wcag|contrast|screen-reader)\b/i.test(combined)) {
218
+ domains.add('accessibility');
219
+ }
220
+ if (/\b(perf|performance|latency|slow|throughput|bundle)\b/i.test(combined)) {
221
+ domains.add('performance');
222
+ }
223
+ if (/\b(npm|yarn|pnpm|dependency|package|cve|vulnerability)\b/i.test(combined)) {
224
+ domains.add('dependency');
225
+ }
226
+
227
+ // 3. Evidence signals
228
+ if (Array.isArray(evidence)) {
229
+ for (const e of evidence) {
230
+ if (e && typeof e === 'object') {
231
+ if (e.is_mandatory && e.type === 'security_boundary') {
232
+ domains.add('security');
233
+ }
234
+ if (
235
+ e.type === 'configuration' &&
236
+ typeof e.path === 'string' &&
237
+ e.path.includes('package')
238
+ ) {
239
+ domains.add('dependency');
240
+ }
241
+ }
242
+ }
243
+ }
244
+
245
+ // 4. Previous findings signals
246
+ if (Array.isArray(previousFindings)) {
247
+ for (const pf of previousFindings) {
248
+ if (pf && typeof pf === 'object' && typeof pf.category === 'string') {
249
+ domains.add(pf.category.toLowerCase());
250
+ }
251
+ }
252
+ }
253
+
254
+ // Default baseline: logic is always relevant when code changes
255
+ if (fileList.some(f => !/\.(md|txt)$/i.test(f))) {
256
+ domains.add('logic');
257
+ }
258
+
259
+ return Array.from(domains);
260
+ }
261
+
262
+ /**
263
+ * Adaptive Reviewer Orchestrator
264
+ * @param {Object} options
265
+ * @param {number} [options.tier] - Impact tier (0 to 3)
266
+ * @param {string[]} [options.files] - Changed files
267
+ * @param {string} [options.diff] - Diff
268
+ * @param {string} [options.task] - Task description
269
+ * @param {Array} [options.evidence] - Evidence items
270
+ * @param {Array} [options.previousFindings] - Previous findings
271
+ * @param {string[]} [options.forcedReviewers] - Reviewers that must be included
272
+ * @returns {Object} Orchestration payload with selected and rejected reviewers
273
+ */
274
+ function orchestrateReviewers(options = {}) {
275
+ const tier = typeof options.tier === 'number' ? options.tier : 1;
276
+ const files = options.files || [];
277
+ const diff = options.diff || '';
278
+ const task = options.task || '';
279
+ const evidence = Array.isArray(options.evidence) ? options.evidence : [];
280
+ const previousFindings = Array.isArray(options.previousFindings) ? options.previousFindings : [];
281
+ const forcedReviewers = new Set(options.forcedReviewers || []);
282
+
283
+ // Determine maximum reviewer capacity based on impact tier
284
+ // Tier 0 (Fast-Pass): 0 reviewers
285
+ // Tier 1 (Express Pass): 1 reviewer
286
+ // Tier 2 (Targeted Audit): 2-3 reviewers
287
+ // Tier 3 (Full Gauntlet): up to 8 reviewers
288
+ const capacityMap = { 0: 0, 1: 1, 2: 3, 3: 8 };
289
+ const maxCapacity = capacityMap[tier] ?? 1;
290
+
291
+ if (maxCapacity === 0) {
292
+ return {
293
+ selected: [],
294
+ rejected: REVIEWER_CATALOG.map(r => ({
295
+ reviewer: r.name,
296
+ reason: 'Fast-Pass (Tier 0) active: 0 reviewers required for low-risk change.',
297
+ })),
298
+ total_selected: 0,
299
+ coverage: {
300
+ domains_required: [],
301
+ domains_covered: [],
302
+ all_risks_covered: true,
303
+ },
304
+ };
305
+ }
306
+
307
+ const requiredDomains = detectRequiredDomains({ files, diff, task, evidence, previousFindings });
308
+ const coveredDomains = new Set();
309
+ const selectedReviewers = [];
310
+ const rejectedReviewers = [];
311
+ const usedOverlapGroups = new Set();
312
+
313
+ // Score candidate reviewers
314
+ const candidateScores = REVIEWER_CATALOG.map(reviewer => {
315
+ let score = 0.0;
316
+ const matchedEvidence = [];
317
+ const matchedReasons = [];
318
+
319
+ // 1. Required Coverage Score
320
+ const primaryMatches = reviewer.primary_domains.filter(d => requiredDomains.includes(d));
321
+ const secondaryMatches = reviewer.secondary_domains.filter(d => requiredDomains.includes(d));
322
+
323
+ if (primaryMatches.length > 0) {
324
+ score += 0.45 * primaryMatches.length;
325
+ matchedReasons.push(`directly covers primary risk domains: ${primaryMatches.join(', ')}`);
326
+ }
327
+ if (secondaryMatches.length > 0) {
328
+ score += 0.2 * secondaryMatches.length;
329
+ matchedReasons.push(`covers secondary risk domains: ${secondaryMatches.join(', ')}`);
330
+ }
331
+
332
+ // 2. Specialization & Priority Score
333
+ const hasSpecificDomainMatch = primaryMatches.some(d => d !== 'logic' && d !== 'all');
334
+ if (hasSpecificDomainMatch) {
335
+ score += 0.3; // Domain specialist bonus over general logic reviewer
336
+ matchedReasons.push(
337
+ `domain specialist for ${primaryMatches.filter(d => d !== 'logic' && d !== 'all').join(', ')}`,
338
+ );
339
+ }
340
+
341
+ if (reviewer.priority === 'critical' && primaryMatches.length > 0) {
342
+ score += 0.25;
343
+ matchedReasons.push('critical priority specialist for active risk domain');
344
+ }
345
+ if (reviewer.priority === 'high' && primaryMatches.length > 0) {
346
+ score += 0.15;
347
+ }
348
+
349
+ // 3. Evidence Match
350
+ if (Array.isArray(evidence)) {
351
+ for (const e of evidence) {
352
+ if (e && typeof e === 'object' && typeof e.type === 'string') {
353
+ if (
354
+ primaryMatches.some(
355
+ d =>
356
+ e.type.includes(d) ||
357
+ (Array.isArray(e.reasons) &&
358
+ e.reasons.some(r => typeof r === 'string' && r.includes(d))),
359
+ )
360
+ ) {
361
+ score += 0.1;
362
+ if (e.id) matchedEvidence.push(e.id);
363
+ }
364
+ }
365
+ }
366
+ }
367
+
368
+ // 4. Previous Findings Usefulness
369
+ const hasPriorIssues =
370
+ Array.isArray(previousFindings) &&
371
+ previousFindings.some(f => {
372
+ return (
373
+ f &&
374
+ typeof f === 'object' &&
375
+ typeof f.category === 'string' &&
376
+ primaryMatches.includes(f.category.toLowerCase())
377
+ );
378
+ });
379
+ if (hasPriorIssues) {
380
+ score += 0.15;
381
+ matchedReasons.push('prior audit findings detected in specialist domain');
382
+ }
383
+
384
+ // 5. Mandatory / Forced Reviewers
385
+ if (forcedReviewers.has(reviewer.name)) {
386
+ score += 1.0;
387
+ matchedReasons.push('explicitly forced by caller / governance contract');
388
+ }
389
+
390
+ return {
391
+ reviewer,
392
+ score: parseFloat(score.toFixed(2)),
393
+ primaryMatches,
394
+ matchedReasons,
395
+ matchedEvidence: Array.from(new Set(matchedEvidence)),
396
+ };
397
+ });
398
+
399
+ // Sort candidates by score DESC, then name ASC
400
+ candidateScores.sort((a, b) => {
401
+ if (Math.abs(b.score - a.score) > 0.001) return b.score - a.score;
402
+ return a.reviewer.name.localeCompare(b.reviewer.name);
403
+ });
404
+
405
+ // Selection Loop with Overlap Penalty
406
+ for (const candidate of candidateScores) {
407
+ const { reviewer, score, primaryMatches, matchedReasons, matchedEvidence } = candidate;
408
+
409
+ // Check if reviewer has any relevance
410
+ if (score <= 0.1 && !forcedReviewers.has(reviewer.name)) {
411
+ rejectedReviewers.push({
412
+ reviewer: reviewer.name,
413
+ reason: 'Zero domain overlap with active change set.',
414
+ });
415
+ continue;
416
+ }
417
+
418
+ // Check capacity limit
419
+ if (selectedReviewers.length >= maxCapacity) {
420
+ rejectedReviewers.push({
421
+ reviewer: reviewer.name,
422
+ reason: `Tier ${tier} capacity limit (${maxCapacity} reviewers) reached. Lower priority than selected peers.`,
423
+ });
424
+ continue;
425
+ }
426
+
427
+ // Check Overlap Group: If an overlap group is already present, apply penalty or skip
428
+ // Exception: In Tier 3 or when unique uncovered domains exist, overlap is tolerated
429
+ const hasOverlap = usedOverlapGroups.has(reviewer.overlap_group);
430
+ const bringsNewDomain = primaryMatches.some(d => !coveredDomains.has(d));
431
+
432
+ if (hasOverlap && !bringsNewDomain && !forcedReviewers.has(reviewer.name)) {
433
+ rejectedReviewers.push({
434
+ reviewer: reviewer.name,
435
+ reason: `Substantial overlap with already selected peer in group "${reviewer.overlap_group}".`,
436
+ });
437
+ continue;
438
+ }
439
+
440
+ // Select this reviewer
441
+ selectedReviewers.push({
442
+ reviewer: reviewer.name,
443
+ reason: matchedReasons.join(' | ') || 'Specialist alignment with detected change scope',
444
+ risk_covered: primaryMatches.join(', ') || 'general',
445
+ evidence_supplied: matchedEvidence,
446
+ expected_contribution: reviewer.expected_contribution,
447
+ score,
448
+ });
449
+
450
+ primaryMatches.forEach(d => coveredDomains.add(d));
451
+ usedOverlapGroups.add(reviewer.overlap_group);
452
+ }
453
+
454
+ // Safety Verification: Ensure critical domains are covered
455
+ const criticalUncovered = requiredDomains.filter(
456
+ d => ['security', 'database', 'auth'].includes(d) && !coveredDomains.has(d),
457
+ );
458
+ const allRisksCovered = criticalUncovered.length === 0;
459
+
460
+ return {
461
+ selected: selectedReviewers,
462
+ rejected: rejectedReviewers,
463
+ total_selected: selectedReviewers.length,
464
+ coverage: {
465
+ domains_required: requiredDomains,
466
+ domains_covered: Array.from(coveredDomains),
467
+ all_risks_covered: allRisksCovered,
468
+ uncovered_critical: criticalUncovered,
469
+ },
470
+ };
471
+ }
472
+
473
+ module.exports = {
474
+ orchestrateReviewers,
475
+ detectRequiredDomains,
476
+ REVIEWER_CATALOG,
477
+ };
package/src/tui/banner.js CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  const { isTTY, hasColor, hasTrueColor, RGB, GLYPHS, color, bold, getColumns } = require('./theme');
9
9
 
10
- function renderBanner(version = '9.2.6', quiet = false) {
10
+ function renderBanner(version = '9.2.7', quiet = false) {
11
11
  if (quiet) return;
12
12
  if (!isTTY && !hasColor) {
13
13
  console.error(`TRIBUNAL-KIT v${version} — Anti-Hallucination Governance Layer`);
package/src/utils/fs.js CHANGED
@@ -8,6 +8,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
8
8
  exports.copyDir = copyDir;
9
9
  exports.countDir = countDir;
10
10
  exports.isSelfInstall = isSelfInstall;
11
+ exports.writeFileSyncAtomic = writeFileSyncAtomic;
11
12
  const fs_1 = __importDefault(require('fs'));
12
13
  const path_1 = __importDefault(require('path'));
13
14
  const logger_1 = require('./logger');
@@ -101,3 +102,29 @@ function isSelfInstall(targetDir, pkgName, kitRoot) {
101
102
  }
102
103
  return false;
103
104
  }
105
+
106
+ /**
107
+ * Atomically writes data to a file by writing to a temporary file in the same directory
108
+ * and renaming it into place. Handles cross-platform and Windows locking cleanly.
109
+ */
110
+ function writeFileSyncAtomic(filePath, data, encoding = 'utf8') {
111
+ const dir = path_1.default.dirname(filePath);
112
+ if (!fs_1.default.existsSync(dir)) fs_1.default.mkdirSync(dir, { recursive: true });
113
+ const tmpPath = path_1.default.join(
114
+ dir,
115
+ `.${path_1.default.basename(filePath)}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 6)}.tmp`,
116
+ );
117
+ fs_1.default.writeFileSync(tmpPath, data, encoding);
118
+ try {
119
+ fs_1.default.renameSync(tmpPath, filePath);
120
+ } catch (err) {
121
+ if (process.platform === 'win32' && (err.code === 'EEXIST' || err.code === 'EPERM')) {
122
+ try {
123
+ fs_1.default.unlinkSync(filePath);
124
+ } catch (_) {}
125
+ fs_1.default.renameSync(tmpPath, filePath);
126
+ } else {
127
+ throw err;
128
+ }
129
+ }
130
+ }