@peasant-labs/schema 0.18.0 → 0.20.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.
@@ -6,6 +6,17 @@ export const zActivityEdge = z.object({
6
6
  taskCount: z.int(),
7
7
  to: z.string()
8
8
  });
9
+ /**
10
+ * Actor Origin
11
+ *
12
+ * Closed session graph value
13
+ */
14
+ export const zActorOrigin = z.enum([
15
+ 'operator',
16
+ 'agent_delegate',
17
+ 'harness',
18
+ 'unknown'
19
+ ]);
9
20
  /**
10
21
  * Annotation Axis
11
22
  *
@@ -209,6 +220,7 @@ export const zAuthoritativeSessionStats = z.object({
209
220
  cachedReadTokens: z.int().nullish(),
210
221
  cachedWriteTokens: z.int().nullish(),
211
222
  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' }),
223
+ inputSubmissionCount: z.int().gte(0).lte(9007199254740991).optional(),
212
224
  subagentCount: z.int(),
213
225
  thoughtTokens: z.int().nullish(),
214
226
  tokensIn: z.int(),
@@ -354,6 +366,31 @@ export const zContentCapability = z.string();
354
366
  * Payload kind carried by a transcript content envelope
355
367
  */
356
368
  export const zContentKind = z.enum(['session_detail']);
369
+ /**
370
+ * Content Origin
371
+ *
372
+ * Closed session graph value
373
+ */
374
+ export const zContentOrigin = z.enum([
375
+ 'submitted_input',
376
+ 'harness_context',
377
+ 'agent_output',
378
+ 'agent_communication',
379
+ 'tool_activity',
380
+ 'system_control',
381
+ 'generated_summary',
382
+ 'unknown'
383
+ ]);
384
+ /**
385
+ * Content Ownership
386
+ *
387
+ * Closed session graph value
388
+ */
389
+ export const zContentOwnership = z.enum([
390
+ 'local',
391
+ 'inherited',
392
+ 'uncertain'
393
+ ]);
357
394
  export const zContractVersion = z.string().nullable();
358
395
  export const zCreateAnnotationRequest = z.object({
359
396
  annotatorName: z.string().optional(),
@@ -397,6 +434,20 @@ export const zDecayLevel = z.enum([
397
434
  'stale',
398
435
  'unexplored'
399
436
  ]);
437
+ /**
438
+ * Delivery Origin
439
+ *
440
+ * Closed session graph value
441
+ */
442
+ export const zDeliveryOrigin = z.enum([
443
+ 'session_admission',
444
+ 'guardian_review',
445
+ 'subagent_delivery',
446
+ 'inherited_context',
447
+ 'tool_delivery',
448
+ 'system_lifecycle',
449
+ 'unknown'
450
+ ]);
400
451
  export const zDiagnosticEntry = z.object({
401
452
  errorType: z.string(),
402
453
  location: z.string(),
@@ -442,6 +493,12 @@ export const zDigestItemKind = z.enum([
442
493
  'skill',
443
494
  'commit'
444
495
  ]);
496
+ /**
497
+ * Earlier History State
498
+ *
499
+ * Closed session graph value
500
+ */
501
+ export const zEarlierHistoryState = z.enum(['uncertain_migrated', 'uncertain_unresolved']);
445
502
  /**
446
503
  * Edge Violation Kind
447
504
  *
@@ -467,6 +524,19 @@ export const zEntryType = z.enum([
467
524
  'error',
468
525
  'result'
469
526
  ]);
527
+ /**
528
+ * Evidence Kind
529
+ *
530
+ * Closed session graph value
531
+ */
532
+ export const zEvidenceKind = z.enum([
533
+ 'native_typed',
534
+ 'lifecycle_typed',
535
+ 'existing_adapter',
536
+ 'retained_last_good',
537
+ 'unknown',
538
+ 'conflict'
539
+ ]);
470
540
  export const zExchangeCodeRequest = z.object({
471
541
  code: z.string(),
472
542
  state: z.string()
@@ -546,6 +616,19 @@ export const zHealthResponse = z.object({
546
616
  * Sanitized, filesystem-safe identifier derived from git remote; contains only [a-zA-Z0-9._<>-]
547
617
  */
548
618
  export const zHostSlug = z.string().regex(/^[a-zA-Z0-9._<>-]+$/);
619
+ /**
620
+ * Input Modality
621
+ *
622
+ * Closed session graph value
623
+ */
624
+ export const zInputModality = z.enum([
625
+ 'none',
626
+ 'text',
627
+ 'media',
628
+ 'user_action',
629
+ 'mixed',
630
+ 'unknown'
631
+ ]);
549
632
  export const zInsightClassification = z.object({
550
633
  category: z.string(),
551
634
  cause: z.string(),
@@ -686,25 +769,12 @@ export const zNativeMetadataSourceType = z.enum([
686
769
  * Pi message role needed for public metadata validation
687
770
  */
688
771
  export const zNativePiMessageRole = z.enum(['toolResult']);
689
- export const zNativeSourceRef = z.object({
690
- entryRef: z.string(),
691
- messageRole: zNativePiMessageRole.optional(),
692
- sourceType: zNativeMetadataSourceType
693
- });
694
- export const zNativeMetadataRecord = z.object({
695
- attachment: zNativeAttachmentRef.nullish(),
696
- customType: z.string().optional(),
697
- data: z.unknown(),
698
- id: z.string(),
699
- kind: zNativeMetadataKind,
700
- source: zNativeSourceRef
701
- });
702
772
  /**
703
773
  * Observed Model ID
704
774
  *
705
775
  * Exact UTF-8 model identifier observed on an assistant-generated turn; producer-enforced as assistant or subagent evidence. Values are non-empty and may not have a Unicode White_Space code point at either edge; all accepted bytes, including Unicode, mixed case, slashes, and internal spaces, are preserved.
706
776
  */
707
- export const zObservedModelID = z.string().min(1).regex(/^(?:|[^\s\x85])(?:[\s\S]*(?:|[^\s\x85]))?(?![\s\S])/);
777
+ export const zObservedModelID = z.string().min(1).regex(/^(?:|[^\s])(?:[\s\S]*(?:|[^\s]))?$/).refine((value) => { const edge = (text) => text === "\uFEFF" || (!/\s/u.test(text) && text !== "\u0085"); return edge(value.charAt(0)) && edge(value.charAt(value.length - 1)); }, { error: "ObservedModelID must match pattern without edge whitespace" });
708
778
  /**
709
779
  * Omitted preserves, null requests clear, and a canonical license replaces
710
780
  */
@@ -724,6 +794,23 @@ export const zAuthoritativeProjectContext = z.object({
724
794
  hash: zProjectHash,
725
795
  name: z.string()
726
796
  }).strict();
797
+ export const zLocalSyncSummary = z.object({
798
+ 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' }),
799
+ harness: zHarness,
800
+ hostSlug: z.string(),
801
+ id: z.string(),
802
+ inputSubmissionCount: z.int().gte(0).lte(9007199254740991).optional(),
803
+ model: z.string(),
804
+ projectHash: zProjectHash,
805
+ projectName: z.string(),
806
+ startTime: z.string(),
807
+ syncStatus: z.string(),
808
+ totalTokens: z.int(),
809
+ turnCount: z.int()
810
+ });
811
+ export const zLocalSyncSessionsPayload = z.object({
812
+ sessions: z.array(zLocalSyncSummary)
813
+ });
727
814
  export const zProjectContext = z.object({
728
815
  filePath: z.string().optional(),
729
816
  hash: zProjectHash,
@@ -764,6 +851,20 @@ export const zProvenance = z.object({
764
851
  method: z.string(),
765
852
  version: z.string().optional()
766
853
  });
854
+ /**
855
+ * Public Revision Reference
856
+ */
857
+ export const zPublicRevisionRef = z.string().min(1).max(96).refine((value) => !/[\uD800-\uDFFF]/u.test(value) && new TextEncoder().encode(value).length <= 96, { error: "PublicRevisionRef is invalid UTF-8 or exceeds 96 bytes" });
858
+ /**
859
+ * Public Source Anchor Kind
860
+ *
861
+ * Closed session graph value
862
+ */
863
+ export const zPublicSourceAnchorKind = z.enum([
864
+ 'general_source_session',
865
+ 'before_redacted_entry',
866
+ 'through_redacted_entry'
867
+ ]);
767
868
  /**
768
869
  * Publish Operation Kind
769
870
  *
@@ -936,6 +1037,39 @@ export const zRedactionInfo = z.object({
936
1037
  redacted_at_ms: z.int().nullish(),
937
1038
  rule_set_version: z.string().optional()
938
1039
  });
1040
+ /**
1041
+ * Relationship Navigation Status
1042
+ *
1043
+ * Closed session graph value
1044
+ */
1045
+ export const zRelationshipNavigationStatus = z.enum([
1046
+ 'resolved',
1047
+ 'general_link_only',
1048
+ 'known_unavailable',
1049
+ 'inaccessible',
1050
+ 'unknown',
1051
+ 'conflicting'
1052
+ ]);
1053
+ export const zHelperContextSummary = z.object({
1054
+ groupId: z.string(),
1055
+ ownerStatus: zRelationshipNavigationStatus
1056
+ }).superRefine((value, context) => {
1057
+ const fail = (reason) => context.addIssue({ code: "custom", message: "schema.zHelperContextSummary during grouped read validation: " + reason });
1058
+ if (value.groupId === "")
1059
+ fail("context groupId must identify its scoped group; refresh the original list");
1060
+ });
1061
+ /**
1062
+ * Relationship Target State
1063
+ *
1064
+ * Closed session graph value
1065
+ */
1066
+ export const zRelationshipTargetState = z.enum([
1067
+ 'target_known',
1068
+ 'target_known_retained',
1069
+ 'explicit_none',
1070
+ 'unknown',
1071
+ 'conflicting_current_native_evidence'
1072
+ ]);
939
1073
  export const zReviewSuggestion = z.object({
940
1074
  daysSince: z.int(),
941
1075
  lastEngaged: z.string(),
@@ -1024,11 +1158,6 @@ export const zServerMessage = z.object({
1024
1158
  * Unique session identifier (UUID, agent-{hex}, ses_{id}, sess_{id} (ACP), msg_{id}, or a Strike session ID)
1025
1159
  */
1026
1160
  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})$/);
1027
- export const zAuthoritativeSessionIdentity = z.object({
1028
- parentSessionId: zSessionID.optional(),
1029
- schemaVersion: z.int(),
1030
- sessionId: zSessionID
1031
- }).strict();
1032
1161
  export const zAuthoritativeSubagentRef = z.object({
1033
1162
  parentUuid: zSessionID,
1034
1163
  sessionId: zSessionID
@@ -1122,6 +1251,12 @@ export const zSessionInsight = z.object({
1122
1251
  summary: z.string().optional(),
1123
1252
  title: z.string()
1124
1253
  });
1254
+ /**
1255
+ * Session List Item Kind
1256
+ *
1257
+ * Closed session graph value
1258
+ */
1259
+ export const zSessionListItemKind = z.enum(['transcript', 'context_container']);
1125
1260
  /**
1126
1261
  * Session Origin
1127
1262
  *
@@ -1230,6 +1365,33 @@ export const zQualityMetrics = z.object({
1230
1365
  turnCount: z.int().nullish(),
1231
1366
  withinSessionReverts: z.int().nullish()
1232
1367
  });
1368
+ /**
1369
+ * Session Purpose
1370
+ *
1371
+ * Closed session graph value
1372
+ */
1373
+ export const zSessionPurpose = z.enum([
1374
+ 'interaction',
1375
+ 'delegated_work',
1376
+ 'helper_review',
1377
+ 'unknown'
1378
+ ]);
1379
+ export const zHelperGroupSummary = z.object({
1380
+ groupId: z.string(),
1381
+ helperThreadCount: z.int().gte(0).lte(9007199254740991),
1382
+ memberScope: z.string(),
1383
+ purpose: zSessionPurpose
1384
+ }).superRefine((value, context) => {
1385
+ const fail = (reason) => context.addIssue({ code: "custom", message: "schema.zHelperGroupSummary during grouped read validation: " + reason });
1386
+ if (value.groupId === "" || value.memberScope === "" || value.purpose !== "helper_review")
1387
+ fail("groupId/memberScope must identify an immediate helper_review group; refresh the original scoped list");
1388
+ });
1389
+ /**
1390
+ * Session Relationship Kind
1391
+ *
1392
+ * Closed session graph value
1393
+ */
1394
+ export const zSessionRelationshipKind = z.enum(['started_by', 'context_from']);
1233
1395
  export const zSessionScorecard = z.object({
1234
1396
  costTotalUsd: z.number().nullish(),
1235
1397
  m2TokenOutcomeRatio: z.number().nullish(),
@@ -1249,6 +1411,7 @@ export const zSessionStats = z.object({
1249
1411
  cachedReadTokens: z.int().nullish(),
1250
1412
  cachedWriteTokens: z.int().nullish(),
1251
1413
  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' }),
1414
+ inputSubmissionCount: z.int().gte(0).lte(9007199254740991).optional(),
1252
1415
  subagentCount: z.int(),
1253
1416
  thoughtTokens: z.int().nullish(),
1254
1417
  tokensIn: z.int(),
@@ -1256,27 +1419,141 @@ export const zSessionStats = z.object({
1256
1419
  toolCallCount: z.int(),
1257
1420
  turnCount: z.int()
1258
1421
  });
1422
+ export const zShutdownResponse = z.object({
1423
+ status: z.string()
1424
+ });
1425
+ /**
1426
+ * Source Entry Reference
1427
+ */
1428
+ export const zSourceEntryRef = z.string().min(1).max(96).refine((value) => !/[\uD800-\uDFFF]/u.test(value) && new TextEncoder().encode(value).length <= 96, { error: "SourceEntryRef is invalid UTF-8 or exceeds 96 bytes" });
1429
+ export const zNativeSourceRef = z.object({
1430
+ entryRef: zSourceEntryRef,
1431
+ messageRole: zNativePiMessageRole.optional(),
1432
+ sourceType: zNativeMetadataSourceType
1433
+ });
1434
+ export const zNativeMetadataRecord = z.object({
1435
+ attachment: zNativeAttachmentRef.nullish(),
1436
+ customType: z.string().optional(),
1437
+ data: z.unknown(),
1438
+ id: z.string(),
1439
+ kind: zNativeMetadataKind,
1440
+ source: zNativeSourceRef
1441
+ });
1442
+ export const zPublicSourceAnchor = z.object({
1443
+ kind: zPublicSourceAnchorKind,
1444
+ sourceEntryRef: zSourceEntryRef.optional(),
1445
+ sourceRevisionRef: zPublicRevisionRef.optional()
1446
+ }).strict();
1447
+ export const zSessionRelationship = z.object({
1448
+ anchor: zPublicSourceAnchor.optional(),
1449
+ evidence: zEvidenceKind,
1450
+ kind: zSessionRelationshipKind,
1451
+ targetLocalId: zSessionID.optional(),
1452
+ targetState: zRelationshipTargetState
1453
+ }).strict();
1454
+ export const zAuthoritativeSessionIdentity = z.object({
1455
+ parentSessionId: zSessionID.optional(),
1456
+ purpose: zSessionPurpose.optional(),
1457
+ relationships: z.array(zSessionRelationship).optional(),
1458
+ rootSessionId: zSessionID.optional(),
1459
+ schemaVersion: z.int(),
1460
+ sessionId: zSessionID
1461
+ }).strict();
1259
1462
  export const zSessionSummary = z.object({
1260
1463
  durationMins: z.number(),
1261
1464
  harness: zHarness,
1262
1465
  id: z.string(),
1466
+ inputSubmissionCount: z.int().gte(0).lte(9007199254740991).optional(),
1263
1467
  outcome: z.string().optional(),
1264
1468
  parentSessionId: z.string().nullish(),
1265
1469
  preview: z.string().optional(),
1266
1470
  project: z.string().optional(),
1267
1471
  projectHash: zProjectHash.optional(),
1472
+ purpose: zSessionPurpose.optional(),
1473
+ relationships: z.array(zSessionRelationship).optional(),
1474
+ rootSessionId: zSessionID.nullish(),
1268
1475
  sessionOrigin: zSessionOrigin.optional(),
1269
1476
  startTime: z.iso.datetime(),
1270
1477
  toolCallCount: z.int(),
1271
1478
  totalTokens: z.int(),
1272
1479
  turnCount: z.int()
1273
1480
  });
1481
+ export const zLocalSessionRow = z.object({
1482
+ matches: z.array(zSearchResult).optional(),
1483
+ session: zSessionSummary,
1484
+ sync: zLocalSyncSummary.nullish()
1485
+ }).superRefine((value, context) => {
1486
+ const fail = (reason) => context.addIssue({ code: "custom", message: "schema.zLocalSessionRow during grouped read validation: " + reason });
1487
+ if (value.session.id === "")
1488
+ fail("session.id is empty; provide the saved transcript identity");
1489
+ if (value.sync && value.matches?.length)
1490
+ fail("sync and matches select incompatible route arms; retain the originating route only");
1491
+ if (value.sync) {
1492
+ const s = value.session, v = value.sync;
1493
+ if (v.id !== s.id || v.harness !== s.harness || v.projectName !== s.project || v.projectHash !== s.projectHash || v.totalTokens !== s.totalTokens || v.turnCount !== s.turnCount || v.inputSubmissionCount !== s.inputSubmissionCount)
1494
+ fail("sync identity or count mirrors disagree; derive both from the same row");
1495
+ }
1496
+ if (value.matches?.some(match => match.sessionId !== value.session.id))
1497
+ fail("search match belongs to another session; retain only this transcript's evidence");
1498
+ });
1499
+ export const zLocalSessionListItem = z.object({
1500
+ context: zHelperContextSummary.nullish(),
1501
+ helperGroups: z.array(zHelperGroupSummary).optional(),
1502
+ kind: zSessionListItemKind,
1503
+ transcript: zLocalSessionRow.nullish()
1504
+ }).superRefine((value, context) => {
1505
+ const fail = (reason) => context.addIssue({ code: "custom", message: "schema.zLocalSessionListItem during grouped read validation: " + reason });
1506
+ if ((value.kind === "transcript") !== (value.transcript != null) || (value.kind === "context_container") !== (value.context != null))
1507
+ fail("kind must select exactly one matching transcript/context arm; omit the other arm");
1508
+ const groups = new Set();
1509
+ for (const group of value.helperGroups ?? []) {
1510
+ if (groups.has(group.groupId))
1511
+ fail("duplicate groupId prevents independent paging; emit each immediate group once");
1512
+ groups.add(group.groupId);
1513
+ }
1514
+ });
1515
+ export const zLocalHelperMembersPayload = z.object({
1516
+ limit: z.int().gte(1).lte(9007199254740991),
1517
+ members: z.array(zLocalSessionListItem.and(z.object({
1518
+ context: z.null().optional(),
1519
+ kind: z.enum(['transcript']).optional(),
1520
+ transcript: zLocalSessionRow
1521
+ }))),
1522
+ page: z.int().gte(1).lte(9007199254740991),
1523
+ total: z.int().gte(0).lte(9007199254740991)
1524
+ }).superRefine((value, context) => {
1525
+ const fail = (reason) => context.addIssue({ code: "custom", message: "schema.zLocalHelperMembersPayload during grouped read validation: " + reason });
1526
+ if (value.members.length > value.limit || value.members.length > value.total)
1527
+ fail("member count exceeds page limit or direct total; count direct saved helpers before paging");
1528
+ const ids = new Set();
1529
+ const groups = new Set();
1530
+ for (const member of value.members) {
1531
+ if (member.kind !== "transcript" || member.transcript == null || member.context != null) {
1532
+ fail("members must be transcript items, never context containers; preserve nested groups on the item");
1533
+ continue;
1534
+ }
1535
+ const id = member.transcript.session.id;
1536
+ if (ids.has(id))
1537
+ fail("duplicate member identity would double count a saved helper; emit each transcript once");
1538
+ ids.add(id);
1539
+ for (const group of member.helperGroups ?? []) {
1540
+ if (groups.has(group.groupId))
1541
+ fail("groupId appears under multiple members; emit each immediate-owner group once");
1542
+ groups.add(group.groupId);
1543
+ }
1544
+ }
1545
+ });
1546
+ export const zLocalSessionListPayload = z.object({
1547
+ helperThreadTotal: z.int().gte(0).lte(9007199254740991),
1548
+ items: z.array(zLocalSessionListItem),
1549
+ limit: z.int().gte(1).lte(9007199254740991),
1550
+ ordinarySessionTotal: z.int().gte(0).lte(9007199254740991),
1551
+ page: z.int().gte(1).lte(9007199254740991),
1552
+ totalItems: z.int().gte(0).lte(9007199254740991)
1553
+ });
1274
1554
  export const zSessionsPayload = z.object({
1275
1555
  sessions: z.array(zSessionSummary).nullable()
1276
1556
  });
1277
- export const zShutdownResponse = z.object({
1278
- status: z.string()
1279
- });
1280
1557
  /**
1281
1558
  * Source Format
1282
1559
  *
@@ -1307,6 +1584,19 @@ export const zSubagentRef = z.object({
1307
1584
  parentUuid: zSessionID,
1308
1585
  sessionId: zSessionID
1309
1586
  });
1587
+ /**
1588
+ * Submission Reference
1589
+ */
1590
+ export const zSubmissionRef = z.string().min(1).max(96).refine((value) => !/[\uD800-\uDFFF]/u.test(value) && new TextEncoder().encode(value).length <= 96, { error: "SubmissionRef is invalid UTF-8 or exceeds 96 bytes" });
1591
+ export const zContentProvenance = z.object({
1592
+ actor: zActorOrigin,
1593
+ delivery: zDeliveryOrigin,
1594
+ evidence: zEvidenceKind,
1595
+ inputModality: zInputModality,
1596
+ origin: zContentOrigin,
1597
+ ownership: zContentOwnership,
1598
+ submissionRef: zSubmissionRef.optional()
1599
+ }).strict();
1310
1600
  /**
1311
1601
  * Target Kind
1312
1602
  *
@@ -1652,9 +1942,11 @@ export const zAuthoritativeSessionEntry = z.object({
1652
1942
  parentEntryId: z.string().nullish(),
1653
1943
  parentIndex: z.int().nullish(),
1654
1944
  partType: z.string().nullish(),
1945
+ provenance: zContentProvenance.optional(),
1655
1946
  rawByteLength: z.int().nullish(),
1656
1947
  role: zRole,
1657
1948
  sessionId: zSessionID,
1949
+ sourceEntryRef: zSourceEntryRef.optional(),
1658
1950
  stopReason: zStopReason.nullish(),
1659
1951
  timestampMs: z.int().nullish(),
1660
1952
  tokensIn: z.int().nullish(),
@@ -1692,9 +1984,11 @@ export const zSessionEntry = z.object({
1692
1984
  parentEntryId: z.string().nullish(),
1693
1985
  parentIndex: z.int().nullish(),
1694
1986
  partType: z.string().nullish(),
1987
+ provenance: zContentProvenance.nullish(),
1695
1988
  rawByteLength: z.int().nullish(),
1696
1989
  role: zRole,
1697
1990
  sessionId: zSessionID,
1991
+ sourceEntryRef: zSourceEntryRef.optional(),
1698
1992
  stopReason: zStopReason.nullish(),
1699
1993
  timestampMs: z.int().nullish(),
1700
1994
  tokensIn: z.int().nullish(),
@@ -1738,8 +2032,11 @@ export const zCanonicalPublishOperation = z.object({
1738
2032
  */
1739
2033
  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}$/);
1740
2034
  export const zPromptDigestItem = z.object({
2035
+ additions: z.int().nullish(),
1741
2036
  commitCount: z.int().nullish(),
1742
2037
  commitSha: z.string().optional(),
2038
+ deletions: z.int().nullish(),
2039
+ filesChanged: z.int().nullish(),
1743
2040
  kind: zDigestItemKind,
1744
2041
  ordinal: z.int().nullish(),
1745
2042
  promptCount: z.int().nullish(),
@@ -1769,6 +2066,13 @@ export const zPullSkipGateResult = z.object({
1769
2066
  export const zPullSkipGateResponse = z.object({
1770
2067
  results: z.array(zPullSkipGateResult)
1771
2068
  });
2069
+ export const zSessionRelationshipNavigation = z.object({
2070
+ anchor: zPublicSourceAnchor.optional(),
2071
+ kind: zSessionRelationshipKind,
2072
+ localId: zSessionID.optional(),
2073
+ status: zRelationshipNavigationStatus,
2074
+ transcriptId: zTranscriptID.optional()
2075
+ }).strict();
1772
2076
  /**
1773
2077
  * TranscriptUpdateLicense
1774
2078
  *
@@ -1859,7 +2163,10 @@ export const zUnifiedMetadata = z.object({
1859
2163
  model: zModelID,
1860
2164
  parentUuid: zSessionID.nullable(),
1861
2165
  project: zProjectContext,
2166
+ purpose: zSessionPurpose.optional(),
1862
2167
  redaction: zRedactionInfo,
2168
+ relationships: z.array(zSessionRelationship).optional(),
2169
+ rootSessionId: zSessionID.nullish(),
1863
2170
  schemaVersion: z.int(),
1864
2171
  sessionId: zSessionID,
1865
2172
  source: zSourceInfo,
@@ -1921,12 +2228,13 @@ export const zUsageDetail = z.object({
1921
2228
  cost: zRecordedCostDetail.nullish(),
1922
2229
  ownerId: z.string(),
1923
2230
  scope: zUsageScope,
1924
- sourceEntryRef: z.string(),
2231
+ sourceEntryRef: zSourceEntryRef,
1925
2232
  tokens: zTokenUsageDetail.nullish()
1926
2233
  });
1927
2234
  export const zToolCallDetail = z.object({
1928
2235
  arguments: z.string(),
1929
- callEntryRef: z.string().optional(),
2236
+ callEntryRef: zSourceEntryRef.optional(),
2237
+ callProvenance: zContentProvenance.nullish(),
1930
2238
  durationMs: z.int().nullish(),
1931
2239
  exitCode: z.int().nullish(),
1932
2240
  filePath: z.string().optional(),
@@ -1935,7 +2243,8 @@ export const zToolCallDetail = z.object({
1935
2243
  name: z.string(),
1936
2244
  namespace: z.string().optional(),
1937
2245
  result: z.string(),
1938
- resultEntryRef: z.string().optional(),
2246
+ resultEntryRef: zSourceEntryRef.optional(),
2247
+ resultProvenance: zContentProvenance.nullish(),
1939
2248
  toolKind: zToolCallKind.optional(),
1940
2249
  usage: zUsageDetail.nullish()
1941
2250
  });
@@ -1949,8 +2258,9 @@ export const zTurnDetail = z.object({
1949
2258
  index: z.int(),
1950
2259
  observedModel: zObservedModelID.optional(),
1951
2260
  parentIndex: z.int().nullish(),
2261
+ provenance: zContentProvenance.nullish(),
1952
2262
  role: zRole,
1953
- sourceEntryRef: z.string().optional(),
2263
+ sourceEntryRef: zSourceEntryRef.optional(),
1954
2264
  stopReason: zStopReason.nullish(),
1955
2265
  timestamp: z.iso.datetime(),
1956
2266
  tokensIn: z.int().nullish(),
@@ -1958,18 +2268,29 @@ export const zTurnDetail = z.object({
1958
2268
  toolCalls: z.array(zToolCallDetail).optional(),
1959
2269
  usage: zUsageDetail.nullish()
1960
2270
  });
2271
+ export const zEarlierHistorySection = z.object({
2272
+ nativeMetadata: z.array(zNativeMetadataRecord).optional(),
2273
+ state: zEarlierHistoryState,
2274
+ turns: z.array(zTurnDetail)
2275
+ }).strict();
1961
2276
  export const zSessionDetailPayload = z.object({
1962
2277
  childSessions: z.array(zChildSessionRef).optional(),
1963
2278
  durationMins: z.number(),
2279
+ earlierHistory: z.array(zEarlierHistorySection).optional(),
1964
2280
  endTime: z.iso.datetime(),
1965
2281
  gitBranch: z.string().optional(),
1966
2282
  gitRemote: z.string().optional(),
1967
2283
  harness: zHarness,
1968
2284
  id: z.string(),
2285
+ inputSubmissionCount: z.int().gte(0).lte(9007199254740991).optional(),
1969
2286
  model: z.string().optional(),
1970
2287
  nativeMetadata: z.array(zNativeMetadataRecord).optional(),
1971
2288
  outcome: zSessionOutcome.optional(),
2289
+ parentSessionId: zSessionID.nullish(),
1972
2290
  project: z.string().optional(),
2291
+ purpose: zSessionPurpose.optional(),
2292
+ relationships: z.array(zSessionRelationship).optional(),
2293
+ rootSessionId: zSessionID.nullish(),
1973
2294
  schemaVersion: z.string().optional(),
1974
2295
  scorecard: zSessionScorecard.nullish(),
1975
2296
  sessionOrigin: zSessionOrigin.optional(),
@@ -1984,6 +2305,39 @@ export const zSessionDetailPayload = z.object({
1984
2305
  turns: z.array(zTurnDetail).nullable(),
1985
2306
  workingDirectory: z.string().optional()
1986
2307
  });
2308
+ export const zSessionDetailReadPayload = z.object({
2309
+ childSessions: z.array(zChildSessionRef).optional(),
2310
+ durationMins: z.number().optional(),
2311
+ earlierHistory: z.array(zEarlierHistorySection).optional(),
2312
+ endTime: z.iso.datetime().optional(),
2313
+ gitBranch: z.string().optional(),
2314
+ gitRemote: z.string().optional(),
2315
+ harness: zHarness.optional(),
2316
+ id: z.string().optional(),
2317
+ inputSubmissionCount: z.int().gte(0).lte(9007199254740991).optional(),
2318
+ model: z.string().optional(),
2319
+ nativeMetadata: z.array(zNativeMetadataRecord).optional(),
2320
+ outcome: zSessionOutcome.optional(),
2321
+ parentSessionId: zSessionID.optional(),
2322
+ project: z.string().optional(),
2323
+ purpose: zSessionPurpose.optional(),
2324
+ relationshipNavigation: z.array(zSessionRelationshipNavigation).optional(),
2325
+ relationships: z.array(zSessionRelationship).optional(),
2326
+ rootSessionId: zSessionID.optional(),
2327
+ schemaVersion: z.string().optional(),
2328
+ scorecard: zSessionScorecard.optional(),
2329
+ sessionOrigin: zSessionOrigin.optional(),
2330
+ source: z.string().optional(),
2331
+ startTime: z.iso.datetime().optional(),
2332
+ status: z.string().optional(),
2333
+ tokensIn: z.int().optional(),
2334
+ tokensOut: z.int().optional(),
2335
+ toolCallCount: z.int().optional(),
2336
+ totalTokens: z.int().optional(),
2337
+ turnCount: z.int().optional(),
2338
+ turns: z.array(zTurnDetail).nullish(),
2339
+ workingDirectory: z.string().optional()
2340
+ });
1987
2341
  export const zTranscriptContent = z.object({
1988
2342
  contractVersion: z.string(),
1989
2343
  kind: zContentKind,
@@ -2140,6 +2494,19 @@ export const zVillageLinkRepositoryRequest = z.object({
2140
2494
  name: z.string(),
2141
2495
  owner: z.string()
2142
2496
  });
2497
+ export const zVillageListTranscriptAttestation = z.object({
2498
+ attestation_type: z.string(),
2499
+ created_at: z.iso.datetime(),
2500
+ org_login: z.string(),
2501
+ transcript_id: zTranscriptID
2502
+ });
2503
+ export const zVillageMetadataUserOrganization = z.object({
2504
+ avatar_url: z.string().nullable(),
2505
+ fetched_at: z.iso.datetime(),
2506
+ org_id: 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' }),
2507
+ org_login: z.string(),
2508
+ visible: z.boolean()
2509
+ });
2143
2510
  /**
2144
2511
  * Village Project Name Source
2145
2512
  *
@@ -2270,6 +2637,7 @@ export const zVillageContributableTranscript = z.object({
2270
2637
  already_shared: z.boolean(),
2271
2638
  git_branch: z.string().nullable(),
2272
2639
  id: zTranscriptID,
2640
+ input_submission_count: z.int().gte(0).lte(9007199254740991).optional(),
2273
2641
  local_id: zSessionID,
2274
2642
  model_provider: z.string(),
2275
2643
  parent_session_id: zSessionID.nullable(),
@@ -2277,6 +2645,9 @@ export const zVillageContributableTranscript = z.object({
2277
2645
  project_hash: zProjectHash,
2278
2646
  project_name_source: zVillageProjectNameSource,
2279
2647
  published_at: z.iso.datetime(),
2648
+ purpose: zSessionPurpose.optional(),
2649
+ relationships: z.array(zSessionRelationship).optional(),
2650
+ root_session_id: zSessionID.nullish(),
2280
2651
  session_origin: zSessionOrigin,
2281
2652
  title: z.string().nullable(),
2282
2653
  visibility: zVillageTranscriptVisibility
@@ -2330,6 +2701,14 @@ export const zVillageContributedCollective = z.object({
2330
2701
  export const zVillageContributedCollectivesResponse = z.object({
2331
2702
  collectives: z.array(zVillageContributedCollective)
2332
2703
  });
2704
+ export const zVillageEnrichedTranscriptShare = z.object({
2705
+ acceptance_mode: zVillageGroupAcceptanceMode,
2706
+ group_id: zVillageUUID,
2707
+ group_name: z.string(),
2708
+ shared_at: z.iso.datetime(),
2709
+ status: zVillageShareStatus,
2710
+ transcript_id: zTranscriptID
2711
+ });
2333
2712
  export const zVillageGroup = z.object({
2334
2713
  acceptance_mode: zVillageGroupAcceptanceMode,
2335
2714
  created_at: z.iso.datetime(),
@@ -2351,6 +2730,21 @@ export const zVillageGroupContributor = z.object({
2351
2730
  id: zVillageUUID,
2352
2731
  transcript_count: z.int().min(-2147483648, { error: 'Invalid value: Expected int32 to be >= -2147483648' }).max(2147483647, { error: 'Invalid value: Expected int32 to be <= 2147483647' })
2353
2732
  });
2733
+ export const zVillageGroupDetailRecord = z.object({
2734
+ acceptance_mode: zVillageGroupAcceptanceMode,
2735
+ created_at: z.iso.datetime(),
2736
+ created_by: zVillageUUID,
2737
+ data_access: zVillageGroupDataAccess,
2738
+ description: z.string().nullable(),
2739
+ display_members: z.boolean(),
2740
+ id: zVillageUUID,
2741
+ linked_github_org: z.string().nullable(),
2742
+ name: z.string(),
2743
+ post_prompts_check: z.boolean().nullish(),
2744
+ prompts_check_mode: zVillagePromptsCheckMode.nullish(),
2745
+ transcript_deletion_policy: zVillageTranscriptDeletionPolicy,
2746
+ updated_at: z.iso.datetime()
2747
+ });
2354
2748
  export const zVillageGroupMember = z.object({
2355
2749
  avatar_url: z.string().nullable(),
2356
2750
  display_name: z.string().nullable(),
@@ -2377,6 +2771,7 @@ export const zVillageGroupTranscript = z.object({
2377
2771
  harness_version: z.string().nullable(),
2378
2772
  id: zTranscriptID,
2379
2773
  ingested_at: z.iso.datetime().nullable(),
2774
+ input_submission_count: z.int().gte(0).lte(9007199254740991).optional(),
2380
2775
  license_id: zLicense.nullable(),
2381
2776
  lines_changed: z.int().nullable(),
2382
2777
  local_id: zSessionID,
@@ -2407,8 +2802,11 @@ export const zVillageGroupTranscript = z.object({
2407
2802
  project_name_source: zVillageProjectNameSource,
2408
2803
  project_remote_label: z.string(),
2409
2804
  published_at: z.iso.datetime(),
2805
+ purpose: zSessionPurpose.optional(),
2806
+ relationships: z.array(zSessionRelationship).optional(),
2410
2807
  retry_loops: z.int().nullable(),
2411
2808
  retry_tokens_wasted: z.int().nullable(),
2809
+ root_session_id: zSessionID.nullish(),
2412
2810
  schema_version: z.string(),
2413
2811
  scope_breadth: z.int().nullable(),
2414
2812
  session_end: z.iso.datetime().nullable(),
@@ -2433,7 +2831,7 @@ export const zVillageGroupTranscript = z.object({
2433
2831
  export const zVillageGroupDetailResponse = z.object({
2434
2832
  can_read: z.boolean(),
2435
2833
  contributors: z.array(zVillageGroupContributor),
2436
- group: zVillageGroup,
2834
+ group: zVillageGroupDetailRecord,
2437
2835
  members: z.array(zVillageGroupMember),
2438
2836
  models: z.array(zVillageGroupModelBreakdown),
2439
2837
  pending_members: z.array(zVillageGroupMember).optional(),
@@ -2455,8 +2853,14 @@ export const zVillageLinkedRepository = z.object({
2455
2853
  export const zVillageLinkedRepositoriesResponse = z.object({
2456
2854
  repositories: z.array(zVillageLinkedRepository)
2457
2855
  });
2856
+ export const zVillageListUserOrganization = z.object({
2857
+ avatar_url: z.string().nullable(),
2858
+ org_login: z.string(),
2859
+ user_id: zVillageUUID
2860
+ });
2458
2861
  export const zVillagePendingShare = z.object({
2459
2862
  branch: z.string().nullable(),
2863
+ input_submission_count: z.int().gte(0).lte(9007199254740991).optional(),
2460
2864
  local_id: zSessionID,
2461
2865
  model_provider: z.string(),
2462
2866
  owner_id: zVillageUUID,
@@ -2465,6 +2869,9 @@ export const zVillagePendingShare = z.object({
2465
2869
  parent_session_id: zSessionID.nullable(),
2466
2870
  project_hash: zProjectHash,
2467
2871
  project_name: z.string().nullable(),
2872
+ purpose: zSessionPurpose.optional(),
2873
+ relationships: z.array(zSessionRelationship).optional(),
2874
+ root_session_id: zSessionID.nullish(),
2468
2875
  shared_at: z.iso.datetime(),
2469
2876
  title: z.string().nullable(),
2470
2877
  transcript_id: zTranscriptID
@@ -2506,6 +2913,10 @@ export const zVillagePullRequestAttachmentResponse = z.object({
2506
2913
  export const zVillageShareTranscriptRequest = z.object({
2507
2914
  group_ids: z.array(zVillageUUID)
2508
2915
  });
2916
+ export const zVillageTag = z.object({
2917
+ id: zVillageUUID,
2918
+ name: z.string()
2919
+ });
2509
2920
  export const zVillageTranscript = z.object({
2510
2921
  blob_size_bytes: z.int().nullable(),
2511
2922
  compute_version: z.int().nullable(),
@@ -2523,6 +2934,7 @@ export const zVillageTranscript = z.object({
2523
2934
  harness_version: z.string().nullable(),
2524
2935
  id: zTranscriptID,
2525
2936
  ingested_at: z.iso.datetime().nullable(),
2937
+ input_submission_count: z.int().gte(0).lte(9007199254740991).optional(),
2526
2938
  license_id: zLicense.nullable(),
2527
2939
  lines_changed: z.int().nullable(),
2528
2940
  local_id: zSessionID,
@@ -2550,8 +2962,11 @@ export const zVillageTranscript = z.object({
2550
2962
  project_name_source: zVillageProjectNameSource,
2551
2963
  project_remote_label: z.string(),
2552
2964
  published_at: z.iso.datetime(),
2965
+ purpose: zSessionPurpose.optional(),
2966
+ relationships: z.array(zSessionRelationship).optional(),
2553
2967
  retry_loops: z.int().nullable(),
2554
2968
  retry_tokens_wasted: z.int().nullable(),
2969
+ root_session_id: zSessionID.nullish(),
2555
2970
  schema_version: z.string(),
2556
2971
  scope_breadth: z.int().nullable(),
2557
2972
  session_end: z.iso.datetime().nullable(),
@@ -2573,6 +2988,16 @@ export const zVillageTranscript = z.object({
2573
2988
  visibility: zVillageTranscriptVisibility,
2574
2989
  within_session_reverts: z.int().nullable()
2575
2990
  });
2991
+ export const zVillageTranscriptAttestation = z.object({
2992
+ attestation_type: z.string(),
2993
+ attester_avatar: z.string().nullable(),
2994
+ attester_username: z.string(),
2995
+ created_at: z.iso.datetime(),
2996
+ id: zVillageUUID,
2997
+ note: z.string().nullable(),
2998
+ org_login: z.string(),
2999
+ transcript_id: zTranscriptID
3000
+ });
2576
3001
  export const zVillageTranscriptCollective = z.object({
2577
3002
  description: z.string().nullable(),
2578
3003
  id: zVillageUUID,
@@ -2602,6 +3027,45 @@ export const zVillageUpdateGroupRequest = z.object({
2602
3027
  export const zVillageUpdateUserSettingsRequest = z.object({
2603
3028
  preview_before_attach: z.boolean().nullish()
2604
3029
  });
3030
+ export const zVillageUser = z.object({
3031
+ avatar_url: z.string().nullable(),
3032
+ created_at: z.iso.datetime(),
3033
+ display_name: z.string().nullable(),
3034
+ github_id: 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' }),
3035
+ github_username: z.string(),
3036
+ id: zVillageUUID,
3037
+ is_discoverable: z.boolean(),
3038
+ provider: z.string(),
3039
+ provider_user_id: z.string(),
3040
+ provider_username: z.string().nullable(),
3041
+ updated_at: z.iso.datetime(),
3042
+ username_chosen: z.boolean()
3043
+ });
3044
+ export const zVillageTranscriptListRow = z.object({
3045
+ attestations: z.array(zVillageListTranscriptAttestation).nullable(),
3046
+ owner: zVillageUser,
3047
+ owner_orgs: z.array(zVillageListUserOrganization).nullable(),
3048
+ shares: z.array(zVillageEnrichedTranscriptShare).nullable(),
3049
+ tags: z.array(zVillageTag),
3050
+ transcript: zVillageTranscript
3051
+ });
3052
+ export const zVillageTranscriptListResponse = z.object({
3053
+ agent_total: z.int(),
3054
+ limit: z.int(),
3055
+ page: z.int(),
3056
+ total: z.int(),
3057
+ transcripts: z.array(zVillageTranscriptListRow)
3058
+ });
3059
+ export const zVillageTranscriptMetadataResponse = z.object({
3060
+ attestations: z.array(zVillageTranscriptAttestation),
3061
+ enriched_shares: z.array(zVillageEnrichedTranscriptShare),
3062
+ owner: zVillageUser,
3063
+ owner_orgs: z.array(zVillageMetadataUserOrganization),
3064
+ relationshipNavigation: z.array(zSessionRelationshipNavigation).optional(),
3065
+ shares: z.array(zVillageTranscriptShare),
3066
+ tags: z.array(zVillageTag),
3067
+ transcript: zVillageTranscript
3068
+ });
2605
3069
  export const zVillageUserGroup = z.object({
2606
3070
  acceptance_mode: zVillageGroupAcceptanceMode,
2607
3071
  created_at: z.iso.datetime(),
@@ -2621,12 +3085,16 @@ export const zVillageUserGroup = z.object({
2621
3085
  });
2622
3086
  export const zVillageUserGroupShare = z.object({
2623
3087
  id: zTranscriptID,
3088
+ input_submission_count: z.int().gte(0).lte(9007199254740991).optional(),
2624
3089
  local_id: zSessionID,
2625
3090
  model_name: z.string().nullable(),
2626
3091
  model_provider: z.string(),
2627
3092
  owner_id: zVillageUUID,
2628
3093
  parent_session_id: zSessionID.nullable(),
2629
3094
  published_at: z.iso.datetime(),
3095
+ purpose: zSessionPurpose.optional(),
3096
+ relationships: z.array(zSessionRelationship).optional(),
3097
+ root_session_id: zSessionID.nullish(),
2630
3098
  shared_at: z.iso.datetime(),
2631
3099
  status: zVillageShareStatus,
2632
3100
  title: z.string().nullable(),
@@ -2635,6 +3103,110 @@ export const zVillageUserGroupShare = z.object({
2635
3103
  turn_count: z.int().nullable(),
2636
3104
  visibility: zVillageTranscriptVisibility
2637
3105
  });
3106
+ export const zVillageSessionRow = z.object({
3107
+ collective: zVillageGroupTranscript.nullish(),
3108
+ contributable: zVillageContributableTranscript.nullish(),
3109
+ myShare: zVillageUserGroupShare.nullish(),
3110
+ pending: zVillagePendingShare.nullish(),
3111
+ session: zVillageTranscript
3112
+ }).superRefine((value, context) => {
3113
+ const fail = (reason) => context.addIssue({ code: "custom", message: "schema.zVillageSessionRow during grouped read validation: " + reason });
3114
+ const s = value.session;
3115
+ const arms = [value.collective, value.pending, value.myShare, value.contributable].filter(v => v != null);
3116
+ if (arms.length > 1)
3117
+ fail("multiple route arms supplied; retain the originating route only");
3118
+ const equal = (a, b) => {
3119
+ if (a === b)
3120
+ return true;
3121
+ if (a === null || b === null || typeof a !== "object" || typeof b !== "object")
3122
+ return false;
3123
+ const left = a, right = b;
3124
+ return Object.keys(left).length === Object.keys(right).length && Object.keys(left).every(k => Object.hasOwn(right, k) && equal(left[k], right[k]));
3125
+ };
3126
+ const check = (v, keys, aliases = {}) => {
3127
+ if (v == null)
3128
+ return;
3129
+ const row = v, session = s;
3130
+ for (const key of keys)
3131
+ if (!equal(row[key], session[aliases[key] ?? key]))
3132
+ fail("route identity or metric mirrors disagree; derive both from the same row");
3133
+ };
3134
+ const graph = ["parent_session_id", "root_session_id", "purpose", "relationships", "input_submission_count"];
3135
+ check(value.collective, [...graph, "id", "owner_id", "local_id", "title", "description", "visibility", "model_provider", "model_name", "harness_version", "turn_count", "token_count", "tokens_in", "tokens_out", "duration_ms", "project_hash", "project_name", "project_display_name", "project_name_source", "project_remote_label", "git_branch", "session_origin"]);
3136
+ check(value.pending, [...graph, "transcript_id", "owner_id", "local_id", "title", "model_provider", "project_hash", "project_name", "branch"], { transcript_id: "id", branch: "git_branch" });
3137
+ check(value.myShare, [...graph, "id", "owner_id", "local_id", "title", "visibility", "published_at", "model_provider", "model_name", "turn_count", "tokens_in", "tokens_out"]);
3138
+ check(value.contributable, [...graph, "id", "local_id", "title", "visibility", "model_provider", "project_hash", "project_display_name", "project_name_source", "git_branch", "published_at", "session_origin"]);
3139
+ });
3140
+ export const zVillageSessionListItem = z.object({
3141
+ context: zHelperContextSummary.nullish(),
3142
+ helperGroups: z.array(zHelperGroupSummary).optional(),
3143
+ kind: zSessionListItemKind,
3144
+ transcript: zVillageSessionRow.nullish()
3145
+ }).superRefine((value, context) => {
3146
+ const fail = (reason) => context.addIssue({ code: "custom", message: "schema.zVillageSessionListItem during grouped read validation: " + reason });
3147
+ if ((value.kind === "transcript") !== (value.transcript != null) || (value.kind === "context_container") !== (value.context != null))
3148
+ fail("kind must select exactly one matching transcript/context arm; omit the other arm");
3149
+ const groups = new Set();
3150
+ for (const group of value.helperGroups ?? []) {
3151
+ if (groups.has(group.groupId))
3152
+ fail("duplicate groupId prevents independent paging; emit each immediate group once");
3153
+ groups.add(group.groupId);
3154
+ }
3155
+ });
3156
+ export const zVillageHelperMembersPayload = z.object({
3157
+ limit: z.int().gte(1).lte(9007199254740991),
3158
+ members: z.array(zVillageSessionListItem.and(z.object({
3159
+ context: z.null().optional(),
3160
+ kind: z.enum(['transcript']).optional(),
3161
+ transcript: zVillageSessionRow
3162
+ }))),
3163
+ page: z.int().gte(1).lte(9007199254740991),
3164
+ total: z.int().gte(0).lte(9007199254740991)
3165
+ }).superRefine((value, context) => {
3166
+ const fail = (reason) => context.addIssue({ code: "custom", message: "schema.zVillageHelperMembersPayload during grouped read validation: " + reason });
3167
+ if (value.members.length > value.limit || value.members.length > value.total)
3168
+ fail("member count exceeds page limit or direct total; count direct saved helpers before paging");
3169
+ const ids = new Set();
3170
+ const groups = new Set();
3171
+ for (const member of value.members) {
3172
+ if (member.kind !== "transcript" || member.transcript == null || member.context != null) {
3173
+ fail("members must be transcript items, never context containers; preserve nested groups on the item");
3174
+ continue;
3175
+ }
3176
+ const id = member.transcript.session.id;
3177
+ if (ids.has(id))
3178
+ fail("duplicate member identity would double count a saved helper; emit each transcript once");
3179
+ ids.add(id);
3180
+ for (const group of member.helperGroups ?? []) {
3181
+ if (groups.has(group.groupId))
3182
+ fail("groupId appears under multiple members; emit each immediate-owner group once");
3183
+ groups.add(group.groupId);
3184
+ }
3185
+ }
3186
+ });
3187
+ export const zVillageSessionListPayload = z.object({
3188
+ helperThreadTotal: z.int().gte(0).lte(9007199254740991),
3189
+ items: z.array(zVillageSessionListItem),
3190
+ limit: z.int().gte(1).lte(9007199254740991),
3191
+ ordinarySessionTotal: z.int().gte(0).lte(9007199254740991),
3192
+ page: z.int().gte(1).lte(9007199254740991),
3193
+ totalItems: z.int().gte(0).lte(9007199254740991)
3194
+ });
3195
+ export const zVillageGroupedContributableResponse = z.object({
3196
+ groupId: zVillageUUID,
3197
+ transcriptList: zVillageSessionListPayload
3198
+ });
3199
+ export const zVillageGroupedGroupDetailResponse = z.object({
3200
+ can_read: z.boolean(),
3201
+ contributors: z.array(zVillageGroupContributor),
3202
+ group: zVillageGroupDetailRecord,
3203
+ members: z.array(zVillageGroupMember),
3204
+ models: z.array(zVillageGroupModelBreakdown),
3205
+ pending_members: z.array(zVillageGroupMember).optional(),
3206
+ stats: zVillageGroupTranscriptStats,
3207
+ transcriptList: zVillageSessionListPayload,
3208
+ your_role: zVillageGroupViewerRole
3209
+ });
2638
3210
  export const zVillageUserSettings = z.object({
2639
3211
  preview_before_attach: z.boolean()
2640
3212
  });