@harness-engineering/cli 2.4.5 → 2.6.0
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/dist/agents-md-2JUQ4FE2.js +13 -0
- package/dist/analyzer-VY6DJVOU-4AHIJLNS.js +26 -0
- package/dist/{architecture-NX7FWQD3.js → architecture-CXAVNB5X.js} +7 -4
- package/dist/{assess-project-PLY6ZWMW.js → assess-project-M626SSPN.js} +1 -1
- package/dist/bin/harness-mcp.js +20 -17
- package/dist/bin/harness.js +38 -35
- package/dist/{check-phase-gate-WFIEJKMN.js → check-phase-gate-XMU6LLUQ.js} +8 -5
- package/dist/{chunk-OPDIMKUZ.js → chunk-24KCOJJG.js} +2 -2
- package/dist/{chunk-72TZ2GZR.js → chunk-43M3RLFQ.js} +7 -7
- package/dist/{chunk-7TRTU7JL.js → chunk-5JNSFYZU.js} +2 -2
- package/dist/{chunk-PGY57ABC.js → chunk-6AX6R3LM.js} +7 -7
- package/dist/{chunk-TC4GQBIK.js → chunk-GWE5LL3R.js} +6 -6
- package/dist/{chunk-LJTQVJEP.js → chunk-GWF2OILZ.js} +2 -2
- package/dist/{chunk-FPUNXFJG.js → chunk-HFOB2MPQ.js} +2 -2
- package/dist/{chunk-Z6PF2YXB.js → chunk-HMW3VKUF.js} +3 -3
- package/dist/{chunk-NSLFLGUB.js → chunk-HYTRDAHV.js} +2 -2
- package/dist/{chunk-3XFFGAX4.js → chunk-I6K43QQS.js} +3 -3
- package/dist/{chunk-YL2N4OZQ.js → chunk-JFZOWO7D.js} +2 -2
- package/dist/{chunk-4H2KIQ3I.js → chunk-K246XQ2L.js} +2 -2
- package/dist/{chunk-ZEKY6PQQ.js → chunk-L5BCZ5XS.js} +2 -2
- package/dist/{chunk-4PO2QAXO.js → chunk-NX6A24DS.js} +2153 -985
- package/dist/{chunk-A5GXGRW6.js → chunk-OA6SWTU4.js} +6 -6
- package/dist/chunk-OH3NXXUY.js +383 -0
- package/dist/{chunk-DUK6C7I7.js → chunk-ORNMAYHB.js} +611 -300
- package/dist/{chunk-73ACYXIS.js → chunk-PFZEADQM.js} +1 -1
- package/dist/{chunk-M5TJOV3A.js → chunk-Q6ZR2L6Q.js} +2 -2
- package/dist/chunk-QCLOIUMX.js +395 -0
- package/dist/{chunk-DUCVDDZO.js → chunk-QOKMDDBJ.js} +4 -4
- package/dist/chunk-SZEFU6XC.js +3337 -0
- package/dist/{chunk-KEF624FQ.js → chunk-VTTNIZJL.js} +27 -6
- package/dist/chunk-XARGEOJV.js +21 -0
- package/dist/{chunk-HCTXLKAH.js → chunk-YP7I25SL.js} +2 -2
- package/dist/{chunk-65M5R3X6.js → chunk-YYRQCQPZ.js} +4204 -7347
- package/dist/ci-workflow-3JNDZQYD.js +13 -0
- package/dist/dist-E3SAAHCM.js +93 -0
- package/dist/{dist-SVZHSOLP.js → dist-OHDQBTSO.js} +119 -48
- package/dist/{docs-7LXCR62T.js → docs-5RYMDHN3.js} +8 -5
- package/dist/engine-KZ3PPUYE.js +13 -0
- package/dist/{entropy-LMOXWMR4.js → entropy-DQTAPSSE.js} +6 -3
- package/dist/{feedback-CLBC3IMP.js → feedback-WH6XPQJS.js} +1 -1
- package/dist/{generate-agent-definitions-5FDIGEVZ.js → generate-agent-definitions-SZA4QIHN.js} +8 -5
- package/dist/index.d.ts +47 -0
- package/dist/index.js +49 -46
- package/dist/loader-BNKGM23C.js +15 -0
- package/dist/{mcp-4W45E6OH.js → mcp-GZH4EYGD.js} +20 -17
- package/dist/{performance-WZQIUHLR.js → performance-54TMJOEU.js} +8 -5
- package/dist/{review-pipeline-YPRUHKM7.js → review-pipeline-OTDDVPNY.js} +6 -3
- package/dist/runtime-W5THSNAL.js +14 -0
- package/dist/{security-AZNLX3N6.js → security-27HW7CYT.js} +1 -1
- package/dist/timeline-manager-FPYKJRHR-VVX7CSGW.js +24 -0
- package/dist/{tool-tiers-QVWKAZX4.js → tool-tiers-B7JC2XC3.js} +9 -2
- package/dist/{validate-S7G6H7F4.js → validate-QRVCD4GP.js} +7 -4
- package/dist/validate-cross-check-BUAGBAPO.js +13 -0
- package/package.json +6 -6
- package/dist/agents-md-KJVGWF2S.js +0 -10
- package/dist/chunk-O63AAPIZ.js +0 -190
- package/dist/ci-workflow-XDIKOFSN.js +0 -10
- package/dist/dist-O733ZU6I.js +0 -49
- package/dist/engine-MMQF2ZW5.js +0 -10
- package/dist/loader-WTWR2CWT.js +0 -12
- package/dist/runtime-WC2IWI2X.js +0 -11
- package/dist/validate-cross-check-Z73SCHXZ.js +0 -10
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
init_dist,
|
|
6
6
|
paginate
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YYRQCQPZ.js";
|
|
8
8
|
|
|
9
9
|
// src/mcp/tools/review-pipeline.ts
|
|
10
10
|
init_dist();
|
|
@@ -79,7 +79,7 @@ var runCodeReviewDefinition = {
|
|
|
79
79
|
};
|
|
80
80
|
async function handleRunCodeReview(input) {
|
|
81
81
|
try {
|
|
82
|
-
const { parseDiff, runReviewPipeline } = await import("./dist-
|
|
82
|
+
const { parseDiff, runReviewPipeline } = await import("./dist-OHDQBTSO.js");
|
|
83
83
|
const parseResult = parseDiff(input.diff);
|
|
84
84
|
if (!parseResult.ok) {
|
|
85
85
|
return {
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__esm
|
|
3
|
+
} from "./chunk-KFQGP6VL.js";
|
|
4
|
+
|
|
5
|
+
// ../core/dist/chunk-IIEDD47I.mjs
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
var ArchMetricCategorySchema, ViolationSchema, MetricResultSchema, CategoryBaselineSchema, ArchBaselineSchema, CategoryRegressionSchema, ArchDiffResultSchema, ThresholdConfigSchema, ArchConfigSchema, ConstraintRuleSchema, ViolationSnapshotSchema, ViolationHistorySchema, EmergenceConfidenceSchema, EmergentConstraintSuggestionSchema, EmergenceResultSchema;
|
|
8
|
+
var init_chunk_IIEDD47I = __esm({
|
|
9
|
+
"../core/dist/chunk-IIEDD47I.mjs"() {
|
|
10
|
+
"use strict";
|
|
11
|
+
ArchMetricCategorySchema = z.enum([
|
|
12
|
+
"circular-deps",
|
|
13
|
+
"layer-violations",
|
|
14
|
+
"complexity",
|
|
15
|
+
"coupling",
|
|
16
|
+
"forbidden-imports",
|
|
17
|
+
"module-size",
|
|
18
|
+
"dependency-depth"
|
|
19
|
+
]);
|
|
20
|
+
ViolationSchema = z.object({
|
|
21
|
+
id: z.string(),
|
|
22
|
+
// stable hash: sha256(relativePath + ':' + category + ':' + normalizedDetail)
|
|
23
|
+
file: z.string(),
|
|
24
|
+
// relative to project root
|
|
25
|
+
category: ArchMetricCategorySchema.optional(),
|
|
26
|
+
// context for baseline reporting
|
|
27
|
+
detail: z.string(),
|
|
28
|
+
// human-readable description
|
|
29
|
+
severity: z.enum(["error", "warning"])
|
|
30
|
+
});
|
|
31
|
+
MetricResultSchema = z.object({
|
|
32
|
+
category: ArchMetricCategorySchema,
|
|
33
|
+
scope: z.string(),
|
|
34
|
+
// e.g., 'project', 'src/services', 'src/api/routes.ts'
|
|
35
|
+
value: z.number(),
|
|
36
|
+
// numeric metric (violation count, complexity score, etc.)
|
|
37
|
+
violations: z.array(ViolationSchema),
|
|
38
|
+
metadata: z.record(z.unknown()).optional()
|
|
39
|
+
});
|
|
40
|
+
CategoryBaselineSchema = z.object({
|
|
41
|
+
value: z.number(),
|
|
42
|
+
// aggregate metric value at baseline time
|
|
43
|
+
violationIds: z.array(z.string())
|
|
44
|
+
// stable IDs of known violations (the allowlist)
|
|
45
|
+
});
|
|
46
|
+
ArchBaselineSchema = z.object({
|
|
47
|
+
version: z.literal(1),
|
|
48
|
+
updatedAt: z.string().datetime(),
|
|
49
|
+
// ISO 8601
|
|
50
|
+
updatedFrom: z.string(),
|
|
51
|
+
// commit hash
|
|
52
|
+
metrics: z.record(ArchMetricCategorySchema, CategoryBaselineSchema)
|
|
53
|
+
});
|
|
54
|
+
CategoryRegressionSchema = z.object({
|
|
55
|
+
category: ArchMetricCategorySchema,
|
|
56
|
+
baselineValue: z.number(),
|
|
57
|
+
currentValue: z.number(),
|
|
58
|
+
delta: z.number()
|
|
59
|
+
});
|
|
60
|
+
ArchDiffResultSchema = z.object({
|
|
61
|
+
passed: z.boolean(),
|
|
62
|
+
newViolations: z.array(ViolationSchema),
|
|
63
|
+
// in current but not in baseline -> FAIL
|
|
64
|
+
resolvedViolations: z.array(z.string()),
|
|
65
|
+
// in baseline but not in current -> celebrate
|
|
66
|
+
preExisting: z.array(z.string()),
|
|
67
|
+
// in both -> allowed, tracked
|
|
68
|
+
regressions: z.array(CategoryRegressionSchema)
|
|
69
|
+
// aggregate value exceeded baseline
|
|
70
|
+
});
|
|
71
|
+
ThresholdConfigSchema = z.record(
|
|
72
|
+
ArchMetricCategorySchema,
|
|
73
|
+
z.union([z.number(), z.record(z.string(), z.number())])
|
|
74
|
+
);
|
|
75
|
+
ArchConfigSchema = z.object({
|
|
76
|
+
enabled: z.boolean().default(true),
|
|
77
|
+
baselinePath: z.string().default(".harness/arch/baselines.json"),
|
|
78
|
+
thresholds: ThresholdConfigSchema.default({}),
|
|
79
|
+
modules: z.record(z.string(), ThresholdConfigSchema).default({})
|
|
80
|
+
});
|
|
81
|
+
ConstraintRuleSchema = z.object({
|
|
82
|
+
id: z.string(),
|
|
83
|
+
// stable hash: sha256(category + ':' + scope + ':' + description)
|
|
84
|
+
category: ArchMetricCategorySchema,
|
|
85
|
+
description: z.string(),
|
|
86
|
+
// e.g., "Layer 'services' must not import from 'ui'"
|
|
87
|
+
scope: z.string(),
|
|
88
|
+
// e.g., 'src/services/', 'project'
|
|
89
|
+
targets: z.array(z.string()).optional()
|
|
90
|
+
// forward-compat for governs edges
|
|
91
|
+
});
|
|
92
|
+
ViolationSnapshotSchema = z.object({
|
|
93
|
+
timestamp: z.string().datetime(),
|
|
94
|
+
violations: z.array(ViolationSchema)
|
|
95
|
+
});
|
|
96
|
+
ViolationHistorySchema = z.object({
|
|
97
|
+
version: z.literal(1),
|
|
98
|
+
snapshots: z.array(ViolationSnapshotSchema)
|
|
99
|
+
});
|
|
100
|
+
EmergenceConfidenceSchema = z.enum(["low", "medium", "high"]);
|
|
101
|
+
EmergentConstraintSuggestionSchema = z.object({
|
|
102
|
+
suggestedRule: ConstraintRuleSchema,
|
|
103
|
+
confidence: EmergenceConfidenceSchema,
|
|
104
|
+
occurrences: z.number(),
|
|
105
|
+
uniqueFiles: z.number(),
|
|
106
|
+
pattern: z.string(),
|
|
107
|
+
sampleViolations: z.array(ViolationSchema),
|
|
108
|
+
rationale: z.string()
|
|
109
|
+
});
|
|
110
|
+
EmergenceResultSchema = z.object({
|
|
111
|
+
suggestions: z.array(EmergentConstraintSuggestionSchema),
|
|
112
|
+
totalViolationsAnalyzed: z.number(),
|
|
113
|
+
windowWeeks: z.number(),
|
|
114
|
+
minOccurrences: z.number()
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// ../core/dist/chunk-XKLVJIPL.mjs
|
|
120
|
+
import { readFileSync, writeFileSync, renameSync, mkdirSync, existsSync } from "fs";
|
|
121
|
+
import { randomBytes } from "crypto";
|
|
122
|
+
import { join, dirname } from "path";
|
|
123
|
+
import { z as z2 } from "zod";
|
|
124
|
+
var CategorySnapshotSchema, TimelineSnapshotSchema, TimelineFileSchema, TrendLineSchema, TrendResultSchema, DEFAULT_STABILITY_THRESHOLDS, ALL_CATEGORIES, TimelineManager;
|
|
125
|
+
var init_chunk_XKLVJIPL = __esm({
|
|
126
|
+
"../core/dist/chunk-XKLVJIPL.mjs"() {
|
|
127
|
+
"use strict";
|
|
128
|
+
init_chunk_IIEDD47I();
|
|
129
|
+
CategorySnapshotSchema = z2.object({
|
|
130
|
+
/** Aggregate metric value (e.g., violation count, avg complexity) */
|
|
131
|
+
value: z2.number(),
|
|
132
|
+
/** Count of violations in this category */
|
|
133
|
+
violationCount: z2.number()
|
|
134
|
+
});
|
|
135
|
+
TimelineSnapshotSchema = z2.object({
|
|
136
|
+
/** ISO 8601 timestamp of capture */
|
|
137
|
+
capturedAt: z2.string().datetime(),
|
|
138
|
+
/** Git commit hash at capture time */
|
|
139
|
+
commitHash: z2.string(),
|
|
140
|
+
/** Composite stability score (0-100, higher is healthier) */
|
|
141
|
+
stabilityScore: z2.number().min(0).max(100),
|
|
142
|
+
/** Per-category metric aggregates */
|
|
143
|
+
metrics: z2.record(ArchMetricCategorySchema, CategorySnapshotSchema)
|
|
144
|
+
});
|
|
145
|
+
TimelineFileSchema = z2.object({
|
|
146
|
+
version: z2.literal(1),
|
|
147
|
+
snapshots: z2.array(TimelineSnapshotSchema)
|
|
148
|
+
});
|
|
149
|
+
TrendLineSchema = z2.object({
|
|
150
|
+
/** Current value */
|
|
151
|
+
current: z2.number(),
|
|
152
|
+
/** Previous value (from comparison snapshot) */
|
|
153
|
+
previous: z2.number(),
|
|
154
|
+
/** Absolute delta (current - previous) */
|
|
155
|
+
delta: z2.number(),
|
|
156
|
+
/** Direction indicator */
|
|
157
|
+
direction: z2.enum(["improving", "stable", "declining"])
|
|
158
|
+
});
|
|
159
|
+
TrendResultSchema = z2.object({
|
|
160
|
+
/** Overall stability trend */
|
|
161
|
+
stability: TrendLineSchema,
|
|
162
|
+
/** Per-category trends */
|
|
163
|
+
categories: z2.record(ArchMetricCategorySchema, TrendLineSchema),
|
|
164
|
+
/** Number of snapshots analyzed */
|
|
165
|
+
snapshotCount: z2.number(),
|
|
166
|
+
/** Time range covered */
|
|
167
|
+
from: z2.string(),
|
|
168
|
+
to: z2.string()
|
|
169
|
+
});
|
|
170
|
+
DEFAULT_STABILITY_THRESHOLDS = {
|
|
171
|
+
"circular-deps": 5,
|
|
172
|
+
"layer-violations": 10,
|
|
173
|
+
complexity: 100,
|
|
174
|
+
coupling: 2,
|
|
175
|
+
"forbidden-imports": 5,
|
|
176
|
+
"module-size": 10,
|
|
177
|
+
"dependency-depth": 10
|
|
178
|
+
};
|
|
179
|
+
ALL_CATEGORIES = ArchMetricCategorySchema.options;
|
|
180
|
+
TimelineManager = class {
|
|
181
|
+
timelinePath;
|
|
182
|
+
constructor(rootDir) {
|
|
183
|
+
this.timelinePath = join(rootDir, ".harness", "arch", "timeline.json");
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Load timeline from disk.
|
|
187
|
+
* Returns empty TimelineFile if file does not exist or is invalid.
|
|
188
|
+
*/
|
|
189
|
+
load() {
|
|
190
|
+
if (!existsSync(this.timelinePath)) {
|
|
191
|
+
return { version: 1, snapshots: [] };
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
const raw = readFileSync(this.timelinePath, "utf-8");
|
|
195
|
+
const data = JSON.parse(raw);
|
|
196
|
+
const parsed = TimelineFileSchema.safeParse(data);
|
|
197
|
+
if (!parsed.success) {
|
|
198
|
+
console.error(
|
|
199
|
+
`Timeline validation failed for ${this.timelinePath}:`,
|
|
200
|
+
parsed.error.format()
|
|
201
|
+
);
|
|
202
|
+
return { version: 1, snapshots: [] };
|
|
203
|
+
}
|
|
204
|
+
return parsed.data;
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error(`Error loading timeline from ${this.timelinePath}:`, error);
|
|
207
|
+
return { version: 1, snapshots: [] };
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Save timeline to disk using atomic write (temp file + rename).
|
|
212
|
+
* Creates parent directories if they do not exist.
|
|
213
|
+
*/
|
|
214
|
+
save(timeline) {
|
|
215
|
+
const dir = dirname(this.timelinePath);
|
|
216
|
+
if (!existsSync(dir)) {
|
|
217
|
+
mkdirSync(dir, { recursive: true });
|
|
218
|
+
}
|
|
219
|
+
const tmp = this.timelinePath + "." + randomBytes(4).toString("hex") + ".tmp";
|
|
220
|
+
writeFileSync(tmp, JSON.stringify(timeline, null, 2));
|
|
221
|
+
renameSync(tmp, this.timelinePath);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Capture a new snapshot from current metric results.
|
|
225
|
+
* Aggregates MetricResult[] by category, computes stability score,
|
|
226
|
+
* appends to timeline (or replaces if same commitHash), and saves.
|
|
227
|
+
*/
|
|
228
|
+
capture(results, commitHash) {
|
|
229
|
+
const metrics = this.aggregateByCategory(results);
|
|
230
|
+
const stabilityScore = this.computeStabilityScore(metrics);
|
|
231
|
+
const snapshot = {
|
|
232
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
233
|
+
commitHash,
|
|
234
|
+
stabilityScore,
|
|
235
|
+
metrics
|
|
236
|
+
};
|
|
237
|
+
const timeline = this.load();
|
|
238
|
+
const lastIndex = timeline.snapshots.length - 1;
|
|
239
|
+
if (lastIndex >= 0 && timeline.snapshots[lastIndex].commitHash === commitHash) {
|
|
240
|
+
timeline.snapshots[lastIndex] = snapshot;
|
|
241
|
+
} else {
|
|
242
|
+
timeline.snapshots.push(snapshot);
|
|
243
|
+
}
|
|
244
|
+
this.save(timeline);
|
|
245
|
+
return snapshot;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Compute trends between snapshots over a window.
|
|
249
|
+
* @param options.last - Number of recent snapshots to analyze (default: 10)
|
|
250
|
+
* @param options.since - ISO date string to filter snapshots from
|
|
251
|
+
*/
|
|
252
|
+
trends(options) {
|
|
253
|
+
const timeline = this.load();
|
|
254
|
+
let snapshots = timeline.snapshots;
|
|
255
|
+
if (options?.since) {
|
|
256
|
+
const sinceDate = new Date(options.since);
|
|
257
|
+
snapshots = snapshots.filter((s) => new Date(s.capturedAt) >= sinceDate);
|
|
258
|
+
}
|
|
259
|
+
if (options?.last && snapshots.length > options.last) {
|
|
260
|
+
snapshots = snapshots.slice(-options.last);
|
|
261
|
+
}
|
|
262
|
+
if (snapshots.length === 0) {
|
|
263
|
+
return this.emptyTrendResult();
|
|
264
|
+
}
|
|
265
|
+
if (snapshots.length === 1) {
|
|
266
|
+
const only = snapshots[0];
|
|
267
|
+
const m = only.metrics;
|
|
268
|
+
return {
|
|
269
|
+
stability: this.buildTrendLine(only.stabilityScore, only.stabilityScore, true),
|
|
270
|
+
categories: this.buildCategoryTrends(m, m),
|
|
271
|
+
snapshotCount: 1,
|
|
272
|
+
from: only.capturedAt,
|
|
273
|
+
to: only.capturedAt
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
const first = snapshots[0];
|
|
277
|
+
const last = snapshots[snapshots.length - 1];
|
|
278
|
+
return {
|
|
279
|
+
stability: this.buildTrendLine(last.stabilityScore, first.stabilityScore, true),
|
|
280
|
+
categories: this.buildCategoryTrends(
|
|
281
|
+
last.metrics,
|
|
282
|
+
first.metrics
|
|
283
|
+
),
|
|
284
|
+
snapshotCount: snapshots.length,
|
|
285
|
+
from: first.capturedAt,
|
|
286
|
+
to: last.capturedAt
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Compute composite stability score from category metrics.
|
|
291
|
+
* Equal weight across all categories. Score is 0-100 (higher = healthier).
|
|
292
|
+
* health = max(0, 1 - (value / threshold)) per category.
|
|
293
|
+
*/
|
|
294
|
+
computeStabilityScore(metrics, thresholds = DEFAULT_STABILITY_THRESHOLDS) {
|
|
295
|
+
const healthScores = [];
|
|
296
|
+
for (const category of ALL_CATEGORIES) {
|
|
297
|
+
const snapshot = metrics[category];
|
|
298
|
+
if (!snapshot) {
|
|
299
|
+
healthScores.push(1);
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
const threshold = thresholds[category] ?? 10;
|
|
303
|
+
const health = Math.max(0, 1 - snapshot.value / threshold);
|
|
304
|
+
healthScores.push(health);
|
|
305
|
+
}
|
|
306
|
+
const mean = healthScores.reduce((sum, h) => sum + h, 0) / healthScores.length;
|
|
307
|
+
return Math.round(mean * 100);
|
|
308
|
+
}
|
|
309
|
+
// --- Private helpers ---
|
|
310
|
+
aggregateByCategory(results) {
|
|
311
|
+
const metrics = {};
|
|
312
|
+
for (const result of results) {
|
|
313
|
+
const existing = metrics[result.category];
|
|
314
|
+
if (existing) {
|
|
315
|
+
existing.value += result.value;
|
|
316
|
+
existing.violationCount += result.violations.length;
|
|
317
|
+
} else {
|
|
318
|
+
metrics[result.category] = {
|
|
319
|
+
value: result.value,
|
|
320
|
+
violationCount: result.violations.length
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
for (const category of ALL_CATEGORIES) {
|
|
325
|
+
if (!metrics[category]) {
|
|
326
|
+
metrics[category] = { value: 0, violationCount: 0 };
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return metrics;
|
|
330
|
+
}
|
|
331
|
+
buildTrendLine(current, previous, isStabilityScore) {
|
|
332
|
+
const delta = current - previous;
|
|
333
|
+
let direction;
|
|
334
|
+
if (Math.abs(delta) < 2) {
|
|
335
|
+
direction = "stable";
|
|
336
|
+
} else if (isStabilityScore) {
|
|
337
|
+
direction = delta > 0 ? "improving" : "declining";
|
|
338
|
+
} else {
|
|
339
|
+
direction = delta < 0 ? "improving" : "declining";
|
|
340
|
+
}
|
|
341
|
+
return { current, previous, delta, direction };
|
|
342
|
+
}
|
|
343
|
+
buildCategoryTrends(currentMetrics, previousMetrics) {
|
|
344
|
+
const trends = {};
|
|
345
|
+
for (const category of ALL_CATEGORIES) {
|
|
346
|
+
const current = currentMetrics[category]?.value ?? 0;
|
|
347
|
+
const previous = previousMetrics[category]?.value ?? 0;
|
|
348
|
+
trends[category] = this.buildTrendLine(current, previous, false);
|
|
349
|
+
}
|
|
350
|
+
return trends;
|
|
351
|
+
}
|
|
352
|
+
emptyTrendResult() {
|
|
353
|
+
const zeroLine = { current: 0, previous: 0, delta: 0, direction: "stable" };
|
|
354
|
+
const categories = {};
|
|
355
|
+
for (const category of ALL_CATEGORIES) {
|
|
356
|
+
categories[category] = { ...zeroLine };
|
|
357
|
+
}
|
|
358
|
+
return {
|
|
359
|
+
stability: { ...zeroLine },
|
|
360
|
+
categories,
|
|
361
|
+
snapshotCount: 0,
|
|
362
|
+
from: "",
|
|
363
|
+
to: ""
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
export {
|
|
371
|
+
ArchMetricCategorySchema,
|
|
372
|
+
ViolationSchema,
|
|
373
|
+
MetricResultSchema,
|
|
374
|
+
CategoryBaselineSchema,
|
|
375
|
+
ArchBaselineSchema,
|
|
376
|
+
CategoryRegressionSchema,
|
|
377
|
+
ArchDiffResultSchema,
|
|
378
|
+
ThresholdConfigSchema,
|
|
379
|
+
ArchConfigSchema,
|
|
380
|
+
ConstraintRuleSchema,
|
|
381
|
+
ViolationSnapshotSchema,
|
|
382
|
+
ViolationHistorySchema,
|
|
383
|
+
EmergenceConfidenceSchema,
|
|
384
|
+
EmergentConstraintSuggestionSchema,
|
|
385
|
+
EmergenceResultSchema,
|
|
386
|
+
init_chunk_IIEDD47I,
|
|
387
|
+
CategorySnapshotSchema,
|
|
388
|
+
TimelineSnapshotSchema,
|
|
389
|
+
TimelineFileSchema,
|
|
390
|
+
TrendLineSchema,
|
|
391
|
+
TrendResultSchema,
|
|
392
|
+
DEFAULT_STABILITY_THRESHOLDS,
|
|
393
|
+
TimelineManager,
|
|
394
|
+
init_chunk_XKLVJIPL
|
|
395
|
+
};
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
} from "./chunk-W6Y7ZW3Y.js";
|
|
7
7
|
import {
|
|
8
8
|
init_dist
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-YYRQCQPZ.js";
|
|
10
10
|
import {
|
|
11
11
|
Ok
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-OH3NXXUY.js";
|
|
13
13
|
|
|
14
14
|
// src/mcp/tools/entropy.ts
|
|
15
15
|
init_dist();
|
|
@@ -127,7 +127,7 @@ function buildSummaryResponse(report) {
|
|
|
127
127
|
}
|
|
128
128
|
async function handleDetectEntropy(input) {
|
|
129
129
|
try {
|
|
130
|
-
const { EntropyAnalyzer } = await import("./dist-
|
|
130
|
+
const { EntropyAnalyzer } = await import("./dist-OHDQBTSO.js");
|
|
131
131
|
const typeFilter = input.type ?? "all";
|
|
132
132
|
const analyzer = new EntropyAnalyzer({
|
|
133
133
|
rootDir: sanitizePath(input.path),
|
|
@@ -146,7 +146,7 @@ async function handleDetectEntropy(input) {
|
|
|
146
146
|
return resultToMcpResponse(result);
|
|
147
147
|
}
|
|
148
148
|
if (!result.ok) return resultToMcpResponse(result);
|
|
149
|
-
const { createFixes, applyFixes, generateSuggestions } = await import("./dist-
|
|
149
|
+
const { createFixes, applyFixes, generateSuggestions } = await import("./dist-OHDQBTSO.js");
|
|
150
150
|
const report = result.value;
|
|
151
151
|
const deadCode = report.deadCode;
|
|
152
152
|
const fixTypesConfig = input.fixTypes ? { fixTypes: input.fixTypes } : void 0;
|