@prmichaelsen/remember-mcp 3.15.4 → 3.15.6
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/AGENT.md +363 -5
- package/CHANGELOG.md +7 -0
- package/agent/commands/acp.clarification-capture.md +386 -0
- package/agent/commands/acp.clarification-create.md +50 -0
- package/agent/commands/acp.command-create.md +60 -0
- package/agent/commands/acp.design-create.md +62 -0
- package/agent/commands/acp.design-reference.md +355 -0
- package/agent/commands/acp.index.md +423 -0
- package/agent/commands/acp.init.md +48 -0
- package/agent/commands/acp.package-create.md +1 -0
- package/agent/commands/acp.package-info.md +1 -0
- package/agent/commands/acp.package-install.md +19 -0
- package/agent/commands/acp.package-list.md +1 -0
- package/agent/commands/acp.package-publish.md +1 -0
- package/agent/commands/acp.package-remove.md +1 -0
- package/agent/commands/acp.package-search.md +1 -0
- package/agent/commands/acp.package-update.md +1 -0
- package/agent/commands/acp.package-validate.md +1 -0
- package/agent/commands/acp.pattern-create.md +60 -0
- package/agent/commands/acp.plan.md +25 -0
- package/agent/commands/acp.proceed.md +621 -75
- package/agent/commands/acp.project-create.md +3 -0
- package/agent/commands/acp.project-info.md +3 -0
- package/agent/commands/acp.project-list.md +3 -1
- package/agent/commands/acp.project-set.md +1 -0
- package/agent/commands/acp.project-update.md +14 -3
- package/agent/commands/acp.projects-restore.md +228 -0
- package/agent/commands/acp.projects-sync.md +347 -0
- package/agent/commands/acp.report.md +13 -0
- package/agent/commands/acp.resume.md +3 -1
- package/agent/commands/acp.sessions.md +301 -0
- package/agent/commands/acp.status.md +13 -0
- package/agent/commands/acp.sync.md +1 -0
- package/agent/commands/acp.task-create.md +105 -3
- package/agent/commands/acp.update.md +1 -0
- package/agent/commands/acp.validate.md +32 -2
- package/agent/commands/acp.version-check-for-updates.md +1 -0
- package/agent/commands/acp.version-check.md +1 -0
- package/agent/commands/acp.version-update.md +1 -0
- package/agent/commands/command.template.md +23 -0
- package/agent/commands/git.commit.md +1 -0
- package/agent/commands/git.init.md +1 -0
- package/agent/design/complete-tool-set.md +157 -233
- package/agent/design/design.template.md +18 -0
- package/agent/design/user-preferences.md +11 -7
- package/agent/milestones/milestone-19-new-search-ghost-tools.md +46 -0
- package/agent/package.template.yaml +50 -0
- package/agent/patterns/pattern.template.md +18 -0
- package/agent/progress.yaml +162 -6
- package/agent/scripts/acp.common.sh +258 -15
- package/agent/scripts/acp.install.sh +91 -4
- package/agent/scripts/acp.package-create.sh +0 -1
- package/agent/scripts/acp.package-info.sh +19 -1
- package/agent/scripts/acp.package-install-optimized.sh +1 -1
- package/agent/scripts/acp.package-install.sh +388 -38
- package/agent/scripts/acp.package-list.sh +52 -4
- package/agent/scripts/acp.package-remove.sh +77 -1
- package/agent/scripts/acp.package-search.sh +2 -2
- package/agent/scripts/acp.package-update.sh +91 -12
- package/agent/scripts/acp.package-validate.sh +136 -1
- package/agent/scripts/acp.project-info.sh +34 -11
- package/agent/scripts/acp.project-list.sh +4 -0
- package/agent/scripts/acp.project-update.sh +66 -19
- package/agent/scripts/acp.projects-restore.sh +170 -0
- package/agent/scripts/acp.projects-sync.sh +155 -0
- package/agent/scripts/acp.sessions.sh +725 -0
- package/agent/scripts/acp.version-update.sh +21 -3
- package/agent/scripts/acp.yaml-parser.sh +20 -6
- package/agent/tasks/milestone-19-new-search-ghost-tools/task-203-create-search-by-tool.md +143 -0
- package/agent/tasks/milestone-19-new-search-ghost-tools/task-204-add-new-filters-existing-tools.md +77 -0
- package/agent/tasks/milestone-19-new-search-ghost-tools/task-205-add-feel-fields-create-update.md +137 -0
- package/agent/tasks/milestone-19-new-search-ghost-tools/task-206-add-byproperty-bysignificance-modes.md +135 -0
- package/agent/tasks/milestone-19-new-search-ghost-tools/task-207-add-emotional-composites-search-results.md +88 -0
- package/agent/tasks/milestone-19-new-search-ghost-tools/task-208-add-bybroad-byrandom-modes.md +115 -0
- package/agent/tasks/milestone-19-new-search-ghost-tools/task-209-create-ghost-memory-tools.md +192 -0
- package/agent/tasks/milestone-19-new-search-ghost-tools/task-210-create-get-core-tool.md +203 -0
- package/agent/tasks/milestone-19-new-search-ghost-tools/task-211-create-search-space-by-tool.md +182 -0
- package/agent/tasks/task-1-{title}.template.md +19 -0
- package/agent/tasks/unassigned/bug-report-remember-core-e2e-findings.md +99 -0
- package/dist/e2e-helpers.d.ts +26 -0
- package/dist/ghost-persona.e2e.d.ts +8 -0
- package/dist/memory-crud.e2e.d.ts +8 -0
- package/dist/preferences.e2e.d.ts +8 -0
- package/dist/relationships.e2e.d.ts +8 -0
- package/dist/search-modes.e2e.d.ts +8 -0
- package/dist/server-factory.js +1977 -100
- package/dist/server.js +1174 -51
- package/dist/shared-spaces.e2e.d.ts +8 -0
- package/dist/tools/create-ghost-memory.d.ts +70 -0
- package/dist/tools/create-memory.d.ts +175 -0
- package/dist/tools/get-core.d.ts +28 -0
- package/dist/tools/get-core.spec.d.ts +2 -0
- package/dist/tools/ghost-tools.spec.d.ts +2 -0
- package/dist/tools/query-ghost-memory.d.ts +34 -0
- package/dist/tools/query-memory.d.ts +4 -0
- package/dist/tools/search-by.d.ts +147 -0
- package/dist/tools/search-by.spec.d.ts +2 -0
- package/dist/tools/search-ghost-memory-by.d.ts +54 -0
- package/dist/tools/search-ghost-memory.d.ts +53 -0
- package/dist/tools/search-memory.d.ts +19 -0
- package/dist/tools/search-space-by.d.ts +78 -0
- package/dist/tools/search-space-by.spec.d.ts +2 -0
- package/dist/tools/search-space.d.ts +2 -0
- package/dist/tools/update-ghost-memory.d.ts +51 -0
- package/dist/tools/update-memory.d.ts +175 -0
- package/jest.e2e.config.js +11 -0
- package/package.json +2 -2
- package/src/e2e-helpers.ts +86 -0
- package/src/ghost-persona.e2e.ts +215 -0
- package/src/memory-crud.e2e.ts +203 -0
- package/src/preferences.e2e.ts +88 -0
- package/src/relationships.e2e.ts +156 -0
- package/src/search-modes.e2e.ts +184 -0
- package/src/server-factory.ts +56 -0
- package/src/shared-spaces.e2e.ts +204 -0
- package/src/tools/create-ghost-memory.ts +103 -0
- package/src/tools/create-memory.ts +45 -1
- package/src/tools/get-core.spec.ts +223 -0
- package/src/tools/get-core.ts +109 -0
- package/src/tools/ghost-tools.spec.ts +361 -0
- package/src/tools/query-ghost-memory.ts +63 -0
- package/src/tools/query-memory.ts +4 -0
- package/src/tools/search-by.spec.ts +325 -0
- package/src/tools/search-by.ts +298 -0
- package/src/tools/search-ghost-memory-by.ts +80 -0
- package/src/tools/search-ghost-memory.ts +73 -0
- package/src/tools/search-memory.ts +23 -0
- package/src/tools/search-space-by.spec.ts +289 -0
- package/src/tools/search-space-by.ts +173 -0
- package/src/tools/search-space.ts +20 -1
- package/src/tools/update-ghost-memory.ts +86 -0
- package/src/tools/update-memory.ts +45 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Task 207: Add Emotional Composites + REM Metadata to Search Results
|
|
2
|
+
|
|
3
|
+
**Milestone**: M19 — New Search Modes, Ghost Tools & Emotional Exposure
|
|
4
|
+
**Status**: Not Started
|
|
5
|
+
**Created**: 2026-03-07
|
|
6
|
+
**Estimated Hours**: 2-3
|
|
7
|
+
**Dependencies**: remember-core schema with composite scores and REM metadata
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Objective
|
|
12
|
+
|
|
13
|
+
Include emotional composite scores (`total_significance`, `feel_significance`, `functional_significance`) and REM metadata (`rem_touched_at`, `rem_visits`) in search result objects across all search tools.
|
|
14
|
+
|
|
15
|
+
## Context
|
|
16
|
+
|
|
17
|
+
When REM has scored memories, the composite significance scores and REM visit metadata are stored in Weaviate. These should be included in search results so the LLM and downstream tools have emotional context. Not all memories will have been scored — unscored fields must be omitted (not returned as null).
|
|
18
|
+
|
|
19
|
+
## Fields to Include
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// Added to search result memory objects (when non-null):
|
|
23
|
+
{
|
|
24
|
+
// ... existing fields (memory_id, title, content, content_type, tags, weight, trust, created_at, etc.) ...
|
|
25
|
+
|
|
26
|
+
// Composite scores (computed by REM, 0-1 floats)
|
|
27
|
+
total_significance?: number; // Combined emotional + functional significance
|
|
28
|
+
feel_significance?: number; // Weighted sum of Layer 1 (21 discrete emotions)
|
|
29
|
+
functional_significance?: number; // Weighted sum of Layer 2 (10 functional signals)
|
|
30
|
+
|
|
31
|
+
// REM metadata
|
|
32
|
+
rem_touched_at?: string; // ISO timestamp of last REM scoring update
|
|
33
|
+
rem_visits?: number; // Number of REM scoring visits
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Tools to Update
|
|
38
|
+
|
|
39
|
+
| Tool File | Function | Notes |
|
|
40
|
+
|-----------|----------|-------|
|
|
41
|
+
| `src/tools/search-memory.ts` | Result serialization | Add composites to each memory result |
|
|
42
|
+
| `src/tools/find-similar.ts` | Result serialization | Add composites to each memory result |
|
|
43
|
+
| `src/tools/query-memory.ts` | Result serialization | Add composites to each memory result |
|
|
44
|
+
| `src/tools/search-space.ts` | Result serialization | Add composites to published memory results |
|
|
45
|
+
| `src/tools/search-by.ts` | Result serialization | Add composites (all modes) |
|
|
46
|
+
|
|
47
|
+
## Implementation Pattern
|
|
48
|
+
|
|
49
|
+
For each tool, find the result serialization code (where memory objects are mapped to response JSON) and add:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
// After existing field mappings:
|
|
53
|
+
...(memory.total_significance != null && { total_significance: memory.total_significance }),
|
|
54
|
+
...(memory.feel_significance != null && { feel_significance: memory.feel_significance }),
|
|
55
|
+
...(memory.functional_significance != null && { functional_significance: memory.functional_significance }),
|
|
56
|
+
...(memory.rem_touched_at != null && { rem_touched_at: memory.rem_touched_at }),
|
|
57
|
+
...(memory.rem_visits != null && { rem_visits: memory.rem_visits }),
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Key Decisions
|
|
61
|
+
|
|
62
|
+
- **Null/undefined values MUST be omitted**: Not all memories have been scored by REM. Never return `null` or `undefined` in the response — only include these fields when they have values.
|
|
63
|
+
- **Use conditional spread**: The `...(value != null && { key: value })` pattern ensures clean omission.
|
|
64
|
+
- **All search tools get composites**: Consistency across all search surfaces. If a memory has been scored, the scores are always visible.
|
|
65
|
+
- **No individual feel_* fields in results**: Only the 3 composites + 2 REM metadata fields. Individual feel_* values are accessible via `byProperty` sorting or future detail tools.
|
|
66
|
+
|
|
67
|
+
## Steps
|
|
68
|
+
|
|
69
|
+
1. Identify result serialization pattern in each of the 5 tool files
|
|
70
|
+
2. Add composite score and REM metadata fields using conditional spread
|
|
71
|
+
3. Update result type definitions if the project has explicit result interfaces
|
|
72
|
+
4. Write tests:
|
|
73
|
+
- Composites appear in results when memory has been scored
|
|
74
|
+
- Composites are omitted when memory has NOT been scored (null/undefined)
|
|
75
|
+
- REM metadata (rem_touched_at, rem_visits) included when available
|
|
76
|
+
- All 5 tools include composites consistently
|
|
77
|
+
|
|
78
|
+
## Verification
|
|
79
|
+
|
|
80
|
+
- [ ] Composite scores included in search_memory results
|
|
81
|
+
- [ ] Composite scores included in find_similar results
|
|
82
|
+
- [ ] Composite scores included in query_memory results
|
|
83
|
+
- [ ] Composite scores included in search_space results
|
|
84
|
+
- [ ] Composite scores included in search_by results
|
|
85
|
+
- [ ] REM metadata (rem_touched_at, rem_visits) included when available
|
|
86
|
+
- [ ] Null/unscored fields omitted from results (no nulls in output)
|
|
87
|
+
- [ ] Tests passing
|
|
88
|
+
- [ ] TypeScript clean
|
package/agent/tasks/milestone-19-new-search-ghost-tools/task-208-add-bybroad-byrandom-modes.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Task 208: Add byBroad and byRandom Modes to search_by
|
|
2
|
+
|
|
3
|
+
**Milestone**: M19 — New Search Modes, Ghost Tools & Emotional Exposure
|
|
4
|
+
**Status**: Not Started
|
|
5
|
+
**Created**: 2026-03-07
|
|
6
|
+
**Estimated Hours**: 3-4
|
|
7
|
+
**Dependencies**: Task 203 (search_by tool exists), remember-core byBroad and byRandom implementations
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Objective
|
|
12
|
+
|
|
13
|
+
Add `byBroad` and `byRandom` modes to `remember_search_by`. These require new core methods that don't exist yet — this task is blocked until remember-core implements them.
|
|
14
|
+
|
|
15
|
+
## Context
|
|
16
|
+
|
|
17
|
+
- **byBroad**: Fetches massive result sets with truncated content (head/mid/tail slices ~100 chars each). Default limit 50-100. Enables "scan and drill-in" workflow — browse broad results, then use `remember_search_memory` or `remember_query_memory` to get full content of interesting items. Includes emotional composites in truncated results.
|
|
18
|
+
- **byRandom**: Random sampling from the collection. Optional query to constrain the random pool. Useful for serendipitous rediscovery of forgotten content.
|
|
19
|
+
|
|
20
|
+
## Schema Changes
|
|
21
|
+
|
|
22
|
+
Update `src/tools/search-by.ts`:
|
|
23
|
+
|
|
24
|
+
1. Add to mode enum: `'byBroad', 'byRandom'`
|
|
25
|
+
2. Update tool description:
|
|
26
|
+
```
|
|
27
|
+
- byBroad: Massive results with truncated content for scan-and-drill-in workflow (default limit: 50)
|
|
28
|
+
- byRandom: Random sampling for serendipitous rediscovery
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## `byBroad` Response Shape
|
|
32
|
+
|
|
33
|
+
byBroad returns a DIFFERENT response shape than other modes — truncated content instead of full content:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
interface BroadSearchResult {
|
|
37
|
+
memory_id: string;
|
|
38
|
+
title?: string;
|
|
39
|
+
content_type: string;
|
|
40
|
+
content_head: string; // First ~100 chars
|
|
41
|
+
content_mid: string; // ~100 chars from middle
|
|
42
|
+
content_tail: string; // Last ~100 chars
|
|
43
|
+
created_at: string;
|
|
44
|
+
tags: string[];
|
|
45
|
+
weight: number;
|
|
46
|
+
// Include emotional composites for context
|
|
47
|
+
total_significance?: number;
|
|
48
|
+
feel_significance?: number;
|
|
49
|
+
functional_significance?: number;
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Handler Logic
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
case 'byBroad':
|
|
57
|
+
results = await services.memoryService.byBroad({
|
|
58
|
+
query: args.query,
|
|
59
|
+
limit: args.limit ?? 50, // Default limit is 50, much higher than normal
|
|
60
|
+
offset: args.offset,
|
|
61
|
+
filters: args.filters,
|
|
62
|
+
deleted_filter: args.deleted_filter
|
|
63
|
+
});
|
|
64
|
+
// Results already have truncated content (content_head/mid/tail) from core
|
|
65
|
+
break;
|
|
66
|
+
|
|
67
|
+
case 'byRandom':
|
|
68
|
+
results = await services.memoryService.byRandom({
|
|
69
|
+
query: args.query, // Optional: constrains the random pool
|
|
70
|
+
limit: args.limit,
|
|
71
|
+
filters: args.filters,
|
|
72
|
+
deleted_filter: args.deleted_filter
|
|
73
|
+
});
|
|
74
|
+
// sort_order is not applicable for byRandom
|
|
75
|
+
break;
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Key Decisions
|
|
79
|
+
|
|
80
|
+
- **byBroad default limit is 50**: Much higher than normal modes (10). The truncated content format makes this feasible without context overload.
|
|
81
|
+
- **byBroad response shape differs**: `content_head`, `content_mid`, `content_tail` replace the full `content` field. The handler may need to serialize differently.
|
|
82
|
+
- **byBroad includes composites**: `total_significance`, `feel_significance`, `functional_significance` in truncated results for emotional context during scanning.
|
|
83
|
+
- **byRandom query is optional**: When provided, constrains the random pool (e.g., "only random memories tagged 'idea'"). When omitted, samples from entire collection.
|
|
84
|
+
- **byRandom ignores sort_order**: Random is random — sort_order is not applicable.
|
|
85
|
+
- **Both modes support standard filters**: types, tags, weight, trust, date, etc. all work with byBroad and byRandom.
|
|
86
|
+
- **Blocked on core implementation**: Core needs `MemoryService.byBroad()` and `MemoryService.byRandom()`. byRandom could use Weaviate's `near_random` or a client-side shuffle approach.
|
|
87
|
+
|
|
88
|
+
## Steps
|
|
89
|
+
|
|
90
|
+
1. Update `src/tools/search-by.ts`:
|
|
91
|
+
- Add `byBroad` and `byRandom` to mode enum
|
|
92
|
+
- Add handler cases per logic above
|
|
93
|
+
- Handle byBroad's different response serialization (content_head/mid/tail)
|
|
94
|
+
- Update tool description with byBroad and byRandom documentation
|
|
95
|
+
2. Write tests:
|
|
96
|
+
- `byBroad` returns truncated content format (content_head/mid/tail, NOT full content)
|
|
97
|
+
- `byBroad` default limit is 50
|
|
98
|
+
- `byBroad` includes emotional composites
|
|
99
|
+
- `byRandom` returns results
|
|
100
|
+
- `byRandom` with query constrains pool
|
|
101
|
+
- `byRandom` ignores sort_order
|
|
102
|
+
- Both modes support standard filters and deleted_filter
|
|
103
|
+
|
|
104
|
+
## Verification
|
|
105
|
+
|
|
106
|
+
- [ ] `byBroad` returns truncated content (content_head/mid/tail)
|
|
107
|
+
- [ ] `byBroad` does NOT return full content field
|
|
108
|
+
- [ ] `byBroad` default limit is 50
|
|
109
|
+
- [ ] `byBroad` includes emotional composites in results
|
|
110
|
+
- [ ] `byRandom` returns random results
|
|
111
|
+
- [ ] `byRandom` query parameter constrains pool
|
|
112
|
+
- [ ] `byRandom` ignores sort_order
|
|
113
|
+
- [ ] Both modes support standard filters
|
|
114
|
+
- [ ] Tests passing
|
|
115
|
+
- [ ] TypeScript clean
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Task 209: Create Ghost Memory Tool Suite (5 Tools)
|
|
2
|
+
|
|
3
|
+
**Milestone**: M19 — New Search Modes, Ghost Tools & Emotional Exposure
|
|
4
|
+
**Status**: Not Started
|
|
5
|
+
**Created**: 2026-03-07
|
|
6
|
+
**Estimated Hours**: 4-6
|
|
7
|
+
**Dependencies**: Task 203 (search_by tool exists for ghost_search_by wrapper)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Objective
|
|
12
|
+
|
|
13
|
+
Create 5 dedicated ghost memory MCP tools that hardcode `content_type: 'ghost'` and ghost-specific tags. Each tool is a thin wrapper around the corresponding non-ghost tool.
|
|
14
|
+
|
|
15
|
+
## Context
|
|
16
|
+
|
|
17
|
+
Ghost memories track cross-user interaction records. Currently, creating ghost memories requires manually setting the correct content_type and tags. Dedicated tools eliminate this error-prone process. Ghost memories are excluded from default searches — they are only visible when explicitly searching with content_type: 'ghost' or using ghost memory tools.
|
|
18
|
+
|
|
19
|
+
## Tool 1: `remember_create_ghost_memory` (`src/tools/create-ghost-memory.ts`)
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
{
|
|
23
|
+
name: 'remember_create_ghost_memory',
|
|
24
|
+
description: `Create a ghost memory (cross-user interaction record).
|
|
25
|
+
|
|
26
|
+
Ghost memories track what happened during ghost conversations — observations,
|
|
27
|
+
impressions, and insights about the accessor. Automatically sets content_type
|
|
28
|
+
to 'ghost' and adds ghost-specific tags.
|
|
29
|
+
|
|
30
|
+
Ghost memories are excluded from default searches. They are only visible when
|
|
31
|
+
explicitly searching with content_type: 'ghost' or using ghost memory tools.`,
|
|
32
|
+
inputSchema: {
|
|
33
|
+
type: 'object',
|
|
34
|
+
properties: {
|
|
35
|
+
content: { type: 'string', description: 'Ghost memory content' },
|
|
36
|
+
title: { type: 'string', description: 'Optional title' },
|
|
37
|
+
tags: { type: 'array', items: { type: 'string' }, description: 'Additional tags (ghost-specific tags added automatically)' },
|
|
38
|
+
weight: { type: 'number', minimum: 0, maximum: 1, description: 'Significance (0-1)' },
|
|
39
|
+
trust: { type: 'number', minimum: 0, maximum: 1, description: 'Trust level (0-1)' },
|
|
40
|
+
// Select feel_* fields relevant to ghost interactions
|
|
41
|
+
feel_salience: { type: 'number', minimum: 0, maximum: 1 },
|
|
42
|
+
feel_social_weight: { type: 'number', minimum: 0, maximum: 1 },
|
|
43
|
+
feel_narrative_importance: { type: 'number', minimum: 0, maximum: 1 }
|
|
44
|
+
},
|
|
45
|
+
required: ['content']
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Handler hardcodes**:
|
|
51
|
+
- `content_type: 'ghost'`
|
|
52
|
+
- Adds tags: `ghost`, `ghost:{accessor_user_id}` (accessor_user_id from auth context)
|
|
53
|
+
- Merges hardcoded tags with any user-provided tags
|
|
54
|
+
- Calls `handleCreateMemory` (or core `memoryService.create()`) with merged args
|
|
55
|
+
|
|
56
|
+
## Tool 2: `remember_update_ghost_memory` (`src/tools/update-ghost-memory.ts`)
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
{
|
|
60
|
+
name: 'remember_update_ghost_memory',
|
|
61
|
+
description: 'Update a ghost memory. Only works on memories with content_type: ghost.',
|
|
62
|
+
inputSchema: {
|
|
63
|
+
type: 'object',
|
|
64
|
+
properties: {
|
|
65
|
+
memory_id: { type: 'string', description: 'Ghost memory ID to update' },
|
|
66
|
+
content: { type: 'string' },
|
|
67
|
+
title: { type: 'string' },
|
|
68
|
+
tags: { type: 'array', items: { type: 'string' } },
|
|
69
|
+
weight: { type: 'number', minimum: 0, maximum: 1 },
|
|
70
|
+
trust: { type: 'number', minimum: 0, maximum: 1 }
|
|
71
|
+
},
|
|
72
|
+
required: ['memory_id']
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Handler logic**:
|
|
78
|
+
1. Fetch the memory by ID first
|
|
79
|
+
2. Validate `content_type === 'ghost'` — reject with clear error if not ghost
|
|
80
|
+
3. Delegate to `handleUpdateMemory` / core `memoryService.update()`
|
|
81
|
+
|
|
82
|
+
## Tool 3: `remember_search_ghost_memory` (`src/tools/search-ghost-memory.ts`)
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
{
|
|
86
|
+
name: 'remember_search_ghost_memory',
|
|
87
|
+
description: `Search ghost memories using hybrid semantic + keyword search.
|
|
88
|
+
Automatically filters to content_type: ghost. Use this to find specific
|
|
89
|
+
ghost interaction records.`,
|
|
90
|
+
inputSchema: {
|
|
91
|
+
type: 'object',
|
|
92
|
+
properties: {
|
|
93
|
+
query: { type: 'string', description: 'Search query' },
|
|
94
|
+
alpha: { type: 'number', minimum: 0, maximum: 1, description: 'Semantic vs keyword balance. Default: 0.7' },
|
|
95
|
+
tags: { type: 'array', items: { type: 'string' }, description: 'Filter by tags' },
|
|
96
|
+
limit: { type: 'number', description: 'Max results. Default: 10' },
|
|
97
|
+
offset: { type: 'number' },
|
|
98
|
+
deleted_filter: { type: 'string', enum: ['exclude', 'include', 'only'] }
|
|
99
|
+
},
|
|
100
|
+
required: ['query']
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Handler hardcodes**: `filters.types: ['ghost']` before calling `handleSearchMemory` / core search.
|
|
106
|
+
|
|
107
|
+
## Tool 4: `remember_query_ghost_memory` (`src/tools/query-ghost-memory.ts`)
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
{
|
|
111
|
+
name: 'remember_query_ghost_memory',
|
|
112
|
+
description: `Query ghost memories using natural language (pure semantic search).
|
|
113
|
+
Automatically filters to content_type: ghost.`,
|
|
114
|
+
inputSchema: {
|
|
115
|
+
type: 'object',
|
|
116
|
+
properties: {
|
|
117
|
+
query: { type: 'string', description: 'Natural language question' },
|
|
118
|
+
limit: { type: 'number', description: 'Max results. Default: 5' },
|
|
119
|
+
min_relevance: { type: 'number', description: 'Minimum relevance score. Default: 0.6' }
|
|
120
|
+
},
|
|
121
|
+
required: ['query']
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Handler hardcodes**: `filters.types: ['ghost']` before calling `handleQueryMemory` / core query.
|
|
127
|
+
|
|
128
|
+
## Tool 5: `remember_search_ghost_memory_by` (`src/tools/search-ghost-memory-by.ts`)
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
{
|
|
132
|
+
name: 'remember_search_ghost_memory_by',
|
|
133
|
+
description: `Search ghost memories using specialized modes (byTime, byDensity,
|
|
134
|
+
byProperty, byBroad, etc.). Automatically filters to content_type: ghost.`,
|
|
135
|
+
inputSchema: {
|
|
136
|
+
type: 'object',
|
|
137
|
+
properties: {
|
|
138
|
+
mode: {
|
|
139
|
+
type: 'string',
|
|
140
|
+
enum: ['byTime', 'byDensity', 'byRating', 'byDiscovery', 'byProperty', 'bySignificance', 'byRandom', 'byBroad'],
|
|
141
|
+
description: 'Search mode'
|
|
142
|
+
},
|
|
143
|
+
query: { type: 'string', description: 'Optional search query' },
|
|
144
|
+
sort_order: { type: 'string', enum: ['asc', 'desc'] },
|
|
145
|
+
sort_field: { type: 'string', description: 'Property to sort by (byProperty mode)' },
|
|
146
|
+
limit: { type: 'number' },
|
|
147
|
+
offset: { type: 'number' },
|
|
148
|
+
deleted_filter: { type: 'string', enum: ['exclude', 'include', 'only'] }
|
|
149
|
+
},
|
|
150
|
+
required: ['mode']
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Handler hardcodes**: `filters.types: ['ghost']` before calling `handleSearchBy`.
|
|
156
|
+
|
|
157
|
+
## Key Decisions
|
|
158
|
+
|
|
159
|
+
- **Ghost tools don't need rating**: Ghosts are read-only accessors. No rating parameters on ghost tools.
|
|
160
|
+
- **Only 3 feel_* fields on create_ghost_memory**: `feel_salience`, `feel_social_weight`, `feel_narrative_importance` — the most relevant for ghost interaction records. NOT all 31.
|
|
161
|
+
- **update_ghost_memory validates content_type**: Must fetch memory first, check `content_type === 'ghost'`, reject if not. This prevents using the ghost update tool on non-ghost memories.
|
|
162
|
+
- **All search/query ghost tools hardcode `filters.types: ['ghost']`**: This is the core behavioral difference from the non-ghost versions. User-provided filters are merged, not replaced.
|
|
163
|
+
- **search_ghost_memory_by has ALL modes**: Even byRating and byDiscovery, though these are less useful for ghost memories. Consistency over restriction.
|
|
164
|
+
- **Tags merging on create**: User-provided tags are merged with hardcoded `['ghost', 'ghost:{accessor_user_id}']`. If user already includes 'ghost' tag, don't duplicate.
|
|
165
|
+
|
|
166
|
+
## Steps
|
|
167
|
+
|
|
168
|
+
1. Create 5 tool files in `src/tools/`
|
|
169
|
+
2. Each file exports tool definition + handler function
|
|
170
|
+
3. Register all 5 tools in `src/server-factory.ts` (imports, ListTools, CallTool switch cases)
|
|
171
|
+
4. Write unit tests for each tool:
|
|
172
|
+
- create: content_type hardcoded to 'ghost', ghost tags added automatically, user tags merged
|
|
173
|
+
- update: validates content_type before update, rejects non-ghost memories with error
|
|
174
|
+
- search: filters.types hardcoded to ['ghost'], query/alpha/tags passthrough
|
|
175
|
+
- query: filters.types hardcoded to ['ghost'], query/limit/min_relevance passthrough
|
|
176
|
+
- search_by: filters.types hardcoded to ['ghost'], all modes work, sort_field passthrough
|
|
177
|
+
|
|
178
|
+
## Verification
|
|
179
|
+
|
|
180
|
+
- [ ] 5 tool files created in src/tools/
|
|
181
|
+
- [ ] All 5 tools registered in server-factory.ts
|
|
182
|
+
- [ ] create_ghost_memory hardcodes content_type: 'ghost'
|
|
183
|
+
- [ ] create_ghost_memory adds 'ghost' and 'ghost:{accessor_user_id}' tags
|
|
184
|
+
- [ ] create_ghost_memory merges user tags without duplicating 'ghost'
|
|
185
|
+
- [ ] update_ghost_memory fetches memory and validates content_type before update
|
|
186
|
+
- [ ] update_ghost_memory rejects non-ghost memories with clear error message
|
|
187
|
+
- [ ] search_ghost_memory hardcodes filters.types: ['ghost']
|
|
188
|
+
- [ ] query_ghost_memory hardcodes filters.types: ['ghost']
|
|
189
|
+
- [ ] search_ghost_memory_by hardcodes filters.types: ['ghost'], all modes work
|
|
190
|
+
- [ ] Unit tests for all 5 tools
|
|
191
|
+
- [ ] TypeScript clean
|
|
192
|
+
- [ ] Build passing
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# Task 210: Create `remember_get_core` Tool
|
|
2
|
+
|
|
3
|
+
**Milestone**: M19 — New Search Modes, Ghost Tools & Emotional Exposure
|
|
4
|
+
**Status**: Not Started
|
|
5
|
+
**Created**: 2026-03-07
|
|
6
|
+
**Estimated Hours**: 2-3
|
|
7
|
+
**Dependencies**: remember-core mood + perception Firestore service
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Objective
|
|
12
|
+
|
|
13
|
+
Create `remember_get_core` MCP tool that reads the ghost's core state from Firestore — mood dimensions, pressures, motivation/goal/purpose, dominant emotion, color, and user perceptions — in a single call.
|
|
14
|
+
|
|
15
|
+
## Context
|
|
16
|
+
|
|
17
|
+
The core mood state lives at `users/{user_id}/core/mood` and user perceptions at `users/{owner_id}/core/perceptions/{target_user_id}` in Firestore. This tool enables ghost introspection — the ghost can explain how it feels and why. Consolidated from separate `remember_get_mood` and `remember_get_perception` since they're on one Firestore document path.
|
|
18
|
+
|
|
19
|
+
## Tool Definition
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
{
|
|
23
|
+
name: 'remember_get_core',
|
|
24
|
+
description: `Get the ghost's current emotional state and perception model.
|
|
25
|
+
|
|
26
|
+
Returns the ghost's current dimensional state (valence, arousal, confidence,
|
|
27
|
+
social_warmth, coherence, trust), derived emotion labels (dominant_emotion, color),
|
|
28
|
+
directional state (motivation, goal, purpose), and active pressure sources.
|
|
29
|
+
|
|
30
|
+
Optionally includes the ghost's internal model of a specific user (personality,
|
|
31
|
+
communication style, interests, patterns, needs).
|
|
32
|
+
|
|
33
|
+
Use this for introspection — understanding how the ghost feels and why.
|
|
34
|
+
The mood state biases memory retrieval and influences ghost behavior.`,
|
|
35
|
+
inputSchema: {
|
|
36
|
+
type: 'object',
|
|
37
|
+
properties: {
|
|
38
|
+
include_pressures: {
|
|
39
|
+
type: 'boolean',
|
|
40
|
+
description: 'Include active pressure sources with reasons. Default: true'
|
|
41
|
+
},
|
|
42
|
+
include_perception: {
|
|
43
|
+
type: 'string',
|
|
44
|
+
description: 'Include the ghost\'s perception of a specific user (by user_id). Omit to skip. Use owner\'s user_id for self-perception.'
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Return Shape
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
interface GetCoreResult {
|
|
55
|
+
mood: {
|
|
56
|
+
state: {
|
|
57
|
+
valence: number; // -1 to 1: Did events move toward or away from goals?
|
|
58
|
+
arousal: number; // 0 to 1: How activated/alert? Prediction error level
|
|
59
|
+
confidence: number; // 0 to 1: How well are actions working? Agency signal
|
|
60
|
+
social_warmth: number; // 0 to 1: How positive are social interactions?
|
|
61
|
+
coherence: number; // 0 to 1: Do beliefs and memories fit together?
|
|
62
|
+
trust: number; // 0 to 1: Trust in user based on accumulated interactions
|
|
63
|
+
};
|
|
64
|
+
color: string; // Natural language self-summary, e.g. "cautiously optimistic"
|
|
65
|
+
dominant_emotion: string; // Emotion label, e.g. "curious wariness"
|
|
66
|
+
reasoning: string; // Why this emotion fits
|
|
67
|
+
motivation: string; // Current behavioral driver
|
|
68
|
+
goal: string; // Active goal
|
|
69
|
+
purpose: string; // Enduring purpose
|
|
70
|
+
pressures?: Pressure[]; // Active pressure sources (when include_pressures=true)
|
|
71
|
+
last_updated: string; // ISO timestamp
|
|
72
|
+
rem_cycles_since_shift: number;
|
|
73
|
+
};
|
|
74
|
+
perception?: {
|
|
75
|
+
owner_id: string;
|
|
76
|
+
target_user_id: string;
|
|
77
|
+
personality_sketch: string; // Sub-LLM summary of who the user is
|
|
78
|
+
communication_style: string; // How the user communicates
|
|
79
|
+
emotional_baseline: string; // User's normal emotional register (calibrates arousal)
|
|
80
|
+
interests: string[]; // Recurring topics
|
|
81
|
+
patterns: string[]; // Observed behavioral patterns
|
|
82
|
+
needs: string[]; // What the user wants from the ghost
|
|
83
|
+
evolution_notes: string[]; // How the perception has changed over time
|
|
84
|
+
confidence_level: number; // 0-1, ghost's confidence in this model
|
|
85
|
+
last_updated: string;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Pressure Object Shape
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
interface Pressure {
|
|
94
|
+
source_memory_id: string; // Memory that caused this pressure
|
|
95
|
+
dimension: string; // Which mood dimension is affected (e.g. 'valence', 'trust')
|
|
96
|
+
magnitude: number; // Strength of pressure (-1 to 1)
|
|
97
|
+
reason: string; // Why this memory creates pressure
|
|
98
|
+
decay_rate: number; // How quickly this pressure fades
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Threshold Flags
|
|
103
|
+
|
|
104
|
+
The mood document may contain threshold flags that should be included in the response when present:
|
|
105
|
+
|
|
106
|
+
| Threshold | Condition | Flag |
|
|
107
|
+
|-----------|-----------|------|
|
|
108
|
+
| coherence < 0.2 for 3+ cycles | Existential crisis | `existential_crisis` |
|
|
109
|
+
| valence < -0.7 for 3+ cycles | Depression analog | `depression_analog` |
|
|
110
|
+
| arousal > 0.9 for 3+ cycles | Burnout risk | `burnout_risk` |
|
|
111
|
+
| social_warmth < 0.2 for 5+ cycles | Isolation | `isolation` |
|
|
112
|
+
| trust < 0.15 for 3+ cycles | Trust crisis | `trust_crisis` |
|
|
113
|
+
| trust > 0.95 for 5+ cycles | Over-trust vulnerability | `over_trust` |
|
|
114
|
+
|
|
115
|
+
If any threshold flags are active, include them in the response as `threshold_flags: string[]`.
|
|
116
|
+
|
|
117
|
+
## Handler Logic
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
async function handleGetCore(userId: string, args: GetCoreArgs): Promise<ToolResult> {
|
|
121
|
+
const services = await createCoreServices(userId);
|
|
122
|
+
|
|
123
|
+
// Read mood state from Firestore: users/{user_id}/core/mood
|
|
124
|
+
const mood = await services.coreMoodService.getMood(userId);
|
|
125
|
+
|
|
126
|
+
if (!mood) {
|
|
127
|
+
return { content: [{ type: 'text', text: JSON.stringify({ mood: null, message: 'No mood state found. Mood is initialized during the first REM cycle.' }) }] };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const result: GetCoreResult = {
|
|
131
|
+
mood: {
|
|
132
|
+
state: mood.state,
|
|
133
|
+
color: mood.color,
|
|
134
|
+
dominant_emotion: mood.dominant_emotion,
|
|
135
|
+
reasoning: mood.reasoning,
|
|
136
|
+
motivation: mood.motivation,
|
|
137
|
+
goal: mood.goal,
|
|
138
|
+
purpose: mood.purpose,
|
|
139
|
+
last_updated: mood.last_updated,
|
|
140
|
+
rem_cycles_since_shift: mood.rem_cycles_since_shift,
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// Include pressures if requested (default: true)
|
|
145
|
+
if (args.include_pressures !== false && mood.pressures) {
|
|
146
|
+
result.mood.pressures = mood.pressures;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Include threshold flags if any are active
|
|
150
|
+
if (mood.threshold_flags?.length > 0) {
|
|
151
|
+
result.mood.threshold_flags = mood.threshold_flags;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Include perception if requested
|
|
155
|
+
if (args.include_perception) {
|
|
156
|
+
const perception = await services.coreMoodService.getPerception(userId, args.include_perception);
|
|
157
|
+
if (perception) {
|
|
158
|
+
result.perception = perception;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Key Decisions
|
|
167
|
+
|
|
168
|
+
- **Privacy: owner only**: Only the owner can read their own core state. Ghost accessors cannot read another user's mood. Enforce via userId from auth context.
|
|
169
|
+
- **Pressures included by default**: `include_pressures` defaults to `true`. Set to `false` to exclude.
|
|
170
|
+
- **Perception is opt-in**: Must provide `include_perception` with a target user_id to include. Self-perception uses the owner's own user_id.
|
|
171
|
+
- **Graceful handling of missing mood**: If no mood document exists (first-time user before any REM cycle), return `{ mood: null }` with a message. Do NOT error.
|
|
172
|
+
- **Threshold flags only when active**: Don't include `threshold_flags` field at all if empty.
|
|
173
|
+
- **Consolidated from get_mood + get_perception**: Single tool because mood and perception live under the same Firestore path (`users/{user_id}/core/`).
|
|
174
|
+
|
|
175
|
+
## Steps
|
|
176
|
+
|
|
177
|
+
1. Create `src/tools/get-core.ts` with tool definition and handler per above
|
|
178
|
+
2. Register in `src/server-factory.ts`
|
|
179
|
+
3. Write unit tests:
|
|
180
|
+
- Mood state returned correctly with all 6 dimensions + derived labels + directional state
|
|
181
|
+
- Pressures included by default, excludable with `include_pressures: false`
|
|
182
|
+
- Perception included when `include_perception` provided with valid user_id
|
|
183
|
+
- Perception omitted when `include_perception` not provided
|
|
184
|
+
- Self-perception works (include_perception = owner's user_id)
|
|
185
|
+
- Privacy enforced (no cross-user access)
|
|
186
|
+
- Graceful handling when mood doc doesn't exist yet (returns null, not error)
|
|
187
|
+
- Threshold flags included when active, omitted when empty/none
|
|
188
|
+
|
|
189
|
+
## Verification
|
|
190
|
+
|
|
191
|
+
- [ ] Tool definition exports `getCoreTool` and `handleGetCore`
|
|
192
|
+
- [ ] Mood state returned with all 6 dimensions (valence, arousal, confidence, social_warmth, coherence, trust)
|
|
193
|
+
- [ ] Derived labels returned (color, dominant_emotion, reasoning)
|
|
194
|
+
- [ ] Directional state returned (motivation, goal, purpose)
|
|
195
|
+
- [ ] Pressures included by default, excludable
|
|
196
|
+
- [ ] Threshold flags included when active
|
|
197
|
+
- [ ] Perception included when target_user_id provided
|
|
198
|
+
- [ ] Self-perception works
|
|
199
|
+
- [ ] Privacy enforced (owner only)
|
|
200
|
+
- [ ] Graceful handling of missing mood doc (null, not error)
|
|
201
|
+
- [ ] Registered in server-factory.ts
|
|
202
|
+
- [ ] Unit tests passing
|
|
203
|
+
- [ ] TypeScript clean
|