@kevin0181/memoc 1.1.11 → 1.2.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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/bin/cli.js +56 -18
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -144,7 +144,7 @@ Run it from the project root. It preserves existing project memory, including:
144
144
  - `.memoc/systems/`
145
145
  - `.memoc/wiki/`
146
146
 
147
- It refreshes the managed blocks, project-local wrappers, runtime copy, PATH helpers, and memoc-owned protocol templates. User-owned memory files such as `session-summary.md`, `03-decisions.md`, `04-handoff.md`, `06-project-rules.md`, and wiki topic/source pages are preserved. If `memoc` is not on PATH after upgrading, keep using:
147
+ It refreshes the managed blocks, project-local wrappers, runtime copy, PATH helpers, and memoc-owned protocol templates. User-owned memory files such as `session-summary.md`, `03-decisions.md`, `04-handoff.md`, `06-project-rules.md`, and wiki topic/source pages are preserved. Upgrade also runs the `trim-summary` compaction pass so startup memory stays small. If `memoc` is not on PATH after upgrading, keep using:
148
148
 
149
149
  ```bash
150
150
  # Windows
package/bin/cli.js CHANGED
@@ -246,6 +246,47 @@ function archiveLegacyLog(dir, mark) {
246
246
  mark('move', `${path.relative(dir, logPath)} -> ${path.relative(dir, archivePath)}`);
247
247
  }
248
248
 
249
+ function summarySectionBulletCounts(src) {
250
+ const counts = {};
251
+ let current = '';
252
+ for (const line of String(src || '').split(/\r?\n/)) {
253
+ const heading = line.match(/^##\s+(.+?)\s*$/);
254
+ if (heading) {
255
+ current = heading[1].trim();
256
+ counts[current] = counts[current] || 0;
257
+ continue;
258
+ }
259
+ if (current && /^-\s+/.test(line)) counts[current] = (counts[current] || 0) + 1;
260
+ }
261
+ return counts;
262
+ }
263
+
264
+ function trimSummaryFile(dir) {
265
+ const summaryPath = path.join(dir, '.memoc', 'session-summary.md');
266
+ const archivePath = path.join(dir, '.memoc', 'session-summary-archive.md');
267
+ if (!fs.existsSync(summaryPath)) {
268
+ write(summaryPath, tplSessionSummary());
269
+ return { action: 'add' };
270
+ }
271
+
272
+ const src = fs.readFileSync(summaryPath, 'utf8');
273
+ const beforeBytes = Buffer.byteLength(src, 'utf8');
274
+ const counts = summarySectionBulletCounts(src);
275
+ const tooManyBullets = Object.values(counts).some(count => count > 3);
276
+ if (beforeBytes <= 800 && !tooManyBullets) {
277
+ return { action: 'skip', beforeBytes };
278
+ }
279
+
280
+ const compact = compactSessionSummary(src);
281
+ const afterBytes = Buffer.byteLength(compact, 'utf8');
282
+ const archiveHeader = fs.existsSync(archivePath)
283
+ ? ''
284
+ : '# Session Summary Archive\n\nOlder oversized startup summaries moved by `memoc trim-summary`.\n';
285
+ fs.appendFileSync(archivePath, `${archiveHeader}\n## [${nowISO()}] archived summary (${beforeBytes}B)\n\n${src.trimEnd()}\n`, 'utf8');
286
+ write(summaryPath, compact);
287
+ return { action: 'trim', beforeBytes, afterBytes };
288
+ }
289
+
249
290
  function migrateLegacyLogReferences(filePath) {
250
291
  if (!fs.existsSync(filePath)) return false;
251
292
  const before = fs.readFileSync(filePath, 'utf8');
@@ -2392,6 +2433,16 @@ function run(dir, forceUpdate, action = 'update') {
2392
2433
 
2393
2434
  archiveLegacyLog(dir, mark);
2394
2435
 
2436
+ const trim = trimSummaryFile(dir);
2437
+ if (trim.action === 'trim') {
2438
+ mark('update', `.memoc/session-summary.md (trimmed ${trim.beforeBytes}B -> ${trim.afterBytes}B)`);
2439
+ mark('update', '.memoc/session-summary-archive.md');
2440
+ } else if (trim.action === 'add') {
2441
+ mark('add', '.memoc/session-summary.md');
2442
+ } else {
2443
+ mark('skip', `.memoc/session-summary.md (compact ${trim.beforeBytes || 0}B)`);
2444
+ }
2445
+
2395
2446
  // Obsidian graph filters — add/merge memoc tags for existing installs too
2396
2447
  ensureObsidianFrontmatter(dir, mark);
2397
2448
  }
@@ -3392,37 +3443,24 @@ function runCompress(dir) {
3392
3443
  // ═══════════════════════════════════════════════════════════════════
3393
3444
 
3394
3445
  function runTrimSummary(dir) {
3395
- const summaryPath = path.join(dir, '.memoc', 'session-summary.md');
3396
- const archivePath = path.join(dir, '.memoc', 'session-summary-archive.md');
3397
- if (!fs.existsSync(summaryPath)) {
3398
- write(summaryPath, tplSessionSummary());
3446
+ const result = trimSummaryFile(dir);
3447
+ if (result.action === 'add') {
3399
3448
  console.log('\n memoc trim-summary\n');
3400
3449
  console.log(' Added .memoc/session-summary.md');
3401
3450
  console.log('\n Done.\n');
3402
3451
  return;
3403
3452
  }
3404
3453
 
3405
- const src = fs.readFileSync(summaryPath, 'utf8');
3406
- const beforeBytes = Buffer.byteLength(src, 'utf8');
3407
- const compact = compactSessionSummary(src);
3408
- const afterBytes = Buffer.byteLength(compact, 'utf8');
3409
-
3410
- if (src === compact && beforeBytes <= 800) {
3454
+ if (result.action === 'skip') {
3411
3455
  console.log('\n memoc trim-summary\n');
3412
- console.log(` session-summary.md is already compact (${beforeBytes}B).`);
3456
+ console.log(` session-summary.md is already compact (${result.beforeBytes}B).`);
3413
3457
  console.log('\n Done.\n');
3414
3458
  return;
3415
3459
  }
3416
3460
 
3417
- const archiveHeader = fs.existsSync(archivePath)
3418
- ? ''
3419
- : '# Session Summary Archive\n\nOlder oversized startup summaries moved by `memoc trim-summary`.\n';
3420
- fs.appendFileSync(archivePath, `${archiveHeader}\n## [${nowISO()}] archived summary (${beforeBytes}B)\n\n${src.trimEnd()}\n`, 'utf8');
3421
- write(summaryPath, compact);
3422
-
3423
3461
  console.log('\n memoc trim-summary\n');
3424
3462
  console.log(` Archived .memoc/session-summary-archive.md`);
3425
- console.log(` Rewrote .memoc/session-summary.md (${beforeBytes}B → ${afterBytes}B)`);
3463
+ console.log(` Rewrote .memoc/session-summary.md (${result.beforeBytes}B → ${result.afterBytes}B)`);
3426
3464
  console.log(' Reminder Completed history belongs in worklog; resume details belong in 04-handoff.md.');
3427
3465
  console.log('\n Done.\n');
3428
3466
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kevin0181/memoc",
3
- "version": "1.1.11",
3
+ "version": "1.2.0",
4
4
  "description": "Give AI agents a memory. Scaffolds session-to-session context for Claude Code, Codex, Cursor, and more.",
5
5
  "keywords": [
6
6
  "ai",