@anthropologies/claudestory 0.1.10 → 0.1.12

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.
package/dist/index.d.ts CHANGED
@@ -104,25 +104,25 @@ type Issue = z.infer<typeof IssueSchema>;
104
104
 
105
105
  declare const NoteSchema: z.ZodObject<{
106
106
  id: z.ZodString;
107
- title: z.ZodEffects<z.ZodNullable<z.ZodString>, string | null, unknown>;
107
+ title: z.ZodNullable<z.ZodString>;
108
108
  content: z.ZodEffects<z.ZodString, string, string>;
109
- tags: z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], unknown>;
109
+ tags: z.ZodArray<z.ZodString, "many">;
110
110
  status: z.ZodEnum<["active", "archived"]>;
111
111
  createdDate: z.ZodEffects<z.ZodString, string, string>;
112
112
  updatedDate: z.ZodEffects<z.ZodString, string, string>;
113
113
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
114
114
  id: z.ZodString;
115
- title: z.ZodEffects<z.ZodNullable<z.ZodString>, string | null, unknown>;
115
+ title: z.ZodNullable<z.ZodString>;
116
116
  content: z.ZodEffects<z.ZodString, string, string>;
117
- tags: z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], unknown>;
117
+ tags: z.ZodArray<z.ZodString, "many">;
118
118
  status: z.ZodEnum<["active", "archived"]>;
119
119
  createdDate: z.ZodEffects<z.ZodString, string, string>;
120
120
  updatedDate: z.ZodEffects<z.ZodString, string, string>;
121
121
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
122
122
  id: z.ZodString;
123
- title: z.ZodEffects<z.ZodNullable<z.ZodString>, string | null, unknown>;
123
+ title: z.ZodNullable<z.ZodString>;
124
124
  content: z.ZodEffects<z.ZodString, string, string>;
125
- tags: z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], unknown>;
125
+ tags: z.ZodArray<z.ZodString, "many">;
126
126
  status: z.ZodEnum<["active", "archived"]>;
127
127
  createdDate: z.ZodEffects<z.ZodString, string, string>;
128
128
  updatedDate: z.ZodEffects<z.ZodString, string, string>;
@@ -340,6 +340,7 @@ declare const ConfigSchema: z.ZodObject<{
340
340
  roadmap: z.ZodBoolean;
341
341
  reviews: z.ZodBoolean;
342
342
  }, z.ZodTypeAny, "passthrough">>;
343
+ recipe: z.ZodOptional<z.ZodString>;
343
344
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
344
345
  version: z.ZodNumber;
345
346
  schemaVersion: z.ZodOptional<z.ZodNumber>;
@@ -365,6 +366,7 @@ declare const ConfigSchema: z.ZodObject<{
365
366
  roadmap: z.ZodBoolean;
366
367
  reviews: z.ZodBoolean;
367
368
  }, z.ZodTypeAny, "passthrough">>;
369
+ recipe: z.ZodOptional<z.ZodString>;
368
370
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
369
371
  version: z.ZodNumber;
370
372
  schemaVersion: z.ZodOptional<z.ZodNumber>;
@@ -390,6 +392,7 @@ declare const ConfigSchema: z.ZodObject<{
390
392
  roadmap: z.ZodBoolean;
391
393
  reviews: z.ZodBoolean;
392
394
  }, z.ZodTypeAny, "passthrough">>;
395
+ recipe: z.ZodOptional<z.ZodString>;
393
396
  }, z.ZodTypeAny, "passthrough">>;
394
397
  type Config = z.infer<typeof ConfigSchema>;
395
398
 
@@ -806,6 +809,7 @@ interface InitOptions {
806
809
  force?: boolean;
807
810
  type?: string;
808
811
  language?: string;
812
+ phases?: Phase[];
809
813
  }
810
814
  interface InitResult {
811
815
  readonly root: string;
@@ -848,6 +852,7 @@ declare const SnapshotV1Schema: z.ZodObject<{
848
852
  roadmap: z.ZodBoolean;
849
853
  reviews: z.ZodBoolean;
850
854
  }, z.ZodTypeAny, "passthrough">>;
855
+ recipe: z.ZodOptional<z.ZodString>;
851
856
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
852
857
  version: z.ZodNumber;
853
858
  schemaVersion: z.ZodOptional<z.ZodNumber>;
@@ -873,6 +878,7 @@ declare const SnapshotV1Schema: z.ZodObject<{
873
878
  roadmap: z.ZodBoolean;
874
879
  reviews: z.ZodBoolean;
875
880
  }, z.ZodTypeAny, "passthrough">>;
881
+ recipe: z.ZodOptional<z.ZodString>;
876
882
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
877
883
  version: z.ZodNumber;
878
884
  schemaVersion: z.ZodOptional<z.ZodNumber>;
@@ -898,6 +904,7 @@ declare const SnapshotV1Schema: z.ZodObject<{
898
904
  roadmap: z.ZodBoolean;
899
905
  reviews: z.ZodBoolean;
900
906
  }, z.ZodTypeAny, "passthrough">>;
907
+ recipe: z.ZodOptional<z.ZodString>;
901
908
  }, z.ZodTypeAny, "passthrough">>;
902
909
  roadmap: z.ZodObject<{
903
910
  title: z.ZodString;
@@ -1123,43 +1130,64 @@ declare const SnapshotV1Schema: z.ZodObject<{
1123
1130
  }, z.ZodTypeAny, "passthrough">>, "many">;
1124
1131
  notes: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
1125
1132
  id: z.ZodString;
1126
- title: z.ZodEffects<z.ZodNullable<z.ZodString>, string | null, unknown>;
1133
+ title: z.ZodNullable<z.ZodString>;
1127
1134
  content: z.ZodEffects<z.ZodString, string, string>;
1128
- tags: z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], unknown>;
1135
+ tags: z.ZodArray<z.ZodString, "many">;
1129
1136
  status: z.ZodEnum<["active", "archived"]>;
1130
1137
  createdDate: z.ZodEffects<z.ZodString, string, string>;
1131
1138
  updatedDate: z.ZodEffects<z.ZodString, string, string>;
1132
1139
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
1133
1140
  id: z.ZodString;
1134
- title: z.ZodEffects<z.ZodNullable<z.ZodString>, string | null, unknown>;
1141
+ title: z.ZodNullable<z.ZodString>;
1135
1142
  content: z.ZodEffects<z.ZodString, string, string>;
1136
- tags: z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], unknown>;
1143
+ tags: z.ZodArray<z.ZodString, "many">;
1137
1144
  status: z.ZodEnum<["active", "archived"]>;
1138
1145
  createdDate: z.ZodEffects<z.ZodString, string, string>;
1139
1146
  updatedDate: z.ZodEffects<z.ZodString, string, string>;
1140
1147
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
1141
1148
  id: z.ZodString;
1142
- title: z.ZodEffects<z.ZodNullable<z.ZodString>, string | null, unknown>;
1149
+ title: z.ZodNullable<z.ZodString>;
1143
1150
  content: z.ZodEffects<z.ZodString, string, string>;
1144
- tags: z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], unknown>;
1151
+ tags: z.ZodArray<z.ZodString, "many">;
1145
1152
  status: z.ZodEnum<["active", "archived"]>;
1146
1153
  createdDate: z.ZodEffects<z.ZodString, string, string>;
1147
1154
  updatedDate: z.ZodEffects<z.ZodString, string, string>;
1148
1155
  }, z.ZodTypeAny, "passthrough">>, "many">>>;
1156
+ handoverFilenames: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
1149
1157
  warnings: z.ZodOptional<z.ZodArray<z.ZodObject<{
1150
1158
  type: z.ZodString;
1151
1159
  file: z.ZodString;
1152
1160
  message: z.ZodString;
1153
1161
  }, "strip", z.ZodTypeAny, {
1154
- message: string;
1155
1162
  type: string;
1163
+ message: string;
1156
1164
  file: string;
1157
1165
  }, {
1158
- message: string;
1159
1166
  type: string;
1167
+ message: string;
1160
1168
  file: string;
1161
1169
  }>, "many">>;
1162
1170
  }, "strip", z.ZodTypeAny, {
1171
+ version: 1;
1172
+ config: {
1173
+ version: number;
1174
+ type: string;
1175
+ language: string;
1176
+ project: string;
1177
+ features: {
1178
+ issues: boolean;
1179
+ tickets: boolean;
1180
+ handovers: boolean;
1181
+ roadmap: boolean;
1182
+ reviews: boolean;
1183
+ } & {
1184
+ [k: string]: unknown;
1185
+ };
1186
+ schemaVersion?: number | undefined;
1187
+ recipe?: string | undefined;
1188
+ } & {
1189
+ [k: string]: unknown;
1190
+ };
1163
1191
  issues: z.objectOutputType<{
1164
1192
  id: z.ZodString;
1165
1193
  title: z.ZodString;
@@ -1195,8 +1223,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
1195
1223
  lastModifiedBy: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1196
1224
  }, z.ZodTypeAny, "passthrough">[];
1197
1225
  roadmap: {
1198
- title: string;
1199
1226
  date: string;
1227
+ title: string;
1200
1228
  phases: z.objectOutputType<{
1201
1229
  id: z.ZodString;
1202
1230
  label: z.ZodString;
@@ -1214,23 +1242,30 @@ declare const SnapshotV1Schema: z.ZodObject<{
1214
1242
  } & {
1215
1243
  [k: string]: unknown;
1216
1244
  };
1217
- version: 1;
1218
1245
  project: string;
1219
1246
  notes: z.objectOutputType<{
1220
1247
  id: z.ZodString;
1221
- title: z.ZodEffects<z.ZodNullable<z.ZodString>, string | null, unknown>;
1248
+ title: z.ZodNullable<z.ZodString>;
1222
1249
  content: z.ZodEffects<z.ZodString, string, string>;
1223
- tags: z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], unknown>;
1250
+ tags: z.ZodArray<z.ZodString, "many">;
1224
1251
  status: z.ZodEnum<["active", "archived"]>;
1225
1252
  createdDate: z.ZodEffects<z.ZodString, string, string>;
1226
1253
  updatedDate: z.ZodEffects<z.ZodString, string, string>;
1227
1254
  }, z.ZodTypeAny, "passthrough">[];
1228
1255
  createdAt: string;
1229
- config: {
1256
+ handoverFilenames: string[];
1257
+ warnings?: {
1230
1258
  type: string;
1259
+ message: string;
1260
+ file: string;
1261
+ }[] | undefined;
1262
+ }, {
1263
+ version: 1;
1264
+ config: {
1231
1265
  version: number;
1232
- project: string;
1266
+ type: string;
1233
1267
  language: string;
1268
+ project: string;
1234
1269
  features: {
1235
1270
  issues: boolean;
1236
1271
  tickets: boolean;
@@ -1241,15 +1276,10 @@ declare const SnapshotV1Schema: z.ZodObject<{
1241
1276
  [k: string]: unknown;
1242
1277
  };
1243
1278
  schemaVersion?: number | undefined;
1279
+ recipe?: string | undefined;
1244
1280
  } & {
1245
1281
  [k: string]: unknown;
1246
1282
  };
1247
- warnings?: {
1248
- message: string;
1249
- type: string;
1250
- file: string;
1251
- }[] | undefined;
1252
- }, {
1253
1283
  issues: z.objectInputType<{
1254
1284
  id: z.ZodString;
1255
1285
  title: z.ZodString;
@@ -1285,8 +1315,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
1285
1315
  lastModifiedBy: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1286
1316
  }, z.ZodTypeAny, "passthrough">[];
1287
1317
  roadmap: {
1288
- title: string;
1289
1318
  date: string;
1319
+ title: string;
1290
1320
  phases: z.objectInputType<{
1291
1321
  id: z.ZodString;
1292
1322
  label: z.ZodString;
@@ -1304,41 +1334,23 @@ declare const SnapshotV1Schema: z.ZodObject<{
1304
1334
  } & {
1305
1335
  [k: string]: unknown;
1306
1336
  };
1307
- version: 1;
1308
1337
  project: string;
1309
1338
  createdAt: string;
1310
- config: {
1311
- type: string;
1312
- version: number;
1313
- project: string;
1314
- language: string;
1315
- features: {
1316
- issues: boolean;
1317
- tickets: boolean;
1318
- handovers: boolean;
1319
- roadmap: boolean;
1320
- reviews: boolean;
1321
- } & {
1322
- [k: string]: unknown;
1323
- };
1324
- schemaVersion?: number | undefined;
1325
- } & {
1326
- [k: string]: unknown;
1327
- };
1328
1339
  notes?: z.objectInputType<{
1329
1340
  id: z.ZodString;
1330
- title: z.ZodEffects<z.ZodNullable<z.ZodString>, string | null, unknown>;
1341
+ title: z.ZodNullable<z.ZodString>;
1331
1342
  content: z.ZodEffects<z.ZodString, string, string>;
1332
- tags: z.ZodEffects<z.ZodArray<z.ZodString, "many">, string[], unknown>;
1343
+ tags: z.ZodArray<z.ZodString, "many">;
1333
1344
  status: z.ZodEnum<["active", "archived"]>;
1334
1345
  createdDate: z.ZodEffects<z.ZodString, string, string>;
1335
1346
  updatedDate: z.ZodEffects<z.ZodString, string, string>;
1336
1347
  }, z.ZodTypeAny, "passthrough">[] | undefined;
1337
1348
  warnings?: {
1338
- message: string;
1339
1349
  type: string;
1350
+ message: string;
1340
1351
  file: string;
1341
1352
  }[] | undefined;
1353
+ handoverFilenames?: string[] | undefined;
1342
1354
  }>;
1343
1355
  type SnapshotV1 = z.infer<typeof SnapshotV1Schema>;
1344
1356
  /**
@@ -1438,6 +1450,10 @@ interface SnapshotDiff {
1438
1450
  }>;
1439
1451
  updated: NoteChange[];
1440
1452
  };
1453
+ handovers: {
1454
+ added: string[];
1455
+ removed: string[];
1456
+ };
1441
1457
  }
1442
1458
  interface RecapResult {
1443
1459
  snapshot: {
package/dist/index.js CHANGED
@@ -79,15 +79,9 @@ var IssueSchema = z3.object({
79
79
  import { z as z4 } from "zod";
80
80
  var NoteSchema = z4.object({
81
81
  id: NoteIdSchema,
82
- title: z4.preprocess((v) => v ?? null, z4.string().nullable()),
82
+ title: z4.string().nullable(),
83
83
  content: z4.string().refine((v) => v.trim().length > 0, "Content cannot be empty"),
84
- tags: z4.preprocess(
85
- (v) => {
86
- const raw = Array.isArray(v) ? v : [];
87
- return raw.filter((t) => typeof t === "string").map((t) => t.trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "")).filter((t) => t.length > 0).filter((t, i, a) => a.indexOf(t) === i);
88
- },
89
- z4.array(z4.string())
90
- ),
84
+ tags: z4.array(z4.string()),
91
85
  status: z4.enum(NOTE_STATUSES),
92
86
  createdDate: DateSchema,
93
87
  updatedDate: DateSchema
@@ -134,7 +128,8 @@ var ConfigSchema = z6.object({
134
128
  project: z6.string().min(1),
135
129
  type: z6.string(),
136
130
  language: z6.string(),
137
- features: FeaturesSchema
131
+ features: FeaturesSchema,
132
+ recipe: z6.string().optional()
138
133
  }).passthrough();
139
134
 
140
135
  // src/core/project-state.ts
@@ -1782,7 +1777,7 @@ function nextOrder(phaseId, state) {
1782
1777
  }
1783
1778
 
1784
1779
  // src/core/init.ts
1785
- import { mkdir as mkdir2, stat as stat2 } from "fs/promises";
1780
+ import { mkdir as mkdir2, stat as stat2, readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
1786
1781
  import { join as join4, resolve as resolve3 } from "path";
1787
1782
  async function initProject(root, options) {
1788
1783
  const absRoot = resolve3(root);
@@ -1836,7 +1831,7 @@ async function initProject(root, options) {
1836
1831
  const roadmap = {
1837
1832
  title: options.name,
1838
1833
  date: today,
1839
- phases: [
1834
+ phases: options.phases ?? [
1840
1835
  {
1841
1836
  id: "p0",
1842
1837
  label: "PHASE 0",
@@ -1848,6 +1843,8 @@ async function initProject(root, options) {
1848
1843
  };
1849
1844
  await writeConfig(config, absRoot);
1850
1845
  await writeRoadmap(roadmap, absRoot);
1846
+ const gitignorePath = join4(wrapDir, ".gitignore");
1847
+ await ensureGitignoreEntries(gitignorePath, STORY_GITIGNORE_ENTRIES);
1851
1848
  const warnings = [];
1852
1849
  if (options.force && exists) {
1853
1850
  try {
@@ -1866,9 +1863,24 @@ async function initProject(root, options) {
1866
1863
  warnings
1867
1864
  };
1868
1865
  }
1866
+ var STORY_GITIGNORE_ENTRIES = ["snapshots/", "status.json", "sessions/"];
1867
+ async function ensureGitignoreEntries(gitignorePath, entries) {
1868
+ let existing = "";
1869
+ try {
1870
+ existing = await readFile3(gitignorePath, "utf-8");
1871
+ } catch {
1872
+ }
1873
+ const lines = existing.split("\n").map((l) => l.trim());
1874
+ const missing = entries.filter((e) => !lines.includes(e));
1875
+ if (missing.length === 0) return;
1876
+ let content = existing;
1877
+ if (content.length > 0 && !content.endsWith("\n")) content += "\n";
1878
+ content += missing.join("\n") + "\n";
1879
+ await writeFile2(gitignorePath, content, "utf-8");
1880
+ }
1869
1881
 
1870
1882
  // src/core/snapshot.ts
1871
- import { readdir as readdir3, readFile as readFile3, mkdir as mkdir3, unlink as unlink2 } from "fs/promises";
1883
+ import { readdir as readdir3, readFile as readFile4, mkdir as mkdir3, unlink as unlink2 } from "fs/promises";
1872
1884
  import { existsSync as existsSync4 } from "fs";
1873
1885
  import { join as join5, resolve as resolve4 } from "path";
1874
1886
  import { z as z7 } from "zod";
@@ -1886,6 +1898,7 @@ var SnapshotV1Schema = z7.object({
1886
1898
  tickets: z7.array(TicketSchema),
1887
1899
  issues: z7.array(IssueSchema),
1888
1900
  notes: z7.array(NoteSchema).optional().default([]),
1901
+ handoverFilenames: z7.array(z7.string()).optional().default([]),
1889
1902
  warnings: z7.array(LoadWarningSchema).optional()
1890
1903
  });
1891
1904
  var MAX_SNAPSHOTS = 20;
@@ -1905,6 +1918,7 @@ async function saveSnapshot(root, loadResult) {
1905
1918
  tickets: [...state.tickets],
1906
1919
  issues: [...state.issues],
1907
1920
  notes: [...state.notes],
1921
+ handoverFilenames: [...state.handoverFilenames],
1908
1922
  ...warnings.length > 0 ? {
1909
1923
  warnings: warnings.map((w) => ({
1910
1924
  type: w.type,
@@ -1929,7 +1943,7 @@ async function loadLatestSnapshot(root) {
1929
1943
  if (files.length === 0) return null;
1930
1944
  for (const filename of files) {
1931
1945
  try {
1932
- const content = await readFile3(join5(snapshotsDir, filename), "utf-8");
1946
+ const content = await readFile4(join5(snapshotsDir, filename), "utf-8");
1933
1947
  const parsed = JSON.parse(content);
1934
1948
  const snapshot = SnapshotV1Schema.parse(parsed);
1935
1949
  return { snapshot, filename };
@@ -2057,12 +2071,23 @@ function diffStates(snapshotState, currentState) {
2057
2071
  notesRemoved.push({ id, title: snap.title });
2058
2072
  }
2059
2073
  }
2074
+ const snapHandovers = new Set(snapshotState.handoverFilenames);
2075
+ const curHandovers = new Set(currentState.handoverFilenames);
2076
+ const handoversAdded = [];
2077
+ const handoversRemoved = [];
2078
+ for (const h of curHandovers) {
2079
+ if (!snapHandovers.has(h)) handoversAdded.push(h);
2080
+ }
2081
+ for (const h of snapHandovers) {
2082
+ if (!curHandovers.has(h)) handoversRemoved.push(h);
2083
+ }
2060
2084
  return {
2061
2085
  tickets: { added: ticketsAdded, removed: ticketsRemoved, statusChanged: ticketsStatusChanged, descriptionChanged: ticketsDescriptionChanged },
2062
2086
  issues: { added: issuesAdded, resolved: issuesResolved, statusChanged: issuesStatusChanged, impactChanged: issuesImpactChanged },
2063
2087
  blockers: { added: blockersAdded, cleared: blockersCleared },
2064
2088
  phases: { added: phasesAdded, removed: phasesRemoved, statusChanged: phasesStatusChanged },
2065
- notes: { added: notesAdded, removed: notesRemoved, updated: notesUpdated }
2089
+ notes: { added: notesAdded, removed: notesRemoved, updated: notesUpdated },
2090
+ handovers: { added: handoversAdded, removed: handoversRemoved }
2066
2091
  };
2067
2092
  }
2068
2093
  function buildRecap(currentState, snapshotInfo) {
@@ -2090,7 +2115,7 @@ function buildRecap(currentState, snapshotInfo) {
2090
2115
  notes: snapshot.notes ?? [],
2091
2116
  roadmap: snapshot.roadmap,
2092
2117
  config: snapshot.config,
2093
- handoverFilenames: []
2118
+ handoverFilenames: snapshot.handoverFilenames ?? []
2094
2119
  });
2095
2120
  const changes = diffStates(snapshotState, currentState);
2096
2121
  const recentlyClearedBlockers = changes.blockers.cleared;
@@ -2536,6 +2561,16 @@ function formatRecap(recap, state, format) {
2536
2561
  lines.push(`- ${escapeMarkdownInline(name)} \u2014 **new**`);
2537
2562
  }
2538
2563
  }
2564
+ if (changes.handovers && (changes.handovers.added.length > 0 || changes.handovers.removed.length > 0)) {
2565
+ lines.push("");
2566
+ lines.push("## Handovers");
2567
+ for (const h of changes.handovers.added) {
2568
+ lines.push(`- ${h} \u2014 **new**`);
2569
+ }
2570
+ for (const h of changes.handovers.removed) {
2571
+ lines.push(`- ${h} \u2014 removed`);
2572
+ }
2573
+ }
2539
2574
  if (changes.notes && (changes.notes.added.length > 0 || changes.notes.removed.length > 0 || changes.notes.updated.length > 0)) {
2540
2575
  lines.push("");
2541
2576
  lines.push("## Notes");
@@ -2757,7 +2792,7 @@ function formatFullExport(state, format) {
2757
2792
  return lines.join("\n");
2758
2793
  }
2759
2794
  function hasAnyChanges(diff) {
2760
- return diff.tickets.added.length > 0 || diff.tickets.removed.length > 0 || diff.tickets.statusChanged.length > 0 || diff.tickets.descriptionChanged.length > 0 || diff.issues.added.length > 0 || diff.issues.resolved.length > 0 || diff.issues.statusChanged.length > 0 || diff.issues.impactChanged.length > 0 || diff.blockers.added.length > 0 || diff.blockers.cleared.length > 0 || diff.phases.added.length > 0 || diff.phases.removed.length > 0 || diff.phases.statusChanged.length > 0 || (diff.notes?.added.length ?? 0) > 0 || (diff.notes?.removed.length ?? 0) > 0 || (diff.notes?.updated.length ?? 0) > 0;
2795
+ return diff.tickets.added.length > 0 || diff.tickets.removed.length > 0 || diff.tickets.statusChanged.length > 0 || diff.tickets.descriptionChanged.length > 0 || diff.issues.added.length > 0 || diff.issues.resolved.length > 0 || diff.issues.statusChanged.length > 0 || diff.issues.impactChanged.length > 0 || diff.blockers.added.length > 0 || diff.blockers.cleared.length > 0 || diff.phases.added.length > 0 || diff.phases.removed.length > 0 || diff.phases.statusChanged.length > 0 || (diff.notes?.added.length ?? 0) > 0 || (diff.notes?.removed.length ?? 0) > 0 || (diff.notes?.updated.length ?? 0) > 0 || (diff.handovers?.added.length ?? 0) > 0 || (diff.handovers?.removed.length ?? 0) > 0;
2761
2796
  }
2762
2797
  function truncate(text, maxLen) {
2763
2798
  if (text.length <= maxLen) return text;