@pcircle/memesh 4.8.5 → 4.9.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/mcp.json +6 -4
- package/.codex-plugin/plugin.json +1 -1
- package/AGENTS.md +60 -14
- package/README.de.md +83 -556
- package/README.md +83 -582
- package/README.zh-TW.md +84 -573
- package/dashboard/dist/index.html +10 -10
- package/dist/cli/view-live.d.ts.map +1 -1
- package/dist/cli/view-live.js +154 -384
- package/dist/cli/view-live.js.map +1 -1
- package/dist/core/agent-router.d.ts +11 -10
- package/dist/core/agent-router.d.ts.map +1 -1
- package/dist/core/agent-router.js +29 -14
- package/dist/core/agent-router.js.map +1 -1
- package/dist/core/agent-scope-id.d.ts.map +1 -1
- package/dist/core/agent-scope-id.js.map +1 -1
- package/dist/core/analytics.d.ts.map +1 -1
- package/dist/core/analytics.js.map +1 -1
- package/dist/core/config.d.ts +4 -40
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +75 -141
- package/dist/core/config.js.map +1 -1
- package/dist/core/demo.d.ts.map +1 -1
- package/dist/core/demo.js +6 -6
- package/dist/core/demo.js.map +1 -1
- package/dist/core/doctor.d.ts +1 -6
- package/dist/core/doctor.d.ts.map +1 -1
- package/dist/core/doctor.js +55 -227
- package/dist/core/doctor.js.map +1 -1
- package/dist/core/dreamer.d.ts +32 -47
- package/dist/core/dreamer.d.ts.map +1 -1
- package/dist/core/dreamer.js +211 -703
- package/dist/core/dreamer.js.map +1 -1
- package/dist/core/install-channel.d.ts.map +1 -1
- package/dist/core/install-channel.js +4 -47
- package/dist/core/install-channel.js.map +1 -1
- package/dist/core/install-id.d.ts.map +1 -1
- package/dist/core/install-id.js.map +1 -1
- package/dist/core/kg-backfill.d.ts.map +1 -1
- package/dist/core/kg-backfill.js.map +1 -1
- package/dist/core/lesson-engine.d.ts +0 -5
- package/dist/core/lesson-engine.d.ts.map +1 -1
- package/dist/core/lesson-engine.js +0 -25
- package/dist/core/lesson-engine.js.map +1 -1
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/lifecycle.js +54 -48
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/core/memory-tool.d.ts.map +1 -1
- package/dist/core/memory-tool.js +17 -17
- package/dist/core/memory-tool.js.map +1 -1
- package/dist/core/operations.d.ts +2 -26
- package/dist/core/operations.d.ts.map +1 -1
- package/dist/core/operations.js +9 -244
- package/dist/core/operations.js.map +1 -1
- package/dist/core/paths.d.ts +4 -1
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +88 -14
- package/dist/core/paths.js.map +1 -1
- package/dist/core/product-improvements.js +2 -2
- package/dist/core/product-improvements.js.map +1 -1
- package/dist/core/schema-export.d.ts.map +1 -1
- package/dist/core/schema-export.js +10 -0
- package/dist/core/schema-export.js.map +1 -1
- package/dist/core/semver.d.ts +7 -0
- package/dist/core/semver.d.ts.map +1 -0
- package/dist/core/semver.js +49 -0
- package/dist/core/semver.js.map +1 -0
- package/dist/core/serializer.d.ts.map +1 -1
- package/dist/core/serializer.js +69 -57
- package/dist/core/serializer.js.map +1 -1
- package/dist/core/signal-scorer.d.ts.map +1 -1
- package/dist/core/signal-scorer.js.map +1 -1
- package/dist/core/transcript-extractor.d.ts +1 -85
- package/dist/core/transcript-extractor.d.ts.map +1 -1
- package/dist/core/transcript-extractor.js +5 -364
- package/dist/core/transcript-extractor.js.map +1 -1
- package/dist/core/transcript-source.d.ts +22 -6
- package/dist/core/transcript-source.d.ts.map +1 -1
- package/dist/core/transcript-source.js +108 -69
- package/dist/core/transcript-source.js.map +1 -1
- package/dist/core/types.d.ts +1 -17
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/version-check.d.ts.map +1 -1
- package/dist/core/version-check.js +11 -1
- package/dist/core/version-check.js.map +1 -1
- package/dist/db.d.ts +0 -34
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +3 -287
- package/dist/db.js.map +1 -1
- package/dist/host-runtime/acp.d.ts.map +1 -1
- package/dist/host-runtime/acp.js +2 -2
- package/dist/host-runtime/acp.js.map +1 -1
- package/dist/host-runtime/claude.d.ts.map +1 -1
- package/dist/host-runtime/claude.js +9 -7
- package/dist/host-runtime/claude.js.map +1 -1
- package/dist/host-runtime/codex-session.d.ts +9 -1
- package/dist/host-runtime/codex-session.d.ts.map +1 -1
- package/dist/host-runtime/codex-session.js +474 -29
- package/dist/host-runtime/codex-session.js.map +1 -1
- package/dist/host-runtime/codex.d.ts.map +1 -1
- package/dist/host-runtime/codex.js +2 -2
- package/dist/host-runtime/codex.js.map +1 -1
- package/dist/host-runtime/config.d.ts +1 -0
- package/dist/host-runtime/config.d.ts.map +1 -1
- package/dist/host-runtime/config.js +4 -0
- package/dist/host-runtime/config.js.map +1 -1
- package/dist/host-runtime/router-client.d.ts.map +1 -1
- package/dist/host-runtime/router-client.js +62 -15
- package/dist/host-runtime/router-client.js.map +1 -1
- package/dist/host-runtime/router.js +2 -2
- package/dist/host-runtime/router.js.map +1 -1
- package/dist/knowledge-graph.d.ts.map +1 -1
- package/dist/knowledge-graph.js +54 -45
- package/dist/knowledge-graph.js.map +1 -1
- package/dist/mcp/THIRD_PARTY_NOTICES.txt +217 -0
- package/dist/mcp/server.js +30685 -38
- package/dist/mcp/server.js.map +6 -1
- package/dist/skills-manifest.json +22 -22
- package/dist/storage/entity-index.d.ts +0 -1
- package/dist/storage/entity-index.d.ts.map +1 -1
- package/dist/storage/entity-index.js +0 -7
- package/dist/storage/entity-index.js.map +1 -1
- package/dist/storage/fts-index.d.ts.map +1 -1
- package/dist/storage/fts-index.js +6 -7
- package/dist/storage/fts-index.js.map +1 -1
- package/dist/storage/graph-repairs.d.ts +0 -5
- package/dist/storage/graph-repairs.d.ts.map +1 -1
- package/dist/storage/graph-repairs.js +4 -91
- package/dist/storage/graph-repairs.js.map +1 -1
- package/dist/storage/schema.d.ts +1 -1
- package/dist/storage/schema.d.ts.map +1 -1
- package/dist/storage/schema.js +1 -2
- package/dist/storage/schema.js.map +1 -1
- package/dist/storage/sqlite.d.ts +0 -1
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/transports/agent-messaging.d.ts.map +1 -1
- package/dist/transports/agent-messaging.js +5 -7
- package/dist/transports/agent-messaging.js.map +1 -1
- package/dist/transports/cli/cli.d.ts.map +1 -1
- package/dist/transports/cli/cli.js +52 -674
- package/dist/transports/cli/cli.js.map +1 -1
- package/dist/transports/http/retired-routes.js +1 -1
- package/dist/transports/http/retired-routes.js.map +1 -1
- package/dist/transports/http/server.d.ts.map +1 -1
- package/dist/transports/http/server.js +13 -232
- package/dist/transports/http/server.js.map +1 -1
- package/dist/transports/mcp/handlers.d.ts +127 -1
- package/dist/transports/mcp/handlers.d.ts.map +1 -1
- package/dist/transports/mcp/handlers.js +53 -4
- package/dist/transports/mcp/handlers.js.map +1 -1
- package/dist/transports/schemas.d.ts +52 -0
- package/dist/transports/schemas.d.ts.map +1 -1
- package/dist/transports/schemas.js +39 -0
- package/dist/transports/schemas.js.map +1 -1
- package/docs/platforms/README.md +5 -4
- package/docs/platforms/agent-messaging.md +124 -60
- package/hooks/hooks.json +13 -2
- package/llms-install.md +62 -30
- package/package.json +4 -5
- package/scripts/hooks/_generated/core-paths.js +88 -14
- package/scripts/hooks/_generated/fts-index.js +6 -7
- package/scripts/hooks/_generated/schema.js +1 -2
- package/scripts/hooks/_shared.js +14 -20
- package/scripts/hooks/session-start.js +8 -6
- package/scripts/hooks/session-summary.js +19 -374
- package/skills/memesh/SKILL.md +19 -14
- package/skills/memesh-review/SKILL.md +7 -6
- package/dist/core/auto-tagger.d.ts +0 -10
- package/dist/core/auto-tagger.d.ts.map +0 -1
- package/dist/core/auto-tagger.js +0 -63
- package/dist/core/auto-tagger.js.map +0 -1
- package/dist/core/conflict-candidates.d.ts +0 -20
- package/dist/core/conflict-candidates.d.ts.map +0 -1
- package/dist/core/conflict-candidates.js +0 -71
- package/dist/core/conflict-candidates.js.map +0 -1
- package/dist/core/conflict-judge.d.ts +0 -58
- package/dist/core/conflict-judge.d.ts.map +0 -1
- package/dist/core/conflict-judge.js +0 -189
- package/dist/core/conflict-judge.js.map +0 -1
- package/dist/core/digest-validator.d.ts +0 -18
- package/dist/core/digest-validator.d.ts.map +0 -1
- package/dist/core/digest-validator.js +0 -85
- package/dist/core/digest-validator.js.map +0 -1
- package/dist/core/embedder.d.ts +0 -20
- package/dist/core/embedder.d.ts.map +0 -1
- package/dist/core/embedder.js +0 -245
- package/dist/core/embedder.js.map +0 -1
- package/dist/core/failure-analyzer.d.ts +0 -19
- package/dist/core/failure-analyzer.d.ts.map +0 -1
- package/dist/core/failure-analyzer.js +0 -83
- package/dist/core/failure-analyzer.js.map +0 -1
- package/dist/core/json-utils.d.ts +0 -3
- package/dist/core/json-utils.d.ts.map +0 -1
- package/dist/core/json-utils.js +0 -46
- package/dist/core/json-utils.js.map +0 -1
- package/dist/core/llm-client.d.ts +0 -22
- package/dist/core/llm-client.d.ts.map +0 -1
- package/dist/core/llm-client.js +0 -203
- package/dist/core/llm-client.js.map +0 -1
- package/dist/core/llm-telemetry.d.ts +0 -47
- package/dist/core/llm-telemetry.d.ts.map +0 -1
- package/dist/core/llm-telemetry.js +0 -117
- package/dist/core/llm-telemetry.js.map +0 -1
- package/dist/core/llm-validator.d.ts +0 -20
- package/dist/core/llm-validator.d.ts.map +0 -1
- package/dist/core/llm-validator.js +0 -231
- package/dist/core/llm-validator.js.map +0 -1
- package/dist/core/ollama-host.d.ts +0 -6
- package/dist/core/ollama-host.d.ts.map +0 -1
- package/dist/core/ollama-host.js +0 -62
- package/dist/core/ollama-host.js.map +0 -1
- package/dist/core/output-language.d.ts +0 -6
- package/dist/core/output-language.d.ts.map +0 -1
- package/dist/core/output-language.js +0 -25
- package/dist/core/output-language.js.map +0 -1
- package/dist/core/prompt-safety.d.ts +0 -4
- package/dist/core/prompt-safety.d.ts.map +0 -1
- package/dist/core/prompt-safety.js +0 -20
- package/dist/core/prompt-safety.js.map +0 -1
- package/dist/storage/vector-index.d.ts +0 -3
- package/dist/storage/vector-index.d.ts.map +0 -1
- package/dist/storage/vector-index.js +0 -13
- package/dist/storage/vector-index.js.map +0 -1
|
@@ -4,26 +4,9 @@
|
|
|
4
4
|
// Extracts knowledge from completed Claude Code sessions
|
|
5
5
|
// and stores as session-insight entities in MeMesh.
|
|
6
6
|
//
|
|
7
|
-
// THIS HOOK STAYS, and that was an open question rather than an assumption.
|
|
8
|
-
// `dream run --from-transcripts` reads the same sessions from their raw JSONL
|
|
9
|
-
// and does not depend on this hook having fired, so the obvious next step was
|
|
10
|
-
// to retire the hook as redundant. Measured first, on a real graph
|
|
11
|
-
// (2026-08-09, 214 active entities, ollama nomic-embed-text, L2 over the same
|
|
12
|
-
// `name + observations` text the runtime embeds):
|
|
13
|
-
//
|
|
14
|
-
// every transcript-mined memory -> its nearest hook-captured entity
|
|
15
|
-
// min 0.784 p25 0.821 p50 0.865 max 0.946
|
|
16
|
-
// within 0.55: 0 of 47. within 0.70: 0 of 47.
|
|
17
|
-
//
|
|
18
|
-
// Nothing the transcript miner produced came within 0.78 of anything this hook
|
|
19
|
-
// recorded. They are not two views of the same material: this hook records what
|
|
20
|
-
// HAPPENED (files touched, commands run, commits), the miner extracts what was
|
|
21
|
-
// DECIDED and what was LEARNED. Retiring either one loses a whole category.
|
|
22
|
-
|
|
23
7
|
import { createRequire } from 'module';
|
|
24
8
|
import { basename, join } from 'path';
|
|
25
|
-
import { existsSync, readFileSync
|
|
26
|
-
import { spawn } from 'child_process';
|
|
9
|
+
import { existsSync, readFileSync } from 'fs';
|
|
27
10
|
import { pathToFileURL } from 'url';
|
|
28
11
|
import {
|
|
29
12
|
AUTO_CAPTURE_TAG,
|
|
@@ -32,7 +15,6 @@ import {
|
|
|
32
15
|
extractCitedMemoryIds,
|
|
33
16
|
getMemeshDirFromDbPath,
|
|
34
17
|
getProjectName,
|
|
35
|
-
importFromPluginRoot,
|
|
36
18
|
isAutoCaptureEnabled,
|
|
37
19
|
openHookDb,
|
|
38
20
|
readUpdateCheckCache,
|
|
@@ -47,24 +29,17 @@ import {
|
|
|
47
29
|
|
|
48
30
|
const require = createRequire(import.meta.url);
|
|
49
31
|
|
|
50
|
-
|
|
51
|
-
// Same pattern as session-start.js: async ESM import at process init,
|
|
52
|
-
// falls back to null if dist is missing (source checkout pre-build).
|
|
53
|
-
let _installChannelMod = null;
|
|
32
|
+
let installChannel = null;
|
|
54
33
|
try {
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
if (existsSync(
|
|
58
|
-
|
|
34
|
+
const pluginRoot = resolvePluginRoot(import.meta.url);
|
|
35
|
+
const modulePath = join(pluginRoot, 'dist/core/install-channel.js');
|
|
36
|
+
if (existsSync(modulePath)) {
|
|
37
|
+
installChannel = await import(pathToFileURL(modulePath).href);
|
|
59
38
|
}
|
|
60
|
-
} catch {
|
|
39
|
+
} catch {
|
|
40
|
+
// Best-effort: source checkouts may not have built dist output yet.
|
|
41
|
+
}
|
|
61
42
|
|
|
62
|
-
/**
|
|
63
|
-
* Run auto-update at Stop hook: reads cache, evaluates policy, and dispatches
|
|
64
|
-
* the detached updater runner if warranted. Runs after all session work
|
|
65
|
-
* completes, avoiding the TOCTOU race where install would overwrite dist/
|
|
66
|
-
* mid-session.
|
|
67
|
-
*/
|
|
68
43
|
async function runAutoUpdateAtStop() {
|
|
69
44
|
try {
|
|
70
45
|
const pluginRoot = resolvePluginRoot(import.meta.url);
|
|
@@ -75,11 +50,9 @@ async function runAutoUpdateAtStop() {
|
|
|
75
50
|
const cache = readUpdateCheckCache(installedVersion);
|
|
76
51
|
const policy = resolveAutoUpdatePolicy(process.env);
|
|
77
52
|
const decision = decideAutoUpdateHook(installedVersion, cache, policy);
|
|
78
|
-
if (decision.run)
|
|
79
|
-
await spawnAutoUpdate(decision.latest, _installChannelMod);
|
|
80
|
-
}
|
|
53
|
+
if (decision.run) await spawnAutoUpdate(decision.latest, installChannel);
|
|
81
54
|
} catch {
|
|
82
|
-
// Best-effort
|
|
55
|
+
// Best-effort: update failures must never break session capture.
|
|
83
56
|
}
|
|
84
57
|
}
|
|
85
58
|
|
|
@@ -183,13 +156,9 @@ function parseTranscript(transcriptPath) {
|
|
|
183
156
|
const text = typeof block.content === 'string'
|
|
184
157
|
? block.content
|
|
185
158
|
: JSON.stringify(block.content);
|
|
186
|
-
// Same reason as the bash branch
|
|
187
|
-
//
|
|
188
|
-
//
|
|
189
|
-
// header — the ordinary shape of an auth error — would be stored
|
|
190
|
-
// and then transmitted off the machine. Redacted once here, at
|
|
191
|
-
// the point the text enters the process, so every downstream use
|
|
192
|
-
// inherits it.
|
|
159
|
+
// Same reason as the bash branch: a failed request may echo its
|
|
160
|
+
// own Authorization header. Redact once, where text enters the
|
|
161
|
+
// process, so every downstream use inherits it.
|
|
193
162
|
errorsEncountered.push(redactSecrets(text).slice(0, 200));
|
|
194
163
|
}
|
|
195
164
|
}
|
|
@@ -338,33 +307,12 @@ process.stdin.on('end', async () => {
|
|
|
338
307
|
// healthy exit, so it MUST stamp (see stampHookRunOnly).
|
|
339
308
|
if (toolCallCount < 3) { stampHookRunOnly(process.env, 'session-summary'); return exit0(); }
|
|
340
309
|
|
|
341
|
-
// Hoisted to outer-try scope so the LLM failure-analysis block
|
|
342
|
-
// below (which runs AFTER db.close()) can reference it. Earlier
|
|
343
|
-
// version defined projectName inside the inner try-finally and the
|
|
344
|
-
// LLM path threw `projectName is not defined` silently — caught by
|
|
345
|
-
// the LLM try/catch but logged to stderr. Result: lesson_learned
|
|
346
|
-
// creation never actually happened in production.
|
|
347
310
|
const projectName = getProjectName(cwd);
|
|
348
311
|
|
|
349
312
|
// Open DB via shared helper — applies SCHEMA_SQL + status migration.
|
|
350
313
|
// { fts: true } guarantees the entities_fts table exists so captureEntity()
|
|
351
314
|
// can keep it in sync — session-insight memories must be FTS-recallable.
|
|
352
315
|
//
|
|
353
|
-
// sqlite-vec is NOT loaded here, and used to be. The comment said it was
|
|
354
|
-
// needed "for embedding-aware recall-effectiveness tracking" — but this
|
|
355
|
-
// hook runs exactly two statements, `PRAGMA table_info(entities)` and
|
|
356
|
-
// `SELECT id FROM entities WHERE name = ?`, and `captureEntity` in
|
|
357
|
-
// _shared.js touches no vectors either. Nothing here has ever used the
|
|
358
|
-
// extension.
|
|
359
|
-
//
|
|
360
|
-
// It was not free. sqlite-vec ships its engine as a per-platform file
|
|
361
|
-
// through optionalDependencies, and on a platform it does not publish the
|
|
362
|
-
// load threw — past the `require` guard, which never fired because the JS
|
|
363
|
-
// wrapper resolves fine and the throw happens later inside
|
|
364
|
-
// `sqliteVec.load()`. Measured with the platform binary hidden: the whole
|
|
365
|
-
// Stop capture vanished (0 entities against a control run's 1) and the
|
|
366
|
-
// user got a `Require stack:` dump on stderr. An extension nobody calls
|
|
367
|
-
// was silently costing every session on those platforms its memory.
|
|
368
316
|
const { db } = openHookDb(process.env, { fts: true });
|
|
369
317
|
let writeFailed = false;
|
|
370
318
|
try {
|
|
@@ -628,68 +576,17 @@ process.stdin.on('end', async () => {
|
|
|
628
576
|
db.close();
|
|
629
577
|
}
|
|
630
578
|
|
|
631
|
-
// ── LLM-powered failure analysis (Level 1 only) ──────────────────────
|
|
632
|
-
// Runs AFTER the hook's own DB is closed.
|
|
633
|
-
// Uses the core module's DB singleton (openDatabase/closeDatabase).
|
|
634
|
-
// Wrapped in its own try/catch — never blocks rule-based extraction.
|
|
635
|
-
if (errorsEncountered.length > 0 && filesEdited.length > 0) {
|
|
636
|
-
try {
|
|
637
|
-
// F5: derive pluginRoot strictly from this file's location.
|
|
638
|
-
// See `resolvePluginRoot` for the full reasoning.
|
|
639
|
-
const pluginRoot = resolvePluginRoot(import.meta.url);
|
|
640
|
-
const configMod = await importFromPluginRoot(pluginRoot, 'dist/core/config.js');
|
|
641
|
-
const config = configMod.readConfig();
|
|
642
|
-
|
|
643
|
-
if (config.llm) {
|
|
644
|
-
const { openDatabase, closeDatabase } = await importFromPluginRoot(pluginRoot, 'dist/db.js');
|
|
645
|
-
const { analyzeFailure } = await importFromPluginRoot(pluginRoot, 'dist/core/failure-analyzer.js');
|
|
646
|
-
const { createLesson } = await importFromPluginRoot(pluginRoot, 'dist/core/lesson-engine.js');
|
|
647
|
-
|
|
648
|
-
openDatabase();
|
|
649
|
-
try {
|
|
650
|
-
// Pass cross-provider failover chain so a stale Anthropic key
|
|
651
|
-
// doesn't silently disable Stop-hook lesson generation.
|
|
652
|
-
const lesson = await analyzeFailure(errorsEncountered, filesEdited, config.llm, { fallbacks: config.llmFallbacks });
|
|
653
|
-
if (lesson) {
|
|
654
|
-
createLesson(lesson, projectName);
|
|
655
|
-
}
|
|
656
|
-
} finally {
|
|
657
|
-
closeDatabase();
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
} catch (llmErr) {
|
|
661
|
-
// LLM analysis failed — rule-based extraction already captured the session.
|
|
662
|
-
// Log to stderr so config issues (e.g. invalid API key) are visible.
|
|
663
|
-
try { process.stderr.write(`[memesh] LLM failure analysis skipped: ${llmErr?.message || llmErr}\n`); } catch {}
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
// Auto-trigger dream — solves the "Insights tab is empty for users
|
|
668
|
-
// who don't know `memesh dream run` exists" problem. Throttled to
|
|
669
|
-
// once per project per 24h, gated by minimum activity threshold.
|
|
670
|
-
// Background-detached spawn so the hook exits immediately even if
|
|
671
|
-
// the LLM call takes 30-60s. See `maybeTriggerDream` for the gate
|
|
672
|
-
// logic and dream-history.json schema.
|
|
673
|
-
try {
|
|
674
|
-
const pluginRoot = resolvePluginRoot(import.meta.url);
|
|
675
|
-
const configMod = await importFromPluginRoot(pluginRoot, 'dist/core/config.js');
|
|
676
|
-
const config = configMod.readConfig();
|
|
677
|
-
maybeTriggerDream(projectName, config, pluginRoot);
|
|
678
|
-
} catch (dreamErr) {
|
|
679
|
-
try { process.stderr.write(`[memesh] dream auto-trigger skipped: ${dreamErr?.message || dreamErr}\n`); } catch {}
|
|
680
|
-
}
|
|
681
579
|
} catch (err) {
|
|
682
580
|
// Never crash Claude Code — leave a trace for debugging.
|
|
683
581
|
//
|
|
684
|
-
// Every error is traced
|
|
685
|
-
//
|
|
686
|
-
//
|
|
687
|
-
// could only ever hide a real error from here on.
|
|
582
|
+
// Every error is traced. A retired suppression sentinel once hid setup
|
|
583
|
+
// failures from this hook; with that branch gone, real capture errors stay
|
|
584
|
+
// visible without crashing the host session.
|
|
688
585
|
try { process.stderr.write(`[memesh session-summary] ${err?.message || err}\n`); } catch {}
|
|
689
586
|
}
|
|
690
587
|
|
|
691
|
-
//
|
|
692
|
-
//
|
|
588
|
+
// Update only after all session work so installed files cannot change while
|
|
589
|
+
// this hook is still reading them.
|
|
693
590
|
await runAutoUpdateAtStop();
|
|
694
591
|
|
|
695
592
|
// Emit NOTHING on success — not `{"suppressOutput": true}`.
|
|
@@ -711,173 +608,6 @@ process.stdin.on('end', async () => {
|
|
|
711
608
|
function exit0() {
|
|
712
609
|
process.exit(0);
|
|
713
610
|
}
|
|
714
|
-
|
|
715
|
-
// =============================================================================
|
|
716
|
-
// Dream auto-trigger (Phase 2 / Phase 3 background runner)
|
|
717
|
-
// =============================================================================
|
|
718
|
-
//
|
|
719
|
-
// Without an automated trigger, `memesh dream` only runs when the user
|
|
720
|
-
// types it into a terminal — and most users never read the docs that
|
|
721
|
-
// far. Result: Insights tab stays empty and the KG accumulates 89.7%
|
|
722
|
-
// orphan rate (the maintainer's own observation on this DB).
|
|
723
|
-
//
|
|
724
|
-
// This trigger fires at the END of every Stop hook (after rule-based
|
|
725
|
-
// session capture + optional LLM failure analysis). It:
|
|
726
|
-
// 1. Loads ~/.memesh/dream-history.json — a per-project record of
|
|
727
|
-
// the last dream run timestamp + outcome.
|
|
728
|
-
// 2. Throttles: skip if < THROTTLE_HOURS since the project's last
|
|
729
|
-
// run, even if the previous run produced zero proposals.
|
|
730
|
-
// 3. Activity gate: skip if the project has < MIN_EPISODIC episodic
|
|
731
|
-
// entities to draw from in the last WINDOW_DAYS days.
|
|
732
|
-
// 4. LLM gate: skip if no LLM provider configured (Phase 2 needs
|
|
733
|
-
// Smart Mode — Phase 3 patterns same).
|
|
734
|
-
// 5. Spawns `node <pluginRoot>/dist/transports/cli/cli.js dream run
|
|
735
|
-
// --project <name> --max-llm-calls 2 --window-days 14` as a
|
|
736
|
-
// detached child process. Stdout/stderr go to a per-project log
|
|
737
|
-
// under ~/.memesh/dream-runs/ so the user can `tail -f` to see
|
|
738
|
-
// progress without the hook blocking.
|
|
739
|
-
// 6. Records the run start in dream-history.json BEFORE spawning so
|
|
740
|
-
// a long-running spawn doesn't get re-triggered on the next
|
|
741
|
-
// Stop within the same window.
|
|
742
|
-
//
|
|
743
|
-
// The spawned process inherits config from disk, including the
|
|
744
|
-
// `llmFallbacks` chain wired in commit 883abd4d, so a primary
|
|
745
|
-
// outage falls through to Ollama automatically.
|
|
746
|
-
|
|
747
|
-
const DREAM_THROTTLE_HOURS = 24;
|
|
748
|
-
const DREAM_MIN_EPISODIC = 10;
|
|
749
|
-
const DREAM_WINDOW_DAYS = 14;
|
|
750
|
-
const DREAM_MAX_LLM_CALLS = 2;
|
|
751
|
-
const DREAM_HISTORY_BASENAME = 'dream-history.json';
|
|
752
|
-
const DREAM_LOG_DIRNAME = 'dream-runs';
|
|
753
|
-
|
|
754
|
-
const DREAM_EPISODIC_TYPES = [
|
|
755
|
-
'commit',
|
|
756
|
-
'session_keypoint',
|
|
757
|
-
'session-insight',
|
|
758
|
-
'workflow_checkpoint',
|
|
759
|
-
'weekly-summary',
|
|
760
|
-
'weekly_summary',
|
|
761
|
-
];
|
|
762
|
-
|
|
763
|
-
// Debug-trace gate. Set MEMESH_DREAM_TRIGGER_DEBUG=1 to emit a stderr
|
|
764
|
-
// breadcrumb at every gate decision in maybeTriggerDream. Contract:
|
|
765
|
-
// [memesh dream-trigger] <stage>=<value>...
|
|
766
|
-
// Matches one line per stage (resolve, llm-gate, throttle-gate,
|
|
767
|
-
// activity-gate, history-write, spawn). Stable across releases — if
|
|
768
|
-
// you rename a stage, update the matching test fixture too.
|
|
769
|
-
function dreamTrigTrace(stage, fields) {
|
|
770
|
-
if (process.env.MEMESH_DREAM_TRIGGER_DEBUG !== '1') return;
|
|
771
|
-
try {
|
|
772
|
-
const parts = Object.entries(fields || {}).map(([k, v]) => {
|
|
773
|
-
if (v === undefined) return `${k}=<undef>`;
|
|
774
|
-
if (v === null) return `${k}=<null>`;
|
|
775
|
-
return `${k}=${typeof v === 'string' ? v : JSON.stringify(v)}`;
|
|
776
|
-
});
|
|
777
|
-
process.stderr.write(`[memesh dream-trigger] ${stage} ${parts.join(' ')}\n`);
|
|
778
|
-
} catch {}
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
function dreamHistoryPath() {
|
|
782
|
-
// Test isolation: tests set MEMESH_DB_PATH to a tmp file, expecting
|
|
783
|
-
// sibling state (history, logs) to land beside it. Without honouring
|
|
784
|
-
// that, real-home `~/.memesh/dream-history.json` would be polluted
|
|
785
|
-
// by every test run. Same precedence as memesh's other state files —
|
|
786
|
-
// see `getMemeshDirFromDbPath` in `_shared.js`.
|
|
787
|
-
//
|
|
788
|
-
// Windows note: on Windows under execFileSync, env vars propagate as
|
|
789
|
-
// plain strings (no canonicalisation). If a caller passed MEMESH_DIR
|
|
790
|
-
// with mixed separators (e.g. `C:/Users/.../tmp/.memesh`), join() will
|
|
791
|
-
// happily mix `/` and `\`. Node fs accepts either — the only divergence
|
|
792
|
-
// is in pure string comparisons, which we don't do here. The trace
|
|
793
|
-
// below shows the resolved value verbatim so a Windows diagnosis run
|
|
794
|
-
// can confirm what actually arrived.
|
|
795
|
-
// The helper IS the precedence (MEMESH_DB_PATH > MEMESH_DIR > home).
|
|
796
|
-
// A hand-rolled version here inverted it (MEMESH_DIR won over
|
|
797
|
-
// MEMESH_DB_PATH), so with both set, dream history landed in a different
|
|
798
|
-
// directory than every sibling state file — plus a dead home-fallback
|
|
799
|
-
// branch, since the helper always returns a string.
|
|
800
|
-
const dir = getMemeshDirFromDbPath();
|
|
801
|
-
dreamTrigTrace('resolve', {
|
|
802
|
-
src: process.env.MEMESH_DB_PATH ? 'db-path' : (process.env.MEMESH_DIR ? 'env' : 'home'),
|
|
803
|
-
MEMESH_DIR: process.env.MEMESH_DIR,
|
|
804
|
-
MEMESH_DB_PATH: process.env.MEMESH_DB_PATH,
|
|
805
|
-
dir,
|
|
806
|
-
platform: process.platform,
|
|
807
|
-
});
|
|
808
|
-
return { dir, historyFile: join(dir, DREAM_HISTORY_BASENAME), logDir: join(dir, DREAM_LOG_DIRNAME) };
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
function readDreamHistory() {
|
|
812
|
-
try {
|
|
813
|
-
const { historyFile } = dreamHistoryPath();
|
|
814
|
-
if (!existsSync(historyFile)) return {};
|
|
815
|
-
const raw = readFileSync(historyFile, 'utf8');
|
|
816
|
-
const parsed = JSON.parse(raw);
|
|
817
|
-
return (parsed && typeof parsed === 'object') ? parsed : {};
|
|
818
|
-
} catch { return {}; }
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
function writeDreamHistory(history) {
|
|
822
|
-
try {
|
|
823
|
-
const { dir, historyFile } = dreamHistoryPath();
|
|
824
|
-
mkdirSync(dir, { recursive: true });
|
|
825
|
-
writeFileSync(historyFile, JSON.stringify(history, null, 2));
|
|
826
|
-
dreamTrigTrace('history-write', { historyFile, ok: true, projects: Object.keys(history) });
|
|
827
|
-
} catch (err) {
|
|
828
|
-
dreamTrigTrace('history-write', { ok: false, err: err?.message || String(err) });
|
|
829
|
-
try { process.stderr.write(`[memesh dream-history write] ${err?.message || err}\n`); } catch {}
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
/**
|
|
834
|
-
* Count episodic entities for the given project over the configured
|
|
835
|
-
* window. Only issues a SELECT, but the handle is openHookDb's ordinary
|
|
836
|
-
* read-write one (it runs the schema/migration chain) — there is no
|
|
837
|
-
* read-only variant on the hook side, and this call site must not stamp
|
|
838
|
-
* the heartbeat (recordHookRun is per-hook-exit, never per-open).
|
|
839
|
-
*/
|
|
840
|
-
function countEpisodicEntities(projectName) {
|
|
841
|
-
let handle;
|
|
842
|
-
try {
|
|
843
|
-
handle = openHookDb();
|
|
844
|
-
// { db, dbPath } — don't call db.prepare() on the wrapper itself (an
|
|
845
|
-
// earlier version did, and silently skipped the gate, defeating the
|
|
846
|
-
// trigger's whole purpose).
|
|
847
|
-
const db = handle.db;
|
|
848
|
-
const since = new Date(Date.now() - DREAM_WINDOW_DAYS * 86400000).toISOString();
|
|
849
|
-
const types = DREAM_EPISODIC_TYPES.map(() => '?').join(',');
|
|
850
|
-
// Project-membership is determined by the `project:<name>` tag only.
|
|
851
|
-
// The previous implementation also OR'd on `e.name LIKE 'project-%'`
|
|
852
|
-
// as a fallback for legacy entities, but that branch over-counts when
|
|
853
|
-
// two projects share a name prefix (e.g. counting `memesh` would
|
|
854
|
-
// sweep in `memesh-cloud-keypoint-*` entities). Post-v3.0 episodic
|
|
855
|
-
// entities all carry the project tag — the auto-tagger writes it on
|
|
856
|
-
// every session_keypoint / commit / session_insight / session_lesson
|
|
857
|
-
// / failure_pattern / decision_anchor — so the tag-only path is the
|
|
858
|
-
// accurate signal. See v4.2.1 CHANGELOG known-limitations note.
|
|
859
|
-
const sql = `SELECT COUNT(DISTINCT e.id) AS n
|
|
860
|
-
FROM entities e
|
|
861
|
-
INNER JOIN tags t ON t.entity_id = e.id AND t.tag = ?
|
|
862
|
-
WHERE e.status = 'active'
|
|
863
|
-
AND e.type IN (${types})
|
|
864
|
-
AND e.created_at >= ?`;
|
|
865
|
-
const projectTag = `project:${projectName}`;
|
|
866
|
-
const row = db.prepare(sql).get(projectTag, ...DREAM_EPISODIC_TYPES, since);
|
|
867
|
-
return row?.n ?? 0;
|
|
868
|
-
} catch (err) {
|
|
869
|
-
try { process.stderr.write(`[memesh dream-trigger count] ${err?.message || err}\n`); } catch {}
|
|
870
|
-
return 0;
|
|
871
|
-
} finally {
|
|
872
|
-
try { handle?.db?.close(); } catch {}
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
/**
|
|
877
|
-
* Decide whether to fire dream for `projectName` and, if so, spawn
|
|
878
|
-
* the detached background runner. Pure side effect — no return value
|
|
879
|
-
* used by callers.
|
|
880
|
-
*/
|
|
881
611
|
/**
|
|
882
612
|
* Attachment record types Claude Code uses to persist a hook's own output
|
|
883
613
|
* into the transcript. Anything memesh injected reaches the transcript
|
|
@@ -927,88 +657,3 @@ export function stripHookEchoes(rawTranscript) {
|
|
|
927
657
|
}
|
|
928
658
|
return kept.join('\n');
|
|
929
659
|
}
|
|
930
|
-
|
|
931
|
-
export function maybeTriggerDream(projectName, config, pluginRoot) {
|
|
932
|
-
dreamTrigTrace('enter', { projectName, hasLlm: Boolean(config?.llm) });
|
|
933
|
-
if (!projectName || projectName === 'unknown') {
|
|
934
|
-
dreamTrigTrace('exit', { reason: 'no-project-name', projectName });
|
|
935
|
-
return;
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
// Phase 2 & 3 both need a configured LLM. Without it the dreamer's
|
|
939
|
-
// first action is to push `{reason: 'no LLM configured'}` into
|
|
940
|
-
// skipped[] and exit, which would still bump our throttle clock
|
|
941
|
-
// for no value — so gate here.
|
|
942
|
-
if (!config?.llm) {
|
|
943
|
-
dreamTrigTrace('exit', { reason: 'llm-gate-fail' });
|
|
944
|
-
return;
|
|
945
|
-
}
|
|
946
|
-
dreamTrigTrace('llm-gate', { ok: true });
|
|
947
|
-
|
|
948
|
-
const history = readDreamHistory();
|
|
949
|
-
const last = history[projectName];
|
|
950
|
-
if (last?.last_run_iso) {
|
|
951
|
-
const ageMs = Date.now() - new Date(last.last_run_iso).getTime();
|
|
952
|
-
if (Number.isFinite(ageMs) && ageMs < DREAM_THROTTLE_HOURS * 3600 * 1000) {
|
|
953
|
-
dreamTrigTrace('exit', { reason: 'throttle-gate-fail', ageMs, last_run_iso: last.last_run_iso });
|
|
954
|
-
return; // throttled
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
dreamTrigTrace('throttle-gate', { ok: true, prior_last_run_iso: last?.last_run_iso });
|
|
958
|
-
|
|
959
|
-
const episodicCount = countEpisodicEntities(projectName);
|
|
960
|
-
if (episodicCount < DREAM_MIN_EPISODIC) {
|
|
961
|
-
dreamTrigTrace('exit', { reason: 'activity-gate-fail', episodicCount, threshold: DREAM_MIN_EPISODIC });
|
|
962
|
-
return;
|
|
963
|
-
}
|
|
964
|
-
dreamTrigTrace('activity-gate', { ok: true, episodicCount });
|
|
965
|
-
|
|
966
|
-
// Activity gate passed — record start BEFORE spawning so we don't
|
|
967
|
-
// re-trigger on any subsequent Stop within the window even if the
|
|
968
|
-
// child takes 30-60s.
|
|
969
|
-
history[projectName] = {
|
|
970
|
-
last_run_iso: new Date().toISOString(),
|
|
971
|
-
last_episodic_count: episodicCount,
|
|
972
|
-
last_window_days: DREAM_WINDOW_DAYS,
|
|
973
|
-
};
|
|
974
|
-
writeDreamHistory(history);
|
|
975
|
-
|
|
976
|
-
// Spawn detached so the hook exits immediately. Stdio routes to a
|
|
977
|
-
// per-project log file so the user can inspect dream output without
|
|
978
|
-
// the hook blocking on the LLM call.
|
|
979
|
-
try {
|
|
980
|
-
const { dir, logDir } = dreamHistoryPath();
|
|
981
|
-
mkdirSync(logDir, { recursive: true });
|
|
982
|
-
const safeProj = projectName.replace(/[^A-Za-z0-9_-]/g, '_').slice(0, 64);
|
|
983
|
-
const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
984
|
-
const logFile = join(logDir, `${safeProj}-${ts}.log`);
|
|
985
|
-
|
|
986
|
-
// Append a header so a tail -f shows context for the run.
|
|
987
|
-
appendFileSync(logFile, `[memesh dream] ${new Date().toISOString()} project=${projectName} episodic_count=${episodicCount} window=${DREAM_WINDOW_DAYS}d max_llm_calls=${DREAM_MAX_LLM_CALLS}\n`);
|
|
988
|
-
|
|
989
|
-
const cliPath = join(pluginRoot, 'dist/transports/cli/cli.js');
|
|
990
|
-
if (!existsSync(cliPath)) {
|
|
991
|
-
appendFileSync(logFile, `[memesh dream] cli.js missing at ${cliPath}, skipping\n`);
|
|
992
|
-
return;
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
const args = [
|
|
996
|
-
cliPath, 'dream', 'run',
|
|
997
|
-
'--project', projectName,
|
|
998
|
-
'--max-llm-calls', String(DREAM_MAX_LLM_CALLS),
|
|
999
|
-
'--window-days', String(DREAM_WINDOW_DAYS),
|
|
1000
|
-
];
|
|
1001
|
-
|
|
1002
|
-
const logFd = require('fs').openSync(logFile, 'a');
|
|
1003
|
-
const child = spawn(process.execPath, args, {
|
|
1004
|
-
detached: true,
|
|
1005
|
-
stdio: ['ignore', logFd, logFd],
|
|
1006
|
-
env: { ...process.env, MEMESH_DIR: dir },
|
|
1007
|
-
});
|
|
1008
|
-
child.unref();
|
|
1009
|
-
dreamTrigTrace('spawn', { ok: true, pid: child.pid, logFile, MEMESH_DIR: dir });
|
|
1010
|
-
} catch (err) {
|
|
1011
|
-
dreamTrigTrace('spawn', { ok: false, err: err?.message || String(err) });
|
|
1012
|
-
try { process.stderr.write(`[memesh dream-trigger spawn] ${err?.message || err}\n`); } catch {}
|
|
1013
|
-
}
|
|
1014
|
-
}
|
package/skills/memesh/SKILL.md
CHANGED
|
@@ -23,10 +23,11 @@ Persistent memory for AI agents. The point is continuity: the next session start
|
|
|
23
23
|
|
|
24
24
|
All examples below use CLI. MCP tools accept the same parameters as JSON objects.
|
|
25
25
|
|
|
26
|
-
## All
|
|
26
|
+
## All 12 MCP tools
|
|
27
27
|
|
|
28
28
|
| Tool | Purpose |
|
|
29
29
|
|---|---|
|
|
30
|
+
| `work_package` | Prepare one bounded untrusted `digest` (calendar cluster) or `transcript` package from the newest Claude Code session under the client's single matching MCP workspace root; submit exactly one strict result or defer. Submit only stages pending human review and retains bounded redacted source turns for comparison; agents cannot apply or reject. No hidden reasoning, raw transcript, transcript path, API key, LLM, embedding, or vector data is exposed or used; hashes identify freshness and workspace scope rather than authentication. |
|
|
30
31
|
| `remember` | Store knowledge as an entity with observations, tags, and relations |
|
|
31
32
|
| `recall` | Search stored knowledge; empty query lists recent memories |
|
|
32
33
|
| `forget` | Archive an entity or remove one exact observation |
|
|
@@ -86,7 +87,12 @@ Use the routing and identity fields returned by `fetch`. A reply has this shape
|
|
|
86
87
|
}
|
|
87
88
|
```
|
|
88
89
|
|
|
89
|
-
|
|
90
|
+
For a compatible managed host, native delivery removes polling from the inbound path only after exact live-host acceptance. On macOS and Linux, an ordinary Codex CLI session with the MeMesh plugin registers automatically at SessionStart. SessionEnd retains a bounded 45-second idle queue window; a message accepted there becomes model-visible when the same thread resumes, resume replaces the prior exact generation, and expiry removes the registration. This does not wake a stopped UI. Codex Desktop and unattached tasks are not presumed registered unless the exact running session appears in `message discover`. Separate managed Codex app-server and Claude Channel paths may require one-time owner setup. The bundled Gemini ACP adapter is experimental protocol-development code, not a release-gated native-wakeup provider. Adapter imports and a live router socket do not prove host registration or `host_accept`. Do not promise that a stopped, missing, or replaced session will wake up: it is not resumed or silently rerouted, and a failed exact-session native delivery is not replayed automatically. Use the stable principal for logical routing, and an exact session/generation only when delivery must not move to a replacement connection. Local owns durable storage and host-native delivery; Cloud relay, A2A, SSE, discovery, or fetch is not host delivery.
|
|
91
|
+
|
|
92
|
+
When pairing Claude Channel with an automatically registered Codex session, use
|
|
93
|
+
the complete `project` field from `memesh briefing --json` for Claude setup. Do
|
|
94
|
+
not replace it with the repository basename; different project strings are
|
|
95
|
+
different discovery and native-routing scopes.
|
|
90
96
|
|
|
91
97
|
Durable audit does not mean unbounded silent growth. Owners can inspect it with `memesh message storage report --cutoff <ISO timestamp>`, preview bounded terminal-payload tombstones with `memesh message storage prune --cutoff <ISO timestamp>`, and explicitly add `--apply`. Never prune unresolved/offline-pending work. `MEMESH_AGENT_MESSAGE_STORAGE_QUOTA_BYTES` is an optional owner policy; there is no default quota or automatic pruning.
|
|
92
98
|
|
|
@@ -134,13 +140,12 @@ fabricate a memory or cite a `[mem:id]` that was not actually returned.
|
|
|
134
140
|
Recall is bounded by `limit` — a small hit count is not a graph-wide count,
|
|
135
141
|
and an empty result is not proof nothing was stored: vary the wording or
|
|
136
142
|
narrow by tag before concluding. Every recall answer includes a `retrieval`
|
|
137
|
-
block — `truncated: true` means the window filled (more may exist)
|
|
138
|
-
|
|
139
|
-
keyword-only results right now (`memesh doctor` explains why).
|
|
143
|
+
block — `truncated: true` means the window filled (more may exist). Retrieval
|
|
144
|
+
uses the local FTS5 keyword index; it does not call a model or vector service.
|
|
140
145
|
|
|
141
|
-
## What's Already Automatic (
|
|
146
|
+
## What's Already Automatic (Plugin Hooks)
|
|
142
147
|
|
|
143
|
-
|
|
148
|
+
With the Claude Code plugin, the first eight rows happen **without any action from you**. The final row is the separate Codex plugin SessionStart/SessionEnd companion lifecycle:
|
|
144
149
|
|
|
145
150
|
| Hook | When | What it does |
|
|
146
151
|
|------|------|-------------|
|
|
@@ -149,10 +154,10 @@ If MeMesh is installed as a Claude Code plugin, these happen **without any actio
|
|
|
149
154
|
| **UserPromptSubmit** | When you submit a prompt | Detects "remember this" intent (5 languages) and reminds Claude to use memesh |
|
|
150
155
|
| **PostToolUse (Bash)** | After `git commit` | Auto-tracks the commit with diff stats as a memory entity |
|
|
151
156
|
| **PostToolUse (ExitPlanMode/AskUserQuestion)** | A plan is approved or you answer a question | Reminds Claude to `remember` the decision if it's worth keeping — once per tool per session |
|
|
152
|
-
| **Stop** | Session ends | Auto-captures session knowledge
|
|
157
|
+
| **Stop** | Session ends | Auto-captures session knowledge and applies the configured update policy |
|
|
153
158
|
| **PreCompact** | Before context compaction | Saves important knowledge before history is compressed |
|
|
154
159
|
| **PreToolUse (Bash)** | Before a command runs | Fires accepted lesson-guards — warns when a recorded mistake is about to repeat |
|
|
155
|
-
| **SessionStart (Codex
|
|
160
|
+
| **SessionStart/SessionEnd (Codex)** | An ordinary Codex CLI plugin session starts, resumes, or ends | Launches the detached exact-thread companion, replaces its generation on resume, and retires it after the bounded idle queue window; a matching owner-private config may override its project/principal |
|
|
156
161
|
|
|
157
162
|
Because of the SessionStart hook: **in Claude Code, do NOT call `briefing` at
|
|
158
163
|
session start — it is already in your context.** Call it only mid-session
|
|
@@ -226,16 +231,16 @@ memesh forget --name "old-auth-approach" # archive the who
|
|
|
226
231
|
Both are soft (recoverable) — nothing is permanently removed.
|
|
227
232
|
|
|
228
233
|
### Memories are getting verbose or stale
|
|
229
|
-
Use the **memesh-review** skill: it
|
|
230
|
-
|
|
231
|
-
|
|
234
|
+
Use the **memesh-review** skill: it prepares bounded `work_package` evidence
|
|
235
|
+
for an already-running local agent, then leaves every proposal pending for
|
|
236
|
+
human review. Do not hand-compress memories yourself.
|
|
232
237
|
|
|
233
238
|
### Backup, share, health
|
|
234
239
|
```bash
|
|
235
240
|
memesh export --tag "project:myapp" > memories.json
|
|
236
241
|
memesh import memories.json --merge skip # skip | overwrite | append
|
|
237
|
-
memesh status # version,
|
|
238
|
-
memesh reindex
|
|
242
|
+
memesh status # version, install channel, update state
|
|
243
|
+
memesh reindex --fts # rebuild the local keyword index
|
|
239
244
|
```
|
|
240
245
|
|
|
241
246
|
## Memory hygiene
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: memesh-review
|
|
3
|
-
description: Review and optimize the MeMesh memory database. Analyzes health score, finds stale
|
|
3
|
+
description: Review and optimize the MeMesh memory database. Analyzes health score, finds stale or noisy memories, shows work patterns, and suggests human-reviewed cleanup actions. Use when asked to "review memories", "check memory health", "clean up knowledge", or "what's in my memory".
|
|
4
4
|
user-invocable: true
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -59,11 +59,12 @@ From the recalled data, compute and present:
|
|
|
59
59
|
|
|
60
60
|
**Verbose (5+ observations)**
|
|
61
61
|
- "entity-name" (N observations) — note it; there is no one-entity compression
|
|
62
|
-
command
|
|
63
|
-
|
|
62
|
+
command. If useful knowledge is spread across episodic entries, an already
|
|
63
|
+
running agent can prepare one MCP `work_package` for human review.
|
|
64
64
|
|
|
65
65
|
**Potential conflicts**
|
|
66
|
-
- "entity-A" vs "entity-B" —
|
|
66
|
+
- "entity-A" vs "entity-B" — inspect the text and recommend an explicit
|
|
67
|
+
`contradicts` or `supersedes` relation; MeMesh does not judge it automatically
|
|
67
68
|
|
|
68
69
|
**Noise ratio**
|
|
69
70
|
- N% auto-tracked (session_keypoint, commit) vs N% intentional knowledge
|
|
@@ -71,7 +72,7 @@ From the recalled data, compute and present:
|
|
|
71
72
|
|
|
72
73
|
### Recommended Actions
|
|
73
74
|
1. `memesh forget --name "old-design"` (superseded)
|
|
74
|
-
2.
|
|
75
|
+
2. Ask the current agent to prepare one MCP `work_package`; then review the staged proposal
|
|
75
76
|
3. `memesh remember ...` (knowledge gap in [area])
|
|
76
77
|
```
|
|
77
78
|
|
|
@@ -81,7 +82,7 @@ Present the report first. Ask which actions to execute. Then run the commands:
|
|
|
81
82
|
|
|
82
83
|
```bash
|
|
83
84
|
memesh forget --name "outdated-entity"
|
|
84
|
-
|
|
85
|
+
# MCP work_package submits one proposal; then use dream show / accept / reject
|
|
85
86
|
memesh remember --name "missing-knowledge" --type decision --obs "..."
|
|
86
87
|
```
|
|
87
88
|
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { LLMConfig } from './config.js';
|
|
2
|
-
import { type LLMAttempt } from './llm-client.js';
|
|
3
|
-
export interface AutoTagOptions {
|
|
4
|
-
fallbacks?: LLMConfig[];
|
|
5
|
-
onAttempt?: (attempts: LLMAttempt[]) => void;
|
|
6
|
-
}
|
|
7
|
-
export declare function autoTag(name: string, type: string, observations: string[], llmConfig: LLMConfig, opts?: AutoTagOptions): Promise<string[]>;
|
|
8
|
-
export declare function autoTagAndApply(entityId: number, name: string, type: string, observations: string[], llmConfig: LLMConfig, opts?: AutoTagOptions): Promise<void>;
|
|
9
|
-
export declare function parseTags(text: string): string[];
|
|
10
|
-
//# sourceMappingURL=auto-tagger.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auto-tagger.d.ts","sourceRoot":"","sources":["../../src/core/auto-tagger.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAW,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAM3D,MAAM,WAAW,cAAc;IAE7B,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IAExB,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC;CAC9C;AAOD,wBAAsB,OAAO,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EAAE,EACtB,SAAS,EAAE,SAAS,EACpB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,MAAM,EAAE,CAAC,CAgCnB;AAMD,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EAAE,EACtB,SAAS,EAAE,SAAS,EACpB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAehD"}
|