@peasant-labs/schema 0.1.0-rc10

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 (37) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +66 -0
  3. package/dist/fixtures/quality.d.ts +81 -0
  4. package/dist/fixtures/quality.js +36 -0
  5. package/dist/fixtures/timeline.d.ts +53 -0
  6. package/dist/fixtures/timeline.js +2 -0
  7. package/dist/fixtures.d.ts +2 -0
  8. package/dist/fixtures.js +2 -0
  9. package/dist/index.d.ts +8 -0
  10. package/dist/index.js +36 -0
  11. package/dist/internal/generated/contract/zod.gen.d.ts +3441 -0
  12. package/dist/internal/generated/contract/zod.gen.js +1623 -0
  13. package/dist/internal/generated/enums.gen.d.ts +406 -0
  14. package/dist/internal/generated/enums.gen.js +445 -0
  15. package/dist/internal/generated/local-api.d.ts +1047 -0
  16. package/dist/internal/generated/local-api.js +1 -0
  17. package/dist/internal/generated/public-contract.gen.d.ts +2 -0
  18. package/dist/internal/generated/public-contract.gen.js +2 -0
  19. package/dist/internal/generated/quality-fixtures.gen.d.ts +2 -0
  20. package/dist/internal/generated/quality-fixtures.gen.js +367 -0
  21. package/dist/internal/generated/testcase.gen.d.ts +17 -0
  22. package/dist/internal/generated/testcase.gen.js +20 -0
  23. package/dist/internal/generated/timeline-fixtures.gen.d.ts +2 -0
  24. package/dist/internal/generated/timeline-fixtures.gen.js +1554 -0
  25. package/dist/internal/generated/versions.gen.d.ts +4 -0
  26. package/dist/internal/generated/versions.gen.js +5 -0
  27. package/dist/internal/generated/village-api.d.ts +652 -0
  28. package/dist/internal/generated/village-api.js +1 -0
  29. package/dist/local-api.d.ts +4 -0
  30. package/dist/local-api.js +1 -0
  31. package/dist/testcase.d.ts +32 -0
  32. package/dist/testcase.js +144 -0
  33. package/dist/types.d.ts +2 -0
  34. package/dist/types.js +2 -0
  35. package/dist/village-api.d.ts +4 -0
  36. package/dist/village-api.js +1 -0
  37. package/package.json +75 -0
@@ -0,0 +1,1623 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+ import * as z from 'zod';
3
+ export const zActivityEdge = z.object({
4
+ from: z.string(),
5
+ taskCount: z.int(),
6
+ to: z.string()
7
+ });
8
+ /**
9
+ * Annotation Axis
10
+ *
11
+ * Subscription dimension for annotation channels
12
+ */
13
+ export const zAnnotationAxis = z.enum([
14
+ 'type',
15
+ 'session',
16
+ 'project'
17
+ ]);
18
+ /**
19
+ * Annotation Datatype
20
+ *
21
+ * Storage type for annotation values (maps to SQLite STRICT column type)
22
+ */
23
+ export const zAnnotationDatatype = z.enum([
24
+ 'text',
25
+ 'integer',
26
+ 'real',
27
+ 'boolean'
28
+ ]);
29
+ export const zAnnotationEntryTarget = z.object({
30
+ endIndex: z.int(),
31
+ entryIndex: z.int(),
32
+ sessionId: z.string().min(1)
33
+ }).superRefine((value, context) => {
34
+ if (value.sessionId === "")
35
+ context.addIssue({ code: "custom", message: "entry targets require a non-empty sessionId" });
36
+ if (value.endIndex <= value.entryIndex)
37
+ context.addIssue({ code: "custom", message: "entry targets require endIndex greater than entryIndex" });
38
+ });
39
+ export const zAnnotationManifestResponse = z.object({
40
+ digest: z.string(),
41
+ hashes: z.array(z.string())
42
+ });
43
+ /**
44
+ * Annotation Push Status
45
+ *
46
+ * Per-item annotation push outcome
47
+ */
48
+ export const zAnnotationPushStatus = z.enum([
49
+ 'created',
50
+ 'updated',
51
+ 'skipped',
52
+ 'error'
53
+ ]);
54
+ export const zAnnotationPushResult = z.object({
55
+ contentHash: z.string().optional(),
56
+ error: z.string().optional(),
57
+ status: zAnnotationPushStatus
58
+ });
59
+ export const zAnnotationPushResponse = z.object({
60
+ created: z.int(),
61
+ errors: z.int(),
62
+ results: z.array(zAnnotationPushResult).optional(),
63
+ skipped: z.int(),
64
+ updated: z.int()
65
+ });
66
+ /**
67
+ * Annotation Status
68
+ *
69
+ * ISO 11179 lifecycle state of an annotation type
70
+ */
71
+ export const zAnnotationStatus = z.enum([
72
+ 'proposed',
73
+ 'active',
74
+ 'deprecated',
75
+ 'retired'
76
+ ]);
77
+ /**
78
+ * Annotator Kind
79
+ *
80
+ * Type of entity that produced an annotation: human, agent (AI model), or rule (automated classifier)
81
+ */
82
+ export const zAnnotatorKind = z.enum([
83
+ 'human',
84
+ 'agent',
85
+ 'rule'
86
+ ]);
87
+ export const zAnnotatorSummary = z.object({
88
+ description: z.string().optional(),
89
+ displayName: z.string(),
90
+ id: z.string(),
91
+ kind: zAnnotatorKind,
92
+ modelId: z.string().nullish(),
93
+ name: z.string(),
94
+ providerKey: z.string().nullish(),
95
+ status: z.string()
96
+ });
97
+ /**
98
+ * Association Conclusion
99
+ *
100
+ * Producer-supplied conclusion for a session-to-commit association: confirmed or candidate
101
+ */
102
+ export const zAssociationConclusion = z.enum(['confirmed', 'candidate']);
103
+ /**
104
+ * Association Evidence Kind
105
+ *
106
+ * Atomic observation supporting a session-to-commit association
107
+ */
108
+ export const zAssociationEvidenceKind = z.enum([
109
+ 'recorded_commit',
110
+ 'touched_file',
111
+ 'branch_membership',
112
+ 'time_window'
113
+ ]);
114
+ export const zAssociationEvidenceObservation = z.object({
115
+ branchName: z.string().nullish(),
116
+ kind: zAssociationEvidenceKind,
117
+ recordedCommitHash: z.string().nullish(),
118
+ touchedFilePath: z.string().nullish(),
119
+ windowEndMs: z.int().nullish(),
120
+ windowStartMs: z.int().nullish()
121
+ }).superRefine((value, context) => {
122
+ const isAbsent = (detail) => detail === undefined || detail === null;
123
+ const isGoWhitespace = (codePoint) => (codePoint >= 0x0009 && codePoint <= 0x000D)
124
+ || codePoint === 0x0020
125
+ || codePoint === 0x0085
126
+ || codePoint === 0x00A0
127
+ || codePoint === 0x1680
128
+ || (codePoint >= 0x2000 && codePoint <= 0x200A)
129
+ || codePoint === 0x2028
130
+ || codePoint === 0x2029
131
+ || codePoint === 0x202F
132
+ || codePoint === 0x205F
133
+ || codePoint === 0x3000;
134
+ const hasNonEmptyString = (detail) => {
135
+ if (typeof detail !== "string")
136
+ return false;
137
+ for (const character of detail) {
138
+ const codePoint = character.codePointAt(0);
139
+ if (codePoint !== undefined && !isGoWhitespace(codePoint))
140
+ return true;
141
+ }
142
+ return false;
143
+ };
144
+ const hasValidTouchedFilePath = (detail) => typeof detail === "string"
145
+ && detail !== ""
146
+ && !detail.startsWith("/")
147
+ && !detail.startsWith("\\")
148
+ && !detail.includes("\\")
149
+ && !/^[A-Za-z]:\//.test(detail)
150
+ && !detail.split("/").some((segment) => segment === "" || segment === "." || segment === "..");
151
+ const addIssue = (message) => context.addIssue({ code: "custom", message });
152
+ switch (value.kind) {
153
+ case "recorded_commit":
154
+ if (!hasNonEmptyString(value.recordedCommitHash))
155
+ addIssue("recorded_commit evidence requires a non-empty recordedCommitHash");
156
+ if (!isAbsent(value.touchedFilePath) || !isAbsent(value.branchName) || !isAbsent(value.windowStartMs) || !isAbsent(value.windowEndMs))
157
+ addIssue("recorded_commit evidence must not populate another detail arm");
158
+ return;
159
+ case "touched_file":
160
+ if (!hasValidTouchedFilePath(value.touchedFilePath))
161
+ addIssue("touched_file evidence requires a non-empty repository-relative touchedFilePath");
162
+ if (!isAbsent(value.recordedCommitHash) || !isAbsent(value.branchName) || !isAbsent(value.windowStartMs) || !isAbsent(value.windowEndMs))
163
+ addIssue("touched_file evidence must not populate another detail arm");
164
+ return;
165
+ case "branch_membership":
166
+ if (!hasNonEmptyString(value.branchName))
167
+ addIssue("branch_membership evidence requires a non-empty branchName");
168
+ if (!isAbsent(value.recordedCommitHash) || !isAbsent(value.touchedFilePath) || !isAbsent(value.windowStartMs) || !isAbsent(value.windowEndMs))
169
+ addIssue("branch_membership evidence must not populate another detail arm");
170
+ return;
171
+ case "time_window":
172
+ if (value.windowStartMs === undefined || value.windowStartMs === null || value.windowEndMs === undefined || value.windowEndMs === null) {
173
+ addIssue("time_window evidence requires windowStartMs and windowEndMs");
174
+ }
175
+ else if (value.windowStartMs > value.windowEndMs) {
176
+ addIssue("time_window evidence requires windowStartMs less than or equal to windowEndMs");
177
+ }
178
+ if (!isAbsent(value.recordedCommitHash) || !isAbsent(value.touchedFilePath) || !isAbsent(value.branchName))
179
+ addIssue("time_window evidence must not populate another detail arm");
180
+ return;
181
+ }
182
+ });
183
+ /**
184
+ * Association ID
185
+ *
186
+ * Opaque durable Peasant identifier for one session-to-commit association
187
+ */
188
+ export const zAssociationID = z.string().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/);
189
+ export const zBatchCreateAnnotationsErrorResponse = z.object({
190
+ error: z.string(),
191
+ failingIndex: z.int()
192
+ });
193
+ export const zBatchCreateAnnotationsResponse = z.object({
194
+ ids: z.array(z.string()).nullable()
195
+ });
196
+ /**
197
+ * Built-in Command
198
+ *
199
+ * Claude Code built-in slash command name without the leading slash
200
+ */
201
+ export const zBuiltinCommand = z.enum([
202
+ 'exit',
203
+ 'compact',
204
+ 'clear',
205
+ 'new',
206
+ 'model',
207
+ 'usage',
208
+ 'cost',
209
+ 'context',
210
+ 'plugin',
211
+ 'permissions',
212
+ 'login',
213
+ 'resume',
214
+ 'plan',
215
+ 'fast',
216
+ 'voice',
217
+ 'todos',
218
+ 'reload-plugins',
219
+ 'sandbox',
220
+ 'config',
221
+ 'statusline',
222
+ 'upgrade',
223
+ 'extra-usage',
224
+ 'rate-limit-options',
225
+ 'privacy-settings',
226
+ 'help',
227
+ 'commands'
228
+ ]);
229
+ export const zCLILoginQuery = z.object({
230
+ port: z.int(),
231
+ state: z.string()
232
+ });
233
+ /**
234
+ * Change Binding
235
+ *
236
+ * Strength of the evidence connecting a recorded session to a code change
237
+ */
238
+ export const zChangeBinding = z.enum(['bound', 'candidate']);
239
+ export const zChangeSummary = z.object({
240
+ aheadCount: z.int(),
241
+ baseHash: z.string().optional(),
242
+ behindCount: z.int(),
243
+ branch: z.string(),
244
+ filesChanged: z.int(),
245
+ lastWorkMs: z.int().nullish(),
246
+ mergeCommitHash: z.string().optional(),
247
+ merged: z.boolean(),
248
+ mergedAtMs: z.int().nullish(),
249
+ newEdges: z.int(),
250
+ removedEdges: z.int(),
251
+ reverted: z.boolean().optional(),
252
+ sessionCount: z.int(),
253
+ taskCount: z.int(),
254
+ tipCommitMs: z.int().nullish(),
255
+ violations: z.int()
256
+ });
257
+ /**
258
+ * Channel Topic
259
+ *
260
+ * Subscribable WebSocket data stream
261
+ */
262
+ export const zChannelTopic = z.enum([
263
+ 'dashboard',
264
+ 'sessions',
265
+ 'session_detail',
266
+ 'trends',
267
+ 'quality',
268
+ 'annotations',
269
+ 'project_familiarity'
270
+ ]);
271
+ export const zChannelSubscription = z.object({
272
+ axis: zAnnotationAxis.optional(),
273
+ id: z.string().optional(),
274
+ topic: zChannelTopic
275
+ });
276
+ export const zChildSessionRef = z.object({
277
+ id: z.string(),
278
+ project: z.string().optional(),
279
+ startTime: z.iso.datetime()
280
+ });
281
+ export const zCommitInfo = z.object({
282
+ authorEmail: z.string(),
283
+ authorName: z.string(),
284
+ authorTime: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }),
285
+ commitTime: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }),
286
+ hash: z.string(),
287
+ message: z.string()
288
+ });
289
+ /**
290
+ * Confidence
291
+ *
292
+ * Strength of evidence behind a derived relationship: high, medium, or low
293
+ */
294
+ export const zConfidence = z.enum([
295
+ 'high',
296
+ 'medium',
297
+ 'low'
298
+ ]);
299
+ /**
300
+ * Content Kind
301
+ *
302
+ * Payload kind carried by a transcript content envelope
303
+ */
304
+ export const zContentKind = z.enum(['session_detail']);
305
+ export const zContractVersion = z.string().nullable();
306
+ export const zCreateAnnotationRequest = z.object({
307
+ annotatorName: z.string().optional(),
308
+ confidence: z.number().nullish(),
309
+ isPrimary: z.boolean(),
310
+ reason: z.string().nullish(),
311
+ sessionId: z.string(),
312
+ targetAnnotationId: z.string().nullish(),
313
+ targetEntryEndIndex: z.int().nullish(),
314
+ targetEntryIndex: z.int().nullish(),
315
+ typeId: z.string(),
316
+ value: z.string()
317
+ });
318
+ export const zBatchCreateAnnotationsRequest = z.object({
319
+ annotations: z.array(zCreateAnnotationRequest).nullable()
320
+ });
321
+ export const zCreateAnnotationResponse = z.object({
322
+ id: z.string()
323
+ });
324
+ export const zDashboardPayload = z.object({
325
+ acceptanceRate: z.number(),
326
+ avgDurationMins: z.number(),
327
+ avgTurnsPerSession: z.number(),
328
+ harnessBreakdown: z.record(z.string(), z.int()).nullable(),
329
+ totalSessions: z.int(),
330
+ totalTokens: z.int()
331
+ });
332
+ export const zDayStats = z.object({
333
+ date: z.string(),
334
+ sessions: z.int(),
335
+ tokens: z.int()
336
+ });
337
+ /**
338
+ * Decay Level
339
+ *
340
+ * Recency band for project file familiarity
341
+ */
342
+ export const zDecayLevel = z.enum([
343
+ 'fresh',
344
+ 'fading',
345
+ 'stale',
346
+ 'unexplored'
347
+ ]);
348
+ export const zDiagnosticEntry = z.object({
349
+ errorType: z.string(),
350
+ location: z.string(),
351
+ message: z.string(),
352
+ remediation: z.string()
353
+ });
354
+ export const zDiagnosticsInfo = z.object({
355
+ partial: z.boolean().nullish(),
356
+ warnings: z.array(zDiagnosticEntry).nullable()
357
+ });
358
+ /**
359
+ * Diff Line Kind
360
+ *
361
+ * Unified-diff line kind: context, addition, or deletion
362
+ */
363
+ export const zDiffLineKind = z.enum([
364
+ 'context',
365
+ 'add',
366
+ 'del'
367
+ ]);
368
+ export const zDiffLine = z.object({
369
+ kind: zDiffLineKind,
370
+ text: z.string()
371
+ });
372
+ export const zDiffHunk = z.object({
373
+ header: z.string().optional(),
374
+ lines: z.array(zDiffLine).nullable(),
375
+ newLines: z.int(),
376
+ newStart: z.int(),
377
+ oldLines: z.int(),
378
+ oldStart: z.int(),
379
+ sessionId: z.string().optional(),
380
+ sessionTitle: z.string().optional()
381
+ });
382
+ /**
383
+ * Edge Violation Kind
384
+ *
385
+ * Structural violation detected on a map edge
386
+ */
387
+ export const zEdgeViolationKind = z.enum(['cycle', 'wrong_way']);
388
+ export const zEdgeViolation = z.object({
389
+ from: z.string(),
390
+ kind: zEdgeViolationKind,
391
+ to: z.string()
392
+ });
393
+ /**
394
+ * Entry Type
395
+ *
396
+ * Classification of a single entry within an agent session transcript
397
+ */
398
+ export const zEntryType = z.enum([
399
+ 'text',
400
+ 'tool_use',
401
+ 'tool_result',
402
+ 'thinking',
403
+ 'system',
404
+ 'error',
405
+ 'result'
406
+ ]);
407
+ export const zExchangeCodeRequest = z.object({
408
+ code: z.string(),
409
+ state: z.string()
410
+ });
411
+ export const zExchangeCodeResponse = z.object({
412
+ api_key: z.string(),
413
+ key_id: z.string(),
414
+ user_id: z.string(),
415
+ username: z.string()
416
+ });
417
+ /**
418
+ * File Change Status
419
+ *
420
+ * Git file delta status: modified, added, deleted, or renamed
421
+ */
422
+ export const zFileChangeStatus = z.enum([
423
+ 'M',
424
+ 'A',
425
+ 'D',
426
+ 'R'
427
+ ]);
428
+ export const zChangeDiffPayload = z.object({
429
+ binary: z.boolean(),
430
+ branch: z.string(),
431
+ file: z.string(),
432
+ hunks: z.array(zDiffHunk).nullable(),
433
+ oldPath: z.string().nullish(),
434
+ status: zFileChangeStatus,
435
+ truncated: z.boolean()
436
+ });
437
+ export const zFileChange = z.object({
438
+ linesAdded: z.int(),
439
+ linesRemoved: z.int(),
440
+ oldPath: z.string().nullish(),
441
+ path: z.string(),
442
+ status: zFileChangeStatus
443
+ });
444
+ export const zFileFamiliarity = z.object({
445
+ daysSince: z.int().nullable(),
446
+ decayLevel: zDecayLevel,
447
+ depth: z.int(),
448
+ humanTurns: z.int(),
449
+ isSourceFile: z.boolean(),
450
+ lastEngagedAt: z.string().nullable(),
451
+ path: z.string(),
452
+ sessionCount: z.int(),
453
+ totalTurns: z.int()
454
+ });
455
+ export const zFrictionCluster = z.object({
456
+ count: z.int(),
457
+ file: z.string(),
458
+ kind: z.string(),
459
+ label: z.string(),
460
+ sessions: z.int()
461
+ });
462
+ /**
463
+ * Harness
464
+ *
465
+ * AI coding tool or development environment
466
+ */
467
+ export const zHarness = z.enum([
468
+ 'claude-code',
469
+ 'gemini-cli',
470
+ 'codex',
471
+ 'opencode',
472
+ 'cursor',
473
+ 'antigravity',
474
+ 'strike'
475
+ ]);
476
+ export const zHealthResponse = z.object({
477
+ status: z.string()
478
+ });
479
+ /**
480
+ * Host Slug
481
+ *
482
+ * Sanitized, filesystem-safe identifier derived from git remote; contains only [a-zA-Z0-9._<>-]
483
+ */
484
+ export const zHostSlug = z.string().regex(/^[a-zA-Z0-9._<>-]+$/);
485
+ export const zInsightClassification = z.object({
486
+ category: z.string(),
487
+ cause: z.string(),
488
+ resolution: z.string(),
489
+ severityLocus: z.string(),
490
+ severityScope: z.string()
491
+ });
492
+ /**
493
+ * Insight Kind
494
+ *
495
+ * What a SessionInsight observed: a decision, friction, an unusual rate elevation, or a retry loop
496
+ */
497
+ export const zInsightKind = z.enum([
498
+ 'decision',
499
+ 'friction',
500
+ 'unusual',
501
+ 'retry_loop'
502
+ ]);
503
+ /**
504
+ * Insight Provenance
505
+ *
506
+ * How a SessionInsight was produced: mechanical (rule-derived) or mined
507
+ */
508
+ export const zInsightProvenance = z.enum(['mechanical', 'mined']);
509
+ /**
510
+ * Interaction Type
511
+ *
512
+ * How deeply a session engaged with a project file
513
+ */
514
+ export const zInteractionType = z.enum([
515
+ 'mentioned',
516
+ 'read',
517
+ 'discussed',
518
+ 'questioned'
519
+ ]);
520
+ /**
521
+ * License
522
+ *
523
+ * Content license for a published transcript
524
+ */
525
+ export const zLicense = z.enum([
526
+ 'CC0-1.0',
527
+ 'CC-BY-4.0',
528
+ 'CC-BY-SA-4.0'
529
+ ]);
530
+ export const zMapEdge = z.object({
531
+ count: z.int(),
532
+ from: z.string(),
533
+ to: z.string()
534
+ });
535
+ /**
536
+ * Map Node Kind
537
+ *
538
+ * Path-derived map node classification
539
+ */
540
+ export const zMapNodeKind = z.enum([
541
+ 'module',
542
+ 'package',
543
+ 'file'
544
+ ]);
545
+ /**
546
+ * Message Type
547
+ *
548
+ * WebSocket message discriminator
549
+ */
550
+ export const zMessageType = z.enum([
551
+ 'subscribe',
552
+ 'unsubscribe',
553
+ 'dashboard',
554
+ 'sessions',
555
+ 'session_detail',
556
+ 'trends',
557
+ 'quality',
558
+ 'annotations',
559
+ 'project_familiarity',
560
+ 'connected',
561
+ 'error'
562
+ ]);
563
+ export const zClientMessage = z.object({
564
+ channels: z.array(zChannelSubscription).optional(),
565
+ type: zMessageType
566
+ });
567
+ export const zMockConfigResponse = z.object({
568
+ api: z.array(z.string()).optional(),
569
+ enabled: z.boolean(),
570
+ tui: z.array(z.string()).optional(),
571
+ web: z.array(z.string()).optional()
572
+ });
573
+ /**
574
+ * Model ID
575
+ *
576
+ * Model identifier (e.g. 'claude-opus-4-6', 'gemini-2.0-flash')
577
+ */
578
+ export const zModelID = z.string().min(1);
579
+ export const zModelInfo = z.object({
580
+ harness: zHarness,
581
+ hostSlug: zHostSlug.optional(),
582
+ model: zModelID,
583
+ version: z.string().optional()
584
+ });
585
+ /**
586
+ * Project Hash
587
+ *
588
+ * SHA-256 hex digest of the project's origin URL or local path
589
+ */
590
+ export const zProjectHash = z.string().regex(/^[0-9a-f]{64}$/).brand();
591
+ export const zProjectContext = z.object({
592
+ filePath: z.string().optional(),
593
+ hash: zProjectHash,
594
+ name: z.string()
595
+ });
596
+ export const zProjectResolutionPayload = z.object({
597
+ project: z.string(),
598
+ projectHash: zProjectHash
599
+ });
600
+ export const zProjectSummary = z.object({
601
+ lastWorkMs: z.int().nullish(),
602
+ openChanges: z.int(),
603
+ project: z.string(),
604
+ projectHash: zProjectHash,
605
+ recordedFiles: z.int(),
606
+ sessions: z.int(),
607
+ totalFiles: z.int()
608
+ });
609
+ export const zProjectSummariesPayload = z.object({
610
+ projects: z.array(zProjectSummary).nullable()
611
+ });
612
+ export const zProvenance = z.object({
613
+ details: z.record(z.string(), z.string()).optional(),
614
+ function: z.string().optional(),
615
+ method: z.string(),
616
+ version: z.string().optional()
617
+ });
618
+ export const zPublishResponse = z.object({
619
+ blobKey: z.string(),
620
+ blobSizeBytes: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }),
621
+ created: z.boolean(),
622
+ publishedAt: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }),
623
+ transcriptId: z.string(),
624
+ updatedAt: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })
625
+ });
626
+ export const zPublishedAssociation = z.object({
627
+ id: zAssociationID,
628
+ observedCommitHash: z.string()
629
+ });
630
+ export const zGitContext = z.object({
631
+ associations: z.array(zPublishedAssociation).optional(),
632
+ branch: z.string().nullish(),
633
+ commits: z.array(zCommitInfo).optional(),
634
+ remote: z.string().nullish(),
635
+ tracking: z.string().nullish(),
636
+ worktree: z.string().nullish()
637
+ }).superRefine((value, context) => {
638
+ if (value.associations === undefined || value.associations === null)
639
+ return;
640
+ const seenIDs = new Map();
641
+ const seenObservedHashes = new Map();
642
+ for (const [index, association] of value.associations.entries()) {
643
+ if (association.observedCommitHash.trim() === "") {
644
+ context.addIssue({ code: "custom", path: ["associations", index, "observedCommitHash"], message: "published associations require a non-empty observedCommitHash" });
645
+ }
646
+ const priorID = seenIDs.get(association.id);
647
+ if (priorID !== undefined) {
648
+ context.addIssue({ code: "custom", path: ["associations", index, "id"], message: "published association IDs must be unique within one request" });
649
+ }
650
+ else {
651
+ seenIDs.set(association.id, index);
652
+ }
653
+ const priorObservedHash = seenObservedHashes.get(association.observedCommitHash);
654
+ if (priorObservedHash !== undefined) {
655
+ context.addIssue({ code: "custom", path: ["associations", index, "observedCommitHash"], message: "published association observedCommitHash values must be unique within one request" });
656
+ }
657
+ else {
658
+ seenObservedHashes.set(association.observedCommitHash, index);
659
+ }
660
+ }
661
+ });
662
+ /**
663
+ * Read Attribution State
664
+ *
665
+ * Whether per-file read attribution is recoverable for a node's editing sessions: complete, partial, or unavailable
666
+ */
667
+ export const zReadAttributionState = z.enum([
668
+ 'complete',
669
+ 'partial',
670
+ 'unavailable'
671
+ ]);
672
+ /**
673
+ * Read State Grade
674
+ *
675
+ * Ordinal explicit read-state act: none, viewed, reviewed, or reviewed_in_detail
676
+ */
677
+ export const zReadStateGrade = z.enum([
678
+ 'none',
679
+ 'viewed',
680
+ 'reviewed',
681
+ 'reviewed_in_detail'
682
+ ]);
683
+ export const zMapNode = z.object({
684
+ agentEditedCount: z.int(),
685
+ attributedRegionCount: z.int(),
686
+ changedRegionCount: z.int(),
687
+ effortDensity: z.number(),
688
+ fileCount: z.int(),
689
+ id: z.string(),
690
+ kind: zMapNodeKind,
691
+ language: z.string().optional(),
692
+ layer: z.int(),
693
+ loc: z.int(),
694
+ name: z.string(),
695
+ order: z.int(),
696
+ parent: z.string().optional(),
697
+ readAttribution: zReadAttributionState,
698
+ readCount: z.int(),
699
+ readState: zReadStateGrade,
700
+ recordedFiles: z.int(),
701
+ reviewedRegionCount: z.int(),
702
+ totalFiles: z.int(),
703
+ touchCount: z.int()
704
+ });
705
+ export const zMapGraphPayload = z.object({
706
+ activityEdges: z.array(zActivityEdge).nullable(),
707
+ atCommit: z.string().optional(),
708
+ generatedAtMs: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }),
709
+ nodes: z.array(zMapNode).nullable(),
710
+ parsedLanguages: z.array(z.string()).nullable(),
711
+ projectHash: zProjectHash,
712
+ repoFound: z.boolean(),
713
+ repoPath: z.string().optional(),
714
+ structureEdges: z.array(zMapEdge).nullable(),
715
+ violations: z.array(zEdgeViolation).nullable()
716
+ });
717
+ export const zMapSlice = z.object({
718
+ activityEdges: z.array(zActivityEdge).nullable(),
719
+ nodes: z.array(zMapNode).nullable(),
720
+ structureEdges: z.array(zMapEdge).nullable()
721
+ });
722
+ export const zRedactionInfo = z.object({
723
+ applied: z.boolean(),
724
+ content_hash_at_redact: z.string().optional(),
725
+ level: z.string().optional(),
726
+ redacted_at_ms: z.int().nullish(),
727
+ rule_set_version: z.string().optional()
728
+ });
729
+ export const zReviewSuggestion = z.object({
730
+ daysSince: z.int(),
731
+ lastEngaged: z.string(),
732
+ path: z.string(),
733
+ suggestedPrompt: z.string()
734
+ });
735
+ /**
736
+ * Rewrite Method
737
+ *
738
+ * Mechanism the resolver used to map a ghost commit to its successor
739
+ */
740
+ export const zRewriteMethod = z.enum([
741
+ 'hash',
742
+ 'patch_id',
743
+ 'author_identity',
744
+ 'message_embedded',
745
+ 'temporal',
746
+ 'none'
747
+ ]);
748
+ /**
749
+ * Rewrite Resolution
750
+ *
751
+ * Whether a ledger-observed commit hash is live, was rewritten, or could not be resolved
752
+ */
753
+ export const zRewriteResolution = z.enum([
754
+ 'live',
755
+ 'rewritten',
756
+ 'unresolved'
757
+ ]);
758
+ /**
759
+ * Role
760
+ *
761
+ * Sender role of a message turn
762
+ */
763
+ export const zRole = z.enum([
764
+ 'user',
765
+ 'assistant',
766
+ 'tool',
767
+ 'system'
768
+ ]);
769
+ /**
770
+ * Scale Kind
771
+ *
772
+ * Stevens measurement level: nominal (categories without order), ordinal (ordered categories), continuous (numeric range)
773
+ */
774
+ export const zScaleKind = z.enum([
775
+ 'nominal',
776
+ 'ordinal',
777
+ 'continuous'
778
+ ]);
779
+ export const zSchemaVersionResponse = z.object({
780
+ annotationSchemaVersion: z.string(),
781
+ minPullContractVersion: z.string().optional(),
782
+ minPushContractVersion: z.string(),
783
+ pullContractVersion: z.string().optional(),
784
+ pushContractVersion: z.string(),
785
+ supportedTargetKinds: z.array(z.string()).nullable(),
786
+ supportedTypeIds: z.array(z.string()).nullable()
787
+ });
788
+ export const zSearchResult = z.object({
789
+ entryIndex: z.int(),
790
+ project: z.string(),
791
+ projectHash: zProjectHash.optional(),
792
+ role: z.string(),
793
+ score: z.number(),
794
+ sessionId: z.string(),
795
+ snippet: z.string()
796
+ });
797
+ export const zSearchPayload = z.object({
798
+ query: z.string(),
799
+ results: z.array(zSearchResult).nullable()
800
+ });
801
+ export const zServerMessage = z.object({
802
+ axis: zAnnotationAxis.optional(),
803
+ data: z.unknown().optional(),
804
+ id: z.string().optional(),
805
+ message: z.string().optional(),
806
+ topic: zChannelTopic.optional(),
807
+ type: zMessageType,
808
+ version: z.string().optional()
809
+ });
810
+ /**
811
+ * Session ID
812
+ *
813
+ * Unique session identifier (UUID, agent-{hex}, ses_{id}, sess_{id} (ACP), msg_{id}, or a Strike session ID)
814
+ */
815
+ export const zSessionID = z.string().regex(/^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|agent-[a-f0-9]+|sess?_[a-zA-Z0-9]+|msg_[a-zA-Z0-9]+|[0-9]{8}T[0-9]{6}\.[0-9]{9}Z-[A-Z2-7]{26}|[A-Z2-7]{26})$/);
816
+ export const zInsightEvidence = z.object({
817
+ commitHash: z.string().optional(),
818
+ entryIndex: z.int().nullish(),
819
+ file: z.string().optional(),
820
+ sessionId: zSessionID
821
+ });
822
+ export const zSessionAssociation = z.object({
823
+ conclusion: zAssociationConclusion,
824
+ confidence: zConfidence,
825
+ evidence: z.array(zAssociationEvidenceObservation).min(1),
826
+ id: zAssociationID,
827
+ sessionId: z.string().min(1)
828
+ }).superRefine((value, context) => {
829
+ const kindOrder = ["recorded_commit", "touched_file", "branch_membership", "time_window"];
830
+ const compareStrings = (left, right) => {
831
+ const leftBytes = new TextEncoder().encode(left);
832
+ const rightBytes = new TextEncoder().encode(right);
833
+ const sharedLength = Math.min(leftBytes.length, rightBytes.length);
834
+ for (let index = 0; index < sharedLength; index += 1) {
835
+ const leftByte = leftBytes[index];
836
+ const rightByte = rightBytes[index];
837
+ if (leftByte < rightByte)
838
+ return -1;
839
+ if (leftByte > rightByte)
840
+ return 1;
841
+ }
842
+ return compareNumbers(leftBytes.length, rightBytes.length);
843
+ };
844
+ const compareNumbers = (left, right) => left < right ? -1 : left > right ? 1 : 0;
845
+ const compareObservations = (left, right) => {
846
+ const leftKindOrder = kindOrder.indexOf(left.kind);
847
+ const rightKindOrder = kindOrder.indexOf(right.kind);
848
+ if (leftKindOrder !== rightKindOrder)
849
+ return compareNumbers(leftKindOrder, rightKindOrder);
850
+ switch (left.kind) {
851
+ case "recorded_commit": return compareStrings(typeof left.recordedCommitHash === "string" ? left.recordedCommitHash : "", typeof right.recordedCommitHash === "string" ? right.recordedCommitHash : "");
852
+ case "touched_file": return compareStrings(typeof left.touchedFilePath === "string" ? left.touchedFilePath : "", typeof right.touchedFilePath === "string" ? right.touchedFilePath : "");
853
+ case "branch_membership": return compareStrings(typeof left.branchName === "string" ? left.branchName : "", typeof right.branchName === "string" ? right.branchName : "");
854
+ case "time_window": {
855
+ const startOrder = compareNumbers(left.windowStartMs ?? 0, right.windowStartMs ?? 0);
856
+ return startOrder === 0 ? compareNumbers(left.windowEndMs ?? 0, right.windowEndMs ?? 0) : startOrder;
857
+ }
858
+ }
859
+ return 0;
860
+ };
861
+ for (let index = 1; index < value.evidence.length; index += 1) {
862
+ const previous = value.evidence[index - 1];
863
+ const current = value.evidence[index];
864
+ if (previous === undefined || current === undefined)
865
+ continue;
866
+ if (compareObservations(previous, current) >= 0) {
867
+ context.addIssue({ code: "custom", message: "association evidence must be duplicate-free and in canonical kind/detail order" });
868
+ }
869
+ }
870
+ });
871
+ export const zCommitRef = z.object({
872
+ associations: z.array(zSessionAssociation),
873
+ hasSession: z.boolean(),
874
+ hash: z.string(),
875
+ sessionIds: z.array(zSessionID),
876
+ subject: z.string(),
877
+ timeMs: z.int().nullish()
878
+ });
879
+ export const zRewrittenCommit = z.object({
880
+ associations: z.array(zSessionAssociation),
881
+ authorTimeMs: z.int().nullish(),
882
+ confidence: zConfidence,
883
+ ghostHash: z.string(),
884
+ method: zRewriteMethod,
885
+ resolution: zRewriteResolution,
886
+ sessionIds: z.array(zSessionID),
887
+ subject: z.string(),
888
+ successorHash: z.string().nullish()
889
+ });
890
+ export const zSessionIdentity = z.object({
891
+ parentUuid: zSessionID.nullish(),
892
+ schemaVersion: z.int(),
893
+ sessionId: zSessionID
894
+ });
895
+ export const zSessionInsight = z.object({
896
+ classification: zInsightClassification.nullish(),
897
+ confidence: zConfidence,
898
+ evidence: z.array(zInsightEvidence),
899
+ kind: zInsightKind,
900
+ provenance: zInsightProvenance,
901
+ subjects: z.array(z.string()),
902
+ summary: z.string().optional(),
903
+ title: z.string()
904
+ });
905
+ /**
906
+ * Session Outcome
907
+ *
908
+ * Resolution status of the session
909
+ */
910
+ export const zSessionOutcome = z.enum([
911
+ 'resolved',
912
+ 'partial',
913
+ 'failed'
914
+ ]);
915
+ export const zQualityMetrics = z.object({
916
+ computeVersion: z.int().nullish(),
917
+ computedAt: z.int().nullish(),
918
+ costCacheReadUsd: z.number().nullish(),
919
+ costCacheWriteUsd: z.number().nullish(),
920
+ costInputUsd: z.number().nullish(),
921
+ costModelId: z.string().nullish(),
922
+ costOutputUsd: z.number().nullish(),
923
+ costReasoningUsd: z.number().nullish(),
924
+ costTotalUsd: z.number().nullish(),
925
+ discoveryTurns: z.int().nullish(),
926
+ durationMinutes: z.number().nullish(),
927
+ explorationRatio: z.number().nullish(),
928
+ filesTouched: z.int().nullish(),
929
+ inputTokens: z.int().nullish(),
930
+ linesChanged: z.int().nullish(),
931
+ m2TokenOutcomeRatio: z.number().nullish(),
932
+ m3UniqueToolCount: z.int().nullish(),
933
+ m4ConsecutiveErrorMax: z.int().nullish(),
934
+ m4ErrorRecoveryCount: z.int().nullish(),
935
+ m5AvgMessageTokens: z.int().nullish(),
936
+ m5ContextUtilizationPct: z.number().nullish(),
937
+ m5PeakContextTokens: z.int().nullish(),
938
+ m6LinesSurvived: z.int().nullish(),
939
+ m6LinesTotal: z.int().nullish(),
940
+ m6OutputSurvivalPct: z.number().nullish(),
941
+ m7SpecHasConstraints: z.boolean().nullish(),
942
+ m7SpecHasExamples: z.boolean().nullish(),
943
+ m7SpecWordCount: z.int().nullish(),
944
+ outcome: zSessionOutcome.nullish(),
945
+ outputTokens: z.int().nullish(),
946
+ retryLoops: z.int().nullish(),
947
+ retryTokensWasted: z.int().nullish(),
948
+ scope: z.string().nullish(),
949
+ scopeBreadth: z.int().nullish(),
950
+ signalDensity: z.number().nullish(),
951
+ specQualityScore: z.number().nullish(),
952
+ subagentCount: z.int().nullish(),
953
+ titleGenerated: z.string().nullish(),
954
+ toolCalls: z.int().nullish(),
955
+ totalTokens: z.int().nullish(),
956
+ turnCount: z.int().nullish(),
957
+ withinSessionReverts: z.int().nullish()
958
+ });
959
+ export const zSessionScorecard = z.object({
960
+ costTotalUsd: z.number().nullish(),
961
+ m2TokenOutcomeRatio: z.number().nullish(),
962
+ m4ConsecutiveErrorMax: z.int().nullish(),
963
+ m5ContextUtilizationPct: z.number().nullish(),
964
+ m6OutputSurvivalPct: z.number().nullish(),
965
+ m7SpecHasConstraints: z.boolean().nullish(),
966
+ m7SpecHasExamples: z.boolean().nullish(),
967
+ outcome: zSessionOutcome.optional(),
968
+ retryTokensWasted: z.int().nullish(),
969
+ signalDensity: z.number().nullish(),
970
+ specQualityScore: z.number().nullish(),
971
+ totalTokens: z.int().nullish(),
972
+ withinSessionReverts: z.int().nullish()
973
+ });
974
+ export const zSessionStats = z.object({
975
+ cachedReadTokens: z.int().nullish(),
976
+ cachedWriteTokens: z.int().nullish(),
977
+ durationMs: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }),
978
+ subagentCount: z.int(),
979
+ thoughtTokens: z.int().nullish(),
980
+ tokensIn: z.int(),
981
+ tokensOut: z.int(),
982
+ toolCallCount: z.int(),
983
+ turnCount: z.int()
984
+ });
985
+ export const zSessionSummary = z.object({
986
+ durationMins: z.number(),
987
+ harness: zHarness,
988
+ id: z.string(),
989
+ outcome: z.string().optional(),
990
+ parentSessionId: z.string().nullish(),
991
+ preview: z.string().optional(),
992
+ project: z.string().optional(),
993
+ projectHash: zProjectHash.optional(),
994
+ startTime: z.iso.datetime(),
995
+ toolCallCount: z.int(),
996
+ totalTokens: z.int(),
997
+ turnCount: z.int()
998
+ });
999
+ export const zSessionsPayload = z.object({
1000
+ sessions: z.array(zSessionSummary).nullable()
1001
+ });
1002
+ export const zShutdownResponse = z.object({
1003
+ status: z.string()
1004
+ });
1005
+ /**
1006
+ * Source Format
1007
+ *
1008
+ * Transcript file format
1009
+ */
1010
+ export const zSourceFormat = z.enum(['jsonl', 'json']);
1011
+ export const zSourceInfo = z.object({
1012
+ filePath: z.string().optional(),
1013
+ format: zSourceFormat
1014
+ });
1015
+ /**
1016
+ * Stop Reason
1017
+ *
1018
+ * Reason why a session or turn ended (ACP-aligned)
1019
+ */
1020
+ export const zStopReason = z.enum([
1021
+ 'end_turn',
1022
+ 'cancelled',
1023
+ 'max_tokens',
1024
+ 'max_turn_requests',
1025
+ 'refusal'
1026
+ ]);
1027
+ export const zSubagentRef = z.object({
1028
+ parentUuid: zSessionID,
1029
+ sessionId: zSessionID
1030
+ });
1031
+ /**
1032
+ * Target Kind
1033
+ *
1034
+ * What is being annotated: session-level, entry-level (turn/tool call), meta-annotation, project-level, a specific file version (content-hash keyed read-state receipt), or a durable session-to-commit association
1035
+ */
1036
+ export const zTargetKind = z.enum([
1037
+ 'session',
1038
+ 'entry',
1039
+ 'annotation',
1040
+ 'project',
1041
+ 'file_version',
1042
+ 'association'
1043
+ ]);
1044
+ export const zAnnotationPushItem = z.intersection(z.union([
1045
+ z.object({
1046
+ targetAssociationId: zAssociationID,
1047
+ targetKind: z.literal('association')
1048
+ }),
1049
+ z.object({
1050
+ sessionId: z.string().min(1),
1051
+ targetKind: z.literal('session')
1052
+ }),
1053
+ z.object({
1054
+ entryTarget: zAnnotationEntryTarget,
1055
+ targetKind: z.literal('entry')
1056
+ }),
1057
+ z.object({
1058
+ annotationId: z.string().min(1),
1059
+ targetKind: z.literal('annotation')
1060
+ }),
1061
+ z.object({
1062
+ projectHash: zProjectHash,
1063
+ targetKind: z.literal('project')
1064
+ })
1065
+ ]), z.object({
1066
+ annotationId: z.string().nullish(),
1067
+ annotatorName: z.string().optional(),
1068
+ confidence: z.number().nullish(),
1069
+ contentHash: z.string(),
1070
+ entryTarget: zAnnotationEntryTarget.nullish(),
1071
+ isPrimary: z.boolean(),
1072
+ projectHash: zProjectHash.nullish(),
1073
+ provenance: zProvenance.nullish(),
1074
+ reason: z.string().nullish(),
1075
+ sessionId: z.string().nullish(),
1076
+ targetAssociationId: zAssociationID.nullish(),
1077
+ targetKind: zTargetKind,
1078
+ typeId: z.string(),
1079
+ value: z.string()
1080
+ })).superRefine((value, context) => {
1081
+ const isPresent = (detail) => detail !== undefined && detail !== null;
1082
+ const hasNonEmptyString = (detail) => typeof detail === "string" && detail !== "";
1083
+ const hasOnly = (allowed) => {
1084
+ const targetFields = [
1085
+ ["targetAssociationId", value.targetAssociationId],
1086
+ ["sessionId", value.sessionId],
1087
+ ["entryTarget", value.entryTarget],
1088
+ ["annotationId", value.annotationId],
1089
+ ["projectHash", value.projectHash]
1090
+ ];
1091
+ return targetFields.every(([name, detail]) => allowed.includes(name) || !isPresent(detail));
1092
+ };
1093
+ const addIssue = (message) => context.addIssue({ code: "custom", message });
1094
+ switch (value.targetKind) {
1095
+ case "association":
1096
+ if (!isPresent(value.targetAssociationId))
1097
+ addIssue("association annotations require targetAssociationId");
1098
+ if (!hasOnly(["targetAssociationId"]))
1099
+ addIssue("association annotations must not mix target arms");
1100
+ return;
1101
+ case "session":
1102
+ if (!hasNonEmptyString(value.sessionId))
1103
+ addIssue("session annotations require a non-empty sessionId");
1104
+ if (!hasOnly(["sessionId"]))
1105
+ addIssue("session annotations must not mix target arms");
1106
+ return;
1107
+ case "entry":
1108
+ if (!isPresent(value.entryTarget))
1109
+ addIssue("entry annotations require entryTarget");
1110
+ if (!hasOnly(["entryTarget"]))
1111
+ addIssue("entry annotations must not mix target arms");
1112
+ return;
1113
+ case "annotation":
1114
+ if (!hasNonEmptyString(value.annotationId))
1115
+ addIssue("annotation targets require a non-empty annotationId");
1116
+ if (!hasOnly(["annotationId"]))
1117
+ addIssue("annotation targets must not mix target arms");
1118
+ return;
1119
+ case "project":
1120
+ if (!isPresent(value.projectHash))
1121
+ addIssue("project annotations require projectHash");
1122
+ if (!hasOnly(["projectHash"]))
1123
+ addIssue("project annotations must not mix target arms");
1124
+ return;
1125
+ }
1126
+ });
1127
+ export const zAnnotationPushRequest = z.object({
1128
+ annotations: z.array(zAnnotationPushItem),
1129
+ retractions: z.array(z.string()).optional()
1130
+ });
1131
+ export const zAnnotationSummary = z.object({
1132
+ annotatorKind: zAnnotatorKind,
1133
+ annotatorName: z.string(),
1134
+ confidence: z.number().nullish(),
1135
+ contentHash: z.string().nullish(),
1136
+ createdAt: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }),
1137
+ id: z.string(),
1138
+ isPrimary: z.boolean(),
1139
+ provenance: zProvenance.nullish(),
1140
+ reason: z.string().nullish(),
1141
+ supersededBy: z.string().nullish(),
1142
+ targetAnnotationId: z.string().nullish(),
1143
+ targetAssociationId: zAssociationID.nullish(),
1144
+ targetContentHash: z.string().nullish(),
1145
+ targetEntryEndIndex: z.int().nullish(),
1146
+ targetEntryIndex: z.int().nullish(),
1147
+ targetFilePath: z.string().nullish(),
1148
+ targetKind: zTargetKind,
1149
+ targetProjectHash: zProjectHash.nullish(),
1150
+ targetSessionId: z.string().nullish(),
1151
+ typeId: z.string(),
1152
+ typeName: z.string(),
1153
+ value: z.string()
1154
+ }).superRefine((value, context) => {
1155
+ const isPresent = (detail) => detail !== undefined && detail !== null;
1156
+ const hasNonEmptyString = (detail) => typeof detail === "string" && detail !== "";
1157
+ const hasOnly = (allowed) => {
1158
+ const targetFields = [
1159
+ ["targetAssociationId", value.targetAssociationId],
1160
+ ["targetSessionId", value.targetSessionId],
1161
+ ["targetEntryIndex", value.targetEntryIndex],
1162
+ ["targetEntryEndIndex", value.targetEntryEndIndex],
1163
+ ["targetAnnotationId", value.targetAnnotationId],
1164
+ ["targetProjectHash", value.targetProjectHash],
1165
+ ["targetFilePath", value.targetFilePath],
1166
+ ["targetContentHash", value.targetContentHash]
1167
+ ];
1168
+ return targetFields.every(([name, detail]) => allowed.includes(name) || !isPresent(detail));
1169
+ };
1170
+ const addIssue = (message) => context.addIssue({ code: "custom", message });
1171
+ switch (value.targetKind) {
1172
+ case "association":
1173
+ if (!isPresent(value.targetAssociationId))
1174
+ addIssue("association annotations require targetAssociationId");
1175
+ if (!hasOnly(["targetAssociationId"]))
1176
+ addIssue("association annotations must not mix target arms");
1177
+ return;
1178
+ case "session":
1179
+ if (!hasNonEmptyString(value.targetSessionId))
1180
+ addIssue("session annotations require a non-empty targetSessionId");
1181
+ if (!hasOnly(["targetSessionId"]))
1182
+ addIssue("session annotations must not mix target arms");
1183
+ return;
1184
+ case "entry":
1185
+ if (!hasNonEmptyString(value.targetSessionId) || !isPresent(value.targetEntryIndex))
1186
+ addIssue("entry annotations require targetSessionId and targetEntryIndex");
1187
+ if (!hasOnly(["targetSessionId", "targetEntryIndex", "targetEntryEndIndex"]))
1188
+ addIssue("entry annotations must not mix target arms");
1189
+ if (value.targetEntryIndex !== undefined && value.targetEntryIndex !== null && value.targetEntryEndIndex !== undefined && value.targetEntryEndIndex !== null && value.targetEntryEndIndex <= value.targetEntryIndex)
1190
+ addIssue("entry annotation targetEntryEndIndex must be greater than targetEntryIndex");
1191
+ return;
1192
+ case "annotation":
1193
+ if (!hasNonEmptyString(value.targetAnnotationId))
1194
+ addIssue("annotation targets require a non-empty targetAnnotationId");
1195
+ if (!hasOnly(["targetAnnotationId"]))
1196
+ addIssue("annotation targets must not mix target arms");
1197
+ return;
1198
+ case "project":
1199
+ if (!isPresent(value.targetProjectHash))
1200
+ addIssue("project annotations require targetProjectHash");
1201
+ if (!hasOnly(["targetProjectHash"]))
1202
+ addIssue("project annotations must not mix target arms");
1203
+ return;
1204
+ case "file_version":
1205
+ if (!hasNonEmptyString(value.targetFilePath) || !hasNonEmptyString(value.targetContentHash))
1206
+ addIssue("file_version annotations require non-empty targetFilePath and targetContentHash");
1207
+ if (!hasOnly(["targetFilePath", "targetContentHash"]))
1208
+ addIssue("file_version annotations must not mix target arms");
1209
+ return;
1210
+ }
1211
+ });
1212
+ export const zAnnotationsPayload = z.object({
1213
+ annotations: z.array(zAnnotationSummary).nullable(),
1214
+ axis: zAnnotationAxis,
1215
+ id: z.string()
1216
+ });
1217
+ export const zPullAnnotation = z.object({
1218
+ annotatorKind: zAnnotatorKind.optional(),
1219
+ annotatorName: z.string().optional(),
1220
+ authorUserId: z.string(),
1221
+ authorUsername: z.string(),
1222
+ confidence: z.number().nullish(),
1223
+ contentHash: z.string().nullish(),
1224
+ createdAt: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }).optional(),
1225
+ id: z.string().optional(),
1226
+ isPrimary: z.boolean().optional(),
1227
+ provenance: zProvenance.optional(),
1228
+ reason: z.string().nullish(),
1229
+ supersededBy: z.string().nullish(),
1230
+ targetAnnotationId: z.string().nullish(),
1231
+ targetAssociationId: zAssociationID.optional(),
1232
+ targetContentHash: z.string().nullish(),
1233
+ targetEntryEndIndex: z.int().nullish(),
1234
+ targetEntryIndex: z.int().nullish(),
1235
+ targetFilePath: z.string().nullish(),
1236
+ targetKind: zTargetKind.optional(),
1237
+ targetProjectHash: zProjectHash.optional(),
1238
+ targetSessionId: z.string().nullish(),
1239
+ typeId: z.string().optional(),
1240
+ typeName: z.string().optional(),
1241
+ value: z.string().optional()
1242
+ });
1243
+ export const zQualitySession = z.object({
1244
+ date: z.string(),
1245
+ discoveryTurns: z.int(),
1246
+ durationMinutes: z.number(),
1247
+ effectiveAnnotations: z.array(zAnnotationSummary).optional(),
1248
+ explorationRatio: z.number(),
1249
+ filesTouched: z.int(),
1250
+ id: z.string(),
1251
+ inputTokens: z.int(),
1252
+ linesChanged: z.int(),
1253
+ outcome: z.string(),
1254
+ outputTokens: z.int(),
1255
+ project: z.string(),
1256
+ retryLoops: z.int(),
1257
+ retryTokensWasted: z.int(),
1258
+ scope: z.string(),
1259
+ scopeBreadth: z.int(),
1260
+ signalDensity: z.number(),
1261
+ specQualityScore: z.number(),
1262
+ title: z.string(),
1263
+ toolCalls: z.int(),
1264
+ totalTokens: z.int(),
1265
+ turnCount: z.int(),
1266
+ withinSessionReverts: z.int()
1267
+ });
1268
+ export const zQualityPayload = z.object({
1269
+ sessions: z.array(zQualitySession).nullable()
1270
+ });
1271
+ export const zTaskSummary = z.object({
1272
+ editedFiles: z.array(z.string()).nullable(),
1273
+ entryIndex: z.int(),
1274
+ labels: z.array(z.string()).nullable(),
1275
+ outcome: z.string().optional(),
1276
+ readCount: z.int(),
1277
+ readFiles: z.array(z.string()),
1278
+ retryLoop: z.boolean(),
1279
+ sessionId: z.string(),
1280
+ startMs: z.int().nullish(),
1281
+ title: z.string()
1282
+ });
1283
+ export const zChangeSession = z.object({
1284
+ binding: zChangeBinding,
1285
+ harness: z.string(),
1286
+ sessionId: z.string(),
1287
+ startMs: z.int().nullish(),
1288
+ tasks: z.array(zTaskSummary).nullable(),
1289
+ title: z.string()
1290
+ });
1291
+ export const zMapNodeDetailPayload = z.object({
1292
+ costUsd: z.number().nullish(),
1293
+ dependsOn: z.array(z.string()).nullable(),
1294
+ insights: z.array(zSessionInsight),
1295
+ kind: zMapNodeKind,
1296
+ language: z.string().optional(),
1297
+ lastTouchMs: z.int().nullish(),
1298
+ loc: z.int(),
1299
+ path: z.string(),
1300
+ reEdits: z.int(),
1301
+ recentCommits: z.array(zCommitRef).nullable(),
1302
+ recordedFiles: z.int(),
1303
+ retryLoops: z.int(),
1304
+ rewrittenCommits: z.array(zRewrittenCommit),
1305
+ sessionCount: z.int(),
1306
+ shapedBy: z.array(zTaskSummary).nullable(),
1307
+ taskCount: z.int(),
1308
+ totalFiles: z.int(),
1309
+ usedBy: z.array(z.string()).nullable()
1310
+ });
1311
+ export const zProjectTasksPayload = z.object({
1312
+ fileFilter: z.string().optional(),
1313
+ projectHash: zProjectHash,
1314
+ tasks: z.array(zTaskSummary).nullable()
1315
+ });
1316
+ export const zTimelineSessionRef = z.object({
1317
+ harness: zHarness,
1318
+ hasCommitBinding: z.boolean(),
1319
+ sessionId: zSessionID,
1320
+ startMs: z.int().nullish(),
1321
+ title: z.string()
1322
+ });
1323
+ export const zReviewListPayload = z.object({
1324
+ changes: z.array(zChangeSummary),
1325
+ defaultBranch: z.string().optional(),
1326
+ projectHash: zProjectHash,
1327
+ recentCommits: z.array(zCommitRef),
1328
+ repoFound: z.boolean(),
1329
+ rewrittenCommits: z.array(zRewrittenCommit),
1330
+ sessions: z.array(zTimelineSessionRef)
1331
+ });
1332
+ export const zTimestampInfo = z.object({
1333
+ end: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }),
1334
+ ingested: z.int().nullish(),
1335
+ start: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' })
1336
+ });
1337
+ /**
1338
+ * Tool Call Kind
1339
+ *
1340
+ * Classification of a tool call, aligned with ACP ToolCallUpdate.kind
1341
+ */
1342
+ export const zToolCallKind = z.enum([
1343
+ 'read',
1344
+ 'edit',
1345
+ 'delete',
1346
+ 'move',
1347
+ 'search',
1348
+ 'execute',
1349
+ 'think',
1350
+ 'fetch',
1351
+ 'other'
1352
+ ]);
1353
+ export const zSessionEntry = z.object({
1354
+ contentPreview: z.string().nullish(),
1355
+ depth: z.int(),
1356
+ entryId: z.string().nullish(),
1357
+ entryIndex: z.int(),
1358
+ entryType: zEntryType,
1359
+ extra: z.string().nullish(),
1360
+ harness: zHarness,
1361
+ hasThinking: z.boolean(),
1362
+ hasToolUse: z.boolean(),
1363
+ isError: z.boolean(),
1364
+ parentEntryId: z.string().nullish(),
1365
+ parentIndex: z.int().nullish(),
1366
+ partType: z.string().nullish(),
1367
+ rawByteLength: z.int().nullish(),
1368
+ role: zRole,
1369
+ sessionId: zSessionID,
1370
+ stopReason: zStopReason.nullish(),
1371
+ timestampMs: z.int().nullish(),
1372
+ tokensIn: z.int().nullish(),
1373
+ tokensOut: z.int().nullish(),
1374
+ toolCallId: z.string().nullish(),
1375
+ toolInput: z.string().nullish(),
1376
+ toolKind: zToolCallKind.nullish(),
1377
+ toolNamesCsv: z.string().nullish(),
1378
+ toolOutput: z.string().nullish()
1379
+ });
1380
+ export const zPublishRequest = z.object({
1381
+ diagnostics: zDiagnosticsInfo,
1382
+ entries: z.array(zSessionEntry).optional(),
1383
+ git: zGitContext,
1384
+ identity: zSessionIdentity,
1385
+ license: zLicense.optional(),
1386
+ model: zModelInfo,
1387
+ project: zProjectContext,
1388
+ quality: zQualityMetrics.nullish(),
1389
+ source: zSourceInfo,
1390
+ stats: zSessionStats,
1391
+ subagents: z.array(zSubagentRef).optional(),
1392
+ timestamp: zTimestampInfo
1393
+ });
1394
+ export const zToolCallDetail = z.object({
1395
+ arguments: z.string(),
1396
+ durationMs: z.int().nullish(),
1397
+ exitCode: z.int().nullish(),
1398
+ filePath: z.string().optional(),
1399
+ id: z.string(),
1400
+ isError: z.boolean().optional(),
1401
+ name: z.string(),
1402
+ result: z.string(),
1403
+ toolKind: zToolCallKind.optional()
1404
+ });
1405
+ /**
1406
+ * Transcript ID
1407
+ *
1408
+ * Village-side transcript identifier (canonical lowercase-hex UUID)
1409
+ */
1410
+ export const zTranscriptID = z.uuid().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/);
1411
+ export const zPullSkipGateItem = z.object({
1412
+ annotationHashes: z.array(z.string()),
1413
+ contentHash: z.string(),
1414
+ transcriptId: zTranscriptID
1415
+ });
1416
+ export const zPullSkipGateRequest = z.object({
1417
+ items: z.array(zPullSkipGateItem)
1418
+ });
1419
+ export const zPullSkipGateResult = z.object({
1420
+ annotationsCurrent: z.boolean(),
1421
+ contentCurrent: z.boolean(),
1422
+ transcriptId: zTranscriptID
1423
+ });
1424
+ export const zPullSkipGateResponse = z.object({
1425
+ results: z.array(zPullSkipGateResult)
1426
+ });
1427
+ export const zTrendsPayload = z.object({
1428
+ days: z.array(zDayStats).nullable(),
1429
+ totalSessions: z.int(),
1430
+ totalTokens: z.int()
1431
+ });
1432
+ export const zTurnDetail = z.object({
1433
+ agentName: z.string().optional(),
1434
+ content: z.string(),
1435
+ depth: z.int(),
1436
+ entryType: zEntryType.optional(),
1437
+ hasThinking: z.boolean().optional(),
1438
+ index: z.int(),
1439
+ parentIndex: z.int().nullish(),
1440
+ role: zRole,
1441
+ stopReason: zStopReason.nullish(),
1442
+ timestamp: z.iso.datetime(),
1443
+ tokensIn: z.int().nullish(),
1444
+ tokensOut: z.int().nullish(),
1445
+ toolCalls: z.array(zToolCallDetail).optional()
1446
+ });
1447
+ export const zSessionDetailPayload = z.object({
1448
+ childSessions: z.array(zChildSessionRef).optional(),
1449
+ durationMins: z.number(),
1450
+ endTime: z.iso.datetime(),
1451
+ gitBranch: z.string().optional(),
1452
+ gitRemote: z.string().optional(),
1453
+ harness: zHarness,
1454
+ id: z.string(),
1455
+ model: z.string().optional(),
1456
+ outcome: zSessionOutcome.optional(),
1457
+ project: z.string().optional(),
1458
+ schemaVersion: z.string().optional(),
1459
+ scorecard: zSessionScorecard.nullish(),
1460
+ source: z.string().optional(),
1461
+ startTime: z.iso.datetime(),
1462
+ status: z.string().optional(),
1463
+ tokensIn: z.int(),
1464
+ tokensOut: z.int(),
1465
+ toolCallCount: z.int(),
1466
+ totalTokens: z.int(),
1467
+ turnCount: z.int(),
1468
+ turns: z.array(zTurnDetail).nullable(),
1469
+ workingDirectory: z.string().optional()
1470
+ });
1471
+ export const zTranscriptContent = z.object({
1472
+ contractVersion: z.string(),
1473
+ kind: zContentKind,
1474
+ sessionDetail: zSessionDetailPayload.nullish()
1475
+ });
1476
+ /**
1477
+ * Type Origin
1478
+ *
1479
+ * Who created an annotation type: system (built-in), user (individual), or group (shared)
1480
+ */
1481
+ export const zTypeOrigin = z.enum([
1482
+ 'system',
1483
+ 'user',
1484
+ 'group'
1485
+ ]);
1486
+ export const zUnifiedMetadata = z.object({
1487
+ contentHash: z.string(),
1488
+ cwd: z.string().optional(),
1489
+ derivedAt: z.int().nullish(),
1490
+ diagnostics: zDiagnosticsInfo,
1491
+ git: zGitContext,
1492
+ harness: zHarness,
1493
+ hostSlug: zHostSlug,
1494
+ metadataHash: z.string(),
1495
+ model: zModelID,
1496
+ parentUuid: zSessionID.nullable(),
1497
+ project: zProjectContext,
1498
+ redaction: zRedactionInfo,
1499
+ schemaVersion: z.int(),
1500
+ sessionId: zSessionID,
1501
+ source: zSourceInfo,
1502
+ stats: zSessionStats,
1503
+ subagents: z.array(zSubagentRef).nullable(),
1504
+ timestamp: zTimestampInfo,
1505
+ version: z.string()
1506
+ });
1507
+ export const zUnusualSignal = z.object({
1508
+ kind: z.string(),
1509
+ label: z.string(),
1510
+ perChange: z.number(),
1511
+ perProject: z.number()
1512
+ });
1513
+ export const zChangeDetailPayload = z.object({
1514
+ baseRef: z.string(),
1515
+ branch: z.string(),
1516
+ costUsd: z.number().nullish(),
1517
+ defaultBranch: z.string(),
1518
+ files: z.array(zFileChange).nullable(),
1519
+ frictions: z.array(zFrictionCluster).nullable(),
1520
+ insights: z.array(zSessionInsight),
1521
+ linesAdded: z.int(),
1522
+ linesRemoved: z.int(),
1523
+ newEdges: z.array(zMapEdge).nullable(),
1524
+ newNodes: z.array(z.string()).nullable(),
1525
+ outputTokens: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }),
1526
+ removedEdges: z.array(zMapEdge).nullable(),
1527
+ removedNodes: z.array(z.string()).nullable(),
1528
+ slice: zMapSlice,
1529
+ unrecordedCommits: z.array(zCommitRef).nullable(),
1530
+ unusual: z.array(zUnusualSignal).nullable(),
1531
+ violations: z.array(zEdgeViolation).nullable(),
1532
+ work: z.array(zChangeSession).nullable()
1533
+ });
1534
+ /**
1535
+ * Value Domain Kind
1536
+ *
1537
+ * ISO 11179 value domain: enumerated (finite allowed set) or described (range/pattern constraint)
1538
+ */
1539
+ export const zValueDomainKind = z.enum(['enumerated', 'described']);
1540
+ export const zValueDomain = z.object({
1541
+ constraintSpec: z.string().optional(),
1542
+ datatype: zAnnotationDatatype,
1543
+ kind: zValueDomainKind,
1544
+ permissibleValues: z.array(z.string()).optional()
1545
+ });
1546
+ export const zAnnotationTypeSummary = z.object({
1547
+ allowedTargetKinds: z.array(zTargetKind).optional(),
1548
+ class: z.string(),
1549
+ description: z.string().optional(),
1550
+ displayName: z.string(),
1551
+ family: z.string(),
1552
+ id: z.string().optional(),
1553
+ lowerIsBetter: z.boolean().nullish(),
1554
+ origin: zTypeOrigin,
1555
+ priorityOverride: z.int().nullish(),
1556
+ scaleKind: zScaleKind.optional(),
1557
+ status: zAnnotationStatus,
1558
+ typeId: z.string(),
1559
+ valueDomain: zValueDomain,
1560
+ version: z.int()
1561
+ });
1562
+ export const zTaxonomyFamilyNode = z.object({
1563
+ family: z.string(),
1564
+ types: z.array(zAnnotationTypeSummary).nullable()
1565
+ });
1566
+ export const zTaxonomyNode = z.object({
1567
+ class: z.string(),
1568
+ families: z.array(zTaxonomyFamilyNode).nullable()
1569
+ });
1570
+ /**
1571
+ * Visibility
1572
+ *
1573
+ * Access control level for a published transcript
1574
+ */
1575
+ export const zVisibility = z.enum([
1576
+ 'private',
1577
+ 'group',
1578
+ 'public'
1579
+ ]);
1580
+ export const zPullTranscriptInfo = z.object({
1581
+ annotationCount: z.int(),
1582
+ contentHash: z.string().optional(),
1583
+ contractVersion: z.string().optional(),
1584
+ harness: zHarness.optional(),
1585
+ license: zLicense.optional(),
1586
+ localId: z.string().optional(),
1587
+ ownerUserId: z.string(),
1588
+ ownerUsername: z.string(),
1589
+ projectName: z.string().optional(),
1590
+ publishedAt: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }),
1591
+ title: z.string().optional(),
1592
+ transcriptId: zTranscriptID,
1593
+ updatedAt: z.coerce.bigint().min(BigInt('-9223372036854775808'), { error: 'Invalid value: Expected int64 to be >= -9223372036854775808' }).max(BigInt('9223372036854775807'), { error: 'Invalid value: Expected int64 to be <= 9223372036854775807' }),
1594
+ visibility: zVisibility
1595
+ });
1596
+ export const zPullListResponse = z.object({
1597
+ limit: z.int(),
1598
+ page: z.int(),
1599
+ total: z.int(),
1600
+ transcripts: z.array(zPullTranscriptInfo).nullable()
1601
+ });
1602
+ export const zWalkthroughStep = z.object({
1603
+ excerpt: z.string(),
1604
+ file: z.string(),
1605
+ line: z.int().nullish()
1606
+ });
1607
+ export const zWalkthroughTrail = z.object({
1608
+ date: z.string(),
1609
+ isCoherent: z.boolean(),
1610
+ sessionId: z.string(),
1611
+ steps: z.array(zWalkthroughStep).nullable(),
1612
+ title: z.string(),
1613
+ turnCount: z.int()
1614
+ });
1615
+ export const zFamiliarityPayload = z.object({
1616
+ familiarityPct: z.number(),
1617
+ files: z.array(zFileFamiliarity).nullable(),
1618
+ freshnessDays: z.int().nullable(),
1619
+ projectHash: zProjectHash,
1620
+ suggestions: z.array(zReviewSuggestion).nullable(),
1621
+ trails: z.array(zWalkthroughTrail).nullable(),
1622
+ unexploredCount: z.int()
1623
+ });