@vitest-agent/sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/DataReader-2kJ9I9Hh.d.ts +1809 -0
  2. package/LICENSE +21 -0
  3. package/README.md +52 -0
  4. package/dispatch.d.ts +48 -0
  5. package/dispatch.js +5 -0
  6. package/errors/AgentErrors.js +65 -0
  7. package/errors/DataStoreError.js +44 -0
  8. package/errors/DiscoveryError.js +21 -0
  9. package/errors/PathResolutionError.js +27 -0
  10. package/errors/ProjectIdentityError.js +29 -0
  11. package/errors/RunContextError.js +35 -0
  12. package/errors/TddErrors.js +66 -0
  13. package/exit-code-for-tag.js +18 -0
  14. package/formatters/ci-annotations.js +61 -0
  15. package/formatters/gfm.js +20 -0
  16. package/formatters/json.js +18 -0
  17. package/formatters/markdown.js +39 -0
  18. package/formatters/silent.js +9 -0
  19. package/formatters/terminal.js +56 -0
  20. package/index.d.ts +3334 -0
  21. package/index.js +120 -0
  22. package/internal-inject-env.js +42 -0
  23. package/layers/ConfigLive.js +47 -0
  24. package/layers/DataReaderLive.js +1666 -0
  25. package/layers/DataStoreLive.js +1185 -0
  26. package/layers/DetailResolverLive.js +9 -0
  27. package/layers/DiscoveryRegistryLive.js +70 -0
  28. package/layers/EnvironmentDetectorLive.js +21 -0
  29. package/layers/EnvironmentDetectorTest.js +13 -0
  30. package/layers/ExecutorResolverLive.js +9 -0
  31. package/layers/FormatSelectorLive.js +20 -0
  32. package/layers/HistoryTrackerLive.js +47 -0
  33. package/layers/HistoryTrackerTest.js +25 -0
  34. package/layers/LoggerLive.js +64 -0
  35. package/layers/OutputPipelineLive.js +13 -0
  36. package/layers/OutputRendererLive.js +28 -0
  37. package/layers/PathResolutionLive.js +36 -0
  38. package/layers/PerClientSessionMapLive.js +145 -0
  39. package/layers/ProjectDiscoveryLive.js +70 -0
  40. package/layers/ProjectDiscoveryTest.js +12 -0
  41. package/layers/ProjectIdentityLive.js +92 -0
  42. package/layers/RunContextLive.js +81 -0
  43. package/lib/format-triage.js +103 -0
  44. package/lib/format-wrapup.js +67 -0
  45. package/migrations/0001_initial.js +849 -0
  46. package/migrations/registry_0001_initial.js +39 -0
  47. package/migrations/session_map_0001_initial.js +61 -0
  48. package/package.json +64 -0
  49. package/schemas/Agent.js +42 -0
  50. package/schemas/AgentReport.js +71 -0
  51. package/schemas/Baselines.js +16 -0
  52. package/schemas/CacheManifest.js +27 -0
  53. package/schemas/ChannelEvent.js +138 -0
  54. package/schemas/Common.js +105 -0
  55. package/schemas/Config.js +28 -0
  56. package/schemas/Coverage.js +51 -0
  57. package/schemas/CoverageLevel.js +117 -0
  58. package/schemas/CoverageTargets.js +39 -0
  59. package/schemas/History.js +31 -0
  60. package/schemas/Identity.js +64 -0
  61. package/schemas/Options.js +57 -0
  62. package/schemas/RenderState.js +161 -0
  63. package/schemas/RunEvent.js +163 -0
  64. package/schemas/Tdd.js +44 -0
  65. package/schemas/Thresholds.js +30 -0
  66. package/schemas/Transport.js +16 -0
  67. package/schemas/Trends.js +23 -0
  68. package/schemas/turns/FileEditPayload.js +15 -0
  69. package/schemas/turns/HookFirePayload.js +13 -0
  70. package/schemas/turns/HypothesisPayload.js +13 -0
  71. package/schemas/turns/NotePayload.js +13 -0
  72. package/schemas/turns/ToolCallPayload.js +13 -0
  73. package/schemas/turns/ToolResultPayload.js +15 -0
  74. package/schemas/turns/UserPromptPayload.js +12 -0
  75. package/schemas/turns/index.js +15 -0
  76. package/services/Config.js +15 -0
  77. package/services/DataReader.js +8 -0
  78. package/services/DataStore.js +8 -0
  79. package/services/DetailResolver.js +8 -0
  80. package/services/DiscoveryRegistry.js +8 -0
  81. package/services/EnvironmentDetector.js +8 -0
  82. package/services/ExecutorResolver.js +8 -0
  83. package/services/FormatSelector.js +8 -0
  84. package/services/HistoryTracker.js +8 -0
  85. package/services/OutputRenderer.js +8 -0
  86. package/services/PerClientSessionMap.js +22 -0
  87. package/services/ProjectDiscovery.js +8 -0
  88. package/services/ProjectIdentity.js +63 -0
  89. package/services/RunContext.js +53 -0
  90. package/services/idempotency.js +57 -0
  91. package/sidecar-dispatch.js +84 -0
  92. package/sql/assemblers.js +59 -0
  93. package/testing/layers.js +21 -0
  94. package/testing.d.ts +25 -0
  95. package/testing.js +243 -0
  96. package/tsdoc-metadata.json +11 -0
  97. package/utils/ansi.js +49 -0
  98. package/utils/build-report.js +130 -0
  99. package/utils/canonicalize-git-url.js +66 -0
  100. package/utils/classify-test.js +22 -0
  101. package/utils/compress-lines.js +45 -0
  102. package/utils/compute-trend.js +88 -0
  103. package/utils/detect-pm.js +58 -0
  104. package/utils/detect-timeout.js +17 -0
  105. package/utils/ensure-migrated.js +52 -0
  106. package/utils/failure-signature.js +33 -0
  107. package/utils/format-console.js +219 -0
  108. package/utils/format-fatal-error.js +35 -0
  109. package/utils/format-gfm.js +161 -0
  110. package/utils/format-terminal.js +480 -0
  111. package/utils/function-boundary.js +75 -0
  112. package/utils/hyperlink.js +11 -0
  113. package/utils/match-vitest-command.js +88 -0
  114. package/utils/normalize-workspace-key.js +34 -0
  115. package/utils/probe-host-metadata.js +99 -0
  116. package/utils/resolve-data-path.js +66 -0
  117. package/utils/resolve-project-key-from-cwd.js +52 -0
  118. package/utils/resolve-workspace-key.js +33 -0
  119. package/utils/safe-filename.js +34 -0
  120. package/utils/validate-coverage-targets-shape.js +84 -0
  121. package/utils/validate-phase-transition.js +113 -0
@@ -0,0 +1,39 @@
1
+ import { Effect } from "effect";
2
+ import { SqlClient } from "@effect/sql/SqlClient";
3
+
4
+ //#region src/migrations/registry_0001_initial.ts
5
+ /**
6
+ * Migration for the global discovery registry SQLite at
7
+ * `$XDG_DATA_HOME/vitest-agent/registry.db`.
8
+ *
9
+ * Single table `known_projects` indexed by `project_key` (the
10
+ * filesystem-safe form from {@link ProjectIdentity}). Tooling like
11
+ * `mcp-app` queries this table to enumerate every vitest-agent
12
+ * project the user has ever run on this machine.
13
+ *
14
+ * The registry never blocks anything — its writes are best-effort.
15
+ * Concurrent writers from multiple Claude Code windows converge via
16
+ * the `ON CONFLICT(project_key) DO UPDATE` upsert.
17
+ * @public
18
+ */
19
+ const migration = Effect.gen(function* () {
20
+ const sql = yield* SqlClient;
21
+ yield* sql`PRAGMA journal_mode=WAL`;
22
+ yield* sql`PRAGMA foreign_keys=ON`;
23
+ yield* sql`PRAGMA busy_timeout=5000`;
24
+ yield* sql`
25
+ CREATE TABLE known_projects (
26
+ project_key TEXT PRIMARY KEY,
27
+ canonical_form TEXT NOT NULL,
28
+ data_db_path TEXT NOT NULL,
29
+ git_remote_origin TEXT,
30
+ workspace_root TEXT NOT NULL,
31
+ first_seen_at INTEGER NOT NULL,
32
+ last_seen_at INTEGER NOT NULL
33
+ ) STRICT
34
+ `;
35
+ yield* sql`CREATE INDEX idx_known_projects_workspace_root ON known_projects(workspace_root)`;
36
+ });
37
+
38
+ //#endregion
39
+ export { migration as default };
@@ -0,0 +1,61 @@
1
+ import { Effect } from "effect";
2
+ import { SqlClient } from "@effect/sql/SqlClient";
3
+
4
+ //#region src/migrations/session_map_0001_initial.ts
5
+ /**
6
+ * Migration for the per-client session map SQLite at
7
+ * `${CLAUDE_PLUGIN_DATA}/sessions.db` (Claude Code) or the
8
+ * client-specific equivalent.
9
+ *
10
+ * The session map is a host-specific side-channel that translates
11
+ * client-native identifiers (transcript path, hook-payload session id)
12
+ * into the canonical UUIDs the per-project `data.db` expects. It lets
13
+ * `claude --resume` reuse the same `conversation_id` UUID across
14
+ * restarts.
15
+ *
16
+ * Two STRICT tables:
17
+ * - `conversation_map` keyed on the transcript filename UUID
18
+ * (already a UUID per Claude Code's convention)
19
+ * - `session_map` keyed on the host's native session id (the chat
20
+ * UUID — `session_id` from the Claude Code hook payload, exposed
21
+ * to agents as `chatId` post the 2026-05 rename)
22
+ *
23
+ * Concurrent writers from multiple Claude Code windows converge via
24
+ * idempotent UPSERTs on the native-id keys; WAL mode plus 5s
25
+ * busy_timeout absorb contention.
26
+ * @public
27
+ */
28
+ /** @internal */
29
+ const migration = Effect.gen(function* () {
30
+ const sql = yield* SqlClient;
31
+ yield* sql`PRAGMA journal_mode=WAL`;
32
+ yield* sql`PRAGMA foreign_keys=ON`;
33
+ yield* sql`PRAGMA busy_timeout=5000`;
34
+ yield* sql`
35
+ CREATE TABLE conversation_map (
36
+ transcript_uuid TEXT PRIMARY KEY,
37
+ transcript_path TEXT NOT NULL,
38
+ conversation_id TEXT NOT NULL UNIQUE,
39
+ first_seen_at INTEGER NOT NULL,
40
+ last_seen_at INTEGER NOT NULL
41
+ ) STRICT
42
+ `;
43
+ yield* sql`
44
+ CREATE TABLE session_map (
45
+ host_session_id TEXT PRIMARY KEY,
46
+ conversation_id TEXT NOT NULL REFERENCES conversation_map(conversation_id) ON DELETE RESTRICT,
47
+ project_key TEXT NOT NULL,
48
+ project_dir TEXT NOT NULL,
49
+ main_agent_id TEXT NOT NULL,
50
+ started_at INTEGER NOT NULL,
51
+ ended_at INTEGER
52
+ ) STRICT
53
+ `;
54
+ yield* sql`CREATE INDEX idx_session_map_project_key ON session_map(project_key)`;
55
+ yield* sql`CREATE INDEX idx_session_map_project_dir ON session_map(project_dir)`;
56
+ yield* sql`CREATE INDEX idx_session_map_active ON session_map(project_dir) WHERE ended_at IS NULL`;
57
+ yield* sql`CREATE INDEX idx_session_map_conversation_id ON session_map(conversation_id)`;
58
+ });
59
+
60
+ //#endregion
61
+ export { migration as default };
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@vitest-agent/sdk",
3
+ "version": "1.0.0",
4
+ "private": false,
5
+ "description": "Shared Effect Schema, SQLite migrations, data layer, services, formatters, and utilities for vitest-agent packages.",
6
+ "keywords": [
7
+ "vitest",
8
+ "agent",
9
+ "shared",
10
+ "effect",
11
+ "sqlite"
12
+ ],
13
+ "homepage": "https://github.com/spencerbeggs/vitest-agent#readme",
14
+ "bugs": {
15
+ "url": "https://github.com/spencerbeggs/vitest-agent/issues"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/spencerbeggs/vitest-agent.git",
20
+ "directory": "packages/sdk"
21
+ },
22
+ "license": "MIT",
23
+ "author": {
24
+ "name": "C. Spencer Beggs",
25
+ "email": "spencer@beggs.codes",
26
+ "url": "https://spencerbeg.gs"
27
+ },
28
+ "type": "module",
29
+ "exports": {
30
+ ".": {
31
+ "types": "./index.d.ts",
32
+ "import": "./index.js"
33
+ },
34
+ "./dispatch": {
35
+ "types": "./dispatch.d.ts",
36
+ "import": "./dispatch.js"
37
+ },
38
+ "./testing": {
39
+ "types": "./testing.d.ts",
40
+ "import": "./testing.js"
41
+ },
42
+ "./package.json": "./package.json"
43
+ },
44
+ "dependencies": {
45
+ "@effect/cluster": "^0.59.0",
46
+ "@effect/platform": "^0.96.2",
47
+ "@effect/platform-node": "^0.107.0",
48
+ "@effect/rpc": "^0.75.1",
49
+ "@effect/sql": "^0.51.1",
50
+ "@effect/sql-sqlite-node": "^0.52.0",
51
+ "@types/acorn": "^6.0.4",
52
+ "acorn": "^8.17.0",
53
+ "acorn-typescript": "^1.4.13",
54
+ "ajv": "^8.20.0",
55
+ "config-file-effect": "^0.2.3",
56
+ "effect": "^3.21.4",
57
+ "std-env": "^4.1.0",
58
+ "workspaces-effect": "^1.2.0",
59
+ "xdg-effect": "^2.0.1"
60
+ },
61
+ "engines": {
62
+ "node": ">=24.11.0"
63
+ }
64
+ }
@@ -0,0 +1,42 @@
1
+ import { AgentId, ConversationId } from "./Identity.js";
2
+ import { Data, Schema } from "effect";
3
+
4
+ //#region src/schemas/Agent.ts
5
+ /**
6
+ * Successful registration row. The fields mirror the `agents` SQLite
7
+ * table 1:1 in camelCase.
8
+ *
9
+ * `startGitBranch`, `startGitCommitSha`, `startWorktreeDir` capture
10
+ * *what the agent inherited at registration time* — distinct from the
11
+ * per-run git context recorded on `runs`. A divergence between the
12
+ * two reveals a mid-session branch switch, which is itself signal.
13
+ * @public
14
+ */
15
+ var Agent = class extends Schema.TaggedClass()("Agent", {
16
+ agentId: AgentId,
17
+ sessionId: Schema.Number,
18
+ parentAgentId: Schema.NullOr(AgentId),
19
+ conversationId: Schema.NullOr(ConversationId),
20
+ agentType: Schema.String,
21
+ startedAt: Schema.Number,
22
+ endedAt: Schema.NullOr(Schema.Number),
23
+ startGitBranch: Schema.NullOr(Schema.String),
24
+ startGitCommitSha: Schema.NullOr(Schema.String),
25
+ startWorktreeDir: Schema.NullOr(Schema.String),
26
+ idempotencyKey: Schema.String
27
+ }) {};
28
+ /**
29
+ * Returned by `DataStore.registerAgent` when the
30
+ * `(session_id, idempotency_key)` UNIQUE constraint already has a
31
+ * row. Not an error — the caller treats it as a successful recovery
32
+ * of the existing `agentId`.
33
+ *
34
+ * Modeled as a `Data.TaggedClass` so the success channel of
35
+ * `registerAgent` is `Effect<Agent | IdempotencyHit, ...>` and
36
+ * downstream code uses `Match.tag` to branch.
37
+ * @public
38
+ */
39
+ var IdempotencyHit = class extends Data.TaggedClass("IdempotencyHit") {};
40
+
41
+ //#endregion
42
+ export { Agent, IdempotencyHit };
@@ -0,0 +1,71 @@
1
+ import { ReportError, TestClassification, TestRunReason, TestState } from "./Common.js";
2
+ import { CoverageReport } from "./Coverage.js";
3
+ import { Schema } from "effect";
4
+
5
+ //#region src/schemas/AgentReport.ts
6
+ /**
7
+ * Aggregate test run statistics.
8
+ * @public
9
+ */
10
+ const ReportSummary = Schema.Struct({
11
+ total: Schema.Number,
12
+ passed: Schema.Number,
13
+ failed: Schema.Number,
14
+ skipped: Schema.Number,
15
+ duration: Schema.Number
16
+ }).annotations({ identifier: "ReportSummary" });
17
+ /**
18
+ * An individual test case result.
19
+ * @public
20
+ */
21
+ const TestReport = Schema.Struct({
22
+ name: Schema.String,
23
+ fullName: Schema.String,
24
+ state: TestState,
25
+ duration: Schema.optional(Schema.Number),
26
+ flaky: Schema.optional(Schema.Boolean),
27
+ slow: Schema.optional(Schema.Boolean),
28
+ errors: Schema.optional(Schema.Array(ReportError)),
29
+ classification: Schema.optional(TestClassification)
30
+ }).annotations({ identifier: "TestReport" });
31
+ /**
32
+ * A test module (file) and its contained test cases.
33
+ * @public
34
+ */
35
+ const ModuleReport = Schema.Struct({
36
+ file: Schema.String,
37
+ state: TestState,
38
+ duration: Schema.optional(Schema.Number),
39
+ errors: Schema.optional(Schema.Array(ReportError)),
40
+ tests: Schema.Array(TestReport)
41
+ }).annotations({ identifier: "ModuleReport" });
42
+ /**
43
+ * Per-tag pass/fail/skip aggregates for a single project run.
44
+ * @public
45
+ */
46
+ const TagCountEntry = Schema.Struct({
47
+ passed: Schema.optional(Schema.Number),
48
+ failed: Schema.optional(Schema.Number),
49
+ skipped: Schema.optional(Schema.Number)
50
+ }).annotations({ identifier: "TagCountEntry" });
51
+ /**
52
+ * Complete per-project test report written to disk as JSON.
53
+ * @public
54
+ */
55
+ const AgentReport = Schema.Struct({
56
+ timestamp: Schema.String,
57
+ project: Schema.optional(Schema.String),
58
+ reason: TestRunReason,
59
+ summary: ReportSummary,
60
+ failed: Schema.Array(ModuleReport),
61
+ unhandledErrors: Schema.Array(ReportError),
62
+ failedFiles: Schema.Array(Schema.String),
63
+ coverage: Schema.optional(CoverageReport),
64
+ tagCounts: Schema.optional(Schema.Record({
65
+ key: Schema.String,
66
+ value: TagCountEntry
67
+ }))
68
+ }).annotations({ identifier: "AgentReport" });
69
+
70
+ //#endregion
71
+ export { AgentReport, ModuleReport, ReportSummary, TagCountEntry, TestReport };
@@ -0,0 +1,16 @@
1
+ import { MetricThresholds, PatternThresholds } from "./Thresholds.js";
2
+ import { Schema } from "effect";
3
+
4
+ //#region src/schemas/Baselines.ts
5
+ /**
6
+ * Coverage baselines -- the auto-ratcheting high-water mark.
7
+ * @public
8
+ */
9
+ const CoverageBaselines = Schema.Struct({
10
+ updatedAt: Schema.String,
11
+ global: MetricThresholds,
12
+ patterns: Schema.optionalWith(Schema.Array(PatternThresholds), { default: () => [] })
13
+ }).annotations({ identifier: "CoverageBaselines" });
14
+
15
+ //#endregion
16
+ export { CoverageBaselines };
@@ -0,0 +1,27 @@
1
+ import { TestRunReason } from "./Common.js";
2
+ import { Schema } from "effect";
3
+
4
+ //#region src/schemas/CacheManifest.ts
5
+ /**
6
+ * A single project entry in the cache manifest.
7
+ * @public
8
+ */
9
+ const CacheManifestEntry = Schema.Struct({
10
+ project: Schema.String,
11
+ reportFile: Schema.String,
12
+ historyFile: Schema.optional(Schema.String),
13
+ lastRun: Schema.NullOr(Schema.String),
14
+ lastResult: Schema.NullOr(TestRunReason)
15
+ }).annotations({ identifier: "CacheManifestEntry" });
16
+ /**
17
+ * Root manifest file that indexes all project reports.
18
+ * @public
19
+ */
20
+ const CacheManifest = Schema.Struct({
21
+ updatedAt: Schema.String,
22
+ cacheDir: Schema.String,
23
+ projects: Schema.Array(CacheManifestEntry)
24
+ }).annotations({ identifier: "CacheManifest" });
25
+
26
+ //#endregion
27
+ export { CacheManifest, CacheManifestEntry };
@@ -0,0 +1,138 @@
1
+ import { Schema } from "effect";
2
+
3
+ //#region src/schemas/ChannelEvent.ts
4
+ /**
5
+ * Channel event schemas for the orchestrator → main-agent progress push.
6
+ *
7
+ * All payloads share a `type` discriminator and pass through
8
+ * `tdd_progress_push`. Behavior-level events declare goalId/sessionId
9
+ * fields, but the MCP server resolves those server-side from
10
+ * behaviorId via `DataReader.resolveGoalIdForBehavior` before emitting
11
+ * the notification — caller-supplied values for goalId/sessionId on
12
+ * behavior events are advisory and may be overwritten.
13
+ */
14
+ /** @public */
15
+ const SessionOutcome = Schema.Literal("succeeded", "blocked", "abandoned");
16
+ const PhaseLiteral = Schema.Literal("spike", "red", "red.triangulate", "green", "green.fake-it", "refactor", "extended-red", "green-without-red");
17
+ const GoalSummary = Schema.Struct({
18
+ id: Schema.Number,
19
+ ordinal: Schema.Number,
20
+ goal: Schema.String
21
+ });
22
+ const BehaviorSummary = Schema.Struct({
23
+ id: Schema.Number,
24
+ ordinal: Schema.Number,
25
+ behavior: Schema.String
26
+ });
27
+ /** @public */
28
+ const GoalsReadyEvent = Schema.Struct({
29
+ type: Schema.Literal("goals_ready"),
30
+ sessionId: Schema.Number,
31
+ goals: Schema.Array(GoalSummary)
32
+ });
33
+ /** @public */
34
+ const GoalAddedEvent = Schema.Struct({
35
+ type: Schema.Literal("goal_added"),
36
+ sessionId: Schema.Number,
37
+ goal: GoalSummary
38
+ });
39
+ /** @public */
40
+ const GoalStartedEvent = Schema.Struct({
41
+ type: Schema.Literal("goal_started"),
42
+ sessionId: Schema.Number,
43
+ goalId: Schema.Number
44
+ });
45
+ /** @public */
46
+ const GoalCompletedEvent = Schema.Struct({
47
+ type: Schema.Literal("goal_completed"),
48
+ sessionId: Schema.Number,
49
+ goalId: Schema.Number,
50
+ behaviorIds: Schema.Array(Schema.Number)
51
+ });
52
+ /** @public */
53
+ const GoalAbandonedEvent = Schema.Struct({
54
+ type: Schema.Literal("goal_abandoned"),
55
+ sessionId: Schema.Number,
56
+ goalId: Schema.Number,
57
+ reason: Schema.String
58
+ });
59
+ /** @public */
60
+ const BehaviorsReadyEvent = Schema.Struct({
61
+ type: Schema.Literal("behaviors_ready"),
62
+ sessionId: Schema.Number,
63
+ goalId: Schema.Number,
64
+ behaviors: Schema.Array(BehaviorSummary)
65
+ });
66
+ /** @public */
67
+ const BehaviorAddedEvent = Schema.Struct({
68
+ type: Schema.Literal("behavior_added"),
69
+ sessionId: Schema.Number,
70
+ goalId: Schema.Number,
71
+ behavior: BehaviorSummary
72
+ });
73
+ /** @public */
74
+ const BehaviorStartedEvent = Schema.Struct({
75
+ type: Schema.Literal("behavior_started"),
76
+ sessionId: Schema.Number,
77
+ goalId: Schema.Number,
78
+ behaviorId: Schema.Number
79
+ });
80
+ /** @public */
81
+ const PhaseTransitionEvent = Schema.Struct({
82
+ type: Schema.Literal("phase_transition"),
83
+ sessionId: Schema.Number,
84
+ goalId: Schema.Number,
85
+ behaviorId: Schema.Number,
86
+ from: PhaseLiteral,
87
+ to: PhaseLiteral
88
+ });
89
+ /** @public */
90
+ const BehaviorCompletedEvent = Schema.Struct({
91
+ type: Schema.Literal("behavior_completed"),
92
+ sessionId: Schema.Number,
93
+ goalId: Schema.Number,
94
+ behaviorId: Schema.Number
95
+ });
96
+ /** @public */
97
+ const BehaviorAbandonedEvent = Schema.Struct({
98
+ type: Schema.Literal("behavior_abandoned"),
99
+ sessionId: Schema.Number,
100
+ goalId: Schema.Number,
101
+ behaviorId: Schema.Number,
102
+ reason: Schema.String
103
+ });
104
+ /** @public */
105
+ const BlockedEvent = Schema.Struct({
106
+ type: Schema.Literal("blocked"),
107
+ sessionId: Schema.Number,
108
+ goalId: Schema.Number,
109
+ behaviorId: Schema.Number,
110
+ reason: Schema.String,
111
+ failureSignatureHash: Schema.optional(Schema.String)
112
+ });
113
+ /** @public */
114
+ const SessionCompleteEvent = Schema.Struct({
115
+ type: Schema.Literal("session_complete"),
116
+ sessionId: Schema.Number,
117
+ goalIds: Schema.Array(Schema.Number),
118
+ outcome: SessionOutcome
119
+ });
120
+ /** @public */
121
+ const ChannelEvent = Schema.Union(GoalsReadyEvent, GoalAddedEvent, GoalStartedEvent, GoalCompletedEvent, GoalAbandonedEvent, BehaviorsReadyEvent, BehaviorAddedEvent, BehaviorStartedEvent, PhaseTransitionEvent, BehaviorCompletedEvent, BehaviorAbandonedEvent, BlockedEvent, SessionCompleteEvent);
122
+ /**
123
+ * Event types whose `goalId` and `sessionId` should be resolved
124
+ * server-side from `behaviorId` (per spec: "not trusting the
125
+ * orchestrator's request"). Listed explicitly so the resolver knows
126
+ * which subset to enrich vs pass through.
127
+ * @public
128
+ */
129
+ const BehaviorScopedEventTypes = [
130
+ "behavior_started",
131
+ "phase_transition",
132
+ "behavior_completed",
133
+ "behavior_abandoned",
134
+ "blocked"
135
+ ];
136
+
137
+ //#endregion
138
+ export { BehaviorAbandonedEvent, BehaviorAddedEvent, BehaviorCompletedEvent, BehaviorScopedEventTypes, BehaviorStartedEvent, BehaviorsReadyEvent, BlockedEvent, ChannelEvent, GoalAbandonedEvent, GoalAddedEvent, GoalCompletedEvent, GoalStartedEvent, GoalsReadyEvent, PhaseTransitionEvent, SessionCompleteEvent, SessionOutcome };
@@ -0,0 +1,105 @@
1
+ import { Schema } from "effect";
2
+
3
+ //#region src/schemas/Common.ts
4
+ /**
5
+ * Common schemas shared across multiple modules.
6
+ *
7
+ * Defines enums/literals and the ReportError struct used by
8
+ * both AgentReport and CacheManifest schemas.
9
+ */
10
+ /**
11
+ * Possible states for an individual test case.
12
+ * @public
13
+ */
14
+ const TestState = Schema.Literal("passed", "failed", "skipped", "pending").annotations({ identifier: "TestState" });
15
+ /**
16
+ * Overall outcome of a test run.
17
+ * @public
18
+ */
19
+ const TestRunReason = Schema.Literal("passed", "failed", "interrupted").annotations({ identifier: "TestRunReason" });
20
+ /**
21
+ * Classification of a test's failure history across runs.
22
+ * @public
23
+ */
24
+ const TestClassification = Schema.Literal("stable", "new-failure", "persistent", "flaky", "recovered").annotations({ identifier: "TestClassification" });
25
+ /**
26
+ * Console output verbosity mode for AgentReporter.
27
+ * @public
28
+ */
29
+ const ConsoleOutputMode = Schema.Literal("failures", "full", "silent").annotations({ identifier: "ConsoleOutputMode" });
30
+ /**
31
+ * Console output choices per executor type.
32
+ *
33
+ * - `passthrough` — plugin emits nothing observable; Vitest's own reporters
34
+ * do the visible work. Persistence still runs. Default for `human` and `ci`.
35
+ * - `silent` — strip Vitest's reporters AND emit nothing from the plugin.
36
+ * True silence. Persistence still runs.
37
+ * - `agent` — markdown-flavored final-frame string tuned for token economy.
38
+ * Default for `agent` executor. Set on `human` as the debugging mode for
39
+ * inspecting the exact plain-text output an agent consumes.
40
+ * - `stream` — progressively-drawn, colored, animated rendering of the
41
+ * agent's run-shape view. Strips Vitest's reporters and owns stdout for
42
+ * the duration of the run. Human executor only.
43
+ * - `ci-annotations` — GitHub Actions `::error::` annotations. Opt-in for
44
+ * the `ci` executor; the matching dedicated emitter is not yet shipped,
45
+ * so the default for `ci` is `passthrough` until it lands.
46
+ * @public
47
+ */
48
+ const HumanConsoleMode = Schema.Literal("passthrough", "silent", "stream", "agent").annotations({ identifier: "HumanConsoleMode" });
49
+ /** @public */
50
+ const AgentConsoleMode = Schema.Literal("passthrough", "silent", "agent").annotations({ identifier: "AgentConsoleMode" });
51
+ /** @public */
52
+ const CiConsoleMode = Schema.Literal("passthrough", "silent", "ci-annotations").annotations({ identifier: "CiConsoleMode" });
53
+ /**
54
+ * Union of every legal console-output value across the three executor slots.
55
+ * Useful for type-narrowing in renderers that take the resolved value.
56
+ * @public
57
+ */
58
+ const ConsoleMode = Schema.Union(HumanConsoleMode, AgentConsoleMode, CiConsoleMode).annotations({ identifier: "ConsoleMode" });
59
+ /**
60
+ * Supported package managers for run command generation.
61
+ * @public
62
+ */
63
+ const PackageManager = Schema.Literal("pnpm", "npm", "yarn", "bun").annotations({ identifier: "PackageManager" });
64
+ /**
65
+ * Runtime environment where tests are being executed.
66
+ * @public
67
+ */
68
+ const Environment = Schema.Literal("agent-shell", "terminal", "ci-github", "ci-generic").annotations({ identifier: "Environment" });
69
+ /**
70
+ * Who or what is executing the test run.
71
+ * @public
72
+ */
73
+ const Executor = Schema.Literal("human", "agent", "ci").annotations({ identifier: "Executor" });
74
+ /**
75
+ * Output format for the reporter pipeline.
76
+ * @public
77
+ */
78
+ const OutputFormat = Schema.Literal("terminal", "markdown", "json", "vitest-bypass", "silent", "ci-annotations").annotations({ identifier: "OutputFormat" });
79
+ /**
80
+ * Level of detail in reporter output.
81
+ * @public
82
+ */
83
+ const DetailLevel = Schema.Literal("minimal", "neutral", "standard", "verbose").annotations({ identifier: "DetailLevel" });
84
+ /**
85
+ * A single test or module error with optional stack trace, diff, and
86
+ * structured assertion values.
87
+ *
88
+ * `expected` / `received` are pre-stringified, one-line representations
89
+ * of the assertion's expected and received JS values. They are populated
90
+ * only when the underlying test runner error carries structured `.expected`
91
+ * / `.actual` properties (assertion errors). The raw JS values stay in
92
+ * Vitest's internal error object; only the string representation crosses
93
+ * the schema boundary.
94
+ * @public
95
+ */
96
+ const ReportError = Schema.Struct({
97
+ message: Schema.String,
98
+ stack: Schema.optional(Schema.String),
99
+ diff: Schema.optional(Schema.String),
100
+ expected: Schema.optional(Schema.String),
101
+ received: Schema.optional(Schema.String)
102
+ }).annotations({ identifier: "ReportError" });
103
+
104
+ //#endregion
105
+ export { AgentConsoleMode, CiConsoleMode, ConsoleMode, ConsoleOutputMode, DetailLevel, Environment, Executor, HumanConsoleMode, OutputFormat, PackageManager, ReportError, TestClassification, TestRunReason, TestState };
@@ -0,0 +1,28 @@
1
+ import { Schema } from "effect";
2
+
3
+ //#region src/schemas/Config.ts
4
+ /**
5
+ * Schema for the optional `vitest-agent.config.toml` file.
6
+ *
7
+ * Both fields are optional. When the file is absent or these fields are
8
+ * unset, `resolveDataPath` falls back to deriving the path from the
9
+ * workspace's `package.json` `name` under the XDG data directory.
10
+ *
11
+ * Fields:
12
+ * - `cacheDir` — absolute path overriding the entire data directory. Highest
13
+ * precedence after the programmatic option. Use this to relocate the SQLite
14
+ * database (e.g. project-local `.vitest-agent/`) instead of the
15
+ * default XDG location.
16
+ * - `projectKey` — overrides the workspace key segment under the XDG data
17
+ * directory. Use this when two unrelated projects on the same machine
18
+ * share a `package.json` `name` (the collision case for workspace-name
19
+ * keying), or when you want a stable key independent of `name` changes.
20
+ * @public
21
+ */
22
+ var VitestAgentConfig = class extends Schema.Class("VitestAgentConfig")({
23
+ cacheDir: Schema.optional(Schema.String),
24
+ projectKey: Schema.optional(Schema.String)
25
+ }) {};
26
+
27
+ //#endregion
28
+ export { VitestAgentConfig };
@@ -0,0 +1,51 @@
1
+ import { MetricThresholds, PatternThresholds } from "./Thresholds.js";
2
+ import { Schema } from "effect";
3
+
4
+ //#region src/schemas/Coverage.ts
5
+ /**
6
+ * Aggregate coverage percentages across four istanbul metrics.
7
+ * @public
8
+ */
9
+ const CoverageTotals = Schema.Struct({
10
+ statements: Schema.Number,
11
+ branches: Schema.Number,
12
+ functions: Schema.Number,
13
+ lines: Schema.Number
14
+ }).annotations({ identifier: "CoverageTotals" });
15
+ /**
16
+ * Per-file coverage data including uncovered line ranges.
17
+ * @public
18
+ */
19
+ const FileCoverageReport = Schema.Struct({
20
+ file: Schema.String,
21
+ summary: CoverageTotals,
22
+ uncoveredLines: Schema.String
23
+ }).annotations({ identifier: "FileCoverageReport" });
24
+ /**
25
+ * Complete coverage report attached to an AgentReport.
26
+ * @public
27
+ */
28
+ const CoverageReport = Schema.Struct({
29
+ totals: CoverageTotals,
30
+ thresholds: Schema.Struct({
31
+ global: MetricThresholds,
32
+ patterns: Schema.optionalWith(Schema.Array(PatternThresholds), { default: () => [] })
33
+ }),
34
+ targets: Schema.optional(Schema.Struct({
35
+ global: MetricThresholds,
36
+ patterns: Schema.optionalWith(Schema.Array(PatternThresholds), { default: () => [] })
37
+ })),
38
+ baselines: Schema.optional(Schema.Struct({
39
+ global: MetricThresholds,
40
+ patterns: Schema.optionalWith(Schema.Array(PatternThresholds), { default: () => [] })
41
+ })),
42
+ scoped: Schema.optionalWith(Schema.Boolean, { default: () => false }),
43
+ scopedFiles: Schema.optional(Schema.Array(Schema.String)),
44
+ lowCoverage: Schema.Array(FileCoverageReport),
45
+ lowCoverageFiles: Schema.Array(Schema.String),
46
+ belowTarget: Schema.optional(Schema.Array(FileCoverageReport)),
47
+ belowTargetFiles: Schema.optional(Schema.Array(Schema.String))
48
+ }).annotations({ identifier: "CoverageReport" });
49
+
50
+ //#endregion
51
+ export { CoverageReport, CoverageTotals, FileCoverageReport };