@mnemom/mnemom 0.17.7 → 0.17.8

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.
@@ -1,27 +1,45 @@
1
1
  /**
2
2
  * The first-run screen: one plain terminal screen (at most 22 lines of at most 78
3
- * columns, ASCII) built from the backtest numbers. Pure — no I/O — so every layout is
3
+ * columns, ASCII; with the command's blank line above and below, 24 rows) built from
4
+ * the backtest numbers. Pure — no I/O — so every layout is
4
5
  * unit-tested. Every number on it is recorded in the audit with its raw value and
5
6
  * method.
6
7
  *
7
- * Exactly three variations (operator v1, 2026-10-01); every number has one source and no
8
- * two lines make the same claim:
9
- * A saving the shown saving is >= $5 and >= 5%: the usage at API prices, with Mnemom,
10
- * the saving, the biggest session; plus ONE subscription sentence for a Team /
11
- * Enterprise subscriber whose usage cut rounds to >= 5%. Where sessions ran
12
- * through Mnemom (launch ledger), that part is said to be SAVED: what it
13
- * saved you, and what it would have saved on the rest (operator 2026-10-02).
14
- * B small >= $5 of usage at API prices but a smaller saving: the usage, the honest
15
- * "wouldn't have changed that much" line, and the forward line.
16
- * C none too little history: the forward line only.
17
- * All three end with the price line and the live lines.
8
+ * Sessions come in two buckets (index.ts): THROUGH Mnemom (launch ledger, a window / env
9
+ * signal, or fold evidence), whose saving is REALIZED (replay.ts: stock Claude Code
10
+ * replayed at its default window, can be negative), and NOT through Mnemom, whose saving
11
+ * is the POTENTIAL one (backtest.ts: the flat S46 rule, 23.8% of every request at or
12
+ * above 60k, for dollars and for tokens alike). Tokens and dollars are both shown
13
+ * (operator 2026-10-02). Percentages drop their decimals (rounded DOWN).
18
14
  *
19
- * Operator rulings (2026-09-30 / 2026-10-01), binding:
20
- * - Cost only. Nothing about conduct ("habits", "caught", "checked").
21
- * - Round DOWN, never overstate; frame the number around the biggest session.
22
- * - Every kept session is priced at API list prices whatever it was billed on, and the
23
- * screen says "at API prices". A subscriber gets a usage %, never a seat bill, an
24
- * overage dollar figure or a limit-hit count.
15
+ * Variations; every number has one source and no two lines make the same claim:
16
+ * A no through-Mnemom usage, and the potential saving qualifies: the usage in
17
+ * tokens and at API prices, the cut with Mnemom, the biggest session.
18
+ * mixed both buckets have usage: one block per bucket, each with its saving line
19
+ * only if that BUCKET's saving qualifies, then the largest dollar saving
20
+ * across the shown buckets, worded by its bucket ("biggest saving ... of"
21
+ * through, "biggest session ... less with Mnemom" not through).
22
+ * through only through-Mnemom usage: its block alone, then its biggest saving.
23
+ * B >= $5 of usage but no saving line qualifies: the usage, the honest "wouldn't
24
+ * have changed that much" line (no through usage) or the bucket usage lines,
25
+ * and the forward line.
26
+ * C too little history: the forward line only.
27
+ * A saving qualifies iff it rounds DOWN to >= $5 and its token percent to >= 5%. A
28
+ * Team / Enterprise subscriber also gets the subscription line whenever a saving line is
29
+ * shown; its overage clause only when the account has extra usage enabled. All end with
30
+ * the price line and the live lines.
31
+ *
32
+ * Layout (operator 2026-10-02): a blank line between every block (each bucket's usage
33
+ * and saving lines, the biggest line, the subscriber lines, the price line, the live
34
+ * lines); the saving lines are not indented.
35
+ *
36
+ * Operator rulings (2026-09-30 .. 2026-10-02), binding:
37
+ * - Cost and usage only. Nothing about conduct ("habits", "caught", "checked").
38
+ * - Round DOWN, never overstate. A through session's saving may be negative: the
39
+ * bucket total is the honest sum, never floored per session.
40
+ * - Every session is priced at API list prices whatever it was billed on, and the
41
+ * screen says "at API prices". A subscriber never gets a seat bill, an overage dollar
42
+ * figure or a limit-hit count.
25
43
  * - No live counter is promised: `mnemom agent` has no status bar today.
26
44
  */
27
45
  import { ESTIMATOR_METHOD } from "./backtest.js";
@@ -29,7 +47,7 @@ export const WIDTH = 78;
29
47
  export const MAX_LINES = 22;
30
48
  /** Less history than this (API prices, in the window) is too little to backtest. */
31
49
  export const MIN_HISTORY_USD = 5;
32
- /** Variation A iff the shown saving is at least this many dollars and this many percent. */
50
+ /** A saving line is shown iff its saving rounds to at least this many dollars and percent. */
33
51
  export const STRONG_MIN_USD = 5;
34
52
  export const STRONG_MIN_PCT = 5;
35
53
  export const DAYS = 30;
@@ -45,6 +63,17 @@ const FORWARD_SOURCE = "operator 2026-10-02: S46 C2n total bill -20.9% [-25.6, -
45
63
  /** Prices, promotions and plan allocations move; the saving is in usage (operator 2026-10-01). */
46
64
  export const PRICE_LINE = "Prices and plan limits change. Mnemom cuts what you use, so you stay ahead.";
47
65
  /** What `mnemom agent` does today: routes through the gateway, records, keeps context lean. */
66
+ /**
67
+ * The subscriber lines, fixed like the live lines: the operator's break, so the overage
68
+ * form reads as two lines and never as one 78-column line.
69
+ */
70
+ export const SUB_LINES = {
71
+ limit: ["On your subscription, fewer tokens means more work before you hit a limit."],
72
+ overage: [
73
+ "On your subscription, fewer tokens means more work before you hit a",
74
+ "limit, and less overage when you go past it.",
75
+ ],
76
+ };
48
77
  export const LIVE_LINES = [
49
78
  "From now on it's live: your sessions run through Mnemom, which keeps long",
50
79
  "conversations lean and puts each tool call your agent makes on the record.",
@@ -87,6 +116,26 @@ export function day(t) {
87
116
  export function usd(n) {
88
117
  return `$${Math.floor(n).toLocaleString("en-US")}`;
89
118
  }
119
+ /** A token count rounded DOWN to 2 significant figures (the number it stands for). */
120
+ export function tokShown(n) {
121
+ return n >= 1 ? sig2(n) : 0;
122
+ }
123
+ /**
124
+ * A token count in words, 2 significant figures DOWN: "9.0 billion", "39 billion",
125
+ * "450 million", "12 thousand"; below a thousand, the plain number.
126
+ */
127
+ export function tokens(n) {
128
+ const v = tokShown(n);
129
+ for (const [u, w] of [
130
+ [1e9, "billion"],
131
+ [1e6, "million"],
132
+ [1e3, "thousand"],
133
+ ]) {
134
+ if (v >= u)
135
+ return `${v >= 10 * u ? String(v / u) : (v / u).toFixed(1)} ${w}`;
136
+ }
137
+ return String(v);
138
+ }
90
139
  // ── output hygiene ───────────────────────────────────────────────────────────
91
140
  const SECRETS = /(sk-[A-Za-z0-9_-]{6,}|ghp_[A-Za-z0-9]{6,}|mnm_[A-Za-z0-9_-]{6,}|op:\/\/\S+|Bearer\s+\S+|\b[0-9a-f]{40,}\b|\b[A-Za-z0-9+/]{48,}={0,2})/g;
92
141
  const PATHISH = /(\/Users\/\S+|\/home\/\S+|\/private\/\S+|~\/\S+)/g;
@@ -119,27 +168,45 @@ export function wrap(text, width = WIDTH) {
119
168
  out.push(cur);
120
169
  return out;
121
170
  }
122
- const SPENT_METHOD = "transcript usage x Claude Code 2.1.285's price table, deduped by message id, every kept " +
123
- "session's requests in the last 30 days, priced at API list prices whatever they were billed " +
124
- "on; 3 sig figs DOWN; a lower bound (side calls not in transcripts are missing)";
171
+ const SPENT_METHOD = "transcript usage x Claude Code 2.1.285's price table, deduped by message id, the bucket's " +
172
+ "requests in the last 30 days, priced at API list prices whatever they were billed on; 3 sig " +
173
+ "figs DOWN; a lower bound (side calls not in transcripts are missing)";
174
+ const TOKENS_METHOD = "Σ (input + cache read + cache write 5m + cache write 1h + output) over the same requests; " +
175
+ "2 sig figs DOWN";
125
176
  const SAVED_METHOD = `backtest.estimate(): ${ESTIMATOR_METHOD}; 2 sig figs DOWN`;
177
+ const SAVED_TOKENS_METHOD = "backtest.estimate(): ruleRate(prompt) x prompt per request (the same flat rule as the " +
178
+ "dollars); 2 sig figs DOWN";
179
+ const REALIZED_METHOD = "replay.replayStock(): stock Claude Code at its default window for the session's dominant " +
180
+ "main-thread model, replayed on the client size rebuilt from the fold drops; Σ per session, " +
181
+ "negative sessions kept; 2 sig figs DOWN";
182
+ function sum(ses) {
183
+ const b = { n: ses.length, usd: 0, tokens: 0, saved: 0, savedTokens: 0 };
184
+ for (const r of ses) {
185
+ b.usd += r.actual;
186
+ b.tokens += r.tokens;
187
+ b.saved += r.saved;
188
+ b.savedTokens += r.savedTokens;
189
+ }
190
+ return b;
191
+ }
192
+ /** The shown saving of a bucket, or null when it does not qualify. */
193
+ function qualifying(saved, savedTokens, base) {
194
+ const u = sig2(Math.max(saved, 0));
195
+ const pct = pctDown(savedTokens, base);
196
+ if (u < STRONG_MIN_USD || pct < STRONG_MIN_PCT)
197
+ return null;
198
+ // pct >= 5 implies base > 0.
199
+ return { usd: u, tok: tokShown(savedTokens), pct, rawPct: (100 * savedTokens) / base };
200
+ }
126
201
  function subLines(sub, A) {
127
202
  if (!sub)
128
203
  return [];
129
- const p = pctDown(sub.saved, sub.actual);
130
- const raw = sub.actual > 0 ? (100 * sub.saved) / sub.actual : 0;
131
- if (p < 5) {
132
- A("sub_line_omitted", { shown: true, raw, method: "usage cut below 5% (decimals dropped)" });
133
- return [];
134
- }
135
- A("sub_usage_pct", {
136
- shown: p,
137
- raw,
138
- method: "saving / API-price cost over the subscription sessions in the window (all sessions if " +
139
- "none is tagged); cost-weighted, decimals dropped",
204
+ A("sub_overage_clause", {
205
+ shown: sub.extraUsage,
206
+ raw: sub.extraUsage,
207
+ method: "the account's hasExtraUsageEnabled (authShape().extraUsage); never a dollar figure",
140
208
  });
141
- return wrap(`On your subscription that is about ${p}% less usage: fewer limit hits, and less ` +
142
- "overage if you use extra usage.");
209
+ return sub.extraUsage ? SUB_LINES.overage : SUB_LINES.limit;
143
210
  }
144
211
  /** -> the screen lines, the variation and the audit of every number on them. */
145
212
  export function buildScreen(inp) {
@@ -148,88 +215,176 @@ export function buildScreen(inp) {
148
215
  audit[k] = e;
149
216
  };
150
217
  const ses = inp.sessions;
151
- const actual = ses.reduce((t, r) => t + r.actual, 0);
152
- const saved = ses.reduce((t, r) => t + r.saved, 0);
153
- const [a, s, e] = pair(actual, saved);
154
- const p = pctDown(saved, actual);
155
- const enough = actual >= MIN_HISTORY_USD;
156
- const variation = enough && s >= STRONG_MIN_USD && p >= STRONG_MIN_PCT ? "A" : enough ? "B" : "C";
157
- A("variation", { shown: variation, raw: { actual, saved }, method: "see screen.ts header" });
218
+ const all = sum(ses);
219
+ const thr = sum(ses.filter((r) => r.through));
220
+ const not = sum(ses.filter((r) => !r.through));
221
+ // A bucket "has usage" when it shows at least $1 at API prices.
222
+ const hasThr = sig3(thr.usd) >= 1;
223
+ const hasNot = sig3(not.usd) >= 1;
224
+ const enough = all.usd >= MIN_HISTORY_USD;
225
+ // Through: the base is the without-Mnemom total (used + saved). Not: what was used.
226
+ const qThr = hasThr ? qualifying(thr.saved, thr.savedTokens, thr.tokens + thr.savedTokens) : null;
227
+ const qNot = hasNot ? qualifying(not.saved, not.savedTokens, not.tokens) : null;
228
+ const variation = !enough
229
+ ? "C"
230
+ : !qThr && !qNot
231
+ ? "B"
232
+ : !hasThr
233
+ ? "A"
234
+ : hasNot
235
+ ? "mixed"
236
+ : "through";
237
+ A("variation", {
238
+ shown: variation,
239
+ raw: { through: thr, not_through: not },
240
+ method: "see screen.ts header; raw = each bucket's honest sums (negative sessions kept)",
241
+ });
158
242
  const L = ["Welcome to Mnemom.", ""];
159
243
  L.push(...(variation === "C"
160
244
  ? wrap("We didn't find enough Claude Code history on this machine to look at.")
161
245
  : wrap(`We looked at your last ${DAYS} days of Claude Code. It all stayed on this machine.`)));
162
- L.push("");
163
- if (variation === "A") {
164
- A("spent_usd", { shown: a, raw: actual, method: SPENT_METHOD });
165
- A("saved_pct", {
166
- shown: p,
167
- raw: (100 * saved) / actual,
168
- method: "decimals dropped (rounded DOWN)",
169
- });
170
- const viaRaw = ses.reduce((t, r) => t + (r.viaMnemom ? r.saved : 0), 0);
171
- const via = sig2(viaRaw);
172
- const rest = sig2(saved - viaRaw);
173
- if (via < 1) {
174
- A("saved_usd", { shown: s, raw: saved, method: SAVED_METHOD });
175
- A("with_mnemom_usd", { shown: e, raw: actual - saved, method: "spent shown - saved shown" });
176
- L.push(...wrap(`At API prices that usage cost about ${usd(a)}. With Mnemom: about ${usd(e)}.`));
246
+ /** Start a block: one blank line after whatever came before. */
247
+ const gap = () => {
248
+ if (L[L.length - 1] !== "")
177
249
  L.push("");
178
- L.push(...wrap(`That's about ${usd(s)} less (${p}%), and you don't change how you work.`));
250
+ };
251
+ const usage = (key, b) => {
252
+ A(`${key}_tokens`, { shown: tokShown(b.tokens), raw: b.tokens, method: TOKENS_METHOD });
253
+ A(`${key}_usd`, { shown: sig3(b.usd), raw: b.usd, method: SPENT_METHOD });
254
+ return { t: tokens(b.tokens), u: usd(sig3(b.usd)) };
255
+ };
256
+ const saving = (key, b, q, method, tokMethod, base) => {
257
+ A(`${key}_saved_tokens`, { shown: q.tok, raw: b.savedTokens, method: tokMethod });
258
+ A(`${key}_saved_pct`, {
259
+ shown: q.pct,
260
+ raw: q.rawPct,
261
+ method: `${base}; decimals dropped (rounded DOWN)`,
262
+ });
263
+ A(`${key}_saved_usd`, { shown: q.usd, raw: b.saved, method });
264
+ };
265
+ /** The per-bucket lines; only called when the through bucket has usage. */
266
+ const bucketBlock = () => {
267
+ gap();
268
+ const { t, u } = usage("through", thr);
269
+ L.push(...wrap(`Through Mnemom: ${t} tokens, about ${u} at API prices.`));
270
+ if (qThr) {
271
+ saving("through", thr, qThr, REALIZED_METHOD, REALIZED_METHOD, "saved tokens / (used + saved)");
272
+ L.push(...wrap(`That saved about ${tokens(thr.savedTokens)} tokens (${qThr.pct}%), about ${usd(qThr.usd)}.`));
179
273
  }
180
274
  else {
181
- const m = `${SAVED_METHOD}; sessions the launch ledger shows ran through Mnemom`;
182
- A("saved_via_mnemom_usd", { shown: via, raw: viaRaw, method: m });
183
- L.push(...wrap(`At API prices that usage comes to about ${usd(a)} without Mnemom.`));
184
- L.push("");
185
- if (rest < 1) {
186
- L.push(...wrap(`Mnemom saved you about ${usd(via)} of it (${p}%), and you didn't change how you work.`));
275
+ A("through_saved_not_shown", {
276
+ shown: null,
277
+ raw: { usd: thr.saved, tokens: thr.savedTokens },
278
+ method: `below $${STRONG_MIN_USD} or ${STRONG_MIN_PCT}% after rounding DOWN`,
279
+ });
280
+ }
281
+ if (hasNot) {
282
+ gap();
283
+ const { t, u } = usage("not_through", not);
284
+ L.push(...wrap(`Not through Mnemom: ${t} tokens, about ${u} at API prices.`));
285
+ if (qNot) {
286
+ saving("not_through", not, qNot, SAVED_METHOD, SAVED_TOKENS_METHOD, "saved tokens / used");
287
+ L.push(...wrap(`Mnemom would have cut about ${tokens(not.savedTokens)} tokens (${qNot.pct}%), ` +
288
+ `about ${usd(qNot.usd)}.`));
187
289
  }
188
290
  else {
189
- A("saved_rest_usd", {
190
- shown: rest,
191
- raw: saved - viaRaw,
192
- method: `${SAVED_METHOD}; the rest`,
291
+ A("not_through_saved_not_shown", {
292
+ shown: null,
293
+ raw: { usd: not.saved, tokens: not.savedTokens },
294
+ method: `below $${STRONG_MIN_USD} or ${STRONG_MIN_PCT}% after rounding DOWN`,
193
295
  });
194
- L.push(...wrap(`Mnemom saved you about ${usd(via)} of it, and would have saved about ${usd(rest)} ` +
195
- "more on the sessions that didn't run through it."));
196
296
  }
197
297
  }
198
- // A has a saving, so the session with the largest saving exists and saved something.
199
- const big = ses.reduce((m, r) => (r.saved > m.saved ? r : m));
200
- const [ba, , be] = pair(big.actual, big.saved);
201
- A("biggest_session_usd", {
202
- shown: ba,
203
- raw: big.actual,
204
- method: "the session with the largest saving; its API-price cost, 3 sig figs DOWN",
205
- });
206
- A("biggest_session_with_mnemom_usd", {
207
- shown: be,
208
- raw: big.actual - big.saved,
209
- method: "its cost shown - its saving (2 sig figs DOWN)",
210
- });
211
- L.push("");
212
- const where = big.label ? `${big.label} on ${day(big.end)}` : `on ${day(big.end)}`;
213
- L.push(...wrap(big.viaMnemom
214
- ? `Your biggest session, ${where}: ${usd(ba)} without Mnemom, about ${usd(be)} with it.`
215
- : `Your biggest session, ${where}: ${usd(ba)}, with Mnemom about ${usd(be)}.`));
216
- const subL = subLines(inp.sub, A);
217
- if (subL.length)
218
- L.push("", ...subL);
298
+ };
299
+ /** The session with the largest dollar saving, if it rounds to >= $5. */
300
+ const biggest = (pool) => {
301
+ let big = null;
302
+ for (const r of pool)
303
+ if (!big || r.saved > big.saved)
304
+ big = r;
305
+ return big && sig2(big.saved) >= STRONG_MIN_USD ? big : null;
306
+ };
307
+ const where = (r) => r.label ? `${r.label} on ${day(r.end)}` : `on ${day(r.end)}`;
308
+ /**
309
+ * The biggest line, worded by the session's bucket (operator 2026-10-02): through, the
310
+ * realized saving of what it would have cost without Mnemom (used + saved); not
311
+ * through, what it cost and the would-have saving.
312
+ */
313
+ const biggestLine = (big) => {
314
+ gap();
315
+ if (big.through) {
316
+ const without = big.actual + big.saved;
317
+ const ba = sig3(without);
318
+ const bs = Math.min(sig2(big.saved), ba);
319
+ A("biggest_saving_usd", {
320
+ shown: bs,
321
+ raw: big.saved,
322
+ method: `the session with the largest dollar saving (${REALIZED_METHOD})`,
323
+ });
324
+ A("biggest_saving_of_usd", {
325
+ shown: ba,
326
+ raw: without,
327
+ method: "that session's cost without Mnemom at API prices (used + saved), 3 sig figs DOWN",
328
+ });
329
+ L.push(...wrap(`Your biggest saving, ${where(big)}: about ${usd(bs)} of ${usd(ba)}.`));
330
+ }
331
+ else {
332
+ const ba = sig3(big.actual);
333
+ const bs = Math.min(sig2(big.saved), ba);
334
+ A("biggest_session_usd", {
335
+ shown: ba,
336
+ raw: big.actual,
337
+ method: "the session with the largest saving; its API-price cost, 3 sig figs DOWN",
338
+ });
339
+ A("biggest_session_saved_usd", {
340
+ shown: bs,
341
+ raw: big.saved,
342
+ method: `${SAVED_METHOD}; that session`,
343
+ });
344
+ L.push(...wrap(`Your biggest session, ${where(big)}: ${usd(ba)}, about ${usd(bs)} less with Mnemom.`));
345
+ }
346
+ };
347
+ if (variation === "A") {
348
+ gap();
349
+ const { t, u } = usage("spent", not);
350
+ L.push(...wrap(`You used about ${t} tokens, about ${u} at API prices.`));
351
+ const q = qNot;
352
+ saving("spent", not, q, SAVED_METHOD, SAVED_TOKENS_METHOD, "saved tokens / used");
353
+ L.push(...wrap(`With Mnemom: about ${tokens(not.savedTokens)} fewer tokens (${q.pct}%), about ` +
354
+ `${usd(q.usd)} less.`));
355
+ const big = biggest(ses.filter((r) => !r.through));
356
+ if (big)
357
+ biggestLine(big);
358
+ gap();
359
+ L.push(...subLines(inp.sub, A));
360
+ }
361
+ else if (variation === "mixed" || variation === "through") {
362
+ bucketBlock();
363
+ // The largest dollar saving across the buckets whose saving line is shown.
364
+ const big = biggest(ses.filter((r) => (r.through ? qThr : qNot)));
365
+ if (big)
366
+ biggestLine(big);
367
+ gap();
368
+ L.push(...subLines(inp.sub, A));
219
369
  }
220
370
  else {
221
371
  if (variation === "B") {
222
- A("spent_usd", { shown: a, raw: actual, method: SPENT_METHOD });
223
- A("saved_usd_not_shown", {
224
- shown: null,
225
- raw: saved,
226
- method: `below $${STRONG_MIN_USD} or ${STRONG_MIN_PCT}% after rounding DOWN`,
227
- });
228
- L.push(...wrap(`Your sessions used about ${usd(a)} at API prices. They stayed small, so Mnemom ` +
229
- "wouldn't have changed that much."));
372
+ if (hasThr) {
373
+ bucketBlock();
374
+ }
375
+ else {
376
+ const { t, u } = usage("spent", all);
377
+ A("saved_not_shown", {
378
+ shown: null,
379
+ raw: { usd: all.saved, tokens: all.savedTokens },
380
+ method: `below $${STRONG_MIN_USD} or ${STRONG_MIN_PCT}% after rounding DOWN`,
381
+ });
382
+ gap();
383
+ L.push(...wrap(`Your sessions used about ${t} tokens, about ${u} at API prices. They stayed ` +
384
+ "small, so Mnemom wouldn't have changed that much."));
385
+ }
230
386
  }
231
- if (variation === "B")
232
- L.push("");
387
+ gap();
233
388
  L.push(...wrap(FORWARD_LINE));
234
389
  A("forward_range_pct", {
235
390
  shown: "15 to 25",
@@ -237,11 +392,12 @@ export function buildScreen(inp) {
237
392
  method: FORWARD_SOURCE,
238
393
  });
239
394
  }
240
- L.push("", PRICE_LINE, "", ...LIVE_LINES);
395
+ gap();
396
+ L.push(PRICE_LINE, "", ...LIVE_LINES);
241
397
  A("sessions", {
242
398
  shown: null,
243
- raw: ses.length,
244
- method: "kept sessions with requests in the window",
399
+ raw: { all: all.n, through: thr.n, not_through: not.n },
400
+ method: "sessions with requests in the window, by bucket",
245
401
  });
246
402
  return { lines: L.map(clean), audit, variation };
247
403
  }
@@ -56,10 +56,11 @@ export interface LauncherConfig {
56
56
  */
57
57
  compactionIntercept?: boolean;
58
58
  /**
59
- * How the gateway folds each session's context (`balanced` when unset): `off` leaves
60
- * compaction to the coding agent, `balanced` keeps more earlier work verbatim, `aggressive`
61
- * folds earlier with a tighter working set, `adaptive` sizes the fold to the conversation
62
- * (none below 200k tokens, aggressive up to 1M, balanced above). `--context-profile` overrides it per launch.
59
+ * How the gateway folds each session's context (unset: nothing is sent, the gateway cell's
60
+ * own default decides): `off` leaves compaction to the coding agent, `balanced` keeps more
61
+ * earlier work verbatim, `aggressive` folds earlier with a tighter working set, `adaptive`
62
+ * sizes the fold to the conversation (none below 200k tokens, aggressive up to 1M, balanced
63
+ * above). `--context-profile` overrides it for one launch without saving anything.
63
64
  */
64
65
  contextProfile?: ContextProfile;
65
66
  /**
@@ -215,7 +215,7 @@ export const CONFIG_KEYS = [
215
215
  },
216
216
  {
217
217
  key: "context_profile",
218
- describe: `How the gateway folds each session's context (${CONTEXT_PROFILES.join("|")}; balanced by default)`,
218
+ describe: `How the gateway folds each session's context (${CONTEXT_PROFILES.join("|")}; unset = the gateway cell's default)`,
219
219
  get: (c) => c.contextProfile,
220
220
  set: (c, v) => {
221
221
  c.contextProfile = parseContextProfile(v, "context_profile");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mnemom/mnemom",
3
- "version": "0.17.7",
3
+ "version": "0.17.8",
4
4
  "description": "Transparent AI agent tracing",
5
5
  "type": "module",
6
6
  "bin": {