@kevin0181/memoc 1.1.10 → 1.1.11
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/README.md +2 -2
- package/bin/cli.js +77 -11
- 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
|
|
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:
|
|
148
148
|
|
|
149
149
|
```bash
|
|
150
150
|
# Windows
|
|
@@ -277,7 +277,7 @@ Actor detection order:
|
|
|
277
277
|
|
|
278
278
|
`activity.md`, `actors/README.md`, and `worklog/README.md` are regenerated indexes. Run `memoc activity --write` when you want to refresh them from worklog files.
|
|
279
279
|
|
|
280
|
-
`log.md` is legacy. New installs do not create it, and shared activity should live in worklog files.
|
|
280
|
+
`log.md` is legacy. New installs do not create it, and shared activity should live in worklog files. On upgrade, an existing `.memoc/log.md` is moved to `.memoc/raw/legacy-log.md` so old history is preserved but no longer part of the normal memory flow.
|
|
281
281
|
|
|
282
282
|
---
|
|
283
283
|
|
package/bin/cli.js
CHANGED
|
@@ -209,6 +209,12 @@ function write(filePath, content) {
|
|
|
209
209
|
fs.writeFileSync(filePath, content, 'utf8');
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
+
function writeChanged(filePath, content) {
|
|
213
|
+
if (fs.existsSync(filePath) && fs.readFileSync(filePath, 'utf8') === content) return false;
|
|
214
|
+
write(filePath, content);
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
|
|
212
218
|
function slugify(value, fallback = 'note') {
|
|
213
219
|
const slug = String(value || '')
|
|
214
220
|
.toLowerCase()
|
|
@@ -228,6 +234,35 @@ function uniquePath(filePath) {
|
|
|
228
234
|
return `${base}-${i}${ext}`;
|
|
229
235
|
}
|
|
230
236
|
|
|
237
|
+
function archiveLegacyLog(dir, mark) {
|
|
238
|
+
const logPath = path.join(dir, '.memoc', 'log.md');
|
|
239
|
+
if (!fs.existsSync(logPath)) {
|
|
240
|
+
mark('skip', '.memoc/log.md (legacy; no file)');
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const archivePath = uniquePath(path.join(dir, '.memoc', 'raw', 'legacy-log.md'));
|
|
244
|
+
fs.mkdirSync(path.dirname(archivePath), { recursive: true });
|
|
245
|
+
fs.renameSync(logPath, archivePath);
|
|
246
|
+
mark('move', `${path.relative(dir, logPath)} -> ${path.relative(dir, archivePath)}`);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function migrateLegacyLogReferences(filePath) {
|
|
250
|
+
if (!fs.existsSync(filePath)) return false;
|
|
251
|
+
const before = fs.readFileSync(filePath, 'utf8');
|
|
252
|
+
let after = before
|
|
253
|
+
.replace(/- \[Project Log\]\(log\.md\)\n/g, '- [Activity](activity.md)\n- [Worklog](worklog/README.md)\n')
|
|
254
|
+
.replace(/\| `\.memoc\/log\.md` \| For append-only history \|\n/g, '| `.memoc/activity.md` | Generated worklog index |\n| `.memoc/worklog/` | Actor-scoped work history |\n')
|
|
255
|
+
.replace(/See `\.memoc\/log\.md` for full history\./g, 'See `.memoc/worklog/` for full shared activity history.')
|
|
256
|
+
.replace(/See `\.memoc\/log\.md`\./g, 'See `.memoc/worklog/` and generated `.memoc/activity.md`.')
|
|
257
|
+
.replace(/- \[ \] `\.memoc\/log\.md` has a new entry for meaningful work\./g, '- [ ] Meaningful shared work has a `.memoc/worklog/<actor>/YYYY-MM/*.md` entry.')
|
|
258
|
+
.replace(/Append `\.memoc\/log\.md` for meaningful changes, decisions, and handoffs\./g, 'Create a short actor worklog with `memoc work "<title>" --from-git` for meaningful changes, decisions, and handoffs.')
|
|
259
|
+
.replace(/Keep completed history in `\.memoc\/log\.md`; keep current-state files short\./g, 'Keep completed history in actor worklogs; keep current-state files short.')
|
|
260
|
+
.replace(/Append `\.memoc\/log\.md`\./g, 'If the change is meaningful shared work, run `memoc work "<title>" --from-git`.');
|
|
261
|
+
if (after === before) return false;
|
|
262
|
+
write(filePath, after);
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
|
|
231
266
|
function markdownTitle(src, fallback) {
|
|
232
267
|
const m = String(src || '').match(/^#\s+(.+)$/m);
|
|
233
268
|
return m ? m[1].trim() : fallback;
|
|
@@ -2252,10 +2287,18 @@ function run(dir, forceUpdate, action = 'update') {
|
|
|
2252
2287
|
mark('add', 'llms.txt');
|
|
2253
2288
|
}
|
|
2254
2289
|
|
|
2255
|
-
//
|
|
2290
|
+
// Generated memory maps — replace so old protocols do not linger.
|
|
2291
|
+
const generatedRefresh = [
|
|
2292
|
+
[path.join(memDir, '00-project-brief.md'), () => tplProjectBrief(p)],
|
|
2293
|
+
[path.join(memDir, '00-agent-index.md'), () => tplAgentIndex(p)],
|
|
2294
|
+
];
|
|
2295
|
+
for (const [fp, tpl] of generatedRefresh) {
|
|
2296
|
+
const rel = path.relative(dir, fp);
|
|
2297
|
+
mark(writeChanged(fp, tpl()) ? 'update' : 'skip', rel);
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2300
|
+
// Dynamic user-owned memory files — update managed sections only
|
|
2256
2301
|
const dynUpdates = [
|
|
2257
|
-
[path.join(memDir, '00-project-brief.md'), () => tplProjectBrief(p), ID_S, ID_E, identityInner(p)],
|
|
2258
|
-
[path.join(memDir, '00-agent-index.md'), () => tplAgentIndex(p), SNAP_S, SNAP_E, snapshotInner(p)],
|
|
2259
2302
|
[path.join(memDir, '02-current-project-state.md'), () => tplCurrentState(p), SNAP_S, SNAP_E, snapshotInner(p)],
|
|
2260
2303
|
];
|
|
2261
2304
|
for (const [fp, tpl, s, e, inner] of dynUpdates) {
|
|
@@ -2283,18 +2326,27 @@ function run(dir, forceUpdate, action = 'update') {
|
|
|
2283
2326
|
mark('add', '.memoc/session-summary.md');
|
|
2284
2327
|
}
|
|
2285
2328
|
|
|
2286
|
-
//
|
|
2287
|
-
const
|
|
2329
|
+
// Protocol/template files — replace on update so old instructions are removed.
|
|
2330
|
+
const templateRefresh = [
|
|
2288
2331
|
[path.join(memDir, 'boot.md'), tplBoot],
|
|
2289
2332
|
[path.join(memDir, '01-agent-workflow.md'), tplWorkflow],
|
|
2333
|
+
[path.join(memDir, '05-done-checklist.md'), tplDoneChecklist],
|
|
2334
|
+
[path.join(memDir, 'memoc-usage.md'), tplMemocUsage],
|
|
2335
|
+
[path.join(dir, 'skills/project-memory-maintainer/SKILL.md'), tplSkillMaintainer],
|
|
2336
|
+
];
|
|
2337
|
+
for (const [fp, tpl] of templateRefresh) {
|
|
2338
|
+
const rel = path.relative(dir, fp);
|
|
2339
|
+
mark(writeChanged(fp, tpl()) ? 'update' : 'skip', rel);
|
|
2340
|
+
}
|
|
2341
|
+
|
|
2342
|
+
// Static indexes/scaffolds — add if missing; content may be user- or command-owned.
|
|
2343
|
+
const addIfMissing = [
|
|
2290
2344
|
[path.join(memDir, '03-decisions.md'), tplDecisions],
|
|
2291
2345
|
[path.join(memDir, '04-handoff.md'), tplHandoff],
|
|
2292
|
-
[path.join(memDir, '05-done-checklist.md'), tplDoneChecklist],
|
|
2293
2346
|
[path.join(memDir, '06-project-rules.md'), tplProjectRules],
|
|
2294
2347
|
[path.join(memDir, 'activity.md'), tplActivity],
|
|
2295
2348
|
[path.join(memDir, 'actors/README.md'), tplActorsReadme],
|
|
2296
2349
|
[path.join(memDir, 'worklog/README.md'), tplWorklogReadme],
|
|
2297
|
-
[path.join(memDir, 'memoc-usage.md'), tplMemocUsage],
|
|
2298
2350
|
[path.join(memDir, 'systems/README.md'), tplSystemsReadme],
|
|
2299
2351
|
[path.join(memDir, 'raw/README.md'), tplRawReadme],
|
|
2300
2352
|
[path.join(memDir, 'raw/files/README.md'), tplRawFilesReadme],
|
|
@@ -2309,7 +2361,6 @@ function run(dir, forceUpdate, action = 'update') {
|
|
|
2309
2361
|
[path.join(memDir, 'wiki/sources/README.md'), tplWikiSourcesReadme],
|
|
2310
2362
|
[path.join(memDir, 'wiki/topics/README.md'), tplWikiTopicsReadme],
|
|
2311
2363
|
[path.join(memDir, 'wiki/global/README.md'), tplWikiGlobalReadme],
|
|
2312
|
-
[path.join(dir, 'skills/project-memory-maintainer/SKILL.md'), tplSkillMaintainer],
|
|
2313
2364
|
];
|
|
2314
2365
|
for (const [fp, tpl] of addIfMissing) {
|
|
2315
2366
|
const rel = path.relative(dir, fp);
|
|
@@ -2318,8 +2369,20 @@ function run(dir, forceUpdate, action = 'update') {
|
|
|
2318
2369
|
}
|
|
2319
2370
|
ensureWikiScaffoldLinks(memDir, mark);
|
|
2320
2371
|
|
|
2321
|
-
|
|
2322
|
-
|
|
2372
|
+
const legacyReferenceFiles = [
|
|
2373
|
+
path.join(memDir, '02-current-project-state.md'),
|
|
2374
|
+
path.join(memDir, '04-handoff.md'),
|
|
2375
|
+
path.join(memDir, '06-project-rules.md'),
|
|
2376
|
+
path.join(memDir, 'systems/README.md'),
|
|
2377
|
+
path.join(memDir, 'wiki/index.md'),
|
|
2378
|
+
path.join(memDir, 'wiki/sources.md'),
|
|
2379
|
+
path.join(memDir, 'wiki/glossary.md'),
|
|
2380
|
+
path.join(memDir, 'wiki/questions.md'),
|
|
2381
|
+
path.join(memDir, 'wiki/lint.md'),
|
|
2382
|
+
];
|
|
2383
|
+
for (const fp of legacyReferenceFiles) {
|
|
2384
|
+
if (migrateLegacyLogReferences(fp)) mark('update', `${path.relative(dir, fp)} (legacy refs)`);
|
|
2385
|
+
}
|
|
2323
2386
|
|
|
2324
2387
|
// PATH helpers — let agents run memoc even when the npm bin is not on PATH
|
|
2325
2388
|
ensureClaudeStopHookFile(dir, mark);
|
|
@@ -2327,7 +2390,10 @@ function run(dir, forceUpdate, action = 'update') {
|
|
|
2327
2390
|
ensurePathHelpers(dir, mark);
|
|
2328
2391
|
ensurePathRegistration(dir, mark);
|
|
2329
2392
|
|
|
2330
|
-
|
|
2393
|
+
archiveLegacyLog(dir, mark);
|
|
2394
|
+
|
|
2395
|
+
// Obsidian graph filters — add/merge memoc tags for existing installs too
|
|
2396
|
+
ensureObsidianFrontmatter(dir, mark);
|
|
2331
2397
|
}
|
|
2332
2398
|
|
|
2333
2399
|
hideOnWindows(memDir);
|