@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.
- package/README.md +7 -2
- package/package.json +10 -2
- package/templates/.claude/commands/brain-export.md +97 -20
- package/templates/.claude/commands/brain-import.md +75 -4
- package/templates/.claude/commands/dream.md +101 -0
- package/templates/.claude/commands/feature-adr.md +92 -0
- package/templates/.claude/commands/init-platform.md +161 -0
- package/templates/.claude/commands/learning-stats.md +130 -0
- package/templates/.claude/commands/workers.md +140 -0
- package/templates/.claude/rules/background-workers.md +72 -0
- package/templates/.claude/rules/dream-cycles.md +90 -0
- package/templates/.claude/rules/feature-adr-conventions.md +82 -0
- package/templates/.claude/rules/reward-learning.md +124 -0
- package/templates/.claude/shards/feature-adr.shard.md +98 -0
- package/templates/.claude/skills/feature-adr/SKILL.md +252 -0
- package/templates/.claude/skills/feature-adr/examples/sample-feature-output.md +257 -0
- package/templates/.claude/skills/feature-adr/modules/00-complexity-router.md +114 -0
- package/templates/.claude/skills/feature-adr/modules/01-requirements.md +113 -0
- package/templates/.claude/skills/feature-adr/modules/02-research.md +92 -0
- package/templates/.claude/skills/feature-adr/modules/03-adr.md +135 -0
- package/templates/.claude/skills/feature-adr/modules/04-ddd.md +114 -0
- package/templates/.claude/skills/feature-adr/modules/05-architecture.md +149 -0
- package/templates/.claude/skills/feature-adr/modules/06-implementation-plan.md +129 -0
- package/templates/.claude/skills/feature-adr/modules/07-code.md +126 -0
- package/templates/.claude/skills/feature-adr/modules/08-qe.md +167 -0
- package/templates/.claude/skills/feature-adr/references/adr-template.md +102 -0
- package/templates/.claude/skills/feature-adr/references/c4-template.md +120 -0
- package/templates/.claude/skills/feature-adr/references/complexity-matrix.md +139 -0
- package/templates/.claude/skills/feature-adr/references/qe-checklist.md +86 -0
- package/templates/CLAUDE.md +135 -8
- package/templates/docs/feature-adr/01-architecture.md +750 -0
- package/templates/docs/feature-adr/02-functionality.md +712 -0
- package/templates/docs/feature-adr/03-deployment-guide.md +614 -0
- package/templates/docs/feature-adr/04-admin-guide.md +564 -0
- package/templates/docs/feature-adr/05-user-guide.md +508 -0
- package/templates/docs/feature-adr/06-user-flows.md +1101 -0
- package/templates/docs/improvement-directions.md +16 -16
- package/templates/docs/keysarium/01-deployment-guide.md +21 -12
- package/templates/docs/keysarium/02-admin-guide.md +204 -3
- package/templates/docs/keysarium/03-user-guide.md +224 -0
- package/templates/docs/keysarium/05-architecture.md +181 -0
- package/templates/docs/keysarium/06-user-flows.md +235 -0
- package/templates/docs/keysarium-core/01-architecture.md +559 -0
- package/templates/docs/keysarium-core/02-functionality.md +953 -0
- package/templates/docs/keysarium-core/03-deployment-guide.md +625 -0
- package/templates/docs/keysarium-core/04-admin-guide.md +529 -0
- package/templates/docs/keysarium-core/05-user-guide.md +599 -0
- package/templates/docs/keysarium-core/06-user-flows.md +804 -0
- package/templates/lib/background-workers.md +278 -0
- package/templates/lib/dream-engine.md +460 -0
- package/templates/lib/judge-attestation.md +322 -0
- package/templates/lib/memory-protocol.md +344 -0
- package/templates/lib/platform-adapters.md +100 -0
- package/templates/lib/platform-templates/copilot.md +134 -0
- package/templates/lib/platform-templates/cursor.md +95 -0
- package/templates/lib/platform-templates/opencode.md +155 -0
- package/templates/lib/reward-tracker.md +256 -0
- package/templates/lib/witness-chain.md +372 -0
- package/templates/lib/worker-templates/brain-export.md +187 -0
- package/templates/lib/worker-templates/consolidate.md +180 -0
- package/templates/lib/worker-templates/dream-cycle.md +154 -0
- 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.
|