@vitest-agent/sdk 1.2.0 → 1.3.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/index.d.ts +32 -7
- package/index.js +3 -3
- package/layers/DataReaderLive.js +30 -17
- package/layers/DataStoreLive.js +4 -3
- package/layers/HistoryTrackerLive.js +7 -5
- package/migrations/0001_initial.js +3 -2
- package/package.json +4 -4
- package/schemas/History.js +1 -0
- package/services/HistoryTracker.js +13 -1
- package/sql/assemblers.js +15 -5
- package/testing.d.ts +4 -1
- package/testing.js +5 -5
package/index.d.ts
CHANGED
|
@@ -1932,6 +1932,7 @@ type TestRun = typeof TestRun.Type;
|
|
|
1932
1932
|
* @public
|
|
1933
1933
|
*/
|
|
1934
1934
|
declare const TestHistory: Schema.Struct<{
|
|
1935
|
+
modulePath: typeof Schema.String;
|
|
1935
1936
|
fullName: typeof Schema.String;
|
|
1936
1937
|
runs: Schema.Array$<Schema.Struct<{
|
|
1937
1938
|
timestamp: typeof Schema.String;
|
|
@@ -1948,6 +1949,7 @@ declare const HistoryRecord: Schema.Struct<{
|
|
|
1948
1949
|
project: typeof Schema.String;
|
|
1949
1950
|
updatedAt: typeof Schema.String;
|
|
1950
1951
|
tests: Schema.Array$<Schema.Struct<{
|
|
1952
|
+
modulePath: typeof Schema.String;
|
|
1951
1953
|
fullName: typeof Schema.String;
|
|
1952
1954
|
runs: Schema.Array$<Schema.Struct<{
|
|
1953
1955
|
timestamp: typeof Schema.String;
|
|
@@ -2596,7 +2598,7 @@ declare const DataStore_base: Context.TagClass<DataStore, "vitest-agent/DataStor
|
|
|
2596
2598
|
readonly writeTestCases: (moduleId: number, tests: ReadonlyArray<TestCaseInput>) => Effect.Effect<ReadonlyArray<number>, DataStoreError>;
|
|
2597
2599
|
readonly writeErrors: (runId: number, errors: ReadonlyArray<TestErrorInput>) => Effect.Effect<void, DataStoreError>;
|
|
2598
2600
|
readonly writeCoverage: (runId: number, coverage: ReadonlyArray<FileCoverageInput>) => Effect.Effect<void, DataStoreError>;
|
|
2599
|
-
readonly writeHistory: (project: string, fullName: string, runId: number, timestamp: string, state: string, duration: number | null, flaky: boolean, retryCount: number, errorMessage: string | null) => Effect.Effect<void, DataStoreError>;
|
|
2601
|
+
readonly writeHistory: (project: string, fullName: string, modulePath: string, runId: number, timestamp: string, state: string, duration: number | null, flaky: boolean, retryCount: number, errorMessage: string | null) => Effect.Effect<void, DataStoreError>;
|
|
2600
2602
|
readonly writeBaselines: (baselines: CoverageBaselines) => Effect.Effect<void, DataStoreError>;
|
|
2601
2603
|
readonly writeTrends: (project: string, runId: number, entry: TrendEntry) => Effect.Effect<void, DataStoreError>;
|
|
2602
2604
|
readonly writeSourceMap: (sourceFilePath: string, testModuleId: number, mappingType: string) => Effect.Effect<void, DataStoreError>;
|
|
@@ -2682,6 +2684,7 @@ interface ProjectRunSummary {
|
|
|
2682
2684
|
/** @public */
|
|
2683
2685
|
interface FlakyTest {
|
|
2684
2686
|
readonly fullName: string;
|
|
2687
|
+
readonly modulePath: string;
|
|
2685
2688
|
readonly project: string;
|
|
2686
2689
|
readonly passCount: number;
|
|
2687
2690
|
readonly failCount: number;
|
|
@@ -2691,6 +2694,7 @@ interface FlakyTest {
|
|
|
2691
2694
|
/** @public */
|
|
2692
2695
|
interface PersistentFailure {
|
|
2693
2696
|
readonly fullName: string;
|
|
2697
|
+
readonly modulePath: string;
|
|
2694
2698
|
readonly project: string;
|
|
2695
2699
|
readonly consecutiveFailures: number;
|
|
2696
2700
|
readonly firstFailedAt: string;
|
|
@@ -3208,9 +3212,22 @@ declare const FormatSelectorLive: Layer.Layer<FormatSelector, never, never>;
|
|
|
3208
3212
|
* @public
|
|
3209
3213
|
*/
|
|
3210
3214
|
interface TestOutcome {
|
|
3215
|
+
readonly modulePath: string;
|
|
3211
3216
|
readonly fullName: string;
|
|
3212
3217
|
readonly state: "passed" | "failed";
|
|
3213
3218
|
}
|
|
3219
|
+
/**
|
|
3220
|
+
* Builds the composite (modulePath, fullName) key used to key the internal
|
|
3221
|
+
* testMap and the returned classifications Map, so identically-named tests
|
|
3222
|
+
* in different files classify independently instead of colliding.
|
|
3223
|
+
*
|
|
3224
|
+
* Uses `JSON.stringify` for an injective encoding: a plain delimiter such as
|
|
3225
|
+
* a space is not collision-proof (e.g. `("a b", "c")` and `("a", "b c")` would
|
|
3226
|
+
* both yield `"a b c"`), which would reintroduce the very collision class this
|
|
3227
|
+
* key exists to prevent.
|
|
3228
|
+
* @public
|
|
3229
|
+
*/
|
|
3230
|
+
declare const historyKey: (modulePath: string, fullName: string) => string;
|
|
3214
3231
|
declare const HistoryTracker_base: Context.TagClass<HistoryTracker, "vitest-agent/HistoryTracker", {
|
|
3215
3232
|
readonly classify: (project: string, testOutcomes: ReadonlyArray<TestOutcome>, timestamp: string) => Effect.Effect<{
|
|
3216
3233
|
history: HistoryRecord;
|
|
@@ -4325,12 +4342,15 @@ interface ManifestRow {
|
|
|
4325
4342
|
* @public
|
|
4326
4343
|
*/
|
|
4327
4344
|
interface HistoryRow {
|
|
4345
|
+
module_path: string;
|
|
4328
4346
|
full_name: string;
|
|
4329
4347
|
timestamp: string;
|
|
4330
4348
|
state: string;
|
|
4331
4349
|
}
|
|
4332
4350
|
/**
|
|
4333
|
-
* A `Record<
|
|
4351
|
+
* A `Record<compositeKey, { modulePath, fullName, runs: TestRun[] }>` keyed by
|
|
4352
|
+
* the injective `historyKey(modulePath, fullName)` string, so identically-named
|
|
4353
|
+
* tests in different files are tracked as distinct entries.
|
|
4334
4354
|
*
|
|
4335
4355
|
* This is the internal representation returned by `assembleHistoryRecord`.
|
|
4336
4356
|
* Callers that need the Effect Schema `HistoryRecord` type should adapt this
|
|
@@ -4338,7 +4358,9 @@ interface HistoryRow {
|
|
|
4338
4358
|
* @public
|
|
4339
4359
|
*/
|
|
4340
4360
|
interface AssembledHistoryRecord {
|
|
4341
|
-
[
|
|
4361
|
+
[compositeKey: string]: {
|
|
4362
|
+
modulePath: string;
|
|
4363
|
+
fullName: string;
|
|
4342
4364
|
runs: TestRun[];
|
|
4343
4365
|
};
|
|
4344
4366
|
}
|
|
@@ -4351,10 +4373,13 @@ interface AssembledHistoryRecord {
|
|
|
4351
4373
|
*/
|
|
4352
4374
|
declare function assembleManifest(rows: ManifestRow[], dbPath: string): CacheManifest;
|
|
4353
4375
|
/**
|
|
4354
|
-
* Groups test_history rows by
|
|
4376
|
+
* Groups test_history rows by the composite (module_path, full_name) key
|
|
4377
|
+
* into a keyed record.
|
|
4355
4378
|
*
|
|
4356
|
-
* Returns `Record<
|
|
4357
|
-
* accumulated test runs for that test, in the order
|
|
4379
|
+
* Returns `Record<compositeKey, { modulePath, fullName, runs: TestRun[] }>`
|
|
4380
|
+
* where `runs` are the accumulated test runs for that test, in the order
|
|
4381
|
+
* they appear in `rows`. Two rows sharing `full_name` but differing
|
|
4382
|
+
* `module_path` are tracked as distinct entries rather than merged.
|
|
4358
4383
|
*
|
|
4359
4384
|
* Only rows with state `"passed"` or `"failed"` are included in runs
|
|
4360
4385
|
* (matching the `TestRun` schema constraint).
|
|
@@ -5240,5 +5265,5 @@ declare function validateCoverageTargetsShape(input: unknown): CoverageTargetsSh
|
|
|
5240
5265
|
*/
|
|
5241
5266
|
declare const CURRENT_SDK_VERSION: string;
|
|
5242
5267
|
//#endregion
|
|
5243
|
-
export { AcceptanceMetrics, ActionSeverity, ActorType, Agent, AgentConsoleMode, AgentContext, AgentId, AgentNotFoundError, AgentPluginOptions, AgentReport, AgentReporterOptions, AgentTreeNode, AnsiOptions, ArtifactKind, AssembledHistoryRecord, AssociateRunSessionInput, BehaviorAbandonedEvent, BehaviorAddedEvent, BehaviorCompletedEvent, BehaviorDetail, BehaviorNotFoundError, BehaviorRow, BehaviorScopedEventType, BehaviorScopedEventTypes, BehaviorStartedEvent, BehaviorStatus, BehaviorsReadyEvent, BlockedEvent, CURRENT_SDK_VERSION, CacheManifest, CacheManifestEntry, CandidateContext, CellOptions, ChangeKind, ChannelEvent, ChatId, CiConsoleMode, CitedArtifact, CitedArtifactRow, CommitChangesEntry, ConfigLive, ConsoleFormatOptions, ConsoleLeakEntry, ConsoleLeakFile, ConsoleLeakTask, ConsoleLeaks, ConsoleLogLevel, ConsoleMode, ConsoleOutputMode, ConsoleOutputs, ConversationId, ConversationNotFoundError, CoverageBaselines, FileCoverageReport as CoverageFile, FileCoverageReport, CoverageGap, CoverageInput, CoverageLevel, CoverageLevelName, CoverageMetric, CoverageRenderState, CoverageReport, CoverageTargets, CoverageTargetsMetrics, CoverageTargetsShapeError, CoverageTargetsShapeInfo, CoverageTargetsShapeResult, CoverageTargetsShapeWarning, CoverageTotals, CreateBehaviorInput, CreateGoalInput, CurrentTddPhase, DATABASE_FILENAME, DataReader, DataReaderLive, DataStore, DataStoreError, DataStoreLive, DenialReason, DetailLevel, DetailResolver, DetailResolverLive, DiscoveryError, DiscoveryRegistry, DiscoveryRegistryLive, DispatchInputs, EndTddTaskInput, Environment, EnvironmentDetector, EnvironmentDetectorLive, EnvironmentDetectorTest, Executor, ExecutorResolver, ExecutorResolverLive, FailureRecord, FailureSignatureDetail, FailureSignatureInput, FailureSignatureWriteInput, FileCoverageInput, FileEditPayload, FileSystemAdapter, FlakyTest, FormatSelector, FormatSelectorLive, type FormatTriageOptions, type FormatWrapupOptions, Formatter, FormatterContext, FunctionBoundary, GfmFormatter, GitCommandError, GoalAbandonedEvent, GoalAddedEvent, GoalCompletedEvent, GoalDetail, GoalNotFoundError, GoalRow, GoalStartedEvent, GoalStatus, GoalsReadyEvent, HistoryRecord, HistoryRow, HistoryTracker, HistoryTrackerLive, HistoryTrackerTest, HistoryTrackerTestState, HookFirePayload, HookStatus, HookType, HostKind, HostMetadataParseError, HostMetadataResult, HumanConsoleMode, HypothesisDetail, HypothesisInput, HypothesisPayload, IDEMPOTENCY_ROOT_SENTINEL, IdempotencyHit, IdempotencyInput, IdempotentResponseInput, IllegalStatusTransitionEntity, IllegalStatusTransitionError, JsonFormatter, KnownProject, KnownProjectInput, LoggerLive, ManifestRow, MapSessionInput, MapSessionOutput, MarkdownFormatter, MetricThresholds, ModuleInput, ModuleListEntry, ModuleRecord, ModuleReport, NoteInput, NotePayload, NoteRow, Osc8Options, OutputFormat, OutputPipelineLive, OutputRenderer, OutputRendererLive, PackageManager, PathResolutionError, PathResolutionLive, PatternThresholds, PerClientSessionMapReader, PerClientSessionMapReaderLive, PerClientSessionMapWriter, PerClientSessionMapWriterLive, PersistentFailure, Phase, PhaseTransitionContext, PhaseTransitionEvent, PhaseTransitionResult, ProbeMissError, ProjectDiscovery, ProjectDiscoveryLive, ProjectDiscoveryTest, ProjectIdentity, ProjectIdentityCandidate, ProjectIdentityCandidates, ProjectIdentityLive, ProjectIdentityNotResolvableError, ProjectIdentitySource, ProjectIdentityTest, ProjectKey, ProjectRunSummary, ProjectSummary, RegisterAgentInput, RegisterAgentResult, RegistrationConflictError, Remediation, RenderState, RenderTotals, RenderedOutput, ReportError, ReportSummary, ReporterKit, ReporterRenderInput, ResolveDataPathOptions, ResolveProjectIdentityOptions, ResolvedIdentity, ResolvedReporterConfig, ResolvedThresholds, RunChangedFile, RunContext, RunContext$, RunContextLive, RunContextService, RunContextTest, RunEvent, RunEventByTag, RunHealth, RunInvocationMethod, RunOutcome, RunShape, SessionCompleteEvent, SessionContextRow, SessionDetail, SessionInput, SessionNotFoundError, SessionOutcome, SettingsInput, SettingsListEntry, SettingsRow, SidecarTimeoutError, SilentFormatter, StackFrameInput, SuggestedActionRecord, SuiteInput, SuiteListEntry, TagCountEntry, TagInventoryRow, TddArtifactDetail, TddArtifactRow, TddPhaseDetail, TddTaskAlreadyEndedError, TddTaskDetail, TddTaskEndOutcome, TddTaskId, TddTaskInput, TddTaskNotFoundError, TddTaskSummary, TerminalFormatter, TestCaseInput, TestClassification, TestError, TestErrorInput, TestFileEntry, TestHistory, TestListEntry, TestOutcome, TestRecord, TestReport, TestRun, TestRunInput, TestRunReason, TestState, ToolCallPayload, ToolResultPayload, Transport, TrendEntry, TrendRecord, TrendSummary, TurnInput, TurnPayload, TurnSearchOptions, TurnSummary, UpdateBehaviorInput, UpdateGoalInput, UserPromptPayload, ValidateHypothesisInput, VitestAgentConfig, VitestAgentConfigFile, VitestAgentConfigFileService, VitestAgentReporter, VitestAgentReporterFactory, VitestModuleDiagnostic, VitestModuleError, VitestParsedStack, VitestTestCase, VitestTestDiagnostic, VitestTestError, VitestTestModule, VitestTestResult, VitestTestSuite, type WrapupKind, WriteCommitInput, WriteRunChangedFilesInput, WriteTddArtifactInput, WriteTddPhaseInput, WriteTddPhaseOutput, _resetMigrationCacheForTesting, ansi, assembleHistoryRecord, assembleManifest, buildAgentReport, buildConsoleLeaks, buildEnvPrefix, canonicalizeGitUrl, ciAnnotationsFormatter, classifyTest, collectConsoleLeakEntries, compressLines, computeFailureSignature, computeTrend, deriveIdempotencyKey, detectPackageManager, detectVitestScripts, determineTier, ensureMigrated, extractSqlReason, findFunctionBoundary, formatConsoleMarkdown, formatFatalError, formatGfm, formatTriageEffect, formatWrapupEffect, getRecentDirection, getRunCommand, getWorstMetric, gitUrlToProjectKey, hashTargets, initialRenderState, isTimeoutError, isVitestInvocation, migration as migration0001, normalizeAssertionShape, normalizeWorkspaceKey, osc8, probeHostMetadataFromEnv, migration$1 as registryMigration0001, relativePath, requiredArtifactForTransition, resolveCoverageInput, resolveDataPath, resolveLogFile, resolveLogLevel, resolveProjectIdentityFromCandidates, resolveProjectKeyFromCwd, resolveWorkspaceKey, rewriteBashCommand, safeFilename, migration$2 as sessionMapMigration0001, stripAnsi, transitionEnforcesBehaviorMatch, validateCoverageConfig, validateCoverageTargetsShape, validatePhaseTransition };
|
|
5268
|
+
export { AcceptanceMetrics, ActionSeverity, ActorType, Agent, AgentConsoleMode, AgentContext, AgentId, AgentNotFoundError, AgentPluginOptions, AgentReport, AgentReporterOptions, AgentTreeNode, AnsiOptions, ArtifactKind, AssembledHistoryRecord, AssociateRunSessionInput, BehaviorAbandonedEvent, BehaviorAddedEvent, BehaviorCompletedEvent, BehaviorDetail, BehaviorNotFoundError, BehaviorRow, BehaviorScopedEventType, BehaviorScopedEventTypes, BehaviorStartedEvent, BehaviorStatus, BehaviorsReadyEvent, BlockedEvent, CURRENT_SDK_VERSION, CacheManifest, CacheManifestEntry, CandidateContext, CellOptions, ChangeKind, ChannelEvent, ChatId, CiConsoleMode, CitedArtifact, CitedArtifactRow, CommitChangesEntry, ConfigLive, ConsoleFormatOptions, ConsoleLeakEntry, ConsoleLeakFile, ConsoleLeakTask, ConsoleLeaks, ConsoleLogLevel, ConsoleMode, ConsoleOutputMode, ConsoleOutputs, ConversationId, ConversationNotFoundError, CoverageBaselines, FileCoverageReport as CoverageFile, FileCoverageReport, CoverageGap, CoverageInput, CoverageLevel, CoverageLevelName, CoverageMetric, CoverageRenderState, CoverageReport, CoverageTargets, CoverageTargetsMetrics, CoverageTargetsShapeError, CoverageTargetsShapeInfo, CoverageTargetsShapeResult, CoverageTargetsShapeWarning, CoverageTotals, CreateBehaviorInput, CreateGoalInput, CurrentTddPhase, DATABASE_FILENAME, DataReader, DataReaderLive, DataStore, DataStoreError, DataStoreLive, DenialReason, DetailLevel, DetailResolver, DetailResolverLive, DiscoveryError, DiscoveryRegistry, DiscoveryRegistryLive, DispatchInputs, EndTddTaskInput, Environment, EnvironmentDetector, EnvironmentDetectorLive, EnvironmentDetectorTest, Executor, ExecutorResolver, ExecutorResolverLive, FailureRecord, FailureSignatureDetail, FailureSignatureInput, FailureSignatureWriteInput, FileCoverageInput, FileEditPayload, FileSystemAdapter, FlakyTest, FormatSelector, FormatSelectorLive, type FormatTriageOptions, type FormatWrapupOptions, Formatter, FormatterContext, FunctionBoundary, GfmFormatter, GitCommandError, GoalAbandonedEvent, GoalAddedEvent, GoalCompletedEvent, GoalDetail, GoalNotFoundError, GoalRow, GoalStartedEvent, GoalStatus, GoalsReadyEvent, HistoryRecord, HistoryRow, HistoryTracker, HistoryTrackerLive, HistoryTrackerTest, HistoryTrackerTestState, HookFirePayload, HookStatus, HookType, HostKind, HostMetadataParseError, HostMetadataResult, HumanConsoleMode, HypothesisDetail, HypothesisInput, HypothesisPayload, IDEMPOTENCY_ROOT_SENTINEL, IdempotencyHit, IdempotencyInput, IdempotentResponseInput, IllegalStatusTransitionEntity, IllegalStatusTransitionError, JsonFormatter, KnownProject, KnownProjectInput, LoggerLive, ManifestRow, MapSessionInput, MapSessionOutput, MarkdownFormatter, MetricThresholds, ModuleInput, ModuleListEntry, ModuleRecord, ModuleReport, NoteInput, NotePayload, NoteRow, Osc8Options, OutputFormat, OutputPipelineLive, OutputRenderer, OutputRendererLive, PackageManager, PathResolutionError, PathResolutionLive, PatternThresholds, PerClientSessionMapReader, PerClientSessionMapReaderLive, PerClientSessionMapWriter, PerClientSessionMapWriterLive, PersistentFailure, Phase, PhaseTransitionContext, PhaseTransitionEvent, PhaseTransitionResult, ProbeMissError, ProjectDiscovery, ProjectDiscoveryLive, ProjectDiscoveryTest, ProjectIdentity, ProjectIdentityCandidate, ProjectIdentityCandidates, ProjectIdentityLive, ProjectIdentityNotResolvableError, ProjectIdentitySource, ProjectIdentityTest, ProjectKey, ProjectRunSummary, ProjectSummary, RegisterAgentInput, RegisterAgentResult, RegistrationConflictError, Remediation, RenderState, RenderTotals, RenderedOutput, ReportError, ReportSummary, ReporterKit, ReporterRenderInput, ResolveDataPathOptions, ResolveProjectIdentityOptions, ResolvedIdentity, ResolvedReporterConfig, ResolvedThresholds, RunChangedFile, RunContext, RunContext$, RunContextLive, RunContextService, RunContextTest, RunEvent, RunEventByTag, RunHealth, RunInvocationMethod, RunOutcome, RunShape, SessionCompleteEvent, SessionContextRow, SessionDetail, SessionInput, SessionNotFoundError, SessionOutcome, SettingsInput, SettingsListEntry, SettingsRow, SidecarTimeoutError, SilentFormatter, StackFrameInput, SuggestedActionRecord, SuiteInput, SuiteListEntry, TagCountEntry, TagInventoryRow, TddArtifactDetail, TddArtifactRow, TddPhaseDetail, TddTaskAlreadyEndedError, TddTaskDetail, TddTaskEndOutcome, TddTaskId, TddTaskInput, TddTaskNotFoundError, TddTaskSummary, TerminalFormatter, TestCaseInput, TestClassification, TestError, TestErrorInput, TestFileEntry, TestHistory, TestListEntry, TestOutcome, TestRecord, TestReport, TestRun, TestRunInput, TestRunReason, TestState, ToolCallPayload, ToolResultPayload, Transport, TrendEntry, TrendRecord, TrendSummary, TurnInput, TurnPayload, TurnSearchOptions, TurnSummary, UpdateBehaviorInput, UpdateGoalInput, UserPromptPayload, ValidateHypothesisInput, VitestAgentConfig, VitestAgentConfigFile, VitestAgentConfigFileService, VitestAgentReporter, VitestAgentReporterFactory, VitestModuleDiagnostic, VitestModuleError, VitestParsedStack, VitestTestCase, VitestTestDiagnostic, VitestTestError, VitestTestModule, VitestTestResult, VitestTestSuite, type WrapupKind, WriteCommitInput, WriteRunChangedFilesInput, WriteTddArtifactInput, WriteTddPhaseInput, WriteTddPhaseOutput, _resetMigrationCacheForTesting, ansi, assembleHistoryRecord, assembleManifest, buildAgentReport, buildConsoleLeaks, buildEnvPrefix, canonicalizeGitUrl, ciAnnotationsFormatter, classifyTest, collectConsoleLeakEntries, compressLines, computeFailureSignature, computeTrend, deriveIdempotencyKey, detectPackageManager, detectVitestScripts, determineTier, ensureMigrated, extractSqlReason, findFunctionBoundary, formatConsoleMarkdown, formatFatalError, formatGfm, formatTriageEffect, formatWrapupEffect, getRecentDirection, getRunCommand, getWorstMetric, gitUrlToProjectKey, hashTargets, historyKey, initialRenderState, isTimeoutError, isVitestInvocation, migration as migration0001, normalizeAssertionShape, normalizeWorkspaceKey, osc8, probeHostMetadataFromEnv, migration$1 as registryMigration0001, relativePath, requiredArtifactForTransition, resolveCoverageInput, resolveDataPath, resolveLogFile, resolveLogLevel, resolveProjectIdentityFromCandidates, resolveProjectKeyFromCwd, resolveWorkspaceKey, rewriteBashCommand, safeFilename, migration$2 as sessionMapMigration0001, stripAnsi, transitionEnforcesBehaviorMatch, validateCoverageConfig, validateCoverageTargetsShape, validatePhaseTransition };
|
|
5244
5269
|
//# sourceMappingURL=index.d.ts.map
|
package/index.js
CHANGED
|
@@ -20,6 +20,7 @@ import { VitestAgentConfig } from "./schemas/Config.js";
|
|
|
20
20
|
import { VitestAgentConfigFile } from "./services/Config.js";
|
|
21
21
|
import { ConfigLive } from "./layers/ConfigLive.js";
|
|
22
22
|
import { DataReader } from "./services/DataReader.js";
|
|
23
|
+
import { HistoryTracker, historyKey } from "./services/HistoryTracker.js";
|
|
23
24
|
import { DataReaderLive } from "./layers/DataReaderLive.js";
|
|
24
25
|
import { ActorType, AgentId, ChatId, ConversationId, HostKind, ProjectKey, TddTaskId } from "./schemas/Identity.js";
|
|
25
26
|
import { Agent, IdempotencyHit } from "./schemas/Agent.js";
|
|
@@ -36,7 +37,6 @@ import { ExecutorResolver } from "./services/ExecutorResolver.js";
|
|
|
36
37
|
import { ExecutorResolverLive } from "./layers/ExecutorResolverLive.js";
|
|
37
38
|
import { FormatSelector } from "./services/FormatSelector.js";
|
|
38
39
|
import { FormatSelectorLive } from "./layers/FormatSelectorLive.js";
|
|
39
|
-
import { HistoryTracker } from "./services/HistoryTracker.js";
|
|
40
40
|
import { classifyTest } from "./utils/classify-test.js";
|
|
41
41
|
import { HistoryTrackerLive } from "./layers/HistoryTrackerLive.js";
|
|
42
42
|
import { HistoryTrackerTest } from "./layers/HistoryTrackerTest.js";
|
|
@@ -115,7 +115,7 @@ import { requiredArtifactForTransition, transitionEnforcesBehaviorMatch, validat
|
|
|
115
115
|
* substituted yet. Exported for version introspection by downstream tooling.
|
|
116
116
|
* @public
|
|
117
117
|
*/
|
|
118
|
-
const CURRENT_SDK_VERSION = "1.
|
|
118
|
+
const CURRENT_SDK_VERSION = "1.3.0";
|
|
119
119
|
|
|
120
120
|
//#endregion
|
|
121
|
-
export { ActionSeverity, ActorType, Agent, AgentConsoleMode, AgentContext, AgentId, AgentNotFoundError, AgentPluginOptions, AgentReport, AgentReporterOptions, BehaviorAbandonedEvent, BehaviorAddedEvent, BehaviorCompletedEvent, BehaviorDetail, BehaviorNotFoundError, BehaviorRow, BehaviorScopedEventTypes, BehaviorStartedEvent, BehaviorStatus, BehaviorsReadyEvent, BlockedEvent, CURRENT_SDK_VERSION, CacheManifest, CacheManifestEntry, ChannelEvent, ChatId, CiConsoleMode, ConfigLive, ConsoleLeakFile, ConsoleLeaks, ConsoleLogLevel, ConsoleMode, ConsoleOutputMode, ConsoleOutputs, ConversationId, ConversationNotFoundError, CoverageBaselines, FileCoverageReport as CoverageFile, CoverageGap, CoverageLevel, CoverageMetric, CoverageRenderState, CoverageReport, CoverageTargets, CoverageTargetsMetrics, CoverageTotals, DATABASE_FILENAME, DataReader, DataReaderLive, DataStore, DataStoreError, DataStoreLive, DetailLevel, DetailResolver, DetailResolverLive, DiscoveryError, DiscoveryRegistry, DiscoveryRegistryLive, Environment, EnvironmentDetector, EnvironmentDetectorLive, EnvironmentDetectorTest, Executor, ExecutorResolver, ExecutorResolverLive, FailureRecord, FileCoverageReport, FileEditPayload, FormatSelector, FormatSelectorLive, GfmFormatter, GitCommandError, GoalAbandonedEvent, GoalAddedEvent, GoalCompletedEvent, GoalDetail, GoalNotFoundError, GoalRow, GoalStartedEvent, GoalStatus, GoalsReadyEvent, HistoryRecord, HistoryTracker, HistoryTrackerLive, HistoryTrackerTest, HookFirePayload, HookStatus, HookType, HostKind, HostMetadataParseError, HumanConsoleMode, HypothesisPayload, IDEMPOTENCY_ROOT_SENTINEL, IdempotencyHit, IllegalStatusTransitionError, JsonFormatter, LoggerLive, MarkdownFormatter, MetricThresholds, ModuleRecord, ModuleReport, NotePayload, OutputFormat, OutputPipelineLive, OutputRenderer, OutputRendererLive, PackageManager, PathResolutionError, PathResolutionLive, PatternThresholds, PerClientSessionMapReader, PerClientSessionMapReaderLive, PerClientSessionMapWriter, PerClientSessionMapWriterLive, PhaseTransitionEvent, ProbeMissError, ProjectDiscovery, ProjectDiscoveryLive, ProjectDiscoveryTest, ProjectIdentity, ProjectIdentityLive, ProjectIdentityNotResolvableError, ProjectIdentityTest, ProjectKey, RegistrationConflictError, RenderState, RenderTotals, ReportError, ReportSummary, ResolvedThresholds, RunContext, RunContext$, RunContextLive, RunContextService, RunContextTest, RunEvent, SessionCompleteEvent, SessionNotFoundError, SessionOutcome, SidecarTimeoutError, SilentFormatter, SuggestedActionRecord, TagCountEntry, TddTaskAlreadyEndedError, TddTaskId, TddTaskNotFoundError, TerminalFormatter, TestClassification, TestHistory, TestRecord, TestReport, TestRun, TestRunReason, TestState, ToolCallPayload, ToolResultPayload, Transport, TrendEntry, TrendRecord, TurnPayload, UserPromptPayload, VitestAgentConfig, VitestAgentConfigFile, _resetMigrationCacheForTesting, ansi, assembleHistoryRecord, assembleManifest, buildAgentReport, buildConsoleLeaks, buildEnvPrefix, canonicalizeGitUrl, ciAnnotationsFormatter, classifyTest, collectConsoleLeakEntries, compressLines, computeFailureSignature, computeTrend, deriveIdempotencyKey, detectPackageManager, detectVitestScripts, determineTier, ensureMigrated, extractSqlReason, findFunctionBoundary, formatConsoleMarkdown, formatFatalError, formatGfm, formatTriageEffect, formatWrapupEffect, getRecentDirection, getRunCommand, getWorstMetric, gitUrlToProjectKey, hashTargets, initialRenderState, isTimeoutError, isVitestInvocation, migration as migration0001, normalizeAssertionShape, normalizeWorkspaceKey, osc8, probeHostMetadataFromEnv, migration$1 as registryMigration0001, relativePath, requiredArtifactForTransition, resolveCoverageInput, resolveDataPath, resolveLogFile, resolveLogLevel, resolveProjectIdentityFromCandidates, resolveProjectKeyFromCwd, resolveWorkspaceKey, rewriteBashCommand, safeFilename, migration$2 as sessionMapMigration0001, stripAnsi, transitionEnforcesBehaviorMatch, validateCoverageConfig, validateCoverageTargetsShape, validatePhaseTransition };
|
|
121
|
+
export { ActionSeverity, ActorType, Agent, AgentConsoleMode, AgentContext, AgentId, AgentNotFoundError, AgentPluginOptions, AgentReport, AgentReporterOptions, BehaviorAbandonedEvent, BehaviorAddedEvent, BehaviorCompletedEvent, BehaviorDetail, BehaviorNotFoundError, BehaviorRow, BehaviorScopedEventTypes, BehaviorStartedEvent, BehaviorStatus, BehaviorsReadyEvent, BlockedEvent, CURRENT_SDK_VERSION, CacheManifest, CacheManifestEntry, ChannelEvent, ChatId, CiConsoleMode, ConfigLive, ConsoleLeakFile, ConsoleLeaks, ConsoleLogLevel, ConsoleMode, ConsoleOutputMode, ConsoleOutputs, ConversationId, ConversationNotFoundError, CoverageBaselines, FileCoverageReport as CoverageFile, CoverageGap, CoverageLevel, CoverageMetric, CoverageRenderState, CoverageReport, CoverageTargets, CoverageTargetsMetrics, CoverageTotals, DATABASE_FILENAME, DataReader, DataReaderLive, DataStore, DataStoreError, DataStoreLive, DetailLevel, DetailResolver, DetailResolverLive, DiscoveryError, DiscoveryRegistry, DiscoveryRegistryLive, Environment, EnvironmentDetector, EnvironmentDetectorLive, EnvironmentDetectorTest, Executor, ExecutorResolver, ExecutorResolverLive, FailureRecord, FileCoverageReport, FileEditPayload, FormatSelector, FormatSelectorLive, GfmFormatter, GitCommandError, GoalAbandonedEvent, GoalAddedEvent, GoalCompletedEvent, GoalDetail, GoalNotFoundError, GoalRow, GoalStartedEvent, GoalStatus, GoalsReadyEvent, HistoryRecord, HistoryTracker, HistoryTrackerLive, HistoryTrackerTest, HookFirePayload, HookStatus, HookType, HostKind, HostMetadataParseError, HumanConsoleMode, HypothesisPayload, IDEMPOTENCY_ROOT_SENTINEL, IdempotencyHit, IllegalStatusTransitionError, JsonFormatter, LoggerLive, MarkdownFormatter, MetricThresholds, ModuleRecord, ModuleReport, NotePayload, OutputFormat, OutputPipelineLive, OutputRenderer, OutputRendererLive, PackageManager, PathResolutionError, PathResolutionLive, PatternThresholds, PerClientSessionMapReader, PerClientSessionMapReaderLive, PerClientSessionMapWriter, PerClientSessionMapWriterLive, PhaseTransitionEvent, ProbeMissError, ProjectDiscovery, ProjectDiscoveryLive, ProjectDiscoveryTest, ProjectIdentity, ProjectIdentityLive, ProjectIdentityNotResolvableError, ProjectIdentityTest, ProjectKey, RegistrationConflictError, RenderState, RenderTotals, ReportError, ReportSummary, ResolvedThresholds, RunContext, RunContext$, RunContextLive, RunContextService, RunContextTest, RunEvent, SessionCompleteEvent, SessionNotFoundError, SessionOutcome, SidecarTimeoutError, SilentFormatter, SuggestedActionRecord, TagCountEntry, TddTaskAlreadyEndedError, TddTaskId, TddTaskNotFoundError, TerminalFormatter, TestClassification, TestHistory, TestRecord, TestReport, TestRun, TestRunReason, TestState, ToolCallPayload, ToolResultPayload, Transport, TrendEntry, TrendRecord, TurnPayload, UserPromptPayload, VitestAgentConfig, VitestAgentConfigFile, _resetMigrationCacheForTesting, ansi, assembleHistoryRecord, assembleManifest, buildAgentReport, buildConsoleLeaks, buildEnvPrefix, canonicalizeGitUrl, ciAnnotationsFormatter, classifyTest, collectConsoleLeakEntries, compressLines, computeFailureSignature, computeTrend, deriveIdempotencyKey, detectPackageManager, detectVitestScripts, determineTier, ensureMigrated, extractSqlReason, findFunctionBoundary, formatConsoleMarkdown, formatFatalError, formatGfm, formatTriageEffect, formatWrapupEffect, getRecentDirection, getRunCommand, getWorstMetric, gitUrlToProjectKey, hashTargets, historyKey, initialRenderState, isTimeoutError, isVitestInvocation, migration as migration0001, normalizeAssertionShape, normalizeWorkspaceKey, osc8, probeHostMetadataFromEnv, migration$1 as registryMigration0001, relativePath, requiredArtifactForTransition, resolveCoverageInput, resolveDataPath, resolveLogFile, resolveLogLevel, resolveProjectIdentityFromCandidates, resolveProjectKeyFromCwd, resolveWorkspaceKey, rewriteBashCommand, safeFilename, migration$2 as sessionMapMigration0001, stripAnsi, transitionEnforcesBehaviorMatch, validateCoverageConfig, validateCoverageTargetsShape, validatePhaseTransition };
|
package/layers/DataReaderLive.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DataStoreError, extractSqlReason } from "../errors/DataStoreError.js";
|
|
2
2
|
import { DataReader } from "../services/DataReader.js";
|
|
3
|
+
import { historyKey } from "../services/HistoryTracker.js";
|
|
3
4
|
import { Effect, Layer, Option } from "effect";
|
|
4
5
|
import { SqlClient } from "@effect/sql/SqlClient";
|
|
5
6
|
|
|
@@ -195,24 +196,30 @@ const DataReaderLive = Layer.effect(DataReader, Effect.gen(function* () {
|
|
|
195
196
|
})));
|
|
196
197
|
const getHistory = (project) => Effect.gen(function* () {
|
|
197
198
|
yield* Effect.logDebug("getHistory").pipe(Effect.annotateLogs({ project }));
|
|
198
|
-
const rows = yield* sql`SELECT full_name, timestamp, state
|
|
199
|
+
const rows = yield* sql`SELECT module_path, full_name, timestamp, state
|
|
199
200
|
FROM test_history
|
|
200
201
|
WHERE project = ${project}
|
|
201
|
-
ORDER BY full_name, timestamp DESC`;
|
|
202
|
+
ORDER BY module_path, full_name, timestamp DESC`;
|
|
202
203
|
const testsMap = /* @__PURE__ */ new Map();
|
|
203
204
|
for (const row of rows) {
|
|
204
205
|
if (row.state !== "passed" && row.state !== "failed") continue;
|
|
205
|
-
const
|
|
206
|
-
|
|
206
|
+
const key = historyKey(row.module_path, row.full_name);
|
|
207
|
+
const existing = testsMap.get(key);
|
|
208
|
+
if (existing) existing.runs.push({
|
|
207
209
|
timestamp: row.timestamp,
|
|
208
210
|
state: row.state
|
|
209
211
|
});
|
|
210
|
-
else testsMap.set(
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
212
|
+
else testsMap.set(key, {
|
|
213
|
+
modulePath: row.module_path,
|
|
214
|
+
fullName: row.full_name,
|
|
215
|
+
runs: [{
|
|
216
|
+
timestamp: row.timestamp,
|
|
217
|
+
state: row.state
|
|
218
|
+
}]
|
|
219
|
+
});
|
|
214
220
|
}
|
|
215
|
-
const tests = Array.from(testsMap.
|
|
221
|
+
const tests = Array.from(testsMap.values()).map(({ modulePath, fullName, runs }) => ({
|
|
222
|
+
modulePath,
|
|
216
223
|
fullName,
|
|
217
224
|
runs
|
|
218
225
|
}));
|
|
@@ -307,27 +314,31 @@ const DataReaderLive = Layer.effect(DataReader, Effect.gen(function* () {
|
|
|
307
314
|
yield* Effect.logDebug("getFlaky").pipe(Effect.annotateLogs({ project }));
|
|
308
315
|
return (yield* sql`SELECT
|
|
309
316
|
th1.full_name,
|
|
317
|
+
th1.module_path,
|
|
310
318
|
th1.project,
|
|
311
319
|
SUM(CASE WHEN th1.state = 'passed' THEN 1 ELSE 0 END) as pass_count,
|
|
312
320
|
SUM(CASE WHEN th1.state = 'failed' THEN 1 ELSE 0 END) as fail_count,
|
|
313
321
|
(SELECT state FROM test_history th2
|
|
314
322
|
WHERE th2.full_name = th1.full_name
|
|
323
|
+
AND th2.module_path = th1.module_path
|
|
315
324
|
AND th2.project = th1.project
|
|
316
325
|
ORDER BY timestamp DESC LIMIT 1) as last_state,
|
|
317
326
|
MAX(th1.timestamp) as last_timestamp
|
|
318
327
|
FROM test_history th1
|
|
319
328
|
WHERE th1.project = ${project}
|
|
320
|
-
GROUP BY th1.full_name, th1.project
|
|
329
|
+
GROUP BY th1.full_name, th1.module_path, th1.project
|
|
321
330
|
-- Flaky means oscillation, not a clean recovery. A test with both
|
|
322
331
|
-- passes and fails is only flaky when at least one failure occurs at
|
|
323
332
|
-- or after the earliest pass (a fail-after-pass regression). A
|
|
324
333
|
-- monotonic red->green cycle — every failure precedes every pass — is
|
|
325
334
|
-- a recovery, not flakiness, so it is excluded here. ISO-8601
|
|
326
|
-
-- timestamps compare lexicographically.
|
|
335
|
+
-- timestamps compare lexicographically. Grouping keys on module_path
|
|
336
|
+
-- so same-named tests in different files stay distinct series.
|
|
327
337
|
HAVING pass_count > 0 AND fail_count > 0
|
|
328
338
|
AND MAX(CASE WHEN th1.state = 'failed' THEN th1.timestamp END)
|
|
329
339
|
>= MIN(CASE WHEN th1.state = 'passed' THEN th1.timestamp END)`).map((r) => ({
|
|
330
340
|
fullName: r.full_name,
|
|
341
|
+
modulePath: r.module_path,
|
|
331
342
|
project: r.project,
|
|
332
343
|
passCount: r.pass_count,
|
|
333
344
|
failCount: r.fail_count,
|
|
@@ -342,36 +353,38 @@ const DataReaderLive = Layer.effect(DataReader, Effect.gen(function* () {
|
|
|
342
353
|
const getPersistentFailures = (project) => Effect.gen(function* () {
|
|
343
354
|
yield* Effect.logDebug("getPersistentFailures").pipe(Effect.annotateLogs({ project }));
|
|
344
355
|
return (yield* sql`WITH ranked AS (
|
|
345
|
-
SELECT full_name, project, state, timestamp, error_message,
|
|
356
|
+
SELECT full_name, module_path, project, state, timestamp, error_message,
|
|
346
357
|
ROW_NUMBER() OVER (
|
|
347
|
-
PARTITION BY project, full_name
|
|
358
|
+
PARTITION BY project, module_path, full_name
|
|
348
359
|
ORDER BY timestamp DESC
|
|
349
360
|
) as rn
|
|
350
361
|
FROM test_history
|
|
351
362
|
WHERE project = ${project}
|
|
352
363
|
),
|
|
353
364
|
streak AS (
|
|
354
|
-
SELECT full_name, project, state, timestamp, error_message, rn,
|
|
365
|
+
SELECT full_name, module_path, project, state, timestamp, error_message, rn,
|
|
355
366
|
MIN(CASE WHEN state != 'failed' THEN rn END) OVER (
|
|
356
|
-
PARTITION BY project, full_name
|
|
367
|
+
PARTITION BY project, module_path, full_name
|
|
357
368
|
) as first_pass_rn
|
|
358
369
|
FROM ranked
|
|
359
370
|
)
|
|
360
371
|
SELECT
|
|
361
|
-
full_name, project,
|
|
372
|
+
full_name, module_path, project,
|
|
362
373
|
COUNT(*) as consecutive_failures,
|
|
363
374
|
MIN(timestamp) as first_failed_at,
|
|
364
375
|
MAX(timestamp) as last_failed_at,
|
|
365
376
|
(SELECT error_message FROM streak s2
|
|
366
377
|
WHERE s2.full_name = streak.full_name
|
|
378
|
+
AND s2.module_path = streak.module_path
|
|
367
379
|
AND s2.project = streak.project
|
|
368
380
|
AND s2.rn = 1) as last_error_message
|
|
369
381
|
FROM streak
|
|
370
382
|
WHERE state = 'failed'
|
|
371
383
|
AND (first_pass_rn IS NULL OR rn < first_pass_rn)
|
|
372
|
-
GROUP BY full_name, project
|
|
384
|
+
GROUP BY full_name, module_path, project
|
|
373
385
|
HAVING consecutive_failures >= 2`).map((row) => ({
|
|
374
386
|
fullName: row.full_name,
|
|
387
|
+
modulePath: row.module_path,
|
|
375
388
|
project: row.project,
|
|
376
389
|
consecutiveFailures: row.consecutive_failures,
|
|
377
390
|
firstFailedAt: row.first_failed_at,
|
package/layers/DataStoreLive.js
CHANGED
|
@@ -174,13 +174,14 @@ const DataStoreLive = Layer.effect(DataStore, Effect.gen(function* () {
|
|
|
174
174
|
table: "file_coverage",
|
|
175
175
|
reason: extractSqlReason(e)
|
|
176
176
|
})));
|
|
177
|
-
const writeHistory = (project, fullName, runId, timestamp, state, duration, flaky, retryCount, errorMessage) => Effect.gen(function* () {
|
|
177
|
+
const writeHistory = (project, fullName, modulePath, runId, timestamp, state, duration, flaky, retryCount, errorMessage) => Effect.gen(function* () {
|
|
178
178
|
yield* Effect.logDebug("writeHistory").pipe(Effect.annotateLogs({
|
|
179
179
|
project,
|
|
180
|
+
modulePath,
|
|
180
181
|
runId
|
|
181
182
|
}));
|
|
182
|
-
yield* sql`INSERT INTO test_history (run_id, project, full_name, timestamp, state, duration, flaky, retry_count, error_message) VALUES (${runId}, ${project}, ${fullName}, ${timestamp}, ${state}, ${duration}, ${flaky ? 1 : 0}, ${retryCount}, ${errorMessage})`;
|
|
183
|
-
yield* sql`DELETE FROM test_history WHERE id NOT IN (SELECT id FROM test_history WHERE project = ${project} AND full_name = ${fullName} ORDER BY timestamp DESC LIMIT 10) AND project = ${project} AND full_name = ${fullName}`;
|
|
183
|
+
yield* sql`INSERT INTO test_history (run_id, project, module_path, full_name, timestamp, state, duration, flaky, retry_count, error_message) VALUES (${runId}, ${project}, ${modulePath}, ${fullName}, ${timestamp}, ${state}, ${duration}, ${flaky ? 1 : 0}, ${retryCount}, ${errorMessage})`;
|
|
184
|
+
yield* sql`DELETE FROM test_history WHERE id NOT IN (SELECT id FROM test_history WHERE project = ${project} AND module_path = ${modulePath} AND full_name = ${fullName} ORDER BY timestamp DESC LIMIT 10) AND project = ${project} AND module_path = ${modulePath} AND full_name = ${fullName}`;
|
|
184
185
|
}).pipe(Effect.annotateLogs("service", "DataStore"), Effect.mapError((e) => new DataStoreError({
|
|
185
186
|
operation: "write",
|
|
186
187
|
table: "test_history",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DataReader } from "../services/DataReader.js";
|
|
2
|
-
import { HistoryTracker } from "../services/HistoryTracker.js";
|
|
2
|
+
import { HistoryTracker, historyKey } from "../services/HistoryTracker.js";
|
|
3
3
|
import { classifyTest } from "../utils/classify-test.js";
|
|
4
4
|
import { Effect, Layer } from "effect";
|
|
5
5
|
|
|
@@ -11,26 +11,28 @@ const HistoryTrackerLive = Layer.effect(HistoryTracker, Effect.gen(function* ()
|
|
|
11
11
|
return { classify: (project, testOutcomes, timestamp) => Effect.gen(function* () {
|
|
12
12
|
const existing = yield* reader.getHistory(project);
|
|
13
13
|
const testMap = /* @__PURE__ */ new Map();
|
|
14
|
-
for (const entry of existing.tests) testMap.set(entry.fullName, {
|
|
14
|
+
for (const entry of existing.tests) testMap.set(historyKey(entry.modulePath, entry.fullName), {
|
|
15
15
|
...entry,
|
|
16
16
|
runs: [...entry.runs]
|
|
17
17
|
});
|
|
18
18
|
const classifications = /* @__PURE__ */ new Map();
|
|
19
19
|
for (const outcome of testOutcomes) {
|
|
20
|
-
|
|
20
|
+
const key = historyKey(outcome.modulePath, outcome.fullName);
|
|
21
|
+
let entry = testMap.get(key);
|
|
21
22
|
if (!entry) {
|
|
22
23
|
entry = {
|
|
24
|
+
modulePath: outcome.modulePath,
|
|
23
25
|
fullName: outcome.fullName,
|
|
24
26
|
runs: []
|
|
25
27
|
};
|
|
26
|
-
testMap.set(
|
|
28
|
+
testMap.set(key, entry);
|
|
27
29
|
}
|
|
28
30
|
const priorRuns = entry.runs;
|
|
29
31
|
entry.runs = [{
|
|
30
32
|
timestamp,
|
|
31
33
|
state: outcome.state
|
|
32
34
|
}, ...priorRuns].slice(0, WINDOW_SIZE);
|
|
33
|
-
classifications.set(
|
|
35
|
+
classifications.set(key, classifyTest(outcome.state, priorRuns));
|
|
34
36
|
}
|
|
35
37
|
return {
|
|
36
38
|
history: {
|
|
@@ -352,6 +352,7 @@ const migration = Effect.gen(function* () {
|
|
|
352
352
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
353
353
|
run_id INTEGER NOT NULL REFERENCES test_runs(id) ON DELETE CASCADE,
|
|
354
354
|
project TEXT NOT NULL,
|
|
355
|
+
module_path TEXT NOT NULL,
|
|
355
356
|
full_name TEXT NOT NULL,
|
|
356
357
|
timestamp TEXT NOT NULL,
|
|
357
358
|
state TEXT NOT NULL CHECK (state IN ('passed', 'failed', 'skipped', 'pending')),
|
|
@@ -359,10 +360,10 @@ const migration = Effect.gen(function* () {
|
|
|
359
360
|
flaky INTEGER CHECK (flaky IN (0, 1)),
|
|
360
361
|
retry_count INTEGER DEFAULT 0,
|
|
361
362
|
error_message TEXT,
|
|
362
|
-
UNIQUE(project, full_name, timestamp)
|
|
363
|
+
UNIQUE(project, module_path, full_name, timestamp)
|
|
363
364
|
)
|
|
364
365
|
`;
|
|
365
|
-
yield* sql`CREATE INDEX idx_test_history_lookup ON test_history(project, full_name)`;
|
|
366
|
+
yield* sql`CREATE INDEX idx_test_history_lookup ON test_history(project, module_path, full_name)`;
|
|
366
367
|
yield* sql`CREATE INDEX idx_test_history_full_name ON test_history(full_name, timestamp)`;
|
|
367
368
|
yield* sql`CREATE INDEX idx_test_history_run ON test_history(run_id)`;
|
|
368
369
|
yield* sql`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitest-agent/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Shared Effect Schema, SQLite migrations, data layer, services, formatters, and utilities for vitest-agent packages.",
|
|
6
6
|
"keywords": [
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
"acorn": "^8.17.0",
|
|
53
53
|
"acorn-typescript": "^1.4.13",
|
|
54
54
|
"ajv": "^8.20.0",
|
|
55
|
-
"config-file-effect": "^0.
|
|
55
|
+
"config-file-effect": "^0.3.0",
|
|
56
56
|
"effect": "^3.21.4",
|
|
57
57
|
"std-env": "^4.1.0",
|
|
58
|
-
"workspaces-effect": "^1.
|
|
59
|
-
"xdg-effect": "^2.0
|
|
58
|
+
"workspaces-effect": "^1.3.0",
|
|
59
|
+
"xdg-effect": "^2.1.0"
|
|
60
60
|
},
|
|
61
61
|
"engines": {
|
|
62
62
|
"node": ">=24.11.0"
|
package/schemas/History.js
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import { Context } from "effect";
|
|
2
2
|
|
|
3
3
|
//#region src/services/HistoryTracker.ts
|
|
4
|
+
/**
|
|
5
|
+
* Builds the composite (modulePath, fullName) key used to key the internal
|
|
6
|
+
* testMap and the returned classifications Map, so identically-named tests
|
|
7
|
+
* in different files classify independently instead of colliding.
|
|
8
|
+
*
|
|
9
|
+
* Uses `JSON.stringify` for an injective encoding: a plain delimiter such as
|
|
10
|
+
* a space is not collision-proof (e.g. `("a b", "c")` and `("a", "b c")` would
|
|
11
|
+
* both yield `"a b c"`), which would reintroduce the very collision class this
|
|
12
|
+
* key exists to prevent.
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
const historyKey = (modulePath, fullName) => JSON.stringify([modulePath, fullName]);
|
|
4
16
|
/** @public */
|
|
5
17
|
var HistoryTracker = class extends Context.Tag("vitest-agent/HistoryTracker")() {};
|
|
6
18
|
|
|
7
19
|
//#endregion
|
|
8
|
-
export { HistoryTracker };
|
|
20
|
+
export { HistoryTracker, historyKey };
|
package/sql/assemblers.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { historyKey } from "../services/HistoryTracker.js";
|
|
2
|
+
|
|
1
3
|
//#region src/sql/assemblers.ts
|
|
2
4
|
/**
|
|
3
5
|
* Builds a `CacheManifest` from an array of test_runs aggregation rows.
|
|
@@ -32,10 +34,13 @@ function assembleManifest(rows, dbPath) {
|
|
|
32
34
|
};
|
|
33
35
|
}
|
|
34
36
|
/**
|
|
35
|
-
* Groups test_history rows by
|
|
37
|
+
* Groups test_history rows by the composite (module_path, full_name) key
|
|
38
|
+
* into a keyed record.
|
|
36
39
|
*
|
|
37
|
-
* Returns `Record<
|
|
38
|
-
* accumulated test runs for that test, in the order
|
|
40
|
+
* Returns `Record<compositeKey, { modulePath, fullName, runs: TestRun[] }>`
|
|
41
|
+
* where `runs` are the accumulated test runs for that test, in the order
|
|
42
|
+
* they appear in `rows`. Two rows sharing `full_name` but differing
|
|
43
|
+
* `module_path` are tracked as distinct entries rather than merged.
|
|
39
44
|
*
|
|
40
45
|
* Only rows with state `"passed"` or `"failed"` are included in runs
|
|
41
46
|
* (matching the `TestRun` schema constraint).
|
|
@@ -46,8 +51,13 @@ function assembleHistoryRecord(rows) {
|
|
|
46
51
|
for (const row of rows) {
|
|
47
52
|
const state = row.state === "passed" || row.state === "failed" ? row.state : null;
|
|
48
53
|
if (state === null) continue;
|
|
49
|
-
|
|
50
|
-
record[
|
|
54
|
+
const key = historyKey(row.module_path, row.full_name);
|
|
55
|
+
if (!record[key]) record[key] = {
|
|
56
|
+
modulePath: row.module_path,
|
|
57
|
+
fullName: row.full_name,
|
|
58
|
+
runs: []
|
|
59
|
+
};
|
|
60
|
+
record[key].runs.push({
|
|
51
61
|
timestamp: row.timestamp,
|
|
52
62
|
state
|
|
53
63
|
});
|
package/testing.d.ts
CHANGED
|
@@ -742,7 +742,7 @@ declare const DataStore_base: Context.TagClass<DataStore, "vitest-agent/DataStor
|
|
|
742
742
|
readonly writeTestCases: (moduleId: number, tests: ReadonlyArray<TestCaseInput>) => Effect.Effect<ReadonlyArray<number>, DataStoreError>;
|
|
743
743
|
readonly writeErrors: (runId: number, errors: ReadonlyArray<TestErrorInput>) => Effect.Effect<void, DataStoreError>;
|
|
744
744
|
readonly writeCoverage: (runId: number, coverage: ReadonlyArray<FileCoverageInput>) => Effect.Effect<void, DataStoreError>;
|
|
745
|
-
readonly writeHistory: (project: string, fullName: string, runId: number, timestamp: string, state: string, duration: number | null, flaky: boolean, retryCount: number, errorMessage: string | null) => Effect.Effect<void, DataStoreError>;
|
|
745
|
+
readonly writeHistory: (project: string, fullName: string, modulePath: string, runId: number, timestamp: string, state: string, duration: number | null, flaky: boolean, retryCount: number, errorMessage: string | null) => Effect.Effect<void, DataStoreError>;
|
|
746
746
|
readonly writeBaselines: (baselines: CoverageBaselines) => Effect.Effect<void, DataStoreError>;
|
|
747
747
|
readonly writeTrends: (project: string, runId: number, entry: TrendEntry) => Effect.Effect<void, DataStoreError>;
|
|
748
748
|
readonly writeSourceMap: (sourceFilePath: string, testModuleId: number, mappingType: string) => Effect.Effect<void, DataStoreError>;
|
|
@@ -1102,6 +1102,7 @@ declare const HistoryRecord: Schema.Struct<{
|
|
|
1102
1102
|
project: typeof Schema.String;
|
|
1103
1103
|
updatedAt: typeof Schema.String;
|
|
1104
1104
|
tests: Schema.Array$<Schema.Struct<{
|
|
1105
|
+
modulePath: typeof Schema.String;
|
|
1105
1106
|
fullName: typeof Schema.String;
|
|
1106
1107
|
runs: Schema.Array$<Schema.Struct<{
|
|
1107
1108
|
timestamp: typeof Schema.String;
|
|
@@ -1126,6 +1127,7 @@ interface ProjectRunSummary {
|
|
|
1126
1127
|
/** @public */
|
|
1127
1128
|
interface FlakyTest {
|
|
1128
1129
|
readonly fullName: string;
|
|
1130
|
+
readonly modulePath: string;
|
|
1129
1131
|
readonly project: string;
|
|
1130
1132
|
readonly passCount: number;
|
|
1131
1133
|
readonly failCount: number;
|
|
@@ -1135,6 +1137,7 @@ interface FlakyTest {
|
|
|
1135
1137
|
/** @public */
|
|
1136
1138
|
interface PersistentFailure {
|
|
1137
1139
|
readonly fullName: string;
|
|
1140
|
+
readonly modulePath: string;
|
|
1138
1141
|
readonly project: string;
|
|
1139
1142
|
readonly consecutiveFailures: number;
|
|
1140
1143
|
readonly firstFailedAt: string;
|
package/testing.js
CHANGED
|
@@ -176,9 +176,9 @@ function flaky(filename) {
|
|
|
176
176
|
state: "passed",
|
|
177
177
|
duration: 300
|
|
178
178
|
}]);
|
|
179
|
-
yield* store.writeHistory("default", "async > resolves within timeout", runId1, "2025-12-31T23:00:00.000Z", "passed", 500, false, 0, null);
|
|
180
|
-
yield* store.writeHistory("default", "async > resolves within timeout", runId1, "2026-01-01T00:00:00.000Z", "failed", 500, false, 0, null);
|
|
181
|
-
yield* store.writeHistory("default", "async > rejects on error", runId1, "2026-01-01T00:00:00.000Z", "passed", 300, false, 0, null);
|
|
179
|
+
yield* store.writeHistory("default", "async > resolves within timeout", "src/async.test.ts", runId1, "2025-12-31T23:00:00.000Z", "passed", 500, false, 0, null);
|
|
180
|
+
yield* store.writeHistory("default", "async > resolves within timeout", "src/async.test.ts", runId1, "2026-01-01T00:00:00.000Z", "failed", 500, false, 0, null);
|
|
181
|
+
yield* store.writeHistory("default", "async > rejects on error", "src/async.test.ts", runId1, "2026-01-01T00:00:00.000Z", "passed", 300, false, 0, null);
|
|
182
182
|
const runId2 = yield* store.writeRun({
|
|
183
183
|
invocationId: "inv-preset-flaky-2",
|
|
184
184
|
project: "default",
|
|
@@ -211,8 +211,8 @@ function flaky(filename) {
|
|
|
211
211
|
state: "passed",
|
|
212
212
|
duration: 300
|
|
213
213
|
}]);
|
|
214
|
-
yield* store.writeHistory("default", "async > resolves within timeout", runId2, "2026-01-01T01:00:00.000Z", "passed", 400, false, 0, null);
|
|
215
|
-
yield* store.writeHistory("default", "async > rejects on error", runId2, "2026-01-01T01:00:00.000Z", "passed", 300, false, 0, null);
|
|
214
|
+
yield* store.writeHistory("default", "async > resolves within timeout", "src/async.test.ts", runId2, "2026-01-01T01:00:00.000Z", "passed", 400, false, 0, null);
|
|
215
|
+
yield* store.writeHistory("default", "async > rejects on error", "src/async.test.ts", runId2, "2026-01-01T01:00:00.000Z", "passed", 300, false, 0, null);
|
|
216
216
|
});
|
|
217
217
|
return Layer.effectDiscard(seed).pipe(Layer.provideMerge(base));
|
|
218
218
|
}
|