@peasant-labs/schema 0.1.0-rc6 → 0.1.0-rc8

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.
@@ -89,6 +89,98 @@ export const zAnnotatorSummary = z.object({
89
89
  providerKey: z.string().nullish(),
90
90
  status: z.string()
91
91
  });
92
+ /**
93
+ * Association Conclusion
94
+ *
95
+ * Producer-supplied conclusion for a session-to-commit association: confirmed or candidate
96
+ */
97
+ export const zAssociationConclusion = z.enum(['confirmed', 'candidate']);
98
+ /**
99
+ * Association Evidence Kind
100
+ *
101
+ * Atomic observation supporting a session-to-commit association
102
+ */
103
+ export const zAssociationEvidenceKind = z.enum([
104
+ 'recorded_commit',
105
+ 'touched_file',
106
+ 'branch_membership',
107
+ 'time_window'
108
+ ]);
109
+ export const zAssociationEvidenceObservation = z.object({
110
+ branchName: z.string().nullish(),
111
+ kind: zAssociationEvidenceKind,
112
+ recordedCommitHash: z.string().nullish(),
113
+ touchedFilePath: z.string().nullish(),
114
+ windowEndMs: z.int().nullish(),
115
+ windowStartMs: z.int().nullish()
116
+ }).superRefine((value, context) => {
117
+ const isAbsent = (detail) => detail === undefined || detail === null;
118
+ const isGoWhitespace = (codePoint) => (codePoint >= 0x0009 && codePoint <= 0x000D)
119
+ || codePoint === 0x0020
120
+ || codePoint === 0x0085
121
+ || codePoint === 0x00A0
122
+ || codePoint === 0x1680
123
+ || (codePoint >= 0x2000 && codePoint <= 0x200A)
124
+ || codePoint === 0x2028
125
+ || codePoint === 0x2029
126
+ || codePoint === 0x202F
127
+ || codePoint === 0x205F
128
+ || codePoint === 0x3000;
129
+ const hasNonEmptyString = (detail) => {
130
+ if (typeof detail !== "string")
131
+ return false;
132
+ for (const character of detail) {
133
+ const codePoint = character.codePointAt(0);
134
+ if (codePoint !== undefined && !isGoWhitespace(codePoint))
135
+ return true;
136
+ }
137
+ return false;
138
+ };
139
+ const hasValidTouchedFilePath = (detail) => typeof detail === "string"
140
+ && detail !== ""
141
+ && !detail.startsWith("/")
142
+ && !detail.startsWith("\\")
143
+ && !detail.includes("\\")
144
+ && !/^[A-Za-z]:\//.test(detail)
145
+ && !detail.split("/").some((segment) => segment === "" || segment === "." || segment === "..");
146
+ const addIssue = (message) => context.addIssue({ code: "custom", message });
147
+ switch (value.kind) {
148
+ case "recorded_commit":
149
+ if (!hasNonEmptyString(value.recordedCommitHash))
150
+ addIssue("recorded_commit evidence requires a non-empty recordedCommitHash");
151
+ if (!isAbsent(value.touchedFilePath) || !isAbsent(value.branchName) || !isAbsent(value.windowStartMs) || !isAbsent(value.windowEndMs))
152
+ addIssue("recorded_commit evidence must not populate another detail arm");
153
+ return;
154
+ case "touched_file":
155
+ if (!hasValidTouchedFilePath(value.touchedFilePath))
156
+ addIssue("touched_file evidence requires a non-empty repository-relative touchedFilePath");
157
+ if (!isAbsent(value.recordedCommitHash) || !isAbsent(value.branchName) || !isAbsent(value.windowStartMs) || !isAbsent(value.windowEndMs))
158
+ addIssue("touched_file evidence must not populate another detail arm");
159
+ return;
160
+ case "branch_membership":
161
+ if (!hasNonEmptyString(value.branchName))
162
+ addIssue("branch_membership evidence requires a non-empty branchName");
163
+ if (!isAbsent(value.recordedCommitHash) || !isAbsent(value.touchedFilePath) || !isAbsent(value.windowStartMs) || !isAbsent(value.windowEndMs))
164
+ addIssue("branch_membership evidence must not populate another detail arm");
165
+ return;
166
+ case "time_window":
167
+ if (value.windowStartMs === undefined || value.windowStartMs === null || value.windowEndMs === undefined || value.windowEndMs === null) {
168
+ addIssue("time_window evidence requires windowStartMs and windowEndMs");
169
+ }
170
+ else if (value.windowStartMs > value.windowEndMs) {
171
+ addIssue("time_window evidence requires windowStartMs less than or equal to windowEndMs");
172
+ }
173
+ if (!isAbsent(value.recordedCommitHash) || !isAbsent(value.touchedFilePath) || !isAbsent(value.branchName))
174
+ addIssue("time_window evidence must not populate another detail arm");
175
+ return;
176
+ }
177
+ });
178
+ /**
179
+ * Association ID
180
+ *
181
+ * Opaque durable Peasant identifier for one session-to-commit association
182
+ */
183
+ export const zAssociationID = z.string().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/);
92
184
  export const zBatchCreateAnnotationsErrorResponse = z.object({
93
185
  error: z.string(),
94
186
  failingIndex: z.int()
@@ -189,6 +281,16 @@ export const zCommitInfo = z.object({
189
281
  hash: z.string(),
190
282
  message: z.string()
191
283
  });
284
+ /**
285
+ * Confidence
286
+ *
287
+ * Strength of evidence behind a derived relationship: high, medium, or low
288
+ */
289
+ export const zConfidence = z.enum([
290
+ 'high',
291
+ 'medium',
292
+ 'low'
293
+ ]);
192
294
  /**
193
295
  * Content Kind
194
296
  *
@@ -381,6 +483,30 @@ export const zHealthResponse = z.object({
381
483
  * Sanitized, filesystem-safe identifier derived from git remote; contains only [a-zA-Z0-9._<>-]
382
484
  */
383
485
  export const zHostSlug = z.string().regex(/^[a-zA-Z0-9._<>-]+$/);
486
+ export const zInsightClassification = z.object({
487
+ category: z.string(),
488
+ cause: z.string(),
489
+ resolution: z.string(),
490
+ severityLocus: z.string(),
491
+ severityScope: z.string()
492
+ });
493
+ /**
494
+ * Insight Kind
495
+ *
496
+ * What a SessionInsight observed: a decision, friction, an unusual rate elevation, or a retry loop
497
+ */
498
+ export const zInsightKind = z.enum([
499
+ 'decision',
500
+ 'friction',
501
+ 'unusual',
502
+ 'retry_loop'
503
+ ]);
504
+ /**
505
+ * Insight Provenance
506
+ *
507
+ * How a SessionInsight was produced: mechanical (rule-derived) or mined
508
+ */
509
+ export const zInsightProvenance = z.enum(['mechanical', 'mined']);
384
510
  /**
385
511
  * Interaction Type
386
512
  *
@@ -417,26 +543,6 @@ export const zMapNodeKind = z.enum([
417
543
  'package',
418
544
  'file'
419
545
  ]);
420
- export const zMapNode = z.object({
421
- effortDensity: z.number(),
422
- fileCount: z.int(),
423
- id: z.string(),
424
- kind: zMapNodeKind,
425
- language: z.string().optional(),
426
- layer: z.int(),
427
- loc: z.int(),
428
- name: z.string(),
429
- order: z.int(),
430
- parent: z.string().optional(),
431
- recordedFiles: z.int(),
432
- totalFiles: z.int(),
433
- touchCount: z.int()
434
- });
435
- export const zMapSlice = z.object({
436
- activityEdges: z.array(zActivityEdge).nullable(),
437
- nodes: z.array(zMapNode).nullable(),
438
- structureEdges: z.array(zMapEdge).nullable()
439
- });
440
546
  /**
441
547
  * Message Type
442
548
  *
@@ -483,18 +589,6 @@ export const zModelInfo = z.object({
483
589
  * SHA-256 hex digest of the project's origin URL or local path
484
590
  */
485
591
  export const zProjectHash = z.string().regex(/^[0-9a-f]{64}$/).brand();
486
- export const zMapGraphPayload = z.object({
487
- activityEdges: z.array(zActivityEdge).nullable(),
488
- atCommit: z.string().optional(),
489
- 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' }),
490
- nodes: z.array(zMapNode).nullable(),
491
- parsedLanguages: z.array(z.string()).nullable(),
492
- projectHash: zProjectHash,
493
- repoFound: z.boolean(),
494
- repoPath: z.string().optional(),
495
- structureEdges: z.array(zMapEdge).nullable(),
496
- violations: z.array(zEdgeViolation).nullable()
497
- });
498
592
  export const zProjectContext = z.object({
499
593
  filePath: z.string().optional(),
500
594
  hash: zProjectHash,
@@ -530,6 +624,66 @@ export const zPublishResponse = z.object({
530
624
  transcriptId: z.string(),
531
625
  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' })
532
626
  });
627
+ /**
628
+ * Read Attribution State
629
+ *
630
+ * Whether per-file read attribution is recoverable for a node's editing sessions: complete, partial, or unavailable
631
+ */
632
+ export const zReadAttributionState = z.enum([
633
+ 'complete',
634
+ 'partial',
635
+ 'unavailable'
636
+ ]);
637
+ /**
638
+ * Read State Grade
639
+ *
640
+ * Ordinal explicit read-state act: none, viewed, reviewed, or reviewed_in_detail
641
+ */
642
+ export const zReadStateGrade = z.enum([
643
+ 'none',
644
+ 'viewed',
645
+ 'reviewed',
646
+ 'reviewed_in_detail'
647
+ ]);
648
+ export const zMapNode = z.object({
649
+ agentEditedCount: z.int(),
650
+ attributedRegionCount: z.int(),
651
+ changedRegionCount: z.int(),
652
+ effortDensity: z.number(),
653
+ fileCount: z.int(),
654
+ id: z.string(),
655
+ kind: zMapNodeKind,
656
+ language: z.string().optional(),
657
+ layer: z.int(),
658
+ loc: z.int(),
659
+ name: z.string(),
660
+ order: z.int(),
661
+ parent: z.string().optional(),
662
+ readAttribution: zReadAttributionState,
663
+ readCount: z.int(),
664
+ readState: zReadStateGrade,
665
+ recordedFiles: z.int(),
666
+ reviewedRegionCount: z.int(),
667
+ totalFiles: z.int(),
668
+ touchCount: z.int()
669
+ });
670
+ export const zMapGraphPayload = z.object({
671
+ activityEdges: z.array(zActivityEdge).nullable(),
672
+ atCommit: z.string().optional(),
673
+ 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' }),
674
+ nodes: z.array(zMapNode).nullable(),
675
+ parsedLanguages: z.array(z.string()).nullable(),
676
+ projectHash: zProjectHash,
677
+ repoFound: z.boolean(),
678
+ repoPath: z.string().optional(),
679
+ structureEdges: z.array(zMapEdge).nullable(),
680
+ violations: z.array(zEdgeViolation).nullable()
681
+ });
682
+ export const zMapSlice = z.object({
683
+ activityEdges: z.array(zActivityEdge).nullable(),
684
+ nodes: z.array(zMapNode).nullable(),
685
+ structureEdges: z.array(zMapEdge).nullable()
686
+ });
533
687
  export const zRedactionInfo = z.object({
534
688
  applied: z.boolean(),
535
689
  content_hash_at_redact: z.string().optional(),
@@ -543,6 +697,29 @@ export const zReviewSuggestion = z.object({
543
697
  path: z.string(),
544
698
  suggestedPrompt: z.string()
545
699
  });
700
+ /**
701
+ * Rewrite Method
702
+ *
703
+ * Mechanism the resolver used to map a ghost commit to its successor
704
+ */
705
+ export const zRewriteMethod = z.enum([
706
+ 'hash',
707
+ 'patch_id',
708
+ 'author_identity',
709
+ 'message_embedded',
710
+ 'temporal',
711
+ 'none'
712
+ ]);
713
+ /**
714
+ * Rewrite Resolution
715
+ *
716
+ * Whether a ledger-observed commit hash is live, was rewritten, or could not be resolved
717
+ */
718
+ export const zRewriteResolution = z.enum([
719
+ 'live',
720
+ 'rewritten',
721
+ 'unresolved'
722
+ ]);
546
723
  /**
547
724
  * Role
548
725
  *
@@ -601,18 +778,95 @@ export const zServerMessage = z.object({
601
778
  * Unique session identifier (UUID, agent-{hex}, ses_{id}, sess_{id} (ACP), or msg_{id})
602
779
  */
603
780
  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]+)$/);
781
+ export const zInsightEvidence = z.object({
782
+ commitHash: z.string().optional(),
783
+ entryIndex: z.int().nullish(),
784
+ file: z.string().optional(),
785
+ sessionId: zSessionID
786
+ });
787
+ export const zSessionAssociation = z.object({
788
+ conclusion: zAssociationConclusion,
789
+ confidence: zConfidence,
790
+ evidence: z.array(zAssociationEvidenceObservation).min(1),
791
+ id: zAssociationID,
792
+ sessionId: z.string().min(1)
793
+ }).superRefine((value, context) => {
794
+ const kindOrder = ["recorded_commit", "touched_file", "branch_membership", "time_window"];
795
+ const compareStrings = (left, right) => {
796
+ const leftBytes = new TextEncoder().encode(left);
797
+ const rightBytes = new TextEncoder().encode(right);
798
+ const sharedLength = Math.min(leftBytes.length, rightBytes.length);
799
+ for (let index = 0; index < sharedLength; index += 1) {
800
+ const leftByte = leftBytes[index];
801
+ const rightByte = rightBytes[index];
802
+ if (leftByte < rightByte)
803
+ return -1;
804
+ if (leftByte > rightByte)
805
+ return 1;
806
+ }
807
+ return compareNumbers(leftBytes.length, rightBytes.length);
808
+ };
809
+ const compareNumbers = (left, right) => left < right ? -1 : left > right ? 1 : 0;
810
+ const compareObservations = (left, right) => {
811
+ const leftKindOrder = kindOrder.indexOf(left.kind);
812
+ const rightKindOrder = kindOrder.indexOf(right.kind);
813
+ if (leftKindOrder !== rightKindOrder)
814
+ return compareNumbers(leftKindOrder, rightKindOrder);
815
+ switch (left.kind) {
816
+ case "recorded_commit": return compareStrings(typeof left.recordedCommitHash === "string" ? left.recordedCommitHash : "", typeof right.recordedCommitHash === "string" ? right.recordedCommitHash : "");
817
+ case "touched_file": return compareStrings(typeof left.touchedFilePath === "string" ? left.touchedFilePath : "", typeof right.touchedFilePath === "string" ? right.touchedFilePath : "");
818
+ case "branch_membership": return compareStrings(typeof left.branchName === "string" ? left.branchName : "", typeof right.branchName === "string" ? right.branchName : "");
819
+ case "time_window": {
820
+ const startOrder = compareNumbers(left.windowStartMs ?? 0, right.windowStartMs ?? 0);
821
+ return startOrder === 0 ? compareNumbers(left.windowEndMs ?? 0, right.windowEndMs ?? 0) : startOrder;
822
+ }
823
+ }
824
+ return 0;
825
+ };
826
+ for (let index = 1; index < value.evidence.length; index += 1) {
827
+ const previous = value.evidence[index - 1];
828
+ const current = value.evidence[index];
829
+ if (previous === undefined || current === undefined)
830
+ continue;
831
+ if (compareObservations(previous, current) >= 0) {
832
+ context.addIssue({ code: "custom", message: "association evidence must be duplicate-free and in canonical kind/detail order" });
833
+ }
834
+ }
835
+ });
604
836
  export const zCommitRef = z.object({
837
+ associations: z.array(zSessionAssociation),
605
838
  hasSession: z.boolean(),
606
839
  hash: z.string(),
607
840
  sessionIds: z.array(zSessionID),
608
841
  subject: z.string(),
609
842
  timeMs: z.int().nullish()
610
843
  });
844
+ export const zRewrittenCommit = z.object({
845
+ associations: z.array(zSessionAssociation),
846
+ authorTimeMs: z.int().nullish(),
847
+ confidence: zConfidence,
848
+ ghostHash: z.string(),
849
+ method: zRewriteMethod,
850
+ resolution: zRewriteResolution,
851
+ sessionIds: z.array(zSessionID),
852
+ subject: z.string(),
853
+ successorHash: z.string().nullish()
854
+ });
611
855
  export const zSessionIdentity = z.object({
612
856
  parentUuid: zSessionID.nullish(),
613
857
  schemaVersion: z.int(),
614
858
  sessionId: zSessionID
615
859
  });
860
+ export const zSessionInsight = z.object({
861
+ classification: zInsightClassification.nullish(),
862
+ confidence: zConfidence,
863
+ evidence: z.array(zInsightEvidence),
864
+ kind: zInsightKind,
865
+ provenance: zInsightProvenance,
866
+ subjects: z.array(z.string()),
867
+ summary: z.string().optional(),
868
+ title: z.string()
869
+ });
616
870
  /**
617
871
  * Session Outcome
618
872
  *
@@ -742,13 +996,15 @@ export const zSubagentRef = z.object({
742
996
  /**
743
997
  * Target Kind
744
998
  *
745
- * What is being annotated: session-level, entry-level (turn/tool call), meta-annotation, or project-level
999
+ * 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
746
1000
  */
747
1001
  export const zTargetKind = z.enum([
748
1002
  'session',
749
1003
  'entry',
750
1004
  'annotation',
751
- 'project'
1005
+ 'project',
1006
+ 'file_version',
1007
+ 'association'
752
1008
  ]);
753
1009
  export const zAnnotationPushItem = z.object({
754
1010
  annotationId: z.string().nullish(),
@@ -781,14 +1037,74 @@ export const zAnnotationSummary = z.object({
781
1037
  reason: z.string().nullish(),
782
1038
  supersededBy: z.string().nullish(),
783
1039
  targetAnnotationId: z.string().nullish(),
1040
+ targetAssociationId: zAssociationID.nullish(),
1041
+ targetContentHash: z.string().nullish(),
784
1042
  targetEntryEndIndex: z.int().nullish(),
785
1043
  targetEntryIndex: z.int().nullish(),
1044
+ targetFilePath: z.string().nullish(),
786
1045
  targetKind: zTargetKind,
787
1046
  targetProjectHash: zProjectHash.nullish(),
788
1047
  targetSessionId: z.string().nullish(),
789
1048
  typeId: z.string(),
790
1049
  typeName: z.string(),
791
1050
  value: z.string()
1051
+ }).superRefine((value, context) => {
1052
+ const isPresent = (detail) => detail !== undefined && detail !== null;
1053
+ const hasNonEmptyString = (detail) => typeof detail === "string" && detail !== "";
1054
+ const hasOnly = (allowed) => {
1055
+ const targetFields = [
1056
+ ["targetAssociationId", value.targetAssociationId],
1057
+ ["targetSessionId", value.targetSessionId],
1058
+ ["targetEntryIndex", value.targetEntryIndex],
1059
+ ["targetEntryEndIndex", value.targetEntryEndIndex],
1060
+ ["targetAnnotationId", value.targetAnnotationId],
1061
+ ["targetProjectHash", value.targetProjectHash],
1062
+ ["targetFilePath", value.targetFilePath],
1063
+ ["targetContentHash", value.targetContentHash]
1064
+ ];
1065
+ return targetFields.every(([name, detail]) => allowed.includes(name) || !isPresent(detail));
1066
+ };
1067
+ const addIssue = (message) => context.addIssue({ code: "custom", message });
1068
+ switch (value.targetKind) {
1069
+ case "association":
1070
+ if (!isPresent(value.targetAssociationId))
1071
+ addIssue("association annotations require targetAssociationId");
1072
+ if (!hasOnly(["targetAssociationId"]))
1073
+ addIssue("association annotations must not mix target arms");
1074
+ return;
1075
+ case "session":
1076
+ if (!hasNonEmptyString(value.targetSessionId))
1077
+ addIssue("session annotations require a non-empty targetSessionId");
1078
+ if (!hasOnly(["targetSessionId"]))
1079
+ addIssue("session annotations must not mix target arms");
1080
+ return;
1081
+ case "entry":
1082
+ if (!hasNonEmptyString(value.targetSessionId) || !isPresent(value.targetEntryIndex))
1083
+ addIssue("entry annotations require targetSessionId and targetEntryIndex");
1084
+ if (!hasOnly(["targetSessionId", "targetEntryIndex", "targetEntryEndIndex"]))
1085
+ addIssue("entry annotations must not mix target arms");
1086
+ if (value.targetEntryIndex !== undefined && value.targetEntryIndex !== null && value.targetEntryEndIndex !== undefined && value.targetEntryEndIndex !== null && value.targetEntryEndIndex <= value.targetEntryIndex)
1087
+ addIssue("entry annotation targetEntryEndIndex must be greater than targetEntryIndex");
1088
+ return;
1089
+ case "annotation":
1090
+ if (!hasNonEmptyString(value.targetAnnotationId))
1091
+ addIssue("annotation targets require a non-empty targetAnnotationId");
1092
+ if (!hasOnly(["targetAnnotationId"]))
1093
+ addIssue("annotation targets must not mix target arms");
1094
+ return;
1095
+ case "project":
1096
+ if (!isPresent(value.targetProjectHash))
1097
+ addIssue("project annotations require targetProjectHash");
1098
+ if (!hasOnly(["targetProjectHash"]))
1099
+ addIssue("project annotations must not mix target arms");
1100
+ return;
1101
+ case "file_version":
1102
+ if (!hasNonEmptyString(value.targetFilePath) || !hasNonEmptyString(value.targetContentHash))
1103
+ addIssue("file_version annotations require non-empty targetFilePath and targetContentHash");
1104
+ if (!hasOnly(["targetFilePath", "targetContentHash"]))
1105
+ addIssue("file_version annotations must not mix target arms");
1106
+ return;
1107
+ }
792
1108
  });
793
1109
  export const zAnnotationsPayload = z.object({
794
1110
  annotations: z.array(zAnnotationSummary).nullable(),
@@ -809,8 +1125,11 @@ export const zPullAnnotation = z.object({
809
1125
  reason: z.string().nullish(),
810
1126
  supersededBy: z.string().nullish(),
811
1127
  targetAnnotationId: z.string().nullish(),
1128
+ targetAssociationId: zAssociationID.optional(),
1129
+ targetContentHash: z.string().nullish(),
812
1130
  targetEntryEndIndex: z.int().nullish(),
813
1131
  targetEntryIndex: z.int().nullish(),
1132
+ targetFilePath: z.string().nullish(),
814
1133
  targetKind: zTargetKind.optional(),
815
1134
  targetProjectHash: zProjectHash.optional(),
816
1135
  targetSessionId: z.string().nullish(),
@@ -852,6 +1171,7 @@ export const zTaskSummary = z.object({
852
1171
  labels: z.array(z.string()).nullable(),
853
1172
  outcome: z.string().optional(),
854
1173
  readCount: z.int(),
1174
+ readFiles: z.array(z.string()),
855
1175
  retryLoop: z.boolean(),
856
1176
  sessionId: z.string(),
857
1177
  startMs: z.int().nullish(),
@@ -868,6 +1188,7 @@ export const zChangeSession = z.object({
868
1188
  export const zMapNodeDetailPayload = z.object({
869
1189
  costUsd: z.number().nullish(),
870
1190
  dependsOn: z.array(z.string()).nullable(),
1191
+ insights: z.array(zSessionInsight),
871
1192
  kind: zMapNodeKind,
872
1193
  language: z.string().optional(),
873
1194
  lastTouchMs: z.int().nullish(),
@@ -877,6 +1198,7 @@ export const zMapNodeDetailPayload = z.object({
877
1198
  recentCommits: z.array(zCommitRef).nullable(),
878
1199
  recordedFiles: z.int(),
879
1200
  retryLoops: z.int(),
1201
+ rewrittenCommits: z.array(zRewrittenCommit),
880
1202
  sessionCount: z.int(),
881
1203
  shapedBy: z.array(zTaskSummary).nullable(),
882
1204
  taskCount: z.int(),
@@ -901,6 +1223,7 @@ export const zReviewListPayload = z.object({
901
1223
  projectHash: zProjectHash,
902
1224
  recentCommits: z.array(zCommitRef),
903
1225
  repoFound: z.boolean(),
1226
+ rewrittenCommits: z.array(zRewrittenCommit),
904
1227
  sessions: z.array(zTimelineSessionRef)
905
1228
  });
906
1229
  export const zTimestampInfo = z.object({
@@ -1091,6 +1414,7 @@ export const zChangeDetailPayload = z.object({
1091
1414
  defaultBranch: z.string(),
1092
1415
  files: z.array(zFileChange).nullable(),
1093
1416
  frictions: z.array(zFrictionCluster).nullable(),
1417
+ insights: z.array(zSessionInsight),
1094
1418
  linesAdded: z.int(),
1095
1419
  linesRemoved: z.int(),
1096
1420
  newEdges: z.array(zMapEdge).nullable(),
@@ -3,9 +3,12 @@ import { type AnnotationDatatype as AnnotationDatatypeContract } from "./contrac
3
3
  import { type AnnotationPushStatus as AnnotationPushStatusContract } from "./contract/zod.gen.js";
4
4
  import { type AnnotationStatus as AnnotationStatusContract } from "./contract/zod.gen.js";
5
5
  import { type AnnotatorKind as AnnotatorKindContract } from "./contract/zod.gen.js";
6
+ import { type AssociationConclusion as AssociationConclusionContract } from "./contract/zod.gen.js";
7
+ import { type AssociationEvidenceKind as AssociationEvidenceKindContract } from "./contract/zod.gen.js";
6
8
  import { type BuiltinCommand as BuiltinCommandContract } from "./contract/zod.gen.js";
7
9
  import { type ChangeBinding as ChangeBindingContract } from "./contract/zod.gen.js";
8
10
  import { type ChannelTopic as ChannelTopicContract } from "./contract/zod.gen.js";
11
+ import { type Confidence as ConfidenceContract } from "./contract/zod.gen.js";
9
12
  import { type ContentKind as ContentKindContract } from "./contract/zod.gen.js";
10
13
  import { type DecayLevel as DecayLevelContract } from "./contract/zod.gen.js";
11
14
  import { type DiffLineKind as DiffLineKindContract } from "./contract/zod.gen.js";
@@ -13,10 +16,16 @@ import { type EdgeViolationKind as EdgeViolationKindContract } from "./contract/
13
16
  import { type EntryType as EntryTypeContract } from "./contract/zod.gen.js";
14
17
  import { type FileChangeStatus as FileChangeStatusContract } from "./contract/zod.gen.js";
15
18
  import { type Harness as HarnessContract } from "./contract/zod.gen.js";
19
+ import { type InsightKind as InsightKindContract } from "./contract/zod.gen.js";
20
+ import { type InsightProvenance as InsightProvenanceContract } from "./contract/zod.gen.js";
16
21
  import { type InteractionType as InteractionTypeContract } from "./contract/zod.gen.js";
17
22
  import { type License as LicenseContract } from "./contract/zod.gen.js";
18
23
  import { type MapNodeKind as MapNodeKindContract } from "./contract/zod.gen.js";
19
24
  import { type MessageType as MessageTypeContract } from "./contract/zod.gen.js";
25
+ import { type ReadAttributionState as ReadAttributionStateContract } from "./contract/zod.gen.js";
26
+ import { type ReadStateGrade as ReadStateGradeContract } from "./contract/zod.gen.js";
27
+ import { type RewriteMethod as RewriteMethodContract } from "./contract/zod.gen.js";
28
+ import { type RewriteResolution as RewriteResolutionContract } from "./contract/zod.gen.js";
20
29
  import { type Role as RoleContract } from "./contract/zod.gen.js";
21
30
  import { type ScaleKind as ScaleKindContract } from "./contract/zod.gen.js";
22
31
  import { type SessionOutcome as SessionOutcomeContract } from "./contract/zod.gen.js";
@@ -70,6 +79,22 @@ export declare const AnnotatorKind: Readonly<{
70
79
  }>;
71
80
  export declare const AllAnnotatorKinds: readonly AnnotatorKind[];
72
81
  export declare function isAnnotatorKind(value: unknown): value is AnnotatorKind;
82
+ export type AssociationConclusion = AssociationConclusionContract;
83
+ export declare const AssociationConclusion: Readonly<{
84
+ readonly Confirmed: "candidate" | "confirmed";
85
+ readonly Candidate: "candidate" | "confirmed";
86
+ }>;
87
+ export declare const AllAssociationConclusions: readonly AssociationConclusion[];
88
+ export declare function isAssociationConclusion(value: unknown): value is AssociationConclusion;
89
+ export type AssociationEvidenceKind = AssociationEvidenceKindContract;
90
+ export declare const AssociationEvidenceKind: Readonly<{
91
+ readonly RecordedCommit: "recorded_commit" | "touched_file" | "branch_membership" | "time_window";
92
+ readonly TouchedFile: "recorded_commit" | "touched_file" | "branch_membership" | "time_window";
93
+ readonly BranchMembership: "recorded_commit" | "touched_file" | "branch_membership" | "time_window";
94
+ readonly TimeWindow: "recorded_commit" | "touched_file" | "branch_membership" | "time_window";
95
+ }>;
96
+ export declare const AllAssociationEvidenceKinds: readonly AssociationEvidenceKind[];
97
+ export declare function isAssociationEvidenceKind(value: unknown): value is AssociationEvidenceKind;
73
98
  export type BuiltinCommand = BuiltinCommandContract;
74
99
  export declare const BuiltinCommand: Readonly<{
75
100
  readonly Exit: "new" | "clear" | "resume" | "exit" | "compact" | "config" | "model" | "usage" | "cost" | "context" | "plugin" | "permissions" | "login" | "plan" | "fast" | "voice" | "todos" | "reload-plugins" | "sandbox" | "statusline" | "upgrade" | "extra-usage" | "rate-limit-options" | "privacy-settings" | "help" | "commands";
@@ -120,6 +145,14 @@ export declare const ChannelTopic: Readonly<{
120
145
  }>;
121
146
  export declare const AllChannelTopics: readonly ChannelTopic[];
122
147
  export declare function isChannelTopic(value: unknown): value is ChannelTopic;
148
+ export type Confidence = ConfidenceContract;
149
+ export declare const Confidence: Readonly<{
150
+ readonly High: "high" | "low" | "medium";
151
+ readonly Medium: "high" | "low" | "medium";
152
+ readonly Low: "high" | "low" | "medium";
153
+ }>;
154
+ export declare const AllConfidences: readonly Confidence[];
155
+ export declare function isConfidence(value: unknown): value is Confidence;
123
156
  export type ContentKind = ContentKindContract;
124
157
  export declare const ContentKind: Readonly<{
125
158
  readonly SessionDetail: "session_detail";
@@ -187,6 +220,22 @@ export declare const Harness: Readonly<{
187
220
  */
188
221
  export declare const AllHarnesses: readonly Harness[];
189
222
  export declare function isHarness(value: unknown): value is Harness;
223
+ export type InsightKind = InsightKindContract;
224
+ export declare const InsightKind: Readonly<{
225
+ readonly Decision: "decision" | "friction" | "unusual" | "retry_loop";
226
+ readonly Friction: "decision" | "friction" | "unusual" | "retry_loop";
227
+ readonly Unusual: "decision" | "friction" | "unusual" | "retry_loop";
228
+ readonly RetryLoop: "decision" | "friction" | "unusual" | "retry_loop";
229
+ }>;
230
+ export declare const AllInsightKinds: readonly InsightKind[];
231
+ export declare function isInsightKind(value: unknown): value is InsightKind;
232
+ export type InsightProvenance = InsightProvenanceContract;
233
+ export declare const InsightProvenance: Readonly<{
234
+ readonly Mechanical: "mechanical" | "mined";
235
+ readonly Mined: "mechanical" | "mined";
236
+ }>;
237
+ export declare const AllInsightProvenances: readonly InsightProvenance[];
238
+ export declare function isInsightProvenance(value: unknown): value is InsightProvenance;
190
239
  export type InteractionType = InteractionTypeContract;
191
240
  export declare const InteractionType: Readonly<{
192
241
  readonly Mentioned: "mentioned" | "read" | "discussed" | "questioned";
@@ -228,6 +277,42 @@ export declare const MessageType: Readonly<{
228
277
  }>;
229
278
  export declare const AllMessageTypes: readonly MessageType[];
230
279
  export declare function isMessageType(value: unknown): value is MessageType;
280
+ export type ReadAttributionState = ReadAttributionStateContract;
281
+ export declare const ReadAttributionState: Readonly<{
282
+ readonly Complete: "complete" | "partial" | "unavailable";
283
+ readonly Partial: "complete" | "partial" | "unavailable";
284
+ readonly Unavailable: "complete" | "partial" | "unavailable";
285
+ }>;
286
+ export declare const AllReadAttributionStates: readonly ReadAttributionState[];
287
+ export declare function isReadAttributionState(value: unknown): value is ReadAttributionState;
288
+ export type ReadStateGrade = ReadStateGradeContract;
289
+ export declare const ReadStateGrade: Readonly<{
290
+ readonly None: "none" | "viewed" | "reviewed" | "reviewed_in_detail";
291
+ readonly Viewed: "none" | "viewed" | "reviewed" | "reviewed_in_detail";
292
+ readonly Reviewed: "none" | "viewed" | "reviewed" | "reviewed_in_detail";
293
+ readonly ReviewedInDetail: "none" | "viewed" | "reviewed" | "reviewed_in_detail";
294
+ }>;
295
+ export declare const AllReadStateGrades: readonly ReadStateGrade[];
296
+ export declare function isReadStateGrade(value: unknown): value is ReadStateGrade;
297
+ export type RewriteMethod = RewriteMethodContract;
298
+ export declare const RewriteMethod: Readonly<{
299
+ readonly Hash: "none" | "hash" | "patch_id" | "author_identity" | "message_embedded" | "temporal";
300
+ readonly PatchID: "none" | "hash" | "patch_id" | "author_identity" | "message_embedded" | "temporal";
301
+ readonly AuthorIdentity: "none" | "hash" | "patch_id" | "author_identity" | "message_embedded" | "temporal";
302
+ readonly MessageEmbedded: "none" | "hash" | "patch_id" | "author_identity" | "message_embedded" | "temporal";
303
+ readonly Temporal: "none" | "hash" | "patch_id" | "author_identity" | "message_embedded" | "temporal";
304
+ readonly None: "none" | "hash" | "patch_id" | "author_identity" | "message_embedded" | "temporal";
305
+ }>;
306
+ export declare const AllRewriteMethods: readonly RewriteMethod[];
307
+ export declare function isRewriteMethod(value: unknown): value is RewriteMethod;
308
+ export type RewriteResolution = RewriteResolutionContract;
309
+ export declare const RewriteResolution: Readonly<{
310
+ readonly Live: "live" | "rewritten" | "unresolved";
311
+ readonly Rewritten: "live" | "rewritten" | "unresolved";
312
+ readonly Unresolved: "live" | "rewritten" | "unresolved";
313
+ }>;
314
+ export declare const AllRewriteResolutions: readonly RewriteResolution[];
315
+ export declare function isRewriteResolution(value: unknown): value is RewriteResolution;
231
316
  export type Role = RoleContract;
232
317
  export declare const Role: Readonly<{
233
318
  readonly User: "user" | "system" | "assistant" | "tool";
@@ -272,10 +357,12 @@ export declare const AllStopReasons: readonly StopReason[];
272
357
  export declare function isStopReason(value: unknown): value is StopReason;
273
358
  export type TargetKind = TargetKindContract;
274
359
  export declare const TargetKind: Readonly<{
275
- readonly Session: "session" | "annotation" | "project" | "entry";
276
- readonly Entry: "session" | "annotation" | "project" | "entry";
277
- readonly Annotation: "session" | "annotation" | "project" | "entry";
278
- readonly Project: "session" | "annotation" | "project" | "entry";
360
+ readonly Session: "session" | "annotation" | "project" | "entry" | "file_version" | "association";
361
+ readonly Entry: "session" | "annotation" | "project" | "entry" | "file_version" | "association";
362
+ readonly Annotation: "session" | "annotation" | "project" | "entry" | "file_version" | "association";
363
+ readonly Project: "session" | "annotation" | "project" | "entry" | "file_version" | "association";
364
+ readonly FileVersion: "session" | "annotation" | "project" | "entry" | "file_version" | "association";
365
+ readonly Association: "session" | "annotation" | "project" | "entry" | "file_version" | "association";
279
366
  }>;
280
367
  export declare const AllTargetKinds: readonly TargetKind[];
281
368
  export declare function isTargetKind(value: unknown): value is TargetKind;