@aiassesstech/mighty-mark 0.1.1 → 0.2.1

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 (70) hide show
  1. package/dist/checks/check-context.d.ts +2 -0
  2. package/dist/checks/check-context.d.ts.map +1 -1
  3. package/dist/checks/check-context.js.map +1 -1
  4. package/dist/checks/check-runner.d.ts +1 -1
  5. package/dist/checks/check-runner.d.ts.map +1 -1
  6. package/dist/checks/check-runner.js +7 -1
  7. package/dist/checks/check-runner.js.map +1 -1
  8. package/dist/checks/memory-health.d.ts +44 -0
  9. package/dist/checks/memory-health.d.ts.map +1 -0
  10. package/dist/checks/memory-health.js +389 -0
  11. package/dist/checks/memory-health.js.map +1 -0
  12. package/dist/cli/memory-commands.d.ts +22 -0
  13. package/dist/cli/memory-commands.d.ts.map +1 -0
  14. package/dist/cli/memory-commands.js +343 -0
  15. package/dist/cli/memory-commands.js.map +1 -0
  16. package/dist/cli/runner.d.ts.map +1 -1
  17. package/dist/cli/runner.js +27 -0
  18. package/dist/cli/runner.js.map +1 -1
  19. package/dist/config/fleet-topology.d.ts +3 -0
  20. package/dist/config/fleet-topology.d.ts.map +1 -1
  21. package/dist/config/fleet-topology.js +21 -11
  22. package/dist/config/fleet-topology.js.map +1 -1
  23. package/dist/index.d.ts +11 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +7 -0
  26. package/dist/index.js.map +1 -1
  27. package/dist/memory/backfill.d.ts +33 -0
  28. package/dist/memory/backfill.d.ts.map +1 -0
  29. package/dist/memory/backfill.js +206 -0
  30. package/dist/memory/backfill.js.map +1 -0
  31. package/dist/memory/config.d.ts +55 -0
  32. package/dist/memory/config.d.ts.map +1 -0
  33. package/dist/memory/config.js +45 -0
  34. package/dist/memory/config.js.map +1 -0
  35. package/dist/memory/organize.d.ts +27 -0
  36. package/dist/memory/organize.d.ts.map +1 -0
  37. package/dist/memory/organize.js +108 -0
  38. package/dist/memory/organize.js.map +1 -0
  39. package/dist/memory/remediate.d.ts +37 -0
  40. package/dist/memory/remediate.d.ts.map +1 -0
  41. package/dist/memory/remediate.js +143 -0
  42. package/dist/memory/remediate.js.map +1 -0
  43. package/dist/memory/retention.d.ts +42 -0
  44. package/dist/memory/retention.d.ts.map +1 -0
  45. package/dist/memory/retention.js +186 -0
  46. package/dist/memory/retention.js.map +1 -0
  47. package/dist/memory/tag.d.ts +26 -0
  48. package/dist/memory/tag.d.ts.map +1 -0
  49. package/dist/memory/tag.js +134 -0
  50. package/dist/memory/tag.js.map +1 -0
  51. package/dist/memory/writer.d.ts +46 -0
  52. package/dist/memory/writer.d.ts.map +1 -0
  53. package/dist/memory/writer.js +115 -0
  54. package/dist/memory/writer.js.map +1 -0
  55. package/dist/notify/report-formatter.d.ts.map +1 -1
  56. package/dist/notify/report-formatter.js +17 -1
  57. package/dist/notify/report-formatter.js.map +1 -1
  58. package/dist/plugin.d.ts +1 -1
  59. package/dist/plugin.d.ts.map +1 -1
  60. package/dist/plugin.js +196 -4
  61. package/dist/plugin.js.map +1 -1
  62. package/dist/store/json-store.d.ts +6 -0
  63. package/dist/store/json-store.d.ts.map +1 -1
  64. package/dist/store/json-store.js +27 -0
  65. package/dist/store/json-store.js.map +1 -1
  66. package/dist/types/fleet.d.ts +7 -0
  67. package/dist/types/fleet.d.ts.map +1 -1
  68. package/dist/types/health.d.ts +2 -2
  69. package/dist/types/health.d.ts.map +1 -1
  70. package/package.json +1 -1
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Memory auto-remediation — patches openclaw.json with local embedding
3
+ * configuration and triggers re-indexing when memory search is broken.
4
+ *
5
+ * Follows Do No Harm: always creates a timestamped backup before patching.
6
+ */
7
+ import fs from 'node:fs';
8
+ import { mkdir } from 'node:fs/promises';
9
+ import path from 'node:path';
10
+ import { getConfigPath, exec } from '../checks/check-context.js';
11
+ import { MEMORY_SEARCH_CONFIG, getDefaultMemoryDir } from './config.js';
12
+ /**
13
+ * Patch openclaw.json with local embedding configuration.
14
+ * Creates a timestamped backup before modifying.
15
+ */
16
+ export async function patchMemoryConfig(ctx) {
17
+ const configPath = getConfigPath(ctx);
18
+ if (!fs.existsSync(configPath)) {
19
+ return {
20
+ action: 'patch-config',
21
+ success: false,
22
+ message: `Config file not found: ${configPath}`,
23
+ };
24
+ }
25
+ try {
26
+ const raw = fs.readFileSync(configPath, 'utf-8');
27
+ const config = JSON.parse(raw);
28
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '').slice(0, 15);
29
+ const backupPath = `${configPath}.backup.${timestamp}`;
30
+ fs.writeFileSync(backupPath, raw, 'utf-8');
31
+ if (!config.agents)
32
+ config.agents = {};
33
+ if (!config.agents.defaults)
34
+ config.agents.defaults = {};
35
+ config.agents.defaults.memorySearch = MEMORY_SEARCH_CONFIG;
36
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
37
+ return {
38
+ action: 'patch-config',
39
+ success: true,
40
+ message: 'Patched openclaw.json with local embedding configuration',
41
+ backupPath,
42
+ };
43
+ }
44
+ catch (err) {
45
+ return {
46
+ action: 'patch-config',
47
+ success: false,
48
+ message: `Failed to patch config: ${err instanceof Error ? err.message : String(err)}`,
49
+ };
50
+ }
51
+ }
52
+ /**
53
+ * Trigger memory re-indexing via `openclaw memory status --deep --index`.
54
+ * Uses --deep --index instead of --force to avoid EBUSY on SQLite.
55
+ */
56
+ export function triggerReindex(ctx) {
57
+ try {
58
+ exec('openclaw memory status --deep --index', ctx);
59
+ return {
60
+ action: 'trigger-reindex',
61
+ success: true,
62
+ message: 'Triggered memory re-indexing via --deep --index',
63
+ };
64
+ }
65
+ catch (err) {
66
+ return {
67
+ action: 'trigger-reindex',
68
+ success: false,
69
+ message: `Re-indexing failed: ${err instanceof Error ? err.message : String(err)}`,
70
+ };
71
+ }
72
+ }
73
+ /** Restart the OpenClaw gateway. */
74
+ export function restartGateway(ctx) {
75
+ try {
76
+ exec('openclaw gateway restart', ctx);
77
+ return {
78
+ action: 'restart-gateway',
79
+ success: true,
80
+ message: 'Gateway restarted for embedding model reload',
81
+ };
82
+ }
83
+ catch (err) {
84
+ return {
85
+ action: 'restart-gateway',
86
+ success: false,
87
+ message: `Gateway restart failed: ${err instanceof Error ? err.message : String(err)}`,
88
+ };
89
+ }
90
+ }
91
+ /**
92
+ * Create missing agent memory directories based on fleet topology.
93
+ * Returns list of directories created.
94
+ */
95
+ export async function createAgentMemoryDirs(topology, ctx) {
96
+ const memoryDir = ctx?.memoryDir ?? getDefaultMemoryDir();
97
+ const created = [];
98
+ try {
99
+ for (const agent of topology.agents) {
100
+ const subdirs = agent.memoryConfig?.subdirs ?? [];
101
+ for (const sub of subdirs) {
102
+ const dir = path.join(memoryDir, agent.id, sub);
103
+ if (!fs.existsSync(dir)) {
104
+ await mkdir(dir, { recursive: true });
105
+ created.push(`${agent.id}/${sub}`);
106
+ }
107
+ }
108
+ }
109
+ if (created.length === 0) {
110
+ return {
111
+ action: 'create-dirs',
112
+ success: true,
113
+ message: 'All agent memory directories already exist',
114
+ };
115
+ }
116
+ return {
117
+ action: 'create-dirs',
118
+ success: true,
119
+ message: `Created ${created.length} directories: ${created.join(', ')}`,
120
+ };
121
+ }
122
+ catch (err) {
123
+ return {
124
+ action: 'create-dirs',
125
+ success: false,
126
+ message: `Failed to create directories: ${err instanceof Error ? err.message : String(err)}`,
127
+ };
128
+ }
129
+ }
130
+ /**
131
+ * Check if node-llama-cpp native bindings are available.
132
+ * If missing, local embedding provider will fail even after config patching.
133
+ */
134
+ export function checkNativeBindings(ctx) {
135
+ try {
136
+ const output = exec('pnpm list node-llama-cpp 2>/dev/null || echo "not-found"', ctx);
137
+ return !output.includes('not-found') && !output.includes('ERR');
138
+ }
139
+ catch {
140
+ return false;
141
+ }
142
+ }
143
+ //# sourceMappingURL=remediate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remediate.js","sourceRoot":"","sources":["../../src/memory/remediate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Retention policy enforcement for memory files on disk-constrained VPS.
3
+ *
4
+ * - File count ceiling per agent subdirectory (default 500)
5
+ * - Oldest files archived to .archive/ as monthly .tar.gz bundles (never deleted)
6
+ * - Session directory size monitoring
7
+ * - Total memory directory size monitoring
8
+ */
9
+ export interface RetentionConfig {
10
+ maxFilesPerSubdir: number;
11
+ sessionSizeWarnMB: number;
12
+ totalMemoryWarnMB: number;
13
+ archiveDir: string;
14
+ }
15
+ export interface RetentionResult {
16
+ archived: Array<{
17
+ subdir: string;
18
+ fileCount: number;
19
+ archivePath: string;
20
+ }>;
21
+ warnings: string[];
22
+ errors: string[];
23
+ }
24
+ export interface DiskReport {
25
+ totalMemoryBytes: number;
26
+ sessionBytes: number;
27
+ agentBytes: Record<string, number>;
28
+ warnings: string[];
29
+ }
30
+ /**
31
+ * Enforce file count ceilings across all agent subdirectories.
32
+ * Files over the limit are compressed into monthly .tar.gz archives.
33
+ */
34
+ export declare function enforceRetention(memoryDir?: string, config?: Partial<RetentionConfig>): Promise<RetentionResult>;
35
+ /**
36
+ * Check disk usage and produce warnings for session/total thresholds.
37
+ */
38
+ export declare function checkDiskUsage(memoryDir?: string, config?: Partial<RetentionConfig>): DiskReport;
39
+ /** List markdown files sorted oldest-first by filename date prefix, then mtime. */
40
+ declare function listMarkdownFilesByAge(dir: string): string[];
41
+ export { listMarkdownFilesByAge as _listMarkdownFilesByAge_for_testing };
42
+ //# sourceMappingURL=retention.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../src/memory/retention.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH,MAAM,WAAW,eAAe;IAC9B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5E,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AASD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAChC,OAAO,CAAC,eAAe,CAAC,CAuC1B;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,CAwChG;AAqDD,mFAAmF;AACnF,iBAAS,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAiBrD;AAuCD,OAAO,EAAE,sBAAsB,IAAI,mCAAmC,EAAE,CAAC"}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Retention policy enforcement for memory files on disk-constrained VPS.
3
+ *
4
+ * - File count ceiling per agent subdirectory (default 500)
5
+ * - Oldest files archived to .archive/ as monthly .tar.gz bundles (never deleted)
6
+ * - Session directory size monitoring
7
+ * - Total memory directory size monitoring
8
+ */
9
+ import fs from 'node:fs';
10
+ import path from 'node:path';
11
+ import { execSync } from 'node:child_process';
12
+ import { getDefaultMemoryDir, MAX_FILES_PER_SUBDIR, SESSION_SIZE_WARN_BYTES, TOTAL_MEMORY_WARN_BYTES, } from './config.js';
13
+ const DEFAULT_CONFIG = {
14
+ maxFilesPerSubdir: MAX_FILES_PER_SUBDIR,
15
+ sessionSizeWarnMB: SESSION_SIZE_WARN_BYTES / (1024 * 1024),
16
+ totalMemoryWarnMB: TOTAL_MEMORY_WARN_BYTES / (1024 * 1024),
17
+ archiveDir: '.archive',
18
+ };
19
+ /**
20
+ * Enforce file count ceilings across all agent subdirectories.
21
+ * Files over the limit are compressed into monthly .tar.gz archives.
22
+ */
23
+ export async function enforceRetention(memoryDir, config) {
24
+ const dir = memoryDir ?? getDefaultMemoryDir();
25
+ const cfg = { ...DEFAULT_CONFIG, ...config };
26
+ const result = { archived: [], warnings: [], errors: [] };
27
+ if (!fs.existsSync(dir)) {
28
+ result.errors.push(`Memory directory not found: ${dir}`);
29
+ return result;
30
+ }
31
+ const agentDirs = listSubdirs(dir);
32
+ for (const agentDir of agentDirs) {
33
+ const agentPath = path.join(dir, agentDir);
34
+ const subdirs = listSubdirs(agentPath);
35
+ for (const sub of subdirs) {
36
+ if (sub === cfg.archiveDir)
37
+ continue;
38
+ const subPath = path.join(agentPath, sub);
39
+ const files = listMarkdownFilesByAge(subPath);
40
+ if (files.length <= cfg.maxFilesPerSubdir)
41
+ continue;
42
+ const excess = files.length - cfg.maxFilesPerSubdir;
43
+ const toArchive = files.slice(0, excess);
44
+ try {
45
+ const archiveEntry = await archiveFiles(agentPath, sub, toArchive, cfg.archiveDir);
46
+ result.archived.push(archiveEntry);
47
+ }
48
+ catch (err) {
49
+ result.errors.push(`${agentDir}/${sub}: ${err instanceof Error ? err.message : String(err)}`);
50
+ }
51
+ }
52
+ }
53
+ return result;
54
+ }
55
+ /**
56
+ * Check disk usage and produce warnings for session/total thresholds.
57
+ */
58
+ export function checkDiskUsage(memoryDir, config) {
59
+ const dir = memoryDir ?? getDefaultMemoryDir();
60
+ const cfg = { ...DEFAULT_CONFIG, ...config };
61
+ const report = {
62
+ totalMemoryBytes: 0,
63
+ sessionBytes: 0,
64
+ agentBytes: {},
65
+ warnings: [],
66
+ };
67
+ if (!fs.existsSync(dir))
68
+ return report;
69
+ report.totalMemoryBytes = getDirSize(dir);
70
+ const sessionsDir = path.join(dir, '..', 'sessions');
71
+ if (fs.existsSync(sessionsDir)) {
72
+ report.sessionBytes = getDirSize(sessionsDir);
73
+ }
74
+ const agentDirs = listSubdirs(dir);
75
+ for (const agent of agentDirs) {
76
+ report.agentBytes[agent] = getDirSize(path.join(dir, agent));
77
+ }
78
+ const totalMB = report.totalMemoryBytes / (1024 * 1024);
79
+ if (totalMB > cfg.totalMemoryWarnMB) {
80
+ report.warnings.push(`Total memory directory is ${totalMB.toFixed(0)}MB (threshold: ${cfg.totalMemoryWarnMB}MB)`);
81
+ }
82
+ const sessionMB = report.sessionBytes / (1024 * 1024);
83
+ if (sessionMB > cfg.sessionSizeWarnMB) {
84
+ report.warnings.push(`Session directory is ${sessionMB.toFixed(0)}MB (threshold: ${cfg.sessionSizeWarnMB}MB)`);
85
+ }
86
+ return report;
87
+ }
88
+ /**
89
+ * Archive a batch of files into a monthly .tar.gz bundle.
90
+ * Files are grouped by YYYY-MM from their filename date prefix.
91
+ */
92
+ async function archiveFiles(agentPath, subdir, files, archiveDirName) {
93
+ const archiveDir = path.join(agentPath, archiveDirName);
94
+ if (!fs.existsSync(archiveDir)) {
95
+ fs.mkdirSync(archiveDir, { recursive: true });
96
+ }
97
+ const month = extractMonth(files[0] ?? '') ?? formatMonth(new Date());
98
+ const archiveName = `${subdir}-${month}-archive.tar.gz`;
99
+ const archivePath = path.join(archiveDir, archiveName);
100
+ let finalPath = archivePath;
101
+ if (fs.existsSync(archivePath)) {
102
+ finalPath = path.join(archiveDir, `${subdir}-${month}-archive-${Date.now()}.tar.gz`);
103
+ }
104
+ const subPath = path.join(agentPath, subdir);
105
+ const relativeFiles = files.map(f => path.relative(subPath, f));
106
+ try {
107
+ execSync(`tar -czf "${finalPath}" -C "${subPath}" ${relativeFiles.map(f => `"${f}"`).join(' ')}`, { timeout: 30_000 });
108
+ }
109
+ catch {
110
+ const bundleDir = path.join(archiveDir, `${subdir}-${month}`);
111
+ if (!fs.existsSync(bundleDir))
112
+ fs.mkdirSync(bundleDir, { recursive: true });
113
+ for (const file of files) {
114
+ const dest = path.join(bundleDir, path.basename(file));
115
+ fs.renameSync(file, dest);
116
+ }
117
+ finalPath = bundleDir;
118
+ }
119
+ if (finalPath !== archivePath || fs.existsSync(finalPath)) {
120
+ for (const file of files) {
121
+ if (fs.existsSync(file))
122
+ fs.unlinkSync(file);
123
+ }
124
+ }
125
+ return { subdir: `${path.basename(agentPath)}/${subdir}`, fileCount: files.length, archivePath: finalPath };
126
+ }
127
+ /** List markdown files sorted oldest-first by filename date prefix, then mtime. */
128
+ function listMarkdownFilesByAge(dir) {
129
+ if (!fs.existsSync(dir))
130
+ return [];
131
+ try {
132
+ const entries = fs.readdirSync(dir)
133
+ .filter(f => f.endsWith('.md'))
134
+ .map(f => ({
135
+ name: f,
136
+ full: path.join(dir, f),
137
+ mtime: fs.statSync(path.join(dir, f)).mtimeMs,
138
+ }))
139
+ .sort((a, b) => a.mtime - b.mtime);
140
+ return entries.map(e => e.full);
141
+ }
142
+ catch {
143
+ return [];
144
+ }
145
+ }
146
+ function listSubdirs(dir) {
147
+ try {
148
+ return fs.readdirSync(dir, { withFileTypes: true })
149
+ .filter(e => e.isDirectory() && !e.name.startsWith('.'))
150
+ .map(e => e.name)
151
+ .sort();
152
+ }
153
+ catch {
154
+ return [];
155
+ }
156
+ }
157
+ function getDirSize(dir) {
158
+ let total = 0;
159
+ try {
160
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
161
+ for (const entry of entries) {
162
+ const full = path.join(dir, entry.name);
163
+ if (entry.isDirectory()) {
164
+ total += getDirSize(full);
165
+ }
166
+ else {
167
+ try {
168
+ total += fs.statSync(full).size;
169
+ }
170
+ catch { /* skip */ }
171
+ }
172
+ }
173
+ }
174
+ catch { /* skip */ }
175
+ return total;
176
+ }
177
+ function extractMonth(filePath) {
178
+ const basename = path.basename(filePath);
179
+ const match = basename.match(/^(\d{4}-\d{2})/);
180
+ return match?.[1] ?? null;
181
+ }
182
+ function formatMonth(date) {
183
+ return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
184
+ }
185
+ export { listMarkdownFilesByAge as _listMarkdownFilesByAge_for_testing };
186
+ //# sourceMappingURL=retention.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.js","sourceRoot":"","sources":["../../src/memory/retention.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Memory tagger — scans memory files for missing or incomplete YAML
3
+ * frontmatter and adds/fixes it based on file path and content heuristics.
4
+ */
5
+ export interface TagOptions {
6
+ memoryDir?: string;
7
+ dryRun?: boolean;
8
+ /** Only process a specific agent's directory. */
9
+ agent?: string;
10
+ }
11
+ export interface TagResult {
12
+ tagged: string[];
13
+ alreadyTagged: string[];
14
+ errors: string[];
15
+ }
16
+ /**
17
+ * Add YAML frontmatter to markdown files that are missing it.
18
+ */
19
+ export declare function tagMemoryFiles(opts?: TagOptions): Promise<TagResult>;
20
+ /**
21
+ * Infer YAML frontmatter from file path and first heading.
22
+ * Path structure: agent/subdir/filename.md
23
+ */
24
+ declare function inferFrontmatter(relativePath: string, content: string): string;
25
+ export { inferFrontmatter as _inferFrontmatter_for_testing };
26
+ //# sourceMappingURL=tag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../src/memory/tag.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,IAAI,GAAE,UAAe,GAAG,OAAO,CAAC,SAAS,CAAC,CAgD9E;AAMD;;;GAGG;AACH,iBAAS,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAyBvE;AA6DD,OAAO,EAAE,gBAAgB,IAAI,6BAA6B,EAAE,CAAC"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Memory tagger — scans memory files for missing or incomplete YAML
3
+ * frontmatter and adds/fixes it based on file path and content heuristics.
4
+ */
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import { getDefaultMemoryDir } from './config.js';
8
+ /**
9
+ * Add YAML frontmatter to markdown files that are missing it.
10
+ */
11
+ export async function tagMemoryFiles(opts = {}) {
12
+ const memoryDir = opts.memoryDir ?? getDefaultMemoryDir();
13
+ const dryRun = opts.dryRun ?? false;
14
+ const result = { tagged: [], alreadyTagged: [], errors: [] };
15
+ if (!fs.existsSync(memoryDir)) {
16
+ result.errors.push(`Memory directory not found: ${memoryDir}`);
17
+ return result;
18
+ }
19
+ const searchDir = opts.agent
20
+ ? path.join(memoryDir, opts.agent)
21
+ : memoryDir;
22
+ if (!fs.existsSync(searchDir)) {
23
+ result.errors.push(`Agent directory not found: ${searchDir}`);
24
+ return result;
25
+ }
26
+ const mdFiles = findAllMarkdownFiles(searchDir);
27
+ for (const file of mdFiles) {
28
+ try {
29
+ const content = fs.readFileSync(file, 'utf-8');
30
+ if (hasFrontmatter(content)) {
31
+ result.alreadyTagged.push(file);
32
+ continue;
33
+ }
34
+ const relativePath = path.relative(memoryDir, file);
35
+ const frontmatter = inferFrontmatter(relativePath, content);
36
+ const tagged = `${frontmatter}\n${content}`;
37
+ if (dryRun) {
38
+ result.tagged.push(file);
39
+ continue;
40
+ }
41
+ fs.writeFileSync(file, tagged, 'utf-8');
42
+ result.tagged.push(file);
43
+ }
44
+ catch (err) {
45
+ result.errors.push(`${file}: ${err instanceof Error ? err.message : String(err)}`);
46
+ }
47
+ }
48
+ return result;
49
+ }
50
+ function hasFrontmatter(content) {
51
+ return content.startsWith('---\n') || content.startsWith('---\r\n');
52
+ }
53
+ /**
54
+ * Infer YAML frontmatter from file path and first heading.
55
+ * Path structure: agent/subdir/filename.md
56
+ */
57
+ function inferFrontmatter(relativePath, content) {
58
+ const parts = relativePath.replace(/\\/g, '/').split('/');
59
+ const agent = parts[0] ?? 'unknown';
60
+ const subdir = parts.length >= 3 ? parts[1] : 'general';
61
+ const filename = path.basename(relativePath, '.md');
62
+ const dateMatch = filename.match(/^(\d{4}-\d{2}-\d{2})/);
63
+ const date = dateMatch?.[1] ?? new Date().toISOString().slice(0, 10);
64
+ const heading = extractFirstHeading(content) ?? filename;
65
+ const type = subdirToType(subdir);
66
+ const tags = inferTags(agent, type, content);
67
+ const lines = [
68
+ '---',
69
+ `tags: [${tags.join(', ')}]`,
70
+ `agent: ${agent}`,
71
+ `type: ${type}`,
72
+ `date: ${date}`,
73
+ 'auto-tagged: true',
74
+ '---',
75
+ ];
76
+ return lines.join('\n');
77
+ }
78
+ function extractFirstHeading(content) {
79
+ const match = content.match(/^#+\s+(.+)$/m);
80
+ return match?.[1]?.trim() ?? null;
81
+ }
82
+ const TYPE_MAP = {
83
+ governance: 'governance-decision',
84
+ scores: 'score-published',
85
+ intelligence: 'intelligence',
86
+ assessments: 'assessment',
87
+ drift: 'drift',
88
+ fleet: 'fleet-anomaly',
89
+ 'flight-plans': 'flight-plan',
90
+ deviations: 'deviation',
91
+ transitions: 'phase-transition',
92
+ incidents: 'incident',
93
+ health: 'morning-check',
94
+ trends: 'trend',
95
+ decisions: 'decision',
96
+ vetoes: 'veto',
97
+ strategic: 'strategic',
98
+ engineering: 'engineering',
99
+ deployments: 'deployment',
100
+ reviews: 'review',
101
+ };
102
+ function subdirToType(subdir) {
103
+ return TYPE_MAP[subdir] ?? subdir;
104
+ }
105
+ function inferTags(agent, type, content) {
106
+ const tags = [type, agent];
107
+ const lower = content.toLowerCase();
108
+ if (lower.includes('critical') || lower.includes('severity: critical'))
109
+ tags.push('critical');
110
+ if (lower.includes('backfill'))
111
+ tags.push('backfill');
112
+ if (lower.includes('remediat'))
113
+ tags.push('remediation');
114
+ return [...new Set(tags)];
115
+ }
116
+ function findAllMarkdownFiles(dir) {
117
+ const results = [];
118
+ try {
119
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
120
+ for (const entry of entries) {
121
+ const full = path.join(dir, entry.name);
122
+ if (entry.isDirectory() && !entry.name.startsWith('.')) {
123
+ results.push(...findAllMarkdownFiles(full));
124
+ }
125
+ else if (entry.name.endsWith('.md')) {
126
+ results.push(full);
127
+ }
128
+ }
129
+ }
130
+ catch { /* ignore */ }
131
+ return results.sort();
132
+ }
133
+ export { inferFrontmatter as _inferFrontmatter_for_testing };
134
+ //# sourceMappingURL=tag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tag.js","sourceRoot":"","sources":["../../src/memory/tag.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * MemoryWriter — writes structured markdown files with YAML frontmatter
3
+ * into the shared memory directory for OpenClaw's memory_search to index.
4
+ *
5
+ * This class has zero dependencies beyond Node.js built-ins so that
6
+ * consumer agents (Grillo, Noah, Nole) can import it without pulling
7
+ * in Mark's health check infrastructure.
8
+ */
9
+ export interface MemoryWriteOptions {
10
+ /** Which agent is writing (grillo, noah, nole, mighty-mark, jessie, sam). */
11
+ agent: string;
12
+ /** Event type (assessment, governance-decision, incident, flight-plan, etc.). */
13
+ type: string;
14
+ /** Searchable tags — indexed by BM25 keyword search. */
15
+ tags: string[];
16
+ /** Human-readable title — becomes the markdown H1. */
17
+ title: string;
18
+ /** Markdown body — embedded by vector model for semantic search. */
19
+ body: string;
20
+ /** Optional ISO date override (defaults to today). */
21
+ date?: string;
22
+ /** Optional extra frontmatter fields (risk, outcome, score, etc.). */
23
+ metadata?: Record<string, string | number | boolean>;
24
+ }
25
+ export interface MemoryWriterConfig {
26
+ /** Root memory directory. Default: ~/.openclaw/workspace/memory */
27
+ memoryDir?: string;
28
+ /** Whether to auto-create subdirectories. Default: true */
29
+ autoCreateDirs?: boolean;
30
+ }
31
+ export declare class MemoryWriter {
32
+ private readonly memoryDir;
33
+ private readonly autoCreate;
34
+ constructor(config?: MemoryWriterConfig);
35
+ /** Returns the root memory directory this writer targets. */
36
+ getMemoryDir(): string;
37
+ /**
38
+ * Write a memory file with YAML frontmatter + markdown body.
39
+ * Returns the absolute path of the written file.
40
+ */
41
+ write(opts: MemoryWriteOptions): Promise<string>;
42
+ }
43
+ /** Convert a title to a filename-safe slug. */
44
+ declare function slugify(text: string): string;
45
+ export { slugify as _slugify_for_testing };
46
+ //# sourceMappingURL=writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../src/memory/writer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,MAAM,WAAW,kBAAkB;IACjC,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AA0CD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;gBAEzB,MAAM,CAAC,EAAE,kBAAkB;IAKvC,6DAA6D;IAC7D,YAAY,IAAI,MAAM;IAItB;;;OAGG;IACG,KAAK,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC;CAkBvD;AA6BD,+CAA+C;AAC/C,iBAAS,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrC;AAED,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,CAAC"}