@harness-engineering/core 0.26.0 → 0.26.2

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/index.js CHANGED
@@ -55,6 +55,7 @@ __export(index_exports, {
55
55
  CINotifier: () => CINotifier,
56
56
  COMPLIANCE_DESCRIPTOR: () => COMPLIANCE_DESCRIPTOR,
57
57
  CORROBORATED_AGREEMENT: () => CORROBORATED_AGREEMENT,
58
+ CacheMetricsRecorder: () => CacheMetricsRecorder,
58
59
  CategoryBaselineSchema: () => CategoryBaselineSchema,
59
60
  CategoryForecastSchema: () => CategoryForecastSchema,
60
61
  CategoryRegressionSchema: () => CategoryRegressionSchema,
@@ -119,6 +120,7 @@ __export(index_exports, {
119
120
  NoOpExecutor: () => NoOpExecutor,
120
121
  NoOpSink: () => NoOpSink,
121
122
  NoOpTelemetryAdapter: () => NoOpTelemetryAdapter,
123
+ OTLPExporter: () => OTLPExporter,
122
124
  OpenAICacheAdapter: () => OpenAICacheAdapter,
123
125
  PII_FIELD_DENYLIST: () => PII_FIELD_DENYLIST,
124
126
  PII_LINE_RE: () => PII_LINE_RE,
@@ -157,6 +159,7 @@ __export(index_exports, {
157
159
  SharableSecurityRulesSchema: () => SharableSecurityRulesSchema,
158
160
  SkillEventSchema: () => SkillEventSchema,
159
161
  SolutionDocFrontmatterSchema: () => SolutionDocFrontmatterSchema,
162
+ SpanKind: () => SpanKind,
160
163
  SpecImpactEstimateSchema: () => SpecImpactEstimateSchema,
161
164
  SpecImpactEstimator: () => SpecImpactEstimator,
162
165
  SpecImpactSignalsSchema: () => SpecImpactSignalsSchema,
@@ -325,6 +328,7 @@ __export(index_exports, {
325
328
  goRules: () => goRules,
326
329
  injectionRules: () => injectionRules,
327
330
  insecureDefaultsRules: () => insecureDefaultsRules,
331
+ invalidateCheckState: () => invalidateCheckState,
328
332
  isBadPort: () => isBadPort,
329
333
  isDuplicateFinding: () => isDuplicateFinding,
330
334
  isRegression: () => isRegression,
@@ -5645,7 +5649,10 @@ function findDeadFiles(snapshot, reachability) {
5645
5649
  return deadFiles;
5646
5650
  }
5647
5651
  function isIdentifierUsedInAST(ast, identifier, skipImportDeclaration = true) {
5648
- const astString = JSON.stringify(ast);
5652
+ const astString = JSON.stringify(
5653
+ ast,
5654
+ (_key, value) => typeof value === "bigint" ? value.toString() : value
5655
+ );
5649
5656
  const identifierPattern = new RegExp(`"name"\\s*:\\s*"${identifier}"`, "g");
5650
5657
  const matches = astString.match(identifierPattern);
5651
5658
  if (!matches) return false;
@@ -20193,6 +20200,12 @@ function shouldRunCheck(state, intervalMs) {
20193
20200
  if (state === null) return true;
20194
20201
  return state.lastCheckTime + intervalMs <= Date.now();
20195
20202
  }
20203
+ function invalidateCheckState() {
20204
+ try {
20205
+ fs36.unlinkSync(getStatePath());
20206
+ } catch {
20207
+ }
20208
+ }
20196
20209
  function readCheckState() {
20197
20210
  try {
20198
20211
  const raw = fs36.readFileSync(getStatePath(), "utf-8");
@@ -21390,7 +21403,7 @@ function resolveConsent(projectRoot, config) {
21390
21403
  }
21391
21404
 
21392
21405
  // src/version.ts
21393
- var VERSION = "0.23.3";
21406
+ var VERSION = "0.25.0";
21394
21407
 
21395
21408
  // src/telemetry/collector.ts
21396
21409
  function mapOutcome(outcome) {
@@ -21451,6 +21464,221 @@ async function send(events, apiKey) {
21451
21464
  }
21452
21465
  }
21453
21466
 
21467
+ // src/telemetry/cache-metrics.ts
21468
+ var DEFAULT_CAPACITY = 1e3;
21469
+ var CacheMetricsRecorder = class {
21470
+ capacity;
21471
+ now;
21472
+ buffer = [];
21473
+ windowStartedAt = 0;
21474
+ constructor(opts = {}) {
21475
+ this.capacity = opts.capacity ?? DEFAULT_CAPACITY;
21476
+ this.now = opts.now ?? Date.now;
21477
+ }
21478
+ /**
21479
+ * Append a single cache observation. Hot-path: O(1) amortized, no
21480
+ * allocations beyond the sample object itself.
21481
+ */
21482
+ record(backendId, hit, tokensCreated, tokensRead) {
21483
+ if (this.windowStartedAt === 0) this.windowStartedAt = this.now();
21484
+ if (this.buffer.length >= this.capacity) this.buffer.shift();
21485
+ this.buffer.push({ backendId, hit, tokensCreated, tokensRead });
21486
+ }
21487
+ /** Aggregate the current window into a `PromptCacheStats` snapshot. */
21488
+ getStats() {
21489
+ let hits = 0;
21490
+ let misses = 0;
21491
+ const byBackend = {};
21492
+ for (const s of this.buffer) {
21493
+ if (s.hit) hits++;
21494
+ else misses++;
21495
+ const slot = byBackend[s.backendId] ?? { hits: 0, misses: 0 };
21496
+ if (s.hit) slot.hits++;
21497
+ else slot.misses++;
21498
+ byBackend[s.backendId] = slot;
21499
+ }
21500
+ const totalRequests = hits + misses;
21501
+ const hitRate = totalRequests === 0 ? 0 : hits / totalRequests;
21502
+ return {
21503
+ totalRequests,
21504
+ hits,
21505
+ misses,
21506
+ hitRate,
21507
+ byBackend,
21508
+ windowStartedAt: this.windowStartedAt
21509
+ };
21510
+ }
21511
+ /** Clear the buffer and reset the window-start marker. */
21512
+ reset() {
21513
+ this.buffer.length = 0;
21514
+ this.windowStartedAt = 0;
21515
+ }
21516
+ };
21517
+
21518
+ // src/telemetry/exporter/otlp-http.ts
21519
+ var RETRY_BACKOFFS_MS = [1e3, 2e3, 4e3];
21520
+ function toUnixNanoString(ns) {
21521
+ return ns.toString(10);
21522
+ }
21523
+ function attributesToOTLP(attrs) {
21524
+ const out = [];
21525
+ for (const [key, value] of Object.entries(attrs)) {
21526
+ if (typeof value === "string") {
21527
+ out.push({ key, value: { stringValue: value } });
21528
+ } else if (typeof value === "boolean") {
21529
+ out.push({ key, value: { boolValue: value } });
21530
+ } else if (typeof value === "number") {
21531
+ if (Number.isInteger(value)) {
21532
+ out.push({ key, value: { intValue: String(value) } });
21533
+ } else {
21534
+ out.push({ key, value: { doubleValue: value } });
21535
+ }
21536
+ }
21537
+ }
21538
+ return out;
21539
+ }
21540
+ var OTLPExporter = class {
21541
+ endpoint;
21542
+ enabled;
21543
+ headers;
21544
+ flushIntervalMs;
21545
+ batchSize;
21546
+ fetchImpl;
21547
+ warn;
21548
+ buffer = [];
21549
+ timer = null;
21550
+ inFlightFlushes = /* @__PURE__ */ new Set();
21551
+ constructor(opts) {
21552
+ this.endpoint = opts.endpoint;
21553
+ this.enabled = opts.enabled !== false;
21554
+ this.headers = { "Content-Type": "application/json", ...opts.headers ?? {} };
21555
+ this.flushIntervalMs = opts.flushIntervalMs ?? 2e3;
21556
+ this.batchSize = opts.batchSize ?? 64;
21557
+ this.fetchImpl = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
21558
+ this.warn = opts.warn ?? ((...a) => console.warn(...a));
21559
+ }
21560
+ /**
21561
+ * O(1) buffer push. When `enabled === false` this is a no-op. If the
21562
+ * buffer reaches `batchSize`, a flush is triggered without awaiting.
21563
+ */
21564
+ push(span) {
21565
+ if (!this.enabled) return;
21566
+ this.buffer.push(span);
21567
+ if (this.buffer.length >= this.batchSize) {
21568
+ void this.flush();
21569
+ }
21570
+ }
21571
+ /** Start the periodic flush timer. Idempotent. */
21572
+ start() {
21573
+ if (!this.enabled || this.timer !== null) return;
21574
+ this.timer = setInterval(() => {
21575
+ void this.flush();
21576
+ }, this.flushIntervalMs);
21577
+ if (typeof this.timer.unref === "function") {
21578
+ this.timer.unref();
21579
+ }
21580
+ }
21581
+ /** Flush any pending spans and stop the timer. Awaits all in-flight flushes. */
21582
+ async stop() {
21583
+ if (this.timer !== null) {
21584
+ clearInterval(this.timer);
21585
+ this.timer = null;
21586
+ }
21587
+ void this.flush();
21588
+ while (this.inFlightFlushes.size > 0) {
21589
+ await Promise.all([...this.inFlightFlushes]);
21590
+ }
21591
+ }
21592
+ /**
21593
+ * Synchronously claim the current buffer and POST it to `/v1/traces`.
21594
+ * Each invocation runs independently — concurrent flushes (e.g. one
21595
+ * from the timer, one from a `batchSize` trip) each drain their own
21596
+ * batch. Retries up to 3 times on transport or 5xx failure, then
21597
+ * drops with a single warning.
21598
+ */
21599
+ flush() {
21600
+ if (this.buffer.length === 0) return Promise.resolve();
21601
+ const batch = this.buffer;
21602
+ this.buffer = [];
21603
+ const payload = this.spansToOTLPJSON(batch);
21604
+ const work = (async () => {
21605
+ let lastError = null;
21606
+ for (let attempt = 0; attempt < RETRY_BACKOFFS_MS.length; attempt++) {
21607
+ try {
21608
+ const response = await this.fetchImpl(this.endpoint, {
21609
+ method: "POST",
21610
+ headers: this.headers,
21611
+ body: JSON.stringify(payload)
21612
+ });
21613
+ if (response.ok) return;
21614
+ try {
21615
+ await response.text();
21616
+ } catch {
21617
+ }
21618
+ lastError = new Error(`OTLP endpoint returned ${response.status}`);
21619
+ } catch (err) {
21620
+ lastError = err;
21621
+ }
21622
+ const backoff = RETRY_BACKOFFS_MS[attempt] ?? 0;
21623
+ if (attempt < RETRY_BACKOFFS_MS.length - 1) {
21624
+ await new Promise((resolve12) => setTimeout(resolve12, backoff));
21625
+ }
21626
+ }
21627
+ this.warn(
21628
+ `[harness telemetry] dropping ${batch.length} span(s) after 3 failed OTLP attempts:`,
21629
+ lastError
21630
+ );
21631
+ })();
21632
+ this.inFlightFlushes.add(work);
21633
+ void work.finally(() => this.inFlightFlushes.delete(work));
21634
+ return work;
21635
+ }
21636
+ /**
21637
+ * Build the OTLP/HTTP JSON envelope for a batch of spans. Public for
21638
+ * tests; not part of the supported API surface.
21639
+ */
21640
+ spansToOTLPJSON(spans) {
21641
+ return {
21642
+ resourceSpans: [
21643
+ {
21644
+ resource: {
21645
+ attributes: [{ key: "service.name", value: { stringValue: "harness" } }]
21646
+ },
21647
+ scopeSpans: [
21648
+ {
21649
+ scope: { name: "harness" },
21650
+ spans: spans.map((s) => {
21651
+ const span = {
21652
+ traceId: s.traceId,
21653
+ spanId: s.spanId,
21654
+ name: s.name,
21655
+ kind: s.kind,
21656
+ startTimeUnixNano: toUnixNanoString(s.startTimeNs),
21657
+ endTimeUnixNano: toUnixNanoString(s.endTimeNs),
21658
+ attributes: attributesToOTLP(s.attributes)
21659
+ };
21660
+ if (s.parentSpanId !== void 0) span["parentSpanId"] = s.parentSpanId;
21661
+ if (s.statusCode !== void 0) span["status"] = { code: s.statusCode };
21662
+ return span;
21663
+ })
21664
+ }
21665
+ ]
21666
+ }
21667
+ ]
21668
+ };
21669
+ }
21670
+ };
21671
+
21672
+ // src/telemetry/exporter/types.ts
21673
+ var SpanKind = /* @__PURE__ */ ((SpanKind2) => {
21674
+ SpanKind2[SpanKind2["INTERNAL"] = 1] = "INTERNAL";
21675
+ SpanKind2[SpanKind2["SERVER"] = 2] = "SERVER";
21676
+ SpanKind2[SpanKind2["CLIENT"] = 3] = "CLIENT";
21677
+ SpanKind2[SpanKind2["PRODUCER"] = 4] = "PRODUCER";
21678
+ SpanKind2[SpanKind2["CONSUMER"] = 5] = "CONSUMER";
21679
+ return SpanKind2;
21680
+ })(SpanKind || {});
21681
+
21454
21682
  // src/locks/compound-lock.ts
21455
21683
  var fs43 = __toESM(require("fs"));
21456
21684
  var path43 = __toESM(require("path"));
@@ -22210,6 +22438,7 @@ function assembleCandidateReport(input) {
22210
22438
  CINotifier,
22211
22439
  COMPLIANCE_DESCRIPTOR,
22212
22440
  CORROBORATED_AGREEMENT,
22441
+ CacheMetricsRecorder,
22213
22442
  CategoryBaselineSchema,
22214
22443
  CategoryForecastSchema,
22215
22444
  CategoryRegressionSchema,
@@ -22274,6 +22503,7 @@ function assembleCandidateReport(input) {
22274
22503
  NoOpExecutor,
22275
22504
  NoOpSink,
22276
22505
  NoOpTelemetryAdapter,
22506
+ OTLPExporter,
22277
22507
  OpenAICacheAdapter,
22278
22508
  PII_FIELD_DENYLIST,
22279
22509
  PII_LINE_RE,
@@ -22312,6 +22542,7 @@ function assembleCandidateReport(input) {
22312
22542
  SharableSecurityRulesSchema,
22313
22543
  SkillEventSchema,
22314
22544
  SolutionDocFrontmatterSchema,
22545
+ SpanKind,
22315
22546
  SpecImpactEstimateSchema,
22316
22547
  SpecImpactEstimator,
22317
22548
  SpecImpactSignalsSchema,
@@ -22480,6 +22711,7 @@ function assembleCandidateReport(input) {
22480
22711
  goRules,
22481
22712
  injectionRules,
22482
22713
  insecureDefaultsRules,
22714
+ invalidateCheckState,
22483
22715
  isBadPort,
22484
22716
  isDuplicateFinding,
22485
22717
  isRegression,
package/dist/index.mjs CHANGED
@@ -3988,7 +3988,10 @@ function findDeadFiles(snapshot, reachability) {
3988
3988
  return deadFiles;
3989
3989
  }
3990
3990
  function isIdentifierUsedInAST(ast, identifier, skipImportDeclaration = true) {
3991
- const astString = JSON.stringify(ast);
3991
+ const astString = JSON.stringify(
3992
+ ast,
3993
+ (_key, value) => typeof value === "bigint" ? value.toString() : value
3994
+ );
3992
3995
  const identifierPattern = new RegExp(`"name"\\s*:\\s*"${identifier}"`, "g");
3993
3996
  const matches = astString.match(identifierPattern);
3994
3997
  if (!matches) return false;
@@ -16920,6 +16923,12 @@ function shouldRunCheck(state, intervalMs) {
16920
16923
  if (state === null) return true;
16921
16924
  return state.lastCheckTime + intervalMs <= Date.now();
16922
16925
  }
16926
+ function invalidateCheckState() {
16927
+ try {
16928
+ fs36.unlinkSync(getStatePath());
16929
+ } catch {
16930
+ }
16931
+ }
16923
16932
  function readCheckState() {
16924
16933
  try {
16925
16934
  const raw = fs36.readFileSync(getStatePath(), "utf-8");
@@ -18117,7 +18126,7 @@ function resolveConsent(projectRoot, config) {
18117
18126
  }
18118
18127
 
18119
18128
  // src/version.ts
18120
- var VERSION = "0.23.3";
18129
+ var VERSION = "0.25.0";
18121
18130
 
18122
18131
  // src/telemetry/collector.ts
18123
18132
  function mapOutcome(outcome) {
@@ -18178,6 +18187,221 @@ async function send(events, apiKey) {
18178
18187
  }
18179
18188
  }
18180
18189
 
18190
+ // src/telemetry/cache-metrics.ts
18191
+ var DEFAULT_CAPACITY = 1e3;
18192
+ var CacheMetricsRecorder = class {
18193
+ capacity;
18194
+ now;
18195
+ buffer = [];
18196
+ windowStartedAt = 0;
18197
+ constructor(opts = {}) {
18198
+ this.capacity = opts.capacity ?? DEFAULT_CAPACITY;
18199
+ this.now = opts.now ?? Date.now;
18200
+ }
18201
+ /**
18202
+ * Append a single cache observation. Hot-path: O(1) amortized, no
18203
+ * allocations beyond the sample object itself.
18204
+ */
18205
+ record(backendId, hit, tokensCreated, tokensRead) {
18206
+ if (this.windowStartedAt === 0) this.windowStartedAt = this.now();
18207
+ if (this.buffer.length >= this.capacity) this.buffer.shift();
18208
+ this.buffer.push({ backendId, hit, tokensCreated, tokensRead });
18209
+ }
18210
+ /** Aggregate the current window into a `PromptCacheStats` snapshot. */
18211
+ getStats() {
18212
+ let hits = 0;
18213
+ let misses = 0;
18214
+ const byBackend = {};
18215
+ for (const s of this.buffer) {
18216
+ if (s.hit) hits++;
18217
+ else misses++;
18218
+ const slot = byBackend[s.backendId] ?? { hits: 0, misses: 0 };
18219
+ if (s.hit) slot.hits++;
18220
+ else slot.misses++;
18221
+ byBackend[s.backendId] = slot;
18222
+ }
18223
+ const totalRequests = hits + misses;
18224
+ const hitRate = totalRequests === 0 ? 0 : hits / totalRequests;
18225
+ return {
18226
+ totalRequests,
18227
+ hits,
18228
+ misses,
18229
+ hitRate,
18230
+ byBackend,
18231
+ windowStartedAt: this.windowStartedAt
18232
+ };
18233
+ }
18234
+ /** Clear the buffer and reset the window-start marker. */
18235
+ reset() {
18236
+ this.buffer.length = 0;
18237
+ this.windowStartedAt = 0;
18238
+ }
18239
+ };
18240
+
18241
+ // src/telemetry/exporter/otlp-http.ts
18242
+ var RETRY_BACKOFFS_MS = [1e3, 2e3, 4e3];
18243
+ function toUnixNanoString(ns) {
18244
+ return ns.toString(10);
18245
+ }
18246
+ function attributesToOTLP(attrs) {
18247
+ const out = [];
18248
+ for (const [key, value] of Object.entries(attrs)) {
18249
+ if (typeof value === "string") {
18250
+ out.push({ key, value: { stringValue: value } });
18251
+ } else if (typeof value === "boolean") {
18252
+ out.push({ key, value: { boolValue: value } });
18253
+ } else if (typeof value === "number") {
18254
+ if (Number.isInteger(value)) {
18255
+ out.push({ key, value: { intValue: String(value) } });
18256
+ } else {
18257
+ out.push({ key, value: { doubleValue: value } });
18258
+ }
18259
+ }
18260
+ }
18261
+ return out;
18262
+ }
18263
+ var OTLPExporter = class {
18264
+ endpoint;
18265
+ enabled;
18266
+ headers;
18267
+ flushIntervalMs;
18268
+ batchSize;
18269
+ fetchImpl;
18270
+ warn;
18271
+ buffer = [];
18272
+ timer = null;
18273
+ inFlightFlushes = /* @__PURE__ */ new Set();
18274
+ constructor(opts) {
18275
+ this.endpoint = opts.endpoint;
18276
+ this.enabled = opts.enabled !== false;
18277
+ this.headers = { "Content-Type": "application/json", ...opts.headers ?? {} };
18278
+ this.flushIntervalMs = opts.flushIntervalMs ?? 2e3;
18279
+ this.batchSize = opts.batchSize ?? 64;
18280
+ this.fetchImpl = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
18281
+ this.warn = opts.warn ?? ((...a) => console.warn(...a));
18282
+ }
18283
+ /**
18284
+ * O(1) buffer push. When `enabled === false` this is a no-op. If the
18285
+ * buffer reaches `batchSize`, a flush is triggered without awaiting.
18286
+ */
18287
+ push(span) {
18288
+ if (!this.enabled) return;
18289
+ this.buffer.push(span);
18290
+ if (this.buffer.length >= this.batchSize) {
18291
+ void this.flush();
18292
+ }
18293
+ }
18294
+ /** Start the periodic flush timer. Idempotent. */
18295
+ start() {
18296
+ if (!this.enabled || this.timer !== null) return;
18297
+ this.timer = setInterval(() => {
18298
+ void this.flush();
18299
+ }, this.flushIntervalMs);
18300
+ if (typeof this.timer.unref === "function") {
18301
+ this.timer.unref();
18302
+ }
18303
+ }
18304
+ /** Flush any pending spans and stop the timer. Awaits all in-flight flushes. */
18305
+ async stop() {
18306
+ if (this.timer !== null) {
18307
+ clearInterval(this.timer);
18308
+ this.timer = null;
18309
+ }
18310
+ void this.flush();
18311
+ while (this.inFlightFlushes.size > 0) {
18312
+ await Promise.all([...this.inFlightFlushes]);
18313
+ }
18314
+ }
18315
+ /**
18316
+ * Synchronously claim the current buffer and POST it to `/v1/traces`.
18317
+ * Each invocation runs independently — concurrent flushes (e.g. one
18318
+ * from the timer, one from a `batchSize` trip) each drain their own
18319
+ * batch. Retries up to 3 times on transport or 5xx failure, then
18320
+ * drops with a single warning.
18321
+ */
18322
+ flush() {
18323
+ if (this.buffer.length === 0) return Promise.resolve();
18324
+ const batch = this.buffer;
18325
+ this.buffer = [];
18326
+ const payload = this.spansToOTLPJSON(batch);
18327
+ const work = (async () => {
18328
+ let lastError = null;
18329
+ for (let attempt = 0; attempt < RETRY_BACKOFFS_MS.length; attempt++) {
18330
+ try {
18331
+ const response = await this.fetchImpl(this.endpoint, {
18332
+ method: "POST",
18333
+ headers: this.headers,
18334
+ body: JSON.stringify(payload)
18335
+ });
18336
+ if (response.ok) return;
18337
+ try {
18338
+ await response.text();
18339
+ } catch {
18340
+ }
18341
+ lastError = new Error(`OTLP endpoint returned ${response.status}`);
18342
+ } catch (err) {
18343
+ lastError = err;
18344
+ }
18345
+ const backoff = RETRY_BACKOFFS_MS[attempt] ?? 0;
18346
+ if (attempt < RETRY_BACKOFFS_MS.length - 1) {
18347
+ await new Promise((resolve10) => setTimeout(resolve10, backoff));
18348
+ }
18349
+ }
18350
+ this.warn(
18351
+ `[harness telemetry] dropping ${batch.length} span(s) after 3 failed OTLP attempts:`,
18352
+ lastError
18353
+ );
18354
+ })();
18355
+ this.inFlightFlushes.add(work);
18356
+ void work.finally(() => this.inFlightFlushes.delete(work));
18357
+ return work;
18358
+ }
18359
+ /**
18360
+ * Build the OTLP/HTTP JSON envelope for a batch of spans. Public for
18361
+ * tests; not part of the supported API surface.
18362
+ */
18363
+ spansToOTLPJSON(spans) {
18364
+ return {
18365
+ resourceSpans: [
18366
+ {
18367
+ resource: {
18368
+ attributes: [{ key: "service.name", value: { stringValue: "harness" } }]
18369
+ },
18370
+ scopeSpans: [
18371
+ {
18372
+ scope: { name: "harness" },
18373
+ spans: spans.map((s) => {
18374
+ const span = {
18375
+ traceId: s.traceId,
18376
+ spanId: s.spanId,
18377
+ name: s.name,
18378
+ kind: s.kind,
18379
+ startTimeUnixNano: toUnixNanoString(s.startTimeNs),
18380
+ endTimeUnixNano: toUnixNanoString(s.endTimeNs),
18381
+ attributes: attributesToOTLP(s.attributes)
18382
+ };
18383
+ if (s.parentSpanId !== void 0) span["parentSpanId"] = s.parentSpanId;
18384
+ if (s.statusCode !== void 0) span["status"] = { code: s.statusCode };
18385
+ return span;
18386
+ })
18387
+ }
18388
+ ]
18389
+ }
18390
+ ]
18391
+ };
18392
+ }
18393
+ };
18394
+
18395
+ // src/telemetry/exporter/types.ts
18396
+ var SpanKind = /* @__PURE__ */ ((SpanKind2) => {
18397
+ SpanKind2[SpanKind2["INTERNAL"] = 1] = "INTERNAL";
18398
+ SpanKind2[SpanKind2["SERVER"] = 2] = "SERVER";
18399
+ SpanKind2[SpanKind2["CLIENT"] = 3] = "CLIENT";
18400
+ SpanKind2[SpanKind2["PRODUCER"] = 4] = "PRODUCER";
18401
+ SpanKind2[SpanKind2["CONSUMER"] = 5] = "CONSUMER";
18402
+ return SpanKind2;
18403
+ })(SpanKind || {});
18404
+
18181
18405
  // src/locks/compound-lock.ts
18182
18406
  import * as fs43 from "fs";
18183
18407
  import * as path43 from "path";
@@ -18935,6 +19159,7 @@ export {
18935
19159
  CINotifier,
18936
19160
  COMPLIANCE_DESCRIPTOR,
18937
19161
  CORROBORATED_AGREEMENT,
19162
+ CacheMetricsRecorder,
18938
19163
  CategoryBaselineSchema,
18939
19164
  CategoryForecastSchema,
18940
19165
  CategoryRegressionSchema,
@@ -18999,6 +19224,7 @@ export {
18999
19224
  NoOpExecutor,
19000
19225
  NoOpSink,
19001
19226
  NoOpTelemetryAdapter,
19227
+ OTLPExporter,
19002
19228
  OpenAICacheAdapter,
19003
19229
  PII_FIELD_DENYLIST,
19004
19230
  PII_LINE_RE,
@@ -19037,6 +19263,7 @@ export {
19037
19263
  SharableSecurityRulesSchema,
19038
19264
  SkillEventSchema,
19039
19265
  SolutionDocFrontmatterSchema,
19266
+ SpanKind,
19040
19267
  SpecImpactEstimateSchema,
19041
19268
  SpecImpactEstimator,
19042
19269
  SpecImpactSignalsSchema,
@@ -19205,6 +19432,7 @@ export {
19205
19432
  goRules,
19206
19433
  injectionRules,
19207
19434
  insecureDefaultsRules,
19435
+ invalidateCheckState,
19208
19436
  isBadPort,
19209
19437
  isDuplicateFinding,
19210
19438
  isRegression,