wicked-brain 0.4.8 → 0.4.9
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/package.json
CHANGED
|
@@ -96,6 +96,7 @@ const actions = {
|
|
|
96
96
|
backlinks: (p) => ({ links: db.backlinks(p.id) }),
|
|
97
97
|
forward_links: (p) => ({ links: db.forwardLinks(p.id) }),
|
|
98
98
|
stats: () => db.stats(),
|
|
99
|
+
memory_stats: () => db.memoryStats(),
|
|
99
100
|
candidates: (p) => ({ candidates: db.candidates(p) }),
|
|
100
101
|
symbols: async (p) => {
|
|
101
102
|
// Prefer LSP workspace symbols (structured, language-aware)
|
|
@@ -421,7 +421,51 @@ export class SqliteSearch {
|
|
|
421
421
|
// in-memory or inaccessible
|
|
422
422
|
}
|
|
423
423
|
|
|
424
|
-
return {
|
|
424
|
+
return {
|
|
425
|
+
total,
|
|
426
|
+
chunks,
|
|
427
|
+
wiki,
|
|
428
|
+
memory,
|
|
429
|
+
memory_breakdown: this.memoryStats(),
|
|
430
|
+
last_indexed,
|
|
431
|
+
db_size,
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Breakdown of memory documents by type, tier, and age.
|
|
437
|
+
* Parses frontmatter from `memory/%` rows. Missing fields count as "unknown".
|
|
438
|
+
* Age buckets: <1d, 1-7d, 7-30d, 30-90d, >90d.
|
|
439
|
+
*/
|
|
440
|
+
memoryStats() {
|
|
441
|
+
const rows = this.#db.prepare(`
|
|
442
|
+
SELECT frontmatter, indexed_at FROM documents WHERE path LIKE 'memory/%'
|
|
443
|
+
`).all();
|
|
444
|
+
|
|
445
|
+
const by_type = {};
|
|
446
|
+
const by_tier = {};
|
|
447
|
+
const by_age = { "<1d": 0, "1-7d": 0, "7-30d": 0, "30-90d": 0, ">90d": 0 };
|
|
448
|
+
const now = Date.now();
|
|
449
|
+
const DAY = 86400000;
|
|
450
|
+
|
|
451
|
+
for (const row of rows) {
|
|
452
|
+
const fm = row.frontmatter || "";
|
|
453
|
+
const typeMatch = fm.match(/^type:\s*(\S+)/m);
|
|
454
|
+
const tierMatch = fm.match(/^tier:\s*(\S+)/m);
|
|
455
|
+
const type = typeMatch ? typeMatch[1].replace(/["']/g, "") : "unknown";
|
|
456
|
+
const tier = tierMatch ? tierMatch[1].replace(/["']/g, "") : "unknown";
|
|
457
|
+
by_type[type] = (by_type[type] ?? 0) + 1;
|
|
458
|
+
by_tier[tier] = (by_tier[tier] ?? 0) + 1;
|
|
459
|
+
|
|
460
|
+
const age = now - (row.indexed_at ?? now);
|
|
461
|
+
if (age < DAY) by_age["<1d"]++;
|
|
462
|
+
else if (age < 7 * DAY) by_age["1-7d"]++;
|
|
463
|
+
else if (age < 30 * DAY) by_age["7-30d"]++;
|
|
464
|
+
else if (age < 90 * DAY) by_age["30-90d"]++;
|
|
465
|
+
else by_age[">90d"]++;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return { total: rows.length, by_type, by_tier, by_age };
|
|
425
469
|
}
|
|
426
470
|
|
|
427
471
|
health() {
|
package/server/package.json
CHANGED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wicked-brain:forget
|
|
3
|
+
description: |
|
|
4
|
+
Archive or delete a memory (or any indexed document) by id or path.
|
|
5
|
+
Removes the document from the FTS index and renames the file with an
|
|
6
|
+
`.archived-{timestamp}` suffix so the data is recoverable.
|
|
7
|
+
|
|
8
|
+
Use when: "forget this memory", "archive this", "drop this decision",
|
|
9
|
+
"remove from brain", "brain forget".
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# wicked-brain:forget
|
|
13
|
+
|
|
14
|
+
Archive or hard-delete a memory by id or path. Wraps the server `remove` action
|
|
15
|
+
and the archive-rename convention used by wicked-brain:agent dispatch consolidate.
|
|
16
|
+
|
|
17
|
+
## Cross-Platform Notes
|
|
18
|
+
|
|
19
|
+
- Uses `curl` for server API calls (Windows 10+, macOS, Linux)
|
|
20
|
+
- Uses agent-native Read/Bash tools for file ops — no Unix-only shell features
|
|
21
|
+
- Paths always use forward slashes
|
|
22
|
+
|
|
23
|
+
## Config
|
|
24
|
+
|
|
25
|
+
Read `_meta/config.json` for brain path and server port.
|
|
26
|
+
If it doesn't exist, trigger wicked-brain:init.
|
|
27
|
+
|
|
28
|
+
## Parameters
|
|
29
|
+
|
|
30
|
+
- **id** (required if `path` not given): document id as returned by search
|
|
31
|
+
- **path** (required if `id` not given): path relative to the brain root (e.g. `memory/jwt-decision.md`)
|
|
32
|
+
- **mode** (optional, default `archive`): `archive` (rename file + remove from index, recoverable) or `delete` (rename + remove + final deletion is still left to the user — this skill never unlinks files)
|
|
33
|
+
- **reason** (optional): short string recorded in the log for auditability
|
|
34
|
+
|
|
35
|
+
This skill never hard-deletes a file. `delete` mode still renames with
|
|
36
|
+
`.archived-{timestamp}` — actual `rm` is a human decision.
|
|
37
|
+
|
|
38
|
+
## Process
|
|
39
|
+
|
|
40
|
+
### Step 1: Resolve id and path
|
|
41
|
+
|
|
42
|
+
If only `id` is given, find the path by calling search or reading the id (ids
|
|
43
|
+
are of the form `{path}` or `{path}::{fragment}` in this brain). If only `path`
|
|
44
|
+
is given, the id is normally the same string for top-level documents.
|
|
45
|
+
|
|
46
|
+
### Step 2: Confirm the document exists
|
|
47
|
+
|
|
48
|
+
Read the file at `{brain_path}/{path}` to verify it is present and (if it is a
|
|
49
|
+
memory) inspect its frontmatter so the log entry can record type/tier.
|
|
50
|
+
|
|
51
|
+
### Step 3: Remove from index
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
curl -s -X POST http://localhost:{port}/api \
|
|
55
|
+
-H "Content-Type: application/json" \
|
|
56
|
+
-d '{"action":"remove","params":{"id":"{id}"}}'
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Step 4: Archive the file
|
|
60
|
+
|
|
61
|
+
Rename the file in-place with an `.archived-{unix-ms}` suffix.
|
|
62
|
+
|
|
63
|
+
macOS / Linux:
|
|
64
|
+
```bash
|
|
65
|
+
mv "{brain_path}/{path}" "{brain_path}/{path}.archived-$(date +%s)"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Windows (PowerShell):
|
|
69
|
+
```powershell
|
|
70
|
+
Rename-Item "{brain_path}/{path}" "{path}.archived-$([DateTimeOffset]::UtcNow.ToUnixTimeSeconds())"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Prefer the agent-native Bash tool on the current platform; both forms produce a
|
|
74
|
+
recoverable archive marker.
|
|
75
|
+
|
|
76
|
+
### Step 5: Log the forget event
|
|
77
|
+
|
|
78
|
+
Append to `{brain_path}/_meta/log.jsonl`:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{"ts":"{ISO}","op":"memory_forget","path":"{path}","id":"{id}","mode":"{mode}","reason":"{reason}","author":"agent:forget"}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Step 6: Report
|
|
85
|
+
|
|
86
|
+
Report: path, id, previous frontmatter type/tier (if memory), archive filename,
|
|
87
|
+
and whether index removal succeeded. Always surface the archive path so the
|
|
88
|
+
user can restore it by renaming back.
|
|
89
|
+
|
|
90
|
+
## Recovery
|
|
91
|
+
|
|
92
|
+
To restore an archived memory, rename the `.archived-{ts}` file back to its
|
|
93
|
+
original name. The file watcher will pick it up and re-index automatically.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wicked-brain:review
|
|
3
|
+
description: |
|
|
4
|
+
Browse stored memories with filters on type, tier, and recency. Read-only —
|
|
5
|
+
use wicked-brain:forget to archive or wicked-brain:agent dispatch consolidate
|
|
6
|
+
to promote.
|
|
7
|
+
|
|
8
|
+
Use when: "review my memories", "browse decisions", "what have I stored",
|
|
9
|
+
"list recent gotchas", "brain review".
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# wicked-brain:review
|
|
13
|
+
|
|
14
|
+
Filtered browse over the memory store. Combines the server `memory_stats` and
|
|
15
|
+
`recent_memories` actions with agent-side frontmatter filtering to render a
|
|
16
|
+
compact, navigable list.
|
|
17
|
+
|
|
18
|
+
## Cross-Platform Notes
|
|
19
|
+
|
|
20
|
+
- Uses `curl` for server API calls (Windows 10+, macOS, Linux)
|
|
21
|
+
- File reads use the agent-native Read tool
|
|
22
|
+
- Paths always use forward slashes
|
|
23
|
+
|
|
24
|
+
## Config
|
|
25
|
+
|
|
26
|
+
Read `_meta/config.json` for brain path and server port.
|
|
27
|
+
If it doesn't exist, trigger wicked-brain:init.
|
|
28
|
+
|
|
29
|
+
## Parameters
|
|
30
|
+
|
|
31
|
+
- **filter_type** (optional): `decision`, `pattern`, `preference`, `gotcha`, or `discovery`
|
|
32
|
+
- **filter_tier** (optional): `working`, `episodic`, or `semantic`
|
|
33
|
+
- **days** (optional, default 30): only include memories indexed within this many days
|
|
34
|
+
- **limit** (optional, default 20): max results
|
|
35
|
+
- **depth** (optional, default 0): 0=frontmatter only, 1=+summary line, 2=full content
|
|
36
|
+
|
|
37
|
+
## Process
|
|
38
|
+
|
|
39
|
+
### Step 1: Fetch breakdown
|
|
40
|
+
|
|
41
|
+
Start with the aggregate view so the user can see the landscape before the list:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
curl -s -X POST http://localhost:{port}/api \
|
|
45
|
+
-H "Content-Type: application/json" \
|
|
46
|
+
-d '{"action":"memory_stats"}'
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Render `total`, `by_type`, `by_tier`, `by_age` as a one-line header.
|
|
50
|
+
|
|
51
|
+
### Step 2: Fetch candidates
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
curl -s -X POST http://localhost:{port}/api \
|
|
55
|
+
-H "Content-Type: application/json" \
|
|
56
|
+
-d '{"action":"recent_memories","params":{"days":{days},"limit":{limit * 3}}}'
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Over-fetch by 3x so agent-side type/tier filtering still returns a useful page.
|
|
60
|
+
|
|
61
|
+
### Step 3: Filter
|
|
62
|
+
|
|
63
|
+
For each returned memory, parse its frontmatter. Drop any memory whose `type`
|
|
64
|
+
or `tier` does not match `filter_type` / `filter_tier` when those parameters
|
|
65
|
+
are set. Stop once `limit` matches are collected.
|
|
66
|
+
|
|
67
|
+
### Step 4: Render
|
|
68
|
+
|
|
69
|
+
For each matching memory, render at the requested depth:
|
|
70
|
+
|
|
71
|
+
- **Depth 0**: `{path} — type={type} tier={tier} importance={importance} age={age}`
|
|
72
|
+
- **Depth 1**: depth 0 line + first 3 lines of content
|
|
73
|
+
- **Depth 2**: depth 0 line + full content
|
|
74
|
+
|
|
75
|
+
Age is derived from `indexed_at` relative to now (`Xd` / `Xh`).
|
|
76
|
+
|
|
77
|
+
### Step 5: Suggest next actions
|
|
78
|
+
|
|
79
|
+
After the list, suggest one of:
|
|
80
|
+
- `wicked-brain:forget path=…` to archive a specific entry
|
|
81
|
+
- `wicked-brain:agent dispatch consolidate` to promote patterns and drop expired entries
|
|
82
|
+
- `wicked-brain:retag` if many entries have thin `contains:` arrays
|
|
83
|
+
|
|
84
|
+
## Notes
|
|
85
|
+
|
|
86
|
+
- Review is read-only. It never mutates the index or files.
|
|
87
|
+
- For semantic search (content keywords) use `wicked-brain:search` or the
|
|
88
|
+
`recall` mode of `wicked-brain:memory` — review is for browsing by metadata.
|
|
89
|
+
- If no filters are given and `days=30`, this is effectively "show me what I
|
|
90
|
+
have been remembering lately, grouped by type and tier".
|