@bli-cockpit/telemetry-core 0.1.33 → 0.1.34

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.
@@ -105,6 +105,7 @@ export declare const CollectorHeartbeatSchema: z.ZodObject<{
105
105
  hook_timeouts_24h: z.ZodOptional<z.ZodNumber>;
106
106
  hook_printed_24h: z.ZodOptional<z.ZodNumber>;
107
107
  hook_failed_24h: z.ZodOptional<z.ZodNumber>;
108
+ hook_skipped_trivial_24h: z.ZodOptional<z.ZodNumber>;
108
109
  hook_stats_reason: z.ZodOptional<z.ZodString>;
109
110
  hook_performance: z.ZodOptional<z.ZodObject<{
110
111
  schema_version: z.ZodLiteral<"memory-hook-performance.v1">;
@@ -45,6 +45,7 @@ export declare const MemoryHookCountsSchema: z.ZodObject<{
45
45
  timeouts: z.ZodNumber;
46
46
  failed: z.ZodNumber;
47
47
  skipped: z.ZodNumber;
48
+ skipped_trivial: z.ZodOptional<z.ZodNumber>;
48
49
  }, z.core.$strict>;
49
50
  export type MemoryHookCounts = z.infer<typeof MemoryHookCountsSchema>;
50
51
  /** `YYYY-MM-DDTHH` in UTC — the bucket key, and the reason the window is exact. */
@@ -62,6 +63,7 @@ export declare const MemoryHookStatsFileSchema: z.ZodObject<{
62
63
  timeouts: z.ZodNumber;
63
64
  failed: z.ZodNumber;
64
65
  skipped: z.ZodNumber;
66
+ skipped_trivial: z.ZodOptional<z.ZodNumber>;
65
67
  }, z.core.$strict>>>;
66
68
  }, z.core.$strict>;
67
69
  export type MemoryHookStatsFile = z.infer<typeof MemoryHookStatsFileSchema>;
@@ -74,6 +76,8 @@ export interface MemoryHookWindow {
74
76
  printed: number;
75
77
  timeouts: number;
76
78
  failed: number;
79
+ /** Trivial prompts the hook declined to search for (BLI-3881). A subset of skips. */
80
+ skippedTrivial: number;
77
81
  /** Buckets that were inside the window and had something in them. */
78
82
  hours: number;
79
83
  }
@@ -46,6 +46,23 @@ export const MemoryHookCountsSchema = z
46
46
  timeouts: z.number().int().min(0),
47
47
  failed: z.number().int().min(0),
48
48
  skipped: z.number().int().min(0),
49
+ /**
50
+ * BLI-3881 — the SUBSET of `skipped` the hook declined to search for.
51
+ *
52
+ * "ok", "continue", "y", a slash command: a turn whose whole text carries
53
+ * no subject to recall against. Searching one spends a person's whole
54
+ * budget on a query that can only return noise, so the hook returns early
55
+ * and this counts how often — because a hook that stops doing something
56
+ * and says nothing is indistinguishable from a hook that broke.
57
+ *
58
+ * OPTIONAL, and it must stay optional: a file written by a memory-mcp
59
+ * older than this ticket has no such key, and `MemoryHookCountsSchema` is
60
+ * strict, so a required field would make every existing machine's history
61
+ * `hook_stats_unrecognised_shape` overnight. It is counted BESIDE
62
+ * `skipped`, never instead of it, so `runs = printed + empty + timeouts +
63
+ * failed + skipped` still holds.
64
+ */
65
+ skipped_trivial: z.number().int().min(0).optional(),
49
66
  })
50
67
  .strict();
51
68
  /** `YYYY-MM-DDTHH` in UTC — the bucket key, and the reason the window is exact. */
@@ -69,7 +86,7 @@ export function memoryHookHourBucket(at) {
69
86
  return at.toISOString().slice(0, 13);
70
87
  }
71
88
  export function emptyMemoryHookCounts() {
72
- return { runs: 0, printed: 0, empty: 0, timeouts: 0, failed: 0, skipped: 0 };
89
+ return { runs: 0, printed: 0, empty: 0, timeouts: 0, failed: 0, skipped: 0, skipped_trivial: 0 };
73
90
  }
74
91
  /**
75
92
  * Sum one event's buckets over the last `hours` hours, ending at `now`.
@@ -83,7 +100,14 @@ export function summariseMemoryHookWindow(file, event, options) {
83
100
  const hours = options.hours ?? 24;
84
101
  const earliest = memoryHookHourBucket(new Date(options.now.getTime() - (hours - 1) * 3_600_000));
85
102
  const latest = memoryHookHourBucket(options.now);
86
- const total = { runs: 0, printed: 0, timeouts: 0, failed: 0, hours: 0 };
103
+ const total = {
104
+ runs: 0,
105
+ printed: 0,
106
+ timeouts: 0,
107
+ failed: 0,
108
+ skippedTrivial: 0,
109
+ hours: 0,
110
+ };
87
111
  for (const [bucket, events] of Object.entries(file.buckets)) {
88
112
  // Lexical order is chronological for this key, which is the only reason a
89
113
  // string comparison is allowed to stand in for a date one here.
@@ -96,6 +120,9 @@ export function summariseMemoryHookWindow(file, event, options) {
96
120
  total.printed += counts.printed;
97
121
  total.timeouts += counts.timeouts;
98
122
  total.failed += counts.failed;
123
+ // Absent means an older writer never counted one, which sums as zero and
124
+ // is honest: that machine genuinely skipped none, because it could not.
125
+ total.skippedTrivial += counts.skipped_trivial ?? 0;
99
126
  total.hours += 1;
100
127
  }
101
128
  return total;
@@ -113,6 +113,7 @@ export declare const MemoryInstallReceiptSchema: z.ZodObject<{
113
113
  hook_timeouts_24h: z.ZodOptional<z.ZodNumber>;
114
114
  hook_printed_24h: z.ZodOptional<z.ZodNumber>;
115
115
  hook_failed_24h: z.ZodOptional<z.ZodNumber>;
116
+ hook_skipped_trivial_24h: z.ZodOptional<z.ZodNumber>;
116
117
  hook_stats_reason: z.ZodOptional<z.ZodString>;
117
118
  hook_performance: z.ZodOptional<z.ZodObject<{
118
119
  schema_version: z.ZodLiteral<"memory-hook-performance.v1">;
@@ -132,6 +132,15 @@ export const MemoryInstallReceiptSchema = z
132
132
  hook_timeouts_24h: z.number().int().min(0).optional(),
133
133
  hook_printed_24h: z.number().int().min(0).optional(),
134
134
  hook_failed_24h: z.number().int().min(0).optional(),
135
+ /**
136
+ * BLI-3881: runs the hook DECLINED to search for — "ok", "continue", a
137
+ * slash command. It is a subset of the skips inside `hook_runs_24h`, and
138
+ * it exists because a hook that quietly stops searching looks exactly like
139
+ * a hook that broke. Optional like the four above: absent means the
140
+ * machine is on a memory-mcp older than the rule, never that it skipped
141
+ * none.
142
+ */
143
+ hook_skipped_trivial_24h: z.number().int().min(0).optional(),
135
144
  /** Named when the counts are absent because the file could not be read. */
136
145
  hook_stats_reason: ReasonLabelSchema.optional(),
137
146
  /** Observed ordinary invocations, not legacy floors or a full host trace. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bli-cockpit/telemetry-core",
3
- "version": "0.1.33",
3
+ "version": "0.1.34",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",