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
|
@@ -1,260 +1,303 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* architecture_diff.js — Tribunal Semantic Architecture Change Diff
|
|
4
|
-
* ═════════════════════════════════════════════════════════════════════════════
|
|
5
|
-
* Goes beyond superficial visual diffs (added/removed/moved boxes) to detect
|
|
6
|
-
* true semantic architectural impact between Base and Head architectures.
|
|
7
|
-
*
|
|
8
|
-
* Detects:
|
|
9
|
-
* - Entity & Relationship Additions / Deletions
|
|
10
|
-
* - Trust Boundaries Crossed (e.g. public access to isolated datastore)
|
|
11
|
-
* - Blast Radius Expansion (increased coupling/centrality)
|
|
12
|
-
* - Failure Resilience Regressions (timeouts/retries/fallbacks removed)
|
|
13
|
-
* - New External Third-Party Dependencies
|
|
14
|
-
* - Direct Database Couplings Introduced
|
|
15
|
-
* - Critical Path Shifts & Single Points of Failure (SPOFs)
|
|
16
|
-
*
|
|
17
|
-
* Zero external dependencies.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
'use strict';
|
|
21
|
-
|
|
22
|
-
const fs = require('fs');
|
|
23
|
-
const {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
console.log(
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* architecture_diff.js — Tribunal Semantic Architecture Change Diff
|
|
4
|
+
* ═════════════════════════════════════════════════════════════════════════════
|
|
5
|
+
* Goes beyond superficial visual diffs (added/removed/moved boxes) to detect
|
|
6
|
+
* true semantic architectural impact between Base and Head architectures.
|
|
7
|
+
*
|
|
8
|
+
* Detects:
|
|
9
|
+
* - Entity & Relationship Additions / Deletions
|
|
10
|
+
* - Trust Boundaries Crossed (e.g. public access to isolated datastore)
|
|
11
|
+
* - Blast Radius Expansion (increased coupling/centrality)
|
|
12
|
+
* - Failure Resilience Regressions (timeouts/retries/fallbacks removed)
|
|
13
|
+
* - New External Third-Party Dependencies
|
|
14
|
+
* - Direct Database Couplings Introduced
|
|
15
|
+
* - Critical Path Shifts & Single Points of Failure (SPOFs)
|
|
16
|
+
*
|
|
17
|
+
* Zero external dependencies.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
'use strict';
|
|
21
|
+
|
|
22
|
+
const fs = require('fs');
|
|
23
|
+
const {
|
|
24
|
+
GREEN,
|
|
25
|
+
YELLOW,
|
|
26
|
+
CYAN,
|
|
27
|
+
RED,
|
|
28
|
+
BOLD,
|
|
29
|
+
RESET,
|
|
30
|
+
BOX,
|
|
31
|
+
banner,
|
|
32
|
+
timer,
|
|
33
|
+
formatMs,
|
|
34
|
+
} = require('./_colors');
|
|
35
|
+
const { BlastRadiusEngine } = require('./blast_radius_engine');
|
|
36
|
+
|
|
37
|
+
class ArchitectureDiffer {
|
|
38
|
+
constructor(baseModel, headModel) {
|
|
39
|
+
this.base = baseModel;
|
|
40
|
+
this.head = headModel;
|
|
41
|
+
|
|
42
|
+
this.baseEntities = new Map((baseModel.entities || []).map(e => [e.id, e]));
|
|
43
|
+
this.headEntities = new Map((headModel.entities || []).map(e => [e.id, e]));
|
|
44
|
+
|
|
45
|
+
this.baseRelations = new Map(
|
|
46
|
+
(baseModel.relationships || []).map(r => [r.id || `${r.sourceId}->${r.targetId}`, r]),
|
|
47
|
+
);
|
|
48
|
+
this.headRelations = new Map(
|
|
49
|
+
(headModel.relationships || []).map(r => [r.id || `${r.sourceId}->${r.targetId}`, r]),
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
compare() {
|
|
54
|
+
const diff = {
|
|
55
|
+
timestamp: new Date().toISOString(),
|
|
56
|
+
summary: {
|
|
57
|
+
entitiesAdded: 0,
|
|
58
|
+
entitiesRemoved: 0,
|
|
59
|
+
entitiesModified: 0,
|
|
60
|
+
relationshipsAdded: 0,
|
|
61
|
+
relationshipsRemoved: 0,
|
|
62
|
+
relationshipsModified: 0,
|
|
63
|
+
architecturalImpactScore: 0.0, // 0.0 to 1.0
|
|
64
|
+
riskLevel: 'LOW',
|
|
65
|
+
},
|
|
66
|
+
entityChanges: [],
|
|
67
|
+
relationshipChanges: [],
|
|
68
|
+
semanticImpacts: [],
|
|
69
|
+
trustBoundaryViolations: [],
|
|
70
|
+
resilienceRegressions: [],
|
|
71
|
+
blastRadiusShifts: [],
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// 1. Entity Diff
|
|
75
|
+
for (const [id, headEntity] of this.headEntities.entries()) {
|
|
76
|
+
if (!this.baseEntities.has(id)) {
|
|
77
|
+
diff.summary.entitiesAdded++;
|
|
78
|
+
diff.entityChanges.push({ status: 'added', entity: headEntity });
|
|
79
|
+
if (headEntity.kind === 'external_api') {
|
|
80
|
+
diff.semanticImpacts.push({
|
|
81
|
+
type: 'NEW_EXTERNAL_DEPENDENCY',
|
|
82
|
+
severity: 'HIGH',
|
|
83
|
+
message: `New external SaaS/Cloud dependency introduced: ${headEntity.name}`,
|
|
84
|
+
entityId: id,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
const baseEntity = this.baseEntities.get(id);
|
|
89
|
+
const modified = [];
|
|
90
|
+
if (baseEntity.trustZone !== headEntity.trustZone) modified.push('trustZone');
|
|
91
|
+
if (baseEntity.role !== headEntity.role) modified.push('role');
|
|
92
|
+
if (modified.length > 0) {
|
|
93
|
+
diff.summary.entitiesModified++;
|
|
94
|
+
diff.entityChanges.push({
|
|
95
|
+
status: 'modified',
|
|
96
|
+
id,
|
|
97
|
+
fields: modified,
|
|
98
|
+
base: baseEntity,
|
|
99
|
+
head: headEntity,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
if (
|
|
103
|
+
baseEntity.trustZone === 'isolated_datastore' &&
|
|
104
|
+
headEntity.trustZone !== 'isolated_datastore'
|
|
105
|
+
) {
|
|
106
|
+
diff.trustBoundaryViolations.push({
|
|
107
|
+
severity: 'CRITICAL',
|
|
108
|
+
message: `Entity ${headEntity.name} was moved out of isolated_datastore to ${headEntity.trustZone}!`,
|
|
109
|
+
entityId: id,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
for (const [id, baseEntity] of this.baseEntities.entries()) {
|
|
117
|
+
if (!this.headEntities.has(id)) {
|
|
118
|
+
diff.summary.entitiesRemoved++;
|
|
119
|
+
diff.entityChanges.push({ status: 'removed', entity: baseEntity });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 2. Relationship Diff
|
|
124
|
+
for (const [id, headRel] of this.headRelations.entries()) {
|
|
125
|
+
if (!this.baseRelations.has(id)) {
|
|
126
|
+
diff.summary.relationshipsAdded++;
|
|
127
|
+
diff.relationshipChanges.push({ status: 'added', relationship: headRel });
|
|
128
|
+
|
|
129
|
+
// Check if new relationship bypasses trust zones
|
|
130
|
+
const sourceEntity = this.headEntities.get(headRel.sourceId);
|
|
131
|
+
const targetEntity = this.headEntities.get(headRel.targetId);
|
|
132
|
+
|
|
133
|
+
if (sourceEntity && targetEntity) {
|
|
134
|
+
if (
|
|
135
|
+
(sourceEntity.trustZone === 'public_untrusted' ||
|
|
136
|
+
sourceEntity.trustZone === 'dmz_gateway') &&
|
|
137
|
+
targetEntity.trustZone === 'isolated_datastore'
|
|
138
|
+
) {
|
|
139
|
+
diff.trustBoundaryViolations.push({
|
|
140
|
+
severity: 'CRITICAL',
|
|
141
|
+
message: `Direct edge added from ${sourceEntity.name} (${sourceEntity.trustZone}) to ${targetEntity.name} (${targetEntity.trustZone})! Bypasses internal service layer.`,
|
|
142
|
+
sourceId: headRel.sourceId,
|
|
143
|
+
targetId: headRel.targetId,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
const baseRel = this.baseRelations.get(id);
|
|
149
|
+
// Check for resilience regressions (e.g. timeout or retry removed)
|
|
150
|
+
if (baseRel.failureMode && headRel.failureMode) {
|
|
151
|
+
if (baseRel.failureMode.hasTimeout && !headRel.failureMode.hasTimeout) {
|
|
152
|
+
diff.resilienceRegressions.push({
|
|
153
|
+
severity: 'HIGH',
|
|
154
|
+
message: `Timeout protection removed on relationship ${headRel.sourceId} -> ${headRel.targetId}`,
|
|
155
|
+
relationshipId: id,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
if (baseRel.failureMode.hasCircuitBreaker && !headRel.failureMode.hasCircuitBreaker) {
|
|
159
|
+
diff.resilienceRegressions.push({
|
|
160
|
+
severity: 'HIGH',
|
|
161
|
+
message: `Circuit breaker protection removed on relationship ${headRel.sourceId} -> ${headRel.targetId}`,
|
|
162
|
+
relationshipId: id,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
for (const [id, baseRel] of this.baseRelations.entries()) {
|
|
170
|
+
if (!this.headRelations.has(id)) {
|
|
171
|
+
diff.summary.relationshipsRemoved++;
|
|
172
|
+
diff.relationshipChanges.push({ status: 'removed', relationship: baseRel });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// 3. Blast Radius Shift Analysis
|
|
177
|
+
const baseBlast = new BlastRadiusEngine(this.base);
|
|
178
|
+
const headBlast = new BlastRadiusEngine(this.head);
|
|
179
|
+
|
|
180
|
+
for (const [id, headEntity] of this.headEntities.entries()) {
|
|
181
|
+
if (this.baseEntities.has(id) && headEntity.kind === 'module') {
|
|
182
|
+
const baseRes = baseBlast.computeBlastRadius(id);
|
|
183
|
+
const headRes = headBlast.computeBlastRadius(id);
|
|
184
|
+
|
|
185
|
+
if (baseRes.found && headRes.found) {
|
|
186
|
+
const baseTrans = baseRes.metrics.transitiveDependentsCount;
|
|
187
|
+
const headTrans = headRes.metrics.transitiveDependentsCount;
|
|
188
|
+
if (headTrans > baseTrans + 3 && headTrans >= baseTrans * 1.3) {
|
|
189
|
+
diff.blastRadiusShifts.push({
|
|
190
|
+
entityId: id,
|
|
191
|
+
name: headEntity.name,
|
|
192
|
+
baseTransitive: baseTrans,
|
|
193
|
+
headTransitive: headTrans,
|
|
194
|
+
expansionPct: Math.round(((headTrans - baseTrans) / (baseTrans || 1)) * 100),
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// 4. Calculate Overall Architectural Impact Score (0.0 to 1.0)
|
|
202
|
+
let score = 0.0;
|
|
203
|
+
score += diff.trustBoundaryViolations.length * 0.4;
|
|
204
|
+
score += diff.resilienceRegressions.length * 0.25;
|
|
205
|
+
score += diff.semanticImpacts.length * 0.15;
|
|
206
|
+
score += diff.blastRadiusShifts.length * 0.1;
|
|
207
|
+
score += Math.min(0.2, (diff.summary.entitiesAdded + diff.summary.relationshipsAdded) * 0.02);
|
|
208
|
+
|
|
209
|
+
diff.summary.architecturalImpactScore = Math.min(1.0, Math.round(score * 100) / 100);
|
|
210
|
+
|
|
211
|
+
if (diff.summary.architecturalImpactScore >= 0.7 || diff.trustBoundaryViolations.length > 0) {
|
|
212
|
+
diff.summary.riskLevel = 'CRITICAL';
|
|
213
|
+
} else if (diff.summary.architecturalImpactScore >= 0.4) {
|
|
214
|
+
diff.summary.riskLevel = 'HIGH';
|
|
215
|
+
} else if (diff.summary.architecturalImpactScore >= 0.2) {
|
|
216
|
+
diff.summary.riskLevel = 'MEDIUM';
|
|
217
|
+
} else {
|
|
218
|
+
diff.summary.riskLevel = 'LOW';
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return diff;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ── Standalone CLI ────────────────────────────────────────────────────────────
|
|
226
|
+
if (require.main === module) {
|
|
227
|
+
const t = timer();
|
|
228
|
+
const baseFile = process.argv[2];
|
|
229
|
+
const headFile = process.argv[3];
|
|
230
|
+
|
|
231
|
+
console.log(banner('Tribunal Semantic Architecture Change Differ'));
|
|
232
|
+
|
|
233
|
+
if (!baseFile || !headFile) {
|
|
234
|
+
console.error(
|
|
235
|
+
` ${YELLOW}Usage:${RESET} node architecture_diff.js <base-model.json> <head-model.json>\n`,
|
|
236
|
+
);
|
|
237
|
+
process.exit(1);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (!fs.existsSync(baseFile) || !fs.existsSync(headFile)) {
|
|
241
|
+
console.error(` ${RED}✖ One or both model files do not exist.${RESET}`);
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const baseModel = JSON.parse(fs.readFileSync(baseFile, 'utf8'));
|
|
246
|
+
const headModel = JSON.parse(fs.readFileSync(headFile, 'utf8'));
|
|
247
|
+
|
|
248
|
+
const differ = new ArchitectureDiffer(baseModel, headModel);
|
|
249
|
+
const diff = differ.compare();
|
|
250
|
+
|
|
251
|
+
const riskColors = { CRITICAL: RED, HIGH: YELLOW, MEDIUM: CYAN, LOW: GREEN };
|
|
252
|
+
const rColor = riskColors[diff.summary.riskLevel] || GREEN;
|
|
253
|
+
|
|
254
|
+
console.log(
|
|
255
|
+
` Architectural Risk: ${rColor}${BOLD}${diff.summary.riskLevel} (${diff.summary.architecturalImpactScore})${RESET}`,
|
|
256
|
+
);
|
|
257
|
+
console.log(
|
|
258
|
+
` Entities Changed: +${diff.summary.entitiesAdded} / -${diff.summary.entitiesRemoved} / ~${diff.summary.entitiesModified}`,
|
|
259
|
+
);
|
|
260
|
+
console.log(
|
|
261
|
+
` Relationships Changed: +${diff.summary.relationshipsAdded} / -${diff.summary.relationshipsRemoved}`,
|
|
262
|
+
);
|
|
263
|
+
console.log(
|
|
264
|
+
` Trust Violations: ${diff.trustBoundaryViolations.length > 0 ? RED : GREEN}${diff.trustBoundaryViolations.length}${RESET}`,
|
|
265
|
+
);
|
|
266
|
+
console.log(
|
|
267
|
+
` Resilience Regressions: ${diff.resilienceRegressions.length > 0 ? YELLOW : GREEN}${diff.resilienceRegressions.length}${RESET}`,
|
|
268
|
+
);
|
|
269
|
+
console.log(
|
|
270
|
+
` Blast Radius Shifts: ${diff.blastRadiusShifts.length > 0 ? YELLOW : GREEN}${diff.blastRadiusShifts.length}${RESET}`,
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
if (diff.trustBoundaryViolations.length > 0) {
|
|
274
|
+
console.log(`\n ${RED}${BOLD}Trust Boundary Violations:${RESET}`);
|
|
275
|
+
for (const v of diff.trustBoundaryViolations) {
|
|
276
|
+
console.log(` ${RED}${BOX.cross_mark}${RESET} ${v.message}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (diff.resilienceRegressions.length > 0) {
|
|
281
|
+
console.log(`\n ${YELLOW}${BOLD}Resilience Regressions:${RESET}`);
|
|
282
|
+
for (const r of diff.resilienceRegressions) {
|
|
283
|
+
console.log(` ${YELLOW}!${RESET} ${r.message}`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (diff.blastRadiusShifts.length > 0) {
|
|
288
|
+
console.log(`\n ${CYAN}${BOLD}Blast Radius Expansions:${RESET}`);
|
|
289
|
+
for (const b of diff.blastRadiusShifts) {
|
|
290
|
+
console.log(
|
|
291
|
+
` ${CYAN}▸${RESET} ${b.name}: ${b.baseTransitive} -> ${b.headTransitive} dependents (+${b.expansionPct}%)`,
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
console.log(
|
|
297
|
+
`\n ${GREEN}${BOX.check} Semantic Architecture Diff Complete${RESET} in ${formatMs(t())}\n`,
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
module.exports = {
|
|
302
|
+
ArchitectureDiffer,
|
|
303
|
+
};
|