@pcircle/memesh 4.8.0 → 4.8.2

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 (81) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/AGENTS.md +7 -1
  4. package/README.de.md +1 -1
  5. package/README.md +1 -1
  6. package/README.zh-TW.md +1 -1
  7. package/dashboard/dist/index.html +9 -9
  8. package/dist/core/agent-message-inbox.d.ts +9 -0
  9. package/dist/core/agent-message-inbox.d.ts.map +1 -0
  10. package/dist/core/agent-message-inbox.js +26 -0
  11. package/dist/core/agent-message-inbox.js.map +1 -0
  12. package/dist/core/agent-router.d.ts.map +1 -1
  13. package/dist/core/agent-router.js +5 -5
  14. package/dist/core/agent-router.js.map +1 -1
  15. package/dist/core/briefing.d.ts.map +1 -1
  16. package/dist/core/briefing.js +5 -1
  17. package/dist/core/briefing.js.map +1 -1
  18. package/dist/core/config.d.ts +4 -1
  19. package/dist/core/config.d.ts.map +1 -1
  20. package/dist/core/config.js +12 -3
  21. package/dist/core/config.js.map +1 -1
  22. package/dist/core/doctor.d.ts.map +1 -1
  23. package/dist/core/doctor.js +5 -2
  24. package/dist/core/doctor.js.map +1 -1
  25. package/dist/core/dreamer.d.ts +2 -0
  26. package/dist/core/dreamer.d.ts.map +1 -1
  27. package/dist/core/dreamer.js +7 -1
  28. package/dist/core/dreamer.js.map +1 -1
  29. package/dist/core/lesson-engine.d.ts +2 -1
  30. package/dist/core/lesson-engine.d.ts.map +1 -1
  31. package/dist/core/lesson-engine.js +5 -2
  32. package/dist/core/lesson-engine.js.map +1 -1
  33. package/dist/core/lesson-slug.d.ts +2 -0
  34. package/dist/core/lesson-slug.d.ts.map +1 -0
  35. package/dist/core/lesson-slug.js +12 -0
  36. package/dist/core/lesson-slug.js.map +1 -0
  37. package/dist/core/llm-client.js +1 -1
  38. package/dist/core/llm-client.js.map +1 -1
  39. package/dist/core/llm-validator.d.ts +4 -1
  40. package/dist/core/llm-validator.d.ts.map +1 -1
  41. package/dist/core/llm-validator.js +59 -30
  42. package/dist/core/llm-validator.js.map +1 -1
  43. package/dist/core/operations.d.ts +9 -3
  44. package/dist/core/operations.d.ts.map +1 -1
  45. package/dist/core/operations.js +18 -14
  46. package/dist/core/operations.js.map +1 -1
  47. package/dist/core/paths.d.ts.map +1 -1
  48. package/dist/core/paths.js +2 -3
  49. package/dist/core/paths.js.map +1 -1
  50. package/dist/core/schema-export.js +2 -2
  51. package/dist/core/schema-export.js.map +1 -1
  52. package/dist/core/transcript-extractor.d.ts.map +1 -1
  53. package/dist/core/transcript-extractor.js +2 -2
  54. package/dist/core/transcript-extractor.js.map +1 -1
  55. package/dist/db.d.ts.map +1 -1
  56. package/dist/db.js +12 -0
  57. package/dist/db.js.map +1 -1
  58. package/dist/host-runtime/acp.d.ts.map +1 -1
  59. package/dist/host-runtime/acp.js +12 -4
  60. package/dist/host-runtime/acp.js.map +1 -1
  61. package/dist/skills-manifest.json +14 -9
  62. package/dist/storage/graph-repairs.d.ts +12 -0
  63. package/dist/storage/graph-repairs.d.ts.map +1 -0
  64. package/dist/storage/graph-repairs.js +194 -0
  65. package/dist/storage/graph-repairs.js.map +1 -0
  66. package/dist/transports/cli/cli.d.ts +5 -0
  67. package/dist/transports/cli/cli.d.ts.map +1 -1
  68. package/dist/transports/cli/cli.js +20 -9
  69. package/dist/transports/cli/cli.js.map +1 -1
  70. package/dist/transports/http/server.d.ts.map +1 -1
  71. package/dist/transports/http/server.js +117 -7
  72. package/dist/transports/http/server.js.map +1 -1
  73. package/dist/transports/mcp/handlers.d.ts +1 -1
  74. package/dist/transports/mcp/handlers.js +1 -1
  75. package/dist/transports/mcp/handlers.js.map +1 -1
  76. package/package.json +13 -3
  77. package/scripts/hooks/_generated/agent-message-inbox.js +33 -0
  78. package/scripts/hooks/_generated/core-paths.js +2 -3
  79. package/scripts/hooks/session-start.js +34 -7
  80. package/scripts/hooks/session-summary.js +40 -1
  81. package/skills/memesh/SKILL.md +17 -1
@@ -0,0 +1,194 @@
1
+ import { rebuildFtsIndex, runOnceMigration } from './schema.js';
2
+ import { lessonSlug } from '../core/lesson-slug.js';
3
+ import { computeSignalScore } from '../core/signal-scorer.js';
4
+ export const SESSION_DEDUPE_KEY = 'session_observation_dedupe';
5
+ export const ZERO_EDIT_RETRACT_KEY = 'session_zero_edit_retract';
6
+ export const FUSED_LESSON_SPLIT_KEY = 'fused_lesson_split';
7
+ const ZERO_EDITS = ', 0 files edited';
8
+ const ZERO_EDITS_RETRACTED = ', files edited through Bash (count not recorded before 4.8.2)';
9
+ function note(line) {
10
+ process.stderr.write(`MeMesh: ${line}\n`);
11
+ }
12
+ export function dedupeSessionObservations(db) {
13
+ let removed = -1;
14
+ runOnceMigration(db, {
15
+ key: SESSION_DEDUPE_KEY,
16
+ version: 1,
17
+ describe: 'session observation dedupe',
18
+ migrate: (conn) => {
19
+ const affected = conn
20
+ .prepare(`SELECT DISTINCT e.id FROM entities e JOIN observations o ON o.entity_id = e.id
21
+ WHERE e.name LIKE 'session-%'
22
+ GROUP BY e.id, o.content HAVING COUNT(o.id) > 1`)
23
+ .all();
24
+ removed = 0;
25
+ const del = conn.prepare(`DELETE FROM observations WHERE entity_id = ? AND id NOT IN (
26
+ SELECT MIN(id) FROM observations WHERE entity_id = ? GROUP BY content)`);
27
+ for (const row of affected)
28
+ removed += Number(del.run(row.id, row.id).changes);
29
+ if (removed > 0) {
30
+ rebuildFtsIndex(conn);
31
+ note(`removed ${removed} duplicate observation(s) from ${affected.length} session entit${affected.length === 1 ? 'y' : 'ies'} (written by 4.8.1 hooks).`);
32
+ }
33
+ },
34
+ });
35
+ return removed;
36
+ }
37
+ const BASH_WRITE_SHAPES = [
38
+ /(?:^|[^<])>\s*"?([^\s"'>|&;]+)"?\s*<<\s*['"]?\w+['"]?/,
39
+ /\bcat\s*>\s*"?([^\s"'>|&;]+)"?/,
40
+ /\btee\s+(?:-a\s+)?"?([^\s"'>|&;]+)"?/,
41
+ /\bsed\s+-i(?:\s+'')?\s+(?:'[^']*'|"[^"]*")\s+"?([^\s"'>|&;]+)"?/,
42
+ /Path\(\s*['"]([^'"]+)['"]\s*\)\s*\.write_text\(/,
43
+ /writeFileSync\(\s*['"]([^'"]+)['"]/,
44
+ ];
45
+ export function bashWritesFiles(command) {
46
+ for (const re of BASH_WRITE_SHAPES) {
47
+ for (const m of command.matchAll(new RegExp(re.source, 'g'))) {
48
+ if (m[1] && !m[1].startsWith('/dev/') && !m[1].startsWith('/tmp/'))
49
+ return true;
50
+ }
51
+ }
52
+ return false;
53
+ }
54
+ export function retractZeroEditClaims(db) {
55
+ let rewritten = -1;
56
+ runOnceMigration(db, {
57
+ key: ZERO_EDIT_RETRACT_KEY,
58
+ version: 1,
59
+ describe: 'session zero-edit retraction',
60
+ migrate: (conn) => {
61
+ const candidates = conn
62
+ .prepare(`SELECT o.id, o.content, o.entity_id FROM observations o JOIN entities e ON e.id = o.entity_id
63
+ WHERE e.name LIKE 'session-%-summary'
64
+ AND o.content LIKE 'Significant session:%${ZERO_EDITS}%'`)
65
+ .all();
66
+ const commands = conn.prepare("SELECT content FROM observations WHERE entity_id = ? AND content LIKE 'Command:%'");
67
+ const update = conn.prepare('UPDATE observations SET content = ? WHERE id = ?');
68
+ rewritten = 0;
69
+ for (const row of candidates) {
70
+ const cmds = commands.all(row.entity_id);
71
+ if (!cmds.some((c) => bashWritesFiles(c.content)))
72
+ continue;
73
+ update.run(row.content.replace(ZERO_EDITS, ZERO_EDITS_RETRACTED), row.id);
74
+ rewritten += 1;
75
+ }
76
+ if (rewritten > 0) {
77
+ rebuildFtsIndex(conn);
78
+ note(`retracted "0 files edited" on ${rewritten} session summar${rewritten === 1 ? 'y' : 'ies'} that recorded a Bash write.`);
79
+ }
80
+ },
81
+ });
82
+ return rewritten;
83
+ }
84
+ function groupLessons(rows) {
85
+ const groups = [];
86
+ for (const row of rows) {
87
+ if (row.content.startsWith('Error: ')) {
88
+ groups.push({ error: row.content.slice('Error: '.length), rows: [row] });
89
+ }
90
+ else if (groups.length > 0) {
91
+ groups[groups.length - 1].rows.push(row);
92
+ }
93
+ }
94
+ return groups;
95
+ }
96
+ export function splitFusedLessons(db, deps) {
97
+ let moved = -1;
98
+ runOnceMigration(db, {
99
+ key: FUSED_LESSON_SPLIT_KEY,
100
+ version: 1,
101
+ describe: 'fused lesson split',
102
+ migrate: (conn) => {
103
+ const buckets = conn
104
+ .prepare(`SELECT e.id, e.name, e.type, e.namespace, e.confidence, e.metadata
105
+ FROM entities e
106
+ WHERE e.type = 'lesson_learned' AND e.name LIKE 'lesson-%-other'
107
+ AND EXISTS (SELECT 1 FROM tags t WHERE t.entity_id = e.id AND t.tag = 'source:explicit')`)
108
+ .all();
109
+ const tagsOf = conn.prepare('SELECT tag FROM tags WHERE entity_id = ?');
110
+ const obsOf = conn.prepare('SELECT id, content, created_at FROM observations WHERE entity_id = ? ORDER BY id');
111
+ const findTarget = conn.prepare('SELECT id, status FROM entities WHERE name = ?');
112
+ const revive = conn.prepare("UPDATE entities SET status = 'active' WHERE id = ?");
113
+ const insertEntity = conn.prepare(`INSERT INTO entities (name, type, created_at, metadata, status, confidence, namespace, title)
114
+ VALUES (?, ?, ?, ?, 'active', ?, ?, ?)`);
115
+ const insertTag = conn.prepare('INSERT OR IGNORE INTO tags (entity_id, tag) VALUES (?, ?)');
116
+ const moveRow = conn.prepare('UPDATE observations SET entity_id = ? WHERE id = ?');
117
+ const emptied = 'NOT EXISTS (SELECT 1 FROM observations WHERE entity_id = ?)';
118
+ const dropExplicit = conn.prepare(`DELETE FROM tags WHERE entity_id = ? AND tag = 'source:explicit' AND ${emptied}`);
119
+ const archive = conn.prepare(`UPDATE entities SET status = 'archived' WHERE id = ? AND ${emptied}`);
120
+ moved = 0;
121
+ let bucketsTouched = 0;
122
+ for (const bucket of buckets) {
123
+ const groups = groupLessons(obsOf.all(bucket.id));
124
+ if (groups.length === 0)
125
+ continue;
126
+ const tags = tagsOf.all(bucket.id).map((t) => t.tag);
127
+ const project = tags.find((t) => t.startsWith('project:'))?.slice('project:'.length) ??
128
+ bucket.name.slice('lesson-'.length, -'-other'.length);
129
+ let inherited = {};
130
+ try {
131
+ const parsed = bucket.metadata ? JSON.parse(bucket.metadata) : {};
132
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
133
+ inherited = parsed;
134
+ }
135
+ catch { }
136
+ const severities = tags.filter((t) => t.startsWith('severity:'));
137
+ const carried = tags.filter((t) => !t.startsWith('severity:') && !t.startsWith('source:'));
138
+ if (severities.length === 1)
139
+ carried.push(severities[0]);
140
+ if (!tags.includes('source:auto-learned'))
141
+ carried.push('source:explicit');
142
+ let movedFromBucket = 0;
143
+ for (const group of groups) {
144
+ const slug = lessonSlug(group.error);
145
+ if (slug === 'other')
146
+ continue;
147
+ const name = `lesson-${project}-${slug}`;
148
+ if (name === bucket.name)
149
+ continue;
150
+ let target = findTarget.get(name);
151
+ if (target) {
152
+ if (target.status !== 'active')
153
+ revive.run(target.id);
154
+ }
155
+ else {
156
+ const contents = group.rows.map((o) => o.content);
157
+ const title = deps.deriveTitle(bucket.type, contents);
158
+ const metadata = {
159
+ ...inherited,
160
+ split_from: bucket.name,
161
+ signal_score: computeSignalScore({ type: bucket.type, name, observations: contents, tags: carried }),
162
+ };
163
+ if (title)
164
+ metadata.title_source = 'heuristic';
165
+ else
166
+ delete metadata.title_source;
167
+ delete metadata.guard;
168
+ delete metadata.evidence_for;
169
+ delete metadata.previous_namespace;
170
+ const inserted = insertEntity.run(name, bucket.type, group.rows[0].created_at, JSON.stringify(metadata), bucket.confidence, bucket.namespace, title);
171
+ target = { id: Number(inserted.lastInsertRowid), status: 'active' };
172
+ for (const tag of carried)
173
+ insertTag.run(target.id, tag);
174
+ }
175
+ for (const row of group.rows)
176
+ moveRow.run(target.id, row.id);
177
+ moved += 1;
178
+ movedFromBucket += 1;
179
+ }
180
+ dropExplicit.run(bucket.id, bucket.id);
181
+ archive.run(bucket.id, bucket.id);
182
+ if (movedFromBucket > 0)
183
+ bucketsTouched += 1;
184
+ }
185
+ if (moved > 0) {
186
+ rebuildFtsIndex(conn);
187
+ deps.markReindexOwed(conn);
188
+ note(`moved ${moved} lesson(s) out of ${bucketsTouched} "-other" bucket(s) into their own entities; run 'memesh reindex' to refresh their vectors.`);
189
+ }
190
+ },
191
+ });
192
+ return moved;
193
+ }
194
+ //# sourceMappingURL=graph-repairs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-repairs.js","sourceRoot":"","sources":["../../src/storage/graph-repairs.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,8 @@
1
1
  #!/usr/bin/env node
2
+ export declare function createHostConfigAtomically(host: string, configPath: string, config: Record<string, unknown>): void;
3
+ export declare function feedbackBrowserOpenCommand(platform: NodeJS.Platform, url: string): {
4
+ command: string;
5
+ args: [string];
6
+ };
2
7
  export declare function runCli(argv?: readonly string[]): Promise<void>;
3
8
  //# sourceMappingURL=cli.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/transports/cli/cli.ts"],"names":[],"mappings":";AA4nGA,wBAAsB,MAAM,CAAC,IAAI,GAAE,SAAS,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAElF"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/transports/cli/cli.ts"],"names":[],"mappings":";AAkMA,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,IAAI,CASN;AAGD,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,GAAG,EAAE,MAAM,GACV;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAA;CAAE,CAKrC;AAw7FD,wBAAsB,MAAM,CAAC,IAAI,GAAE,SAAS,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAElF"}
@@ -93,6 +93,23 @@ function isOnPath(tool) {
93
93
  }
94
94
  return false;
95
95
  }
96
+ export function createHostConfigAtomically(host, configPath, config) {
97
+ try {
98
+ fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, { flag: 'wx', mode: 0o600 });
99
+ }
100
+ catch (error) {
101
+ if (error.code === 'EEXIST') {
102
+ throw new Error(`Managed ${host} config already exists at ${configPath}; it was not overwritten.`, { cause: error });
103
+ }
104
+ throw error;
105
+ }
106
+ }
107
+ export function feedbackBrowserOpenCommand(platform, url) {
108
+ const command = platform === 'darwin' ? 'open'
109
+ : platform === 'win32' ? 'explorer.exe'
110
+ : 'xdg-open';
111
+ return { command, args: [url] };
112
+ }
96
113
  function wireUserHooks() {
97
114
  const r = installHooks({ pluginRoot: packageRoot, pluginVersion: pkg.version, scope: 'user' });
98
115
  return `hooks: added ${r.added}, skipped ${r.skipped} already-installed${r.backupPath ? ` (backup: ${r.backupPath})` : ''}`;
@@ -779,9 +796,6 @@ agentCmd
779
796
  }
780
797
  const filename = host === 'gemini' ? 'gemini-acp.json' : `${host}.json`;
781
798
  const configPath = path.join(hostsDir, filename);
782
- if (fs.existsSync(configPath)) {
783
- throw new Error(`Managed ${host} config already exists at ${configPath}; it was not overwritten.`);
784
- }
785
799
  const routerTokenFile = path.join(messageDir, 'agent-router.token');
786
800
  ensureRouterTokenFile(routerTokenFile);
787
801
  const common = {
@@ -797,7 +811,7 @@ agentCmd
797
811
  : host === 'claude'
798
812
  ? { ...common, server_name: 'memesh-channel' }
799
813
  : { ...common, workspace: path.resolve(opts.workspace), command: 'gemini', args: [] };
800
- fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, { flag: 'wx', mode: 0o600 });
814
+ createHostConfigAtomically(host, configPath, config);
801
815
  const launchCommand = host === 'codex-session'
802
816
  ? null
803
817
  : host === 'codex'
@@ -2248,12 +2262,9 @@ program
2248
2262
  console.log('Re-run with --no-diagnostics to leave out the install ID and the doctor report.');
2249
2263
  }
2250
2264
  const { spawn } = await import('child_process');
2251
- const cmd = process.platform === 'darwin' ? 'open'
2252
- : process.platform === 'win32' ? 'cmd'
2253
- : 'xdg-open';
2254
- const args = process.platform === 'win32' ? ['/c', 'start', '', url] : [url];
2265
+ const { command, args } = feedbackBrowserOpenCommand(process.platform, url);
2255
2266
  try {
2256
- const child = spawn(cmd, args, { stdio: 'ignore', detached: true });
2267
+ const child = spawn(command, args, { stdio: 'ignore', detached: true });
2257
2268
  child.unref();
2258
2269
  console.log(`Opened browser to file ${fbType} issue.`);
2259
2270
  console.log('Edit the title + body before submitting.');