@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/cli.js +2593 -386
- package/dist/index.d.ts +65 -49
- package/dist/index.js +51 -16
- package/dist/mcp.js +4795 -2476
- package/package.json +1 -1
- package/src/skill/SKILL.md +130 -2
- package/src/skill/reference.md +15 -6
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.
|
|
107
|
+
title: z.ZodNullable<z.ZodString>;
|
|
108
108
|
content: z.ZodEffects<z.ZodString, string, string>;
|
|
109
|
-
tags: z.
|
|
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.
|
|
115
|
+
title: z.ZodNullable<z.ZodString>;
|
|
116
116
|
content: z.ZodEffects<z.ZodString, string, string>;
|
|
117
|
-
tags: z.
|
|
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.
|
|
123
|
+
title: z.ZodNullable<z.ZodString>;
|
|
124
124
|
content: z.ZodEffects<z.ZodString, string, string>;
|
|
125
|
-
tags: z.
|
|
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.
|
|
1133
|
+
title: z.ZodNullable<z.ZodString>;
|
|
1127
1134
|
content: z.ZodEffects<z.ZodString, string, string>;
|
|
1128
|
-
tags: z.
|
|
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.
|
|
1141
|
+
title: z.ZodNullable<z.ZodString>;
|
|
1135
1142
|
content: z.ZodEffects<z.ZodString, string, string>;
|
|
1136
|
-
tags: z.
|
|
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.
|
|
1149
|
+
title: z.ZodNullable<z.ZodString>;
|
|
1143
1150
|
content: z.ZodEffects<z.ZodString, string, string>;
|
|
1144
|
-
tags: z.
|
|
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.
|
|
1248
|
+
title: z.ZodNullable<z.ZodString>;
|
|
1222
1249
|
content: z.ZodEffects<z.ZodString, string, string>;
|
|
1223
|
-
tags: z.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
1341
|
+
title: z.ZodNullable<z.ZodString>;
|
|
1331
1342
|
content: z.ZodEffects<z.ZodString, string, string>;
|
|
1332
|
-
tags: z.
|
|
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.
|
|
82
|
+
title: z4.string().nullable(),
|
|
83
83
|
content: z4.string().refine((v) => v.trim().length > 0, "Content cannot be empty"),
|
|
84
|
-
tags: z4.
|
|
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
|
|
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
|
|
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;
|