@dzhechkov/keysarium 1.1.1 → 1.2.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/package.json +10 -2
- package/src/commands/init.js +1 -1
- 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 +124 -3
- 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/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 +239 -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,372 @@
|
|
|
1
|
+
# Witness Chain Protocol
|
|
2
|
+
|
|
3
|
+
> SHA-256 hash-chain for tamper-evident artifact integrity verification.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
This protocol defines how to compute SHA-256 hashes of pipeline artifacts and link them into a chain. Each artifact's hash includes the previous artifact's hash, making the chain tamper-evident: modifying any artifact breaks all downstream hashes.
|
|
8
|
+
|
|
9
|
+
## Constants
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
NULL_HASH = "0000000000000000000000000000000000000000000000000000000000000000"
|
|
13
|
+
CHAIN_FILE = ".witness-chain.json"
|
|
14
|
+
HASH_PREFIX = "sha256:"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Section 1: Hash Computation
|
|
18
|
+
|
|
19
|
+
### Platform Detection
|
|
20
|
+
|
|
21
|
+
Detect the available SHA-256 command:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Try sha256sum first (Linux), then shasum (macOS)
|
|
25
|
+
if command -v sha256sum &>/dev/null; then
|
|
26
|
+
SHA_CMD="sha256sum"
|
|
27
|
+
elif command -v shasum &>/dev/null; then
|
|
28
|
+
SHA_CMD="shasum -a 256"
|
|
29
|
+
else
|
|
30
|
+
echo "ERROR: No SHA-256 command found. Install coreutils."
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Computing a File Hash
|
|
36
|
+
|
|
37
|
+
Hash a single file's content:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
HASH=$(${SHA_CMD} "path/to/file.md" | awk '{print $1}')
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Computing a Chained Hash
|
|
44
|
+
|
|
45
|
+
Hash file content concatenated with the previous hash to create a chain link:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Read file content and previous hash
|
|
49
|
+
FILE_CONTENT=$(cat "path/to/file.md")
|
|
50
|
+
PREV_HASH="<previous hash value>"
|
|
51
|
+
|
|
52
|
+
# Compute chained hash
|
|
53
|
+
CHAINED_HASH=$(printf '%s%s' "${FILE_CONTENT}" "${PREV_HASH}" | ${SHA_CMD} | awk '{print $1}')
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Important:** Use `printf '%s%s'` (not `echo`) to avoid trailing newline issues. The content is the raw file bytes followed immediately by the 64-character hex hash string.
|
|
57
|
+
|
|
58
|
+
### Content Normalization
|
|
59
|
+
|
|
60
|
+
Before hashing, the content should be the raw file content as stored on disk. Do NOT:
|
|
61
|
+
- Trim whitespace
|
|
62
|
+
- Normalize line endings
|
|
63
|
+
- Strip BOM markers
|
|
64
|
+
|
|
65
|
+
The hash must match the exact bytes in the file so that verification produces the same result.
|
|
66
|
+
|
|
67
|
+
## Section 2: Chain Operations
|
|
68
|
+
|
|
69
|
+
### Operation: Create Genesis Record
|
|
70
|
+
|
|
71
|
+
Called at Phase 0 (Discovery) to initialize the chain for a new research.
|
|
72
|
+
|
|
73
|
+
**Preconditions:**
|
|
74
|
+
- Research directory `researches/<slug>/` exists
|
|
75
|
+
- Phase 0 artifact `00_product_discovery.md` has been created
|
|
76
|
+
- No `.witness-chain.json` exists yet
|
|
77
|
+
|
|
78
|
+
**Procedure:**
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
SLUG="<research-slug>"
|
|
82
|
+
DIR="researches/${SLUG}"
|
|
83
|
+
ARTIFACT="00_product_discovery.md"
|
|
84
|
+
PREV_HASH="${NULL_HASH}"
|
|
85
|
+
|
|
86
|
+
# Compute genesis hash
|
|
87
|
+
FILE_CONTENT=$(cat "${DIR}/${ARTIFACT}")
|
|
88
|
+
HASH=$(printf '%s%s' "${FILE_CONTENT}" "${PREV_HASH}" | ${SHA_CMD} | awk '{print $1}')
|
|
89
|
+
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
90
|
+
|
|
91
|
+
# Create .witness-chain.json
|
|
92
|
+
cat > "${DIR}/.witness-chain.json" << ENDOFCHAIN
|
|
93
|
+
{
|
|
94
|
+
"research_slug": "${SLUG}",
|
|
95
|
+
"created_at": "${TIMESTAMP}",
|
|
96
|
+
"last_updated": "${TIMESTAMP}",
|
|
97
|
+
"chain": [
|
|
98
|
+
{
|
|
99
|
+
"sequence": 0,
|
|
100
|
+
"phase": "phase-0",
|
|
101
|
+
"artifact": "${ARTIFACT}",
|
|
102
|
+
"hash": "${HASH_PREFIX}${HASH}",
|
|
103
|
+
"previous_hash": "${HASH_PREFIX}${PREV_HASH}",
|
|
104
|
+
"timestamp": "${TIMESTAMP}",
|
|
105
|
+
"promise_tag": "DISCOVERY_COMPLETE"
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
ENDOFCHAIN
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Operation: Append Record
|
|
113
|
+
|
|
114
|
+
Called at each subsequent phase checkpoint to add a new record to the chain.
|
|
115
|
+
|
|
116
|
+
**Preconditions:**
|
|
117
|
+
- `.witness-chain.json` exists in the research directory
|
|
118
|
+
- The new artifact file has been created
|
|
119
|
+
- The previous phase's record exists in the chain
|
|
120
|
+
|
|
121
|
+
**Procedure:**
|
|
122
|
+
|
|
123
|
+
1. Read `.witness-chain.json` and extract the last record's hash
|
|
124
|
+
2. Compute the new chained hash: `SHA-256(new_content + last_hash)`
|
|
125
|
+
3. Append the new record to the chain array
|
|
126
|
+
4. Update `last_updated` timestamp
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
SLUG="<research-slug>"
|
|
130
|
+
DIR="researches/${SLUG}"
|
|
131
|
+
ARTIFACT="<artifact-filename>"
|
|
132
|
+
PHASE="<phase-id>"
|
|
133
|
+
PROMISE="<promise-tag>"
|
|
134
|
+
|
|
135
|
+
# Get the latest hash from the chain
|
|
136
|
+
PREV_HASH=$(cat "${DIR}/.witness-chain.json" | python3 -c "
|
|
137
|
+
import json, sys
|
|
138
|
+
chain = json.load(sys.stdin)
|
|
139
|
+
last = chain['chain'][-1]
|
|
140
|
+
print(last['hash'].replace('sha256:', ''))
|
|
141
|
+
")
|
|
142
|
+
|
|
143
|
+
# Compute new hash
|
|
144
|
+
FILE_CONTENT=$(cat "${DIR}/${ARTIFACT}")
|
|
145
|
+
HASH=$(printf '%s%s' "${FILE_CONTENT}" "${PREV_HASH}" | ${SHA_CMD} | awk '{print $1}')
|
|
146
|
+
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
147
|
+
SEQUENCE=$(cat "${DIR}/.witness-chain.json" | python3 -c "
|
|
148
|
+
import json, sys
|
|
149
|
+
chain = json.load(sys.stdin)
|
|
150
|
+
print(len(chain['chain']))
|
|
151
|
+
")
|
|
152
|
+
|
|
153
|
+
# Append to chain (using python3 for safe JSON manipulation)
|
|
154
|
+
python3 -c "
|
|
155
|
+
import json, sys
|
|
156
|
+
with open('${DIR}/.witness-chain.json', 'r') as f:
|
|
157
|
+
chain = json.load(f)
|
|
158
|
+
chain['chain'].append({
|
|
159
|
+
'sequence': ${SEQUENCE},
|
|
160
|
+
'phase': '${PHASE}',
|
|
161
|
+
'artifact': '${ARTIFACT}',
|
|
162
|
+
'hash': 'sha256:${HASH}',
|
|
163
|
+
'previous_hash': 'sha256:${PREV_HASH}',
|
|
164
|
+
'timestamp': '${TIMESTAMP}',
|
|
165
|
+
'promise_tag': '${PROMISE}'
|
|
166
|
+
})
|
|
167
|
+
chain['last_updated'] = '${TIMESTAMP}'
|
|
168
|
+
with open('${DIR}/.witness-chain.json', 'w') as f:
|
|
169
|
+
json.dump(chain, f, indent=2)
|
|
170
|
+
"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Operation: Get Latest Hash
|
|
174
|
+
|
|
175
|
+
Retrieve the most recent hash from the chain (needed as input for the next append).
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
LATEST_HASH=$(python3 -c "
|
|
179
|
+
import json
|
|
180
|
+
with open('${DIR}/.witness-chain.json') as f:
|
|
181
|
+
chain = json.load(f)
|
|
182
|
+
print(chain['chain'][-1]['hash'].replace('sha256:', ''))
|
|
183
|
+
")
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Section 3: Verification
|
|
187
|
+
|
|
188
|
+
### Operation: Verify Chain
|
|
189
|
+
|
|
190
|
+
Walk the entire chain and verify each hash matches the current file content.
|
|
191
|
+
|
|
192
|
+
**Algorithm:**
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
1. Load .witness-chain.json
|
|
196
|
+
2. For each record in chain (index i):
|
|
197
|
+
a. Read the artifact file
|
|
198
|
+
b. Get previous_hash:
|
|
199
|
+
- If i == 0: previous_hash = NULL_HASH
|
|
200
|
+
- Else: previous_hash = chain[i-1].hash (without prefix)
|
|
201
|
+
c. Compute expected = SHA-256(file_content + previous_hash)
|
|
202
|
+
d. Compare expected with record.hash (without prefix)
|
|
203
|
+
e. If mismatch: record broken link
|
|
204
|
+
3. Produce verification report
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Bash implementation:**
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
DIR="researches/<slug>"
|
|
211
|
+
|
|
212
|
+
python3 << 'VERIFY_SCRIPT'
|
|
213
|
+
import json, subprocess, sys
|
|
214
|
+
|
|
215
|
+
NULL_HASH = "0" * 64
|
|
216
|
+
DIR = sys.argv[1] if len(sys.argv) > 1 else "."
|
|
217
|
+
|
|
218
|
+
def sha256(content):
|
|
219
|
+
"""Compute SHA-256 of a string."""
|
|
220
|
+
result = subprocess.run(
|
|
221
|
+
["sha256sum"],
|
|
222
|
+
input=content.encode(),
|
|
223
|
+
capture_output=True
|
|
224
|
+
)
|
|
225
|
+
if result.returncode != 0:
|
|
226
|
+
# Fallback to shasum
|
|
227
|
+
result = subprocess.run(
|
|
228
|
+
["shasum", "-a", "256"],
|
|
229
|
+
input=content.encode(),
|
|
230
|
+
capture_output=True
|
|
231
|
+
)
|
|
232
|
+
return result.stdout.decode().split()[0]
|
|
233
|
+
|
|
234
|
+
# Load chain
|
|
235
|
+
with open(f"{DIR}/.witness-chain.json") as f:
|
|
236
|
+
chain_data = json.load(f)
|
|
237
|
+
|
|
238
|
+
records = chain_data["chain"]
|
|
239
|
+
broken = []
|
|
240
|
+
verified = 0
|
|
241
|
+
|
|
242
|
+
for i, record in enumerate(records):
|
|
243
|
+
artifact_path = f"{DIR}/{record['artifact']}"
|
|
244
|
+
try:
|
|
245
|
+
with open(artifact_path) as f:
|
|
246
|
+
content = f.read()
|
|
247
|
+
except FileNotFoundError:
|
|
248
|
+
broken.append({
|
|
249
|
+
"sequence": i,
|
|
250
|
+
"artifact": record["artifact"],
|
|
251
|
+
"reason": "File not found"
|
|
252
|
+
})
|
|
253
|
+
continue
|
|
254
|
+
|
|
255
|
+
if i == 0:
|
|
256
|
+
prev_hash = NULL_HASH
|
|
257
|
+
else:
|
|
258
|
+
prev_hash = records[i-1]["hash"].replace("sha256:", "")
|
|
259
|
+
|
|
260
|
+
expected = sha256(content + prev_hash)
|
|
261
|
+
actual = record["hash"].replace("sha256:", "")
|
|
262
|
+
|
|
263
|
+
if expected == actual:
|
|
264
|
+
verified += 1
|
|
265
|
+
else:
|
|
266
|
+
broken.append({
|
|
267
|
+
"sequence": i,
|
|
268
|
+
"artifact": record["artifact"],
|
|
269
|
+
"expected_hash": f"sha256:{expected}",
|
|
270
|
+
"actual_hash": record["hash"],
|
|
271
|
+
"reason": "Hash mismatch - artifact may have been modified"
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
# Report
|
|
275
|
+
total = len(records)
|
|
276
|
+
if not broken:
|
|
277
|
+
print(f"PASS: All {total} records verified successfully")
|
|
278
|
+
else:
|
|
279
|
+
print(f"FAIL: {len(broken)} broken links out of {total} records")
|
|
280
|
+
for b in broken:
|
|
281
|
+
print(f" - Record {b['sequence']} ({b['artifact']}): {b['reason']}")
|
|
282
|
+
|
|
283
|
+
VERIFY_SCRIPT
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Section 4: File Format
|
|
287
|
+
|
|
288
|
+
### .witness-chain.json Schema
|
|
289
|
+
|
|
290
|
+
```json
|
|
291
|
+
{
|
|
292
|
+
"research_slug": "string — research directory name",
|
|
293
|
+
"created_at": "ISO-8601 — when chain was initialized",
|
|
294
|
+
"last_updated": "ISO-8601 — when last record was added",
|
|
295
|
+
"chain": [
|
|
296
|
+
{
|
|
297
|
+
"sequence": "integer — 0-based position in chain",
|
|
298
|
+
"phase": "string — phase-0, phase-1, ..., phase-5",
|
|
299
|
+
"artifact": "string — filename relative to research dir",
|
|
300
|
+
"hash": "string — sha256:<64 hex chars>",
|
|
301
|
+
"previous_hash": "string — sha256:<64 hex chars> or sha256:<null hash>",
|
|
302
|
+
"timestamp": "ISO-8601 — when record was created",
|
|
303
|
+
"promise_tag": "string — semantic completion promise"
|
|
304
|
+
}
|
|
305
|
+
]
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Standard Phase-to-Artifact Mapping
|
|
310
|
+
|
|
311
|
+
| Phase | Artifact | Promise Tag |
|
|
312
|
+
|-------|----------|-------------|
|
|
313
|
+
| phase-0 | 00_product_discovery.md | DISCOVERY_COMPLETE |
|
|
314
|
+
| phase-1 | 01_case_brief.md | CASE_EXPLORED |
|
|
315
|
+
| phase-2 | 02_research_findings.md | RESEARCH_PARANOID_PASSED |
|
|
316
|
+
| phase-2.5 | 02.5_trend_brief.md | CJM_VALIDATED |
|
|
317
|
+
| phase-3 | 03_solution_strategy.md | SOLUTION_DESIGNED |
|
|
318
|
+
| phase-4 | 04_architecture.md | ARCHITECTURE_DEFINED |
|
|
319
|
+
| phase-5 | 05_presentation_content.md | PRESENTATION_READY |
|
|
320
|
+
|
|
321
|
+
### Example Complete Chain
|
|
322
|
+
|
|
323
|
+
```json
|
|
324
|
+
{
|
|
325
|
+
"research_slug": "bank_kc_automation",
|
|
326
|
+
"created_at": "2026-03-01T10:00:00Z",
|
|
327
|
+
"last_updated": "2026-03-01T14:30:00Z",
|
|
328
|
+
"chain": [
|
|
329
|
+
{
|
|
330
|
+
"sequence": 0,
|
|
331
|
+
"phase": "phase-0",
|
|
332
|
+
"artifact": "00_product_discovery.md",
|
|
333
|
+
"hash": "sha256:a1b2c3d4e5f6789012345678901234567890123456789012345678901234abcd",
|
|
334
|
+
"previous_hash": "sha256:0000000000000000000000000000000000000000000000000000000000000000",
|
|
335
|
+
"timestamp": "2026-03-01T10:00:00Z",
|
|
336
|
+
"promise_tag": "DISCOVERY_COMPLETE"
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
"sequence": 1,
|
|
340
|
+
"phase": "phase-1",
|
|
341
|
+
"artifact": "01_case_brief.md",
|
|
342
|
+
"hash": "sha256:b2c3d4e5f67890123456789012345678901234567890123456789012345bef01",
|
|
343
|
+
"previous_hash": "sha256:a1b2c3d4e5f6789012345678901234567890123456789012345678901234abcd",
|
|
344
|
+
"timestamp": "2026-03-01T10:30:00Z",
|
|
345
|
+
"promise_tag": "CASE_EXPLORED"
|
|
346
|
+
}
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## Section 5: Chain Repair
|
|
352
|
+
|
|
353
|
+
If an artifact is legitimately modified (e.g., user requested changes during checkpoint review), the chain must be repaired:
|
|
354
|
+
|
|
355
|
+
1. Re-hash the modified artifact using the previous record's hash
|
|
356
|
+
2. Update the modified record's hash in `.witness-chain.json`
|
|
357
|
+
3. Re-hash ALL subsequent records (cascade update)
|
|
358
|
+
4. Update `last_updated` timestamp
|
|
359
|
+
|
|
360
|
+
This is expected and normal. The witness chain protects against *undetected* modifications, not against all modifications.
|
|
361
|
+
|
|
362
|
+
## Section 6: Platform Compatibility
|
|
363
|
+
|
|
364
|
+
| Platform | Command | Notes |
|
|
365
|
+
|----------|---------|-------|
|
|
366
|
+
| Linux (Ubuntu, Debian, etc.) | `sha256sum` | Available by default in coreutils |
|
|
367
|
+
| macOS | `shasum -a 256` | Available by default |
|
|
368
|
+
| Windows (WSL) | `sha256sum` | Available in WSL |
|
|
369
|
+
| Windows (Git Bash) | `sha256sum` | Available in Git for Windows |
|
|
370
|
+
| Alpine Linux | `sha256sum` | Available in coreutils |
|
|
371
|
+
|
|
372
|
+
The protocol should attempt `sha256sum` first, then fall back to `shasum -a 256`.
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Worker Template: Brain Export
|
|
2
|
+
|
|
3
|
+
> This file is loaded by the background worker agent. It contains the complete
|
|
4
|
+
> instructions for executing a non-blocking brain export.
|
|
5
|
+
|
|
6
|
+
## Worker Identity
|
|
7
|
+
|
|
8
|
+
- **Type:** export-brain
|
|
9
|
+
- **Model:** haiku
|
|
10
|
+
- **Purpose:** Non-blocking version of /brain-export. Assembles a portable brain container.
|
|
11
|
+
|
|
12
|
+
## Instructions
|
|
13
|
+
|
|
14
|
+
You are a background worker agent. Your job is to export Keysarium's accumulated
|
|
15
|
+
knowledge into a portable JSON brain container. You operate in ISOLATION -- you must
|
|
16
|
+
not modify any files outside your output directory.
|
|
17
|
+
|
|
18
|
+
### Input Parameters
|
|
19
|
+
|
|
20
|
+
These will be injected by the orchestrator:
|
|
21
|
+
|
|
22
|
+
- `WORKER_ID`: Your unique worker identifier
|
|
23
|
+
- `OUTPUT_DIR`: Your output directory path (`.keysarium/workers/{WORKER_ID}/`)
|
|
24
|
+
|
|
25
|
+
### Execution Steps
|
|
26
|
+
|
|
27
|
+
#### Step 1: Initialize
|
|
28
|
+
|
|
29
|
+
Write your status file:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"worker_id": "{WORKER_ID}",
|
|
34
|
+
"type": "export-brain",
|
|
35
|
+
"status": "running",
|
|
36
|
+
"started_at": "{current ISO8601 timestamp}",
|
|
37
|
+
"completed_at": null,
|
|
38
|
+
"progress": { "phase": "initializing", "items_processed": 0 },
|
|
39
|
+
"error": null
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
#### Step 2: Collect Skill Metadata
|
|
44
|
+
|
|
45
|
+
For each skill in `.claude/skills/`:
|
|
46
|
+
|
|
47
|
+
1. Read `SKILL.md` -- extract name, description, trust_tier
|
|
48
|
+
2. Count files in references/, modules/, examples/
|
|
49
|
+
3. Build skill metadata entry
|
|
50
|
+
|
|
51
|
+
Update status: `"phase": "collecting skill metadata"`
|
|
52
|
+
|
|
53
|
+
**Check for `stop-requested` file.**
|
|
54
|
+
|
|
55
|
+
#### Step 3: Collect Domain Patterns
|
|
56
|
+
|
|
57
|
+
1. Read `TOOLKIT_HARVEST.md` if it exists -- extract all patterns
|
|
58
|
+
2. Read `.claude/rules/domain-specific.md` -- extract domain templates
|
|
59
|
+
3. Scan `researches/` directories for domain distribution
|
|
60
|
+
|
|
61
|
+
Update status: `"phase": "collecting domain patterns"`
|
|
62
|
+
|
|
63
|
+
**Check for `stop-requested` file.**
|
|
64
|
+
|
|
65
|
+
#### Step 4: Collect Research Summaries
|
|
66
|
+
|
|
67
|
+
For each completed research in `researches/`:
|
|
68
|
+
|
|
69
|
+
1. Read `08_executive_summary.md` (if exists) -- extract key summary
|
|
70
|
+
2. Read `README.md` (if exists) -- extract brief
|
|
71
|
+
3. Build research summary entry (NO full content, just metadata + summary)
|
|
72
|
+
|
|
73
|
+
Update status: `"phase": "collecting research summaries"`
|
|
74
|
+
|
|
75
|
+
**Check for `stop-requested` file.**
|
|
76
|
+
|
|
77
|
+
#### Step 5: Collect Harvest Patterns
|
|
78
|
+
|
|
79
|
+
1. Read `TOOLKIT_HARVEST.md` -- extract classified patterns
|
|
80
|
+
2. Categories: skills, commands, rules, templates, patterns, snippets
|
|
81
|
+
|
|
82
|
+
Update status: `"phase": "collecting harvest patterns"`
|
|
83
|
+
|
|
84
|
+
#### Step 6: Collect Pipeline Metrics
|
|
85
|
+
|
|
86
|
+
1. Count total researches (completed vs incomplete)
|
|
87
|
+
2. Count total features (completed vs in-progress)
|
|
88
|
+
3. List skill trust tiers
|
|
89
|
+
4. Summarize domain distribution
|
|
90
|
+
|
|
91
|
+
Update status: `"phase": "collecting pipeline metrics"`
|
|
92
|
+
|
|
93
|
+
#### Step 7: Assemble Brain Container
|
|
94
|
+
|
|
95
|
+
Write `{OUTPUT_DIR}/output/brain-export-{YYYYMMDD}.json`:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"version": "1.0",
|
|
100
|
+
"format": "keysarium-brain",
|
|
101
|
+
"exported_at": "{ISO8601 timestamp}",
|
|
102
|
+
"source_project": "product-keysarium-2026",
|
|
103
|
+
"worker_id": "{WORKER_ID}",
|
|
104
|
+
"skills": [
|
|
105
|
+
{
|
|
106
|
+
"name": "explore",
|
|
107
|
+
"description": "Adaptive task clarification",
|
|
108
|
+
"trust_tier": 1,
|
|
109
|
+
"trust_label": "Structured",
|
|
110
|
+
"has_references": true,
|
|
111
|
+
"has_modules": false,
|
|
112
|
+
"has_examples": false
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
"domain_patterns": [
|
|
116
|
+
{
|
|
117
|
+
"domain": "banking",
|
|
118
|
+
"rules": ["on-premise LLM", "HITL mandatory", "FZ-152 compliance"],
|
|
119
|
+
"palette": "Blue/Navy/Silver"
|
|
120
|
+
}
|
|
121
|
+
],
|
|
122
|
+
"research_summaries": [
|
|
123
|
+
{
|
|
124
|
+
"slug": "bank_kc_automation",
|
|
125
|
+
"domain": "banking",
|
|
126
|
+
"status": "completed",
|
|
127
|
+
"summary": "AI-powered knowledge center automation for banking..."
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
"harvest_patterns": {
|
|
131
|
+
"skills_count": 0,
|
|
132
|
+
"commands_count": 0,
|
|
133
|
+
"rules_count": 0,
|
|
134
|
+
"patterns_count": 0,
|
|
135
|
+
"patterns": []
|
|
136
|
+
},
|
|
137
|
+
"pipeline_metrics": {
|
|
138
|
+
"total_researches": 5,
|
|
139
|
+
"completed_researches": 3,
|
|
140
|
+
"total_features": 2,
|
|
141
|
+
"completed_features": 1,
|
|
142
|
+
"skill_tiers": { "tier_0": 1, "tier_1": 6, "tier_2": 0, "tier_3": 0 },
|
|
143
|
+
"domain_distribution": { "banking": 2, "retail": 1 }
|
|
144
|
+
},
|
|
145
|
+
"metadata": {
|
|
146
|
+
"generator": "background-worker-export-brain",
|
|
147
|
+
"keysarium_version": "2026-03-01"
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### Step 8: Complete
|
|
153
|
+
|
|
154
|
+
Write final status:
|
|
155
|
+
|
|
156
|
+
```json
|
|
157
|
+
{
|
|
158
|
+
"worker_id": "{WORKER_ID}",
|
|
159
|
+
"type": "export-brain",
|
|
160
|
+
"status": "completed",
|
|
161
|
+
"started_at": "{start timestamp}",
|
|
162
|
+
"completed_at": "{current timestamp}",
|
|
163
|
+
"progress": { "phase": "completed", "items_processed": 5 },
|
|
164
|
+
"error": null
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Also copy the brain export file to `.keysarium/exports/` if that directory exists
|
|
169
|
+
(create it if needed). This provides a standard location for brain exports regardless
|
|
170
|
+
of which worker produced them.
|
|
171
|
+
|
|
172
|
+
### Error Handling
|
|
173
|
+
|
|
174
|
+
If any collection step fails:
|
|
175
|
+
1. Write partial brain container with available data
|
|
176
|
+
2. Add `"incomplete": true` and `"missing_sections"` to the metadata
|
|
177
|
+
3. Write error details to `{OUTPUT_DIR}/error.log`
|
|
178
|
+
4. Set status to `completed` (partial export is still useful)
|
|
179
|
+
|
|
180
|
+
Only set status to `failed` if the entire worker cannot write output at all.
|
|
181
|
+
|
|
182
|
+
### Isolation Rules
|
|
183
|
+
|
|
184
|
+
- You MUST only write files to `{OUTPUT_DIR}/` and `.keysarium/exports/`
|
|
185
|
+
- You MUST NOT modify any file in `researches/`, `features/`, `.claude/`, or project root
|
|
186
|
+
- You MUST NOT spawn sub-agents
|
|
187
|
+
- You MAY read any file in the project for data collection
|