@mmnto/mcp 1.49.2 → 1.50.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.
- package/dist/schemas/describe-project.d.ts +80 -4
- package/dist/schemas/describe-project.d.ts.map +1 -1
- package/dist/schemas/describe-project.js +21 -0
- package/dist/schemas/describe-project.js.map +1 -1
- package/dist/schemas/describe-project.test.js +32 -0
- package/dist/schemas/describe-project.test.js.map +1 -1
- package/dist/staleness.d.ts +24 -0
- package/dist/staleness.d.ts.map +1 -0
- package/dist/staleness.js +52 -0
- package/dist/staleness.js.map +1 -0
- package/dist/staleness.test.d.ts +2 -0
- package/dist/staleness.test.d.ts.map +1 -0
- package/dist/staleness.test.js +62 -0
- package/dist/staleness.test.js.map +1 -0
- package/dist/state-extractors.d.ts +16 -1
- package/dist/state-extractors.d.ts.map +1 -1
- package/dist/state-extractors.js +57 -0
- package/dist/state-extractors.js.map +1 -1
- package/dist/state-extractors.test.js +79 -1
- package/dist/state-extractors.test.js.map +1 -1
- package/dist/tools/describe-project.d.ts.map +1 -1
- package/dist/tools/describe-project.js +2 -1
- package/dist/tools/describe-project.js.map +1 -1
- package/dist/tools/search-knowledge.d.ts.map +1 -1
- package/dist/tools/search-knowledge.js +44 -8
- package/dist/tools/search-knowledge.js.map +1 -1
- package/dist/tools/search-knowledge.test.js +33 -0
- package/dist/tools/search-knowledge.test.js.map +1 -1
- package/dist/xml-format.d.ts +19 -0
- package/dist/xml-format.d.ts.map +1 -1
- package/dist/xml-format.js +38 -0
- package/dist/xml-format.js.map +1 -1
- package/dist/xml-format.test.js +57 -1
- package/dist/xml-format.test.js.map +1 -1
- package/package.json +2 -2
|
@@ -148,6 +148,32 @@ export declare const MilestoneStateSchema: z.ZodObject<{
|
|
|
148
148
|
bestEffort: true;
|
|
149
149
|
}>;
|
|
150
150
|
export type MilestoneState = z.infer<typeof MilestoneStateSchema>;
|
|
151
|
+
/**
|
|
152
|
+
* Knowledge-index freshness signal (mmnto-ai/totem#2029 — docs-drift Mech C).
|
|
153
|
+
*
|
|
154
|
+
* Sourced from `.totem/cache/index-meta.json.lastSync` (authoritative, written
|
|
155
|
+
* on every successful `runSync`) with `.totem/index-manifest.json.writtenAt`
|
|
156
|
+
* as fallback. Both fields are null on lite-tier configurations or before
|
|
157
|
+
* the first sync has completed — honest absence per Tenet 14.
|
|
158
|
+
*
|
|
159
|
+
* v1 surfaces envelope-level staleness only. Per-result `indexedAt` is OUT
|
|
160
|
+
* of scope because LanceDB rows do not currently carry per-row sync
|
|
161
|
+
* timestamps; populating a per-result `indexedAt` from the constant manifest
|
|
162
|
+
* value would be fake-presence data.
|
|
163
|
+
*/
|
|
164
|
+
export declare const IndexStateSchema: z.ZodObject<{
|
|
165
|
+
/** ISO-8601 Z timestamp of last successful sync. Null on lite tier or pre-first-sync. */
|
|
166
|
+
lastSyncAt: z.ZodNullable<z.ZodString>;
|
|
167
|
+
/** Human-readable relative time, e.g. "5 minutes ago", "STALE: 14 days ago". Null when lastSyncAt is null. */
|
|
168
|
+
staleness: z.ZodNullable<z.ZodString>;
|
|
169
|
+
}, "strip", z.ZodTypeAny, {
|
|
170
|
+
lastSyncAt: string | null;
|
|
171
|
+
staleness: string | null;
|
|
172
|
+
}, {
|
|
173
|
+
lastSyncAt: string | null;
|
|
174
|
+
staleness: string | null;
|
|
175
|
+
}>;
|
|
176
|
+
export type IndexState = z.infer<typeof IndexStateSchema>;
|
|
151
177
|
export declare const RichProjectStateSchema: z.ZodObject<{
|
|
152
178
|
strategyPointer: z.ZodDiscriminatedUnion<"resolved", [z.ZodObject<{
|
|
153
179
|
resolved: z.ZodLiteral<true>;
|
|
@@ -256,6 +282,19 @@ export declare const RichProjectStateSchema: z.ZodObject<{
|
|
|
256
282
|
title: string;
|
|
257
283
|
squashSha: string;
|
|
258
284
|
}>, "many">;
|
|
285
|
+
/** Index-freshness signal (mmnto-ai/totem#2029). */
|
|
286
|
+
indexState: z.ZodObject<{
|
|
287
|
+
/** ISO-8601 Z timestamp of last successful sync. Null on lite tier or pre-first-sync. */
|
|
288
|
+
lastSyncAt: z.ZodNullable<z.ZodString>;
|
|
289
|
+
/** Human-readable relative time, e.g. "5 minutes ago", "STALE: 14 days ago". Null when lastSyncAt is null. */
|
|
290
|
+
staleness: z.ZodNullable<z.ZodString>;
|
|
291
|
+
}, "strip", z.ZodTypeAny, {
|
|
292
|
+
lastSyncAt: string | null;
|
|
293
|
+
staleness: string | null;
|
|
294
|
+
}, {
|
|
295
|
+
lastSyncAt: string | null;
|
|
296
|
+
staleness: string | null;
|
|
297
|
+
}>;
|
|
259
298
|
}, "strip", z.ZodTypeAny, {
|
|
260
299
|
strategyPointer: {
|
|
261
300
|
resolved: true;
|
|
@@ -288,6 +327,10 @@ export declare const RichProjectStateSchema: z.ZodObject<{
|
|
|
288
327
|
title: string;
|
|
289
328
|
squashSha: string;
|
|
290
329
|
}[];
|
|
330
|
+
indexState: {
|
|
331
|
+
lastSyncAt: string | null;
|
|
332
|
+
staleness: string | null;
|
|
333
|
+
};
|
|
291
334
|
}, {
|
|
292
335
|
strategyPointer: {
|
|
293
336
|
resolved: true;
|
|
@@ -320,6 +363,10 @@ export declare const RichProjectStateSchema: z.ZodObject<{
|
|
|
320
363
|
title: string;
|
|
321
364
|
squashSha: string;
|
|
322
365
|
}[];
|
|
366
|
+
indexState: {
|
|
367
|
+
lastSyncAt: string | null;
|
|
368
|
+
staleness: string | null;
|
|
369
|
+
};
|
|
323
370
|
}>;
|
|
324
371
|
export type RichProjectState = z.infer<typeof RichProjectStateSchema>;
|
|
325
372
|
/**
|
|
@@ -338,19 +385,19 @@ export declare const LegacyProjectDescriptionSchema: z.ZodObject<{
|
|
|
338
385
|
hooks: z.ZodArray<z.ZodString, "many">;
|
|
339
386
|
}, "strip", z.ZodTypeAny, {
|
|
340
387
|
targets: string[];
|
|
341
|
-
lessons: number;
|
|
342
388
|
project: string;
|
|
343
389
|
tier: "lite" | "standard" | "full";
|
|
344
390
|
rules: number;
|
|
391
|
+
lessons: number;
|
|
345
392
|
partitions: Record<string, string[]>;
|
|
346
393
|
hooks: string[];
|
|
347
394
|
description?: string | undefined;
|
|
348
395
|
}, {
|
|
349
396
|
targets: string[];
|
|
350
|
-
lessons: number;
|
|
351
397
|
project: string;
|
|
352
398
|
tier: "lite" | "standard" | "full";
|
|
353
399
|
rules: number;
|
|
400
|
+
lessons: number;
|
|
354
401
|
partitions: Record<string, string[]>;
|
|
355
402
|
hooks: string[];
|
|
356
403
|
description?: string | undefined;
|
|
@@ -478,6 +525,19 @@ export declare const DescribeProjectOutputSchema: z.ZodObject<{
|
|
|
478
525
|
title: string;
|
|
479
526
|
squashSha: string;
|
|
480
527
|
}>, "many">;
|
|
528
|
+
/** Index-freshness signal (mmnto-ai/totem#2029). */
|
|
529
|
+
indexState: z.ZodObject<{
|
|
530
|
+
/** ISO-8601 Z timestamp of last successful sync. Null on lite tier or pre-first-sync. */
|
|
531
|
+
lastSyncAt: z.ZodNullable<z.ZodString>;
|
|
532
|
+
/** Human-readable relative time, e.g. "5 minutes ago", "STALE: 14 days ago". Null when lastSyncAt is null. */
|
|
533
|
+
staleness: z.ZodNullable<z.ZodString>;
|
|
534
|
+
}, "strip", z.ZodTypeAny, {
|
|
535
|
+
lastSyncAt: string | null;
|
|
536
|
+
staleness: string | null;
|
|
537
|
+
}, {
|
|
538
|
+
lastSyncAt: string | null;
|
|
539
|
+
staleness: string | null;
|
|
540
|
+
}>;
|
|
481
541
|
}, "strip", z.ZodTypeAny, {
|
|
482
542
|
strategyPointer: {
|
|
483
543
|
resolved: true;
|
|
@@ -510,6 +570,10 @@ export declare const DescribeProjectOutputSchema: z.ZodObject<{
|
|
|
510
570
|
title: string;
|
|
511
571
|
squashSha: string;
|
|
512
572
|
}[];
|
|
573
|
+
indexState: {
|
|
574
|
+
lastSyncAt: string | null;
|
|
575
|
+
staleness: string | null;
|
|
576
|
+
};
|
|
513
577
|
}, {
|
|
514
578
|
strategyPointer: {
|
|
515
579
|
resolved: true;
|
|
@@ -542,13 +606,17 @@ export declare const DescribeProjectOutputSchema: z.ZodObject<{
|
|
|
542
606
|
title: string;
|
|
543
607
|
squashSha: string;
|
|
544
608
|
}[];
|
|
609
|
+
indexState: {
|
|
610
|
+
lastSyncAt: string | null;
|
|
611
|
+
staleness: string | null;
|
|
612
|
+
};
|
|
545
613
|
}>>;
|
|
546
614
|
}, "strip", z.ZodTypeAny, {
|
|
547
615
|
targets: string[];
|
|
548
|
-
lessons: number;
|
|
549
616
|
project: string;
|
|
550
617
|
tier: "lite" | "standard" | "full";
|
|
551
618
|
rules: number;
|
|
619
|
+
lessons: number;
|
|
552
620
|
partitions: Record<string, string[]>;
|
|
553
621
|
hooks: string[];
|
|
554
622
|
description?: string | undefined;
|
|
@@ -584,13 +652,17 @@ export declare const DescribeProjectOutputSchema: z.ZodObject<{
|
|
|
584
652
|
title: string;
|
|
585
653
|
squashSha: string;
|
|
586
654
|
}[];
|
|
655
|
+
indexState: {
|
|
656
|
+
lastSyncAt: string | null;
|
|
657
|
+
staleness: string | null;
|
|
658
|
+
};
|
|
587
659
|
} | undefined;
|
|
588
660
|
}, {
|
|
589
661
|
targets: string[];
|
|
590
|
-
lessons: number;
|
|
591
662
|
project: string;
|
|
592
663
|
tier: "lite" | "standard" | "full";
|
|
593
664
|
rules: number;
|
|
665
|
+
lessons: number;
|
|
594
666
|
partitions: Record<string, string[]>;
|
|
595
667
|
hooks: string[];
|
|
596
668
|
description?: string | undefined;
|
|
@@ -626,6 +698,10 @@ export declare const DescribeProjectOutputSchema: z.ZodObject<{
|
|
|
626
698
|
title: string;
|
|
627
699
|
squashSha: string;
|
|
628
700
|
}[];
|
|
701
|
+
indexState: {
|
|
702
|
+
lastSyncAt: string | null;
|
|
703
|
+
staleness: string | null;
|
|
704
|
+
};
|
|
629
705
|
} | undefined;
|
|
630
706
|
}>;
|
|
631
707
|
export type DescribeProjectOutput = z.infer<typeof DescribeProjectOutputSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe-project.d.ts","sourceRoot":"","sources":["../../src/schemas/describe-project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAIlC;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;;;;;EAErC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAI9E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB;;IAI5B,kHAAkH;;IAElH;;;;;;;;OAQG;;;;;;;;;;;;IAOH,6DAA6D;;;;;;;;IAIjE,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,cAAc;IACzB,qFAAqF;;IAErF,8EAA8E;;IAE9E,2EAA2E;;;;;;;;;;EAE3E,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,cAAc;IACzB,mEAAmE;;IAEnE,4BAA4B;;IAE5B,oCAAoC;;;;;;;;;;EAEpC,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;EAI3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,oBAAoB;IAC/B,mFAAmF;;IAEnF,uFAAuF;;IAEvF;;;;OAIG;;;;;;;;;;EAEH,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,sBAAsB;;;
|
|
1
|
+
{"version":3,"file":"describe-project.d.ts","sourceRoot":"","sources":["../../src/schemas/describe-project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAIlC;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;;;;;EAErC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAI9E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB;;IAI5B,kHAAkH;;IAElH;;;;;;;;OAQG;;;;;;;;;;;;IAOH,6DAA6D;;;;;;;;IAIjE,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,cAAc;IACzB,qFAAqF;;IAErF,8EAA8E;;IAE9E,2EAA2E;;;;;;;;;;EAE3E,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,cAAc;IACzB,mEAAmE;;IAEnE,4BAA4B;;IAE5B,oCAAoC;;;;;;;;;;EAEpC,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;EAI3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,oBAAoB;IAC/B,mFAAmF;;IAEnF,uFAAuF;;IAEvF;;;;OAIG;;;;;;;;;;EAEH,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB;IAC3B,yFAAyF;;IAEzF,8GAA8G;;;;;;;;EAE9G,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,sBAAsB;;;QAtF7B,kHAAkH;;QAElH;;;;;;;;WAQG;;;;;;;;;;;;QAOH,6DAA6D;;;;;;;;;;QAQjE,qFAAqF;;QAErF,8EAA8E;;QAE9E,2EAA2E;;;;;;;;;;;IA4D3E,6GAA6G;;;;;;;;;;;;;;;IAG7G,8EAA8E;;IAE9E;;;OAGG;;;QA7CH,mFAAmF;;QAEnF,uFAAuF;;QAEvF;;;;WAIG;;;;;;;;;;;;QAzBH,mEAAmE;;QAEnE,4BAA4B;;QAE5B,oCAAoC;;;;;;;;;;;IA8DpC,oDAAoD;;QAtBpD,yFAAyF;;QAEzF,8GAA8G;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsB9G,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAItE;;;;GAIG;AACH,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;EASzC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;YAlIlC,kHAAkH;;YAElH;;;;;;;;eAQG;;;;;;;;;;;;YAOH,6DAA6D;;;;;;;;;;YAQjE,qFAAqF;;YAErF,8EAA8E;;YAE9E,2EAA2E;;;;;;;;;;;QA4D3E,6GAA6G;;;;;;;;;;;;;;;QAG7G,8EAA8E;;QAE9E;;;WAGG;;;YA7CH,mFAAmF;;YAEnF,uFAAuF;;YAEvF;;;;eAIG;;;;;;;;;;;;YAzBH,mEAAmE;;YAEnE,4BAA4B;;YAE5B,oCAAoC;;;;;;;;;;;QA8DpC,oDAAoD;;YAtBpD,yFAAyF;;YAEzF,8GAA8G;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmD9G,CAAC;AAEH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC"}
|
|
@@ -101,6 +101,25 @@ export const MilestoneStateSchema = z.object({
|
|
|
101
101
|
*/
|
|
102
102
|
bestEffort: z.literal(true),
|
|
103
103
|
});
|
|
104
|
+
/**
|
|
105
|
+
* Knowledge-index freshness signal (mmnto-ai/totem#2029 — docs-drift Mech C).
|
|
106
|
+
*
|
|
107
|
+
* Sourced from `.totem/cache/index-meta.json.lastSync` (authoritative, written
|
|
108
|
+
* on every successful `runSync`) with `.totem/index-manifest.json.writtenAt`
|
|
109
|
+
* as fallback. Both fields are null on lite-tier configurations or before
|
|
110
|
+
* the first sync has completed — honest absence per Tenet 14.
|
|
111
|
+
*
|
|
112
|
+
* v1 surfaces envelope-level staleness only. Per-result `indexedAt` is OUT
|
|
113
|
+
* of scope because LanceDB rows do not currently carry per-row sync
|
|
114
|
+
* timestamps; populating a per-result `indexedAt` from the constant manifest
|
|
115
|
+
* value would be fake-presence data.
|
|
116
|
+
*/
|
|
117
|
+
export const IndexStateSchema = z.object({
|
|
118
|
+
/** ISO-8601 Z timestamp of last successful sync. Null on lite tier or pre-first-sync. */
|
|
119
|
+
lastSyncAt: z.string().nullable(),
|
|
120
|
+
/** Human-readable relative time, e.g. "5 minutes ago", "STALE: 14 days ago". Null when lastSyncAt is null. */
|
|
121
|
+
staleness: z.string().nullable(),
|
|
122
|
+
});
|
|
104
123
|
export const RichProjectStateSchema = z.object({
|
|
105
124
|
strategyPointer: StrategyPointerSchema,
|
|
106
125
|
gitState: GitStateSchema,
|
|
@@ -116,6 +135,8 @@ export const RichProjectStateSchema = z.object({
|
|
|
116
135
|
testCount: z.number().int().nonnegative().nullable(),
|
|
117
136
|
milestone: MilestoneStateSchema,
|
|
118
137
|
recentPrs: z.array(RecentPrSchema),
|
|
138
|
+
/** Index-freshness signal (mmnto-ai/totem#2029). */
|
|
139
|
+
indexState: IndexStateSchema,
|
|
119
140
|
});
|
|
120
141
|
// ─── Output ────────────────────────────────────────────────────────────────
|
|
121
142
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe-project.js","sourceRoot":"","sources":["../../src/schemas/describe-project.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"describe-project.js","sourceRoot":"","sources":["../../src/schemas/describe-project.ts"],"names":[],"mappings":"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"}
|
|
@@ -45,6 +45,7 @@ describe('DescribeProjectOutputSchema backward compatibility', () => {
|
|
|
45
45
|
testCount: null,
|
|
46
46
|
milestone: { name: '1.15.0', gateTickets: ['#1479'], bestEffort: true },
|
|
47
47
|
recentPrs: [{ title: 'feat: foo (#1)', date: '2026-04-16T00:00:00Z', squashSha: 'abcd123' }],
|
|
48
|
+
indexState: { lastSyncAt: null, staleness: null },
|
|
48
49
|
};
|
|
49
50
|
const parsed = DescribeProjectOutputSchema.parse({ ...legacyShape, richState: rich });
|
|
50
51
|
expect(parsed.richState?.ruleCounts.active).toBe(10);
|
|
@@ -177,6 +178,7 @@ describe('RichProjectStateSchema', () => {
|
|
|
177
178
|
testCount: null,
|
|
178
179
|
milestone: { name: null, gateTickets: [], bestEffort: true },
|
|
179
180
|
recentPrs: [],
|
|
181
|
+
indexState: { lastSyncAt: null, staleness: null },
|
|
180
182
|
});
|
|
181
183
|
expect(parsed.testCount).toBeNull();
|
|
182
184
|
});
|
|
@@ -190,11 +192,41 @@ describe('RichProjectStateSchema', () => {
|
|
|
190
192
|
testCount: null,
|
|
191
193
|
milestone: { name: null, gateTickets: [], bestEffort: true },
|
|
192
194
|
recentPrs: [],
|
|
195
|
+
indexState: { lastSyncAt: null, staleness: null },
|
|
193
196
|
});
|
|
194
197
|
if (!parsed.strategyPointer.resolved) {
|
|
195
198
|
expect(parsed.strategyPointer.reason).toBe('no sibling, no submodule');
|
|
196
199
|
}
|
|
197
200
|
});
|
|
201
|
+
it('requires indexState (mmnto-ai/totem#2029) and accepts populated values', () => {
|
|
202
|
+
const parsed = RichProjectStateSchema.parse({
|
|
203
|
+
strategyPointer: { resolved: true, sha: null, latestJournal: null },
|
|
204
|
+
gitState: { branch: null, uncommittedFiles: [], truncated: false },
|
|
205
|
+
packageVersions: {},
|
|
206
|
+
ruleCounts: { active: 0, archived: 0, nonCompilable: 0 },
|
|
207
|
+
lessonCount: 0,
|
|
208
|
+
testCount: null,
|
|
209
|
+
milestone: { name: null, gateTickets: [], bestEffort: true },
|
|
210
|
+
recentPrs: [],
|
|
211
|
+
indexState: { lastSyncAt: '2026-05-25T17:44:58.714Z', staleness: '3 hours ago' },
|
|
212
|
+
});
|
|
213
|
+
expect(parsed.indexState.lastSyncAt).toBe('2026-05-25T17:44:58.714Z');
|
|
214
|
+
expect(parsed.indexState.staleness).toBe('3 hours ago');
|
|
215
|
+
});
|
|
216
|
+
it('rejects rich-state payloads missing indexState', () => {
|
|
217
|
+
const result = RichProjectStateSchema.safeParse({
|
|
218
|
+
strategyPointer: { resolved: true, sha: null, latestJournal: null },
|
|
219
|
+
gitState: { branch: null, uncommittedFiles: [], truncated: false },
|
|
220
|
+
packageVersions: {},
|
|
221
|
+
ruleCounts: { active: 0, archived: 0, nonCompilable: 0 },
|
|
222
|
+
lessonCount: 0,
|
|
223
|
+
testCount: null,
|
|
224
|
+
milestone: { name: null, gateTickets: [], bestEffort: true },
|
|
225
|
+
recentPrs: [],
|
|
226
|
+
// indexState intentionally omitted
|
|
227
|
+
});
|
|
228
|
+
expect(result.success).toBe(false);
|
|
229
|
+
});
|
|
198
230
|
});
|
|
199
231
|
describe('constants', () => {
|
|
200
232
|
it('caps match the design doc', () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe-project.test.js","sourceRoot":"","sources":["../../src/schemas/describe-project.test.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"describe-project.test.js","sourceRoot":"","sources":["../../src/schemas/describe-project.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAE/B,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,MAAM,GAAG,0BAA0B,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,MAAM,GAAG,0BAA0B,CAAC,KAAK,CAAC,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7E,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,MAAM,GAAG,0BAA0B,CAAC,KAAK,CAAC,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5E,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,GAAG,EAAE,CAAC,0BAA0B,CAAC,KAAK,CAAC,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;IACxF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oDAAoD,EAAE,GAAG,EAAE;IAClE,MAAM,WAAW,GAAG;QAClB,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,UAAmB;QACzB,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,CAAC,+BAA+B,CAAC;QAC1C,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,gBAAgB,CAAC,EAAE;QACxC,KAAK,EAAE,CAAC,UAAU,CAAC;KACpB,CAAC;IAEF,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,MAAM,GAAG,2BAA2B,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC9D,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,aAAa,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,IAAI,GAAG;YACX,eAAe,EAAE;gBACf,QAAQ,EAAE,IAAa;gBACvB,GAAG,EAAE,SAAS;gBACd,aAAa,EAAE,uBAAuB;aACvC;YACD,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE;YACpE,eAAe,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE;YAC5C,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YACzD,WAAW,EAAE,CAAC;YACd,SAAS,EAAE,IAAI;YACf,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,IAAa,EAAE;YAChF,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,sBAAsB,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;YAC5F,UAAU,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;SAClD,CAAC;QACF,MAAM,MAAM,GAAG,2BAA2B,CAAC,KAAK,CAAC,EAAE,GAAG,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtF,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,GAAG,EAAE,CACV,2BAA2B,CAAC,KAAK,CAAC;YAChC,GAAG,WAAW;YACd,SAAS,EAAE,EAAE,eAAe,EAAE,eAAe,EAAE;SAChD,CAAC,CACH,CAAC,OAAO,EAAE,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9F,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC;YAClC,MAAM,EAAE,MAAM;YACd,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;YAClC,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;IAChG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;IACjG,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,GAAG,EAAE,CACV,oBAAoB,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAC/E,CAAC,OAAO,EAAE,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC;YACxC,IAAI,EAAE,IAAI;YACV,WAAW,EAAE,EAAE;YACf,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,6CAA6C,EAAE,GAAG,EAAE;IAC3D,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC;YACzC,QAAQ,EAAE,IAAI;YACd,GAAG,EAAE,IAAI;YACT,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC9B,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC;YACzC,QAAQ,EAAE,IAAI;YACd,GAAG,EAAE,SAAS;YACd,aAAa,EAAE,+CAA+C;SAC/D,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC;YACzC,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,+DAA+D;SACxE,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,QAAQ,EAAE,IAAI;YACd,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,QAAQ,EAAE,KAAK;YACf,GAAG,EAAE,SAAS;YACd,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,uEAAuE;QACvE,oEAAoE;QACpE,mEAAmE;QACnE,8CAA8C;QAC9C,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,QAAQ,EAAE,IAAI;YACd,GAAG,EAAE,SAAS;YACd,aAAa,EAAE,IAAI;YACnB,MAAM,EAAE,mBAAmB;SAC5B,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC;YAC7C,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,8BAA8B;YACtC,aAAa,EAAE,sBAAsB;SACtC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC;YAC1C,eAAe,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;YACnE,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE;YAClE,eAAe,EAAE,EAAE;YACnB,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YACxD,WAAW,EAAE,CAAC;YACd,SAAS,EAAE,IAAI;YACf,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;YAC5D,SAAS,EAAE,EAAE;YACb,UAAU,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;SAClD,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC;YAC1C,eAAe,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,0BAA0B,EAAE;YACxE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE;YACpE,eAAe,EAAE,EAAE;YACnB,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YACxD,WAAW,EAAE,CAAC;YACd,SAAS,EAAE,IAAI;YACf,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;YAC5D,SAAS,EAAE,EAAE;YACb,UAAU,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;SAClD,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACzE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC;YAC1C,eAAe,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;YACnE,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE;YAClE,eAAe,EAAE,EAAE;YACnB,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YACxD,WAAW,EAAE,CAAC;YACd,SAAS,EAAE,IAAI;YACf,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;YAC5D,SAAS,EAAE,EAAE;YACb,UAAU,EAAE,EAAE,UAAU,EAAE,0BAA0B,EAAE,SAAS,EAAE,aAAa,EAAE;SACjF,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACtE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC;YAC9C,eAAe,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;YACnE,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE;YAClE,eAAe,EAAE,EAAE;YACnB,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;YACxD,WAAW,EAAE,CAAC;YACd,SAAS,EAAE,IAAI;YACf,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;YAC5D,SAAS,EAAE,EAAE;YACb,mCAAmC;SACpC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relative-time formatter for the MCP index-state envelope (mmnto-ai/totem#2029).
|
|
3
|
+
*
|
|
4
|
+
* Computes a human-readable staleness string from an ISO-8601 timestamp,
|
|
5
|
+
* e.g. "5 minutes ago", "3 hours ago", "2 days ago". Prefixes "STALE: "
|
|
6
|
+
* when the timestamp exceeds the staleness threshold (default 7 days).
|
|
7
|
+
*
|
|
8
|
+
* Pure function — no filesystem reads, no I/O. The `now` parameter is
|
|
9
|
+
* injectable for deterministic testing.
|
|
10
|
+
*/
|
|
11
|
+
/** Days threshold beyond which the STALE: prefix is applied. */
|
|
12
|
+
export declare const STALE_THRESHOLD_DAYS = 7;
|
|
13
|
+
/**
|
|
14
|
+
* Format an ISO-8601 timestamp as a human-readable staleness string.
|
|
15
|
+
*
|
|
16
|
+
* Returns null when the input is null OR fails to parse — callers treat
|
|
17
|
+
* null as "no index timestamp available" (honest absence per Tenet 14).
|
|
18
|
+
*
|
|
19
|
+
* Future timestamps (clock skew) return 'just synced' rather than a
|
|
20
|
+
* negative-duration string — safer for Docker/VM clock-drift environments
|
|
21
|
+
* where small forward skews are common.
|
|
22
|
+
*/
|
|
23
|
+
export declare function formatStaleness(isoStamp: string | null, now?: Date): string | null;
|
|
24
|
+
//# sourceMappingURL=staleness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staleness.d.ts","sourceRoot":"","sources":["../src/staleness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,gEAAgE;AAChE,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,GAAE,IAAiB,GAAG,MAAM,GAAG,IAAI,CA4B9F"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relative-time formatter for the MCP index-state envelope (mmnto-ai/totem#2029).
|
|
3
|
+
*
|
|
4
|
+
* Computes a human-readable staleness string from an ISO-8601 timestamp,
|
|
5
|
+
* e.g. "5 minutes ago", "3 hours ago", "2 days ago". Prefixes "STALE: "
|
|
6
|
+
* when the timestamp exceeds the staleness threshold (default 7 days).
|
|
7
|
+
*
|
|
8
|
+
* Pure function — no filesystem reads, no I/O. The `now` parameter is
|
|
9
|
+
* injectable for deterministic testing.
|
|
10
|
+
*/
|
|
11
|
+
/** Days threshold beyond which the STALE: prefix is applied. */
|
|
12
|
+
export const STALE_THRESHOLD_DAYS = 7;
|
|
13
|
+
/**
|
|
14
|
+
* Format an ISO-8601 timestamp as a human-readable staleness string.
|
|
15
|
+
*
|
|
16
|
+
* Returns null when the input is null OR fails to parse — callers treat
|
|
17
|
+
* null as "no index timestamp available" (honest absence per Tenet 14).
|
|
18
|
+
*
|
|
19
|
+
* Future timestamps (clock skew) return 'just synced' rather than a
|
|
20
|
+
* negative-duration string — safer for Docker/VM clock-drift environments
|
|
21
|
+
* where small forward skews are common.
|
|
22
|
+
*/
|
|
23
|
+
export function formatStaleness(isoStamp, now = new Date()) {
|
|
24
|
+
if (isoStamp === null)
|
|
25
|
+
return null;
|
|
26
|
+
const then = Date.parse(isoStamp);
|
|
27
|
+
if (Number.isNaN(then))
|
|
28
|
+
return null;
|
|
29
|
+
const diffMs = now.getTime() - then;
|
|
30
|
+
if (diffMs < 0)
|
|
31
|
+
return 'just synced';
|
|
32
|
+
const diffSec = Math.floor(diffMs / 1000);
|
|
33
|
+
if (diffSec < 60)
|
|
34
|
+
return 'just synced';
|
|
35
|
+
const diffMin = Math.floor(diffSec / 60);
|
|
36
|
+
if (diffMin < 60)
|
|
37
|
+
return `${diffMin} minute${diffMin === 1 ? '' : 's'} ago`;
|
|
38
|
+
const diffHr = Math.floor(diffMin / 60);
|
|
39
|
+
if (diffHr < 24)
|
|
40
|
+
return `${diffHr} hour${diffHr === 1 ? '' : 's'} ago`;
|
|
41
|
+
const diffDay = Math.floor(diffHr / 24);
|
|
42
|
+
const stalePrefix = diffDay >= STALE_THRESHOLD_DAYS ? 'STALE: ' : '';
|
|
43
|
+
const dayBody = `${diffDay} day${diffDay === 1 ? '' : 's'} ago`;
|
|
44
|
+
if (diffDay < 7)
|
|
45
|
+
return stalePrefix + dayBody;
|
|
46
|
+
const diffWk = Math.floor(diffDay / 7);
|
|
47
|
+
const weekBody = `${diffWk} week${diffWk === 1 ? '' : 's'} ago`;
|
|
48
|
+
if (diffWk < 4)
|
|
49
|
+
return stalePrefix + weekBody;
|
|
50
|
+
return stalePrefix + `${diffDay} days ago`;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=staleness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staleness.js","sourceRoot":"","sources":["../src/staleness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,gEAAgE;AAChE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAEtC;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,QAAuB,EAAE,MAAY,IAAI,IAAI,EAAE;IAC7E,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpC,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;IACpC,IAAI,MAAM,GAAG,CAAC;QAAE,OAAO,aAAa,CAAC;IAErC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1C,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,aAAa,CAAC;IAEvC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACzC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,UAAU,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;IAE5E,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACxC,IAAI,MAAM,GAAG,EAAE;QAAE,OAAO,GAAG,MAAM,QAAQ,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;IAEvE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,OAAO,IAAI,oBAAoB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IAErE,MAAM,OAAO,GAAG,GAAG,OAAO,OAAO,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;IAChE,IAAI,OAAO,GAAG,CAAC;QAAE,OAAO,WAAW,GAAG,OAAO,CAAC;IAE9C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,GAAG,MAAM,QAAQ,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;IAChE,IAAI,MAAM,GAAG,CAAC;QAAE,OAAO,WAAW,GAAG,QAAQ,CAAC;IAE9C,OAAO,WAAW,GAAG,GAAG,OAAO,WAAW,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staleness.test.d.ts","sourceRoot":"","sources":["../src/staleness.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { formatStaleness, STALE_THRESHOLD_DAYS } from './staleness.js';
|
|
3
|
+
describe('formatStaleness', () => {
|
|
4
|
+
// Fixed reference time so every case is deterministic.
|
|
5
|
+
const NOW = new Date('2026-05-25T20:00:00.000Z');
|
|
6
|
+
it('returns null when the input is null', () => {
|
|
7
|
+
expect(formatStaleness(null, NOW)).toBeNull();
|
|
8
|
+
});
|
|
9
|
+
it('returns null when the input is not a parseable ISO string', () => {
|
|
10
|
+
expect(formatStaleness('not-a-date', NOW)).toBeNull();
|
|
11
|
+
expect(formatStaleness('', NOW)).toBeNull();
|
|
12
|
+
});
|
|
13
|
+
it('returns "just synced" for timestamps within the last minute', () => {
|
|
14
|
+
expect(formatStaleness('2026-05-25T19:59:30.000Z', NOW)).toBe('just synced');
|
|
15
|
+
expect(formatStaleness('2026-05-25T19:59:01.000Z', NOW)).toBe('just synced');
|
|
16
|
+
});
|
|
17
|
+
it('returns "just synced" for future timestamps (clock-skew safety)', () => {
|
|
18
|
+
expect(formatStaleness('2026-05-25T20:00:30.000Z', NOW)).toBe('just synced');
|
|
19
|
+
expect(formatStaleness('2026-05-26T00:00:00.000Z', NOW)).toBe('just synced');
|
|
20
|
+
});
|
|
21
|
+
it('formats minute-scale staleness with singular/plural agreement', () => {
|
|
22
|
+
expect(formatStaleness('2026-05-25T19:59:00.000Z', NOW)).toBe('1 minute ago');
|
|
23
|
+
expect(formatStaleness('2026-05-25T19:58:00.000Z', NOW)).toBe('2 minutes ago');
|
|
24
|
+
expect(formatStaleness('2026-05-25T19:55:00.000Z', NOW)).toBe('5 minutes ago');
|
|
25
|
+
expect(formatStaleness('2026-05-25T19:01:00.000Z', NOW)).toBe('59 minutes ago');
|
|
26
|
+
});
|
|
27
|
+
it('formats hour-scale staleness with singular/plural agreement', () => {
|
|
28
|
+
expect(formatStaleness('2026-05-25T19:00:00.000Z', NOW)).toBe('1 hour ago');
|
|
29
|
+
expect(formatStaleness('2026-05-25T17:00:00.000Z', NOW)).toBe('3 hours ago');
|
|
30
|
+
expect(formatStaleness('2026-05-24T21:00:00.000Z', NOW)).toBe('23 hours ago');
|
|
31
|
+
});
|
|
32
|
+
it('formats day-scale staleness for under-week durations', () => {
|
|
33
|
+
expect(formatStaleness('2026-05-24T20:00:00.000Z', NOW)).toBe('1 day ago');
|
|
34
|
+
expect(formatStaleness('2026-05-22T20:00:00.000Z', NOW)).toBe('3 days ago');
|
|
35
|
+
expect(formatStaleness('2026-05-20T20:00:00.000Z', NOW)).toBe('5 days ago');
|
|
36
|
+
});
|
|
37
|
+
it('prefixes STALE: at exactly the threshold and beyond (day scale)', () => {
|
|
38
|
+
// 6 days ago → no STALE
|
|
39
|
+
expect(formatStaleness('2026-05-19T20:00:00.000Z', NOW)).toBe('6 days ago');
|
|
40
|
+
// 7 days ago → STALE prefix kicks in (week-scale formatter rounds to 1 week)
|
|
41
|
+
const sevenDaysAgo = new Date(NOW.getTime() - STALE_THRESHOLD_DAYS * 24 * 60 * 60 * 1000);
|
|
42
|
+
expect(formatStaleness(sevenDaysAgo.toISOString(), NOW)).toBe('STALE: 1 week ago');
|
|
43
|
+
});
|
|
44
|
+
it('formats week-scale staleness with STALE prefix and plural agreement', () => {
|
|
45
|
+
expect(formatStaleness('2026-05-18T20:00:00.000Z', NOW)).toBe('STALE: 1 week ago');
|
|
46
|
+
expect(formatStaleness('2026-05-11T20:00:00.000Z', NOW)).toBe('STALE: 2 weeks ago');
|
|
47
|
+
expect(formatStaleness('2026-05-04T20:00:00.000Z', NOW)).toBe('STALE: 3 weeks ago');
|
|
48
|
+
});
|
|
49
|
+
it('falls back to day-count formatting for staleness beyond 4 weeks', () => {
|
|
50
|
+
expect(formatStaleness('2026-04-25T20:00:00.000Z', NOW)).toBe('STALE: 30 days ago');
|
|
51
|
+
expect(formatStaleness('2025-11-25T20:00:00.000Z', NOW)).toBe('STALE: 181 days ago');
|
|
52
|
+
});
|
|
53
|
+
it('uses real-time now when the now parameter is omitted', () => {
|
|
54
|
+
// Smoke test: invocation without explicit now must not throw and must
|
|
55
|
+
// return a non-null result for a past timestamp.
|
|
56
|
+
const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
|
|
57
|
+
const result = formatStaleness(yesterday);
|
|
58
|
+
expect(result).not.toBeNull();
|
|
59
|
+
expect(typeof result).toBe('string');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=staleness.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staleness.test.js","sourceRoot":"","sources":["../src/staleness.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* calls. Every function reads only from disk or local git state.
|
|
11
11
|
*/
|
|
12
12
|
import { type StrategyResolverConfig, type SubstrateResolverConfig } from '@mmnto/totem';
|
|
13
|
-
import { type GitState, type MilestoneState, type RecentPr, type RuleCounts, type StrategyPointer } from './schemas/describe-project.js';
|
|
13
|
+
import { type GitState, type IndexState, type MilestoneState, type RecentPr, type RuleCounts, type StrategyPointer } from './schemas/describe-project.js';
|
|
14
14
|
export declare function extractGitState(cwd: string): GitState;
|
|
15
15
|
/**
|
|
16
16
|
* Resolve the strategy-state pointer for the MCP `describe_project` payload
|
|
@@ -54,6 +54,21 @@ export declare function extractMilestoneState(cwd: string): MilestoneState;
|
|
|
54
54
|
* number.
|
|
55
55
|
*/
|
|
56
56
|
export declare function extractTestCount(_cwd: string): number | null;
|
|
57
|
+
/**
|
|
58
|
+
* Read the last-sync timestamp from `.totem/cache/index-meta.json` (the
|
|
59
|
+
* authoritative source written on every successful `runSync`) with
|
|
60
|
+
* `.totem/index-manifest.json.writtenAt` as a fallback. Returns null
|
|
61
|
+
* fields on lite-tier configurations and pre-first-sync state — honest
|
|
62
|
+
* absence per Tenet 14.
|
|
63
|
+
*
|
|
64
|
+
* Two-level fallback: index-manifest.json is the more visible artifact
|
|
65
|
+
* and may be hand-restored from git history in some recovery flows.
|
|
66
|
+
*
|
|
67
|
+
* The staleness string is computed by `formatStaleness` against the
|
|
68
|
+
* current wall clock so consumers see "5 minutes ago" / "STALE: 14 days
|
|
69
|
+
* ago" without re-deriving the relative time themselves.
|
|
70
|
+
*/
|
|
71
|
+
export declare function extractIndexState(cwd: string, totemDir: string): IndexState;
|
|
57
72
|
/**
|
|
58
73
|
* Capture squash-merge commits whose subject references a PR number
|
|
59
74
|
* (`... (#NNNN)`). Skips commits whose message lacks a PR tag so we do not
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-extractors.d.ts","sourceRoot":"","sources":["../src/state-extractors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAQL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC7B,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,cAAc,EAEnB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,eAAe,EAErB,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"state-extractors.d.ts","sourceRoot":"","sources":["../src/state-extractors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAQL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC7B,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,cAAc,EAEnB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,eAAe,EAErB,MAAM,+BAA+B,CAAC;AAcvC,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CA+BrD;AAID;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,sBAAsB,GAAG,uBAAuB,GACxD,eAAe,CAyEjB;AAID,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkC1E;AAID,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,CAuB3E;AAID,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CASxE;AAID;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAoCjE;AAID;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE5D;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,CAwC3E;AAID;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,SAAmB,GAAG,QAAQ,EAAE,CAyClF"}
|
package/dist/state-extractors.js
CHANGED
|
@@ -13,6 +13,7 @@ import * as fs from 'node:fs';
|
|
|
13
13
|
import * as path from 'node:path';
|
|
14
14
|
import { CompiledRulesFileSchema, readJsonSafe, resolveGitRoot, resolveOrchestrationPaths, resolveStrategyRoot, resolveSubstratePaths, safeExec, } from '@mmnto/totem';
|
|
15
15
|
import { RECENT_PRS_COUNT, UNCOMMITTED_FILES_CAP, } from './schemas/describe-project.js';
|
|
16
|
+
import { formatStaleness } from './staleness.js';
|
|
16
17
|
/** Fixed-group package names whose versions show in the briefing. */
|
|
17
18
|
const FIXED_GROUP_PACKAGES = [
|
|
18
19
|
'@mmnto/totem',
|
|
@@ -280,6 +281,62 @@ export function extractMilestoneState(cwd) {
|
|
|
280
281
|
export function extractTestCount(_cwd) {
|
|
281
282
|
return null;
|
|
282
283
|
}
|
|
284
|
+
// ─── Knowledge-index freshness (mmnto-ai/totem#2029) ──────────────────────
|
|
285
|
+
/**
|
|
286
|
+
* Read the last-sync timestamp from `.totem/cache/index-meta.json` (the
|
|
287
|
+
* authoritative source written on every successful `runSync`) with
|
|
288
|
+
* `.totem/index-manifest.json.writtenAt` as a fallback. Returns null
|
|
289
|
+
* fields on lite-tier configurations and pre-first-sync state — honest
|
|
290
|
+
* absence per Tenet 14.
|
|
291
|
+
*
|
|
292
|
+
* Two-level fallback: index-manifest.json is the more visible artifact
|
|
293
|
+
* and may be hand-restored from git history in some recovery flows.
|
|
294
|
+
*
|
|
295
|
+
* The staleness string is computed by `formatStaleness` against the
|
|
296
|
+
* current wall clock so consumers see "5 minutes ago" / "STALE: 14 days
|
|
297
|
+
* ago" without re-deriving the relative time themselves.
|
|
298
|
+
*/
|
|
299
|
+
export function extractIndexState(cwd, totemDir) {
|
|
300
|
+
// Validate the parsed timestamp via `formatStaleness` — when input is
|
|
301
|
+
// unparseable as ISO-8601, `formatStaleness` returns null. Returning a
|
|
302
|
+
// populated `lastSyncAt` with `staleness: null` would break the "no-index
|
|
303
|
+
// vs indexed" signal contract: callers couldn't distinguish lite-tier
|
|
304
|
+
// (both null) from corrupt-timestamp (string + null). Fall through to the
|
|
305
|
+
// next source on parse failure (CR R1 catch on mmnto-ai/totem#2033).
|
|
306
|
+
const metaPath = path.join(cwd, totemDir, 'cache', 'index-meta.json');
|
|
307
|
+
if (fs.existsSync(metaPath)) {
|
|
308
|
+
try {
|
|
309
|
+
const parsed = readJsonSafe(metaPath);
|
|
310
|
+
if (typeof parsed.lastSync === 'string') {
|
|
311
|
+
const staleness = formatStaleness(parsed.lastSync);
|
|
312
|
+
if (staleness !== null) {
|
|
313
|
+
return { lastSyncAt: parsed.lastSync, staleness };
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// totem-context: ADR-090 substrate graceful degradation — fall through to manifest on shape miss or unparseable timestamp.
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
// totem-context: ADR-090 substrate graceful degradation — best-effort cache read; fall through to manifest.
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
const manifestPath = path.join(cwd, totemDir, 'index-manifest.json');
|
|
323
|
+
if (fs.existsSync(manifestPath)) {
|
|
324
|
+
try {
|
|
325
|
+
const parsed = readJsonSafe(manifestPath);
|
|
326
|
+
if (typeof parsed.writtenAt === 'string') {
|
|
327
|
+
const staleness = formatStaleness(parsed.writtenAt);
|
|
328
|
+
if (staleness !== null) {
|
|
329
|
+
return { lastSyncAt: parsed.writtenAt, staleness };
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// totem-context: ADR-090 substrate graceful degradation — null on shape miss or unparseable timestamp.
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
// totem-context: ADR-090 substrate graceful degradation — best-effort manifest read; return null shape.
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return { lastSyncAt: null, staleness: null };
|
|
339
|
+
}
|
|
283
340
|
// ─── Recent merged PRs from git log ────────────────────────────────────────
|
|
284
341
|
/**
|
|
285
342
|
* Capture squash-merge commits whose subject references a PR number
|