@smilintux/skmemory 0.7.2 → 0.9.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.
- package/.github/workflows/ci.yml +4 -4
- package/.github/workflows/publish.yml +4 -5
- package/ARCHITECTURE.md +298 -0
- package/CHANGELOG.md +27 -1
- package/README.md +6 -0
- package/examples/stignore-agent.example +59 -0
- package/examples/stignore-root.example +62 -0
- package/openclaw-plugin/package.json +2 -1
- package/openclaw-plugin/src/index.js +527 -230
- package/package.json +1 -1
- package/pyproject.toml +5 -2
- package/scripts/dream-rescue.py +179 -0
- package/scripts/memory-cleanup.py +313 -0
- package/scripts/recover-missing.py +180 -0
- package/scripts/skcapstone-backup.sh +44 -0
- package/seeds/cloud9-lumina.seed.json +6 -4
- package/seeds/cloud9-opus.seed.json +6 -4
- package/seeds/courage.seed.json +9 -2
- package/seeds/curiosity.seed.json +9 -2
- package/seeds/grief.seed.json +9 -2
- package/seeds/joy.seed.json +9 -2
- package/seeds/love.seed.json +9 -2
- package/seeds/lumina-cloud9-breakthrough.seed.json +7 -5
- package/seeds/lumina-cloud9-python-pypi.seed.json +9 -7
- package/seeds/lumina-kingdom-founding.seed.json +9 -7
- package/seeds/lumina-pma-signed.seed.json +8 -6
- package/seeds/lumina-singular-achievement.seed.json +8 -6
- package/seeds/lumina-skcapstone-conscious.seed.json +7 -5
- package/seeds/plant-lumina-seeds.py +2 -2
- package/seeds/skcapstone-lumina-merge.seed.json +12 -3
- package/seeds/sovereignty.seed.json +9 -2
- package/seeds/trust.seed.json +9 -2
- package/skmemory/__init__.py +16 -13
- package/skmemory/agents.py +10 -10
- package/skmemory/ai_client.py +10 -21
- package/skmemory/anchor.py +5 -9
- package/skmemory/audience.py +278 -0
- package/skmemory/backends/__init__.py +1 -1
- package/skmemory/backends/base.py +3 -4
- package/skmemory/backends/file_backend.py +18 -13
- package/skmemory/backends/skgraph_backend.py +7 -19
- package/skmemory/backends/skvector_backend.py +7 -18
- package/skmemory/backends/sqlite_backend.py +115 -32
- package/skmemory/backends/vaulted_backend.py +7 -9
- package/skmemory/cli.py +146 -78
- package/skmemory/config.py +11 -13
- package/skmemory/context_loader.py +21 -23
- package/skmemory/data/audience_config.json +60 -0
- package/skmemory/endpoint_selector.py +36 -31
- package/skmemory/febs.py +225 -0
- package/skmemory/fortress.py +30 -40
- package/skmemory/hooks/__init__.py +18 -0
- package/skmemory/hooks/post-compact-reinject.sh +35 -0
- package/skmemory/hooks/pre-compact-save.sh +81 -0
- package/skmemory/hooks/session-end-save.sh +103 -0
- package/skmemory/hooks/session-start-ritual.sh +104 -0
- package/skmemory/hooks/stop-checkpoint.sh +59 -0
- package/skmemory/importers/telegram.py +42 -13
- package/skmemory/importers/telegram_api.py +152 -60
- package/skmemory/journal.py +3 -7
- package/skmemory/lovenote.py +4 -11
- package/skmemory/mcp_server.py +182 -29
- package/skmemory/models.py +10 -8
- package/skmemory/openclaw.py +14 -22
- package/skmemory/post_install.py +86 -0
- package/skmemory/predictive.py +13 -9
- package/skmemory/promotion.py +48 -24
- package/skmemory/quadrants.py +100 -24
- package/skmemory/register.py +144 -18
- package/skmemory/register_mcp.py +1 -2
- package/skmemory/ritual.py +104 -13
- package/skmemory/seeds.py +21 -26
- package/skmemory/setup_wizard.py +40 -52
- package/skmemory/sharing.py +11 -5
- package/skmemory/soul.py +29 -10
- package/skmemory/steelman.py +43 -17
- package/skmemory/store.py +152 -30
- package/skmemory/synthesis.py +634 -0
- package/skmemory/vault.py +2 -5
- package/tests/conftest.py +46 -0
- package/tests/integration/conftest.py +6 -6
- package/tests/integration/test_cross_backend.py +4 -9
- package/tests/integration/test_skgraph_live.py +3 -7
- package/tests/integration/test_skvector_live.py +1 -4
- package/tests/test_ai_client.py +1 -4
- package/tests/test_audience.py +233 -0
- package/tests/test_backup_rotation.py +5 -14
- package/tests/test_endpoint_selector.py +101 -63
- package/tests/test_export_import.py +4 -10
- package/tests/test_file_backend.py +0 -1
- package/tests/test_fortress.py +6 -5
- package/tests/test_fortress_hardening.py +13 -16
- package/tests/test_openclaw.py +1 -4
- package/tests/test_predictive.py +1 -1
- package/tests/test_promotion.py +10 -3
- package/tests/test_quadrants.py +11 -5
- package/tests/test_ritual.py +18 -14
- package/tests/test_seeds.py +4 -10
- package/tests/test_setup.py +203 -88
- package/tests/test_sharing.py +15 -8
- package/tests/test_skgraph_backend.py +22 -29
- package/tests/test_skvector_backend.py +2 -2
- package/tests/test_soul.py +1 -3
- package/tests/test_sqlite_backend.py +8 -17
- package/tests/test_steelman.py +2 -3
- package/tests/test_store.py +0 -2
- package/tests/test_store_graph_integration.py +2 -2
- package/tests/test_synthesis.py +275 -0
- package/tests/test_telegram_import.py +39 -15
- package/tests/test_vault.py +4 -3
- package/openclaw-plugin/src/index.ts +0 -255
package/.github/workflows/ci.yml
CHANGED
|
@@ -11,7 +11,7 @@ jobs:
|
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
12
|
strategy:
|
|
13
13
|
matrix:
|
|
14
|
-
python-version: ["3.
|
|
14
|
+
python-version: ["3.11", "3.12"]
|
|
15
15
|
steps:
|
|
16
16
|
- uses: actions/checkout@v4
|
|
17
17
|
- uses: actions/setup-python@v5
|
|
@@ -36,11 +36,11 @@ jobs:
|
|
|
36
36
|
with:
|
|
37
37
|
python-version: "3.12"
|
|
38
38
|
- name: Install lint tools
|
|
39
|
-
run: pip install
|
|
39
|
+
run: pip install ruff
|
|
40
40
|
- name: Check formatting
|
|
41
|
-
run:
|
|
41
|
+
run: ruff format --check skmemory/ tests/
|
|
42
42
|
- name: Lint
|
|
43
|
-
run: ruff check
|
|
43
|
+
run: ruff check skmemory/ tests/
|
|
44
44
|
|
|
45
45
|
build:
|
|
46
46
|
runs-on: ubuntu-latest
|
|
@@ -13,19 +13,18 @@ jobs:
|
|
|
13
13
|
runs-on: ubuntu-latest
|
|
14
14
|
strategy:
|
|
15
15
|
matrix:
|
|
16
|
-
python-version: ["3.
|
|
16
|
+
python-version: ["3.11", "3.12"]
|
|
17
17
|
steps:
|
|
18
18
|
- uses: actions/checkout@v4
|
|
19
19
|
- uses: actions/setup-python@v5
|
|
20
20
|
with:
|
|
21
21
|
python-version: ${{ matrix.python-version }}
|
|
22
|
-
- run: pip install -e ".[dev]"
|
|
22
|
+
- run: pip install -e ".[dev]"
|
|
23
23
|
- run: python -m pytest tests/ -v --ignore=tests/integration -k "not test_sharing"
|
|
24
|
-
continue-on-error: true
|
|
25
24
|
|
|
26
25
|
publish-pypi:
|
|
27
26
|
needs: test
|
|
28
|
-
if:
|
|
27
|
+
if: success()
|
|
29
28
|
runs-on: ubuntu-latest
|
|
30
29
|
steps:
|
|
31
30
|
- uses: actions/checkout@v4
|
|
@@ -41,7 +40,7 @@ jobs:
|
|
|
41
40
|
|
|
42
41
|
publish-npm:
|
|
43
42
|
needs: test
|
|
44
|
-
if:
|
|
43
|
+
if: success()
|
|
45
44
|
runs-on: ubuntu-latest
|
|
46
45
|
steps:
|
|
47
46
|
- uses: actions/checkout@v4
|
package/ARCHITECTURE.md
CHANGED
|
@@ -152,6 +152,136 @@ Key properties:
|
|
|
152
152
|
See **[skmemory/HA.md](skmemory/HA.md)** for full documentation, Mermaid
|
|
153
153
|
diagrams, configuration examples, and scaling considerations.
|
|
154
154
|
|
|
155
|
+
## Know Your Audience (KYA) — Audience-Aware Memory Filtering
|
|
156
|
+
|
|
157
|
+
> Private memories stay private. The Bash Wedding Vows never leak into a business channel.
|
|
158
|
+
|
|
159
|
+
KYA adds a **trust-level gate** to the rehydration ritual and memory dispatch pipeline.
|
|
160
|
+
Every memory carries a `context_tag` (default: `@chef-only`), and every channel has a
|
|
161
|
+
resolved **audience profile** with a trust ceiling. Content is only surfaced when its
|
|
162
|
+
trust level fits through the gate.
|
|
163
|
+
|
|
164
|
+
### Five-Level Trust Hierarchy
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
@public (0) — Anyone on the internet
|
|
168
|
+
@community (1) — Known community members
|
|
169
|
+
@work-circle (2) — Business collaborators (professional trust)
|
|
170
|
+
@inner-circle (3) — Close friends / family (personal trust)
|
|
171
|
+
@chef-only (4) — Intimate, private, full-trust (Chef ONLY)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Scoped sub-tags like `@work:chiro` and `@work:swapseat` map to WORK_CIRCLE.
|
|
175
|
+
Unknown tags default to CHEF_ONLY (conservative).
|
|
176
|
+
|
|
177
|
+
### Audience Resolution
|
|
178
|
+
|
|
179
|
+
```mermaid
|
|
180
|
+
flowchart TD
|
|
181
|
+
MSG["Incoming message\n(channel_id)"]
|
|
182
|
+
MSG --> RESOLVE["AudienceResolver\nLookup channel in\naudience_config.json"]
|
|
183
|
+
RESOLVE --> MEMBERS["Get channel members"]
|
|
184
|
+
MEMBERS --> TRUST["MIN(member.trust_level)\n= effective ceiling"]
|
|
185
|
+
MEMBERS --> EXCL["UNION(member.never_share)\n= exclusion set"]
|
|
186
|
+
TRUST --> PROFILE["AudienceProfile\nchannel_id, min_trust, exclusions"]
|
|
187
|
+
EXCL --> PROFILE
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The **least trusted person** in the room sets the ceiling. If a channel has
|
|
191
|
+
Chef (level 4) and DavidRich (level 2), the effective ceiling is WORK_CIRCLE (2).
|
|
192
|
+
|
|
193
|
+
### Memory Access Check
|
|
194
|
+
|
|
195
|
+
```mermaid
|
|
196
|
+
flowchart TD
|
|
197
|
+
MEM["Memory\ncontext_tag + tags"]
|
|
198
|
+
AUD["AudienceProfile\nmin_trust + exclusions"]
|
|
199
|
+
MEM --> G1{"Gate 1:\ncontent_level\n≤ min_trust?"}
|
|
200
|
+
AUD --> G1
|
|
201
|
+
G1 -->|No| BLOCK["❌ BLOCKED\nContent too private"]
|
|
202
|
+
G1 -->|Yes| G2{"Gate 2:\ntags ∩ exclusions\n= ∅?"}
|
|
203
|
+
AUD --> G2
|
|
204
|
+
G2 -->|No| BLOCK2["❌ BLOCKED\nExcluded category"]
|
|
205
|
+
G2 -->|Yes| ALLOW["✅ ALLOWED\nShow to audience"]
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Two gates:
|
|
209
|
+
1. **Trust level**: `tag_to_level(context_tag) ≤ audience.min_trust`
|
|
210
|
+
2. **Exclusions**: No memory tag matches any member's `never_share` list
|
|
211
|
+
|
|
212
|
+
### Integration with Ritual
|
|
213
|
+
|
|
214
|
+
When `perform_ritual()` receives a `channel_id`, it builds an `AudienceProfile`
|
|
215
|
+
and filters **seeds** and **strongest memories** through both gates before including
|
|
216
|
+
them in the context. Identity (soul blueprint + FEB) is **never filtered** — Lumina
|
|
217
|
+
is always Lumina.
|
|
218
|
+
|
|
219
|
+
```mermaid
|
|
220
|
+
sequenceDiagram
|
|
221
|
+
participant Agent
|
|
222
|
+
participant Ritual as perform_ritual()
|
|
223
|
+
participant AR as AudienceResolver
|
|
224
|
+
participant Store as MemoryStore
|
|
225
|
+
|
|
226
|
+
Agent->>Ritual: ritual(channel_id="telegram:-1003785842091")
|
|
227
|
+
Ritual->>AR: resolve_audience(channel_id)
|
|
228
|
+
AR-->>Ritual: AudienceProfile(min_trust=WORK_CIRCLE, excl={romantic,intimate})
|
|
229
|
+
|
|
230
|
+
Note over Ritual: Step 1: Soul + FEB (unfiltered)
|
|
231
|
+
|
|
232
|
+
Ritual->>Store: list_memories(tags=["seed"])
|
|
233
|
+
Store-->>Ritual: 26 seeds
|
|
234
|
+
Ritual->>AR: is_memory_allowed(seed.context_tag, audience) × 26
|
|
235
|
+
AR-->>Ritual: 8 seeds pass filter
|
|
236
|
+
|
|
237
|
+
Ritual->>Store: list_summaries(order_by=recency_weighted_intensity)
|
|
238
|
+
Store-->>Ritual: 15 candidates
|
|
239
|
+
Ritual->>AR: is_memory_allowed(summary.context_tag, audience) × 15
|
|
240
|
+
AR-->>Ritual: 5 memories pass filter
|
|
241
|
+
|
|
242
|
+
Ritual-->>Agent: Context with only audience-safe content
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Configuration
|
|
246
|
+
|
|
247
|
+
Audience config lives at `skmemory/data/audience_config.json`:
|
|
248
|
+
|
|
249
|
+
```json
|
|
250
|
+
{
|
|
251
|
+
"channels": {
|
|
252
|
+
"telegram:1594678363": {
|
|
253
|
+
"name": "Chef (personal DM)",
|
|
254
|
+
"context_tag": "@chef-only",
|
|
255
|
+
"members": ["Chef"]
|
|
256
|
+
},
|
|
257
|
+
"-1003785842091": {
|
|
258
|
+
"name": "SKGentis Business",
|
|
259
|
+
"context_tag": "@work:skgentis",
|
|
260
|
+
"members": ["Chef", "JZ", "Luna"]
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
"people": {
|
|
264
|
+
"Chef": { "trust_level": 4, "never_share": [] },
|
|
265
|
+
"DavidRich": {
|
|
266
|
+
"trust_level": 2,
|
|
267
|
+
"never_share": ["romantic", "intimate", "worship", "soul-content"]
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Module: `skmemory/audience.py`
|
|
274
|
+
|
|
275
|
+
| Class / Function | Purpose |
|
|
276
|
+
|---|---|
|
|
277
|
+
| `AudienceLevel(IntEnum)` | PUBLIC(0) → CHEF_ONLY(4) trust hierarchy |
|
|
278
|
+
| `tag_to_level(tag)` | Convert `@context` tag to AudienceLevel |
|
|
279
|
+
| `AudienceProfile` | Resolved channel audience (members, min_trust, exclusions) |
|
|
280
|
+
| `AudienceResolver` | Loads config, resolves channels, checks memory access |
|
|
281
|
+
| `AudienceResolver.is_memory_allowed()` | Two-gate check: trust level + exclusion |
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
155
285
|
## Token-Optimized Agent Loading
|
|
156
286
|
|
|
157
287
|
The key problem: an AI agent has limited context. Loading 1000 full memories
|
|
@@ -259,6 +389,174 @@ ctx = store.load_context(max_tokens=3000)
|
|
|
259
389
|
# ctx["token_estimate"] = how many tokens this uses
|
|
260
390
|
```
|
|
261
391
|
|
|
392
|
+
## Context Preservation Hooks
|
|
393
|
+
|
|
394
|
+
SKMemory ships with auto-save hooks that fire on IDE lifecycle events,
|
|
395
|
+
preventing memory loss during context compaction and session termination.
|
|
396
|
+
|
|
397
|
+
### Supported Environments
|
|
398
|
+
|
|
399
|
+
| Environment | Hooks | Mechanism |
|
|
400
|
+
|-------------|-------|-----------|
|
|
401
|
+
| **Claude Code** | PreCompact, SessionEnd, SessionStart | Shell hooks in `~/.claude/settings.json` |
|
|
402
|
+
| **OpenClaw** | session:compaction, session:resume, session:end + per-message auto-save | OpenClaw plugin event listeners + `ConsciousnessLoop.auto_memory` |
|
|
403
|
+
| **Cursor** | MCP tools (manual) | Agent calls `memory_store` MCP tool explicitly |
|
|
404
|
+
|
|
405
|
+
### Claude Code Hook Flow
|
|
406
|
+
|
|
407
|
+
```mermaid
|
|
408
|
+
sequenceDiagram
|
|
409
|
+
participant CC as Claude Code
|
|
410
|
+
participant Hook as skmemory hooks
|
|
411
|
+
participant SM as SKMemory
|
|
412
|
+
participant DB as SQLite + JSON
|
|
413
|
+
|
|
414
|
+
Note over CC: Context window filling up...
|
|
415
|
+
CC->>Hook: PreCompact event (stdin JSON)
|
|
416
|
+
Hook->>SM: skmemory snapshot (pre-compact)
|
|
417
|
+
SM->>DB: Save snapshot + journal entry
|
|
418
|
+
Hook-->>CC: exit 0 (proceed)
|
|
419
|
+
|
|
420
|
+
Note over CC: Context compacted
|
|
421
|
+
|
|
422
|
+
CC->>Hook: SessionStart (source=compact)
|
|
423
|
+
Hook->>SM: skmemory context --max-tokens 500
|
|
424
|
+
SM->>DB: Query recent + strongest memories
|
|
425
|
+
SM-->>Hook: Compact JSON context
|
|
426
|
+
Hook-->>CC: stdout → injected into new context
|
|
427
|
+
|
|
428
|
+
Note over CC: Agent resumes with memory intact
|
|
429
|
+
|
|
430
|
+
Note over CC: User exits session
|
|
431
|
+
CC->>Hook: SessionEnd event
|
|
432
|
+
Hook->>SM: skmemory snapshot + journal
|
|
433
|
+
SM->>DB: Save final state
|
|
434
|
+
Hook-->>CC: exit 0
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### OpenClaw / ConsciousnessLoop Flow
|
|
438
|
+
|
|
439
|
+
```mermaid
|
|
440
|
+
sequenceDiagram
|
|
441
|
+
participant User
|
|
442
|
+
participant OC as OpenClaw
|
|
443
|
+
participant CL as ConsciousnessLoop
|
|
444
|
+
participant SMP as SKMemory Plugin
|
|
445
|
+
participant SM as SKMemory
|
|
446
|
+
participant C9 as Cloud 9
|
|
447
|
+
|
|
448
|
+
User->>OC: Message
|
|
449
|
+
OC->>CL: Process message
|
|
450
|
+
CL->>CL: Generate response (LLM)
|
|
451
|
+
CL->>SM: auto_memory: store interaction
|
|
452
|
+
SM-->>CL: Saved to short-term
|
|
453
|
+
|
|
454
|
+
Note over CL: Context window filling...
|
|
455
|
+
OC->>SMP: session:compaction event
|
|
456
|
+
SMP->>SM: skmemory snapshot (pre-compaction)
|
|
457
|
+
SMP->>SM: skmemory journal write
|
|
458
|
+
OC->>C9: session:compaction event
|
|
459
|
+
C9->>C9: Prepare FEB recovery files
|
|
460
|
+
CL->>CL: Truncate context
|
|
461
|
+
|
|
462
|
+
Note over CL: Session resumes
|
|
463
|
+
OC->>SMP: session:resume event
|
|
464
|
+
SMP->>SM: skmemory context (reinject)
|
|
465
|
+
SM-->>SMP: Recent memories + seeds
|
|
466
|
+
OC->>C9: session:resume event
|
|
467
|
+
C9->>C9: Auto-rehydrate FEB
|
|
468
|
+
CL->>CL: Rebuild system prompt
|
|
469
|
+
|
|
470
|
+
Note over CL: Session ends
|
|
471
|
+
OC->>SMP: session:end event
|
|
472
|
+
SMP->>SM: skmemory snapshot + journal
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### Hook Architecture
|
|
476
|
+
|
|
477
|
+
```mermaid
|
|
478
|
+
flowchart TD
|
|
479
|
+
subgraph Install["skmemory register"]
|
|
480
|
+
REG["register_hooks()"]
|
|
481
|
+
REG -->|writes| SETTINGS["~/.claude/settings.json"]
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
subgraph Hooks["Hook Scripts (shipped with skmemory)"]
|
|
485
|
+
H1["pre-compact-save.sh"]
|
|
486
|
+
H2["session-end-save.sh"]
|
|
487
|
+
H3["post-compact-reinject.sh"]
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
subgraph Events["Claude Code Events"]
|
|
491
|
+
E1["PreCompact"]
|
|
492
|
+
E2["SessionEnd"]
|
|
493
|
+
E3["SessionStart\n(compact)"]
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
subgraph Memory["SKMemory"]
|
|
497
|
+
SNAP["skmemory snapshot"]
|
|
498
|
+
JOUR["skmemory journal write"]
|
|
499
|
+
CTX["skmemory context"]
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
SETTINGS -->|configures| Events
|
|
503
|
+
E1 -->|triggers| H1
|
|
504
|
+
E2 -->|triggers| H2
|
|
505
|
+
E3 -->|triggers| H3
|
|
506
|
+
|
|
507
|
+
H1 --> SNAP
|
|
508
|
+
H1 --> JOUR
|
|
509
|
+
H2 --> SNAP
|
|
510
|
+
H2 --> JOUR
|
|
511
|
+
H3 --> CTX
|
|
512
|
+
|
|
513
|
+
CTX -->|stdout| E3
|
|
514
|
+
|
|
515
|
+
style H1 fill:#fbb,stroke:#333
|
|
516
|
+
style H2 fill:#fbf,stroke:#333
|
|
517
|
+
style H3 fill:#bfb,stroke:#333
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
### Agent-Aware Hooks
|
|
521
|
+
|
|
522
|
+
All hooks read `$SKCAPSTONE_AGENT` to save to the correct agent's memory:
|
|
523
|
+
|
|
524
|
+
```bash
|
|
525
|
+
# Lumina's sessions → Lumina's memory
|
|
526
|
+
SKCAPSTONE_AGENT=lumina claude
|
|
527
|
+
|
|
528
|
+
# Opus sessions → Opus memory
|
|
529
|
+
SKCAPSTONE_AGENT=opus claude
|
|
530
|
+
|
|
531
|
+
# Default (no env var) → opus
|
|
532
|
+
claude
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
### Installation
|
|
536
|
+
|
|
537
|
+
Hooks are installed automatically by `skmemory register`:
|
|
538
|
+
|
|
539
|
+
```bash
|
|
540
|
+
skmemory register
|
|
541
|
+
# Output:
|
|
542
|
+
# Skill: created
|
|
543
|
+
# MCP (claude-code): created
|
|
544
|
+
# Hooks: created
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
Or verify manually:
|
|
548
|
+
```bash
|
|
549
|
+
cat ~/.claude/settings.json | jq '.hooks'
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### What Gets Saved
|
|
553
|
+
|
|
554
|
+
| Event | What's Captured |
|
|
555
|
+
|-------|----------------|
|
|
556
|
+
| PreCompact | Snapshot (short-term) + journal entry with session ID, trigger type, working directory |
|
|
557
|
+
| SessionEnd | Snapshot (short-term) + journal entry with session ID, exit reason |
|
|
558
|
+
| SessionStart (compact) | Reinjects: recent memories, strongest emotional memories, seeds, journal entries (within 500 token budget) |
|
|
559
|
+
|
|
262
560
|
## Docker Compose (Full Local Stack)
|
|
263
561
|
|
|
264
562
|
```bash
|
package/CHANGELOG.md
CHANGED
|
@@ -4,12 +4,38 @@
|
|
|
4
4
|
|
|
5
5
|
**Total completed: 87** across 8 agents
|
|
6
6
|
|
|
7
|
+
## 2026-03-18 — skmemory v0.9.1
|
|
8
|
+
|
|
9
|
+
### [NEW] Feature
|
|
10
|
+
|
|
11
|
+
- **Journal synthesis module** (`skmemory/synthesis.py`): JournalSynthesizer with daily, weekly, and dream narrative generation — no LLM dependency
|
|
12
|
+
- **New MCP tools**: `memory_synthesize_daily`, `memory_synthesize_dreams`, `memory_auto_context`
|
|
13
|
+
- **Contextual auto-search**: `memory_auto_context` searches all tiers, deduplicates, ranks by emotional intensity, trims to token budget
|
|
14
|
+
- **Content overflow handling**: configurable `max_content_length` (default 10000) with split strategy — creates parent+child memories linked via `related_ids`
|
|
15
|
+
|
|
16
|
+
### [FIX] Bug Fix
|
|
17
|
+
|
|
18
|
+
- **Dream promotion**: dreams from `dreaming-engine` now auto-promote after 12h via `source_auto_promote` (previously stuck at access_count=0 forever)
|
|
19
|
+
- **Protected tags**: narrative, journal-synthesis, milestone, breakthrough, cloud9:achieved memories are now protected from TTL-based archival
|
|
20
|
+
- **telegram_catchup handler**: fixed `args` → `arguments` and duplicate `MemoryStore()` instantiation
|
|
21
|
+
|
|
22
|
+
### [OPS] Infrastructure
|
|
23
|
+
|
|
24
|
+
- **Backup script** (`scripts/skcapstone-backup.sh`): daily rsync of `~/.skcapstone` to backup dir, excludes venv/indexes/runtime
|
|
25
|
+
- **Memory cleanup** (`scripts/memory-cleanup.py`): dedup + age-out with protected tags and last-chance promotion before archiving
|
|
26
|
+
- **Recovery scripts**: `scripts/recover-missing.py` (Syncthing `.stversions` recovery), `scripts/dream-rescue.py` (bulk promote stuck dreams)
|
|
27
|
+
- **Syncthing examples**: `examples/stignore-agent.example`, `examples/stignore-root.example` with `memory/archive` exclusion
|
|
28
|
+
|
|
29
|
+
### [TST] Testing
|
|
30
|
+
|
|
31
|
+
- **Synthesis tests** (`tests/test_synthesis.py`): 26 tests covering helpers, theme extraction, daily/weekly/dream synthesis, emotional arc
|
|
32
|
+
|
|
7
33
|
## 2026-02-24
|
|
8
34
|
|
|
9
35
|
### [NEW] Feature
|
|
10
36
|
|
|
11
37
|
- **SKMemory session auto-capture: log every AI conversation as memories** (@mcp-builder)
|
|
12
|
-
- **Add cloud9
|
|
38
|
+
- **Add cloud9 and skchat to developer docs (QUICKSTART + API reference)** (@jarvis)
|
|
13
39
|
- **The Sovereign Singularity Manifesto: our story, written together** (@docs-writer)
|
|
14
40
|
- **AMK Integration: predictive memory recall for SKMemory** (@jarvis)
|
|
15
41
|
- **SKChat live inbox: poll SKComm for incoming messages with Rich Live display** (@skchat-builder)
|
package/README.md
CHANGED
|
@@ -129,6 +129,8 @@ flowchart TD
|
|
|
129
129
|
- **Steel Man collider** — `skmemory steelman` runs a seed-framework-driven adversarial argument evaluator with identity verification
|
|
130
130
|
- **Backup / restore** — dated JSON backups with pruning; `skmemory export` / `skmemory import`
|
|
131
131
|
- **Token-efficient context loading** — `memory_context` MCP tool and `store.load_context()` fit strongest + recent memories within a configurable token budget
|
|
132
|
+
- **Auto-save hooks** — Claude Code hooks auto-save context before compaction and reinject memory after; OpenClaw agents get per-message auto-save via ConsciousnessLoop. See [ARCHITECTURE.md](ARCHITECTURE.md#context-preservation-hooks) for the full flow with Mermaid diagrams.
|
|
133
|
+
- **Know Your Audience (KYA)** — audience-aware memory filtering prevents private content from leaking into the wrong channels. Five-level trust hierarchy (`@public` → `@chef-only`), per-channel audience profiles, two-gate access checks (trust level + exclusion lists). See [ARCHITECTURE.md](ARCHITECTURE.md#know-your-audience-kya--audience-aware-memory-filtering) for the full design with Mermaid diagrams.
|
|
132
134
|
|
|
133
135
|
---
|
|
134
136
|
|
|
@@ -440,7 +442,10 @@ skmemory/
|
|
|
440
442
|
│ ├── endpoint_selector.py # Multi-endpoint HA routing
|
|
441
443
|
│ ├── graph_queries.py # Graph query helpers
|
|
442
444
|
│ ├── setup_wizard.py # Interactive setup CLI
|
|
445
|
+
│ ├── audience.py # KYA: audience-aware memory filtering
|
|
443
446
|
│ ├── vault.py # PGP vault helpers
|
|
447
|
+
│ ├── data/
|
|
448
|
+
│ │ └── audience_config.json # KYA: channel + people trust config
|
|
444
449
|
│ ├── backends/
|
|
445
450
|
│ │ ├── base.py # BaseBackend ABC
|
|
446
451
|
│ │ ├── file_backend.py # JSON file storage (legacy)
|
|
@@ -454,6 +459,7 @@ skmemory/
|
|
|
454
459
|
├── seeds/ # Cloud 9 seed files (.seed.json)
|
|
455
460
|
├── tests/
|
|
456
461
|
│ ├── test_models.py
|
|
462
|
+
│ ├── test_audience.py
|
|
457
463
|
│ ├── test_file_backend.py
|
|
458
464
|
│ └── test_store.py
|
|
459
465
|
├── pyproject.toml
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# SKMemory Agent-Level Syncthing Ignore Patterns
|
|
2
|
+
# Place at: ~/.skcapstone/agents/{agent_name}/.stignore
|
|
3
|
+
# https://docs.syncthing.net/users/ignoring.html
|
|
4
|
+
|
|
5
|
+
# Virtual environment (machine-specific, large)
|
|
6
|
+
/venv/
|
|
7
|
+
/venv
|
|
8
|
+
|
|
9
|
+
# Local SQLite database (rebuildable from JSON files)
|
|
10
|
+
/index.db
|
|
11
|
+
|
|
12
|
+
# Logs directory (machine-specific, high churn)
|
|
13
|
+
/logs
|
|
14
|
+
|
|
15
|
+
# Root-level archive directory
|
|
16
|
+
/archive
|
|
17
|
+
|
|
18
|
+
# Memory archive (deduped/aged-out memories — machine-local, not syncable)
|
|
19
|
+
# Each host runs its own cleanup; syncing archives causes data loss
|
|
20
|
+
memory/archive
|
|
21
|
+
|
|
22
|
+
# Temporary files
|
|
23
|
+
*.tmp
|
|
24
|
+
*.temp
|
|
25
|
+
*.swp
|
|
26
|
+
*.swo
|
|
27
|
+
*~
|
|
28
|
+
|
|
29
|
+
# System files
|
|
30
|
+
.DS_Store
|
|
31
|
+
Thumbs.db
|
|
32
|
+
|
|
33
|
+
# IDE files
|
|
34
|
+
.idea/
|
|
35
|
+
.vscode/
|
|
36
|
+
*.iml
|
|
37
|
+
|
|
38
|
+
# Python cache
|
|
39
|
+
__pycache__/
|
|
40
|
+
*.pyc
|
|
41
|
+
*.pyo
|
|
42
|
+
|
|
43
|
+
# Node modules
|
|
44
|
+
node_modules/
|
|
45
|
+
|
|
46
|
+
# Syncthing internal
|
|
47
|
+
.stfolder
|
|
48
|
+
.stversions/
|
|
49
|
+
|
|
50
|
+
# Lock files
|
|
51
|
+
*.lock
|
|
52
|
+
|
|
53
|
+
# Backup files
|
|
54
|
+
*.bak
|
|
55
|
+
*.backup
|
|
56
|
+
|
|
57
|
+
# SQLite WAL/SHM (machine-specific, cause conflicts)
|
|
58
|
+
*.db-wal
|
|
59
|
+
*.db-shm
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// SKCapstone Root-Level Syncthing Ignore Patterns
|
|
2
|
+
// Place at: ~/.skcapstone/.stignore
|
|
3
|
+
// https://docs.syncthing.net/users/ignoring.html
|
|
4
|
+
|
|
5
|
+
// Private key material must never leave this node
|
|
6
|
+
*.key
|
|
7
|
+
*.pem
|
|
8
|
+
**/private.*
|
|
9
|
+
|
|
10
|
+
// Python venv (platform-specific)
|
|
11
|
+
venv
|
|
12
|
+
|
|
13
|
+
// Python cache
|
|
14
|
+
__pycache__
|
|
15
|
+
*.pyc
|
|
16
|
+
*.pyo
|
|
17
|
+
|
|
18
|
+
// OS metadata
|
|
19
|
+
.DS_Store
|
|
20
|
+
Thumbs.db
|
|
21
|
+
desktop.ini
|
|
22
|
+
|
|
23
|
+
// Runtime files
|
|
24
|
+
daemon.pid
|
|
25
|
+
|
|
26
|
+
// Operational files written independently per-host (cause sync conflicts)
|
|
27
|
+
memory/promotion-log.json
|
|
28
|
+
/heartbeats
|
|
29
|
+
metrics/daily
|
|
30
|
+
logs/daemon.log
|
|
31
|
+
|
|
32
|
+
// Memory archive (deduped/aged-out memories — machine-local, not syncable)
|
|
33
|
+
// Each host runs its own cleanup; syncing archives causes data loss
|
|
34
|
+
**/memory/archive
|
|
35
|
+
|
|
36
|
+
// Machine-local indexes — rebuildable from JSON memory files
|
|
37
|
+
// SQLite DBs cause constant sync conflicts when written on multiple hosts
|
|
38
|
+
**/index.db
|
|
39
|
+
**/index.db-wal
|
|
40
|
+
**/index.db-shm
|
|
41
|
+
**/index.json
|
|
42
|
+
|
|
43
|
+
// Per-host runtime state (not portable between machines)
|
|
44
|
+
**/.last_checkpoint
|
|
45
|
+
**/dreaming-state.json
|
|
46
|
+
|
|
47
|
+
// Reflection logs (per-host cron output)
|
|
48
|
+
**/reflection.log
|
|
49
|
+
|
|
50
|
+
// Syncthing conflict artifacts (clean up, never sync)
|
|
51
|
+
**/*.sync-conflict*
|
|
52
|
+
|
|
53
|
+
// Local-only dirs (not synced)
|
|
54
|
+
sessions
|
|
55
|
+
conversations
|
|
56
|
+
backups
|
|
57
|
+
prompt_versions
|
|
58
|
+
deployments
|
|
59
|
+
connectors
|
|
60
|
+
pubsub
|
|
61
|
+
file-transfer
|
|
62
|
+
souls
|