@velum-labs/routekit-eval-setup 1.0.26 → 1.1.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 (38) hide show
  1. package/dist/adapters/git-basis-snapshot.d.ts +27 -0
  2. package/dist/adapters/git-basis-snapshot.js +178 -0
  3. package/dist/basis-candidates.d.ts +72 -0
  4. package/dist/basis-candidates.js +157 -0
  5. package/dist/basis-projection.d.ts +9 -0
  6. package/dist/basis-projection.js +30 -0
  7. package/dist/basis-validation.d.ts +38 -0
  8. package/dist/basis-validation.js +187 -0
  9. package/dist/effect-api.d.ts +8 -0
  10. package/dist/effect-api.js +5 -0
  11. package/dist/errors.d.ts +11 -1
  12. package/dist/errors.js +5 -0
  13. package/dist/index.d.ts +15 -3
  14. package/dist/index.js +10 -2
  15. package/dist/project-artifacts.d.ts +26 -1
  16. package/dist/project-artifacts.js +52 -1
  17. package/dist/project-contracts.d.ts +3594 -0
  18. package/dist/project-contracts.js +344 -1
  19. package/dist/project-store.d.ts +3 -1
  20. package/dist/project-store.js +39 -33
  21. package/dist/project-workflow.d.ts +2 -2
  22. package/dist/services/basis-authoring/service.d.ts +253 -0
  23. package/dist/services/basis-authoring/service.js +547 -0
  24. package/dist/services/basis-onboarding/service.d.ts +48 -0
  25. package/dist/services/basis-onboarding/service.js +491 -0
  26. package/dist/services/basis-repair/service.d.ts +25 -0
  27. package/dist/services/basis-repair/service.js +249 -0
  28. package/dist/test/basis-authoring.test.d.ts +1 -0
  29. package/dist/test/basis-authoring.test.js +194 -0
  30. package/dist/test/basis-onboarding.test.d.ts +1 -0
  31. package/dist/test/basis-onboarding.test.js +385 -0
  32. package/dist/test/basis-repair.test.d.ts +1 -0
  33. package/dist/test/basis-repair.test.js +338 -0
  34. package/dist/test/basis-v3.test.d.ts +1 -0
  35. package/dist/test/basis-v3.test.js +262 -0
  36. package/dist/test/project-v2.test.d.ts +1 -0
  37. package/dist/test/project-v2.test.js +99 -0
  38. package/package.json +4 -3
@@ -1,6 +1,7 @@
1
- import { DecompositionResult, EvalComparisonResult, PublishedRoutingActivation, RoutingActivationConstraints, RequestRoutingRequirements, RoutingObjectivePolicy, WorkloadDimension } from "@velum-labs/routekit-eval-contracts";
1
+ import { DecompositionResult, DimensionScoreLabelV3, DimensionScorePredictionV3, EvalComparisonResult, PublishedRoutingActivation, RoutingBasisApprovalV3, RoutingBasisV3, RoutingActivationConstraints, RequestRoutingRequirements, RoutingObjectivePolicy, WorkloadDimension } from "@velum-labs/routekit-eval-contracts";
2
2
  import { Schema } from "effect";
3
3
  export const EVAL_PROJECT_VERSION = 1;
4
+ export const EVAL_PROJECT_V2_VERSION = 2;
4
5
  export const EvalProjectQuestion = Schema.Struct({
5
6
  id: Schema.Literals([
6
7
  "workload-description",
@@ -167,6 +168,348 @@ export const EvalProjectState = Schema.Union([
167
168
  QualifiedState,
168
169
  ActivatedState
169
170
  ]);
171
+ export const FrozenRepositorySnapshotV3 = Schema.Struct({
172
+ repositoryRootDigest: Schema.String,
173
+ requestedRef: Schema.String,
174
+ commit: Schema.String,
175
+ tree: Schema.String,
176
+ repositoryDigest: Schema.String,
177
+ capturedAt: Schema.String,
178
+ dirty: Schema.Boolean,
179
+ dirtyPatchDigest: Schema.optionalKey(Schema.String),
180
+ sourceInventoryDigest: Schema.String
181
+ });
182
+ export const BasisTaskRecordV3 = Schema.Struct({
183
+ caseId: Schema.String,
184
+ occurredAt: Schema.String,
185
+ taskDigest: Schema.String,
186
+ summary: Schema.String,
187
+ changedPathDigest: Schema.String,
188
+ changedPaths: Schema.Array(Schema.String)
189
+ });
190
+ export const BasisTaskSplitV3 = Schema.Struct({
191
+ version: Schema.Literal(1),
192
+ splitDigest: Schema.String,
193
+ construction: Schema.Array(BasisTaskRecordV3),
194
+ validation: Schema.Array(BasisTaskRecordV3),
195
+ final: Schema.Array(BasisTaskRecordV3),
196
+ provisional: Schema.Boolean,
197
+ warnings: Schema.Array(Schema.String)
198
+ });
199
+ export const BasisCandidateRecipeV3 = Schema.Struct({
200
+ id: Schema.String,
201
+ dimensionCount: NonNegativeInteger,
202
+ historySize: NonNegativeInteger,
203
+ sampling: Schema.Literals(["none", "diverse", "recent"]),
204
+ includeChangedPathStatistics: Schema.Boolean,
205
+ deterministic: Schema.Boolean
206
+ });
207
+ export const BasisGenerationPlanV3 = Schema.Struct({
208
+ version: Schema.Literal(1),
209
+ planDigest: Schema.String,
210
+ repositoryDigest: Schema.String,
211
+ splitDigest: Schema.String,
212
+ authorModel: Schema.String,
213
+ recipes: Schema.Array(BasisCandidateRecipeV3),
214
+ plannedPrimaryCalls: NonNegativeInteger,
215
+ maximumAttempts: NonNegativeInteger,
216
+ requiredTotalInputTokens: NonNegativeInteger,
217
+ requiredTotalOutputTokens: NonNegativeInteger
218
+ });
219
+ export const BasisGenerationJobV3 = Schema.Struct({
220
+ recipeId: Schema.String,
221
+ status: Schema.Literals(["pending", "completed", "failed"]),
222
+ candidateId: Schema.optionalKey(Schema.String),
223
+ attemptCount: NonNegativeInteger,
224
+ inputTokens: NonNegativeInteger,
225
+ outputTokens: NonNegativeInteger,
226
+ callIds: Schema.Array(Schema.String),
227
+ error: Schema.optionalKey(Schema.String)
228
+ });
229
+ export const BasisGenerationLedgerV3 = Schema.Struct({
230
+ version: Schema.Literal(1),
231
+ planDigest: Schema.String,
232
+ ledgerDigest: Schema.String,
233
+ jobs: Schema.Array(BasisGenerationJobV3)
234
+ });
235
+ export const BasisCandidateRecordV3 = Schema.Struct({
236
+ candidateId: Schema.String,
237
+ recipeId: Schema.String,
238
+ basis: RoutingBasisV3,
239
+ basisDigest: Schema.String,
240
+ authorModel: Schema.optionalKey(Schema.String),
241
+ generationConfigurationDigest: Schema.String,
242
+ evidenceDigest: Schema.String,
243
+ createdAt: Schema.String
244
+ });
245
+ export const BasisCandidateCheckpointV3 = Schema.Struct({
246
+ version: Schema.Literal(1),
247
+ generationPlanDigest: Schema.String,
248
+ job: BasisGenerationJobV3,
249
+ candidate: BasisCandidateRecordV3
250
+ });
251
+ export const BasisStructureFindingV3 = Schema.Struct({
252
+ severity: Schema.Literals(["hard", "warning"]),
253
+ code: Schema.String,
254
+ dimensionIds: Schema.Array(Schema.String),
255
+ detail: Schema.String
256
+ });
257
+ export const BasisStructureReportV3 = Schema.Struct({
258
+ candidateId: Schema.String,
259
+ basisDigest: Schema.String,
260
+ eligible: Schema.Boolean,
261
+ dimensionCount: NonNegativeInteger,
262
+ definitionBytes: NonNegativeInteger,
263
+ findings: Schema.Array(BasisStructureFindingV3)
264
+ });
265
+ export const BasisLabelProtocolV3 = Schema.Struct({
266
+ version: Schema.Literal(1),
267
+ protocolDigest: Schema.String,
268
+ kind: Schema.Literals(["reviewed-human", "reviewed-reference-mapper"]),
269
+ author: Schema.String,
270
+ reviewer: Schema.String,
271
+ blindness: Schema.Literal("candidate-output-hidden"),
272
+ activeDimensionThreshold: Schema.Finite,
273
+ unknownThreshold: Schema.Finite
274
+ });
275
+ export const BasisCandidateDatasetV3 = Schema.Struct({
276
+ version: Schema.Literal(1),
277
+ datasetDigest: Schema.String,
278
+ splitDigest: Schema.String,
279
+ basisDigest: Schema.String,
280
+ labelProtocol: BasisLabelProtocolV3,
281
+ tasks: Schema.Array(BasisTaskRecordV3),
282
+ labels: Schema.Array(DimensionScoreLabelV3)
283
+ });
284
+ export const BasisValidationClassifierBindingV3 = Schema.Struct({
285
+ candidateId: Schema.String,
286
+ basisDigest: Schema.String,
287
+ classifierConfigurationDigest: Schema.String
288
+ });
289
+ export const BasisValidationPlanV3 = Schema.Struct({
290
+ version: Schema.Literal(1),
291
+ planDigest: Schema.String,
292
+ repositoryDigest: Schema.String,
293
+ splitDigest: Schema.String,
294
+ classifierBindings: Schema.Array(BasisValidationClassifierBindingV3),
295
+ candidateIds: Schema.Array(Schema.String),
296
+ datasetDigests: Schema.Array(Schema.String),
297
+ repetitions: NonNegativeInteger,
298
+ plannedPrimaryCalls: NonNegativeInteger,
299
+ maximumAttempts: NonNegativeInteger,
300
+ requiredTotalInputTokens: NonNegativeInteger,
301
+ requiredTotalOutputTokens: NonNegativeInteger,
302
+ maximumPricedExposureUsd: Schema.optionalKey(NonNegativeFinite),
303
+ acknowledgeUnpricedExposure: Schema.Boolean
304
+ });
305
+ export const BasisValidationResultV3 = Schema.Struct({
306
+ version: Schema.Literal(1),
307
+ candidateId: Schema.String,
308
+ basisDigest: Schema.String,
309
+ validationDatasetDigest: Schema.String,
310
+ classifierConfigurationDigest: Schema.String,
311
+ predictions: Schema.Array(DimensionScorePredictionV3),
312
+ caseCount: NonNegativeInteger,
313
+ skippedInvalidCount: NonNegativeInteger,
314
+ activeMae: NonNegativeFinite,
315
+ activeF1: NonNegativeFinite,
316
+ topDimensionAgreement: NonNegativeFinite,
317
+ unknownMae: NonNegativeFinite,
318
+ unknownBrier: NonNegativeFinite,
319
+ unknownAccuracy: NonNegativeFinite,
320
+ falseUnknownRate: NonNegativeFinite,
321
+ missedUnknownRate: NonNegativeFinite,
322
+ referenceUnknownRate: NonNegativeFinite,
323
+ averageActiveDimensionCount: NonNegativeFinite,
324
+ selectionScore: NonNegativeFinite,
325
+ provisional: Schema.Boolean
326
+ });
327
+ export const BasisValidationJobCheckpointV3 = Schema.Struct({
328
+ version: Schema.Literal(1),
329
+ validationPlanDigest: Schema.String,
330
+ candidateId: Schema.String,
331
+ basisDigest: Schema.String,
332
+ validationDatasetDigest: Schema.String,
333
+ caseId: Schema.String,
334
+ repetition: NonNegativeInteger,
335
+ classifierConfigurationDigest: Schema.String,
336
+ status: Schema.Literals(["completed", "failed"]),
337
+ prediction: Schema.optionalKey(DimensionScorePredictionV3),
338
+ error: Schema.optionalKey(Schema.Struct({
339
+ name: Schema.String,
340
+ message: Schema.String,
341
+ code: Schema.optionalKey(Schema.String),
342
+ attemptCount: Schema.optionalKey(NonNegativeInteger)
343
+ })),
344
+ attemptCount: NonNegativeInteger,
345
+ callIds: Schema.Array(Schema.String),
346
+ knownInputTokens: NonNegativeInteger,
347
+ knownOutputTokens: NonNegativeInteger,
348
+ knownCostUsd: Schema.optionalKey(NonNegativeFinite),
349
+ unpricedCalls: NonNegativeInteger,
350
+ unknownUsageCalls: NonNegativeInteger
351
+ });
352
+ export const BasisSelectionReportV3 = Schema.Struct({
353
+ version: Schema.Literal(1),
354
+ selectionReportDigest: Schema.String,
355
+ repositoryDigest: Schema.String,
356
+ validationPlanDigest: Schema.String,
357
+ objectiveVersion: Schema.Literal("basis-selection-v1"),
358
+ rankedCandidateIds: Schema.Array(Schema.String),
359
+ paretoCandidateIds: Schema.Array(Schema.String),
360
+ selectedCandidateId: Schema.String,
361
+ provisional: Schema.Boolean
362
+ });
363
+ export const BasisGenerationArtifactsV3 = Schema.Struct({
364
+ version: Schema.Literal(1),
365
+ sourceInventory: Schema.Array(Schema.String),
366
+ snapshot: FrozenRepositorySnapshotV3,
367
+ split: BasisTaskSplitV3,
368
+ generationPlan: BasisGenerationPlanV3,
369
+ generationLedger: BasisGenerationLedgerV3
370
+ });
371
+ export const BasisCandidatesArtifactsV3 = Schema.Struct({
372
+ version: Schema.Literal(1),
373
+ generationPlanDigest: Schema.String,
374
+ generationLedger: BasisGenerationLedgerV3,
375
+ candidates: Schema.Array(BasisCandidateRecordV3),
376
+ structureReports: Schema.Array(BasisStructureReportV3)
377
+ });
378
+ export const BasisValidationArtifactsV3 = Schema.Struct({
379
+ version: Schema.Literal(1),
380
+ generationPlanDigest: Schema.String,
381
+ datasets: Schema.Array(BasisCandidateDatasetV3),
382
+ validationPlan: BasisValidationPlanV3
383
+ });
384
+ export const BasisValidationResultsArtifactsV3 = Schema.Struct({
385
+ version: Schema.Literal(1),
386
+ validationPlanDigest: Schema.String,
387
+ validationResults: Schema.Array(BasisValidationResultV3),
388
+ selection: BasisSelectionReportV3
389
+ });
390
+ export const BasisQualificationArtifactsV3 = Schema.Struct({
391
+ version: Schema.Literal(1),
392
+ validationPlanDigest: Schema.String,
393
+ validationResults: Schema.Array(BasisValidationResultV3),
394
+ selection: BasisSelectionReportV3,
395
+ approval: RoutingBasisApprovalV3,
396
+ approvalDigest: Schema.String
397
+ });
398
+ export const BasisEvaluationProjectionV3 = Schema.Struct({
399
+ version: Schema.Literal(1),
400
+ basisDigest: Schema.String,
401
+ projectedBasisDigest: Schema.String,
402
+ dimensions: Schema.Array(WorkloadDimension)
403
+ });
404
+ export const BasisRepairSummaryV3 = Schema.Struct({
405
+ version: Schema.Literal(1),
406
+ summaryDigest: Schema.String,
407
+ sourceCandidateId: Schema.String,
408
+ sourceBasisDigest: Schema.String,
409
+ errorCategories: Schema.Array(Schema.Struct({
410
+ code: Schema.String,
411
+ dimensionIds: Schema.Array(Schema.String),
412
+ summary: Schema.String
413
+ }))
414
+ });
415
+ export const BasisRepairPlanV3 = Schema.Struct({
416
+ version: Schema.Literal(1),
417
+ planDigest: Schema.String,
418
+ repositoryDigest: Schema.String,
419
+ sourceCandidateId: Schema.String,
420
+ sourceBasisDigest: Schema.String,
421
+ summaryDigest: Schema.String,
422
+ authorModel: Schema.String,
423
+ plannedPrimaryCalls: Schema.Literal(1),
424
+ maximumAttempts: Schema.Literal(2),
425
+ requiredTotalInputTokens: NonNegativeInteger,
426
+ requiredTotalOutputTokens: NonNegativeInteger
427
+ });
428
+ export const BasisRepairArtifactsV3 = Schema.Struct({
429
+ version: Schema.Literal(1),
430
+ plan: BasisRepairPlanV3,
431
+ summary: BasisRepairSummaryV3,
432
+ candidate: BasisCandidateRecordV3
433
+ });
434
+ const ProjectV2Common = {
435
+ version: Schema.Literal(EVAL_PROJECT_V2_VERSION),
436
+ projectId: Schema.String,
437
+ revision: NonNegativeInteger,
438
+ createdAt: Schema.String,
439
+ updatedAt: Schema.String,
440
+ sourceInventory: Schema.Array(Schema.String),
441
+ configuration: EvalProjectConfiguration
442
+ };
443
+ const BasisGenerationReadyStateV2 = Schema.Struct({
444
+ ...ProjectV2Common,
445
+ stage: Schema.Literal("basis-generation-ready"),
446
+ snapshot: FrozenRepositorySnapshotV3,
447
+ split: BasisTaskSplitV3,
448
+ generationPlan: BasisGenerationPlanV3,
449
+ generationLedger: BasisGenerationLedgerV3
450
+ });
451
+ const BasisCandidatesReviewStateV2 = Schema.Struct({
452
+ ...ProjectV2Common,
453
+ stage: Schema.Literal("basis-candidates-review"),
454
+ snapshot: FrozenRepositorySnapshotV3,
455
+ split: BasisTaskSplitV3,
456
+ generationPlan: BasisGenerationPlanV3,
457
+ generationLedger: BasisGenerationLedgerV3,
458
+ candidates: Schema.Array(BasisCandidateRecordV3),
459
+ structureReports: Schema.Array(BasisStructureReportV3)
460
+ });
461
+ const BasisValidationReadyStateV2 = Schema.Struct({
462
+ ...ProjectV2Common,
463
+ stage: Schema.Literal("basis-validation-ready"),
464
+ snapshot: FrozenRepositorySnapshotV3,
465
+ split: BasisTaskSplitV3,
466
+ generationPlan: BasisGenerationPlanV3,
467
+ generationLedger: BasisGenerationLedgerV3,
468
+ candidates: Schema.Array(BasisCandidateRecordV3),
469
+ structureReports: Schema.Array(BasisStructureReportV3),
470
+ datasets: Schema.Array(BasisCandidateDatasetV3),
471
+ validationPlan: BasisValidationPlanV3
472
+ });
473
+ const BasisQualifiedStateV2 = Schema.Struct({
474
+ ...ProjectV2Common,
475
+ stage: Schema.Literal("basis-qualified"),
476
+ snapshot: FrozenRepositorySnapshotV3,
477
+ split: BasisTaskSplitV3,
478
+ generationPlan: BasisGenerationPlanV3,
479
+ generationLedger: BasisGenerationLedgerV3,
480
+ candidates: Schema.Array(BasisCandidateRecordV3),
481
+ structureReports: Schema.Array(BasisStructureReportV3),
482
+ datasets: Schema.Array(BasisCandidateDatasetV3),
483
+ validationPlan: BasisValidationPlanV3,
484
+ validationResults: Schema.Array(BasisValidationResultV3),
485
+ selection: BasisSelectionReportV3,
486
+ approval: RoutingBasisApprovalV3
487
+ });
488
+ const BasisValidationReviewStateV2 = Schema.Struct({
489
+ ...ProjectV2Common,
490
+ stage: Schema.Literal("basis-validation-review"),
491
+ snapshot: FrozenRepositorySnapshotV3,
492
+ split: BasisTaskSplitV3,
493
+ generationPlan: BasisGenerationPlanV3,
494
+ generationLedger: BasisGenerationLedgerV3,
495
+ candidates: Schema.Array(BasisCandidateRecordV3),
496
+ structureReports: Schema.Array(BasisStructureReportV3),
497
+ datasets: Schema.Array(BasisCandidateDatasetV3),
498
+ validationPlan: BasisValidationPlanV3,
499
+ validationResults: Schema.Array(BasisValidationResultV3),
500
+ selection: BasisSelectionReportV3
501
+ });
502
+ export const EvalProjectStateV2 = Schema.Union([
503
+ BasisGenerationReadyStateV2,
504
+ BasisCandidatesReviewStateV2,
505
+ BasisValidationReadyStateV2,
506
+ BasisValidationReviewStateV2,
507
+ BasisQualifiedStateV2
508
+ ]);
509
+ export const EvalProjectDocument = Schema.Union([
510
+ EvalProjectState,
511
+ EvalProjectStateV2
512
+ ]);
170
513
  export const EvalDimensionCase = Schema.Struct({
171
514
  id: Schema.String,
172
515
  prompt: Schema.String,
@@ -1,7 +1,9 @@
1
1
  import { Context, Effect, FileSystem, Layer, Path } from "effect";
2
2
  import { EvalProjectStoreError } from "./errors.js";
3
- import { EvalProjectState } from "./project-contracts.js";
3
+ import { type EvalProjectDocument as EvalProjectDocumentType, EvalProjectState } from "./project-contracts.js";
4
4
  export type EvalProjectStoreShape = {
5
+ readonly loadDocument: (repositoryRoot: string) => Effect.Effect<EvalProjectDocumentType | undefined, EvalProjectStoreError>;
6
+ readonly saveDocument: (repositoryRoot: string, state: EvalProjectDocumentType) => Effect.Effect<void, EvalProjectStoreError>;
5
7
  readonly load: (repositoryRoot: string) => Effect.Effect<EvalProjectState | undefined, EvalProjectStoreError>;
6
8
  readonly save: (repositoryRoot: string, state: EvalProjectState) => Effect.Effect<void, EvalProjectStoreError>;
7
9
  };
@@ -1,7 +1,7 @@
1
1
  import { writeFileAtomicEffect } from "@velum-labs/routekit-runtime/effect";
2
2
  import { Context, Effect, FileSystem, Layer, Path, Schema } from "effect";
3
3
  import { EvalProjectStoreError } from "./errors.js";
4
- import { EvalProjectState } from "./project-contracts.js";
4
+ import { EvalProjectDocument } from "./project-contracts.js";
5
5
  const PROJECT_FILE = "project.json";
6
6
  export class EvalProjectStore extends Context.Service()("@velum-labs/routekit-eval-setup/EvalProjectStore") {
7
7
  }
@@ -15,39 +15,45 @@ export const makeFileEvalProjectStore = Effect.gen(function* () {
15
15
  const fs = yield* FileSystem.FileSystem;
16
16
  const paths = yield* Path.Path;
17
17
  const projectPath = (root) => paths.join(paths.resolve(root), ".routekit", "evals", PROJECT_FILE);
18
+ const loadDocument = (repositoryRoot) => Effect.gen(function* () {
19
+ const root = yield* fs
20
+ .realPath(repositoryRoot)
21
+ .pipe(Effect.mapError((cause) => storeFailure("resolving", repositoryRoot, cause)));
22
+ const target = projectPath(root);
23
+ const exists = yield* fs
24
+ .exists(target)
25
+ .pipe(Effect.mapError((cause) => storeFailure("checking", target, cause)));
26
+ if (!exists)
27
+ return undefined;
28
+ const encoded = yield* fs
29
+ .readFileString(target)
30
+ .pipe(Effect.mapError((cause) => storeFailure("reading", target, cause)));
31
+ const json = yield* Effect.try({
32
+ try: () => JSON.parse(encoded),
33
+ catch: (cause) => storeFailure("parsing", target, cause)
34
+ });
35
+ return yield* Schema.decodeUnknownEffect(EvalProjectDocument)(json).pipe(Effect.mapError((cause) => storeFailure("decoding", target, cause)));
36
+ });
37
+ const saveDocument = (repositoryRoot, state) => Effect.gen(function* () {
38
+ const root = yield* fs
39
+ .realPath(repositoryRoot)
40
+ .pipe(Effect.mapError((cause) => storeFailure("resolving", repositoryRoot, cause)));
41
+ const target = projectPath(root);
42
+ const directory = paths.dirname(target);
43
+ yield* fs
44
+ .makeDirectory(directory, { recursive: true, mode: 0o700 })
45
+ .pipe(Effect.mapError((cause) => storeFailure("creating", directory, cause)));
46
+ yield* writeFileAtomicEffect(target, `${JSON.stringify(state, null, 2)}\n`, {
47
+ mode: 0o600
48
+ }).pipe(Effect.mapError((cause) => storeFailure("committing", target, cause)), Effect.provideService(FileSystem.FileSystem, fs), Effect.provideService(Path.Path, paths));
49
+ });
18
50
  return EvalProjectStore.of({
19
- load: (repositoryRoot) => Effect.gen(function* () {
20
- const root = yield* fs
21
- .realPath(repositoryRoot)
22
- .pipe(Effect.mapError((cause) => storeFailure("resolving", repositoryRoot, cause)));
23
- const target = projectPath(root);
24
- const exists = yield* fs
25
- .exists(target)
26
- .pipe(Effect.mapError((cause) => storeFailure("checking", target, cause)));
27
- if (!exists)
28
- return undefined;
29
- const encoded = yield* fs
30
- .readFileString(target)
31
- .pipe(Effect.mapError((cause) => storeFailure("reading", target, cause)));
32
- const json = yield* Effect.try({
33
- try: () => JSON.parse(encoded),
34
- catch: (cause) => storeFailure("parsing", target, cause)
35
- });
36
- return yield* Schema.decodeUnknownEffect(EvalProjectState)(json).pipe(Effect.mapError((cause) => storeFailure("decoding", target, cause)));
37
- }),
38
- save: (repositoryRoot, state) => Effect.gen(function* () {
39
- const root = yield* fs
40
- .realPath(repositoryRoot)
41
- .pipe(Effect.mapError((cause) => storeFailure("resolving", repositoryRoot, cause)));
42
- const target = projectPath(root);
43
- const directory = paths.dirname(target);
44
- yield* fs
45
- .makeDirectory(directory, { recursive: true, mode: 0o700 })
46
- .pipe(Effect.mapError((cause) => storeFailure("creating", directory, cause)));
47
- yield* writeFileAtomicEffect(target, `${JSON.stringify(state, null, 2)}\n`, {
48
- mode: 0o600
49
- }).pipe(Effect.mapError((cause) => storeFailure("committing", target, cause)), Effect.provideService(FileSystem.FileSystem, fs), Effect.provideService(Path.Path, paths));
50
- })
51
+ loadDocument,
52
+ saveDocument,
53
+ load: (repositoryRoot) => loadDocument(repositoryRoot).pipe(Effect.flatMap((document) => document === undefined || document.version === 1
54
+ ? Effect.succeed(document)
55
+ : Effect.fail(storeFailure("decoding", projectPath(repositoryRoot), new Error("Classification V3 project requires the V2 workflow API"))))),
56
+ save: (repositoryRoot, state) => saveDocument(repositoryRoot, state)
51
57
  });
52
58
  });
53
59
  export const EvalProjectStoreLive = Layer.effect(EvalProjectStore, makeFileEvalProjectStore);
@@ -27,6 +27,6 @@ export type EvalProjectWorkflowShape = {
27
27
  declare const EvalProjectWorkflow_base: Context.ServiceClass<EvalProjectWorkflow, "@velum-labs/routekit-eval-setup/EvalProjectWorkflow", EvalProjectWorkflowShape>;
28
28
  export declare class EvalProjectWorkflow extends EvalProjectWorkflow_base {
29
29
  }
30
- export declare const makeEvalProjectWorkflow: Effect.Effect<EvalProjectWorkflowShape, never, EvalRepositoryInspector | Path.Path | EvalProjectArtifacts | EvalProjectStore>;
31
- export declare const EvalProjectWorkflowLive: Layer.Layer<EvalProjectWorkflow, never, EvalRepositoryInspector | Path.Path | EvalProjectArtifacts | EvalProjectStore>;
30
+ export declare const makeEvalProjectWorkflow: Effect.Effect<EvalProjectWorkflowShape, never, EvalProjectArtifacts | Path.Path | EvalProjectStore | EvalRepositoryInspector>;
31
+ export declare const EvalProjectWorkflowLive: Layer.Layer<EvalProjectWorkflow, never, EvalProjectArtifacts | Path.Path | EvalProjectStore | EvalRepositoryInspector>;
32
32
  export {};