@harness-engineering/cli 2.4.5 → 2.5.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.
Files changed (59) hide show
  1. package/dist/agents-md-KAD3L2NO.js +13 -0
  2. package/dist/analyzer-VY6DJVOU-NI56JRFK.js +26 -0
  3. package/dist/{architecture-NX7FWQD3.js → architecture-OC7TFCFF.js} +7 -4
  4. package/dist/{assess-project-PLY6ZWMW.js → assess-project-ZGMRPTS3.js} +1 -1
  5. package/dist/bin/harness-mcp.js +20 -17
  6. package/dist/bin/harness.js +38 -35
  7. package/dist/{check-phase-gate-WFIEJKMN.js → check-phase-gate-PD5MVEZT.js} +8 -5
  8. package/dist/{chunk-O63AAPIZ.js → chunk-2LPUIBVH.js} +75 -1
  9. package/dist/{chunk-7TRTU7JL.js → chunk-2RNGLYOG.js} +2 -2
  10. package/dist/{chunk-73ACYXIS.js → chunk-4CWFVEVV.js} +1 -1
  11. package/dist/{chunk-4H2KIQ3I.js → chunk-57TS3UGN.js} +2 -2
  12. package/dist/{chunk-A5GXGRW6.js → chunk-65MJPWFN.js} +6 -6
  13. package/dist/{chunk-Z6PF2YXB.js → chunk-6SRKI77C.js} +3 -3
  14. package/dist/{chunk-LJTQVJEP.js → chunk-7DOGGXQU.js} +2 -2
  15. package/dist/{chunk-ZEKY6PQQ.js → chunk-A3EBWI7U.js} +2 -2
  16. package/dist/{chunk-TC4GQBIK.js → chunk-DOUS4ULX.js} +6 -6
  17. package/dist/{chunk-HCTXLKAH.js → chunk-ELMV6QU2.js} +2 -2
  18. package/dist/{chunk-KEF624FQ.js → chunk-HIZXUWWC.js} +8 -6
  19. package/dist/{chunk-YL2N4OZQ.js → chunk-IGBQIXPS.js} +2 -2
  20. package/dist/chunk-IWRYCUDO.js +3337 -0
  21. package/dist/{chunk-NSLFLGUB.js → chunk-IXKGMPMT.js} +2 -2
  22. package/dist/{chunk-M5TJOV3A.js → chunk-JE5GQVCQ.js} +2 -2
  23. package/dist/{chunk-65M5R3X6.js → chunk-KQ6TDRPS.js} +3927 -7322
  24. package/dist/{chunk-DUK6C7I7.js → chunk-LT244Y6E.js} +490 -300
  25. package/dist/{chunk-OPDIMKUZ.js → chunk-N6VWCISQ.js} +2 -2
  26. package/dist/{chunk-3XFFGAX4.js → chunk-NOOPJD5R.js} +3 -3
  27. package/dist/chunk-QCLOIUMX.js +395 -0
  28. package/dist/{chunk-FPUNXFJG.js → chunk-TCSNO7YW.js} +2 -2
  29. package/dist/{chunk-4PO2QAXO.js → chunk-UCL3UZIC.js} +779 -274
  30. package/dist/{chunk-DUCVDDZO.js → chunk-UF7BKRH4.js} +4 -4
  31. package/dist/chunk-XARGEOJV.js +21 -0
  32. package/dist/{chunk-72TZ2GZR.js → chunk-XIW24BJY.js} +7 -7
  33. package/dist/{chunk-PGY57ABC.js → chunk-XSI3RDH6.js} +7 -7
  34. package/dist/ci-workflow-WAG4TOV6.js +13 -0
  35. package/dist/{dist-O733ZU6I.js → dist-HVJUGPSY.js} +23 -1
  36. package/dist/{dist-SVZHSOLP.js → dist-TKHVYUWZ.js} +79 -48
  37. package/dist/{docs-7LXCR62T.js → docs-4WPBYSCF.js} +8 -5
  38. package/dist/engine-5BXDQT5T.js +13 -0
  39. package/dist/{entropy-LMOXWMR4.js → entropy-7FIUFACI.js} +6 -3
  40. package/dist/{feedback-CLBC3IMP.js → feedback-ER2HRTFD.js} +1 -1
  41. package/dist/{generate-agent-definitions-5FDIGEVZ.js → generate-agent-definitions-5PV4O3BD.js} +8 -5
  42. package/dist/index.js +49 -46
  43. package/dist/loader-6RTEYN5Q.js +15 -0
  44. package/dist/{mcp-4W45E6OH.js → mcp-QWSDEYMN.js} +20 -17
  45. package/dist/{performance-WZQIUHLR.js → performance-AZJAT35R.js} +8 -5
  46. package/dist/{review-pipeline-YPRUHKM7.js → review-pipeline-4VF73V4V.js} +6 -3
  47. package/dist/runtime-SAZGLILX.js +14 -0
  48. package/dist/{security-AZNLX3N6.js → security-ZWRABJNE.js} +1 -1
  49. package/dist/timeline-manager-FPYKJRHR-VVX7CSGW.js +24 -0
  50. package/dist/{tool-tiers-QVWKAZX4.js → tool-tiers-LTQNNAFU.js} +7 -2
  51. package/dist/{validate-S7G6H7F4.js → validate-AFJVI4OX.js} +7 -4
  52. package/dist/validate-cross-check-7PO7CBVT.js +13 -0
  53. package/package.json +6 -6
  54. package/dist/agents-md-KJVGWF2S.js +0 -10
  55. package/dist/ci-workflow-XDIKOFSN.js +0 -10
  56. package/dist/engine-MMQF2ZW5.js +0 -10
  57. package/dist/loader-WTWR2CWT.js +0 -12
  58. package/dist/runtime-WC2IWI2X.js +0 -11
  59. package/dist/validate-cross-check-Z73SCHXZ.js +0 -10
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  init_dist
3
- } from "./chunk-65M5R3X6.js";
3
+ } from "./chunk-KQ6TDRPS.js";
4
4
  import {
5
5
  Ok
6
- } from "./chunk-O63AAPIZ.js";
6
+ } from "./chunk-2LPUIBVH.js";
7
7
 
8
8
  // src/commands/validate-cross-check.ts
9
9
  init_dist();
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveProjectConfig
3
- } from "./chunk-LJTQVJEP.js";
3
+ } from "./chunk-7DOGGXQU.js";
4
4
  import {
5
5
  sanitizePath
6
6
  } from "./chunk-W6Y7ZW3Y.js";
@@ -49,7 +49,7 @@ async function handleValidateProject(input) {
49
49
  checks.config = "pass";
50
50
  const config = configResult.value;
51
51
  try {
52
- const core = await import("./dist-SVZHSOLP.js");
52
+ const core = await import("./dist-TKHVYUWZ.js");
53
53
  if (typeof core.validateFileStructure === "function" && Array.isArray(config.conventions)) {
54
54
  const conventions = config.conventions;
55
55
  const structureResult = await core.validateFileStructure(projectPath, conventions);
@@ -68,7 +68,7 @@ async function handleValidateProject(input) {
68
68
  } catch {
69
69
  }
70
70
  try {
71
- const core = await import("./dist-SVZHSOLP.js");
71
+ const core = await import("./dist-TKHVYUWZ.js");
72
72
  if (typeof core.validateAgentsMap === "function") {
73
73
  const agentsMapPath = path.join(projectPath, "AGENTS.md");
74
74
  const agentsResult = await core.validateAgentsMap(agentsMapPath);
@@ -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
+ };
@@ -27,7 +27,7 @@ var runSecurityScanDefinition = {
27
27
  };
28
28
  async function handleRunSecurityScan(input) {
29
29
  try {
30
- const core = await import("./dist-SVZHSOLP.js");
30
+ const core = await import("./dist-TKHVYUWZ.js");
31
31
  const projectRoot = sanitizePath(input.path);
32
32
  let configData = {};
33
33
  try {
@@ -114,7 +114,7 @@ var getSecurityTrendsDefinition = {
114
114
  };
115
115
  async function handleGetSecurityTrends(input) {
116
116
  try {
117
- const core = await import("./dist-SVZHSOLP.js");
117
+ const core = await import("./dist-TKHVYUWZ.js");
118
118
  const projectRoot = sanitizePath(input.path);
119
119
  const manager = new core.SecurityTimelineManager(projectRoot);
120
120
  const trendOptions = {};