@vitest-agent/sdk 3.1.1 → 4.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 (66) hide show
  1. package/README.md +23 -19
  2. package/dispatch.d.ts +25 -6
  3. package/formatters/markdown.js +1 -0
  4. package/formatters/terminal.js +4 -3
  5. package/index.d.ts +448 -2341
  6. package/index.js +10 -68
  7. package/internal-inject-env.js +5 -7
  8. package/package.json +3 -19
  9. package/schemas/run-report-file-1.0.0.json +18 -18
  10. package/sidecar-dispatch.js +7 -5
  11. package/utils/format-console.js +9 -10
  12. package/utils/format-terminal.js +7 -7
  13. package/utils/posix-path.js +52 -0
  14. package/utils/test-location.js +11 -5
  15. package/version.js +17 -0
  16. package/layers/ConfigLive.js +0 -46
  17. package/layers/DataReaderLive.js +0 -1923
  18. package/layers/DataStoreLive.js +0 -1287
  19. package/layers/DetailResolverLive.js +0 -9
  20. package/layers/DiscoveryRegistryLive.js +0 -70
  21. package/layers/EnvironmentDetectorLive.js +0 -21
  22. package/layers/EnvironmentDetectorTest.js +0 -13
  23. package/layers/ExecutorResolverLive.js +0 -9
  24. package/layers/FormatSelectorLive.js +0 -20
  25. package/layers/HistoryTrackerLive.js +0 -49
  26. package/layers/HistoryTrackerTest.js +0 -25
  27. package/layers/LoggerLive.js +0 -64
  28. package/layers/OutputPipelineLive.js +0 -13
  29. package/layers/OutputRendererLive.js +0 -28
  30. package/layers/PathResolutionLive.js +0 -40
  31. package/layers/PerClientSessionMapLive.js +0 -145
  32. package/layers/ProjectDiscoveryLive.js +0 -68
  33. package/layers/ProjectDiscoveryTest.js +0 -12
  34. package/layers/ProjectIdentityLive.js +0 -96
  35. package/layers/RunContextLive.js +0 -81
  36. package/lib/format-triage.js +0 -103
  37. package/lib/format-wrapup.js +0 -67
  38. package/migrations/0001_initial.js +0 -824
  39. package/migrations/0002_test_artifacts.js +0 -30
  40. package/migrations/index.js +0 -26
  41. package/migrations/registry_0001_initial.js +0 -39
  42. package/migrations/session_map_0001_initial.js +0 -38
  43. package/services/Config.js +0 -15
  44. package/services/DataReader.js +0 -8
  45. package/services/DataStore.js +0 -15
  46. package/services/DetailResolver.js +0 -8
  47. package/services/DiscoveryRegistry.js +0 -8
  48. package/services/EnvironmentDetector.js +0 -8
  49. package/services/ExecutorResolver.js +0 -8
  50. package/services/FormatSelector.js +0 -8
  51. package/services/HistoryTracker.js +0 -20
  52. package/services/OutputRenderer.js +0 -8
  53. package/services/PerClientSessionMap.js +0 -22
  54. package/services/ProjectDiscovery.js +0 -8
  55. package/services/ProjectIdentity.js +0 -63
  56. package/services/RunContext.js +0 -53
  57. package/services/idempotency.js +0 -58
  58. package/sql/assemblers.js +0 -69
  59. package/testing/layers.js +0 -21
  60. package/testing.d.ts +0 -1862
  61. package/testing.js +0 -254
  62. package/utils/ensure-migrated.js +0 -52
  63. package/utils/failure-signature.js +0 -34
  64. package/utils/resolve-data-path.js +0 -65
  65. package/utils/resolve-project-key-from-cwd.js +0 -53
  66. package/utils/resolve-workspace-key.js +0 -41
package/index.d.ts CHANGED
@@ -1,9 +1,4 @@
1
- import { Context, Effect, FileSystem, Layer, LogLevel, Option, Path, PubSub, Schema } from "effect";
2
- import { ConfigFileShape } from "@effected/config-file";
3
- import { SqlClient } from "effect/unstable/sql/SqlClient";
4
- import { WorkspaceDiscovery, WorkspaceDiscoveryFailure, WorkspaceRootNotFoundError } from "@effected/workspaces";
5
- import { AppDirs } from "@effected/xdg";
6
- import { ChildProcessSpawner } from "effect/unstable/process";
1
+ import { PubSub, Schema } from "effect";
7
2
  //#region src/schemas/Coverage.d.ts
8
3
  /**
9
4
  * Aggregate coverage percentages across four istanbul metrics.
@@ -972,6 +967,12 @@ export type RenderedOutput = {
972
967
  /** @public */
973
968
  export interface FormatterContext {
974
969
  readonly detail: DetailLevel;
970
+ /**
971
+ * Absolute project root the run executed from. Formatters strip it from
972
+ * absolute file paths for display and resolve relative paths back against
973
+ * it for `file://` hyperlinks — the core never reads `process.cwd()`.
974
+ */
975
+ readonly cwd: string;
975
976
  readonly noColor: boolean;
976
977
  readonly coverageConsoleLimit: number;
977
978
  readonly trendSummary?: {
@@ -1978,70 +1979,63 @@ export declare const SilentFormatter: Formatter;
1978
1979
  /** @public */
1979
1980
  export declare const TerminalFormatter: Formatter;
1980
1981
  //#endregion
1981
- //#region src/schemas/Config.d.ts
1982
- declare const VitestAgentConfig_base: Schema.Class<VitestAgentConfig, Schema.Struct<{
1983
- readonly cacheDir: Schema.optional<Schema.String>;
1984
- readonly projectKey: Schema.optional<Schema.String>;
1982
+ //#region src/schemas/Agent.d.ts
1983
+ declare const Agent_base: Schema.Class<Agent, Schema.TaggedStruct<"Agent", {
1984
+ readonly agentId: Schema.brand<Schema.String, "AgentId">;
1985
+ readonly sessionId: Schema.Number;
1986
+ readonly parentAgentId: Schema.NullOr<Schema.brand<Schema.String, "AgentId">>;
1987
+ readonly conversationId: Schema.NullOr<Schema.brand<Schema.String, "ConversationId">>;
1988
+ readonly agentType: Schema.String;
1989
+ readonly startedAt: Schema.Number;
1990
+ readonly endedAt: Schema.NullOr<Schema.Number>;
1991
+ readonly startGitBranch: Schema.NullOr<Schema.String>;
1992
+ readonly startGitCommitSha: Schema.NullOr<Schema.String>;
1993
+ readonly startWorktreeDir: Schema.NullOr<Schema.String>;
1994
+ readonly idempotencyKey: Schema.String;
1985
1995
  }>, {}>;
1986
1996
  /**
1987
- * Schema for the optional `vitest-agent.config.toml` file.
1988
- *
1989
- * Both fields are optional. When the file is absent or these fields are
1990
- * unset, `resolveDataPath` falls back to deriving the path from the
1991
- * workspace's `package.json` `name` under the XDG data directory.
1997
+ * Successful registration row. The fields mirror the `agents` SQLite
1998
+ * table 1:1 in camelCase.
1992
1999
  *
1993
- * Fields:
1994
- * - `cacheDir` — absolute path overriding the entire data directory. Highest
1995
- * precedence after the programmatic option. Use this to relocate the SQLite
1996
- * database (e.g. project-local `.vitest-agent/`) instead of the
1997
- * default XDG location.
1998
- * - `projectKey` — overrides the workspace key segment under the XDG data
1999
- * directory. Use this when two unrelated projects on the same machine
2000
- * share a `package.json` `name` (the collision case for workspace-name
2001
- * keying), or when you want a stable key independent of `name` changes.
2000
+ * `startGitBranch`, `startGitCommitSha`, `startWorktreeDir` capture
2001
+ * *what the agent inherited at registration time* — distinct from the
2002
+ * per-run git context recorded on `runs`. A divergence between the
2003
+ * two reveals a mid-session branch switch, which is itself signal.
2002
2004
  * @public
2003
2005
  */
2004
- export declare class VitestAgentConfig extends VitestAgentConfig_base {}
2005
- //#endregion
2006
- //#region src/services/Config.d.ts
2006
+ export declare class Agent extends Agent_base {}
2007
+ declare const IdempotencyHit_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => Readonly<A> & {
2008
+ readonly _tag: "IdempotencyHit";
2009
+ } & import("effect/Pipeable").Pipeable;
2007
2010
  /**
2008
- * Service shape that `ConfigLive(projectDir)` provides to downstream
2009
- * consumers. Re-exported so callers can spell out the concrete service
2010
- * type without referencing the `ConfigFileShape<A>` generic directly.
2011
+ * Returned by `DataStore.registerAgent` when the
2012
+ * `(session_id, idempotency_key)` UNIQUE constraint already has a
2013
+ * row. Not an error — the caller treats it as a successful recovery
2014
+ * of the existing `agentId`.
2015
+ *
2016
+ * Modeled as a `Data.TaggedClass` so the success channel of
2017
+ * `registerAgent` is `Effect<Agent | IdempotencyHit, ...>` and
2018
+ * downstream code uses `Match.tag` to branch.
2011
2019
  * @public
2012
2020
  */
2013
- export type VitestAgentConfigFileService = ConfigFileShape<VitestAgentConfig>;
2014
- declare const VitestAgentConfigFile_base: import("effect/Context").ServiceClass<VitestAgentConfigFile, "vitest-agent/Config", ConfigFileShape<VitestAgentConfig>>;
2021
+ export declare class IdempotencyHit extends IdempotencyHit_base<{
2022
+ readonly existingAgentId: typeof AgentId.Type;
2023
+ }> {}
2015
2024
  /**
2016
- * Typed service class (Context tag) for the vitest-agent config file service.
2017
- *
2018
- * Both runtime packages (reporter, MCP) yield this tag to access the loaded
2019
- * `VitestAgentConfig`. The live layer is built per `projectDir` via
2020
- * `ConfigLive(projectDir)`.
2025
+ * Sum type of the two possible outcomes of `registerAgent`.
2021
2026
  * @public
2022
2027
  */
2023
- export declare class VitestAgentConfigFile extends VitestAgentConfigFile_base {}
2024
- //#endregion
2025
- //#region src/layers/ConfigLive.d.ts
2028
+ export type RegisterAgentResult = Agent | IdempotencyHit;
2026
2029
  /**
2027
- * Build the live `ConfigFile` layer for a given project directory.
2028
- *
2029
- * Resolves the optional `vitest-agent.config.toml` from (in order):
2030
- *
2031
- * 1. The workspace root (when `projectDir` is inside a pnpm/npm/yarn workspace).
2032
- * 2. The git repository root (when `projectDir` is inside a git repo).
2033
- * 3. Walking upward from `projectDir`.
2034
- *
2035
- * The first found file wins (`MergeStrategy.firstMatch()`). If no file is
2036
- * present, downstream callers use `loadOrDefault(new VitestAgentConfig({}))`
2037
- * to get an empty config.
2038
- *
2039
- * @param projectDir - Absolute path inside the user's workspace. Resolvers
2040
- * anchor here rather than `process.cwd()` so the plugin-spawned MCP server
2041
- * sees the right config even when invoked from elsewhere.
2030
+ * Agent tree — root agent with all descendants nested under
2031
+ * `children`. Returned by `DataStore.getAgentTree` for forensics and
2032
+ * the `vitest-agent agent list` CLI subcommand.
2042
2033
  * @public
2043
2034
  */
2044
- export declare const ConfigLive: (projectDir: string) => Layer.Layer<VitestAgentConfigFile, never, FileSystem.FileSystem | Path.Path>;
2035
+ export interface AgentTreeNode {
2036
+ readonly agent: Agent;
2037
+ readonly children: ReadonlyArray<AgentTreeNode>;
2038
+ }
2045
2039
  //#endregion
2046
2040
  //#region src/schemas/Baselines.d.ts
2047
2041
  /**
@@ -2104,2107 +2098,87 @@ export declare const CacheManifest: Schema.Struct<{
2104
2098
  /** @public */
2105
2099
  export type CacheManifest = typeof CacheManifest.Type;
2106
2100
  //#endregion
2107
- //#region src/schemas/History.d.ts
2108
- /**
2109
- * A single test run outcome (pass or fail only).
2110
- * @public
2111
- */
2112
- export declare const TestRun: Schema.Struct<{
2113
- readonly timestamp: Schema.String;
2114
- readonly state: Schema.Literals<readonly ["passed", "failed"]>;
2115
- }>;
2101
+ //#region src/schemas/ChannelEvent.d.ts
2116
2102
  /** @public */
2117
- export type TestRun = typeof TestRun.Type;
2118
- /**
2119
- * History for a single test across multiple runs.
2120
- * @public
2121
- */
2122
- export declare const TestHistory: Schema.Struct<{
2123
- readonly modulePath: Schema.String;
2124
- readonly fullName: Schema.String;
2125
- readonly runs: Schema.$Array<Schema.Struct<{
2126
- readonly timestamp: Schema.String;
2127
- readonly state: Schema.Literals<readonly ["passed", "failed"]>;
2128
- }>>;
2129
- }>;
2103
+ export declare const SessionOutcome: Schema.Literals<readonly ["succeeded", "blocked", "abandoned"]>;
2130
2104
  /** @public */
2131
- export type TestHistory = typeof TestHistory.Type;
2132
- /**
2133
- * Per-project history record containing all tracked tests.
2134
- * @public
2135
- */
2136
- export declare const HistoryRecord: Schema.Struct<{
2137
- readonly project: Schema.String;
2138
- readonly updatedAt: Schema.String;
2139
- readonly tests: Schema.$Array<Schema.Struct<{
2140
- readonly modulePath: Schema.String;
2141
- readonly fullName: Schema.String;
2142
- readonly runs: Schema.$Array<Schema.Struct<{
2143
- readonly timestamp: Schema.String;
2144
- readonly state: Schema.Literals<readonly ["passed", "failed"]>;
2145
- }>>;
2105
+ export type SessionOutcome = typeof SessionOutcome.Type;
2106
+ /** @public */
2107
+ export declare const GoalsReadyEvent: Schema.Struct<{
2108
+ readonly type: Schema.Literal<"goals_ready">;
2109
+ readonly sessionId: Schema.Number;
2110
+ readonly goals: Schema.$Array<Schema.Struct<{
2111
+ readonly id: Schema.Number;
2112
+ readonly ordinal: Schema.Number;
2113
+ readonly goal: Schema.String;
2146
2114
  }>>;
2147
2115
  }>;
2148
2116
  /** @public */
2149
- export type HistoryRecord = typeof HistoryRecord.Type;
2150
- //#endregion
2151
- //#region src/schemas/Tdd.d.ts
2117
+ export type GoalsReadyEvent = typeof GoalsReadyEvent.Type;
2152
2118
  /** @public */
2153
- export declare const GoalStatus: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2119
+ export declare const GoalAddedEvent: Schema.Struct<{
2120
+ readonly type: Schema.Literal<"goal_added">;
2121
+ readonly sessionId: Schema.Number;
2122
+ readonly goal: Schema.Struct<{
2123
+ readonly id: Schema.Number;
2124
+ readonly ordinal: Schema.Number;
2125
+ readonly goal: Schema.String;
2126
+ }>;
2127
+ }>;
2154
2128
  /** @public */
2155
- export type GoalStatus = typeof GoalStatus.Type;
2129
+ export type GoalAddedEvent = typeof GoalAddedEvent.Type;
2156
2130
  /** @public */
2157
- export declare const BehaviorStatus: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2131
+ export declare const GoalStartedEvent: Schema.Struct<{
2132
+ readonly type: Schema.Literal<"goal_started">;
2133
+ readonly sessionId: Schema.Number;
2134
+ readonly goalId: Schema.Number;
2135
+ }>;
2158
2136
  /** @public */
2159
- export type BehaviorStatus = typeof BehaviorStatus.Type;
2137
+ export type GoalStartedEvent = typeof GoalStartedEvent.Type;
2160
2138
  /** @public */
2161
- export declare const GoalRow: Schema.Struct<{
2162
- readonly id: Schema.Number;
2139
+ export declare const GoalCompletedEvent: Schema.Struct<{
2140
+ readonly type: Schema.Literal<"goal_completed">;
2163
2141
  readonly sessionId: Schema.Number;
2164
- readonly ordinal: Schema.Number;
2165
- readonly goal: Schema.String;
2166
- readonly status: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2167
- readonly createdAt: Schema.String;
2142
+ readonly goalId: Schema.Number;
2143
+ readonly behaviorIds: Schema.$Array<Schema.Number>;
2168
2144
  }>;
2169
2145
  /** @public */
2170
- export type GoalRow = typeof GoalRow.Type;
2146
+ export type GoalCompletedEvent = typeof GoalCompletedEvent.Type;
2171
2147
  /** @public */
2172
- export declare const BehaviorRow: Schema.Struct<{
2173
- readonly id: Schema.Number;
2148
+ export declare const GoalAbandonedEvent: Schema.Struct<{
2149
+ readonly type: Schema.Literal<"goal_abandoned">;
2150
+ readonly sessionId: Schema.Number;
2174
2151
  readonly goalId: Schema.Number;
2175
- readonly ordinal: Schema.Number;
2176
- readonly behavior: Schema.String;
2177
- readonly suggestedTestName: Schema.NullOr<Schema.String>;
2178
- readonly status: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2179
- readonly createdAt: Schema.String;
2152
+ readonly reason: Schema.String;
2180
2153
  }>;
2181
2154
  /** @public */
2182
- export type BehaviorRow = typeof BehaviorRow.Type;
2155
+ export type GoalAbandonedEvent = typeof GoalAbandonedEvent.Type;
2183
2156
  /** @public */
2184
- export declare const GoalDetail: Schema.Struct<{
2185
- readonly id: Schema.Number;
2157
+ export declare const BehaviorsReadyEvent: Schema.Struct<{
2158
+ readonly type: Schema.Literal<"behaviors_ready">;
2186
2159
  readonly sessionId: Schema.Number;
2187
- readonly ordinal: Schema.Number;
2188
- readonly goal: Schema.String;
2189
- readonly status: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2190
- readonly createdAt: Schema.String;
2160
+ readonly goalId: Schema.Number;
2191
2161
  readonly behaviors: Schema.$Array<Schema.Struct<{
2192
2162
  readonly id: Schema.Number;
2193
- readonly goalId: Schema.Number;
2194
2163
  readonly ordinal: Schema.Number;
2195
2164
  readonly behavior: Schema.String;
2196
- readonly suggestedTestName: Schema.NullOr<Schema.String>;
2197
- readonly status: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2198
- readonly createdAt: Schema.String;
2199
2165
  }>>;
2200
2166
  }>;
2201
2167
  /** @public */
2202
- export type GoalDetail = typeof GoalDetail.Type;
2168
+ export type BehaviorsReadyEvent = typeof BehaviorsReadyEvent.Type;
2203
2169
  /** @public */
2204
- export declare const BehaviorDetail: Schema.Struct<{
2205
- readonly id: Schema.Number;
2170
+ export declare const BehaviorAddedEvent: Schema.Struct<{
2171
+ readonly type: Schema.Literal<"behavior_added">;
2172
+ readonly sessionId: Schema.Number;
2206
2173
  readonly goalId: Schema.Number;
2207
- readonly ordinal: Schema.Number;
2208
- readonly behavior: Schema.String;
2209
- readonly suggestedTestName: Schema.NullOr<Schema.String>;
2210
- readonly status: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2211
- readonly createdAt: Schema.String;
2212
- readonly parentGoal: Schema.Struct<{
2213
- readonly id: Schema.Number;
2214
- readonly goal: Schema.String;
2215
- readonly status: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2216
- }>;
2217
- readonly dependencies: Schema.$Array<Schema.Struct<{
2174
+ readonly behavior: Schema.Struct<{
2218
2175
  readonly id: Schema.Number;
2219
- readonly goalId: Schema.Number;
2220
2176
  readonly ordinal: Schema.Number;
2221
2177
  readonly behavior: Schema.String;
2222
- readonly suggestedTestName: Schema.NullOr<Schema.String>;
2223
- readonly status: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2224
- readonly createdAt: Schema.String;
2225
- }>>;
2226
- }>;
2227
- /** @public */
2228
- export type BehaviorDetail = typeof BehaviorDetail.Type;
2229
- //#endregion
2230
- //#region src/schemas/Trends.d.ts
2231
- /**
2232
- * A single coverage trend data point recorded on a full test run.
2233
- * @public
2234
- */
2235
- export declare const TrendEntry: Schema.Struct<{
2236
- readonly timestamp: Schema.String;
2237
- readonly coverage: Schema.Struct<{
2238
- readonly statements: Schema.Number;
2239
- readonly branches: Schema.Number;
2240
- readonly functions: Schema.Number;
2241
- readonly lines: Schema.Number;
2242
- }>;
2243
- readonly delta: Schema.Struct<{
2244
- readonly statements: Schema.Number;
2245
- readonly branches: Schema.Number;
2246
- readonly functions: Schema.Number;
2247
- readonly lines: Schema.Number;
2248
2178
  }>;
2249
- readonly direction: Schema.Literals<readonly ["improving", "regressing", "stable"]>;
2250
- readonly targetsHash: Schema.optional<Schema.String>;
2251
2179
  }>;
2252
2180
  /** @public */
2253
- export type TrendEntry = typeof TrendEntry.Type;
2254
- /**
2255
- * Per-project trend record with sliding window of entries.
2256
- * @public
2257
- */
2258
- export declare const TrendRecord: Schema.Struct<{
2259
- readonly entries: Schema.$Array<Schema.Struct<{
2260
- readonly timestamp: Schema.String;
2261
- readonly coverage: Schema.Struct<{
2262
- readonly statements: Schema.Number;
2263
- readonly branches: Schema.Number;
2264
- readonly functions: Schema.Number;
2265
- readonly lines: Schema.Number;
2266
- }>;
2267
- readonly delta: Schema.Struct<{
2268
- readonly statements: Schema.Number;
2269
- readonly branches: Schema.Number;
2270
- readonly functions: Schema.Number;
2271
- readonly lines: Schema.Number;
2272
- }>;
2273
- readonly direction: Schema.Literals<readonly ["improving", "regressing", "stable"]>;
2274
- readonly targetsHash: Schema.optional<Schema.String>;
2275
- }>>;
2276
- }>;
2277
- /** @public */
2278
- export type TrendRecord = typeof TrendRecord.Type;
2279
- //#endregion
2280
- //#region src/utils/validate-phase-transition.d.ts
2281
- /** @public */
2282
- export type Phase = "spike" | "red" | "red.triangulate" | "green" | "green.fake-it" | "refactor" | "extended-red" | "green-without-red";
2283
- /** @public */
2284
- export type ArtifactKind = "test_written" | "test_failed_run" | "code_written" | "test_passed_run" | "refactor" | "test_weakened";
2285
- /**
2286
- * Explicit test-runner marker on a `tdd_artifacts` row (issue #363). `vitest`
2287
- * artifacts always carry a `test_case_id` when they anchor a specific test;
2288
- * `bats` artifacts never do (there is no `test_cases` row for a bats test),
2289
- * so the D2 binding-rule validator branches on this to accept a bats
2290
- * run-level artifact without weakening the vitest guard.
2291
- * @public
2292
- */
2293
- export type ArtifactSuite = "vitest" | "bats";
2294
- /** @public */
2295
- export interface CitedArtifact {
2296
- readonly id: number;
2297
- /**
2298
- * `tdd_phases.id` of the phase this artifact was actually recorded in — the
2299
- * artifact's own phase binding. This is the honest anchor for D2 binding
2300
- * rule 1's window check (issue #245): a test_case's first-ever creation
2301
- * turn can predate the current phase (e.g. authored during spike, then
2302
- * re-run inside red) without the evidence itself being stale, so the
2303
- * window check compares this against `PhaseTransitionContext.current_phase_id`
2304
- * rather than `test_case_created_turn_at`.
2305
- */
2306
- readonly phase_id: number;
2307
- readonly artifact_kind: ArtifactKind;
2308
- readonly test_case_id: number | null;
2309
- readonly test_case_created_turn_at: string | null;
2310
- readonly test_case_authored_in_session: boolean;
2311
- readonly test_run_id: number | null;
2312
- readonly test_first_failure_run_id: number | null;
2313
- readonly behavior_id: number | null;
2314
- /**
2315
- * Issue #363: explicit suite marker distinguishing vitest from bats runs.
2316
- * Optional on the pure type so hand-built contexts default to `vitest`;
2317
- * the DB row always carries the persisted value.
2318
- */
2319
- readonly suite?: ArtifactSuite;
2320
- }
2321
- /** @public */
2322
- export interface PhaseTransitionContext {
2323
- readonly tdd_task_id: number;
2324
- readonly current_phase: Phase;
2325
- /**
2326
- * `tdd_phases.id` of the currently open phase row, or `null` when no phase
2327
- * has been opened yet (the implicit "spike" default before the first
2328
- * `tdd_phases` row exists). Compared against `cited_artifact.phase_id` for
2329
- * D2 binding rule 1 (issue #245).
2330
- */
2331
- readonly current_phase_id: number | null;
2332
- readonly phase_started_at: string;
2333
- readonly now: string;
2334
- readonly requested_phase: Phase;
2335
- readonly cited_artifact: CitedArtifact;
2336
- readonly requested_behavior_id: number | null;
2337
- }
2338
- /** @public */
2339
- export type DenialReason = "missing_artifact_evidence" | "wrong_artifact_kind" | "wrong_source_phase" | "unknown_tdd_task" | "tdd_task_already_ended" | "goal_not_started" | "goal_not_found" | "goal_not_in_progress" | "goal_not_in_tdd_task" | "behavior_not_found" | "behavior_not_in_goal" | "refactor_without_passing_run" | "evidence_not_in_phase_window" | "evidence_not_for_behavior" | "evidence_test_was_already_failing";
2340
- /** @public */
2341
- export interface Remediation {
2342
- readonly suggestedTool: string;
2343
- readonly suggestedArgs: Record<string, unknown>;
2344
- readonly humanHint: string;
2345
- }
2346
- /** @public */
2347
- export type PhaseTransitionResult = {
2348
- readonly accepted: true;
2349
- readonly phase: Phase;
2350
- } | {
2351
- readonly accepted: false;
2352
- readonly phase: Phase;
2353
- readonly denialReason: DenialReason;
2354
- readonly remediation: Remediation;
2355
- };
2356
- /**
2357
- * Return the artifact kind a phase transition requires, plus a
2358
- * human-readable hint for surfacing in remediations.
2359
- *
2360
- * Exported so the MCP `tdd_phase_transition_request` tool can pre-compute
2361
- * the expected kind when the agent omits `citedArtifactId` (auto-resolve
2362
- * to the most recent matching artifact). The transitions without a
2363
- * required artifact (`spike→red`, `*→red`, etc.) return `null`.
2364
- * @public
2365
- */
2366
- export declare const requiredArtifactForTransition: (from: Phase, to: Phase) => {
2367
- kind: ArtifactKind;
2368
- humanHint: string;
2369
- } | null;
2370
- /**
2371
- * Whether D2 binding rule 2 (behavior-match) applies to a given transition.
2372
- *
2373
- * Only the transitions whose cited evidence must belong to the behavior being
2374
- * transitioned enforce behavior-match: `red→green` (the failing test for this
2375
- * behavior) and `green→refactor` (its passing test). It deliberately excludes
2376
- * `red.triangulate→green` (the cited failing run belongs to an earlier batch
2377
- * behavior) and `refactor→red` (the required `test_passed_run` is the
2378
- * just-finished behavior's, never the new target). Exported so the MCP
2379
- * `tdd_phase_transition_request` tool scopes artifact auto-resolution by
2380
- * behavior on exactly the same transitions the validator will accept —
2381
- * keeping the two in lockstep (issue #115).
2382
- * @public
2383
- */
2384
- export declare const transitionEnforcesBehaviorMatch: (from: Phase, to: Phase) => boolean;
2385
- /** @public */
2386
- export declare const validatePhaseTransition: (ctx: PhaseTransitionContext) => PhaseTransitionResult;
2387
- //#endregion
2388
- //#region src/schemas/Agent.d.ts
2389
- declare const Agent_base: Schema.Class<Agent, Schema.TaggedStruct<"Agent", {
2390
- readonly agentId: Schema.brand<Schema.String, "AgentId">;
2391
- readonly sessionId: Schema.Number;
2392
- readonly parentAgentId: Schema.NullOr<Schema.brand<Schema.String, "AgentId">>;
2393
- readonly conversationId: Schema.NullOr<Schema.brand<Schema.String, "ConversationId">>;
2394
- readonly agentType: Schema.String;
2395
- readonly startedAt: Schema.Number;
2396
- readonly endedAt: Schema.NullOr<Schema.Number>;
2397
- readonly startGitBranch: Schema.NullOr<Schema.String>;
2398
- readonly startGitCommitSha: Schema.NullOr<Schema.String>;
2399
- readonly startWorktreeDir: Schema.NullOr<Schema.String>;
2400
- readonly idempotencyKey: Schema.String;
2401
- }>, {}>;
2402
- /**
2403
- * Successful registration row. The fields mirror the `agents` SQLite
2404
- * table 1:1 in camelCase.
2405
- *
2406
- * `startGitBranch`, `startGitCommitSha`, `startWorktreeDir` capture
2407
- * *what the agent inherited at registration time* — distinct from the
2408
- * per-run git context recorded on `runs`. A divergence between the
2409
- * two reveals a mid-session branch switch, which is itself signal.
2410
- * @public
2411
- */
2412
- export declare class Agent extends Agent_base {}
2413
- declare const IdempotencyHit_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => Readonly<A> & {
2414
- readonly _tag: "IdempotencyHit";
2415
- } & import("effect/Pipeable").Pipeable;
2416
- /**
2417
- * Returned by `DataStore.registerAgent` when the
2418
- * `(session_id, idempotency_key)` UNIQUE constraint already has a
2419
- * row. Not an error — the caller treats it as a successful recovery
2420
- * of the existing `agentId`.
2421
- *
2422
- * Modeled as a `Data.TaggedClass` so the success channel of
2423
- * `registerAgent` is `Effect<Agent | IdempotencyHit, ...>` and
2424
- * downstream code uses `Match.tag` to branch.
2425
- * @public
2426
- */
2427
- export declare class IdempotencyHit extends IdempotencyHit_base<{
2428
- readonly existingAgentId: typeof AgentId.Type;
2429
- }> {}
2430
- /**
2431
- * Sum type of the two possible outcomes of `registerAgent`.
2432
- * @public
2433
- */
2434
- export type RegisterAgentResult = Agent | IdempotencyHit;
2435
- /**
2436
- * Agent tree — root agent with all descendants nested under
2437
- * `children`. Returned by `DataStore.getAgentTree` for forensics and
2438
- * the `vitest-agent agent list` CLI subcommand.
2439
- * @public
2440
- */
2441
- export interface AgentTreeNode {
2442
- readonly agent: Agent;
2443
- readonly children: ReadonlyArray<AgentTreeNode>;
2444
- }
2445
- //#endregion
2446
- //#region src/services/DataStore.d.ts
2447
- /** @public */
2448
- export interface CreateGoalInput {
2449
- readonly tddTaskId: number;
2450
- readonly goal: string;
2451
- }
2452
- /** @public */
2453
- export interface UpdateGoalInput {
2454
- readonly id: number;
2455
- readonly goal?: string;
2456
- readonly status?: GoalStatus;
2457
- }
2458
- /** @public */
2459
- export interface CreateBehaviorInput {
2460
- readonly goalId: number;
2461
- readonly behavior: string;
2462
- readonly suggestedTestName?: string;
2463
- readonly dependsOnBehaviorIds?: ReadonlyArray<number>;
2464
- }
2465
- /** @public */
2466
- export interface UpdateBehaviorInput {
2467
- readonly id: number;
2468
- readonly behavior?: string;
2469
- readonly suggestedTestName?: string | null;
2470
- readonly status?: BehaviorStatus;
2471
- readonly dependsOnBehaviorIds?: ReadonlyArray<number>;
2472
- }
2473
- /** @public */
2474
- export interface SettingsInput {
2475
- readonly vitestVersion: string;
2476
- readonly pool?: string;
2477
- readonly environment?: string;
2478
- readonly testTimeout?: number;
2479
- readonly hookTimeout?: number;
2480
- readonly slowTestThreshold?: number;
2481
- readonly maxConcurrency?: number;
2482
- readonly maxWorkers?: number;
2483
- readonly isolate?: boolean;
2484
- readonly bail?: number;
2485
- readonly globals?: boolean;
2486
- readonly fileParallelism?: boolean;
2487
- readonly sequenceSeed?: number;
2488
- readonly coverageProvider?: string;
2489
- }
2490
- /** @public */
2491
- export interface TestRunInput {
2492
- readonly invocationId: string;
2493
- readonly project: string;
2494
- readonly settingsHash: string;
2495
- readonly timestamp: string;
2496
- readonly commitSha: string | null;
2497
- readonly branch: string | null;
2498
- readonly reason: "passed" | "failed" | "interrupted";
2499
- readonly duration: number;
2500
- readonly total: number;
2501
- readonly passed: number;
2502
- readonly failed: number;
2503
- readonly skipped: number;
2504
- readonly scoped: boolean;
2505
- readonly snapshotAdded?: number;
2506
- readonly snapshotMatched?: number;
2507
- readonly snapshotUnmatched?: number;
2508
- readonly snapshotUpdated?: number;
2509
- readonly snapshotUnchecked?: number;
2510
- readonly snapshotTotal?: number;
2511
- readonly snapshotFailure?: boolean;
2512
- readonly snapshotDidUpdate?: boolean;
2513
- readonly snapshotFilesAdded?: number;
2514
- readonly snapshotFilesRemoved?: number;
2515
- readonly snapshotFilesUnmatched?: number;
2516
- readonly snapshotFilesUpdated?: number;
2517
- /**
2518
- * Attribution columns added by the agent-agnostic taxonomy work. The
2519
- * reporter walks env vars / session map to populate these; un-attributed
2520
- * runs default to actor_type='system' and NULL agent/conversation ids.
2521
- */
2522
- readonly actorType?: "agent" | "user" | "system";
2523
- readonly agentId?: string | null;
2524
- readonly conversationId?: string | null;
2525
- /**
2526
- * Git context the run executed against. NULL for non-git workspaces.
2527
- */
2528
- readonly gitBranch?: string | null;
2529
- readonly gitCommitSha?: string | null;
2530
- readonly gitDirty?: boolean | null;
2531
- readonly gitUpstream?: string | null;
2532
- readonly gitWorktreeDir?: string | null;
2533
- /**
2534
- * Host metadata probe result (terminal pane, CI runner). NULL when no
2535
- * probe in the priority chain matched.
2536
- * @public
2537
- */
2538
- readonly hostSource?: string | null;
2539
- readonly hostValue?: string | null;
2540
- readonly hostMetadata?: Record<string, unknown> | null;
2541
- }
2542
- /** @public */
2543
- export interface ModuleInput {
2544
- readonly fileId: number;
2545
- readonly relativeModuleId: string;
2546
- readonly state: string;
2547
- readonly duration?: number;
2548
- readonly environmentSetupDuration?: number;
2549
- readonly prepareDuration?: number;
2550
- readonly collectDuration?: number;
2551
- readonly setupDuration?: number;
2552
- readonly heap?: number;
2553
- }
2554
- /** @public */
2555
- export interface TestCaseInput {
2556
- readonly suiteId?: number;
2557
- readonly vitestId?: string;
2558
- readonly name: string;
2559
- readonly fullName: string;
2560
- readonly state: string;
2561
- readonly classification?: string;
2562
- readonly duration?: number;
2563
- readonly startTime?: number;
2564
- readonly flaky?: boolean;
2565
- readonly slow?: boolean;
2566
- readonly retryCount?: number;
2567
- readonly repeatCount?: number;
2568
- readonly heap?: number;
2569
- readonly mode?: string;
2570
- readonly each?: boolean;
2571
- readonly fails?: boolean;
2572
- readonly concurrent?: boolean;
2573
- readonly shuffle?: boolean;
2574
- readonly timeout?: number;
2575
- readonly skipNote?: string;
2576
- readonly locationLine?: number;
2577
- readonly locationColumn?: number;
2578
- readonly tags?: readonly string[];
2579
- /**
2580
- * FK to `turns(id)`. Set by the reporter when the test case row was
2581
- * authored within a recorded turn (D2 binding rule 1).
2582
- * @public
2583
- */
2584
- readonly createdTurnId?: number;
2585
- }
2586
- /** @public */
2587
- export interface StackFrameInput {
2588
- readonly ordinal: number;
2589
- readonly method: string | null;
2590
- readonly filePath: string;
2591
- readonly line: number;
2592
- readonly col: number;
2593
- readonly sourceMappedLine?: number;
2594
- readonly functionBoundaryLine?: number;
2595
- }
2596
- /** @public */
2597
- export interface TestErrorInput {
2598
- readonly testCaseId?: number;
2599
- readonly testSuiteId?: number;
2600
- readonly moduleId?: number;
2601
- readonly scope: "test" | "suite" | "module" | "unhandled";
2602
- readonly name?: string;
2603
- readonly message: string;
2604
- readonly diff?: string;
2605
- readonly actual?: string;
2606
- readonly expected?: string;
2607
- readonly stack?: string;
2608
- readonly causeErrorId?: number;
2609
- readonly signatureHash?: string;
2610
- readonly frames?: ReadonlyArray<StackFrameInput>;
2611
- readonly ordinal?: number;
2612
- }
2613
- /**
2614
- * Ceiling on an inline attachment body. Vitest has already copied file
2615
- * attachments into `.vitest/attachments/`, so a large body is referenced
2616
- * by `path` rather than duplicated into `data.db`.
2617
- * @public
2618
- */
2619
- export declare const INLINE_ATTACHMENT_BODY_CAP_BYTES: number;
2620
- /** @public */
2621
- export interface TestAttachmentInput {
2622
- readonly contentType?: string;
2623
- /** Post-resolution path under `.vitest/attachments/`, or an http(s) URL. */
2624
- readonly path?: string;
2625
- /** Inline body; persisted only when `byteSize` is under the 64 KiB cap. */
2626
- readonly body?: string;
2627
- /** How to read `body`. Vitest treats a string body as base64 unless `"utf-8"`. */
2628
- readonly bodyEncoding?: "base64" | "utf-8";
2629
- readonly byteSize: number;
2630
- }
2631
- /** @public */
2632
- export interface TestAnnotationInput {
2633
- readonly testCaseId: number;
2634
- /** Arbitrary Vitest annotation type -- not an enum. */
2635
- readonly type: string;
2636
- readonly message: string;
2637
- readonly locationFile?: string;
2638
- readonly locationLine?: number;
2639
- readonly locationColumn?: number;
2640
- readonly attachments?: ReadonlyArray<TestAttachmentInput>;
2641
- }
2642
- /** @public */
2643
- export interface TestArtifactInput {
2644
- readonly testCaseId: number;
2645
- /** `pkg:name`; `internal:` types are Vitest's own and are never written. */
2646
- readonly type: string;
2647
- readonly message?: string;
2648
- /** JSON of the artifact's custom fields, minus attachments and location. */
2649
- readonly data?: string;
2650
- readonly locationFile?: string;
2651
- readonly locationLine?: number;
2652
- readonly locationColumn?: number;
2653
- readonly attachments?: ReadonlyArray<TestAttachmentInput>;
2654
- }
2655
- /** @public */
2656
- export interface FileCoverageInput {
2657
- readonly fileId: number;
2658
- readonly statements: number;
2659
- readonly branches: number;
2660
- readonly functions: number;
2661
- readonly lines: number;
2662
- readonly uncoveredLines?: string;
2663
- /**
2664
- * Coverage tier this row represents. `'below_threshold'` is the
2665
- * build-failing tier (file falls below the configured minimum
2666
- * coverage thresholds). `'below_target'` is the warning tier (file
2667
- * is above thresholds but below the aspirational target).
2668
- *
2669
- * Defaults to `'below_threshold'` when omitted, matching the only
2670
- * tier that existed before migration 0005.
2671
- * @public
2672
- */
2673
- readonly tier?: "below_threshold" | "below_target";
2674
- }
2675
- /** @public */
2676
- export interface SuiteInput {
2677
- readonly parentSuiteId?: number;
2678
- readonly name: string;
2679
- readonly fullName: string;
2680
- readonly state: "pending" | "passed" | "failed" | "skipped";
2681
- readonly mode?: "run" | "only" | "skip" | "todo";
2682
- readonly concurrent?: boolean;
2683
- readonly shuffle?: boolean;
2684
- readonly retry?: number;
2685
- readonly repeats?: number;
2686
- readonly locationLine?: number;
2687
- readonly locationColumn?: number;
2688
- }
2689
- /** @public */
2690
- export interface NoteInput {
2691
- readonly title: string;
2692
- readonly content: string;
2693
- readonly scope: "global" | "project" | "module" | "suite" | "test" | "note";
2694
- readonly project?: string;
2695
- readonly testFullName?: string;
2696
- readonly modulePath?: string;
2697
- readonly parentNoteId?: number;
2698
- readonly createdBy?: string;
2699
- readonly expiresAt?: string;
2700
- readonly pinned?: boolean;
2701
- }
2702
- /** @public */
2703
- export interface SessionInput {
2704
- readonly chatId: string;
2705
- readonly project: string;
2706
- readonly cwd: string;
2707
- readonly agentKind: "main" | "subagent";
2708
- readonly agentType?: string;
2709
- readonly parentSessionId?: number;
2710
- readonly triageWasNonEmpty?: boolean;
2711
- readonly startedAt: string;
2712
- /**
2713
- * Canonical conversation UUID this session belongs to (issue #144).
2714
- * Set once at INSERT time — `sessions.conversation_id` is immutable
2715
- * thereafter (see the `trg_sessions_conv_id_immutable` trigger), so
2716
- * omit it here rather than trying to backfill via an update.
2717
- */
2718
- readonly conversationId?: string;
2719
- }
2720
- /** @public */
2721
- export interface TurnInput {
2722
- readonly sessionId: number;
2723
- /** When omitted, writeTurn computes MAX(turnNo) + 1 for the session. */
2724
- readonly turnNo?: number;
2725
- readonly type: "user_prompt" | "tool_call" | "tool_result" | "file_edit" | "hook_fire" | "note" | "hypothesis";
2726
- readonly payload: string;
2727
- readonly occurredAt: string;
2728
- }
2729
- /** @public */
2730
- export interface FailureSignatureWriteInput {
2731
- readonly signatureHash: string;
2732
- readonly runId: number;
2733
- readonly seenAt: string;
2734
- }
2735
- /** @public */
2736
- export interface HypothesisInput {
2737
- readonly sessionId: number;
2738
- readonly content: string;
2739
- readonly createdTurnId?: number;
2740
- readonly citedTestErrorId?: number;
2741
- readonly citedStackFrameId?: number;
2742
- }
2743
- /** @public */
2744
- export interface ValidateHypothesisInput {
2745
- readonly id: number;
2746
- readonly outcome: "confirmed" | "refuted" | "abandoned";
2747
- readonly validatedTurnId?: number;
2748
- readonly validatedAt: string;
2749
- }
2750
- /** @public */
2751
- export interface IdempotentResponseInput {
2752
- readonly procedurePath: string;
2753
- readonly key: string;
2754
- readonly resultJson: string;
2755
- readonly createdAt: string;
2756
- }
2757
- /** @public */
2758
- export interface TddTaskInput {
2759
- readonly sessionId: number;
2760
- readonly goal: string;
2761
- readonly startedAt: string;
2762
- readonly parentTddTaskId?: number;
2763
- readonly runId?: string;
2764
- }
2765
- /** @public */
2766
- export interface EndTddTaskInput {
2767
- readonly id: number;
2768
- readonly endedAt: string;
2769
- readonly outcome: "succeeded" | "blocked" | "abandoned";
2770
- readonly summaryNoteId?: number;
2771
- }
2772
- /** @public */
2773
- export interface WriteTddPhaseInput {
2774
- readonly tddTaskId: number;
2775
- readonly behaviorId?: number;
2776
- readonly phase: Phase;
2777
- readonly startedAt: string;
2778
- readonly transitionReason?: string;
2779
- readonly parentPhaseId?: number;
2780
- }
2781
- /** @public */
2782
- export interface WriteTddPhaseOutput {
2783
- readonly id: number;
2784
- readonly previousPhaseId: number | null;
2785
- }
2786
- /** @public */
2787
- export interface WriteTddArtifactInput {
2788
- readonly phaseId: number;
2789
- readonly artifactKind: ArtifactKind;
2790
- readonly fileId?: number;
2791
- readonly testCaseId?: number;
2792
- readonly testRunId?: number;
2793
- readonly testFirstFailureRunId?: number;
2794
- readonly diffExcerpt?: string;
2795
- readonly recordedAt: string;
2796
- /** Issue #363: explicit suite marker. Defaults to `"vitest"` when omitted. */
2797
- readonly suite?: ArtifactSuite;
2798
- }
2799
- /** @public */
2800
- export interface WriteCommitInput {
2801
- readonly sha: string;
2802
- readonly parentSha?: string;
2803
- readonly message?: string;
2804
- readonly author?: string;
2805
- readonly committedAt?: string;
2806
- readonly branch?: string;
2807
- }
2808
- /** @public */
2809
- export type ChangeKind = "added" | "modified" | "deleted" | "renamed" | "untracked-modified";
2810
- /** @public */
2811
- export interface RunChangedFile {
2812
- readonly filePath: string;
2813
- readonly changeKind: ChangeKind;
2814
- readonly commitSha?: string;
2815
- }
2816
- /** @public */
2817
- export interface WriteRunChangedFilesInput {
2818
- readonly runId: number;
2819
- readonly files: ReadonlyArray<RunChangedFile>;
2820
- }
2821
- /** @public */
2822
- export type RunInvocationMethod = "bash" | "mcp" | "cli";
2823
- /**
2824
- * Input to `DataStore.registerAgent`.
2825
- *
2826
- * `sessionId` is the FK to `sessions.id` (integer PK), NOT the host's
2827
- * chat UUID string. Callers that hold only the chat UUID must resolve
2828
- * it through `getSessionByChatId` first.
2829
- *
2830
- * `idempotencyKey` is pre-derived by the caller via
2831
- * `deriveIdempotencyKey(...)` — both the sidecar CLI and the MCP
2832
- * server compute it the same way so a hook retry collapses to the
2833
- * same row.
2834
- * @public
2835
- */
2836
- export interface RegisterAgentInput {
2837
- readonly sessionId: number;
2838
- readonly agentType: string;
2839
- readonly parentAgentId: string | null;
2840
- readonly conversationId: string | null;
2841
- readonly startedAt: number;
2842
- readonly startGitBranch?: string;
2843
- readonly startGitCommitSha?: string;
2844
- readonly startWorktreeDir?: string;
2845
- readonly idempotencyKey: string;
2846
- /**
2847
- * Pre-allocated `agents.agent_id` UUID. The sidecar passes
2848
- * `PerClientSessionMapWriter.mapSession()`'s `main_agent_id` here so
2849
- * the per-project `agents` row and the per-client session_map row
2850
- * agree on a single canonical id — the same value the SessionStart
2851
- * hook exports as `VITEST_AGENT_MAIN_AGENT_ID` / `_AGENT_ID`. When
2852
- * omitted, the implementation generates a fresh UUID (used by tests
2853
- * and any caller without a session map).
2854
- */
2855
- readonly agentId?: string;
2856
- }
2857
- /** @public */
2858
- export interface AssociateRunSessionInput {
2859
- readonly chatId: string;
2860
- readonly invocationMethod: RunInvocationMethod;
2861
- }
2862
- declare const DataStore_base: Context.ServiceClass<DataStore, "vitest-agent/DataStore", {
2863
- readonly writeSettings: (hash: string, settings: SettingsInput, envVars: Record<string, string>) => Effect.Effect<void, DataStoreError>;
2864
- readonly writeRun: (input: TestRunInput) => Effect.Effect<number, DataStoreError>;
2865
- readonly writeModules: (runId: number, modules: ReadonlyArray<ModuleInput>) => Effect.Effect<ReadonlyArray<number>, DataStoreError>;
2866
- readonly writeSuites: (moduleId: number, suites: ReadonlyArray<SuiteInput>) => Effect.Effect<ReadonlyArray<number>, DataStoreError>;
2867
- readonly writeTestCases: (moduleId: number, tests: ReadonlyArray<TestCaseInput>) => Effect.Effect<ReadonlyArray<number>, DataStoreError>;
2868
- readonly writeErrors: (runId: number, errors: ReadonlyArray<TestErrorInput>) => Effect.Effect<void, DataStoreError>;
2869
- /**
2870
- * Persist `context.annotate` notes and their attachment descriptors.
2871
- * `runId` is carried for log correlation only -- `test_annotations`
2872
- * rows are reachable through `test_cases`.
2873
- */
2874
- readonly writeAnnotations: (runId: number, annotations: ReadonlyArray<TestAnnotationInput>) => Effect.Effect<void, DataStoreError>;
2875
- /**
2876
- * Persist `recordArtifact` payloads and their attachment
2877
- * descriptors. `runId` is carried for log correlation only.
2878
- */
2879
- readonly writeArtifacts: (runId: number, artifacts: ReadonlyArray<TestArtifactInput>) => Effect.Effect<void, DataStoreError>;
2880
- readonly writeCoverage: (runId: number, coverage: ReadonlyArray<FileCoverageInput>) => Effect.Effect<void, DataStoreError>;
2881
- 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>;
2882
- readonly writeBaselines: (baselines: CoverageBaselines) => Effect.Effect<void, DataStoreError>;
2883
- /**
2884
- * Persist the resolved (enforced) Vitest `coverage.thresholds` for the
2885
- * current run, distinct from the ratcheted `coverage_baselines` rows.
2886
- * Stored under `kind='threshold'`. See issue #237.
2887
- */
2888
- readonly writeThresholds: (thresholds: ResolvedThresholds) => Effect.Effect<void, DataStoreError>;
2889
- /**
2890
- * Persist the resolved aspirational `coverageTargets` for the current
2891
- * run, distinct from the ratcheted `coverage_baselines` rows. Stored
2892
- * under `kind='target'`. See issue #237.
2893
- */
2894
- readonly writeTargets: (targets: ResolvedThresholds) => Effect.Effect<void, DataStoreError>;
2895
- readonly writeTrends: (project: string, runId: number, entry: TrendEntry) => Effect.Effect<void, DataStoreError>;
2896
- readonly writeSourceMap: (sourceFilePath: string, testModuleId: number, mappingType: string) => Effect.Effect<void, DataStoreError>;
2897
- readonly ensureFile: (filePath: string) => Effect.Effect<number, DataStoreError>;
2898
- readonly writeNote: (note: NoteInput) => Effect.Effect<number, DataStoreError>;
2899
- readonly updateNote: (id: number, fields: Partial<NoteInput>) => Effect.Effect<void, DataStoreError>;
2900
- readonly deleteNote: (id: number) => Effect.Effect<void, DataStoreError>;
2901
- readonly writeSession: (input: SessionInput) => Effect.Effect<number, DataStoreError>;
2902
- /**
2903
- * Idempotent variant of `writeSession`: if a row with this
2904
- * `chat_id` already exists, return its id and leave the stored
2905
- * fields untouched; otherwise insert a new row. Used by
2906
- * hook-triggered recording paths (artifacts, turns) that fire
2907
- * for sessions whose original `SessionStart` may have missed —
2908
- * e.g. when Claude Code rotates `chat_id` mid-window after a
2909
- * continuation or compaction. Race-safe via
2910
- * `INSERT ... ON CONFLICT DO NOTHING`.
2911
- */
2912
- readonly upsertSession: (input: SessionInput) => Effect.Effect<number, DataStoreError>;
2913
- /**
2914
- * Backfill `sessions.conversation_id` for a row that was inserted
2915
- * before the canonical conversation id was known (issue #144) —
2916
- * `record session-start` always precedes `register-agent`, so the
2917
- * session row exists first. Race-safe and idempotent: the UPDATE's
2918
- * `WHERE conversation_id IS NULL` guard means a session that
2919
- * already carries a value is left untouched (zero rows affected),
2920
- * matching the trigger's null→value-only relaxation rather than
2921
- * risking an immutability-violation error on a redundant call.
2922
- */
2923
- readonly setSessionConversationIdIfNull: (input: {
2924
- readonly sessionId: number;
2925
- readonly conversationId: string;
2926
- }) => Effect.Effect<void, DataStoreError>;
2927
- readonly writeTurn: (input: TurnInput) => Effect.Effect<number, DataStoreError>;
2928
- readonly writeFailureSignature: (input: FailureSignatureWriteInput) => Effect.Effect<void, DataStoreError>;
2929
- readonly endSession: (chatId: string, endedAt: string, endReason: string | null) => Effect.Effect<void, DataStoreError>;
2930
- readonly writeHypothesis: (input: HypothesisInput) => Effect.Effect<number, DataStoreError>;
2931
- readonly validateHypothesis: (input: ValidateHypothesisInput) => Effect.Effect<void, DataStoreError>;
2932
- readonly writeTddTask: (input: TddTaskInput) => Effect.Effect<number, DataStoreError>;
2933
- readonly endTddTask: (input: EndTddTaskInput) => Effect.Effect<void, DataStoreError>;
2934
- readonly createGoal: (input: CreateGoalInput) => Effect.Effect<GoalRow, DataStoreError | TddTaskNotFoundError | TddTaskAlreadyEndedError>;
2935
- readonly getGoal: (id: number) => Effect.Effect<Option.Option<GoalRow>, DataStoreError>;
2936
- readonly updateGoal: (input: UpdateGoalInput) => Effect.Effect<GoalRow, DataStoreError | GoalNotFoundError | TddTaskAlreadyEndedError | IllegalStatusTransitionError>;
2937
- readonly deleteGoal: (id: number) => Effect.Effect<void, DataStoreError | GoalNotFoundError>;
2938
- readonly listGoalsByTddTask: (tddTaskId: number) => Effect.Effect<ReadonlyArray<GoalRow>, DataStoreError | TddTaskNotFoundError>;
2939
- readonly createBehavior: (input: CreateBehaviorInput) => Effect.Effect<BehaviorRow, DataStoreError | GoalNotFoundError | BehaviorNotFoundError | TddTaskAlreadyEndedError | IllegalStatusTransitionError>;
2940
- readonly getBehavior: (id: number) => Effect.Effect<Option.Option<BehaviorRow>, DataStoreError>;
2941
- readonly updateBehavior: (input: UpdateBehaviorInput) => Effect.Effect<BehaviorRow, DataStoreError | BehaviorNotFoundError | TddTaskAlreadyEndedError | IllegalStatusTransitionError>;
2942
- readonly deleteBehavior: (id: number) => Effect.Effect<void, DataStoreError | BehaviorNotFoundError>;
2943
- readonly listBehaviorsByGoal: (goalId: number) => Effect.Effect<ReadonlyArray<BehaviorRow>, DataStoreError | GoalNotFoundError>;
2944
- readonly listBehaviorsByTddTask: (tddTaskId: number) => Effect.Effect<ReadonlyArray<BehaviorRow>, DataStoreError | TddTaskNotFoundError>;
2945
- readonly writeTddPhase: (input: WriteTddPhaseInput) => Effect.Effect<WriteTddPhaseOutput, DataStoreError>;
2946
- readonly writeTddArtifact: (input: WriteTddArtifactInput) => Effect.Effect<number, DataStoreError>;
2947
- readonly writeCommit: (input: WriteCommitInput) => Effect.Effect<void, DataStoreError>;
2948
- readonly writeRunChangedFiles: (input: WriteRunChangedFilesInput) => Effect.Effect<void, DataStoreError>;
2949
- readonly recordIdempotentResponse: (input: IdempotentResponseInput) => Effect.Effect<void, DataStoreError>;
2950
- readonly pruneSessions: (keepRecent: number) => Effect.Effect<{
2951
- readonly affectedSessions: number;
2952
- readonly prunedTurns: number;
2953
- }, DataStoreError>;
2954
- readonly associateLatestRunWithSession: (input: AssociateRunSessionInput) => Effect.Effect<void, DataStoreError>;
2955
- readonly backfillTestCaseTurns: (chatId: string) => Effect.Effect<number, DataStoreError>;
2956
- /**
2957
- * Idempotently insert an `agents` row.
2958
- *
2959
- * Returns `Agent` on a fresh insert, or `IdempotencyHit` carrying
2960
- * the existing `agentId` when the `(session_id, idempotency_key)`
2961
- * UNIQUE constraint already has a row. The caller treats the latter
2962
- * as a successful recovery (same logical agent), not an error.
2963
- *
2964
- * Fails with `RegistrationConflictError` when the supplied
2965
- * `parentAgentId` references an agent in a different session, or
2966
- * when no such agent exists. Surface to the caller for true
2967
- * mis-configuration cases; idempotency hits never produce this.
2968
- */
2969
- readonly registerAgent: (input: RegisterAgentInput) => Effect.Effect<Agent | IdempotencyHit, RegistrationConflictError | DataStoreError>;
2970
- /**
2971
- * Mark an agent as ended. Sets `agents.ended_at` to the supplied
2972
- * timestamp. Fails with `AgentNotFoundError` when no row exists.
2973
- */
2974
- readonly endAgent: (agentId: string, endedAt: number) => Effect.Effect<void, AgentNotFoundError | DataStoreError>;
2975
- }>;
2976
- /** @public */
2977
- export declare class DataStore extends DataStore_base {}
2978
- //#endregion
2979
- //#region src/services/DataReader.d.ts
2980
- /** @public */
2981
- export interface ProjectRunSummary {
2982
- readonly project: string;
2983
- readonly lastRun: string | null;
2984
- readonly lastResult: "passed" | "failed" | "interrupted" | null;
2985
- readonly total: number;
2986
- readonly passed: number;
2987
- readonly failed: number;
2988
- readonly skipped: number;
2989
- }
2990
- /** @public */
2991
- export interface FlakyTest {
2992
- readonly fullName: string;
2993
- readonly modulePath: string;
2994
- readonly project: string;
2995
- readonly passCount: number;
2996
- readonly failCount: number;
2997
- readonly lastState: "passed" | "failed";
2998
- readonly lastTimestamp: string;
2999
- }
3000
- /** @public */
3001
- export interface PersistentFailure {
3002
- readonly fullName: string;
3003
- readonly modulePath: string;
3004
- readonly project: string;
3005
- readonly consecutiveFailures: number;
3006
- readonly firstFailedAt: string;
3007
- readonly lastFailedAt: string;
3008
- readonly lastErrorMessage: string | null;
3009
- }
3010
- /** @public */
3011
- export interface TestError {
3012
- /** `test_errors.id` — required by `hypothesis (action: record).citedTestErrorId`. */
3013
- readonly id: number;
3014
- /**
3015
- * `stack_frames.id` for the top frame of this error (ordinal 0), or
3016
- * `null` if no frames were captured. Required by
3017
- * `hypothesis (action: record).citedStackFrameId`.
3018
- */
3019
- readonly topStackFrameId: number | null;
3020
- readonly name: string | null;
3021
- readonly message: string;
3022
- readonly diff: string | null;
3023
- readonly actual: string | null;
3024
- readonly expected: string | null;
3025
- readonly stack: string | null;
3026
- readonly scope: "test" | "suite" | "module" | "unhandled";
3027
- readonly testFullName: string | null;
3028
- readonly moduleFile: string | null;
3029
- }
3030
- /** @public */
3031
- export interface NoteRow {
3032
- readonly id: number;
3033
- readonly title: string;
3034
- readonly content: string;
3035
- readonly scope: "global" | "project" | "module" | "suite" | "test" | "note";
3036
- readonly project: string | null;
3037
- readonly testFullName: string | null;
3038
- readonly modulePath: string | null;
3039
- readonly parentNoteId: number | null;
3040
- readonly createdBy: string | null;
3041
- readonly expiresAt: string | null;
3042
- readonly pinned: boolean;
3043
- readonly createdAt: string;
3044
- readonly updatedAt: string;
3045
- }
3046
- /** @public */
3047
- export interface SettingsRow {
3048
- readonly hash: string;
3049
- readonly reporters: string | null;
3050
- readonly coverageEnabled: boolean;
3051
- readonly coverageProvider: string | null;
3052
- readonly coverageThresholds: string | null;
3053
- readonly coverageTargets: string | null;
3054
- readonly pool: string | null;
3055
- readonly shard: string | null;
3056
- readonly project: string | null;
3057
- readonly environment: string | null;
3058
- readonly envVars: Record<string, string>;
3059
- readonly capturedAt: string;
3060
- }
3061
- /** @public */
3062
- export interface TestListEntry {
3063
- readonly id: number;
3064
- readonly fullName: string;
3065
- readonly state: string;
3066
- readonly duration: number | null;
3067
- readonly module: string;
3068
- readonly classification: string | null;
3069
- }
3070
- /** @public */
3071
- export interface ModuleListEntry {
3072
- readonly id: number;
3073
- readonly file: string;
3074
- readonly state: string;
3075
- readonly testCount: number;
3076
- readonly duration: number | null;
3077
- }
3078
- /** @public */
3079
- export interface SuiteListEntry {
3080
- readonly id: number;
3081
- readonly name: string;
3082
- readonly module: string;
3083
- readonly state: string;
3084
- readonly testCount: number;
3085
- }
3086
- /** @public */
3087
- export interface SettingsListEntry {
3088
- readonly hash: string;
3089
- readonly capturedAt: string;
3090
- }
3091
- /** @public */
3092
- export interface SessionDetail {
3093
- readonly id: number;
3094
- readonly chatId: string;
3095
- readonly project: string;
3096
- readonly cwd: string;
3097
- readonly agentKind: "main" | "subagent";
3098
- readonly agentType: string | null;
3099
- readonly parentSessionId: number | null;
3100
- readonly triageWasNonEmpty: boolean;
3101
- readonly startedAt: string;
3102
- readonly endedAt: string | null;
3103
- readonly endReason: string | null;
3104
- /** Canonical conversation UUID this session belongs to (issue #144), null when unset. */
3105
- readonly conversationId: string | null;
3106
- }
3107
- /** @public */
3108
- export interface TurnSummary {
3109
- readonly id: number;
3110
- readonly sessionId: number;
3111
- readonly turnNo: number;
3112
- readonly type: string;
3113
- readonly payload: string;
3114
- readonly occurredAt: string;
3115
- }
3116
- /** @public */
3117
- export interface HistoryQueryOptions {
3118
- /** Exact `full_name` match — narrows to a single test's history. */
3119
- readonly testName?: string;
3120
- /** Exact `module_path` match — narrows to tests in one file. */
3121
- readonly modulePath?: string;
3122
- /** Max runs kept per (module_path, full_name) pair, most-recent-first. Default 20. */
3123
- readonly limit?: number;
3124
- }
3125
- /**
3126
- * Narrowing options shared by the classification reads
3127
- * (`DataReader.getFlaky` / `getPersistentFailures`). Mirrors the
3128
- * `testName` / `modulePath` half of {@link HistoryQueryOptions} so a
3129
- * caller that scoped `getHistory` to one test can scope the derived
3130
- * classifications to the same test instead of receiving the whole
3131
- * project's rows.
3132
- *
3133
- * @public
3134
- */
3135
- export interface ClassificationQueryOptions {
3136
- /** Exact `full_name` match — narrows to a single test's classification. */
3137
- readonly testName?: string;
3138
- /** Exact `module_path` match — narrows to tests in one file. */
3139
- readonly modulePath?: string;
3140
- }
3141
- /**
3142
- * Narrowing options for `DataReader.getTestByFullName`. A
3143
- * `full_name` is not file-qualified (Decision D20), so the same name can
3144
- * exist in more than one module; `modulePath` disambiguates.
3145
- *
3146
- * @public
3147
- */
3148
- export interface TestLookupOptions {
3149
- /** Exact `module_path` match — picks one variant of an ambiguous `full_name`. */
3150
- readonly modulePath?: string;
3151
- }
3152
- /** @public */
3153
- export interface TurnSearchOptions {
3154
- readonly sessionId?: number;
3155
- readonly type?: string;
3156
- readonly since?: string;
3157
- readonly limit?: number;
3158
- }
3159
- /** @public */
3160
- export interface AcceptanceMetrics {
3161
- readonly phaseEvidenceIntegrity: {
3162
- total: number;
3163
- compliant: number;
3164
- ratio: number;
3165
- };
3166
- readonly complianceHookResponsiveness: {
3167
- total: number;
3168
- withFollowup: number;
3169
- ratio: number;
3170
- };
3171
- readonly orientationUsefulness: {
3172
- total: number;
3173
- referencedCount: number;
3174
- ratio: number;
3175
- };
3176
- readonly antiPatternDetectionRate: {
3177
- total: number;
3178
- cleanSessions: number;
3179
- ratio: number;
3180
- };
3181
- }
3182
- /** @public */
3183
- export interface FailureSignatureDetail {
3184
- readonly signatureHash: string;
3185
- readonly firstSeenRunId: number | null;
3186
- readonly firstSeenAt: string;
3187
- readonly lastSeenAt: string | null;
3188
- readonly occurrenceCount: number;
3189
- readonly recentErrors: ReadonlyArray<{
3190
- readonly runId: number;
3191
- readonly message: string;
3192
- readonly errorName: string | null;
3193
- }>;
3194
- }
3195
- /** @public */
3196
- export interface TddPhaseDetail {
3197
- readonly id: number;
3198
- readonly behaviorId: number | null;
3199
- readonly phase: string;
3200
- readonly startedAt: string;
3201
- readonly endedAt: string | null;
3202
- readonly transitionReason: string | null;
3203
- }
3204
- /** @public */
3205
- export interface TddArtifactDetail {
3206
- readonly id: number;
3207
- readonly phaseId: number;
3208
- readonly artifactKind: string;
3209
- readonly testCaseId: number | null;
3210
- readonly testRunId: number | null;
3211
- readonly recordedAt: string;
3212
- }
3213
- /** @public */
3214
- export interface TddTaskDetail {
3215
- readonly id: number;
3216
- readonly sessionId: number;
3217
- readonly goal: string;
3218
- readonly startedAt: string;
3219
- readonly endedAt: string | null;
3220
- readonly outcome: string | null;
3221
- readonly runId: string | null;
3222
- readonly goals: ReadonlyArray<GoalDetail>;
3223
- readonly phases: ReadonlyArray<TddPhaseDetail>;
3224
- readonly artifacts: ReadonlyArray<TddArtifactDetail>;
3225
- }
3226
- /** @public */
3227
- export interface CurrentTddPhase {
3228
- readonly id: number;
3229
- readonly phase: Phase;
3230
- readonly startedAt: string;
3231
- readonly behaviorId: number | null;
3232
- }
3233
- /** @public */
3234
- export interface CitedArtifactRow extends CitedArtifact {
3235
- readonly phase_id: number;
3236
- }
3237
- /** @public */
3238
- export interface CommitChangesEntry {
3239
- readonly sha: string;
3240
- readonly parentSha: string | null;
3241
- readonly message: string | null;
3242
- readonly author: string | null;
3243
- readonly committedAt: string | null;
3244
- readonly branch: string | null;
3245
- readonly files: ReadonlyArray<{
3246
- readonly filePath: string;
3247
- readonly changeKind: ChangeKind;
3248
- }>;
3249
- }
3250
- /** @public */
3251
- export interface HypothesisDetail {
3252
- readonly id: number;
3253
- readonly sessionId: number;
3254
- readonly content: string;
3255
- readonly citedTestErrorId: number | null;
3256
- readonly citedStackFrameId: number | null;
3257
- readonly validationOutcome: "confirmed" | "refuted" | "abandoned" | null;
3258
- readonly validatedAt: string | null;
3259
- }
3260
- /** @public */
3261
- export interface TddTaskSummary {
3262
- readonly id: number;
3263
- readonly sessionId: number;
3264
- readonly goal: string;
3265
- readonly startedAt: string;
3266
- readonly endedAt: string | null;
3267
- readonly outcome: "succeeded" | "blocked" | "abandoned" | null;
3268
- }
3269
- /**
3270
- * Row shape returned by `listTddArtifactsForTask`. Carries every
3271
- * field an agent typically needs to cite an artifact in a subsequent
3272
- * `tdd_phase_transition_request` call without further lookups.
3273
- *
3274
- * @public
3275
- */
3276
- export interface TddArtifactRow {
3277
- readonly id: number;
3278
- readonly tddTaskId: number;
3279
- readonly phaseId: number;
3280
- readonly phaseName: Phase;
3281
- readonly artifactKind: ArtifactKind;
3282
- readonly behaviorId: number | null;
3283
- readonly testCaseId: number | null;
3284
- readonly testRunId: number | null;
3285
- readonly testFirstFailureRunId: number | null;
3286
- readonly recordedAt: string;
3287
- readonly suite: ArtifactSuite;
3288
- }
3289
- /** @public */
3290
- export interface TagInventoryRow {
3291
- /** The tag name (e.g. `"int"`, `"e2e"`, `"unit"`). */
3292
- readonly tag: string;
3293
- /** The Vitest project this tag was observed in. */
3294
- readonly project: string;
3295
- /**
3296
- * Number of distinct test modules in the project's latest run that contain
3297
- * at least one test case carrying this tag.
3298
- */
3299
- readonly moduleCount: number;
3300
- /**
3301
- * Number of test cases in the project's latest run that carry this tag.
3302
- */
3303
- readonly testCount: number;
3304
- }
3305
- /** @public */
3306
- export interface TestArtifactQueryOptions {
3307
- /** Disambiguates a fullName that exists in more than one module. */
3308
- readonly modulePath?: string;
3309
- }
3310
- /** @public */
3311
- export interface PersistedAttachment {
3312
- readonly contentType?: string;
3313
- readonly path?: string;
3314
- readonly body?: string;
3315
- /** How to read `body`. Absent when nothing was stored inline. */
3316
- readonly bodyEncoding?: "base64" | "utf-8";
3317
- readonly byteSize: number | null;
3318
- }
3319
- /** @public */
3320
- export interface TestAnnotationRow {
3321
- readonly id: number;
3322
- readonly type: string;
3323
- readonly message: string;
3324
- readonly location?: {
3325
- readonly file: string;
3326
- readonly line: number;
3327
- readonly column: number;
3328
- };
3329
- readonly attachments: ReadonlyArray<PersistedAttachment>;
3330
- }
3331
- /** @public */
3332
- export interface TestArtifactRow {
3333
- readonly id: number;
3334
- readonly type: string;
3335
- readonly message: string | null;
3336
- readonly data: string | null;
3337
- readonly location?: {
3338
- readonly file: string;
3339
- readonly line: number;
3340
- readonly column: number;
3341
- };
3342
- readonly attachments: ReadonlyArray<PersistedAttachment>;
3343
- }
3344
- declare const DataReader_base: Context.ServiceClass<DataReader, "vitest-agent/DataReader", {
3345
- readonly getLatestRun: (project: string) => Effect.Effect<Option.Option<AgentReport>, DataStoreError>;
3346
- readonly getRunsByProject: () => Effect.Effect<ReadonlyArray<ProjectRunSummary>, DataStoreError>;
3347
- readonly getHistory: (project: string, options?: HistoryQueryOptions) => Effect.Effect<HistoryRecord, DataStoreError>;
3348
- readonly getBaselines: (project: string) => Effect.Effect<Option.Option<CoverageBaselines>, DataStoreError>;
3349
- readonly getTrends: (project: string, limit?: number) => Effect.Effect<Option.Option<TrendRecord>, DataStoreError>;
3350
- readonly getFlaky: (project: string, options?: ClassificationQueryOptions) => Effect.Effect<ReadonlyArray<FlakyTest>, DataStoreError>;
3351
- readonly getPersistentFailures: (project: string, options?: ClassificationQueryOptions) => Effect.Effect<ReadonlyArray<PersistentFailure>, DataStoreError>;
3352
- readonly getFileCoverage: (runId: number) => Effect.Effect<ReadonlyArray<FileCoverageReport>, DataStoreError>;
3353
- readonly getCoverage: (project: string) => Effect.Effect<Option.Option<CoverageReport>, DataStoreError>;
3354
- readonly getTestsForFile: (filePath: string) => Effect.Effect<ReadonlyArray<string>, DataStoreError>;
3355
- readonly getErrors: (project: string, errorName?: string) => Effect.Effect<ReadonlyArray<TestError>, DataStoreError>;
3356
- /** Annotations recorded for a test in the project's latest run. */
3357
- readonly getAnnotationsForTest: (project: string, fullName: string, options?: TestArtifactQueryOptions) => Effect.Effect<ReadonlyArray<TestAnnotationRow>, DataStoreError>;
3358
- /** Artifacts recorded for a test in the project's latest run. */
3359
- readonly getArtifactsForTest: (project: string, fullName: string, options?: TestArtifactQueryOptions) => Effect.Effect<ReadonlyArray<TestArtifactRow>, DataStoreError>;
3360
- readonly getNotes: (scope?: string, project?: string, testFullName?: string) => Effect.Effect<ReadonlyArray<NoteRow>, DataStoreError>;
3361
- readonly getNoteById: (id: number) => Effect.Effect<Option.Option<NoteRow>, DataStoreError>;
3362
- readonly searchNotes: (query: string) => Effect.Effect<ReadonlyArray<NoteRow>, DataStoreError>;
3363
- readonly getManifest: () => Effect.Effect<Option.Option<CacheManifest>, DataStoreError>;
3364
- readonly getSettings: (hash: string) => Effect.Effect<Option.Option<SettingsRow>, DataStoreError>;
3365
- readonly getLatestSettings: () => Effect.Effect<Option.Option<SettingsRow>, DataStoreError>;
3366
- readonly getTestByFullName: (project: string, fullName: string, options?: TestLookupOptions) => Effect.Effect<Option.Option<TestListEntry>, DataStoreError>;
3367
- /**
3368
- * Every module path in the project's latest run that carries a test
3369
- * case with this exact `full_name`, ordered ascending. Length > 1
3370
- * means the name is ambiguous and callers must disambiguate with
3371
- * {@link TestLookupOptions.modulePath} rather than guess.
3372
- */
3373
- readonly getTestModulesByFullName: (project: string, fullName: string) => Effect.Effect<ReadonlyArray<string>, DataStoreError>;
3374
- readonly listTests: (project: string, options?: {
3375
- state?: string;
3376
- module?: string;
3377
- limit?: number;
3378
- }) => Effect.Effect<ReadonlyArray<TestListEntry>, DataStoreError>;
3379
- readonly listModules: (project: string) => Effect.Effect<ReadonlyArray<ModuleListEntry>, DataStoreError>;
3380
- readonly listSuites: (project: string, options?: {
3381
- module?: string;
3382
- }) => Effect.Effect<ReadonlyArray<SuiteListEntry>, DataStoreError>;
3383
- readonly listSettings: () => Effect.Effect<ReadonlyArray<SettingsListEntry>, DataStoreError>;
3384
- readonly getSessionById: (id: number) => Effect.Effect<Option.Option<SessionDetail>, DataStoreError>;
3385
- readonly getSessionByChatId: (chatId: string) => Effect.Effect<Option.Option<SessionDetail>, DataStoreError>;
3386
- /**
3387
- * Find every session row whose `chat_id` begins with `prefix`.
3388
- * Used to recover the synthetic subagent row created by the
3389
- * SubagentStart hook (`<parentChatId>-subagent-<ts>-<pid>`)
3390
- * when subsequent PostToolUse hooks fire under the bare
3391
- * parent chat_id. Returns most recent first.
3392
- */
3393
- readonly findSessionsByChatPrefix: (prefix: string) => Effect.Effect<ReadonlyArray<SessionDetail>, DataStoreError>;
3394
- /**
3395
- * Find the most-recently-started subagent session whose
3396
- * `parent_session_id` is `parentSessionId` and that has not ended
3397
- * (`ended_at IS NULL`). Used to attribute orchestrator (subagent)
3398
- * MCP writes — e.g. `hypothesis record` — to the running subagent's
3399
- * own session row instead of the parent main session, since the MCP
3400
- * server's recovered context only ever names the main agent.
3401
- */
3402
- readonly findActiveSubagentSession: (parentSessionId: number) => Effect.Effect<Option.Option<SessionDetail>, DataStoreError>;
3403
- /**
3404
- * Resolve the session a TDD task was opened under: the `sessions`
3405
- * row whose `id` equals `tdd_tasks.session_id` for `tddTaskId`.
3406
- * Returns `Option.none` when the task — or its session — does not
3407
- * exist. Lets `hypothesis (action: record)` bind a hypothesis
3408
- * deterministically from the orchestrator's unambiguous
3409
- * `tddTaskId` (returned by `tdd_task (action: start)`) instead of
3410
- * the fragile recovered host context or a caller-guessed
3411
- * `sessionId`.
3412
- */
3413
- readonly getSessionByTddTaskId: (tddTaskId: number) => Effect.Effect<Option.Option<SessionDetail>, DataStoreError>;
3414
- readonly listSessions: (options: {
3415
- readonly project?: string;
3416
- readonly agentKind?: "main" | "subagent";
3417
- readonly limit?: number;
3418
- }) => Effect.Effect<ReadonlyArray<SessionDetail>, DataStoreError>;
3419
- readonly searchTurns: (options: TurnSearchOptions) => Effect.Effect<ReadonlyArray<TurnSummary>, DataStoreError>;
3420
- readonly computeAcceptanceMetrics: () => Effect.Effect<AcceptanceMetrics, DataStoreError>;
3421
- readonly getFailureSignatureByHash: (hash: string) => Effect.Effect<Option.Option<FailureSignatureDetail>, DataStoreError>;
3422
- readonly getTddTaskById: (id: number) => Effect.Effect<Option.Option<TddTaskDetail>, DataStoreError>;
3423
- readonly getGoalById: (id: number) => Effect.Effect<Option.Option<GoalDetail>, DataStoreError>;
3424
- readonly getGoalsByTddTask: (tddTaskId: number) => Effect.Effect<ReadonlyArray<GoalDetail>, DataStoreError>;
3425
- readonly getBehaviorById: (id: number) => Effect.Effect<Option.Option<BehaviorDetail>, DataStoreError>;
3426
- readonly getBehaviorsByGoal: (goalId: number) => Effect.Effect<ReadonlyArray<BehaviorRow>, DataStoreError>;
3427
- readonly getBehaviorsByTddTask: (tddTaskId: number) => Effect.Effect<ReadonlyArray<BehaviorRow>, DataStoreError>;
3428
- readonly getBehaviorDependencies: (behaviorId: number) => Effect.Effect<ReadonlyArray<BehaviorRow>, DataStoreError>;
3429
- readonly resolveGoalIdForBehavior: (behaviorId: number) => Effect.Effect<Option.Option<number>, DataStoreError>;
3430
- readonly getCurrentTddPhase: (tddTaskId: number) => Effect.Effect<Option.Option<CurrentTddPhase>, DataStoreError>;
3431
- readonly getTddArtifactWithContext: (artifactId: number) => Effect.Effect<Option.Option<CitedArtifactRow>, DataStoreError>;
3432
- readonly getCommitChanges: (sha?: string) => Effect.Effect<ReadonlyArray<CommitChangesEntry>, DataStoreError>;
3433
- readonly listTddTasksForSession: (sessionId: number, options?: {
3434
- /**
3435
- * When true, also return tdd_tasks belonging to any
3436
- * ancestor of `sessionId` via `parent_session_id`. Used
3437
- * by hook-driven artifact recording where the
3438
- * orchestrator opened the tdd task under the parent
3439
- * main row but the subagent's own session row is the
3440
- * one carrying the calling chat_id. Default `false`
3441
- * preserves the prior single-session contract.
3442
- */
3443
- readonly walkParents?: boolean;
3444
- /**
3445
- * When true AND `sessionId`'s session has a non-null
3446
- * `conversation_id`, also return tdd_tasks belonging to
3447
- * any OTHER session sharing that `conversation_id` — the
3448
- * detached-session fallback (issue #144). A session with
3449
- * a null `conversation_id` never triggers this fallback.
3450
- * Rows are ordered so a task owned by an `agent_kind =
3451
- * 'main'` session sorts first, then by `started_at DESC`.
3452
- * Default `false` preserves the prior contract.
3453
- */
3454
- readonly walkConversation?: boolean;
3455
- }) => Effect.Effect<ReadonlyArray<TddTaskSummary>, DataStoreError>;
3456
- /**
3457
- * Diagnostic for the `missing_artifact_evidence` phase-transition
3458
- * denial (issue #144): counts `tdd_artifacts` rows recorded at or
3459
- * after `sinceIso` under sessions OTHER than the one that opened
3460
- * `tddTaskId`, but sharing that session's `conversation_id`. Used
3461
- * to tell an agent "your hooks may be attributing to a detached
3462
- * session" rather than a bare "no artifact found". Returns 0 when
3463
- * `tddTaskId` is unknown or its session's `conversation_id` is
3464
- * null — the diagnostic never fabricates a signal it cannot back.
3465
- */
3466
- readonly countRecentArtifactsInOtherSessionsOfConversation: (input: {
3467
- readonly tddTaskId: number;
3468
- readonly sinceIso: string;
3469
- }) => Effect.Effect<number, DataStoreError>;
3470
- /**
3471
- * List artifacts recorded for a TDD task, optionally filtered
3472
- * by `artifactKind`, `phaseId`, or `behaviorId`. Returns rows in
3473
- * recorded_at DESC order so the most recently captured artifact
3474
- * (the typical citation target for a phase transition) appears
3475
- * first. `limit` defaults to 50.
3476
- */
3477
- readonly listTddArtifactsForTask: (input: {
3478
- readonly tddTaskId: number;
3479
- readonly artifactKind?: ArtifactKind;
3480
- readonly phaseId?: number;
3481
- readonly behaviorId?: number;
3482
- readonly limit?: number;
3483
- }) => Effect.Effect<ReadonlyArray<TddArtifactRow>, DataStoreError>;
3484
- readonly listHypotheses: (options: {
3485
- readonly sessionId?: number;
3486
- readonly outcome?: "confirmed" | "refuted" | "abandoned" | "open";
3487
- readonly limit?: number;
3488
- }) => Effect.Effect<ReadonlyArray<HypothesisDetail>, DataStoreError>;
3489
- readonly findIdempotentResponse: (procedurePath: string, key: string) => Effect.Effect<Option.Option<string>, DataStoreError>;
3490
- readonly getLatestTestCaseForSession: (chatId: string) => Effect.Effect<Option.Option<number>, DataStoreError>;
3491
- /**
3492
- * Returns one `TagInventoryRow` per `(tag, project)` pair observed in
3493
- * each project's latest test run. When `project` is supplied, results
3494
- * are restricted to that project's latest run.
3495
- */
3496
- readonly listTagInventory: (options?: {
3497
- readonly project?: string;
3498
- }) => Effect.Effect<ReadonlyArray<TagInventoryRow>, DataStoreError>;
3499
- /**
3500
- * Returns every `TestListEntry` from the latest run of each project
3501
- * (or the specified project) whose test case carries `tag`.
3502
- */
3503
- readonly listTestsForTag: (tag: string, options?: {
3504
- readonly project?: string;
3505
- }) => Effect.Effect<ReadonlyArray<TestListEntry>, DataStoreError>;
3506
- }>;
3507
- /** @public */
3508
- export declare class DataReader extends DataReader_base {}
3509
- //#endregion
3510
- //#region src/layers/DataReaderLive.d.ts
3511
- /** @public */
3512
- export declare const DataReaderLive: Layer.Layer<DataReader, never, SqlClient>;
3513
- //#endregion
3514
- //#region src/layers/DataStoreLive.d.ts
3515
- /** @public */
3516
- export declare const DataStoreLive: Layer.Layer<DataStore, never, SqlClient>;
3517
- //#endregion
3518
- //#region src/services/DetailResolver.d.ts
3519
- /** @public */
3520
- export interface RunHealth {
3521
- readonly hasFailures: boolean;
3522
- readonly belowTargets: boolean;
3523
- readonly hasTargets?: boolean;
3524
- }
3525
- declare const DetailResolver_base: Context.ServiceClass<DetailResolver, "vitest-agent/DetailResolver", {
3526
- readonly resolve: (executor: Executor, health: RunHealth, explicit?: DetailLevel) => Effect.Effect<DetailLevel>;
3527
- }>;
3528
- /** @public */
3529
- export declare class DetailResolver extends DetailResolver_base {}
3530
- //#endregion
3531
- //#region src/layers/DetailResolverLive.d.ts
3532
- /** @public */
3533
- export declare const DetailResolverLive: Layer.Layer<DetailResolver, never, never>;
3534
- //#endregion
3535
- //#region src/services/DiscoveryRegistry.d.ts
3536
- /**
3537
- * Input for upserting a known project into the global discovery registry.
3538
- *
3539
- * @public
3540
- */
3541
- export interface KnownProjectInput {
3542
- readonly projectKey: string;
3543
- readonly canonicalForm: string;
3544
- readonly dataDbPath: string;
3545
- readonly gitRemoteOrigin: string | null;
3546
- readonly workspaceRoot: string;
3547
- }
3548
- /**
3549
- * A project record as stored in the global discovery registry.
3550
- *
3551
- * @public
3552
- */
3553
- export interface KnownProject {
3554
- readonly projectKey: string;
3555
- readonly canonicalForm: string;
3556
- readonly dataDbPath: string;
3557
- readonly gitRemoteOrigin: string | null;
3558
- readonly workspaceRoot: string;
3559
- readonly firstSeenAt: number;
3560
- readonly lastSeenAt: number;
3561
- }
3562
- declare const DiscoveryRegistry_base: Context.ServiceClass<DiscoveryRegistry, "vitest-agent/DiscoveryRegistry", {
3563
- /**
3564
- * Upsert this project into the registry. Sets `first_seen_at` on
3565
- * insert; updates `last_seen_at` plus all mutable fields on
3566
- * conflict. Returns nothing — the call is fire-and-observe.
3567
- */
3568
- readonly recordProject: (input: KnownProjectInput) => Effect.Effect<void, DataStoreError>;
3569
- /**
3570
- * List all projects ordered by most recent activity first. Used by
3571
- * cross-project discovery tooling.
3572
- */
3573
- readonly listProjects: () => Effect.Effect<ReadonlyArray<KnownProject>, DataStoreError>;
3574
- /**
3575
- * Drop registry rows whose `last_seen_at` is older than `maxAgeDays`
3576
- * days ago. The corresponding `data.db` files are NOT deleted; only
3577
- * the index entry is pruned. Returns the count of removed rows.
3578
- */
3579
- readonly prune: (maxAgeDays: number) => Effect.Effect<number, DataStoreError>;
3580
- }>;
3581
- /** @public */
3582
- export declare class DiscoveryRegistry extends DiscoveryRegistry_base {}
3583
- //#endregion
3584
- //#region src/layers/DiscoveryRegistryLive.d.ts
3585
- /** @public */
3586
- export declare const DiscoveryRegistryLive: Layer.Layer<DiscoveryRegistry, never, SqlClient>;
3587
- //#endregion
3588
- //#region src/services/EnvironmentDetector.d.ts
3589
- declare const EnvironmentDetector_base: Context.ServiceClass<EnvironmentDetector, "vitest-agent/EnvironmentDetector", {
3590
- readonly detect: () => Effect.Effect<Environment>;
3591
- readonly isAgent: Effect.Effect<boolean>;
3592
- readonly agentName: Effect.Effect<string | undefined>;
3593
- }>;
3594
- /** @public */
3595
- export declare class EnvironmentDetector extends EnvironmentDetector_base {}
3596
- //#endregion
3597
- //#region src/layers/EnvironmentDetectorLive.d.ts
3598
- /** @public */
3599
- export declare const EnvironmentDetectorLive: Layer.Layer<EnvironmentDetector>;
3600
- //#endregion
3601
- //#region src/layers/EnvironmentDetectorTest.d.ts
3602
- /** @public */
3603
- export declare const EnvironmentDetectorTest: {
3604
- layer: (env?: Environment) => Layer.Layer<EnvironmentDetector, never, never>;
3605
- };
3606
- //#endregion
3607
- //#region src/services/ExecutorResolver.d.ts
3608
- declare const ExecutorResolver_base: Context.ServiceClass<ExecutorResolver, "vitest-agent/ExecutorResolver", {
3609
- readonly resolve: (env: Environment) => Effect.Effect<Executor>;
3610
- }>;
3611
- /** @public */
3612
- export declare class ExecutorResolver extends ExecutorResolver_base {}
3613
- //#endregion
3614
- //#region src/layers/ExecutorResolverLive.d.ts
3615
- /** @public */
3616
- export declare const ExecutorResolverLive: Layer.Layer<ExecutorResolver, never, never>;
3617
- //#endregion
3618
- //#region src/services/FormatSelector.d.ts
3619
- declare const FormatSelector_base: Context.ServiceClass<FormatSelector, "vitest-agent/FormatSelector", {
3620
- readonly select: (executor: Executor, explicitFormat?: OutputFormat, environment?: Environment) => Effect.Effect<OutputFormat>;
3621
- }>;
3622
- /** @public */
3623
- export declare class FormatSelector extends FormatSelector_base {}
3624
- //#endregion
3625
- //#region src/layers/FormatSelectorLive.d.ts
3626
- /**
3627
- * Default format dispatch:
3628
- *
3629
- * - GitHub Actions CI executor: `ci-annotations` (renders as `::error::`).
3630
- * - Human executor: `silent` (Vitest's own reporters handle the user
3631
- * experience; we just write to the database).
3632
- * - Anyone else (agent-shell, terminal-bound CI): `terminal` — plain
3633
- * text + ANSI color, no markdown syntax in the place that doesn't
3634
- * render it. Markdown stays available via explicit `format: "markdown"`
3635
- * for surfaces that *do* render it (MCP tools, GitHub step summary).
3636
- * @public
3637
- */
3638
- export declare const FormatSelectorLive: Layer.Layer<FormatSelector, never, never>;
3639
- //#endregion
3640
- //#region src/services/HistoryTracker.d.ts
3641
- /**
3642
- * Lightweight test outcome for history classification.
3643
- * @public
3644
- */
3645
- export interface TestOutcome {
3646
- readonly modulePath: string;
3647
- readonly fullName: string;
3648
- readonly state: "passed" | "failed";
3649
- }
3650
- /**
3651
- * Builds the composite (modulePath, fullName) key used to key the internal
3652
- * testMap and the returned classifications Map, so identically-named tests
3653
- * in different files classify independently instead of colliding.
3654
- *
3655
- * Uses `JSON.stringify` for an injective encoding: a plain delimiter such as
3656
- * a space is not collision-proof (e.g. `("a b", "c")` and `("a", "b c")` would
3657
- * both yield `"a b c"`), which would reintroduce the very collision class this
3658
- * key exists to prevent.
3659
- * @public
3660
- */
3661
- export declare const historyKey: (modulePath: string, fullName: string) => string;
3662
- declare const HistoryTracker_base: Context.ServiceClass<HistoryTracker, "vitest-agent/HistoryTracker", {
3663
- readonly classify: (project: string, testOutcomes: ReadonlyArray<TestOutcome>, timestamp: string) => Effect.Effect<{
3664
- history: HistoryRecord;
3665
- classifications: Map<string, TestClassification>;
3666
- }, DataStoreError>;
3667
- }>;
3668
- /** @public */
3669
- export declare class HistoryTracker extends HistoryTracker_base {}
3670
- //#endregion
3671
- //#region src/layers/HistoryTrackerLive.d.ts
3672
- /** @public */
3673
- export declare const HistoryTrackerLive: Layer.Layer<HistoryTracker, never, DataReader>;
3674
- //#endregion
3675
- //#region src/layers/HistoryTrackerTest.d.ts
3676
- /** @public */
3677
- export interface HistoryTrackerTestState {
3678
- readonly classifyCalls: Array<{
3679
- project: string;
3680
- timestamp: string;
3681
- }>;
3682
- }
3683
- /** @public */
3684
- export declare const HistoryTrackerTest: {
3685
- readonly empty: () => HistoryTrackerTestState;
3686
- readonly layer: (state: HistoryTrackerTestState, cannedResult?: {
3687
- history: HistoryRecord;
3688
- classifications: Map<string, TestClassification>;
3689
- }) => Layer.Layer<HistoryTracker>;
3690
- };
3691
- //#endregion
3692
- //#region src/layers/LoggerLive.d.ts
3693
- /**
3694
- * Create a structured JSON (NDJSON) logger layer for stderr.
3695
- *
3696
- * When level is undefined or `"None"`, installs an empty logger set (silent).
3697
- * When logFile is set, composes the stderr logger with a file logger.
3698
- * Uses `Logger.formatJson` / `Logger.formatStructured` for machine-readable
3699
- * output.
3700
- * @public
3701
- */
3702
- export declare const LoggerLive: (level?: LogLevel.LogLevel, logFile?: string) => Layer.Layer<never>;
3703
- /** @public */
3704
- export declare function resolveLogLevel(option?: string): LogLevel.LogLevel | undefined;
3705
- /**
3706
- * Resolve log file from option or environment variable.
3707
- * @public
3708
- */
3709
- export declare function resolveLogFile(option?: string): string | undefined;
3710
- //#endregion
3711
- //#region src/layers/OutputPipelineLive.d.ts
3712
- /** @public */
3713
- export declare const OutputPipelineLive: Layer.Layer<DetailResolver | EnvironmentDetector | ExecutorResolver | FormatSelector | OutputRenderer, never, never>;
3714
- //#endregion
3715
- //#region src/services/OutputRenderer.d.ts
3716
- declare const OutputRenderer_base: Context.ServiceClass<OutputRenderer, "vitest-agent/OutputRenderer", {
3717
- readonly render: (reports: ReadonlyArray<AgentReport>, format: OutputFormat, context: FormatterContext) => Effect.Effect<ReadonlyArray<RenderedOutput>>;
3718
- }>;
3719
- /** @public */
3720
- export declare class OutputRenderer extends OutputRenderer_base {}
3721
- //#endregion
3722
- //#region src/layers/OutputRendererLive.d.ts
3723
- /** @public */
3724
- export declare const OutputRendererLive: Layer.Layer<OutputRenderer, never, never>;
3725
- //#endregion
3726
- //#region src/layers/PathResolutionLive.d.ts
3727
- /**
3728
- * Composite layer providing every service `resolveDataPath` requires:
3729
- * `AppDirs` (XDG path resolution), `VitestAgentConfigFile` (TOML
3730
- * config loader), and `WorkspaceDiscovery` / `WorkspaceRoot` (workspace name
3731
- * lookup).
3732
- *
3733
- * Callers still need to provide `FileSystem` and `Path` from
3734
- * `@effect/platform-node`'s `NodeServices.layer` (or the equivalent on Bun).
3735
- *
3736
- * `WorkspaceDiscovery` is pinned to `projectDir` as its `cwd`, which sets the
3737
- * root for the layer-bound methods (`listPackages`, `info`, `refresh`). The
3738
- * per-root methods (`listPackagesIn`, `infoIn`, `refreshIn`) take a directory
3739
- * per call and ignore that pin — `resolveWorkspaceKey` and
3740
- * `ProjectIdentityLive` use them, so a long-lived host built against one root
3741
- * still answers correctly for a git worktree or an unrelated project.
3742
- *
3743
- * @param projectDir - Absolute path inside the user's workspace, used to
3744
- * anchor the config file resolvers and workspace discovery.
3745
- * @public
3746
- */
3747
- export declare const PathResolutionLive: (projectDir: string) => Layer.Layer<AppDirs | VitestAgentConfigFile | WorkspaceDiscovery, import("@effected/xdg").XdgEnvError, import("effect/FileSystem").FileSystem | import("effect/Path").Path>;
3748
- //#endregion
3749
- //#region src/services/PerClientSessionMap.d.ts
3750
- /** @public */
3751
- export interface MapSessionInput {
3752
- readonly hostSessionId: string;
3753
- readonly conversationId: string;
3754
- readonly projectKey: string;
3755
- readonly projectDir: string;
3756
- }
3757
- /** @public */
3758
- export interface MapSessionOutput {
3759
- readonly mainAgentId: string;
3760
- readonly conversationId: string;
3761
- }
3762
- /** @public */
3763
- export interface SessionContextRow {
3764
- readonly hostSessionId: string;
3765
- readonly conversationId: string;
3766
- readonly projectKey: string;
3767
- readonly projectDir: string;
3768
- readonly mainAgentId: string;
3769
- readonly startedAt: number;
3770
- readonly endedAt: number | null;
3771
- }
3772
- declare const PerClientSessionMapReader_base: Context.ServiceClass<PerClientSessionMapReader, "vitest-agent/PerClientSessionMapReader", {
3773
- /**
3774
- * Look up an existing conversation_id for a given transcript
3775
- * path. Returns `Option.none()` when the transcript hasn't been
3776
- * seen before. Read-only — does not insert.
3777
- */
3778
- readonly lookupConversation: (transcriptPath: string) => Effect.Effect<Option.Option<string>, DataStoreError>;
3779
- /**
3780
- * Return the most recent open session for a project_dir
3781
- * (`ended_at IS NULL`). The MCP server uses this to recover
3782
- * `currentSessionContext` after `/reload-plugins`. The compound
3783
- * index `idx_session_map_active` covers the predicate.
3784
- */
3785
- readonly lookupByProjectDir: (projectDir: string) => Effect.Effect<Option.Option<SessionContextRow>, DataStoreError>;
3786
- }>;
3787
- /**
3788
- * Read-only side of the session map.
3789
- *
3790
- * Provided by `PerClientSessionMapReaderLive` (opens SQLite with
3791
- * `?mode=ro`). MCP server depends on this tag — calls to write
3792
- * methods would be a type error.
3793
- * @public
3794
- */
3795
- export declare class PerClientSessionMapReader extends PerClientSessionMapReader_base {}
3796
- declare const PerClientSessionMapWriter_base: Context.ServiceClass<PerClientSessionMapWriter, "vitest-agent/PerClientSessionMapWriter", {
3797
- /**
3798
- * Upsert a conversation row. Returns the canonical conversation_id
3799
- * for the given transcript_path (existing if seen before, freshly
3800
- * generated otherwise).
3801
- */
3802
- readonly mapConversation: (transcriptPath: string) => Effect.Effect<string, DataStoreError>;
3803
- /**
3804
- * Upsert a session row. Returns the canonical main_agent_id and
3805
- * conversation_id (existing if `host_session_id` was seen before,
3806
- * freshly generated otherwise).
3807
- *
3808
- * The caller is responsible for having already mapped the
3809
- * conversation; this method only records the
3810
- * (host_session_id, conversation_id, project) tuple.
3811
- */
3812
- readonly mapSession: (input: MapSessionInput) => Effect.Effect<MapSessionOutput, DataStoreError>;
3813
- /**
3814
- * Mark a session as ended. Sets `ended_at` to the supplied
3815
- * timestamp. No-op if the session is unknown — endSession is
3816
- * best-effort cleanup.
3817
- */
3818
- readonly endSession: (hostSessionId: string, endedAt: number) => Effect.Effect<void, DataStoreError>;
3819
- /**
3820
- * Read methods so the Writer also satisfies the Reader tag's
3821
- * surface.
3822
- */
3823
- readonly lookupConversation: (transcriptPath: string) => Effect.Effect<Option.Option<string>, DataStoreError>;
3824
- readonly lookupByProjectDir: (projectDir: string) => Effect.Effect<Option.Option<SessionContextRow>, DataStoreError>;
3825
- }>;
3826
- /**
3827
- * Read-write side of the session map. Sidecar provides this; the
3828
- * Writer layer also satisfies the Reader tag so consumers of either
3829
- * one resolve.
3830
- * @public
3831
- */
3832
- export declare class PerClientSessionMapWriter extends PerClientSessionMapWriter_base {}
3833
- //#endregion
3834
- //#region src/layers/PerClientSessionMapLive.d.ts
3835
- /**
3836
- * Read-only layer. The entry point provides an `SqlClient` configured
3837
- * with the `?mode=ro` URI parameter; this layer wraps the read
3838
- * methods and never declares write methods.
3839
- * @public
3840
- */
3841
- export declare const PerClientSessionMapReaderLive: Layer.Layer<PerClientSessionMapReader, never, SqlClient>;
3842
- /**
3843
- * Read-write layer. Provides both write methods and the Reader's read
3844
- * methods so the same layer instance satisfies callers of either
3845
- * tag.
3846
- * @public
3847
- */
3848
- export declare const PerClientSessionMapWriterLive: Layer.Layer<PerClientSessionMapWriter | PerClientSessionMapReader, never, SqlClient>;
3849
- //#endregion
3850
- //#region src/services/ProjectDiscovery.d.ts
3851
- /** @public */
3852
- export interface TestFileEntry {
3853
- readonly testFile: string;
3854
- readonly sourceFiles: ReadonlyArray<string>;
3855
- }
3856
- declare const ProjectDiscovery_base: Context.ServiceClass<ProjectDiscovery, "vitest-agent/ProjectDiscovery", {
3857
- readonly discoverTestFiles: (rootDir: string) => Effect.Effect<ReadonlyArray<TestFileEntry>, DiscoveryError>;
3858
- readonly mapTestToSource: (testFile: string) => Effect.Effect<ReadonlyArray<string>, DiscoveryError>;
3859
- }>;
3860
- /** @public */
3861
- export declare class ProjectDiscovery extends ProjectDiscovery_base {}
3862
- //#endregion
3863
- //#region src/layers/ProjectDiscoveryLive.d.ts
3864
- /** @public */
3865
- export declare const ProjectDiscoveryLive: Layer.Layer<ProjectDiscovery, never, FileSystem.FileSystem>;
3866
- //#endregion
3867
- //#region src/layers/ProjectDiscoveryTest.d.ts
3868
- /** @public */
3869
- export declare const ProjectDiscoveryTest: {
3870
- readonly layer: (entries: ReadonlyArray<TestFileEntry>) => Layer.Layer<ProjectDiscovery>;
3871
- };
3872
- //#endregion
3873
- //#region src/services/ProjectIdentity.d.ts
3874
- /**
3875
- * Result of a successful identity resolution.
3876
- *
3877
- * - `projectKey` — filesystem-safe single segment for the per-project
3878
- * data store directory under `$XDG_DATA_HOME/vitest-agent/`.
3879
- * - `canonicalForm` — human-readable form for display in the discovery
3880
- * registry. Equal to `projectKey` for non-git sources; for git
3881
- * sources, the original `host/path` shape (with slashes preserved).
3882
- * - `source` — which source matched. Useful for diagnostics and the
3883
- * `vitest-agent doctor`-style commands.
3884
- * @public
3885
- */
3886
- export interface ResolvedIdentity {
3887
- readonly projectKey: string;
3888
- readonly canonicalForm: string;
3889
- readonly source: ProjectIdentitySource;
3890
- }
3891
- /** @public */
3892
- export type ProjectIdentitySource = "explicit" | "toml" | "git-remote" | "package-repository" | "package-name";
3893
- /**
3894
- * Per-source candidate values. Each is optional — an absent or empty
3895
- * value causes the resolver to fall through to the next source.
3896
- *
3897
- * The Live layer collects these from real I/O (config file, git
3898
- * subprocess, `package.json` read). Tests pass a literal object.
3899
- * @public
3900
- */
3901
- export interface ProjectIdentityCandidates {
3902
- readonly explicit?: string;
3903
- readonly toml?: string;
3904
- readonly gitRemote?: string;
3905
- readonly packageJsonRepoUrl?: string;
3906
- readonly packageJsonName?: string;
3907
- }
3908
- /**
3909
- * Options accepted by the `ProjectIdentity.resolve` service method.
3910
- *
3911
- * `projectId` is the priority-1 escape hatch — pass when the user has
3912
- * configured `AgentPlugin({ projectId: "..." })` in `vitest.config.ts`.
3913
- * @public
3914
- */
3915
- export interface ResolveProjectIdentityOptions {
3916
- readonly projectId?: string;
3917
- }
3918
- /**
3919
- * Pure priority resolver. Returns `null` when no candidate produces a
3920
- * usable value — the caller wraps `null` into a tagged error.
3921
- *
3922
- * For non-git sources the `canonicalForm` equals the original
3923
- * (un-normalized) input so the discovery registry can display
3924
- * `@spencerbeggs/vitest-agent` rather than the underscored form. For
3925
- * git sources, `canonicalForm` is the slash-preserving `host/path`
3926
- * shape from `canonicalizeGitUrl`.
3927
- * @public
3928
- */
3929
- export declare const resolveProjectIdentityFromCandidates: (candidates: ProjectIdentityCandidates) => ResolvedIdentity | null;
3930
- declare const ProjectIdentity_base: Context.ServiceClass<ProjectIdentity, "vitest-agent/ProjectIdentity", {
3931
- readonly resolve: (workspaceRoot: string, options?: ResolveProjectIdentityOptions) => Effect.Effect<ResolvedIdentity, ProjectIdentityNotResolvableError>;
3932
- }>;
3933
- /**
3934
- * Service tag. The Live layer (in `layers/ProjectIdentityLive.ts`)
3935
- * wires up the I/O sources; tests provide a stub that returns a
3936
- * pre-built `ResolvedIdentity`.
3937
- * @public
3938
- */
3939
- export declare class ProjectIdentity extends ProjectIdentity_base {}
3940
- //#endregion
3941
- //#region src/layers/ProjectIdentityLive.d.ts
3942
- /**
3943
- * Effect environment type required by `collectCandidates` and the
3944
- * `ProjectIdentityLive` layer. Exported only so the layer's
3945
- * `Layer.Layer<ProjectIdentity, never, CandidateContext>` signature
3946
- * has a named referent — consumers should provide the four named
3947
- * services (FileSystem, WorkspaceDiscovery, VitestAgentConfigFile,
3948
- * CommandExecutor) rather than reference this type directly.
3949
- *
3950
- * @public
3951
- */
3952
- export type CandidateContext = FileSystem.FileSystem | WorkspaceDiscovery | VitestAgentConfigFile | ChildProcessSpawner.ChildProcessSpawner;
3953
- /**
3954
- * Live layer that wires the resolver into real I/O. Requires
3955
- * `FileSystem`, `CommandExecutor`, `WorkspaceDiscovery`, and
3956
- * `VitestAgentConfigFile`. The platform context comes from
3957
- * `NodeServices.layer` at the entry point.
3958
- * @public
3959
- */
3960
- export declare const ProjectIdentityLive: Layer.Layer<ProjectIdentity, never, CandidateContext>;
3961
- /**
3962
- * Build a Test layer that returns a fixed `ResolvedIdentity` (or
3963
- * fails with `ProjectIdentityNotResolvableError`). Use in unit tests
3964
- * that depend on `ProjectIdentity` but don't want to wire upstream
3965
- * services.
3966
- * @public
3967
- */
3968
- export declare const ProjectIdentityTest: (result: ResolvedIdentity | ProjectIdentityNotResolvableError) => Layer.Layer<ProjectIdentity, never, never>;
3969
- //#endregion
3970
- //#region src/services/RunContext.d.ts
3971
- declare const RunContext_base: Schema.Class<RunContext, Schema.Struct<{
3972
- readonly gitBranch: Schema.NullOr<Schema.String>;
3973
- readonly gitCommitSha: Schema.NullOr<Schema.String>;
3974
- readonly gitDirty: Schema.NullOr<Schema.Boolean>;
3975
- readonly gitUpstream: Schema.NullOr<Schema.String>;
3976
- readonly gitWorktreeDir: Schema.NullOr<Schema.String>;
3977
- readonly hostSource: Schema.NullOr<Schema.String>;
3978
- readonly hostValue: Schema.NullOr<Schema.String>;
3979
- readonly hostMetadata: Schema.NullOr<Schema.Unknown>;
3980
- }>, {}>;
3981
- /**
3982
- * Per-run snapshot of the workspace's git state and host context.
3983
- * Every field is nullable: a non-git workspace has all-NULL git
3984
- * fields, a CI run with no terminal probe match has all-NULL host
3985
- * fields, and a worker that can't read upstream info has a NULL
3986
- * `gitUpstream` while everything else is set.
3987
- *
3988
- * Declared as a `Schema.Class` so callers can `new RunContext({...})`
3989
- * and `Schema.encode(...)` for the SQLite row mapping.
3990
- * @public
3991
- */
3992
- export declare class RunContext extends RunContext_base {}
3993
- declare const AgentContext_base: Schema.Class<AgentContext, Schema.Struct<{
3994
- readonly startGitBranch: Schema.NullOr<Schema.String>;
3995
- readonly startGitCommitSha: Schema.NullOr<Schema.String>;
3996
- readonly startWorktreeDir: Schema.NullOr<Schema.String>;
3997
- }>, {}>;
3998
- /**
3999
- * Subset of {@link RunContext} captured at agent registration. Only
4000
- * the inheritable git context — branch, sha, worktree path. Mid-run
4001
- * dirty-tree state and upstream tracking are per-run concerns.
4002
- * @public
4003
- */
4004
- export declare class AgentContext extends AgentContext_base {}
4005
- declare const RunContext$_base: Context.ServiceClass<RunContext$, "vitest-agent/RunContextService", {
4006
- readonly captureRunContext: (cwd: string) => Effect.Effect<RunContext>;
4007
- readonly captureAgentContext: (cwd: string) => Effect.Effect<AgentContext>;
4008
- }>;
4009
- /**
4010
- * Service tag. The Live layer captures real I/O; the Test layer
4011
- * returns whatever the test fixture passes.
4012
- * @public
4013
- */
4014
- export declare class RunContext$ extends RunContext$_base {}
4015
- /**
4016
- * Re-export the service tag under a less-collision-prone name. The
4017
- * `RunContext` Schema.Class above shares its symbol-name with the
4018
- * service tag concept; the `$` suffix on the Context.Tag class name
4019
- * keeps both addressable from the same module.
4020
- *
4021
- * @public
4022
- */
4023
- export declare const RunContextService: typeof RunContext$;
4024
- /** @public */
4025
- export type RunContextService = RunContext$;
4026
- //#endregion
4027
- //#region src/layers/RunContextLive.d.ts
4028
- /**
4029
- * Live layer. Requires `ChildProcessSpawner` (provided by
4030
- * `NodeServices.layer` at the entry point). Reads `process.env`
4031
- * directly for host-metadata probes — the env walk is pure but the
4032
- * env source is process-global, captured once when the layer
4033
- * constructs.
4034
- * @public
4035
- */
4036
- export declare const RunContextLive: Layer.Layer<RunContextService, never, ChildProcessSpawner.ChildProcessSpawner>;
4037
- /**
4038
- * Build a Test layer that returns fixed `RunContext` and
4039
- * `AgentContext` values regardless of `cwd`.
4040
- * @public
4041
- */
4042
- export declare const RunContextTest: (fixture: {
4043
- readonly runContext: RunContext;
4044
- readonly agentContext: AgentContext;
4045
- }) => Layer.Layer<RunContextService, never, never>;
4046
- //#endregion
4047
- //#region src/lib/format-triage.d.ts
4048
- /** @public */
4049
- interface FormatTriageOptions {
4050
- readonly project?: string;
4051
- readonly maxLines?: number;
4052
- }
4053
- /**
4054
- * Generates an orientation triage markdown string for LLM agents.
4055
- * Summarises recent test runs, active sessions, acceptance metrics,
4056
- * and (forward-compat) the most recent TDD session.
4057
- *
4058
- * Error channel is `never` — all DataReader errors are swallowed and
4059
- * replaced with empty defaults so the caller is guaranteed a string.
4060
- * @public
4061
- */
4062
- export declare const formatTriageEffect: (options?: FormatTriageOptions) => Effect.Effect<string, never, DataReader>;
4063
- //#endregion
4064
- //#region src/lib/format-wrapup.d.ts
4065
- /** @public */
4066
- type WrapupKind = "stop" | "session_end" | "pre_compact" | "tdd_handoff" | "user_prompt_nudge";
4067
- /** @public */
4068
- interface FormatWrapupOptions {
4069
- readonly sessionId?: number;
4070
- readonly chatId?: string;
4071
- readonly kind: WrapupKind;
4072
- readonly userPromptHint?: string;
4073
- }
4074
- /** @public */
4075
- export declare const formatWrapupEffect: (options: FormatWrapupOptions) => Effect.Effect<string, never, DataReader>;
4076
- //#endregion
4077
- //#region src/migrations/0001_initial.d.ts
4078
- /** @internal */
4079
- declare const migration: Effect.Effect<void, import("effect/unstable/sql/SqlError").SqlError, SqlClient>;
4080
- //#endregion
4081
- //#region src/migrations/0002_test_artifacts.d.ts
4082
- /** @internal */
4083
- declare const migration$1: Effect.Effect<void, import("effect/unstable/sql/SqlError").SqlError, SqlClient>;
4084
- //#endregion
4085
- //#region src/migrations/index.d.ts
4086
- /**
4087
- * Every migration that must run against a per-project `data.db`, keyed by
4088
- * migration id in application order.
4089
- *
4090
- * This is the single source of truth for the project database's migration
4091
- * set: `ensureMigrated`, the sdk testing layer, `ReporterLive`, `McpLive`,
4092
- * `CliLive` and `SidecarLive` all pass it straight to
4093
- * `SqliteMigrator.fromRecord`, so adding a migration file and registering it
4094
- * here is enough to reach every process that opens a project database.
4095
- *
4096
- * The session-map and discovery-registry databases are separate schemas with
4097
- * their own migrations and are deliberately not listed here.
4098
- *
4099
- * @public
4100
- */
4101
- export declare const PROJECT_MIGRATIONS: {
4102
- readonly "0001_initial": import("effect/Effect").Effect<void, import("effect/unstable/sql/SqlError").SqlError, import("effect/unstable/sql/SqlClient").SqlClient>;
4103
- readonly "0002_test_artifacts": import("effect/Effect").Effect<void, import("effect/unstable/sql/SqlError").SqlError, import("effect/unstable/sql/SqlClient").SqlClient>;
4104
- };
4105
- //#endregion
4106
- //#region src/migrations/registry_0001_initial.d.ts
4107
- /**
4108
- * Migration for the global discovery registry SQLite at
4109
- * `$XDG_DATA_HOME/vitest-agent/registry.db`.
4110
- *
4111
- * Single table `known_projects` indexed by `project_key` (the
4112
- * filesystem-safe form from {@link ProjectIdentity}). Tooling like
4113
- * `mcp-app` queries this table to enumerate every vitest-agent
4114
- * project the user has ever run on this machine.
4115
- *
4116
- * The registry never blocks anything — its writes are best-effort.
4117
- * Concurrent writers from multiple Claude Code windows converge via
4118
- * the `ON CONFLICT(project_key) DO UPDATE` upsert.
4119
- * @public
4120
- */
4121
- declare const migration$2: Effect.Effect<void, import("effect/unstable/sql/SqlError").SqlError, SqlClient>;
4122
- //#endregion
4123
- //#region src/migrations/session_map_0001_initial.d.ts
4124
- /** @internal */
4125
- declare const migration$3: Effect.Effect<void, import("effect/unstable/sql/SqlError").SqlError, SqlClient>;
4126
- //#endregion
4127
- //#region src/schemas/ChannelEvent.d.ts
4128
- /** @public */
4129
- export declare const SessionOutcome: Schema.Literals<readonly ["succeeded", "blocked", "abandoned"]>;
4130
- /** @public */
4131
- export type SessionOutcome = typeof SessionOutcome.Type;
4132
- /** @public */
4133
- export declare const GoalsReadyEvent: Schema.Struct<{
4134
- readonly type: Schema.Literal<"goals_ready">;
4135
- readonly sessionId: Schema.Number;
4136
- readonly goals: Schema.$Array<Schema.Struct<{
4137
- readonly id: Schema.Number;
4138
- readonly ordinal: Schema.Number;
4139
- readonly goal: Schema.String;
4140
- }>>;
4141
- }>;
4142
- /** @public */
4143
- export type GoalsReadyEvent = typeof GoalsReadyEvent.Type;
4144
- /** @public */
4145
- export declare const GoalAddedEvent: Schema.Struct<{
4146
- readonly type: Schema.Literal<"goal_added">;
4147
- readonly sessionId: Schema.Number;
4148
- readonly goal: Schema.Struct<{
4149
- readonly id: Schema.Number;
4150
- readonly ordinal: Schema.Number;
4151
- readonly goal: Schema.String;
4152
- }>;
4153
- }>;
4154
- /** @public */
4155
- export type GoalAddedEvent = typeof GoalAddedEvent.Type;
4156
- /** @public */
4157
- export declare const GoalStartedEvent: Schema.Struct<{
4158
- readonly type: Schema.Literal<"goal_started">;
4159
- readonly sessionId: Schema.Number;
4160
- readonly goalId: Schema.Number;
4161
- }>;
4162
- /** @public */
4163
- export type GoalStartedEvent = typeof GoalStartedEvent.Type;
4164
- /** @public */
4165
- export declare const GoalCompletedEvent: Schema.Struct<{
4166
- readonly type: Schema.Literal<"goal_completed">;
4167
- readonly sessionId: Schema.Number;
4168
- readonly goalId: Schema.Number;
4169
- readonly behaviorIds: Schema.$Array<Schema.Number>;
4170
- }>;
4171
- /** @public */
4172
- export type GoalCompletedEvent = typeof GoalCompletedEvent.Type;
4173
- /** @public */
4174
- export declare const GoalAbandonedEvent: Schema.Struct<{
4175
- readonly type: Schema.Literal<"goal_abandoned">;
4176
- readonly sessionId: Schema.Number;
4177
- readonly goalId: Schema.Number;
4178
- readonly reason: Schema.String;
4179
- }>;
4180
- /** @public */
4181
- export type GoalAbandonedEvent = typeof GoalAbandonedEvent.Type;
4182
- /** @public */
4183
- export declare const BehaviorsReadyEvent: Schema.Struct<{
4184
- readonly type: Schema.Literal<"behaviors_ready">;
4185
- readonly sessionId: Schema.Number;
4186
- readonly goalId: Schema.Number;
4187
- readonly behaviors: Schema.$Array<Schema.Struct<{
4188
- readonly id: Schema.Number;
4189
- readonly ordinal: Schema.Number;
4190
- readonly behavior: Schema.String;
4191
- }>>;
4192
- }>;
4193
- /** @public */
4194
- export type BehaviorsReadyEvent = typeof BehaviorsReadyEvent.Type;
4195
- /** @public */
4196
- export declare const BehaviorAddedEvent: Schema.Struct<{
4197
- readonly type: Schema.Literal<"behavior_added">;
4198
- readonly sessionId: Schema.Number;
4199
- readonly goalId: Schema.Number;
4200
- readonly behavior: Schema.Struct<{
4201
- readonly id: Schema.Number;
4202
- readonly ordinal: Schema.Number;
4203
- readonly behavior: Schema.String;
4204
- }>;
4205
- }>;
4206
- /** @public */
4207
- export type BehaviorAddedEvent = typeof BehaviorAddedEvent.Type;
2181
+ export type BehaviorAddedEvent = typeof BehaviorAddedEvent.Type;
4208
2182
  /** @public */
4209
2183
  export declare const BehaviorStartedEvent: Schema.Struct<{
4210
2184
  readonly type: Schema.Literal<"behavior_started">;
@@ -4362,6 +2336,31 @@ export declare const BehaviorScopedEventTypes: readonly ["behavior_started", "ph
4362
2336
  /** @public */
4363
2337
  export type BehaviorScopedEventType = (typeof BehaviorScopedEventTypes)[number];
4364
2338
  //#endregion
2339
+ //#region src/schemas/Config.d.ts
2340
+ declare const VitestAgentConfig_base: Schema.Class<VitestAgentConfig, Schema.Struct<{
2341
+ readonly cacheDir: Schema.optional<Schema.String>;
2342
+ readonly projectKey: Schema.optional<Schema.String>;
2343
+ }>, {}>;
2344
+ /**
2345
+ * Schema for the optional `vitest-agent.config.toml` file.
2346
+ *
2347
+ * Both fields are optional. When the file is absent or these fields are
2348
+ * unset, `resolveDataPath` falls back to deriving the path from the
2349
+ * workspace's `package.json` `name` under the XDG data directory.
2350
+ *
2351
+ * Fields:
2352
+ * - `cacheDir` — absolute path overriding the entire data directory. Highest
2353
+ * precedence after the programmatic option. Use this to relocate the SQLite
2354
+ * database (e.g. project-local `.vitest-agent/`) instead of the
2355
+ * default XDG location.
2356
+ * - `projectKey` — overrides the workspace key segment under the XDG data
2357
+ * directory. Use this when two unrelated projects on the same machine
2358
+ * share a `package.json` `name` (the collision case for workspace-name
2359
+ * keying), or when you want a stable key independent of `name` changes.
2360
+ * @public
2361
+ */
2362
+ export declare class VitestAgentConfig extends VitestAgentConfig_base {}
2363
+ //#endregion
4365
2364
  //#region src/schemas/ConsoleLeaks.d.ts
4366
2365
  /**
4367
2366
  * Per-file stray-console-output detail. Counts are of console writes
@@ -4536,6 +2535,50 @@ export declare const CoverageTargets: Schema.$Record<Schema.String, Schema.Union
4536
2535
  /** @public */
4537
2536
  export type CoverageTargets = typeof CoverageTargets.Type;
4538
2537
  //#endregion
2538
+ //#region src/schemas/History.d.ts
2539
+ /**
2540
+ * A single test run outcome (pass or fail only).
2541
+ * @public
2542
+ */
2543
+ export declare const TestRun: Schema.Struct<{
2544
+ readonly timestamp: Schema.String;
2545
+ readonly state: Schema.Literals<readonly ["passed", "failed"]>;
2546
+ }>;
2547
+ /** @public */
2548
+ export type TestRun = typeof TestRun.Type;
2549
+ /**
2550
+ * History for a single test across multiple runs.
2551
+ * @public
2552
+ */
2553
+ export declare const TestHistory: Schema.Struct<{
2554
+ readonly modulePath: Schema.String;
2555
+ readonly fullName: Schema.String;
2556
+ readonly runs: Schema.$Array<Schema.Struct<{
2557
+ readonly timestamp: Schema.String;
2558
+ readonly state: Schema.Literals<readonly ["passed", "failed"]>;
2559
+ }>>;
2560
+ }>;
2561
+ /** @public */
2562
+ export type TestHistory = typeof TestHistory.Type;
2563
+ /**
2564
+ * Per-project history record containing all tracked tests.
2565
+ * @public
2566
+ */
2567
+ export declare const HistoryRecord: Schema.Struct<{
2568
+ readonly project: Schema.String;
2569
+ readonly updatedAt: Schema.String;
2570
+ readonly tests: Schema.$Array<Schema.Struct<{
2571
+ readonly modulePath: Schema.String;
2572
+ readonly fullName: Schema.String;
2573
+ readonly runs: Schema.$Array<Schema.Struct<{
2574
+ readonly timestamp: Schema.String;
2575
+ readonly state: Schema.Literals<readonly ["passed", "failed"]>;
2576
+ }>>;
2577
+ }>>;
2578
+ }>;
2579
+ /** @public */
2580
+ export type HistoryRecord = typeof HistoryRecord.Type;
2581
+ //#endregion
4539
2582
  //#region src/schemas/Options.d.ts
4540
2583
  /**
4541
2584
  * Per-executor console-output matrix. Most users never set this — the
@@ -4822,6 +2865,85 @@ export declare const RunReportFile: Schema.Struct<{
4822
2865
  /** @public */
4823
2866
  export type RunReportFile = typeof RunReportFile.Type;
4824
2867
  //#endregion
2868
+ //#region src/schemas/Tdd.d.ts
2869
+ /** @public */
2870
+ export declare const GoalStatus: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2871
+ /** @public */
2872
+ export type GoalStatus = typeof GoalStatus.Type;
2873
+ /** @public */
2874
+ export declare const BehaviorStatus: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2875
+ /** @public */
2876
+ export type BehaviorStatus = typeof BehaviorStatus.Type;
2877
+ /** @public */
2878
+ export declare const GoalRow: Schema.Struct<{
2879
+ readonly id: Schema.Number;
2880
+ readonly sessionId: Schema.Number;
2881
+ readonly ordinal: Schema.Number;
2882
+ readonly goal: Schema.String;
2883
+ readonly status: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2884
+ readonly createdAt: Schema.String;
2885
+ }>;
2886
+ /** @public */
2887
+ export type GoalRow = typeof GoalRow.Type;
2888
+ /** @public */
2889
+ export declare const BehaviorRow: Schema.Struct<{
2890
+ readonly id: Schema.Number;
2891
+ readonly goalId: Schema.Number;
2892
+ readonly ordinal: Schema.Number;
2893
+ readonly behavior: Schema.String;
2894
+ readonly suggestedTestName: Schema.NullOr<Schema.String>;
2895
+ readonly status: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2896
+ readonly createdAt: Schema.String;
2897
+ }>;
2898
+ /** @public */
2899
+ export type BehaviorRow = typeof BehaviorRow.Type;
2900
+ /** @public */
2901
+ export declare const GoalDetail: Schema.Struct<{
2902
+ readonly id: Schema.Number;
2903
+ readonly sessionId: Schema.Number;
2904
+ readonly ordinal: Schema.Number;
2905
+ readonly goal: Schema.String;
2906
+ readonly status: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2907
+ readonly createdAt: Schema.String;
2908
+ readonly behaviors: Schema.$Array<Schema.Struct<{
2909
+ readonly id: Schema.Number;
2910
+ readonly goalId: Schema.Number;
2911
+ readonly ordinal: Schema.Number;
2912
+ readonly behavior: Schema.String;
2913
+ readonly suggestedTestName: Schema.NullOr<Schema.String>;
2914
+ readonly status: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2915
+ readonly createdAt: Schema.String;
2916
+ }>>;
2917
+ }>;
2918
+ /** @public */
2919
+ export type GoalDetail = typeof GoalDetail.Type;
2920
+ /** @public */
2921
+ export declare const BehaviorDetail: Schema.Struct<{
2922
+ readonly id: Schema.Number;
2923
+ readonly goalId: Schema.Number;
2924
+ readonly ordinal: Schema.Number;
2925
+ readonly behavior: Schema.String;
2926
+ readonly suggestedTestName: Schema.NullOr<Schema.String>;
2927
+ readonly status: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2928
+ readonly createdAt: Schema.String;
2929
+ readonly parentGoal: Schema.Struct<{
2930
+ readonly id: Schema.Number;
2931
+ readonly goal: Schema.String;
2932
+ readonly status: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2933
+ }>;
2934
+ readonly dependencies: Schema.$Array<Schema.Struct<{
2935
+ readonly id: Schema.Number;
2936
+ readonly goalId: Schema.Number;
2937
+ readonly ordinal: Schema.Number;
2938
+ readonly behavior: Schema.String;
2939
+ readonly suggestedTestName: Schema.NullOr<Schema.String>;
2940
+ readonly status: Schema.Literals<readonly ["pending", "in_progress", "done", "abandoned"]>;
2941
+ readonly createdAt: Schema.String;
2942
+ }>>;
2943
+ }>;
2944
+ /** @public */
2945
+ export type BehaviorDetail = typeof BehaviorDetail.Type;
2946
+ //#endregion
4825
2947
  //#region src/schemas/TestArtifacts.d.ts
4826
2948
  /**
4827
2949
  * Source position a test annotation or test artifact points at.
@@ -4913,6 +3035,56 @@ export declare const TestArtifact: Schema.Struct<{
4913
3035
  /** @public */
4914
3036
  export type TestArtifact = typeof TestArtifact.Type;
4915
3037
  //#endregion
3038
+ //#region src/schemas/Trends.d.ts
3039
+ /**
3040
+ * A single coverage trend data point recorded on a full test run.
3041
+ * @public
3042
+ */
3043
+ export declare const TrendEntry: Schema.Struct<{
3044
+ readonly timestamp: Schema.String;
3045
+ readonly coverage: Schema.Struct<{
3046
+ readonly statements: Schema.Number;
3047
+ readonly branches: Schema.Number;
3048
+ readonly functions: Schema.Number;
3049
+ readonly lines: Schema.Number;
3050
+ }>;
3051
+ readonly delta: Schema.Struct<{
3052
+ readonly statements: Schema.Number;
3053
+ readonly branches: Schema.Number;
3054
+ readonly functions: Schema.Number;
3055
+ readonly lines: Schema.Number;
3056
+ }>;
3057
+ readonly direction: Schema.Literals<readonly ["improving", "regressing", "stable"]>;
3058
+ readonly targetsHash: Schema.optional<Schema.String>;
3059
+ }>;
3060
+ /** @public */
3061
+ export type TrendEntry = typeof TrendEntry.Type;
3062
+ /**
3063
+ * Per-project trend record with sliding window of entries.
3064
+ * @public
3065
+ */
3066
+ export declare const TrendRecord: Schema.Struct<{
3067
+ readonly entries: Schema.$Array<Schema.Struct<{
3068
+ readonly timestamp: Schema.String;
3069
+ readonly coverage: Schema.Struct<{
3070
+ readonly statements: Schema.Number;
3071
+ readonly branches: Schema.Number;
3072
+ readonly functions: Schema.Number;
3073
+ readonly lines: Schema.Number;
3074
+ }>;
3075
+ readonly delta: Schema.Struct<{
3076
+ readonly statements: Schema.Number;
3077
+ readonly branches: Schema.Number;
3078
+ readonly functions: Schema.Number;
3079
+ readonly lines: Schema.Number;
3080
+ }>;
3081
+ readonly direction: Schema.Literals<readonly ["improving", "regressing", "stable"]>;
3082
+ readonly targetsHash: Schema.optional<Schema.String>;
3083
+ }>>;
3084
+ }>;
3085
+ /** @public */
3086
+ export type TrendRecord = typeof TrendRecord.Type;
3087
+ //#endregion
4916
3088
  //#region src/schemas/turns/FileEditPayload.d.ts
4917
3089
  /** @public */
4918
3090
  export declare const FileEditPayload: Schema.Struct<{
@@ -5037,97 +3209,6 @@ export declare const TurnPayload: Schema.Union<readonly [Schema.Struct<{
5037
3209
  /** @public */
5038
3210
  export type TurnPayload = typeof TurnPayload.Type;
5039
3211
  //#endregion
5040
- //#region src/services/idempotency.d.ts
5041
- /**
5042
- * Sentinel substituted for `parentAgentId` when the value is `null`.
5043
- * Avoids ambiguity around hashing the literal string "null" or empty
5044
- * string, both of which could collide with caller-supplied values.
5045
- * @public
5046
- */
5047
- export declare const IDEMPOTENCY_ROOT_SENTINEL = "__ROOT__";
5048
- /** @public */
5049
- export interface IdempotencyInput {
5050
- readonly agentType: string;
5051
- readonly parentAgentId: string | null;
5052
- readonly clientNonce: string;
5053
- }
5054
- /**
5055
- * Derive the canonical idempotency key for an `agents` row.
5056
- *
5057
- * Algorithm:
5058
- * sha256(agentType + "|" + (parentAgentId ?? "__ROOT__") + "|" + clientNonce)
5059
- * then base32 (RFC 4648 alphabet, lowercased) truncated to 26 chars.
5060
- *
5061
- * 26 base32 chars = 130 bits, far beyond the birthday-bound for the
5062
- * scoping (UNIQUE per session). The base32 alphabet is a-z2-7 — all
5063
- * lowercase to keep the column lexicographically friendly and
5064
- * case-insensitive on filesystems that we never hit but might in
5065
- * future debugging.
5066
- * @public
5067
- */
5068
- export declare const deriveIdempotencyKey: (input: IdempotencyInput) => string;
5069
- //#endregion
5070
- //#region src/sql/assemblers.d.ts
5071
- /**
5072
- * Minimal shape of a test_runs aggregation row used to build the manifest.
5073
- * @public
5074
- */
5075
- export interface ManifestRow {
5076
- project: string;
5077
- sub_project: string | null;
5078
- timestamp: string;
5079
- reason: string;
5080
- }
5081
- /**
5082
- * Minimal shape of a test_history row used to build a history record.
5083
- * @public
5084
- */
5085
- export interface HistoryRow {
5086
- module_path: string;
5087
- full_name: string;
5088
- timestamp: string;
5089
- state: string;
5090
- }
5091
- /**
5092
- * A `Record<compositeKey, { modulePath, fullName, runs: TestRun[] }>` keyed by
5093
- * the injective `historyKey(modulePath, fullName)` string, so identically-named
5094
- * tests in different files are tracked as distinct entries.
5095
- *
5096
- * This is the internal representation returned by `assembleHistoryRecord`.
5097
- * Callers that need the Effect Schema `HistoryRecord` type should adapt this
5098
- * into the `tests` array format.
5099
- * @public
5100
- */
5101
- export interface AssembledHistoryRecord {
5102
- [compositeKey: string]: {
5103
- modulePath: string;
5104
- fullName: string;
5105
- runs: TestRun[];
5106
- };
5107
- }
5108
- /**
5109
- * Builds a `CacheManifest` from an array of test_runs aggregation rows.
5110
- *
5111
- * Each row represents the latest run for a project/sub_project pair.
5112
- * The `dbPath` is stored as `cacheDir` so CLI tools can locate the source.
5113
- * @public
5114
- */
5115
- export declare function assembleManifest(rows: ManifestRow[], dbPath: string): CacheManifest;
5116
- /**
5117
- * Groups test_history rows by the composite (module_path, full_name) key
5118
- * into a keyed record.
5119
- *
5120
- * Returns `Record<compositeKey, { modulePath, fullName, runs: TestRun[] }>`
5121
- * where `runs` are the accumulated test runs for that test, in the order
5122
- * they appear in `rows`. Two rows sharing `full_name` but differing
5123
- * `module_path` are tracked as distinct entries rather than merged.
5124
- *
5125
- * Only rows with state `"passed"` or `"failed"` are included in runs
5126
- * (matching the `TestRun` schema constraint).
5127
- * @public
5128
- */
5129
- export declare function assembleHistoryRecord(rows: HistoryRow[]): AssembledHistoryRecord;
5130
- //#endregion
5131
3212
  //#region src/utils/ansi.d.ts
5132
3213
  /**
5133
3214
  * Options for ANSI color output control.
@@ -5642,36 +3723,6 @@ export declare const isTimeoutError: (error: {
5642
3723
  name?: string;
5643
3724
  }) => boolean;
5644
3725
  //#endregion
5645
- //#region src/utils/ensure-migrated.d.ts
5646
- /**
5647
- * Ensure the SQLite database at `dbPath` is migrated. Runs migrations at
5648
- * most once per dbPath in the current process; concurrent calls share the
5649
- * same in-flight promise. Subsequent calls (after the first resolves) are
5650
- * no-ops.
5651
- * @public
5652
- */
5653
- export declare function ensureMigrated(dbPath: string, logLevel?: LogLevel.LogLevel, logFile?: string): Promise<void>;
5654
- /**
5655
- * Reset the migration cache. Test-only.
5656
- *
5657
- * @internal
5658
- */
5659
- export declare function _resetMigrationCacheForTesting(): void;
5660
- //#endregion
5661
- //#region src/utils/failure-signature.d.ts
5662
- /** @public */
5663
- export interface FailureSignatureInput {
5664
- readonly error_name: string;
5665
- readonly assertion_message: string;
5666
- readonly top_frame_function_name: string;
5667
- readonly top_frame_function_boundary_line: number | null;
5668
- readonly top_frame_raw_line?: number;
5669
- }
5670
- /** @public */
5671
- export declare const normalizeAssertionShape: (message: string) => string | null;
5672
- /** @public */
5673
- export declare const computeFailureSignature: (input: FailureSignatureInput) => string;
5674
- //#endregion
5675
3726
  //#region src/utils/format-console.d.ts
5676
3727
  /**
5677
3728
  * Options controlling console markdown output formatting.
@@ -5679,6 +3730,8 @@ export declare const computeFailureSignature: (input: FailureSignatureInput) =>
5679
3730
  * @internal
5680
3731
  */
5681
3732
  export interface ConsoleFormatOptions {
3733
+ /** Absolute project root; stripped from file paths for display. */
3734
+ cwd: string;
5682
3735
  /** Output verbosity: `"failures"` (default), `"full"`, or `"silent"`. */
5683
3736
  consoleOutput: "failures" | "full" | "silent";
5684
3737
  /** Maximum number of low-coverage files to show in console output. */
@@ -5723,12 +3776,12 @@ export declare function getWorstMetric(f: FileCoverageReport): {
5723
3776
  * project-relative path for display.
5724
3777
  *
5725
3778
  * @param filePath - Absolute or relative file path
5726
- * @param cwd - Working directory to strip; defaults to `process.cwd()`
3779
+ * @param cwd - Working directory to strip
5727
3780
  * @returns Project-relative path string
5728
3781
  *
5729
3782
  * @internal
5730
3783
  */
5731
- export declare function relativePath(filePath: string, cwd?: string): string;
3784
+ export declare function relativePath(filePath: string, cwd: string): string;
5732
3785
  /**
5733
3786
  * Determine the output tier based on test results and coverage state.
5734
3787
  *
@@ -5926,6 +3979,41 @@ export declare const detectVitestScripts: (scripts: Record<string, string>) => S
5926
3979
  */
5927
3980
  export declare function normalizeWorkspaceKey(name: string): string;
5928
3981
  //#endregion
3982
+ //#region src/utils/posix-path.d.ts
3983
+ /**
3984
+ * Pure POSIX path helpers for the platform-free core.
3985
+ *
3986
+ * `@vitest-agent/sdk` must not import `node:path`, so the handful of path
3987
+ * operations the core needs are implemented here over normalized
3988
+ * forward-slash strings. Every helper accepts Windows-style input (a
3989
+ * backslash separator) and normalizes it via {@link toPosix} at entry, so a
3990
+ * caller never has to know which separator the platform used.
3991
+ */
3992
+ /**
3993
+ * Normalizes `p` to forward slashes: every backslash becomes `/`.
3994
+ * @public
3995
+ */
3996
+ export declare const toPosix: (p: string) => string;
3997
+ /**
3998
+ * Last segment of `p` after normalization — `"b.ts"` for `"/a/b.ts"`.
3999
+ * Trailing separators are ignored, so `"/a/b/"` yields `"b"`.
4000
+ * @public
4001
+ */
4002
+ export declare const basenamePosix: (p: string) => string;
4003
+ /**
4004
+ * Joins `parts` with a single `/` between each, normalizing every part and
4005
+ * collapsing duplicate separators at the seams. Empty parts are skipped.
4006
+ * @public
4007
+ */
4008
+ export declare const joinPosix: (...parts: ReadonlyArray<string>) => string;
4009
+ /**
4010
+ * Path of `to` relative to `from`, both normalized. Returns `""` when they
4011
+ * are the same path and `to` unchanged when it is not under `from` (no
4012
+ * `../` climbing — the core has no notion of a filesystem to climb through).
4013
+ * @public
4014
+ */
4015
+ export declare const relativePosix: (from: string, to: string) => string;
4016
+ //#endregion
5929
4017
  //#region src/utils/probe-host-metadata.d.ts
5930
4018
  /** @public */
5931
4019
  export interface HostMetadataResult {
@@ -5955,99 +4043,6 @@ export interface HostMetadataResult {
5955
4043
  */
5956
4044
  export declare const probeHostMetadataFromEnv: (env: Record<string, string | undefined>) => HostMetadataResult;
5957
4045
  //#endregion
5958
- //#region src/utils/resolve-data-path.d.ts
5959
- /**
5960
- * Filename of the SQLite database that stores all reporter data.
5961
- * @public
5962
- */
5963
- export declare const DATABASE_FILENAME = "data.db";
5964
- /**
5965
- * Caller-supplied overrides for `resolveDataPath`.
5966
- * @public
5967
- */
5968
- export interface ResolveDataPathOptions {
5969
- /**
5970
- * Programmatic override for the entire data directory. Highest precedence.
5971
- *
5972
- * Use this when the reporter or plugin user has explicitly set
5973
- * `reporter.cacheDir`. The returned path is `<cacheDir>/data.db`.
5974
- */
5975
- readonly cacheDir?: string;
5976
- }
5977
- /**
5978
- * Resolve the absolute path to the SQLite database for `projectDir`.
5979
- *
5980
- * The directory containing the database is ensured to exist before the
5981
- * function returns, so callers can open the database immediately without
5982
- * needing to create parent directories. The SQLite driver creates the file
5983
- * but not its parent.
5984
- *
5985
- * Precedence (highest first):
5986
- *
5987
- * 1. `options.cacheDir` — programmatic override.
5988
- * 2. `cacheDir` from `vitest-agent.config.toml`.
5989
- * 3. `<XDG data>/<normalized projectKey from config>/data.db`.
5990
- * 4. `<XDG data>/<projectKey resolved from cwd's package.json>/data.db`.
5991
- * Source 4 prefers `repository.url` (canonicalized to `host__path`),
5992
- * falling back to the normalized `name`. This matches the sidecar
5993
- * CLI's `_internal register-agent` resolver so the reporter and
5994
- * sidecar always write to the same `data.db`.
5995
- *
5996
- * The XDG data directory is namespaced via `AppDirs` (typically
5997
- * `$XDG_DATA_HOME/vitest-agent`, defaulting to
5998
- * `~/.local/share/vitest-agent`).
5999
- *
6000
- * The path is a function of identity, not filesystem layout. When no
6001
- * `package.json` is reachable from `projectDir`, the cwd basename is used
6002
- * as the final fallback so the function never throws on identity lookup.
6003
- *
6004
- * @param projectDir - Absolute path inside the user's workspace.
6005
- * @param options - Optional programmatic overrides.
6006
- * @public
6007
- */
6008
- export declare const resolveDataPath: (projectDir: string, options?: ResolveDataPathOptions) => Effect.Effect<any, import("@effected/xdg").AppDirsError | import("effect/PlatformError").PlatformError | import("@effected/config-file").ConfigReadError, AppDirs | FileSystem.FileSystem | VitestAgentConfigFile>;
6009
- //#endregion
6010
- //#region src/utils/resolve-project-key-from-cwd.d.ts
6011
- /**
6012
- * Compute the project key for a workspace by reading `package.json`
6013
- * fields directly. Returns the canonical `host__path` form when a git
6014
- * remote URL is present, otherwise the normalized package name.
6015
- *
6016
- * Always returns a non-empty string — falls back to the cwd basename
6017
- * (or `"anonymous-project"`) so callers don't have to handle the
6018
- * empty case.
6019
- * @public
6020
- */
6021
- export declare const resolveProjectKeyFromCwd: (cwd: string) => string;
6022
- //#endregion
6023
- //#region src/utils/resolve-workspace-key.d.ts
6024
- /**
6025
- * Resolve the normalized workspace key for the workspace containing
6026
- * `projectDir`.
6027
- *
6028
- * The key is the root `package.json`'s `name`, normalized via
6029
- * `normalizeWorkspaceKey`. This becomes the directory segment under
6030
- * `$XDG_DATA_HOME/vitest-agent/` where the SQLite database lives.
6031
- *
6032
- * Fails with `WorkspaceRootNotFoundError` when no root workspace is
6033
- * discoverable. `WorkspacePackage.name` is enforced non-empty by
6034
- * `@effected/workspaces`'s schema, so a successful root lookup always yields a
6035
- * usable name.
6036
- *
6037
- * Discovery is anchored at `projectDir` per call via `listPackagesIn`, not at
6038
- * the `WorkspaceDiscovery` layer's `cwd`: patterns, member manifests and names
6039
- * are read from beneath `projectDir`'s own root, so one long-lived layer
6040
- * answers correctly for a git worktree, a nested repository, or an unrelated
6041
- * project. Fails with the library's `WorkspaceRootNotFoundError` when
6042
- * `projectDir` sits in no workspace at all; results are memoized per resolved
6043
- * root, so many directories in one workspace share a single discovery.
6044
- *
6045
- * @param projectDir - Absolute path inside the workspace. Typically the
6046
- * reporter's resolved `projectDir` (CLAUDE_PROJECT_DIR or process.cwd()).
6047
- * @public
6048
- */
6049
- export declare const resolveWorkspaceKey: (projectDir: string) => Effect.Effect<string, WorkspaceRootNotFoundError | WorkspaceDiscoveryFailure, WorkspaceDiscovery>;
6050
- //#endregion
6051
4046
  //#region src/utils/safe-filename.d.ts
6052
4047
  /**
6053
4048
  * Convert a project name to a filesystem-safe filename.
@@ -6213,16 +4208,128 @@ export interface CoverageTargetsShapeResult {
6213
4208
  */
6214
4209
  export declare function validateCoverageTargetsShape(input: unknown): CoverageTargetsShapeResult;
6215
4210
  //#endregion
6216
- //#region src/index.d.ts
4211
+ //#region src/utils/validate-phase-transition.d.ts
4212
+ /** @public */
4213
+ export type Phase = "spike" | "red" | "red.triangulate" | "green" | "green.fake-it" | "refactor" | "extended-red" | "green-without-red";
4214
+ /** @public */
4215
+ export type ArtifactKind = "test_written" | "test_failed_run" | "code_written" | "test_passed_run" | "refactor" | "test_weakened";
4216
+ /**
4217
+ * Explicit test-runner marker on a `tdd_artifacts` row (issue #363). `vitest`
4218
+ * artifacts always carry a `test_case_id` when they anchor a specific test;
4219
+ * `bats` artifacts never do (there is no `test_cases` row for a bats test),
4220
+ * so the D2 binding-rule validator branches on this to accept a bats
4221
+ * run-level artifact without weakening the vitest guard.
4222
+ * @public
4223
+ */
4224
+ export type ArtifactSuite = "vitest" | "bats";
4225
+ /** @public */
4226
+ export interface CitedArtifact {
4227
+ readonly id: number;
4228
+ /**
4229
+ * `tdd_phases.id` of the phase this artifact was actually recorded in — the
4230
+ * artifact's own phase binding. This is the honest anchor for D2 binding
4231
+ * rule 1's window check (issue #245): a test_case's first-ever creation
4232
+ * turn can predate the current phase (e.g. authored during spike, then
4233
+ * re-run inside red) without the evidence itself being stale, so the
4234
+ * window check compares this against `PhaseTransitionContext.current_phase_id`
4235
+ * rather than `test_case_created_turn_at`.
4236
+ */
4237
+ readonly phase_id: number;
4238
+ readonly artifact_kind: ArtifactKind;
4239
+ readonly test_case_id: number | null;
4240
+ readonly test_case_created_turn_at: string | null;
4241
+ readonly test_case_authored_in_session: boolean;
4242
+ readonly test_run_id: number | null;
4243
+ readonly test_first_failure_run_id: number | null;
4244
+ readonly behavior_id: number | null;
4245
+ /**
4246
+ * Issue #363: explicit suite marker distinguishing vitest from bats runs.
4247
+ * Optional on the pure type so hand-built contexts default to `vitest`;
4248
+ * the DB row always carries the persisted value.
4249
+ */
4250
+ readonly suite?: ArtifactSuite;
4251
+ }
4252
+ /** @public */
4253
+ export interface PhaseTransitionContext {
4254
+ readonly tdd_task_id: number;
4255
+ readonly current_phase: Phase;
4256
+ /**
4257
+ * `tdd_phases.id` of the currently open phase row, or `null` when no phase
4258
+ * has been opened yet (the implicit "spike" default before the first
4259
+ * `tdd_phases` row exists). Compared against `cited_artifact.phase_id` for
4260
+ * D2 binding rule 1 (issue #245).
4261
+ */
4262
+ readonly current_phase_id: number | null;
4263
+ readonly phase_started_at: string;
4264
+ readonly now: string;
4265
+ readonly requested_phase: Phase;
4266
+ readonly cited_artifact: CitedArtifact;
4267
+ readonly requested_behavior_id: number | null;
4268
+ }
4269
+ /** @public */
4270
+ export type DenialReason = "missing_artifact_evidence" | "wrong_artifact_kind" | "wrong_source_phase" | "unknown_tdd_task" | "tdd_task_already_ended" | "goal_not_started" | "goal_not_found" | "goal_not_in_progress" | "goal_not_in_tdd_task" | "behavior_not_found" | "behavior_not_in_goal" | "refactor_without_passing_run" | "evidence_not_in_phase_window" | "evidence_not_for_behavior" | "evidence_test_was_already_failing";
4271
+ /** @public */
4272
+ export interface Remediation {
4273
+ readonly suggestedTool: string;
4274
+ readonly suggestedArgs: Record<string, unknown>;
4275
+ readonly humanHint: string;
4276
+ }
4277
+ /** @public */
4278
+ export type PhaseTransitionResult = {
4279
+ readonly accepted: true;
4280
+ readonly phase: Phase;
4281
+ } | {
4282
+ readonly accepted: false;
4283
+ readonly phase: Phase;
4284
+ readonly denialReason: DenialReason;
4285
+ readonly remediation: Remediation;
4286
+ };
4287
+ /**
4288
+ * Return the artifact kind a phase transition requires, plus a
4289
+ * human-readable hint for surfacing in remediations.
4290
+ *
4291
+ * Exported so the MCP `tdd_phase_transition_request` tool can pre-compute
4292
+ * the expected kind when the agent omits `citedArtifactId` (auto-resolve
4293
+ * to the most recent matching artifact). The transitions without a
4294
+ * required artifact (`spike→red`, `*→red`, etc.) return `null`.
4295
+ * @public
4296
+ */
4297
+ export declare const requiredArtifactForTransition: (from: Phase, to: Phase) => {
4298
+ kind: ArtifactKind;
4299
+ humanHint: string;
4300
+ } | null;
4301
+ /**
4302
+ * Whether D2 binding rule 2 (behavior-match) applies to a given transition.
4303
+ *
4304
+ * Only the transitions whose cited evidence must belong to the behavior being
4305
+ * transitioned enforce behavior-match: `red→green` (the failing test for this
4306
+ * behavior) and `green→refactor` (its passing test). It deliberately excludes
4307
+ * `red.triangulate→green` (the cited failing run belongs to an earlier batch
4308
+ * behavior) and `refactor→red` (the required `test_passed_run` is the
4309
+ * just-finished behavior's, never the new target). Exported so the MCP
4310
+ * `tdd_phase_transition_request` tool scopes artifact auto-resolution by
4311
+ * behavior on exactly the same transitions the validator will accept —
4312
+ * keeping the two in lockstep (issue #115).
4313
+ * @public
4314
+ */
4315
+ export declare const transitionEnforcesBehaviorMatch: (from: Phase, to: Phase) => boolean;
4316
+ /** @public */
4317
+ export declare const validatePhaseTransition: (ctx: PhaseTransitionContext) => PhaseTransitionResult;
4318
+ //#endregion
4319
+ //#region src/version.d.ts
6217
4320
  /**
6218
4321
  * The version of this package. Inlined at build time from
6219
4322
  * package.json#version via rslib-builder's __PACKAGE_VERSION__ substitution.
6220
4323
  * Source-level reads (workspace `exports: "./src/index.ts"` during dev)
6221
4324
  * see the `"0.0.0"` fallback — a clear signal the build pipeline has not
6222
4325
  * substituted yet. Exported for version introspection by downstream tooling.
4326
+ *
4327
+ * This is the one sanctioned `process` read in the platform-free core: the
4328
+ * bundler replaces the token at build time, so no runtime `process` access
4329
+ * survives into the published artifact.
6223
4330
  * @public
6224
4331
  */
6225
4332
  export declare const CURRENT_SDK_VERSION: string;
6226
4333
  //#endregion
6227
- export { FileCoverageReport as CoverageFile, type FormatTriageOptions, type FormatWrapupOptions, type WrapupKind, migration as migration0001, migration$1 as migration0002, migration$2 as registryMigration0001, migration$3 as sessionMapMigration0001 };
4334
+ export { FileCoverageReport as CoverageFile };
6228
4335
  //# sourceMappingURL=index.d.ts.map