@dzhechkov/keysarium 1.1.2 → 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.
Files changed (62) hide show
  1. package/README.md +7 -2
  2. package/package.json +10 -2
  3. package/templates/.claude/commands/brain-export.md +97 -20
  4. package/templates/.claude/commands/brain-import.md +75 -4
  5. package/templates/.claude/commands/dream.md +101 -0
  6. package/templates/.claude/commands/feature-adr.md +92 -0
  7. package/templates/.claude/commands/init-platform.md +161 -0
  8. package/templates/.claude/commands/learning-stats.md +130 -0
  9. package/templates/.claude/commands/workers.md +140 -0
  10. package/templates/.claude/rules/background-workers.md +72 -0
  11. package/templates/.claude/rules/dream-cycles.md +90 -0
  12. package/templates/.claude/rules/feature-adr-conventions.md +82 -0
  13. package/templates/.claude/rules/reward-learning.md +124 -0
  14. package/templates/.claude/shards/feature-adr.shard.md +98 -0
  15. package/templates/.claude/skills/feature-adr/SKILL.md +252 -0
  16. package/templates/.claude/skills/feature-adr/examples/sample-feature-output.md +257 -0
  17. package/templates/.claude/skills/feature-adr/modules/00-complexity-router.md +114 -0
  18. package/templates/.claude/skills/feature-adr/modules/01-requirements.md +113 -0
  19. package/templates/.claude/skills/feature-adr/modules/02-research.md +92 -0
  20. package/templates/.claude/skills/feature-adr/modules/03-adr.md +135 -0
  21. package/templates/.claude/skills/feature-adr/modules/04-ddd.md +114 -0
  22. package/templates/.claude/skills/feature-adr/modules/05-architecture.md +149 -0
  23. package/templates/.claude/skills/feature-adr/modules/06-implementation-plan.md +129 -0
  24. package/templates/.claude/skills/feature-adr/modules/07-code.md +126 -0
  25. package/templates/.claude/skills/feature-adr/modules/08-qe.md +167 -0
  26. package/templates/.claude/skills/feature-adr/references/adr-template.md +102 -0
  27. package/templates/.claude/skills/feature-adr/references/c4-template.md +120 -0
  28. package/templates/.claude/skills/feature-adr/references/complexity-matrix.md +139 -0
  29. package/templates/.claude/skills/feature-adr/references/qe-checklist.md +86 -0
  30. package/templates/CLAUDE.md +135 -8
  31. package/templates/docs/feature-adr/01-architecture.md +750 -0
  32. package/templates/docs/feature-adr/02-functionality.md +712 -0
  33. package/templates/docs/feature-adr/03-deployment-guide.md +614 -0
  34. package/templates/docs/feature-adr/04-admin-guide.md +564 -0
  35. package/templates/docs/feature-adr/05-user-guide.md +508 -0
  36. package/templates/docs/feature-adr/06-user-flows.md +1101 -0
  37. package/templates/docs/improvement-directions.md +16 -16
  38. package/templates/docs/keysarium/01-deployment-guide.md +21 -12
  39. package/templates/docs/keysarium/02-admin-guide.md +204 -3
  40. package/templates/docs/keysarium/03-user-guide.md +224 -0
  41. package/templates/docs/keysarium/05-architecture.md +181 -0
  42. package/templates/docs/keysarium/06-user-flows.md +235 -0
  43. package/templates/docs/keysarium-core/01-architecture.md +559 -0
  44. package/templates/docs/keysarium-core/02-functionality.md +953 -0
  45. package/templates/docs/keysarium-core/03-deployment-guide.md +625 -0
  46. package/templates/docs/keysarium-core/04-admin-guide.md +529 -0
  47. package/templates/docs/keysarium-core/05-user-guide.md +599 -0
  48. package/templates/docs/keysarium-core/06-user-flows.md +804 -0
  49. package/templates/lib/background-workers.md +278 -0
  50. package/templates/lib/dream-engine.md +460 -0
  51. package/templates/lib/judge-attestation.md +322 -0
  52. package/templates/lib/memory-protocol.md +344 -0
  53. package/templates/lib/platform-adapters.md +100 -0
  54. package/templates/lib/platform-templates/copilot.md +134 -0
  55. package/templates/lib/platform-templates/cursor.md +95 -0
  56. package/templates/lib/platform-templates/opencode.md +155 -0
  57. package/templates/lib/reward-tracker.md +256 -0
  58. package/templates/lib/witness-chain.md +372 -0
  59. package/templates/lib/worker-templates/brain-export.md +187 -0
  60. package/templates/lib/worker-templates/consolidate.md +180 -0
  61. package/templates/lib/worker-templates/dream-cycle.md +154 -0
  62. package/templates/lib/worker-templates/health-check.md +255 -0
@@ -0,0 +1,322 @@
1
+ # Judge Attestation Protocol
2
+
3
+ > Cryptographic proof of BTO judge isolation via SHA-256 hash chain attestations.
4
+
5
+ ## Purpose
6
+
7
+ This protocol defines how BTO judges (Domain Expert, Critic, Completeness Auditor) create cryptographic attestations proving their evaluations were performed independently. Each judge records a hash of its evaluation before seeing other judges' scores. The attestations are chained to provide ordering proof.
8
+
9
+ ## Constants
10
+
11
+ ```
12
+ NULL_HASH = "0000000000000000000000000000000000000000000000000000000000000000"
13
+ ATTESTATION_FILE = ".judge-attestations.json"
14
+ HASH_PREFIX = "sha256:"
15
+ STANDARD_PANEL_SIZE = 3
16
+ HIGH_STAKES_PANEL_SIZE = 5
17
+ ```
18
+
19
+ ## Section 1: Attestation Creation
20
+
21
+ ### Hash Input Construction
22
+
23
+ Each judge's evaluation hash is computed from a deterministic concatenation of:
24
+
25
+ ```
26
+ evaluation_hash = SHA-256(judge_id + "|" + artifact_hash + "|" + score + "|" + rationale_summary)
27
+ ```
28
+
29
+ The pipe character `|` serves as a delimiter to prevent ambiguity in concatenation.
30
+
31
+ **Fields:**
32
+ - `judge_id`: One of `"domain-expert"`, `"critic"`, `"completeness-auditor"` (or `"meta-judge"` for escalation)
33
+ - `artifact_hash`: SHA-256 hash of the artifact being evaluated (computed before evaluation starts)
34
+ - `score`: The numeric score as a string with one decimal place (e.g., `"8.2"`)
35
+ - `rationale_summary`: First 500 characters of the judge's rationale text, trimmed of leading/trailing whitespace
36
+
37
+ ### Computing the Artifact Hash
38
+
39
+ Before any judge starts evaluation, compute the artifact hash:
40
+
41
+ ```bash
42
+ ARTIFACT_HASH=$(${SHA_CMD} "path/to/artifact.md" | awk '{print $1}')
43
+ ```
44
+
45
+ This hash is shared with all judges and recorded in each attestation. It proves all judges evaluated the same artifact.
46
+
47
+ ### Computing the Evaluation Hash
48
+
49
+ After a judge completes its evaluation:
50
+
51
+ ```bash
52
+ JUDGE_ID="domain-expert"
53
+ ARTIFACT_HASH="<computed above>"
54
+ SCORE="8.2"
55
+ RATIONALE_SUMMARY="<first 500 chars of rationale>"
56
+
57
+ EVAL_HASH=$(printf '%s' "${JUDGE_ID}|${ARTIFACT_HASH}|${SCORE}|${RATIONALE_SUMMARY}" | ${SHA_CMD} | awk '{print $1}')
58
+ ```
59
+
60
+ **Important:** The rationale_summary must be trimmed to exactly 500 characters (or fewer if the rationale is shorter) to ensure deterministic reproduction during verification.
61
+
62
+ ## Section 2: Chain Linking
63
+
64
+ ### Attestation Order
65
+
66
+ Judges are recorded in a fixed order within each evaluation round:
67
+
68
+ 1. Domain Expert (first, previous = NULL_HASH)
69
+ 2. Critic (second, previous = Domain Expert's evaluation_hash)
70
+ 3. Completeness Auditor (third, previous = Critic's evaluation_hash)
71
+
72
+ For a 5-judge high-stakes panel:
73
+ 4. Additional Expert (fourth, previous = Auditor's evaluation_hash)
74
+ 5. Tiebreaker (fifth, previous = Additional Expert's evaluation_hash)
75
+
76
+ ### Chain Link Protocol
77
+
78
+ ```bash
79
+ # Judge 1 (Domain Expert)
80
+ PREV_ATTESTATION_HASH="${NULL_HASH}"
81
+ # ... compute evaluation_hash_1 ...
82
+ # Record attestation with previous = NULL_HASH
83
+
84
+ # Judge 2 (Critic)
85
+ PREV_ATTESTATION_HASH="${EVAL_HASH_1}"
86
+ # ... compute evaluation_hash_2 ...
87
+ # Record attestation with previous = evaluation_hash_1
88
+
89
+ # Judge 3 (Completeness Auditor)
90
+ PREV_ATTESTATION_HASH="${EVAL_HASH_2}"
91
+ # ... compute evaluation_hash_3 ...
92
+ # Record attestation with previous = evaluation_hash_2
93
+ ```
94
+
95
+ ### Ordering Note
96
+
97
+ The chain records the ORDER in which attestations were finalized, not the order in which judges started evaluating. Since judges evaluate in parallel but record sequentially, the chain proves:
98
+ - Each attestation was recorded after the previous one
99
+ - The evaluation_hash was computed from the judge's OWN data only
100
+ - The previous_attestation_hash links to the preceding record (not to the preceding judge's score)
101
+
102
+ ## Section 3: Isolation Verification
103
+
104
+ ### Verification Algorithm
105
+
106
+ ```
107
+ 1. Load .judge-attestations.json
108
+ 2. For each evaluation round:
109
+ a. Verify artifact_hash matches across all attestations
110
+ b. For each attestation (index i):
111
+ i. Reconstruct evaluation_hash from (judge_id, artifact_hash, score, rationale_summary)
112
+ ii. Compare reconstructed hash with stored evaluation_hash
113
+ iii. If i == 0: verify previous_attestation_hash == NULL_HASH
114
+ iv. If i > 0: verify previous_attestation_hash == attestations[i-1].evaluation_hash
115
+ v. Verify timestamp > attestations[i-1].timestamp (if i > 0)
116
+ 3. Produce verification report
117
+ ```
118
+
119
+ ### Isolation Proof Logic
120
+
121
+ The isolation proof works as follows:
122
+
123
+ 1. **Hash Independence:** Each evaluation_hash is computed from `judge_id|artifact_hash|score|rationale`. If a judge had seen another judge's score, it would not affect its own hash computation -- but it would be detectable if the rationale text references specific scores from other judges.
124
+
125
+ 2. **Chain Integrity:** The previous_attestation_hash links attestations in order but does NOT include other judges' scores in the hash input. This means the chain proves ORDER but the evaluation content is provably independent.
126
+
127
+ 3. **Timestamp Monotonicity:** Timestamps must be strictly increasing. If Judge B's timestamp is BEFORE Judge A's, but Judge B's previous_attestation_hash points to Judge A, then something is wrong.
128
+
129
+ ### Verification Script
130
+
131
+ ```bash
132
+ python3 << 'VERIFY_ATTESTATION'
133
+ import json, subprocess, sys
134
+
135
+ NULL_HASH = "0" * 64
136
+
137
+ def sha256(content):
138
+ result = subprocess.run(
139
+ ["sha256sum"],
140
+ input=content.encode(),
141
+ capture_output=True
142
+ )
143
+ if result.returncode != 0:
144
+ result = subprocess.run(
145
+ ["shasum", "-a", "256"],
146
+ input=content.encode(),
147
+ capture_output=True
148
+ )
149
+ return result.stdout.decode().split()[0]
150
+
151
+ DIR = sys.argv[1] if len(sys.argv) > 1 else "."
152
+
153
+ with open(f"{DIR}/.judge-attestations.json") as f:
154
+ data = json.load(f)
155
+
156
+ for eval_round in data.get("evaluations", [data]):
157
+ attestations = eval_round.get("attestations", [])
158
+ artifact_hash = eval_round.get("artifact_hash", "")
159
+ violations = []
160
+
161
+ for i, att in enumerate(attestations):
162
+ # Reconstruct evaluation hash
163
+ hash_input = f"{att['judge_id']}|{artifact_hash}|{att['score']}|{att.get('rationale_summary', '')}"
164
+ expected = sha256(hash_input)
165
+ actual = att["evaluation_hash"].replace("sha256:", "")
166
+
167
+ if expected != actual:
168
+ violations.append(f"Judge {att['judge_id']}: evaluation_hash mismatch")
169
+
170
+ # Verify chain link
171
+ if i == 0:
172
+ expected_prev = NULL_HASH
173
+ else:
174
+ expected_prev = attestations[i-1]["evaluation_hash"].replace("sha256:", "")
175
+
176
+ actual_prev = att["previous_attestation_hash"].replace("sha256:", "")
177
+ if expected_prev != actual_prev:
178
+ violations.append(f"Judge {att['judge_id']}: chain link broken")
179
+
180
+ if not violations:
181
+ print(f"PASS: All {len(attestations)} judge attestations verified. Isolation confirmed.")
182
+ else:
183
+ print(f"FAIL: {len(violations)} violations detected:")
184
+ for v in violations:
185
+ print(f" - {v}")
186
+
187
+ VERIFY_ATTESTATION
188
+ ```
189
+
190
+ ## Section 4: File Format
191
+
192
+ ### .judge-attestations.json Schema
193
+
194
+ ```json
195
+ {
196
+ "evaluations": [
197
+ {
198
+ "evaluation_id": "string — unique ID for this evaluation round",
199
+ "artifact_path": "string — path to the evaluated artifact",
200
+ "artifact_hash": "string — sha256:<hex> of the artifact content",
201
+ "panel_size": "integer — 3 (standard) or 5 (high-stakes)",
202
+ "started_at": "ISO-8601 — when evaluation round began",
203
+ "completed_at": "ISO-8601 — when last attestation recorded",
204
+ "attestations": [
205
+ {
206
+ "judge_id": "string — domain-expert|critic|completeness-auditor",
207
+ "score": "float — 0.0-10.0",
208
+ "rationale_summary": "string — first 500 chars of rationale",
209
+ "evaluation_hash": "string — sha256:<hex>",
210
+ "timestamp": "ISO-8601 — when attestation was recorded",
211
+ "previous_attestation_hash": "string — sha256:<hex> or null hash"
212
+ }
213
+ ],
214
+ "final_score": "float — weighted average",
215
+ "weights": {
216
+ "domain-expert": 0.4,
217
+ "critic": 0.3,
218
+ "completeness-auditor": 0.3
219
+ }
220
+ }
221
+ ]
222
+ }
223
+ ```
224
+
225
+ ### Example Attestation File
226
+
227
+ ```json
228
+ {
229
+ "evaluations": [
230
+ {
231
+ "evaluation_id": "bto-eval-2026-03-01T12:00:00Z",
232
+ "artifact_path": ".claude/skills/explore/SKILL.md",
233
+ "artifact_hash": "sha256:abc123def456789012345678901234567890123456789012345678901234fedc",
234
+ "panel_size": 3,
235
+ "started_at": "2026-03-01T12:00:00Z",
236
+ "completed_at": "2026-03-01T12:01:45Z",
237
+ "attestations": [
238
+ {
239
+ "judge_id": "domain-expert",
240
+ "score": 8.2,
241
+ "rationale_summary": "Strong SKILL.md with clear protocol steps. References directory provides good examples...",
242
+ "evaluation_hash": "sha256:111222333444555666777888999000aaabbbcccdddeeefff000111222333444555",
243
+ "timestamp": "2026-03-01T12:00:30Z",
244
+ "previous_attestation_hash": "sha256:0000000000000000000000000000000000000000000000000000000000000000"
245
+ },
246
+ {
247
+ "judge_id": "critic",
248
+ "score": 7.5,
249
+ "rationale_summary": "Missing edge case handling for multi-language inputs. Error recovery protocol unclear...",
250
+ "evaluation_hash": "sha256:222333444555666777888999000aaabbbcccdddeeefff000111222333444555666",
251
+ "timestamp": "2026-03-01T12:01:00Z",
252
+ "previous_attestation_hash": "sha256:111222333444555666777888999000aaabbbcccdddeeefff000111222333444555"
253
+ },
254
+ {
255
+ "judge_id": "completeness-auditor",
256
+ "score": 8.0,
257
+ "rationale_summary": "All required sections present. References directory has 3 examples. Missing: performance benchmarks...",
258
+ "evaluation_hash": "sha256:333444555666777888999000aaabbbcccdddeeefff000111222333444555666777",
259
+ "timestamp": "2026-03-01T12:01:30Z",
260
+ "previous_attestation_hash": "sha256:222333444555666777888999000aaabbbcccdddeeefff000111222333444555666"
261
+ }
262
+ ],
263
+ "final_score": 7.94,
264
+ "weights": {
265
+ "domain-expert": 0.4,
266
+ "critic": 0.3,
267
+ "completeness-auditor": 0.3
268
+ }
269
+ }
270
+ ]
271
+ }
272
+ ```
273
+
274
+ ## Section 5: Integration with BTO Pipeline
275
+
276
+ ### When to Create Attestations
277
+
278
+ Attestations are created during **BTO Layer 2 evaluation** (the judge panel stage):
279
+
280
+ 1. **Before panel starts:** Compute `artifact_hash` of the artifact being evaluated
281
+ 2. **After each judge completes:** Create attestation record with evaluation_hash
282
+ 3. **After all judges complete:** Write `.judge-attestations.json`
283
+ 4. **If meta-judge is invoked:** Add a 4th attestation with `judge_id: "meta-judge"`
284
+
285
+ ### Integration Points
286
+
287
+ | BTO Stage | Attestation Action |
288
+ |-----------|-------------------|
289
+ | Layer 0 (structural) | No attestation needed (deterministic checks) |
290
+ | Layer 1 (semantic) | No attestation needed (single haiku agent) |
291
+ | Layer 2 (judge panel) | Create attestation set with 3 attestations |
292
+ | Meta-judge (escalation) | Append meta-judge attestation to the set |
293
+ | Optimization rounds | Create new attestation set per round's final evaluation |
294
+
295
+ ### Disagreement Detection Enhancement
296
+
297
+ With attestations, disagreement detection gains cryptographic backing:
298
+
299
+ ```
300
+ If max_score - min_score > 3.0:
301
+ 1. Verify all attestations are valid (no tampering)
302
+ 2. Verify isolation (no judge influenced another)
303
+ 3. If isolation verified: escalate to meta-judge (genuine disagreement)
304
+ 4. If isolation violated: flag conformity collapse warning
305
+ ```
306
+
307
+ ## Section 6: Meta-Judge Attestation
308
+
309
+ When the meta-judge is invoked (disagreement > 3 points), it creates its own attestation:
310
+
311
+ ```json
312
+ {
313
+ "judge_id": "meta-judge",
314
+ "score": 7.8,
315
+ "rationale_summary": "Disagreement between domain-expert (8.5) and critic (5.2) on dimension 'completeness'...",
316
+ "evaluation_hash": "sha256:...",
317
+ "timestamp": "2026-03-01T12:02:00Z",
318
+ "previous_attestation_hash": "sha256:<last judge's eval hash>"
319
+ }
320
+ ```
321
+
322
+ The meta-judge's rationale MAY reference other judges' scores (it has access to them for arbitration). This is expected and does not violate isolation -- the meta-judge is explicitly a synthesizer, not an independent evaluator.
@@ -0,0 +1,344 @@
1
+ # Memory Protocol -- Reward-Calibrated Learning
2
+
3
+ Core protocol for persistent memory in the Keysarium pipeline. Provides `memory_query()` before tasks and `memory_store()` after tasks.
4
+
5
+ **Protocol version: 1.1** — adds 2-tier index, record lifecycle (HOT/WARM/COLD/PURGE), and brain container manifest.
6
+
7
+ ## Memory Namespace
8
+
9
+ All memory files live in `.keysarium/memory/`:
10
+
11
+ ```
12
+ .keysarium/memory/
13
+ ├── config.json ← Global configuration
14
+ ├── index.json ← 2-tier index (v1.1)
15
+ ├── _patterns/
16
+ │ └── domain-patterns.json ← Detected domain patterns
17
+ ├── _stats/
18
+ │ ├── reward-summary.json ← Aggregate statistics
19
+ │ └── imported-baselines.json ← Imported reward baselines
20
+ ├── {domain}/ ← banking | retail | enterprise | healthcare
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
26
+ ```
27
+
28
+ ## Configuration
29
+
30
+ ### config.json (auto-created with defaults on first access)
31
+
32
+ ```json
33
+ {
34
+ "version": "1.1",
35
+ "retention_days": 90,
36
+ "max_results_per_query": 10,
37
+ "enabled": true,
38
+ "known_domains": ["banking", "retail", "enterprise", "healthcare"],
39
+ "reward_levels": {
40
+ "excellent": 1.0,
41
+ "good": 0.7,
42
+ "needs_work": 0.3,
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
+ }
89
+ }
90
+ }
91
+ ```
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
+
100
+ ## Protocol: memory_query(context)
101
+
102
+ Call at the **start** of each pipeline phase to load relevant historical patterns.
103
+
104
+ ### Input
105
+
106
+ ```json
107
+ {
108
+ "phase": "phase-2",
109
+ "domain": "banking",
110
+ "slug": "bank_kc_automation",
111
+ "skill": "goap-research-ed25519"
112
+ }
113
+ ```
114
+
115
+ ### Algorithm
116
+
117
+ 1. **Check enabled:** Read `.keysarium/memory/config.json`. If `enabled` is false or directory does not exist, return empty list.
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.
122
+ 4. **Filter expired:** Exclude records where `expires_at < current_date`.
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.
134
+
135
+ ### Output
136
+
137
+ ```json
138
+ {
139
+ "records": [
140
+ {
141
+ "case_slug": "bank_loan_approval",
142
+ "phase": "phase-2",
143
+ "reward": 1.0,
144
+ "reward_label": "excellent",
145
+ "skill_used": "goap-research-ed25519",
146
+ "outcome_summary": "Research completed with all claims verified...",
147
+ "timestamp": "2026-02-15T14:30:00Z"
148
+ }
149
+ ],
150
+ "patterns": [
151
+ {
152
+ "pattern_id": "banking-phase2-slow",
153
+ "description": "Banking cases take 2x longer in Phase 2 due to regulatory research",
154
+ "confidence": 0.85,
155
+ "actionable_advice": "Allocate extra time budget for Phase 2 in banking domain"
156
+ }
157
+ ],
158
+ "count": 3,
159
+ "domain": "banking"
160
+ }
161
+ ```
162
+
163
+ ### Usage in Phase
164
+
165
+ After calling `memory_query()`, the agent should:
166
+ 1. Log: "Loaded {count} historical patterns for {phase} in {domain} domain"
167
+ 2. If `records` is non-empty, review the top 3 records for relevant approaches
168
+ 3. If `patterns` is non-empty, apply actionable advice to current phase execution
169
+ 4. If both are empty (first run), proceed normally
170
+
171
+ ## Protocol: memory_store(result, reward)
172
+
173
+ Call at each **checkpoint** after the user responds, to persist the phase outcome with a reward score.
174
+
175
+ ### Input
176
+
177
+ ```json
178
+ {
179
+ "case_slug": "bank_kc_automation",
180
+ "domain": "banking",
181
+ "phase": "phase-2",
182
+ "phase_name": "Research",
183
+ "skill_used": "goap-research-ed25519",
184
+ "reward": 0.7,
185
+ "reward_label": "good",
186
+ "reward_reason": "User requested minor edits to competitor analysis section",
187
+ "context": {
188
+ "phase_number": 2,
189
+ "domain_detected": "banking",
190
+ "upstream_promises": ["DISCOVERY_COMPLETE", "CASE_EXPLORED"],
191
+ "patterns_loaded": 3,
192
+ "time_budget_pct": 15.0,
193
+ "agent_count": 3
194
+ },
195
+ "outcome": {
196
+ "artifacts_created": ["02_research_findings.md"],
197
+ "checkpoint_response": "ok, but expand the FinTech competitor section",
198
+ "iterations": 2,
199
+ "promise_emitted": "RESEARCH_PARANOID_PASSED"
200
+ }
201
+ }
202
+ ```
203
+
204
+ ### Algorithm
205
+
206
+ 1. **Ensure directory exists:** Create `.keysarium/memory/{domain}/{slug}/` if it does not exist.
207
+ 2. **Build record:** Construct full RewardRecord JSON from input.
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`.
209
+ 4. **Generate filename:** `{phase}_{ISO-timestamp}.json` (e.g., `phase-2_2026-03-01T12-30-00.json`).
210
+ 5. **Write file:** Write JSON to `.keysarium/memory/{domain}/{slug}/{filename}`.
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}"
220
+
221
+ ### RewardRecord JSON Schema
222
+
223
+ ```json
224
+ {
225
+ "id": "bank_kc_automation_phase-2_2026-03-01T12-30-00",
226
+ "version": "1.1",
227
+ "timestamp": "2026-03-01T12:30:00Z",
228
+ "case_slug": "bank_kc_automation",
229
+ "domain": "banking",
230
+ "phase": "phase-2",
231
+ "phase_name": "Research",
232
+ "skill_used": "goap-research-ed25519",
233
+ "reward": 0.7,
234
+ "reward_label": "good",
235
+ "reward_reason": "User requested minor edits to competitor analysis section",
236
+ "context": {
237
+ "phase_number": 2,
238
+ "domain_detected": "banking",
239
+ "upstream_promises": ["DISCOVERY_COMPLETE", "CASE_EXPLORED"],
240
+ "patterns_loaded": 3,
241
+ "time_budget_pct": 15.0,
242
+ "agent_count": 3
243
+ },
244
+ "outcome": {
245
+ "artifacts_created": ["02_research_findings.md"],
246
+ "checkpoint_response": "ok, but expand the FinTech competitor section",
247
+ "iterations": 2,
248
+ "promise_emitted": "RESEARCH_PARANOID_PASSED"
249
+ },
250
+ "promise_tag": "RESEARCH_PARANOID_PASSED",
251
+ "expires_at": "2026-08-28T12:30:00Z"
252
+ }
253
+ ```
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
+
290
+ ## Reward Assignment Rules
291
+
292
+ The reward score is determined by the user's response at the checkpoint:
293
+
294
+ | User Behavior | Reward | Label | Detection |
295
+ |---------------|--------|-------|-----------|
296
+ | Says "ok" / "ок" / proceeds to next phase immediately | 1.0 | excellent | Exact match or single-word approval |
297
+ | Requests minor adjustments ("углуби X", small edits to one section) | 0.7 | good | Feedback is scoped to one area, does not change direction |
298
+ | Requests significant rework (multiple sections, changed approach, re-research) | 0.3 | needs_work | Feedback affects multiple areas or changes phase direction |
299
+ | Restarts phase entirely / says result is unusable / requests complete redo | 0.0 | failed | Phase restarts from scratch |
300
+
301
+ ### Edge Cases
302
+
303
+ - **"углуби [section]"** = 0.7 (deepening is enhancement, not failure)
304
+ - **Multiple rounds of minor feedback** = 0.7 on first round, 0.3 if third+ round
305
+ - **Positive feedback with minor note** ("great, just fix the typo in section 3") = 1.0
306
+ - **No explicit response** (session ends) = do not store (no record created)
307
+
308
+ ## Error Handling
309
+
310
+ | Error | Behavior |
311
+ |-------|----------|
312
+ | `.keysarium/memory/` does not exist | `memory_query()` returns empty; `memory_store()` creates directory |
313
+ | `config.json` missing | Use defaults (90 days, 10 results, enabled) |
314
+ | Malformed JSON file | Skip that record, log warning, continue |
315
+ | Write fails (permissions, disk) | Log error, continue pipeline without storing |
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 |
319
+
320
+ ## Integration with Brain Export
321
+
322
+ When `/brain-export` runs, it should include a `"reward_data"` section:
323
+
324
+ ```json
325
+ {
326
+ "reward_data": {
327
+ "total_records": 42,
328
+ "domains": ["banking", "retail"],
329
+ "phase_averages": {
330
+ "phase-0": 0.85,
331
+ "phase-1": 0.92,
332
+ "phase-2": 0.65,
333
+ "phase-2.5": 0.78,
334
+ "phase-3": 0.71,
335
+ "phase-4": 0.89,
336
+ "phase-5": 0.74
337
+ },
338
+ "top_patterns": [],
339
+ "exported_from": ".keysarium/memory/"
340
+ }
341
+ }
342
+ ```
343
+
344
+ Individual records are NOT exported (too voluminous). Only aggregates and patterns are included.