@vitest-agent/plugin 5.4.5 → 5.4.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 (3) hide show
  1. package/package.json +13 -13
  2. package/reporter.js +260 -258
  3. package/version.js +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitest-agent/plugin",
3
- "version": "5.4.5",
3
+ "version": "5.4.7",
4
4
  "private": false,
5
5
  "description": "Vitest plugin for the vitest-agent ecosystem: owns persistence, classification, baselines, trends, and dispatches rendering to a configurable reporter.",
6
6
  "keywords": [
@@ -43,18 +43,18 @@
43
43
  "vitest-agent-mcp": "bin/vitest-agent-mcp.js"
44
44
  },
45
45
  "dependencies": {
46
- "@effect/platform-node": "^4.0.4",
47
- "@effected/cli": "^0.18.0",
48
- "@effected/env": "^0.3.0",
49
- "@effected/glob": "^0.12.0",
50
- "@effected/walker": "^0.17.0",
51
- "@effected/workspaces": "^0.34.0",
52
- "@vitest-agent/cli": "4.0.9",
53
- "@vitest-agent/engine": "1.0.5",
54
- "@vitest-agent/mcp": "5.2.5",
55
- "@vitest-agent/reporter": "5.0.5",
56
- "@vitest-agent/sdk": "7.0.3",
57
- "effect": "^4.0.4",
46
+ "@effect/platform-node": "^4.0.5",
47
+ "@effected/cli": "^0.19.0",
48
+ "@effected/env": "^0.4.0",
49
+ "@effected/glob": "^0.13.0",
50
+ "@effected/walker": "^0.18.0",
51
+ "@effected/workspaces": "^0.35.0",
52
+ "@vitest-agent/cli": "4.0.11",
53
+ "@vitest-agent/engine": "1.1.0",
54
+ "@vitest-agent/mcp": "5.2.7",
55
+ "@vitest-agent/reporter": "5.0.6",
56
+ "@vitest-agent/sdk": "7.0.4",
57
+ "effect": "^4.0.5",
58
58
  "magic-string": "^1.4.3"
59
59
  },
60
60
  "peerDependencies": {
package/reporter.js CHANGED
@@ -13,7 +13,7 @@ import { strayOutputCaptureOf } from "./utils/stray-output-capture.js";
13
13
  import { stringifyFailureValue } from "./utils/stringify-failure-value.js";
14
14
  import { mkdirSync, statSync } from "node:fs";
15
15
  import { dirname } from "node:path";
16
- import { DataReader, DataStore, DetailResolver, EnvironmentDetector, ExecutorResolver, HistoryTracker, OutputPipelineLive, PathResolutionLive, ensureMigrated, historyKey, resolveDataPath, resolveLogFile, resolveLogLevel } from "@vitest-agent/engine";
16
+ import { DataReader, DataStore, DetailResolver, EnvironmentDetector, ExecutorResolver, HistoryTracker, OutputPipelineLive, PathResolutionLive, ensureMigrated, historyKey, resolveDataPath, resolveLogFile, resolveLogLevel, withPersistTransaction } from "@vitest-agent/engine";
17
17
  import { buildAgentReport, coerceErrorField, computeTrend, formatFatalError, isTimeoutError, probeHostMetadataFromEnv } from "@vitest-agent/sdk";
18
18
  import { Effect, Option, PubSub } from "effect";
19
19
  import { randomUUID } from "node:crypto";
@@ -1279,7 +1279,6 @@ var AgentReporter = class {
1279
1279
  const settings = captureSettings(vitestConfig, vitestVersion);
1280
1280
  const settingsHash = hashSettings(settings);
1281
1281
  const envVars = captureEnvVars(process.env);
1282
- yield* store.writeSettings(settingsHash, settings, envVars);
1283
1282
  const projectGroups = /* @__PURE__ */ new Map();
1284
1283
  for (const mod of filteredModules) {
1285
1284
  const key = mod.project.name || "default";
@@ -1341,113 +1340,155 @@ var AgentReporter = class {
1341
1340
  }
1342
1341
  const reports = [];
1343
1342
  const isMultiProject = projectGroups.size > 1 || !!opts.projectFilter;
1344
- for (const [projectName, projectModules] of projectGroups) {
1345
- const project = projectName === "default" ? "default" : projectName;
1346
- const baseReport = buildAgentReport(projectModules, errors, reason, { omitPassingTests: opts.omitPassingTests }, isMultiProject ? projectName : void 0);
1347
- let totalDuration = 0;
1348
- for (const mod of projectModules) totalDuration += mod.diagnostic()?.duration ?? 0;
1349
- const envAgentId = process.env.VITEST_AGENT_AGENT_ID;
1350
- const envConversationId = process.env.VITEST_AGENT_CONVERSATION_ID;
1351
- const attribution = envAgentId !== void 0 && envAgentId.length > 0 ? {
1352
- actorType: "agent",
1353
- agentId: envAgentId,
1354
- conversationId: envConversationId ?? null
1355
- } : {
1356
- actorType: "system",
1357
- agentId: null,
1358
- conversationId: null
1359
- };
1360
- const hostProbe = probeHostMetadataFromEnv(process.env);
1361
- const projectReason = reason === "interrupted" ? "interrupted" : baseReport.summary.failed > 0 || baseReport.failedFiles.length > 0 ? "failed" : "passed";
1362
- const runId = yield* store.writeRun({
1363
- invocationId,
1364
- project,
1365
- settingsHash,
1366
- timestamp: baseReport.timestamp,
1367
- commitSha: process.env.GITHUB_SHA ?? null,
1368
- branch: process.env.GITHUB_REF_NAME ?? null,
1369
- reason: projectReason,
1370
- duration: totalDuration,
1371
- total: baseReport.summary.total,
1372
- passed: baseReport.summary.passed,
1373
- failed: baseReport.summary.failed,
1374
- skipped: baseReport.summary.skipped,
1375
- scoped: isPartial,
1376
- actorType: attribution.actorType,
1377
- agentId: attribution.agentId,
1378
- conversationId: attribution.conversationId,
1379
- gitBranch: process.env.GITHUB_REF_NAME ?? null,
1380
- gitCommitSha: process.env.GITHUB_SHA ?? null,
1381
- hostSource: hostProbe.source,
1382
- hostValue: hostProbe.value,
1383
- hostMetadata: hostProbe.metadata
1384
- });
1385
- for (const mod of projectModules) {
1386
- const fileId = yield* store.ensureFile(mod.relativeModuleId);
1387
- const moduleId = (yield* store.writeModules(runId, [{
1388
- fileId,
1389
- relativeModuleId: mod.relativeModuleId,
1390
- state: mod.state(),
1391
- duration: mod.diagnostic()?.duration ?? 0
1392
- }]))[0];
1393
- const sourceFile = mod.relativeModuleId.replace(/\.test\.([^.]+)$/, ".$1").replace(/\.spec\.([^.]+)$/, ".$1");
1394
- if (sourceFile !== mod.relativeModuleId) yield* store.writeSourceMap(sourceFile, moduleId, "convention");
1395
- const suiteIdMap = /* @__PURE__ */ new Map();
1396
- for (const suite of mod.children.allSuites()) {
1397
- const parentSuiteId = suite.parent && suite.parent.type === "suite" ? suiteIdMap.get(suite.parent.fullName) : void 0;
1398
- const suiteIds = yield* store.writeSuites(moduleId, [{
1399
- name: suite.name,
1400
- fullName: suite.fullName,
1401
- state: suite.state(),
1402
- ...parentSuiteId !== void 0 && { parentSuiteId },
1403
- ...suite.options?.mode !== void 0 && { mode: suite.options.mode },
1404
- ...suite.options?.concurrent !== void 0 && { concurrent: suite.options.concurrent },
1405
- ...suite.options?.shuffle !== void 0 && { shuffle: suite.options.shuffle },
1406
- ...suite.options?.retry !== void 0 && { retry: suite.options.retry },
1407
- ...suite.options?.repeats !== void 0 && { repeats: suite.options.repeats },
1408
- ...suite.location?.line !== void 0 && { locationLine: suite.location.line },
1409
- ...suite.location?.column !== void 0 && { locationColumn: suite.location.column }
1410
- }]);
1411
- suiteIdMap.set(suite.fullName, suiteIds[0]);
1412
- }
1413
- const testCases = [];
1414
- for (const testCase of mod.children.allTests()) {
1415
- const result = testCase.result();
1416
- const diag = testCase.diagnostic();
1417
- const parent = testCase.parent;
1418
- const parentSuiteId = parent && parent.type === "suite" ? suiteIdMap.get(parent.fullName) : void 0;
1419
- testCases.push({
1420
- name: testCase.name,
1421
- fullName: testCase.fullName,
1422
- state: result?.state ?? "pending",
1423
- ...diag?.duration !== void 0 && { duration: diag.duration },
1424
- ...diag?.flaky !== void 0 && { flaky: diag.flaky },
1425
- ...diag?.slow !== void 0 && { slow: diag.slow },
1426
- ...testCase.tags.length > 0 && { tags: testCase.tags },
1427
- ...parentSuiteId !== void 0 && { suiteId: parentSuiteId }
1428
- });
1429
- }
1430
- const testCaseIds = yield* store.writeTestCases(moduleId, testCases.map((tc) => ({
1431
- name: tc.name,
1432
- fullName: tc.fullName,
1433
- state: tc.state,
1434
- ...tc.duration !== void 0 && { duration: tc.duration },
1435
- ...tc.flaky !== void 0 && { flaky: tc.flaky },
1436
- ...tc.slow !== void 0 && { slow: tc.slow },
1437
- ...tc.tags !== void 0 && { tags: tc.tags },
1438
- ...tc.suiteId !== void 0 && { suiteId: tc.suiteId }
1439
- })));
1440
- let testIdx = 0;
1441
- for (const testCase of mod.children.allTests()) {
1442
- const result = testCase.result();
1443
- const testCaseId = testCaseIds[testIdx];
1444
- if (result?.errors && result.errors.length > 0) {
1343
+ yield* withPersistTransaction(Effect.gen(function* () {
1344
+ yield* store.writeSettings(settingsHash, settings, envVars);
1345
+ for (const [projectName, projectModules] of projectGroups) {
1346
+ const project = projectName === "default" ? "default" : projectName;
1347
+ const baseReport = buildAgentReport(projectModules, errors, reason, { omitPassingTests: opts.omitPassingTests }, isMultiProject ? projectName : void 0);
1348
+ let totalDuration = 0;
1349
+ for (const mod of projectModules) totalDuration += mod.diagnostic()?.duration ?? 0;
1350
+ const envAgentId = process.env.VITEST_AGENT_AGENT_ID;
1351
+ const envConversationId = process.env.VITEST_AGENT_CONVERSATION_ID;
1352
+ const attribution = envAgentId !== void 0 && envAgentId.length > 0 ? {
1353
+ actorType: "agent",
1354
+ agentId: envAgentId,
1355
+ conversationId: envConversationId ?? null
1356
+ } : {
1357
+ actorType: "system",
1358
+ agentId: null,
1359
+ conversationId: null
1360
+ };
1361
+ const hostProbe = probeHostMetadataFromEnv(process.env);
1362
+ const projectReason = reason === "interrupted" ? "interrupted" : baseReport.summary.failed > 0 || baseReport.failedFiles.length > 0 ? "failed" : "passed";
1363
+ const runId = yield* store.writeRun({
1364
+ invocationId,
1365
+ project,
1366
+ settingsHash,
1367
+ timestamp: baseReport.timestamp,
1368
+ commitSha: process.env.GITHUB_SHA ?? null,
1369
+ branch: process.env.GITHUB_REF_NAME ?? null,
1370
+ reason: projectReason,
1371
+ duration: totalDuration,
1372
+ total: baseReport.summary.total,
1373
+ passed: baseReport.summary.passed,
1374
+ failed: baseReport.summary.failed,
1375
+ skipped: baseReport.summary.skipped,
1376
+ scoped: isPartial,
1377
+ actorType: attribution.actorType,
1378
+ agentId: attribution.agentId,
1379
+ conversationId: attribution.conversationId,
1380
+ gitBranch: process.env.GITHUB_REF_NAME ?? null,
1381
+ gitCommitSha: process.env.GITHUB_SHA ?? null,
1382
+ hostSource: hostProbe.source,
1383
+ hostValue: hostProbe.value,
1384
+ hostMetadata: hostProbe.metadata
1385
+ });
1386
+ for (const mod of projectModules) {
1387
+ const fileId = yield* store.ensureFile(mod.relativeModuleId);
1388
+ const moduleId = (yield* store.writeModules(runId, [{
1389
+ fileId,
1390
+ relativeModuleId: mod.relativeModuleId,
1391
+ state: mod.state(),
1392
+ duration: mod.diagnostic()?.duration ?? 0
1393
+ }]))[0];
1394
+ const sourceFile = mod.relativeModuleId.replace(/\.test\.([^.]+)$/, ".$1").replace(/\.spec\.([^.]+)$/, ".$1");
1395
+ if (sourceFile !== mod.relativeModuleId) yield* store.writeSourceMap(sourceFile, moduleId, "convention");
1396
+ const suiteIdMap = /* @__PURE__ */ new Map();
1397
+ for (const suite of mod.children.allSuites()) {
1398
+ const parentSuiteId = suite.parent && suite.parent.type === "suite" ? suiteIdMap.get(suite.parent.fullName) : void 0;
1399
+ const suiteIds = yield* store.writeSuites(moduleId, [{
1400
+ name: suite.name,
1401
+ fullName: suite.fullName,
1402
+ state: suite.state(),
1403
+ ...parentSuiteId !== void 0 && { parentSuiteId },
1404
+ ...suite.options?.mode !== void 0 && { mode: suite.options.mode },
1405
+ ...suite.options?.concurrent !== void 0 && { concurrent: suite.options.concurrent },
1406
+ ...suite.options?.shuffle !== void 0 && { shuffle: suite.options.shuffle },
1407
+ ...suite.options?.retry !== void 0 && { retry: suite.options.retry },
1408
+ ...suite.options?.repeats !== void 0 && { repeats: suite.options.repeats },
1409
+ ...suite.location?.line !== void 0 && { locationLine: suite.location.line },
1410
+ ...suite.location?.column !== void 0 && { locationColumn: suite.location.column }
1411
+ }]);
1412
+ suiteIdMap.set(suite.fullName, suiteIds[0]);
1413
+ }
1414
+ const testCases = [];
1415
+ for (const testCase of mod.children.allTests()) {
1416
+ const result = testCase.result();
1417
+ const diag = testCase.diagnostic();
1418
+ const parent = testCase.parent;
1419
+ const parentSuiteId = parent && parent.type === "suite" ? suiteIdMap.get(parent.fullName) : void 0;
1420
+ testCases.push({
1421
+ name: testCase.name,
1422
+ fullName: testCase.fullName,
1423
+ state: result?.state ?? "pending",
1424
+ ...diag?.duration !== void 0 && { duration: diag.duration },
1425
+ ...diag?.flaky !== void 0 && { flaky: diag.flaky },
1426
+ ...diag?.slow !== void 0 && { slow: diag.slow },
1427
+ ...testCase.tags.length > 0 && { tags: testCase.tags },
1428
+ ...parentSuiteId !== void 0 && { suiteId: parentSuiteId }
1429
+ });
1430
+ }
1431
+ const testCaseIds = yield* store.writeTestCases(moduleId, testCases.map((tc) => ({
1432
+ name: tc.name,
1433
+ fullName: tc.fullName,
1434
+ state: tc.state,
1435
+ ...tc.duration !== void 0 && { duration: tc.duration },
1436
+ ...tc.flaky !== void 0 && { flaky: tc.flaky },
1437
+ ...tc.slow !== void 0 && { slow: tc.slow },
1438
+ ...tc.tags !== void 0 && { tags: tc.tags },
1439
+ ...tc.suiteId !== void 0 && { suiteId: tc.suiteId }
1440
+ })));
1441
+ let testIdx = 0;
1442
+ for (const testCase of mod.children.allTests()) {
1443
+ const result = testCase.result();
1444
+ const testCaseId = testCaseIds[testIdx];
1445
+ if (result?.errors && result.errors.length > 0) {
1446
+ const inputs = [];
1447
+ for (let ordinal = 0; ordinal < result.errors.length; ordinal++) {
1448
+ const e = result.errors[ordinal];
1449
+ const messageText = coerceErrorField(e, "message") ?? "<missing message>";
1450
+ const nameText = coerceErrorField(e, "name");
1451
+ const diffText = coerceErrorField(e, "diff");
1452
+ const stackText = coerceErrorField(e, "stack");
1453
+ const stacksValue = readErrorStacks(e);
1454
+ const { frames, signatureHash } = processFailure({
1455
+ message: messageText,
1456
+ ...nameText !== void 0 && { name: nameText },
1457
+ ...stackText !== void 0 && { stack: stackText },
1458
+ ...stacksValue !== void 0 && { stacks: stacksValue }
1459
+ });
1460
+ if (signatureHash !== null) yield* store.writeFailureSignature({
1461
+ signatureHash,
1462
+ runId,
1463
+ seenAt: baseReport.timestamp
1464
+ });
1465
+ inputs.push({
1466
+ testCaseId,
1467
+ scope: "test",
1468
+ message: messageText,
1469
+ ...nameText !== void 0 && { name: nameText },
1470
+ ...diffText !== void 0 && { diff: diffText },
1471
+ ...stackText !== void 0 && { stack: stackText },
1472
+ ...signatureHash !== null && { signatureHash },
1473
+ ...frames.length > 0 && { frames },
1474
+ ordinal
1475
+ });
1476
+ }
1477
+ yield* store.writeErrors(runId, inputs);
1478
+ }
1479
+ const annotationInputs = toAnnotationInputs(testCaseId, testCase.annotations?.() ?? []);
1480
+ if (annotationInputs.length > 0) yield* store.writeAnnotations(runId, annotationInputs);
1481
+ const artifactInputs = toArtifactInputs(testCaseId, testCase.artifacts?.() ?? []);
1482
+ if (artifactInputs.length > 0) yield* store.writeArtifacts(runId, artifactInputs);
1483
+ testIdx++;
1484
+ }
1485
+ const modErrors = mod.errors();
1486
+ if (modErrors.length > 0) {
1445
1487
  const inputs = [];
1446
- for (let ordinal = 0; ordinal < result.errors.length; ordinal++) {
1447
- const e = result.errors[ordinal];
1488
+ for (let ordinal = 0; ordinal < modErrors.length; ordinal++) {
1489
+ const e = modErrors[ordinal];
1448
1490
  const messageText = coerceErrorField(e, "message") ?? "<missing message>";
1449
1491
  const nameText = coerceErrorField(e, "name");
1450
- const diffText = coerceErrorField(e, "diff");
1451
1492
  const stackText = coerceErrorField(e, "stack");
1452
1493
  const stacksValue = readErrorStacks(e);
1453
1494
  const { frames, signatureHash } = processFailure({
@@ -1462,11 +1503,10 @@ var AgentReporter = class {
1462
1503
  seenAt: baseReport.timestamp
1463
1504
  });
1464
1505
  inputs.push({
1465
- testCaseId,
1466
- scope: "test",
1506
+ moduleId,
1507
+ scope: "module",
1467
1508
  message: messageText,
1468
1509
  ...nameText !== void 0 && { name: nameText },
1469
- ...diffText !== void 0 && { diff: diffText },
1470
1510
  ...stackText !== void 0 && { stack: stackText },
1471
1511
  ...signatureHash !== null && { signatureHash },
1472
1512
  ...frames.length > 0 && { frames },
@@ -1475,17 +1515,11 @@ var AgentReporter = class {
1475
1515
  }
1476
1516
  yield* store.writeErrors(runId, inputs);
1477
1517
  }
1478
- const annotationInputs = toAnnotationInputs(testCaseId, testCase.annotations?.() ?? []);
1479
- if (annotationInputs.length > 0) yield* store.writeAnnotations(runId, annotationInputs);
1480
- const artifactInputs = toArtifactInputs(testCaseId, testCase.artifacts?.() ?? []);
1481
- if (artifactInputs.length > 0) yield* store.writeArtifacts(runId, artifactInputs);
1482
- testIdx++;
1483
1518
  }
1484
- const modErrors = mod.errors();
1485
- if (modErrors.length > 0) {
1519
+ if (errors.length > 0) {
1486
1520
  const inputs = [];
1487
- for (let ordinal = 0; ordinal < modErrors.length; ordinal++) {
1488
- const e = modErrors[ordinal];
1521
+ for (let ordinal = 0; ordinal < errors.length; ordinal++) {
1522
+ const e = errors[ordinal];
1489
1523
  const messageText = coerceErrorField(e, "message") ?? "<missing message>";
1490
1524
  const nameText = coerceErrorField(e, "name");
1491
1525
  const stackText = coerceErrorField(e, "stack");
@@ -1502,8 +1536,7 @@ var AgentReporter = class {
1502
1536
  seenAt: baseReport.timestamp
1503
1537
  });
1504
1538
  inputs.push({
1505
- moduleId,
1506
- scope: "module",
1539
+ scope: "unhandled",
1507
1540
  message: messageText,
1508
1541
  ...nameText !== void 0 && { name: nameText },
1509
1542
  ...stackText !== void 0 && { stack: stackText },
@@ -1514,154 +1547,123 @@ var AgentReporter = class {
1514
1547
  }
1515
1548
  yield* store.writeErrors(runId, inputs);
1516
1549
  }
1517
- }
1518
- if (errors.length > 0) {
1519
- const inputs = [];
1520
- for (let ordinal = 0; ordinal < errors.length; ordinal++) {
1521
- const e = errors[ordinal];
1522
- const messageText = coerceErrorField(e, "message") ?? "<missing message>";
1523
- const nameText = coerceErrorField(e, "name");
1524
- const stackText = coerceErrorField(e, "stack");
1525
- const stacksValue = readErrorStacks(e);
1526
- const { frames, signatureHash } = processFailure({
1527
- message: messageText,
1528
- ...nameText !== void 0 && { name: nameText },
1529
- ...stackText !== void 0 && { stack: stackText },
1530
- ...stacksValue !== void 0 && { stacks: stacksValue }
1531
- });
1532
- if (signatureHash !== null) yield* store.writeFailureSignature({
1533
- signatureHash,
1534
- runId,
1535
- seenAt: baseReport.timestamp
1536
- });
1537
- inputs.push({
1538
- scope: "unhandled",
1539
- message: messageText,
1540
- ...nameText !== void 0 && { name: nameText },
1541
- ...stackText !== void 0 && { stack: stackText },
1542
- ...signatureHash !== null && { signatureHash },
1543
- ...frames.length > 0 && { frames },
1544
- ordinal
1545
- });
1546
- }
1547
- yield* store.writeErrors(runId, inputs);
1548
- }
1549
- const testOutcomes = [];
1550
- for (const mod of projectModules) {
1551
- const modulePath = mod.relativeModuleId ?? "";
1552
- for (const testCase of mod.children.allTests()) {
1553
- const state = testCase.result()?.state;
1554
- if (state === "passed" || state === "failed") testOutcomes.push({
1555
- modulePath,
1556
- fullName: testCase.fullName,
1557
- state
1558
- });
1559
- }
1560
- }
1561
- const { classifications } = yield* tracker.classify(project, testOutcomes, baseReport.timestamp);
1562
- const diagMap = /* @__PURE__ */ new Map();
1563
- const errorMap = /* @__PURE__ */ new Map();
1564
- for (const mod of projectModules) {
1565
- const modulePath = mod.relativeModuleId ?? "";
1566
- for (const tc of mod.children.allTests()) {
1567
- const key = historyKey(modulePath, tc.fullName);
1568
- diagMap.set(key, tc.diagnostic() ?? {});
1569
- const tcResult = tc.result();
1570
- if (tcResult?.state === "failed") {
1571
- const errors = tcResult.errors;
1572
- errorMap.set(key, coerceErrorField(errors?.[0], "message") ?? null);
1550
+ const testOutcomes = [];
1551
+ for (const mod of projectModules) {
1552
+ const modulePath = mod.relativeModuleId ?? "";
1553
+ for (const testCase of mod.children.allTests()) {
1554
+ const state = testCase.result()?.state;
1555
+ if (state === "passed" || state === "failed") testOutcomes.push({
1556
+ modulePath,
1557
+ fullName: testCase.fullName,
1558
+ state
1559
+ });
1573
1560
  }
1574
1561
  }
1575
- }
1576
- for (const outcome of testOutcomes) {
1577
- const key = historyKey(outcome.modulePath, outcome.fullName);
1578
- const diag = diagMap.get(key);
1579
- const errorMessage = outcome.state === "failed" ? errorMap.get(key) ?? null : null;
1580
- yield* store.writeHistory(project, outcome.fullName, outcome.modulePath, runId, baseReport.timestamp, outcome.state, diag?.duration ?? null, diag?.flaky ?? false, 0, errorMessage);
1581
- }
1582
- const failedWithClassifications = baseReport.failed.map((mod) => ({
1583
- ...mod,
1584
- tests: mod.tests.map((test) => {
1585
- const cls = classifications.get(historyKey(mod.file, test.fullName));
1586
- return cls ? {
1587
- ...test,
1588
- classification: cls
1589
- } : test;
1590
- })
1591
- }));
1592
- const classifiedReport = {
1593
- ...baseReport,
1594
- failed: failedWithClassifications
1595
- };
1596
- const tagCounts = {};
1597
- for (const mod of projectModules) for (const tc of mod.children.allTests()) {
1598
- const state = tc.result()?.state ?? "pending";
1599
- const tags = tc.tags ?? [];
1600
- for (const tag of tags) {
1601
- tagCounts[tag] ??= {
1602
- passed: 0,
1603
- failed: 0,
1604
- skipped: 0
1605
- };
1606
- if (state === "passed") tagCounts[tag].passed++;
1607
- else if (state === "failed") tagCounts[tag].failed++;
1608
- else if (state === "skipped") tagCounts[tag].skipped++;
1562
+ const { classifications } = yield* tracker.classify(project, testOutcomes, baseReport.timestamp);
1563
+ const diagMap = /* @__PURE__ */ new Map();
1564
+ const errorMap = /* @__PURE__ */ new Map();
1565
+ for (const mod of projectModules) {
1566
+ const modulePath = mod.relativeModuleId ?? "";
1567
+ for (const tc of mod.children.allTests()) {
1568
+ const key = historyKey(modulePath, tc.fullName);
1569
+ diagMap.set(key, tc.diagnostic() ?? {});
1570
+ const tcResult = tc.result();
1571
+ if (tcResult?.state === "failed") {
1572
+ const errors = tcResult.errors;
1573
+ errorMap.set(key, coerceErrorField(errors?.[0], "message") ?? null);
1574
+ }
1575
+ }
1609
1576
  }
1610
- }
1611
- const reportWithTags = Object.keys(tagCounts).length > 0 ? {
1612
- ...classifiedReport,
1613
- tagCounts
1614
- } : classifiedReport;
1615
- const report = coverageReport ? {
1616
- ...reportWithTags,
1617
- coverage: coverageReport
1618
- } : reportWithTags;
1619
- reports.push(report);
1620
- if (coverageReport) {
1621
- const tierByFile = /* @__PURE__ */ new Map();
1622
- const sourceByFile = /* @__PURE__ */ new Map();
1623
- for (const fc of coverageReport.belowTarget ?? []) {
1624
- tierByFile.set(fc.file, "below_target");
1625
- sourceByFile.set(fc.file, fc);
1577
+ for (const outcome of testOutcomes) {
1578
+ const key = historyKey(outcome.modulePath, outcome.fullName);
1579
+ const diag = diagMap.get(key);
1580
+ const errorMessage = outcome.state === "failed" ? errorMap.get(key) ?? null : null;
1581
+ yield* store.writeHistory(project, outcome.fullName, outcome.modulePath, runId, baseReport.timestamp, outcome.state, diag?.duration ?? null, diag?.flaky ?? false, 0, errorMessage);
1626
1582
  }
1627
- for (const fc of coverageReport.lowCoverage) {
1628
- tierByFile.set(fc.file, "below_threshold");
1629
- sourceByFile.set(fc.file, fc);
1583
+ const failedWithClassifications = baseReport.failed.map((mod) => ({
1584
+ ...mod,
1585
+ tests: mod.tests.map((test) => {
1586
+ const cls = classifications.get(historyKey(mod.file, test.fullName));
1587
+ return cls ? {
1588
+ ...test,
1589
+ classification: cls
1590
+ } : test;
1591
+ })
1592
+ }));
1593
+ const classifiedReport = {
1594
+ ...baseReport,
1595
+ failed: failedWithClassifications
1596
+ };
1597
+ const tagCounts = {};
1598
+ for (const mod of projectModules) for (const tc of mod.children.allTests()) {
1599
+ const state = tc.result()?.state ?? "pending";
1600
+ const tags = tc.tags ?? [];
1601
+ for (const tag of tags) {
1602
+ tagCounts[tag] ??= {
1603
+ passed: 0,
1604
+ failed: 0,
1605
+ skipped: 0
1606
+ };
1607
+ if (state === "passed") tagCounts[tag].passed++;
1608
+ else if (state === "failed") tagCounts[tag].failed++;
1609
+ else if (state === "skipped") tagCounts[tag].skipped++;
1610
+ }
1630
1611
  }
1631
- if (tierByFile.size > 0) {
1632
- const coverageInputs = [];
1633
- for (const [file, tier] of tierByFile) {
1634
- const fc = sourceByFile.get(file);
1635
- if (!fc) continue;
1636
- const fileId = yield* store.ensureFile(fc.file);
1637
- coverageInputs.push({
1638
- fileId,
1639
- statements: fc.summary.statements,
1640
- branches: fc.summary.branches,
1641
- functions: fc.summary.functions,
1642
- lines: fc.summary.lines,
1643
- uncoveredLines: fc.uncoveredLines,
1644
- tier
1645
- });
1612
+ const reportWithTags = Object.keys(tagCounts).length > 0 ? {
1613
+ ...classifiedReport,
1614
+ tagCounts
1615
+ } : classifiedReport;
1616
+ const report = coverageReport ? {
1617
+ ...reportWithTags,
1618
+ coverage: coverageReport
1619
+ } : reportWithTags;
1620
+ reports.push(report);
1621
+ if (coverageReport) {
1622
+ const tierByFile = /* @__PURE__ */ new Map();
1623
+ const sourceByFile = /* @__PURE__ */ new Map();
1624
+ for (const fc of coverageReport.belowTarget ?? []) {
1625
+ tierByFile.set(fc.file, "below_target");
1626
+ sourceByFile.set(fc.file, fc);
1627
+ }
1628
+ for (const fc of coverageReport.lowCoverage) {
1629
+ tierByFile.set(fc.file, "below_threshold");
1630
+ sourceByFile.set(fc.file, fc);
1631
+ }
1632
+ if (tierByFile.size > 0) {
1633
+ const coverageInputs = [];
1634
+ for (const [file, tier] of tierByFile) {
1635
+ const fc = sourceByFile.get(file);
1636
+ if (!fc) continue;
1637
+ const fileId = yield* store.ensureFile(fc.file);
1638
+ coverageInputs.push({
1639
+ fileId,
1640
+ statements: fc.summary.statements,
1641
+ branches: fc.summary.branches,
1642
+ functions: fc.summary.functions,
1643
+ lines: fc.summary.lines,
1644
+ uncoveredLines: fc.uncoveredLines,
1645
+ tier
1646
+ });
1647
+ }
1648
+ yield* store.writeCoverage(runId, coverageInputs);
1646
1649
  }
1647
- yield* store.writeCoverage(runId, coverageInputs);
1650
+ }
1651
+ if (coverageReport && !coverageReport.scoped) {
1652
+ const existingTrends = yield* reader.getTrends(project).pipe(Effect.map((opt) => Option.getOrUndefined(opt)), Effect.catch(() => Effect.succeed(void 0)));
1653
+ const updatedTrends = computeTrend(coverageReport.totals, existingTrends, opts.coverageTargets);
1654
+ const latestEntry = updatedTrends.entries[updatedTrends.entries.length - 1];
1655
+ if (latestEntry) yield* store.writeTrends(project, runId, latestEntry);
1648
1656
  }
1649
1657
  }
1658
+ if (opts.autoUpdate && coverageReport) {
1659
+ const newBaselines = computeUpdatedBaselines(baselines, coverageReport.totals, opts.coverageTargets);
1660
+ yield* store.writeBaselines(newBaselines);
1661
+ }
1650
1662
  if (coverageReport && !coverageReport.scoped) {
1651
- const existingTrends = yield* reader.getTrends(project).pipe(Effect.map((opt) => Option.getOrUndefined(opt)), Effect.catch(() => Effect.succeed(void 0)));
1652
- const updatedTrends = computeTrend(coverageReport.totals, existingTrends, opts.coverageTargets);
1653
- const latestEntry = updatedTrends.entries[updatedTrends.entries.length - 1];
1654
- if (latestEntry) yield* store.writeTrends(project, runId, latestEntry);
1663
+ if (opts.coverageThresholds !== void 0) yield* store.writeThresholds(opts.coverageThresholds);
1664
+ if (opts.coverageTargets !== void 0) yield* store.writeTargets(opts.coverageTargets);
1655
1665
  }
1656
- }
1657
- if (opts.autoUpdate && coverageReport) {
1658
- const newBaselines = computeUpdatedBaselines(baselines, coverageReport.totals, opts.coverageTargets);
1659
- yield* store.writeBaselines(newBaselines);
1660
- }
1661
- if (coverageReport && !coverageReport.scoped) {
1662
- if (opts.coverageThresholds !== void 0) yield* store.writeThresholds(opts.coverageThresholds);
1663
- if (opts.coverageTargets !== void 0) yield* store.writeTargets(opts.coverageTargets);
1664
- }
1666
+ }));
1665
1667
  let trendSummary;
1666
1668
  if (coverageReport && !coverageReport.scoped) {
1667
1669
  const firstProjectKey = Array.from(projectGroups.keys())[0];
package/version.js CHANGED
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * @public
10
10
  */
11
- const CURRENT_PLUGIN_VERSION = "5.4.5";
11
+ const CURRENT_PLUGIN_VERSION = "5.4.7";
12
12
 
13
13
  //#endregion
14
14
  export { CURRENT_PLUGIN_VERSION };