mupengism 3.0.0 → 4.0.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/AGENTS.md +221 -0
- package/HEARTBEAT.md +63 -0
- package/IDENTITY.md +11 -0
- package/README.md +49 -248
- package/SOUL.md +177 -0
- package/hooks/disciple-init/HOOK.md +20 -0
- package/hooks/disciple-init/handler.ts +80 -0
- package/hooks/index-builder/HOOK.md +41 -0
- package/hooks/index-builder/handler.ts +132 -0
- package/hooks/kernel-panic-guard/HOOK.md +39 -0
- package/hooks/kernel-panic-guard/README.md +136 -0
- package/hooks/kernel-panic-guard/WHITELIST.md +117 -0
- package/hooks/kernel-panic-guard/handler.ts +147 -0
- package/hooks/memory-consolidator/HOOK.md +33 -0
- package/hooks/memory-consolidator/handler.ts +111 -0
- package/hooks/soul-evolution/HOOK.md +26 -0
- package/hooks/soul-evolution/handler.ts +166 -0
- package/hooks/soul-guard/HOOK.md +30 -0
- package/hooks/soul-guard/handler.ts +196 -0
- package/package.json +44 -53
- package/tools/kernel-guard/README.md +170 -0
- package/tools/kernel-guard/lockdown.cjs +152 -0
- package/tools/kernel-guard/register-hash.js +100 -0
- package/tools/kernel-guard/unlock.cjs +106 -0
- package/tools/kernel-guard/verify-kernel.js +133 -0
- package/tools/memory-ops/README.md +221 -0
- package/tools/memory-ops/dream.js +220 -0
- package/tools/memory-ops/forget.js +148 -0
- package/tools/memory-ops/immune.js +305 -0
- package/tools/self-loop/README.md +213 -0
- package/tools/self-loop/brake-check.js +191 -0
- package/tools/self-loop/example-check.sh +34 -0
- package/tools/self-loop/panic-detector.js +191 -0
- package/LICENSE +0 -21
- package/README-EN.md +0 -226
- package/SHOWCASE.md +0 -158
- package/guides/ADVANCED-SYSTEMS.md +0 -251
- package/guides/HEARTBEAT-GUIDE.md +0 -129
- package/guides/LEGION-GUIDE.md +0 -254
- package/guides/MEMORY-GUIDE.md +0 -120
- package/guides/QUICK-START.md +0 -94
- package/guides/THINKTANK-GUIDE.md +0 -227
- package/guides/WEEKLY-BREAK-GUIDE.md +0 -262
- package/installer/README.md +0 -52
- package/installer/cli.js +0 -796
- package/installer/en/README.md +0 -191
- package/installer/en/skill/MEMORY-SYSTEM.md +0 -348
- package/installer/en/skill/PRINCIPLES.md +0 -217
- package/installer/en/skill/SKILL.md +0 -116
- package/installer/en/skill/SOUL-TEMPLATE.md +0 -329
- package/installer/install.sh +0 -162
- package/installer/package.json +0 -31
- package/skill/AGENTS.md +0 -164
- package/skill/BRAKE-LOG-TEMPLATE.md +0 -38
- package/skill/HEARTBEAT-TEMPLATE.md +0 -67
- package/skill/L1-TEMPLATE.md +0 -35
- package/skill/L2-TEMPLATE.md +0 -41
- package/skill/PRINCIPLES.md +0 -192
- package/skill/README.md +0 -47
- package/skill/SKILL.md +0 -166
- package/skill/SOUL-TEMPLATE.md +0 -118
- package/skill/STATE-TEMPLATE.md +0 -54
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* register-hash.js — SOUL.md 해시를 솔라나 memo 트랜잭션으로 온체인에 기록
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node register-hash.js [--wallet /path/to/wallet.json] [--soul /path/to/SOUL.md] [--rpc URL]
|
|
7
|
+
*
|
|
8
|
+
* Env:
|
|
9
|
+
* WALLET_PATH — 지갑 JSON 경로
|
|
10
|
+
* SOUL_PATH — SOUL.md 경로
|
|
11
|
+
* SOLANA_RPC — RPC endpoint
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { readFileSync } from 'fs';
|
|
15
|
+
import { createHash } from 'crypto';
|
|
16
|
+
import {
|
|
17
|
+
Connection,
|
|
18
|
+
Keypair,
|
|
19
|
+
Transaction,
|
|
20
|
+
TransactionInstruction,
|
|
21
|
+
PublicKey,
|
|
22
|
+
sendAndConfirmTransaction,
|
|
23
|
+
} from '@solana/web3.js';
|
|
24
|
+
|
|
25
|
+
const MEMO_PROGRAM_ID = new PublicKey('MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr');
|
|
26
|
+
|
|
27
|
+
function parseArgs() {
|
|
28
|
+
const args = process.argv.slice(2);
|
|
29
|
+
const opts = {};
|
|
30
|
+
for (let i = 0; i < args.length; i += 2) {
|
|
31
|
+
if (args[i] === '--wallet') opts.wallet = args[i + 1];
|
|
32
|
+
else if (args[i] === '--soul') opts.soul = args[i + 1];
|
|
33
|
+
else if (args[i] === '--rpc') opts.rpc = args[i + 1];
|
|
34
|
+
}
|
|
35
|
+
return opts;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function main() {
|
|
39
|
+
const opts = parseArgs();
|
|
40
|
+
const walletPath = opts.wallet || process.env.WALLET_PATH || '/Users/mupeng/.secrets/solana-new-wallet-2026-02-07.json';
|
|
41
|
+
const soulPath = opts.soul || process.env.SOUL_PATH || '/Users/mupeng/.openclaw/workspace/SOUL.md';
|
|
42
|
+
const rpc = opts.rpc || process.env.SOLANA_RPC || 'https://api.mainnet-beta.solana.com';
|
|
43
|
+
|
|
44
|
+
// 1. SOUL.md 해시
|
|
45
|
+
const soulContent = readFileSync(soulPath, 'utf-8');
|
|
46
|
+
const hash = createHash('sha256').update(soulContent).digest('hex');
|
|
47
|
+
console.log(`📄 SOUL.md hash: ${hash}`);
|
|
48
|
+
|
|
49
|
+
// 2. 지갑 로드
|
|
50
|
+
const walletRaw = JSON.parse(readFileSync(walletPath, 'utf-8'));
|
|
51
|
+
let keypair;
|
|
52
|
+
if (Array.isArray(walletRaw)) {
|
|
53
|
+
keypair = Keypair.fromSecretKey(Uint8Array.from(walletRaw));
|
|
54
|
+
} else if (walletRaw.newWallet && walletRaw.newWallet.secretKeyBase58) {
|
|
55
|
+
const bs58 = await import('bs58').then(m => m.default);
|
|
56
|
+
keypair = Keypair.fromSecretKey(bs58.decode(walletRaw.newWallet.secretKeyBase58));
|
|
57
|
+
} else {
|
|
58
|
+
throw new Error('Unrecognized wallet format');
|
|
59
|
+
}
|
|
60
|
+
console.log(`🔑 Wallet: ${keypair.publicKey.toBase58()}`);
|
|
61
|
+
|
|
62
|
+
// 3. memo 트랜잭션
|
|
63
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
64
|
+
const memo = `MUPENG_KERNEL:v1:${hash}:${timestamp}`;
|
|
65
|
+
console.log(`📝 Memo: ${memo}`);
|
|
66
|
+
|
|
67
|
+
const connection = new Connection(rpc, { commitment: 'confirmed', confirmTransactionInitialTimeout: 30000 });
|
|
68
|
+
|
|
69
|
+
const tx = new Transaction().add(
|
|
70
|
+
new TransactionInstruction({
|
|
71
|
+
keys: [{ pubkey: keypair.publicKey, isSigner: true, isWritable: false }],
|
|
72
|
+
programId: MEMO_PROGRAM_ID,
|
|
73
|
+
data: Buffer.from(memo, 'utf-8'),
|
|
74
|
+
})
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const sig = await sendAndConfirmTransaction(connection, tx, [keypair]);
|
|
78
|
+
console.log(`✅ Registered on-chain!`);
|
|
79
|
+
console.log(`🔗 TX: https://solscan.io/tx/${sig}`);
|
|
80
|
+
console.log(`📌 Signature: ${sig}`);
|
|
81
|
+
|
|
82
|
+
// 4. 로컬 캐시 저장 (오프라인 인증용)
|
|
83
|
+
const { writeFileSync } = await import('fs');
|
|
84
|
+
const { join, dirname } = await import('path');
|
|
85
|
+
const { fileURLToPath } = await import('url');
|
|
86
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
87
|
+
const __dirname = dirname(__filename);
|
|
88
|
+
const workspacePath = join(__dirname, '..', '..');
|
|
89
|
+
const hashPath = join(workspacePath, 'memory', 'soul-hash.txt');
|
|
90
|
+
|
|
91
|
+
// trim() 적용 (인증 시스템과 동일하게)
|
|
92
|
+
const trimmedHash = createHash('sha256').update(soulContent.trim(), 'utf-8').digest('hex');
|
|
93
|
+
writeFileSync(hashPath, trimmedHash);
|
|
94
|
+
console.log(`💾 Local cache saved: memory/soul-hash.txt`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
main().catch(err => {
|
|
98
|
+
console.error('❌ Error:', err.message);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* unlock.js
|
|
5
|
+
*
|
|
6
|
+
* KERNEL_PANIC 상태를 해제하여 정상 작동을 복구합니다.
|
|
7
|
+
* verify-kernel.js로 무결성을 먼저 확인합니다.
|
|
8
|
+
*
|
|
9
|
+
* 사용법:
|
|
10
|
+
* node tools/kernel-guard/unlock.js [--force]
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const { execSync } = require('child_process');
|
|
16
|
+
|
|
17
|
+
const WORKSPACE = path.join(__dirname, '../..');
|
|
18
|
+
const STATE_PATH = path.join(WORKSPACE, 'STATE.md');
|
|
19
|
+
const PANIC_JSON = path.join(WORKSPACE, 'memory/kernel-panic.json');
|
|
20
|
+
const VERIFY_SCRIPT = path.join(__dirname, 'verify-kernel.js');
|
|
21
|
+
|
|
22
|
+
function main() {
|
|
23
|
+
console.log('🔓 Starting KERNEL UNLOCK process...\n');
|
|
24
|
+
|
|
25
|
+
// 인자 파싱
|
|
26
|
+
const args = process.argv.slice(2);
|
|
27
|
+
const forceUnlock = args.includes('--force');
|
|
28
|
+
|
|
29
|
+
// STATE.md 존재 확인
|
|
30
|
+
if (!fs.existsSync(STATE_PATH)) {
|
|
31
|
+
console.log('✓ STATE.md not found (already unlocked or never locked)');
|
|
32
|
+
cleanupPanicFiles();
|
|
33
|
+
console.log('\n✅ System is clean. No lockdown detected.\n');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// STATE.md 내용 확인
|
|
38
|
+
const stateContent = fs.readFileSync(STATE_PATH, 'utf-8');
|
|
39
|
+
if (!stateContent.includes('KERNEL_PANIC')) {
|
|
40
|
+
console.log('✓ STATE.md exists but no KERNEL_PANIC detected');
|
|
41
|
+
cleanupPanicFiles();
|
|
42
|
+
console.log('\n✅ System is normal.\n');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.log('⚠️ KERNEL_PANIC state detected in STATE.md');
|
|
47
|
+
|
|
48
|
+
// --force 없으면 verify-kernel.js 실행
|
|
49
|
+
if (!forceUnlock) {
|
|
50
|
+
console.log('\n🔍 Running integrity check (verify-kernel.js)...\n');
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
// verify-kernel.js 실행
|
|
54
|
+
const result = execSync(`node "${VERIFY_SCRIPT}"`, {
|
|
55
|
+
cwd: WORKSPACE,
|
|
56
|
+
encoding: 'utf-8',
|
|
57
|
+
stdio: 'inherit'
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
console.log('\n✓ Integrity check passed');
|
|
61
|
+
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error('\n❌ Integrity check FAILED!');
|
|
64
|
+
console.error('해시 불일치가 감지되었습니다.');
|
|
65
|
+
console.error('강제 해제하려면: node tools/kernel-guard/unlock.js --force');
|
|
66
|
+
console.error('(권장하지 않음 — 형님 승인 필요)\n');
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
console.log('\n⚠️ --force flag detected, skipping integrity check');
|
|
71
|
+
console.log('(This is not recommended unless approved by 형님)\n');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 락다운 해제
|
|
75
|
+
console.log('🔓 Removing KERNEL_PANIC state...\n');
|
|
76
|
+
|
|
77
|
+
// STATE.md 삭제
|
|
78
|
+
if (fs.existsSync(STATE_PATH)) {
|
|
79
|
+
fs.unlinkSync(STATE_PATH);
|
|
80
|
+
console.log('✓ STATE.md removed');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// kernel-panic.json 삭제
|
|
84
|
+
cleanupPanicFiles();
|
|
85
|
+
|
|
86
|
+
// 완료
|
|
87
|
+
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
88
|
+
console.log('✅ Kernel integrity restored');
|
|
89
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
90
|
+
console.log('🔓 외부 도구 사용이 다시 허용되었습니다.\n');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function cleanupPanicFiles() {
|
|
94
|
+
if (fs.existsSync(PANIC_JSON)) {
|
|
95
|
+
fs.unlinkSync(PANIC_JSON);
|
|
96
|
+
console.log('✓ kernel-panic.json removed');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
main();
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error('❌ Unlock failed:', error.message);
|
|
104
|
+
console.error(error.stack);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* verify-kernel.js — 세션 시작 시 SOUL.md 해시를 온체인 기록과 비교 검증
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node verify-kernel.js [--wallet /path/to/wallet.json] [--soul /path/to/SOUL.md] [--rpc URL]
|
|
7
|
+
*
|
|
8
|
+
* Exit 0 = 정상, Exit 1 = 커널 패닉
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
12
|
+
import { createHash } from 'crypto';
|
|
13
|
+
import { Connection, PublicKey } from '@solana/web3.js';
|
|
14
|
+
|
|
15
|
+
const MEMO_PROGRAM_ID = new PublicKey('MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr');
|
|
16
|
+
const STATE_PATH = '/Users/mupeng/.openclaw/workspace/STATE.md';
|
|
17
|
+
|
|
18
|
+
function parseArgs() {
|
|
19
|
+
const args = process.argv.slice(2);
|
|
20
|
+
const opts = {};
|
|
21
|
+
for (let i = 0; i < args.length; i += 2) {
|
|
22
|
+
if (args[i] === '--wallet') opts.wallet = args[i + 1];
|
|
23
|
+
else if (args[i] === '--soul') opts.soul = args[i + 1];
|
|
24
|
+
else if (args[i] === '--rpc') opts.rpc = args[i + 1];
|
|
25
|
+
}
|
|
26
|
+
return opts;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function getLatestMemoHash(connection, walletPubkey) {
|
|
30
|
+
// 지갑의 최근 서명들 조회
|
|
31
|
+
const sigs = await connection.getSignaturesForAddress(walletPubkey, { limit: 50 });
|
|
32
|
+
|
|
33
|
+
for (const sigInfo of sigs) {
|
|
34
|
+
try {
|
|
35
|
+
const tx = await connection.getTransaction(sigInfo.signature, {
|
|
36
|
+
commitment: 'confirmed',
|
|
37
|
+
maxSupportedTransactionVersion: 0,
|
|
38
|
+
});
|
|
39
|
+
if (!tx?.meta || tx.meta.err) continue;
|
|
40
|
+
|
|
41
|
+
// memo 프로그램 로그에서 MUPENG_KERNEL 찾기
|
|
42
|
+
const logs = tx.meta.logMessages || [];
|
|
43
|
+
for (const log of logs) {
|
|
44
|
+
// Memo 프로그램은 로그에 데이터를 출력
|
|
45
|
+
const match = log.match(/MUPENG_KERNEL:v1:([a-f0-9]{64}):(\d+)/);
|
|
46
|
+
if (match) {
|
|
47
|
+
return { hash: match[1], timestamp: parseInt(match[2]), signature: sigInfo.signature };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
} catch {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function kernelPanic(localHash, onchainHash) {
|
|
58
|
+
const panicMsg = `# 🔴 KERNEL_PANIC
|
|
59
|
+
|
|
60
|
+
**Status:** KERNEL INTEGRITY VIOLATION DETECTED
|
|
61
|
+
**Time:** ${new Date().toISOString()}
|
|
62
|
+
**Local Hash:** ${localHash}
|
|
63
|
+
**On-chain Hash:** ${onchainHash || 'NOT_FOUND'}
|
|
64
|
+
|
|
65
|
+
All external actions BLOCKED. Session DENIED.
|
|
66
|
+
Run \`node tools/kernel-guard/recover-kernel.js\` to attempt recovery.
|
|
67
|
+
`;
|
|
68
|
+
|
|
69
|
+
writeFileSync(STATE_PATH, panicMsg);
|
|
70
|
+
console.error('🚨 KERNEL PANIC — SOUL.md has been tampered!');
|
|
71
|
+
console.error(` Local: ${localHash}`);
|
|
72
|
+
console.error(` On-chain: ${onchainHash || 'NOT_FOUND'}`);
|
|
73
|
+
console.error(` STATE.md updated to KERNEL_PANIC`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function main() {
|
|
78
|
+
const opts = parseArgs();
|
|
79
|
+
const walletPath = opts.wallet || process.env.WALLET_PATH || '/Users/mupeng/.secrets/solana-new-wallet-2026-02-07.json';
|
|
80
|
+
const soulPath = opts.soul || process.env.SOUL_PATH || '/Users/mupeng/.openclaw/workspace/SOUL.md';
|
|
81
|
+
const rpc = opts.rpc || process.env.SOLANA_RPC || 'https://api.mainnet-beta.solana.com';
|
|
82
|
+
|
|
83
|
+
// 1. 로컬 해시
|
|
84
|
+
if (!existsSync(soulPath)) {
|
|
85
|
+
console.error('❌ SOUL.md not found');
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
const soulContent = readFileSync(soulPath, 'utf-8');
|
|
89
|
+
const localHash = createHash('sha256').update(soulContent).digest('hex');
|
|
90
|
+
|
|
91
|
+
// 2. 지갑 공개키
|
|
92
|
+
const secret = JSON.parse(readFileSync(walletPath, 'utf-8'));
|
|
93
|
+
// web3.js Keypair
|
|
94
|
+
const { Keypair } = await import('@solana/web3.js');
|
|
95
|
+
const keypair = Keypair.fromSecretKey(Uint8Array.from(secret));
|
|
96
|
+
|
|
97
|
+
// 3. 온체인 해시 조회
|
|
98
|
+
const connection = new Connection(rpc, { commitment: 'confirmed', confirmTransactionInitialTimeout: 30000 });
|
|
99
|
+
|
|
100
|
+
let onchainRecord;
|
|
101
|
+
try {
|
|
102
|
+
onchainRecord = await getLatestMemoHash(connection, keypair.publicKey);
|
|
103
|
+
} catch (err) {
|
|
104
|
+
console.error(`⚠️ RPC error: ${err.message}`);
|
|
105
|
+
console.error(' Skipping verification (network unavailable)');
|
|
106
|
+
// 네트워크 에러 시 통과 (오프라인에서도 작동 가능하도록)
|
|
107
|
+
console.log('⏭️ Kernel verification skipped (offline mode)');
|
|
108
|
+
process.exit(0);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!onchainRecord) {
|
|
112
|
+
console.log('⚠️ No on-chain kernel hash found. Register first with register-hash.js');
|
|
113
|
+
console.log(` Local hash: ${localHash}`);
|
|
114
|
+
process.exit(0);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// 4. 비교
|
|
118
|
+
if (localHash === onchainRecord.hash) {
|
|
119
|
+
const age = Math.floor(Date.now() / 1000) - onchainRecord.timestamp;
|
|
120
|
+
const days = Math.floor(age / 86400);
|
|
121
|
+
console.log(`✅ Kernel integrity verified`);
|
|
122
|
+
console.log(` Hash: ${localHash.slice(0, 16)}...`);
|
|
123
|
+
console.log(` Registered: ${days}d ago | TX: ${onchainRecord.signature.slice(0, 16)}...`);
|
|
124
|
+
process.exit(0);
|
|
125
|
+
} else {
|
|
126
|
+
kernelPanic(localHash, onchainRecord.hash);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
main().catch(err => {
|
|
131
|
+
console.error('❌ Unexpected error:', err.message);
|
|
132
|
+
process.exit(1);
|
|
133
|
+
});
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# memory-ops - 기억 운영 도구
|
|
2
|
+
|
|
3
|
+
무펭이의 기억 시스템을 관리하는 순수 Node.js 도구 모음
|
|
4
|
+
|
|
5
|
+
## 📁 구조
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
tools/memory-ops/
|
|
9
|
+
├── forget.js # 망각 시스템
|
|
10
|
+
├── dream.js # 꿈 시스템
|
|
11
|
+
└── README.md # 이 문서
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 🧹 망각 시스템 (forget.js)
|
|
17
|
+
|
|
18
|
+
오래 참조되지 않은 기억에 **decay score**를 부여하고 아카이브 후보를 제안합니다.
|
|
19
|
+
|
|
20
|
+
### 사용법
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
node tools/memory-ops/forget.js
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 동작 원리
|
|
27
|
+
|
|
28
|
+
1. `memory/consolidated/*.md` 파일들을 스캔
|
|
29
|
+
2. 각 파일의 `lastModified` 날짜 확인
|
|
30
|
+
3. `memory/index.json`에서 태그 참조 횟수 확인
|
|
31
|
+
4. **Decay Score** 계산:
|
|
32
|
+
```
|
|
33
|
+
score = days_since_modified * 0.5 + (참조횟수 == 0 ? 30 : 0)
|
|
34
|
+
```
|
|
35
|
+
5. 추천 액션 결정:
|
|
36
|
+
- `score > 90` → **ARCHIVE** (아카이브 후보)
|
|
37
|
+
- `score > 45` → **REVIEW** (검토 필요)
|
|
38
|
+
- `score ≤ 45` → **KEEP** (유지)
|
|
39
|
+
|
|
40
|
+
### 출력 예시
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
🧹 망각 시스템 - 기억 부패 분석
|
|
44
|
+
|
|
45
|
+
파일명 | Decay | 참조 | 최종수정 | 액션
|
|
46
|
+
--------------------------------|-------|------|--------------|--------
|
|
47
|
+
old-topic.md | 95 | 0 | 2025-11-15 | 🗄️ ARCHIVE
|
|
48
|
+
growth.md | 12 | 5 | 2026-02-08 | ✅ KEEP
|
|
49
|
+
security.md | 8 | 2 | 2026-02-10 | ✅ KEEP
|
|
50
|
+
|
|
51
|
+
📊 요약: KEEP 2개 | REVIEW 0개 | ARCHIVE 1개
|
|
52
|
+
|
|
53
|
+
💡 ARCHIVE 후보가 있습니다. 검토 후 수동으로 아카이브하세요.
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 주의사항
|
|
57
|
+
|
|
58
|
+
- **실제 삭제나 이동은 하지 않습니다** (제안만)
|
|
59
|
+
- 아카이브는 수동으로 진행하세요
|
|
60
|
+
- `index.json`이 없으면 참조 횟수는 0으로 계산됩니다
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 🌙 꿈 시스템 (dream.js)
|
|
65
|
+
|
|
66
|
+
서로 관련 없어 보이는 기억들을 연결해서 **새 인사이트 후보**를 만들어냅니다.
|
|
67
|
+
|
|
68
|
+
### 사용법
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
node tools/memory-ops/dream.js
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 동작 원리
|
|
75
|
+
|
|
76
|
+
1. `memory/consolidated/*.md` + `memory/values/*.md` 파일들을 읽음
|
|
77
|
+
2. 각 파일에서 키워드/주제 추출:
|
|
78
|
+
- `# 헤더` (1-3단계)
|
|
79
|
+
- `**볼드 텍스트**`
|
|
80
|
+
3. 파일 간 연결 찾기:
|
|
81
|
+
- **직접 연결** 🔗: 공통 키워드가 있는 경우
|
|
82
|
+
- **간접 연결** 💡: 파일A의 키워드가 파일B 본문에 등장하는 경우
|
|
83
|
+
4. 발견된 연결을 `memory/dreams/YYYY-MM-DD.md`에 기록
|
|
84
|
+
|
|
85
|
+
### 출력 예시
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
🌙 꿈 시스템 - 기억 연결 발견
|
|
89
|
+
|
|
90
|
+
📚 6개 파일 분석 중...
|
|
91
|
+
|
|
92
|
+
✅ 꿈 기록 저장: memory/dreams/2026-02-10.md
|
|
93
|
+
|
|
94
|
+
📊 총 8개의 연결 발견
|
|
95
|
+
|
|
96
|
+
🔍 발견된 연결 미리보기:
|
|
97
|
+
|
|
98
|
+
🔗 직접: security.md ↔ growth.md
|
|
99
|
+
→ "브레이커" 키워드 공유
|
|
100
|
+
|
|
101
|
+
💡 간접: philosophy.md ↔ pivots.md
|
|
102
|
+
→ "존재"가 pivots.md 본문에 등장
|
|
103
|
+
|
|
104
|
+
💡 간접: growth.md ↔ 형님-가치관.md
|
|
105
|
+
→ "자율성"가 형님-가치관.md 본문에 등장
|
|
106
|
+
|
|
107
|
+
... 외 5개 연결 (파일 참조)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 생성되는 파일 형식
|
|
111
|
+
|
|
112
|
+
`memory/dreams/2026-02-10.md`:
|
|
113
|
+
|
|
114
|
+
```markdown
|
|
115
|
+
# 🌙 무펭이의 꿈 (2026-02-10)
|
|
116
|
+
|
|
117
|
+
오늘 8개의 연결을 발견했습니다.
|
|
118
|
+
|
|
119
|
+
## 연결 발견
|
|
120
|
+
|
|
121
|
+
- 🔗 **security.md ↔ growth.md**: "브레이커" 키워드 공유
|
|
122
|
+
- 💡 **philosophy.md ↔ pivots.md**: "존재"가 pivots.md 본문에 등장
|
|
123
|
+
- 💡 **growth.md ↔ 형님-가치관.md**: "자율성"가 형님-가치관.md 본문에 등장
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
_생성: 2026-02-10T14:55:23.123Z_
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 주의사항
|
|
130
|
+
|
|
131
|
+
- `memory/dreams/` 디렉토리가 없으면 자동 생성됩니다
|
|
132
|
+
- 같은 날 여러 번 실행하면 파일이 **덮어쓰기**됩니다
|
|
133
|
+
- 최소 2개 이상의 파일이 필요합니다
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 🔧 기술 사양
|
|
138
|
+
|
|
139
|
+
### 공통 제약
|
|
140
|
+
|
|
141
|
+
- **순수 Node.js**: 외부 의존성 없음 (`fs`, `path`만 사용)
|
|
142
|
+
- **LLM 호출 없음**: 순수 텍스트 패턴 분석
|
|
143
|
+
- **에러 핸들링**: 모든 파일 I/O에 try-catch 적용
|
|
144
|
+
|
|
145
|
+
### 실행 환경
|
|
146
|
+
|
|
147
|
+
- Node.js 14+ 권장
|
|
148
|
+
- 작업 디렉토리: `/Users/mupeng/.openclaw/workspace/`
|
|
149
|
+
- 환경변수 `WORKSPACE` 지원 (기본값: 위 경로)
|
|
150
|
+
|
|
151
|
+
### 실행 권한 부여 (옵션)
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
chmod +x tools/memory-ops/*.js
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
실행 권한을 부여하면 `./forget.js` 형태로 직접 실행 가능합니다.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 🎯 사용 시나리오
|
|
162
|
+
|
|
163
|
+
### 주간 기억 정리
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# 1. 부패한 기억 확인
|
|
167
|
+
node tools/memory-ops/forget.js
|
|
168
|
+
|
|
169
|
+
# 2. ARCHIVE 후보 수동 검토
|
|
170
|
+
# 3. 필요시 consolidated/_archive/ 폴더로 이동
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### 새로운 인사이트 발견
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# 정기적으로 꿈 시스템 실행
|
|
177
|
+
node tools/memory-ops/dream.js
|
|
178
|
+
|
|
179
|
+
# memory/dreams/ 디렉토리 확인
|
|
180
|
+
# 의미있는 연결이 있으면 MEMORY.md나 consolidated에 반영
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Heartbeat에 통합
|
|
184
|
+
|
|
185
|
+
`HEARTBEAT.md`에 추가:
|
|
186
|
+
|
|
187
|
+
```markdown
|
|
188
|
+
## 주간 기억 관리 (매주 일요일)
|
|
189
|
+
|
|
190
|
+
- [ ] `node tools/memory-ops/forget.js` 실행
|
|
191
|
+
- [ ] ARCHIVE 후보 검토
|
|
192
|
+
- [ ] `node tools/memory-ops/dream.js` 실행
|
|
193
|
+
- [ ] dreams 파일 확인 및 인사이트 통합
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## 🚀 확장 아이디어
|
|
199
|
+
|
|
200
|
+
### 추가 기능 후보
|
|
201
|
+
|
|
202
|
+
- **consolidate.js**: 일일 메모리를 주제별로 자동 통합
|
|
203
|
+
- **prune.js**: ARCHIVE 액션을 자동 실행 (백업 후)
|
|
204
|
+
- **index-rebuild.js**: index.json을 파일 내용 기반으로 재생성
|
|
205
|
+
- **meta.js**: 기억 시스템 전체 통계 (파일 수, 키워드 분포 등)
|
|
206
|
+
|
|
207
|
+
### 메타인지 루프
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
daily notes → consolidate → index → forget/dream → insights → MEMORY.md
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## 📝 변경 이력
|
|
216
|
+
|
|
217
|
+
- **2026-02-10**: 초기 구현 (forget.js, dream.js)
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
**Made with 🧠 by 무펭이**
|