@dzhechkov/keysarium 1.2.0 → 1.3.0

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.
@@ -2,6 +2,8 @@
2
2
 
3
3
  Core protocol for persistent memory in the Keysarium pipeline. Provides `memory_query()` before tasks and `memory_store()` after tasks.
4
4
 
5
+ **Protocol version: 1.1** — adds 2-tier index, record lifecycle (HOT/WARM/COLD/PURGE), and brain container manifest.
6
+
5
7
  ## Memory Namespace
6
8
 
7
9
  All memory files live in `.keysarium/memory/`:
@@ -9,13 +11,18 @@ All memory files live in `.keysarium/memory/`:
9
11
  ```
10
12
  .keysarium/memory/
11
13
  ├── config.json ← Global configuration
14
+ ├── index.json ← 2-tier index (v1.1)
12
15
  ├── _patterns/
13
16
  │ └── domain-patterns.json ← Detected domain patterns
14
17
  ├── _stats/
15
- │ └── reward-summary.json ← Aggregate statistics
18
+ │ ├── reward-summary.json ← Aggregate statistics
19
+ │ └── imported-baselines.json ← Imported reward baselines
16
20
  ├── {domain}/ ← banking | retail | enterprise | healthcare
17
- │ └── {case-slug}/
18
- │ └── {phase}_{timestamp}.json ← Individual reward records
21
+ │ ├── {case-slug}/
22
+ │ │ └── {phase}_{timestamp}.json ← HOT/WARM reward records
23
+ │ └── _archive/ ← COLD compressed records (v1.1)
24
+ │ └── {case-slug}/
25
+ │ └── {phase}_{timestamp}.json ← Archived records
19
26
  ```
20
27
 
21
28
  ## Configuration
@@ -24,7 +31,7 @@ All memory files live in `.keysarium/memory/`:
24
31
 
25
32
  ```json
26
33
  {
27
- "version": "1.0",
34
+ "version": "1.1",
28
35
  "retention_days": 90,
29
36
  "max_results_per_query": 10,
30
37
  "enabled": true,
@@ -34,10 +41,62 @@ All memory files live in `.keysarium/memory/`:
34
41
  "good": 0.7,
35
42
  "needs_work": 0.3,
36
43
  "failed": 0.0
44
+ },
45
+ "tier_hot_days": 30,
46
+ "tier_warm_days": 90,
47
+ "tier_cold_days": 180
48
+ }
49
+ ```
50
+
51
+ **Tier fields (v1.1):** If `tier_hot_days` is absent, fall back to v1.0 behavior (flat `retention_days` with no tiering). When present, `retention_days` is ignored in favor of the tier thresholds.
52
+
53
+ ## Index File (v1.1)
54
+
55
+ The index provides a compact catalog of all records, enabling targeted reads instead of full directory scans.
56
+
57
+ ### index.json Schema
58
+
59
+ ```json
60
+ {
61
+ "version": "1.0",
62
+ "last_updated": "2026-03-02T14:00:00Z",
63
+ "record_count": 47,
64
+ "by_domain": {
65
+ "banking": {
66
+ "count": 23,
67
+ "slugs": ["case-a", "case-b"],
68
+ "avg_reward": 0.82
69
+ }
70
+ },
71
+ "by_phase": {
72
+ "phase-0": { "count": 8, "avg_reward": 0.91 },
73
+ "phase-2": { "count": 12, "avg_reward": 0.65 }
74
+ },
75
+ "by_skill": {
76
+ "goap-research-ed25519": { "count": 10, "avg_reward": 0.78 }
77
+ },
78
+ "records": {
79
+ "bank_kc_automation_phase-2_2026-03-01T12-30-00": {
80
+ "domain": "banking",
81
+ "phase": "phase-2",
82
+ "slug": "bank_kc_automation",
83
+ "reward": 0.7,
84
+ "skill": "goap-research-ed25519",
85
+ "tier": "hot",
86
+ "file": "banking/bank_kc_automation/phase-2_2026-03-01T12-30-00.json",
87
+ "expires_at": "2026-08-28T12:30:00Z"
88
+ }
37
89
  }
38
90
  }
39
91
  ```
40
92
 
93
+ ### Index Behavior
94
+
95
+ - **Created:** On first `memory_store()` call when tier config is present (or `index.json` already exists)
96
+ - **Updated:** On every `memory_store()`, archive, and purge operation
97
+ - **Fallback:** If missing, `memory_query()` uses v1.0 full-scan algorithm
98
+ - **Rebuild:** If corrupted, delete `index.json` — it will be recreated on next `memory_store()`
99
+
41
100
  ## Protocol: memory_query(context)
42
101
 
43
102
  Call at the **start** of each pipeline phase to load relevant historical patterns.
@@ -56,12 +115,22 @@ Call at the **start** of each pipeline phase to load relevant historical pattern
56
115
  ### Algorithm
57
116
 
58
117
  1. **Check enabled:** Read `.keysarium/memory/config.json`. If `enabled` is false or directory does not exist, return empty list.
59
- 2. **Resolve path:** Construct `.keysarium/memory/{domain}/` (scan all slugs, not just current).
60
- 3. **Scan records:** Read all `{phase}_*.json` files matching the requested phase across all slugs in the domain.
118
+ 2. **Read index (v1.1):** If `.keysarium/memory/index.json` exists, read it and filter `records` entries by `domain` + `phase`. Go to step 2a. If index does not exist, fall back to step 3 (v1.0 full scan).
119
+ - 2a. **Index hit:** If filtered record count ≤ `max_results_per_query`, read only those files by `file` path (targeted read). Go to step 4.
120
+ - 2b. **Index overflow:** If filtered count > limit, rank by `reward` from index entries, select top-N `file` paths, read those files. Go to step 4.
121
+ 3. **Full scan (fallback):** Construct `.keysarium/memory/{domain}/` (scan all slugs). Read all `{phase}_*.json` files matching the requested phase.
61
122
  4. **Filter expired:** Exclude records where `expires_at < current_date`.
62
- 5. **Sort:** By `reward` DESC, then `timestamp` DESC.
63
- 6. **Limit:** Return top `max_results_per_query` records (default 10).
64
- 7. **Enrich:** Also load `.keysarium/memory/_patterns/domain-patterns.json` for matching domain patterns.
123
+ 5. **Archive old records (v1.1):** If tier config is present, check record ages. For records older than `tier_warm_days`:
124
+ - Read full record
125
+ - Generate `summary` from `reward_reason` + `outcome.checkpoint_response` (first 200 chars)
126
+ - Write compressed record to `.keysarium/memory/{domain}/_archive/{slug}/{filename}`
127
+ - Delete original file from active directory
128
+ - Update `index.json`: set `tier` to `"cold"`, update `file` path
129
+ - Log: "Archived {count} records to cold storage in {domain}"
130
+ 6. **Purge ancient records (v1.1):** Delete records from `_archive/` older than `tier_cold_days`. In v1.0 mode, delete records where `expires_at < current_date`. Update `index.json`. Log: "Purged {count} expired records from {domain}"
131
+ 7. **Sort:** By `reward` DESC, then `timestamp` DESC. HOT and WARM records first; COLD records included only if result count < `max_results_per_query`.
132
+ 8. **Limit:** Return top `max_results_per_query` records (default 10).
133
+ 9. **Enrich:** Also load `.keysarium/memory/_patterns/domain-patterns.json` for matching domain patterns.
65
134
 
66
135
  ### Output
67
136
 
@@ -136,17 +205,25 @@ Call at each **checkpoint** after the user responds, to persist the phase outcom
136
205
 
137
206
  1. **Ensure directory exists:** Create `.keysarium/memory/{domain}/{slug}/` if it does not exist.
138
207
  2. **Build record:** Construct full RewardRecord JSON from input.
139
- 3. **Compute expires_at:** `current_date + retention_days` (from config, default 90 days).
208
+ 3. **Compute expires_at:** If tier config is present, use `tier_cold_days` (default 180 days). Otherwise, use `retention_days` (default 90 days). Formula: `current_date + threshold`.
140
209
  4. **Generate filename:** `{phase}_{ISO-timestamp}.json` (e.g., `phase-2_2026-03-01T12-30-00.json`).
141
210
  5. **Write file:** Write JSON to `.keysarium/memory/{domain}/{slug}/{filename}`.
142
- 6. **Log:** "Stored reward {reward} ({reward_label}) for {phase} of {slug}"
211
+ 6. **Update index (v1.1):** Read `.keysarium/memory/index.json` (or create if absent and tier config is present):
212
+ - Add record entry to `records` map: key = record id, value = `{domain, phase, slug, reward, skill, tier: "hot", file, expires_at}`
213
+ - Increment `record_count`
214
+ - Update `by_domain` aggregate: increment count, add slug if new, recalculate `avg_reward`
215
+ - Update `by_phase` aggregate: increment count, recalculate `avg_reward`
216
+ - Update `by_skill` aggregate: increment count, recalculate `avg_reward`
217
+ - Set `last_updated` to current timestamp
218
+ - Write updated `index.json`
219
+ 7. **Log:** "Stored reward {reward} ({reward_label}) for {phase} of {slug}"
143
220
 
144
221
  ### RewardRecord JSON Schema
145
222
 
146
223
  ```json
147
224
  {
148
225
  "id": "bank_kc_automation_phase-2_2026-03-01T12-30-00",
149
- "version": "1.0",
226
+ "version": "1.1",
150
227
  "timestamp": "2026-03-01T12:30:00Z",
151
228
  "case_slug": "bank_kc_automation",
152
229
  "domain": "banking",
@@ -171,10 +248,45 @@ Call at each **checkpoint** after the user responds, to persist the phase outcom
171
248
  "promise_emitted": "RESEARCH_PARANOID_PASSED"
172
249
  },
173
250
  "promise_tag": "RESEARCH_PARANOID_PASSED",
174
- "expires_at": "2026-05-30T12:30:00Z"
251
+ "expires_at": "2026-08-28T12:30:00Z"
175
252
  }
176
253
  ```
177
254
 
255
+ ## Record Lifecycle (v1.1)
256
+
257
+ Records transition through tiers based on age:
258
+
259
+ | Tier | Age Range | Location | Fields |
260
+ |------|-----------|----------|--------|
261
+ | **HOT** | 0 – 30 days | `{domain}/{slug}/` | All fields |
262
+ | **WARM** | 30 – 90 days | `{domain}/{slug}/` | All fields (deprioritized in search) |
263
+ | **COLD** | 90 – 180 days | `{domain}/_archive/{slug}/` | Compressed (see below) |
264
+ | **PURGE** | > 180 days | Deleted | — |
265
+
266
+ Tier thresholds are configurable via `config.json` fields: `tier_hot_days`, `tier_warm_days`, `tier_cold_days`.
267
+
268
+ ### COLD Record Schema (compressed)
269
+
270
+ ```json
271
+ {
272
+ "id": "bank_kc_automation_phase-2_2026-01-01T12-00-00",
273
+ "phase": "phase-2",
274
+ "domain": "banking",
275
+ "slug": "bank_kc_automation",
276
+ "reward": 0.7,
277
+ "reward_label": "good",
278
+ "skill_used": "goap-research-ed25519",
279
+ "promise_tag": "RESEARCH_PARANOID_PASSED",
280
+ "summary": "User requested minor edits to competitor analysis section. ok, but expand the FinTech competitor section",
281
+ "archived_at": "2026-03-02T14:00:00Z",
282
+ "original_timestamp": "2026-01-01T12:00:00Z"
283
+ }
284
+ ```
285
+
286
+ ### Backward Compatibility
287
+
288
+ If `tier_hot_days` is NOT present in `config.json`, the lifecycle system is disabled. Records use the v1.0 flat `retention_days` for expiration. No archiving occurs.
289
+
178
290
  ## Reward Assignment Rules
179
291
 
180
292
  The reward score is determined by the user's response at the checkpoint:
@@ -193,15 +305,6 @@ The reward score is determined by the user's response at the checkpoint:
193
305
  - **Positive feedback with minor note** ("great, just fix the typo in section 3") = 1.0
194
306
  - **No explicit response** (session ends) = do not store (no record created)
195
307
 
196
- ## Purge Protocol
197
-
198
- To prevent unbounded growth, expired records should be cleaned up:
199
-
200
- 1. **Trigger:** At each `memory_query()` call, check for expired records
201
- 2. **Scan:** Within the queried domain directory, find records where `expires_at < current_date`
202
- 3. **Delete:** Remove expired JSON files
203
- 4. **Log:** "Purged {count} expired records from {domain}"
204
-
205
308
  ## Error Handling
206
309
 
207
310
  | Error | Behavior |
@@ -211,6 +314,8 @@ To prevent unbounded growth, expired records should be cleaned up:
211
314
  | Malformed JSON file | Skip that record, log warning, continue |
212
315
  | Write fails (permissions, disk) | Log error, continue pipeline without storing |
213
316
  | Domain not in `known_domains` | Use "unknown" as domain directory |
317
+ | `index.json` corrupted | Delete and rebuild on next `memory_store()` call |
318
+ | Archive directory write fails | Log warning, keep record in active directory |
214
319
 
215
320
  ## Integration with Brain Export
216
321