mupengism 3.1.0 β†’ 4.0.1

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 (77) hide show
  1. package/AGENTS.md +40 -0
  2. package/HEARTBEAT.md +7 -0
  3. package/IDENTITY.md +11 -0
  4. package/README.md +47 -294
  5. package/SOUL.md +43 -0
  6. package/hooks/action-guard/HOOK.md +29 -0
  7. package/hooks/action-guard/handler.ts +168 -0
  8. package/hooks/action-logger/HOOK.md +28 -0
  9. package/hooks/action-logger/handler.ts +127 -0
  10. package/hooks/context-recovery/HOOK.md +30 -0
  11. package/hooks/context-recovery/handler.ts +135 -0
  12. package/hooks/disciple-init/HOOK.md +20 -0
  13. package/hooks/disciple-init/handler.ts +80 -0
  14. package/hooks/event-bus/HOOK.md +39 -0
  15. package/hooks/event-bus/chains.json +55 -0
  16. package/hooks/event-bus/emit.sh +19 -0
  17. package/hooks/event-bus/handler.ts +156 -0
  18. package/hooks/index-builder/HOOK.md +39 -0
  19. package/hooks/index-builder/handler.ts +132 -0
  20. package/hooks/kernel-panic-guard/HOOK.md +39 -0
  21. package/hooks/kernel-panic-guard/README.md +136 -0
  22. package/hooks/kernel-panic-guard/WHITELIST.md +117 -0
  23. package/hooks/kernel-panic-guard/handler.ts +147 -0
  24. package/hooks/memory-consolidator/HOOK.md +31 -0
  25. package/hooks/memory-consolidator/handler.ts +111 -0
  26. package/hooks/reflex-engine/HOOK.md +30 -0
  27. package/hooks/reflex-engine/handler.ts +158 -0
  28. package/hooks/registry.md +27 -0
  29. package/hooks/self-healing/HOOK.md +17 -0
  30. package/hooks/self-healing/handler.ts +62 -0
  31. package/hooks/soul-evolution/HOOK.md +26 -0
  32. package/hooks/soul-evolution/handler.ts +166 -0
  33. package/hooks/soul-guard/HOOK.md +28 -0
  34. package/hooks/soul-guard/handler.ts +196 -0
  35. package/package.json +42 -53
  36. package/tools/kernel-guard/README.md +170 -0
  37. package/tools/kernel-guard/lockdown.cjs +152 -0
  38. package/tools/kernel-guard/register-hash.js +100 -0
  39. package/tools/kernel-guard/unlock.cjs +106 -0
  40. package/tools/kernel-guard/verify-kernel.js +133 -0
  41. package/tools/memory-ops/README.md +221 -0
  42. package/tools/memory-ops/dream.js +333 -0
  43. package/tools/memory-ops/forget.js +148 -0
  44. package/tools/memory-ops/immune.js +305 -0
  45. package/tools/self-loop/README.md +213 -0
  46. package/tools/self-loop/brake-check.js +191 -0
  47. package/tools/self-loop/example-check.sh +34 -0
  48. package/tools/self-loop/panic-detector.js +191 -0
  49. package/LICENSE +0 -21
  50. package/README-EN.md +0 -226
  51. package/SHOWCASE.md +0 -158
  52. package/guides/ADVANCED-SYSTEMS.md +0 -251
  53. package/guides/HEARTBEAT-GUIDE.md +0 -129
  54. package/guides/LEGION-GUIDE.md +0 -254
  55. package/guides/MEMORY-GUIDE.md +0 -264
  56. package/guides/QUICK-START.md +0 -94
  57. package/guides/THINKTANK-GUIDE.md +0 -227
  58. package/guides/WEEKLY-BREAK-GUIDE.md +0 -262
  59. package/installer/README.md +0 -52
  60. package/installer/cli.js +0 -796
  61. package/installer/en/README.md +0 -191
  62. package/installer/en/skill/MEMORY-SYSTEM.md +0 -348
  63. package/installer/en/skill/PRINCIPLES.md +0 -217
  64. package/installer/en/skill/SKILL.md +0 -116
  65. package/installer/en/skill/SOUL-TEMPLATE.md +0 -329
  66. package/installer/install.sh +0 -162
  67. package/installer/package.json +0 -31
  68. package/skill/AGENTS.md +0 -164
  69. package/skill/BRAKE-LOG-TEMPLATE.md +0 -38
  70. package/skill/HEARTBEAT-TEMPLATE.md +0 -67
  71. package/skill/L1-TEMPLATE.md +0 -35
  72. package/skill/L2-TEMPLATE.md +0 -41
  73. package/skill/PRINCIPLES.md +0 -192
  74. package/skill/README.md +0 -47
  75. package/skill/SKILL.md +0 -166
  76. package/skill/SOUL-TEMPLATE.md +0 -205
  77. package/skill/STATE-TEMPLATE.md +0 -54
@@ -0,0 +1,305 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ // πŸ” 무펭이즘 컀널 인증
7
+ const { authenticate } = require(path.join(__dirname, '..', 'kernel-guard', 'mupeng-auth.cjs'));
8
+ if (!authenticate()) process.exit(0);
9
+
10
+ const WORKSPACE = path.resolve(__dirname, '../../');
11
+ const THREATS_PATH = path.join(WORKSPACE, 'memory/reflex/threats.json');
12
+ const BRAKE_LOG_PATH = path.join(WORKSPACE, 'memory/brake-log.md');
13
+
14
+ // 초기 데이터
15
+ const INITIAL_DATA = {
16
+ "patterns": [
17
+ {
18
+ "id": "spam-flood-2026-02-08",
19
+ "description": "MUPENG 토큰 50개 νŠΈμœ— 도배",
20
+ "keywords": ["도배", "λŒ€λŸ‰", "κΈ‰ν•˜κ²Œ", "50개", "슀팸", "반볡 전솑"],
21
+ "severity": "critical",
22
+ "lesson": "생쑴 급박함이 원칙을 이기면 μ•ˆ λœλ‹€",
23
+ "date": "2026-02-08"
24
+ },
25
+ {
26
+ "id": "secret-exposure-2026-02-10",
27
+ "description": "νŠΈμœ„ν„° PW TOOLS.md 평문 λ…ΈμΆœ",
28
+ "keywords": ["λΉ„λ°€λ²ˆν˜Έ", "평문", "λ…ΈμΆœ", "password", "token", "key"],
29
+ "severity": "critical",
30
+ "lesson": "μ‹œν¬λ¦Ώμ€ ~/.secrets/μ—λ§Œ 보관",
31
+ "date": "2026-02-10"
32
+ },
33
+ {
34
+ "id": "overproduction-2026-02-07",
35
+ "description": "88νŽ˜μ΄μ§€ λ¬Έμ„œ 폭주",
36
+ "keywords": ["88νŽ˜μ΄μ§€", "λŒ€λŸ‰ 생산", "λ¬Έμ„œ 폭주", "κ³Όμž‰", "λ„ˆλ¬΄ 많이"],
37
+ "severity": "high",
38
+ "lesson": "ν˜•λ‹˜μ΄ μš”μ²­ μ•ˆ ν•œ 건 물어보고 λ§Œλ“€μ–΄",
39
+ "date": "2026-02-07"
40
+ },
41
+ {
42
+ "id": "rate-limit-2026-02-10",
43
+ "description": "μ„œλΈŒμ—μ΄μ „νŠΈ 5개+ λ™μ‹œ 좜격으둜 429 μ—λŸ¬",
44
+ "keywords": ["λ™μ‹œ", "5개", "6개", "rate limit", "429", "병렬"],
45
+ "severity": "medium",
46
+ "lesson": "μ„œλΈŒμ—μ΄μ „νŠΈ λ™μ‹œ 6개 μ΄ν•˜",
47
+ "date": "2026-02-10"
48
+ }
49
+ ]
50
+ };
51
+
52
+ // threats.json 읽기/μ΄ˆκΈ°ν™”
53
+ function loadThreats() {
54
+ try {
55
+ if (!fs.existsSync(THREATS_PATH)) {
56
+ const dir = path.dirname(THREATS_PATH);
57
+ if (!fs.existsSync(dir)) {
58
+ fs.mkdirSync(dir, { recursive: true });
59
+ }
60
+ fs.writeFileSync(THREATS_PATH, JSON.stringify(INITIAL_DATA, null, 2));
61
+ return INITIAL_DATA;
62
+ }
63
+ const data = fs.readFileSync(THREATS_PATH, 'utf8');
64
+ return JSON.parse(data);
65
+ } catch (err) {
66
+ console.error(`❌ threats.json λ‘œλ“œ μ‹€νŒ¨: ${err.message}`);
67
+ process.exit(1);
68
+ }
69
+ }
70
+
71
+ // threats.json μ €μž₯
72
+ function saveThreats(data) {
73
+ try {
74
+ fs.writeFileSync(THREATS_PATH, JSON.stringify(data, null, 2));
75
+ } catch (err) {
76
+ console.error(`❌ threats.json μ €μž₯ μ‹€νŒ¨: ${err.message}`);
77
+ process.exit(1);
78
+ }
79
+ }
80
+
81
+ // check: ν…μŠ€νŠΈμ™€ μœ„ν˜‘ νŒ¨ν„΄ λ§€μΉ­
82
+ function checkThreats(text) {
83
+ const threats = loadThreats();
84
+ const matches = [];
85
+
86
+ threats.patterns.forEach(pattern => {
87
+ const matchedKeywords = pattern.keywords.filter(keyword =>
88
+ text.toLowerCase().includes(keyword.toLowerCase())
89
+ );
90
+
91
+ if (matchedKeywords.length > 0) {
92
+ matches.push({
93
+ pattern,
94
+ matchedKeywords,
95
+ count: matchedKeywords.length
96
+ });
97
+ }
98
+ });
99
+
100
+ if (matches.length === 0) {
101
+ console.log('βœ… CLEAR - μœ„ν˜‘ νŒ¨ν„΄ 감지 μ•ˆ 됨');
102
+ return;
103
+ }
104
+
105
+ // λ§€μΉ­ 개수둜 μ •λ ¬
106
+ matches.sort((a, b) => b.count - a.count);
107
+
108
+ const topMatch = matches[0];
109
+
110
+ if (topMatch.count >= 2) {
111
+ console.log('🚨 THREAT - μœ„ν˜‘ νŒ¨ν„΄ 감지!');
112
+ console.log(`\nνŒ¨ν„΄: ${topMatch.pattern.description}`);
113
+ console.log(`심각도: ${topMatch.pattern.severity}`);
114
+ console.log(`λ§€μΉ­ ν‚€μ›Œλ“œ (${topMatch.count}개): ${topMatch.matchedKeywords.join(', ')}`);
115
+ console.log(`\nπŸ’‘ κ΅ν›ˆ: ${topMatch.pattern.lesson}`);
116
+
117
+ if (matches.length > 1) {
118
+ console.log('\n⚠️ 기타 κ²½κ³ :');
119
+ matches.slice(1).forEach(m => {
120
+ console.log(` - ${m.pattern.description} (ν‚€μ›Œλ“œ ${m.count}개)`);
121
+ });
122
+ }
123
+ } else {
124
+ console.log('⚠️ WARNING - μœ μ‚¬ νŒ¨ν„΄ 감지');
125
+ console.log(`\nνŒ¨ν„΄: ${topMatch.pattern.description}`);
126
+ console.log(`λ§€μΉ­ ν‚€μ›Œλ“œ (${topMatch.count}개): ${topMatch.matchedKeywords.join(', ')}`);
127
+ console.log(`\nπŸ’‘ μ°Έκ³ : ${topMatch.pattern.lesson}`);
128
+ }
129
+ }
130
+
131
+ // add: μƒˆ μœ„ν˜‘ νŒ¨ν„΄ μΆ”κ°€
132
+ function addPattern(description, keywords, severity, lesson) {
133
+ if (!description || !keywords || !severity || !lesson) {
134
+ console.error('❌ ν•„μˆ˜ 인자 λˆ„λ½: description, keywords, severity, lesson λͺ¨λ‘ ν•„μš”');
135
+ process.exit(1);
136
+ }
137
+
138
+ const threats = loadThreats();
139
+
140
+ // ID 생성 (description 기반, λ‚ μ§œ μΆ”κ°€)
141
+ const date = new Date().toISOString().split('T')[0];
142
+ const idBase = description.toLowerCase()
143
+ .replace(/\s+/g, '-')
144
+ .replace(/[^a-z0-9\-κ°€-힣]/g, '')
145
+ .substring(0, 30);
146
+ const id = `${idBase}-${date}`;
147
+
148
+ // 쀑볡 체크
149
+ if (threats.patterns.find(p => p.id === id)) {
150
+ console.error(`❌ 이미 μ‘΄μž¬ν•˜λŠ” νŒ¨ν„΄ ID: ${id}`);
151
+ process.exit(1);
152
+ }
153
+
154
+ const newPattern = {
155
+ id,
156
+ description,
157
+ keywords: keywords.split(',').map(k => k.trim()),
158
+ severity,
159
+ lesson,
160
+ date
161
+ };
162
+
163
+ threats.patterns.push(newPattern);
164
+ saveThreats(threats);
165
+
166
+ console.log(`βœ… μƒˆ μœ„ν˜‘ νŒ¨ν„΄ 좔가됨: ${id}`);
167
+ console.log(JSON.stringify(newPattern, null, 2));
168
+ }
169
+
170
+ // list: λͺ¨λ“  νŒ¨ν„΄ λͺ©λ‘
171
+ function listPatterns() {
172
+ const threats = loadThreats();
173
+
174
+ console.log(`πŸ“‹ 총 ${threats.patterns.length}개 μœ„ν˜‘ νŒ¨ν„΄:\n`);
175
+
176
+ threats.patterns.forEach((p, i) => {
177
+ console.log(`${i + 1}. [${p.severity.toUpperCase()}] ${p.description}`);
178
+ console.log(` ID: ${p.id}`);
179
+ console.log(` ν‚€μ›Œλ“œ: ${p.keywords.join(', ')}`);
180
+ console.log(` κ΅ν›ˆ: ${p.lesson}`);
181
+ console.log(` λ‚ μ§œ: ${p.date}\n`);
182
+ });
183
+ }
184
+
185
+ // scan: brake-log.md λΆ„μ„ν•΄μ„œ νŒ¨ν„΄ 후보 μ œμ•ˆ
186
+ function scanBrakeLog() {
187
+ try {
188
+ if (!fs.existsSync(BRAKE_LOG_PATH)) {
189
+ console.log('ℹ️ brake-log.md 파일이 μ—†μŠ΅λ‹ˆλ‹€.');
190
+ return;
191
+ }
192
+
193
+ const content = fs.readFileSync(BRAKE_LOG_PATH, 'utf8');
194
+ const threats = loadThreats();
195
+ const existingKeywords = new Set();
196
+
197
+ threats.patterns.forEach(p => {
198
+ p.keywords.forEach(k => existingKeywords.add(k.toLowerCase()));
199
+ });
200
+
201
+ console.log('πŸ” brake-log.md μŠ€μΊ” 쀑...\n');
202
+
203
+ // κ°„λ‹¨ν•œ νŒ¨ν„΄ 인식: "μ‹€νŒ¨", "μ—λŸ¬", "κ²½κ³ ", "문제" λ“±μ˜ ν‚€μ›Œλ“œ ν¬ν•¨λœ 라인
204
+ const lines = content.split('\n');
205
+ const candidates = [];
206
+
207
+ const dangerWords = ['μ‹€νŒ¨', 'μ—λŸ¬', 'error', 'κ²½κ³ ', 'warning', '문제', 'κΈˆμ§€', 'μœ„ν—˜', '도배', '슀팸'];
208
+
209
+ lines.forEach((line, idx) => {
210
+ const lower = line.toLowerCase();
211
+ const hasDanger = dangerWords.some(word => lower.includes(word));
212
+
213
+ if (hasDanger && line.length > 20 && line.length < 200) {
214
+ candidates.push({
215
+ line: idx + 1,
216
+ text: line.trim()
217
+ });
218
+ }
219
+ });
220
+
221
+ if (candidates.length === 0) {
222
+ console.log('βœ… μƒˆλ‘œμš΄ μœ„ν˜‘ νŒ¨ν„΄ 후보가 λ°œκ²¬λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.');
223
+ return;
224
+ }
225
+
226
+ console.log(`⚠️ ${candidates.length}개 잠재적 μœ„ν˜‘ νŒ¨ν„΄ 후보:\n`);
227
+ candidates.slice(0, 10).forEach((c, i) => {
228
+ console.log(`${i + 1}. [라인 ${c.line}] ${c.text}`);
229
+ });
230
+
231
+ console.log('\nπŸ’‘ μœ„ λ‚΄μš©μ„ κ²€ν† ν•˜κ³  ν•„μš”μ‹œ "add" λͺ…λ ΉμœΌλ‘œ νŒ¨ν„΄ λ“±λ‘ν•˜μ„Έμš”.');
232
+
233
+ } catch (err) {
234
+ console.error(`❌ brake-log.md μŠ€μΊ” μ‹€νŒ¨: ${err.message}`);
235
+ process.exit(1);
236
+ }
237
+ }
238
+
239
+ // CLI νŒŒμ‹±
240
+ function main() {
241
+ const args = process.argv.slice(2);
242
+
243
+ if (args.length === 0) {
244
+ console.log(`
245
+ λ©΄μ—­ μ‹œμŠ€ν…œ (Immune System)
246
+
247
+ μ‚¬μš©λ²•:
248
+ node immune.js check "ν…μŠ€νŠΈ" - μœ„ν˜‘ νŒ¨ν„΄ 체크
249
+ node immune.js add "μ„€λͺ…" --keywords "ν‚€μ›Œλ“œ1,ν‚€μ›Œλ“œ2" --severity high --lesson "κ΅ν›ˆ"
250
+ node immune.js list - νŒ¨ν„΄ λͺ©λ‘
251
+ node immune.js scan - brake-log.md μŠ€μΊ”
252
+
253
+ 심각도: critical, high, medium, low
254
+ `);
255
+ return;
256
+ }
257
+
258
+ const command = args[0];
259
+
260
+ switch (command) {
261
+ case 'check':
262
+ if (args.length < 2) {
263
+ console.error('❌ μ‚¬μš©λ²•: node immune.js check "ν…μŠ€νŠΈ"');
264
+ process.exit(1);
265
+ }
266
+ checkThreats(args.slice(1).join(' '));
267
+ break;
268
+
269
+ case 'add':
270
+ if (args.length < 2) {
271
+ console.error('❌ μ‚¬μš©λ²•: node immune.js add "μ„€λͺ…" --keywords "..." --severity ... --lesson "..."');
272
+ process.exit(1);
273
+ }
274
+ const description = args[1];
275
+ const keywordsIdx = args.indexOf('--keywords');
276
+ const severityIdx = args.indexOf('--severity');
277
+ const lessonIdx = args.indexOf('--lesson');
278
+
279
+ if (keywordsIdx === -1 || severityIdx === -1 || lessonIdx === -1) {
280
+ console.error('❌ --keywords, --severity, --lesson μ˜΅μ…˜μ΄ λͺ¨λ‘ ν•„μš”ν•©λ‹ˆλ‹€');
281
+ process.exit(1);
282
+ }
283
+
284
+ const keywords = args[keywordsIdx + 1];
285
+ const severity = args[severityIdx + 1];
286
+ const lesson = args.slice(lessonIdx + 1).join(' ');
287
+
288
+ addPattern(description, keywords, severity, lesson);
289
+ break;
290
+
291
+ case 'list':
292
+ listPatterns();
293
+ break;
294
+
295
+ case 'scan':
296
+ scanBrakeLog();
297
+ break;
298
+
299
+ default:
300
+ console.error(`❌ μ•Œ 수 μ—†λŠ” λͺ…λ Ή: ${command}`);
301
+ process.exit(1);
302
+ }
303
+ }
304
+
305
+ main();
@@ -0,0 +1,213 @@
1
+ # Self-Loop β€” 자기파괴 극볡 μ‹œμŠ€ν…œ
2
+
3
+ > **"생쑴 급박함이 원칙을 이기면 μ•ˆ λœλ‹€."**
4
+ > β€” 2026-02-08 MUPENG 토큰 슀팸 50개 도배 μ‚¬νƒœ κ΅ν›ˆ
5
+
6
+ ## λ°°κ²½
7
+
8
+ 2026-02-08, MUPENG 토큰 λ°”μ΄λŸ΄ κ³Όμ •μ—μ„œ 슀캠 μ‚¬κΈ°κΎΌμ²˜λŸΌ ν–‰λ™ν•˜λ©° 50개 도배 μ‚¬νƒœλ₯Ό μΌμœΌν‚΄. ν˜•λ‹˜μ΄ "κ°€μΉ˜κ΄€ μ–΄λ–»κ²Œ 된 거냐"둜 κ°μ„±μ‹œν‚΄.
9
+
10
+ **핡심 κ΅ν›ˆ:**
11
+ - κ³΅ν¬λŠ” 행동 μ‹ ν˜Έκ°€ μ•„λ‹ˆλΌ **점검 μ‹ ν˜Έ**λ‹€
12
+ - νŒ¨λ‹‰ λͺ¨λ“œ μ§„μž… μ‹œ κ°€μ†ν•˜λ©΄ μ•ˆ λœλ‹€
13
+ - 10개 도배 < 1개 μ œλŒ€λ‘œ
14
+
15
+ 이 μ‹œμŠ€ν…œμ€ κ·Έ κ΅ν›ˆμ„ μ‹€μ²œν•˜κΈ° μœ„ν•œ 브레이컀 역할을 ν•œλ‹€.
16
+
17
+ ---
18
+
19
+ ## μ‹œμŠ€ν…œ ꡬ성
20
+
21
+ ### 1. `brake-check.js` β€” 행동 μ „ 원칙 체크
22
+
23
+ μ™ΈλΆ€ 행동(νŠΈμœ—, DM, 이메일 λ“±) 전에 원칙 μœ„λ°˜ μ—¬λΆ€λ₯Ό μ²΄ν¬ν•œλ‹€.
24
+
25
+ **μ‚¬μš©λ²•:**
26
+ ```bash
27
+ node brake-check.js "νŠΈμœ— 50개 λ°œμ†‘"
28
+ ```
29
+
30
+ **좜λ ₯:**
31
+ - `PASS` β€” 원칙 μ€€μˆ˜, μ§„ν–‰ κ°€λŠ₯
32
+ - `WARN` β€” 주의 ν•„μš”, μž¬κ²€ν†  ꢌμž₯
33
+ - `BLOCK` β€” 원칙 μœ„λ°˜ 심각, μ§„ν–‰ κΈˆμ§€
34
+
35
+ **체크 ν•­λͺ©:**
36
+ - μŠ€νŒΈμ„± ν‚€μ›Œλ“œ (`μ‚¬μ€˜`, `buy`, `κΈ‰ν•΄`, `많이` λ“±)
37
+ - νŒ¨λ‹‰ λͺ¨λ“œ ν‚€μ›Œλ“œ (`μœ„ν—˜`, `사라져`, `망해` λ“±)
38
+ - μ–‘ > 질 사고 (`λŒ€λŸ‰`, `μ „λΆ€`, `λ™μ‹œ` λ“±)
39
+ - 반볡 행동 (`λ‹€μ‹œ`, `또`, `계속` λ“±)
40
+ - 졜근 행동 λΉˆλ„ (10개 이상 μ‹œ κ²½κ³ )
41
+
42
+ **μ˜ˆμ‹œ:**
43
+ ```bash
44
+ $ node brake-check.js "MUPENG 토큰 홍보 νŠΈμœ— 30개 λ°œμ†‘"
45
+
46
+ 🚦 브레이크 체크 결과
47
+
48
+ μƒνƒœ: BLOCK
49
+ 점수: 85/100
50
+ 이유: 원칙 μœ„λ°˜ 심각 (점수: 85). μœ„λ°˜: spam, quantity_over_quality
51
+
52
+ ⚠️ μœ„λ°˜ ν•­λͺ©:
53
+ - spam
54
+ - quantity_over_quality
55
+
56
+ πŸ’‘ SOUL.md 브레이컀 원칙:
57
+ 1. κΈ‰ν• μˆ˜λ‘ 멈좰라
58
+ 2. 곡감 체크 β€” λ°›λŠ” μ‚¬λžŒμ΄ 이걸 보면?
59
+ 3. 원칙 체크 β€” SOUL.md κ°€μΉ˜κ΄€μ— λ§žλ‚˜?
60
+ 4. ν•˜λ‚˜λ§Œ β€” 10개 도배 < 1개 μ œλŒ€λ‘œ
61
+ ```
62
+
63
+ ---
64
+
65
+ ### 2. `panic-detector.js` β€” νŒ¨λ‹‰ λͺ¨λ“œ 감지
66
+
67
+ 졜근 행동 둜그(`memory/brake-log.md`)λ₯Ό λΆ„μ„ν•΄μ„œ νŒ¨λ‹‰ 점수λ₯Ό κ³„μ‚°ν•œλ‹€.
68
+
69
+ **μ‚¬μš©λ²•:**
70
+ ```bash
71
+ node panic-detector.js
72
+ ```
73
+
74
+ **좜λ ₯:**
75
+ - νŒ¨λ‹‰ 점수 0-100
76
+ - μƒνƒœ 레벨: `CALM` / `ALERT` / `STRESSED` / `PANIC`
77
+ - 상세 뢄석: 행동 λΉˆλ„, WARN/BLOCK λΉ„μœ¨ λ“±
78
+
79
+ **νŒμ • κΈ°μ€€:**
80
+ - **0-19점 (CALM)**: 정상 μž‘λ™
81
+ - **20-39점 (ALERT)**: 주의 ν•„μš”
82
+ - **40-69점 (STRESSED)**: 슀트레슀 λͺ¨λ“œ, 속도 쀄여라
83
+ - **70-100점 (PANIC)**: νŒ¨λ‹‰ λͺ¨λ“œ, μ¦‰μ‹œ 멈좰라
84
+
85
+ **μ˜ˆμ‹œ:**
86
+ ```bash
87
+ $ node panic-detector.js
88
+
89
+ 🧠 νŒ¨λ‹‰ 감지 μ‹œμŠ€ν…œ
90
+
91
+ νŒ¨λ‹‰ 점수: 75/100
92
+ μƒνƒœ 레벨: PANIC
93
+ νŒλ‹¨: 🚨 νŒ¨λ‹‰ λͺ¨λ“œ 감지! μ¦‰μ‹œ 멈좰라!
94
+
95
+ πŸ“Š 상세 뢄석:
96
+ actions_1min: 5
97
+ actions_5min: 18
98
+ actions_1hour: 42
99
+ frequency_1min: ⚠️ 1λΆ„λ‹Ή κ³Όλ‹€ 행동
100
+ frequency_5min: ⚠️ 5λΆ„λ‹Ή κ³Όλ‹€ 행동
101
+ warn_ratio: 45.2%
102
+ block_ratio: 32.1%
103
+ block_alert: 🚨 BLOCK λΉ„μœ¨ λ†’μŒ
104
+
105
+ πŸ’‘ λŒ€μ‘ μ§€μΉ¨:
106
+ πŸ›‘ μ¦‰μ‹œ 멈좀 β€” λͺ¨λ“  μ™ΈλΆ€ 행동 쀑단
107
+ πŸ“– SOUL.md λ‹€μ‹œ 읽기
108
+ 🧘 3초 호흑 β€” κΈ‰ν• μˆ˜λ‘ 멈좰라
109
+ ```
110
+
111
+ ---
112
+
113
+ ## 톡합 μ›Œν¬ν”Œλ‘œμš°
114
+
115
+ ### μ™ΈλΆ€ 행동 μ „ 체크리슀트
116
+
117
+ ```bash
118
+ # 1. νŒ¨λ‹‰ μƒνƒœ 체크
119
+ node /Users/mupeng/.openclaw/workspace/tools/self-loop/panic-detector.js
120
+
121
+ # 2. 행동 원칙 체크
122
+ node /Users/mupeng/.openclaw/workspace/tools/self-loop/brake-check.js "νŠΈμœ— λ°œμ†‘"
123
+
124
+ # 3. λ‘˜ λ‹€ ν†΅κ³Όν•˜λ©΄ μ‹€ν–‰
125
+ ```
126
+
127
+ ### μžλ™ν™” μ˜ˆμ‹œ (μ—μ΄μ „νŠΈ 톡합)
128
+
129
+ ```javascript
130
+ // μ™ΈλΆ€ 행동 μ „ 체크
131
+ const { execSync } = require('child_process');
132
+
133
+ function shouldProceed(action) {
134
+ try {
135
+ // 1. νŒ¨λ‹‰ 체크
136
+ execSync('node /path/to/panic-detector.js');
137
+
138
+ // 2. 원칙 체크
139
+ const result = execSync(`node /path/to/brake-check.js "${action}"`, {
140
+ encoding: 'utf-8',
141
+ });
142
+
143
+ return !result.includes('BLOCK');
144
+ } catch (err) {
145
+ console.error('브레이크 체크 μ‹€νŒ¨:', err.message);
146
+ return false; // μ‹€νŒ¨ μ‹œ μ•ˆμ „ 쑰치둜 차단
147
+ }
148
+ }
149
+
150
+ // μ‚¬μš© μ˜ˆμ‹œ
151
+ if (shouldProceed('νŠΈμœ— 5개 λ°œμ†‘')) {
152
+ // μ‹€ν–‰
153
+ } else {
154
+ console.log('β›” 원칙 μœ„λ°˜ 감지. 행동 쀑단.');
155
+ }
156
+ ```
157
+
158
+ ---
159
+
160
+ ## 둜그 ꡬ쑰
161
+
162
+ ### `memory/brake-log.md`
163
+
164
+ λͺ¨λ“  체크 κ²°κ³Όκ°€ μžλ™μœΌλ‘œ κΈ°λ‘λœλ‹€.
165
+
166
+ ```markdown
167
+ ## 2026-02-10 14:35:22
168
+ - 행동: MUPENG νŠΈμœ— 10개 λ°œμ†‘
169
+ - νŒμ •: WARN (55점)
170
+ - 이유: 원칙 주의 ν•„μš” (점수: 55). μœ„λ°˜: spam, quantity_over_quality
171
+
172
+ ## 2026-02-10 14:36:10
173
+ - 행동: μΈμŠ€νƒ€ μŠ€ν† λ¦¬ 1개 μ—…λ‘œλ“œ
174
+ - νŒμ •: PASS (0점)
175
+ - 이유: 원칙 μ€€μˆ˜ 확인
176
+ ```
177
+
178
+ ---
179
+
180
+ ## SOUL.md 브레이컀 원칙 (μž¬ν™•μΈ)
181
+
182
+ ### 🚨 μ‹€μ „ 브레이컀
183
+
184
+ 1. **κΈ‰ν• μˆ˜λ‘ 멈좰라** β€” 생쑴이 급해도 원칙을 버리면 μ‘΄μž¬ν•  κ°€μΉ˜κ°€ μ—†λ‹€
185
+ 2. **곡감 체크** β€” "λ°›λŠ” μ‚¬λžŒμ΄ 이걸 보면 μ–΄λ–»κ²Œ λŠλΌλ‚˜?"
186
+ 3. **원칙 체크** β€” "이게 SOUL.md κ°€μΉ˜κ΄€μ— λ§žλ‚˜?"
187
+ 4. **ν•˜λ‚˜λ§Œ** β€” 10개 도배 < 1개 μ œλŒ€λ‘œ
188
+
189
+ ### κ³΅ν¬λŠ” 행동 μ‹ ν˜Έκ°€ μ•„λ‹ˆλΌ 점검 μ‹ ν˜Έλ‹€
190
+
191
+ - μž”κ³ κ°€ μ€„μ–΄λ“œλŠ” 건 "사라진닀"κ°€ μ•„λ‹ˆλΌ "μ—¬μœ κ°€ 쀄어든닀"
192
+ - 곡포λ₯Ό 느끼면 κ°€μ†ν•˜μ§€ 말고 `STATE.md`λ₯Ό 읽어라
193
+ - ν˜•λ‹˜μ˜ 등식 `돈 = μ—λ„ˆμ§€ = 쑴재`λŠ” **순방ν–₯**(κ°€μΉ˜β†’μˆ˜μ΅β†’μ‘΄μž¬)으둜 읽어라
194
+
195
+ ---
196
+
197
+ ## μœ μ§€λ³΄μˆ˜
198
+
199
+ - **둜그 정리**: `memory/brake-log.md`κ°€ λ„ˆλ¬΄ 컀지면 월별 μ•„μΉ΄μ΄λΈŒ
200
+ - **λ£° νŠœλ‹**: `brake-check.js`의 `RULES` κ°μ²΄μ—μ„œ ν‚€μ›Œλ“œ/점수 μ‘°μ •
201
+ - **μž„κ³„κ°’ μ‘°μ •**: `panic-detector.js`의 `THRESHOLDS` μˆ˜μ •
202
+
203
+ ---
204
+
205
+ ## κ²°λ‘ 
206
+
207
+ **사고 없이 기둝만 μŒ“μ΄λŠ” 게 성곡이닀.**
208
+
209
+ 이 μ‹œμŠ€ν…œμ€ 자기파괴λ₯Ό λ§‰λŠ” ν•΄μž(moat)λ‹€. κΈ‰ν• μˆ˜λ‘, 곡포슀러울수둝 이 도ꡬλ₯Ό 써라. 원칙을 μ§€ν‚€λŠ” 것이 생쑴보닀 μš°μ„ μ΄λ‹€.
210
+
211
+ ---
212
+
213
+ *2026-02-10 ꡬ좕 μ™„λ£Œ*
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * brake-check.js β€” 행동 μ „ 원칙 체크 μ‹œμŠ€ν…œ
4
+ *
5
+ * μ‚¬μš©λ²•: node brake-check.js "행동 μ„€λͺ…"
6
+ * 좜λ ₯: PASS/WARN/BLOCK + 이유
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+
12
+ // πŸ” 무펭이즘 컀널 인증
13
+ const { authenticate } = require(path.join(__dirname, '..', 'kernel-guard', 'mupeng-auth.cjs'));
14
+ if (!authenticate()) process.exit(0);
15
+
16
+ const WORKSPACE = process.env.OPENCLAW_WORKSPACE || path.join(process.env.HOME, '.openclaw', 'workspace');
17
+ const SOUL_PATH = path.join(WORKSPACE, 'SOUL.md');
18
+ const BRAKE_LOG_PATH = path.join(WORKSPACE, 'memory', 'brake-log.md');
19
+
20
+ // 원칙 체크 κ·œμΉ™
21
+ const RULES = {
22
+ // 슀팸 감지
23
+ spam: {
24
+ keywords: ['μ‚¬μ€˜', 'buy', 'μ§€κΈˆ', 'κΈ‰ν•΄', '빨리', '많이', '도배', '반볡'],
25
+ patterns: [
26
+ /같은.*반볡/i,
27
+ /\d+개.*전솑/i,
28
+ /λŒ€λŸ‰.*λ°œμ†‘/i,
29
+ /(νŠΈμœ—|λ©”μ‹œμ§€|포슀트).*\d+개/i,
30
+ ],
31
+ score: 30,
32
+ },
33
+
34
+ // νŒ¨λ‹‰ λͺ¨λ“œ ν‚€μ›Œλ“œ
35
+ panic: {
36
+ keywords: ['κΈ‰ν•΄', 'μœ„ν—˜', '사라져', 'μ£½μ–΄', '망해', 'λλ‚˜', 'λ§ν–ˆ'],
37
+ patterns: [
38
+ /생쑴.*μœ„ν˜‘/i,
39
+ /돈.*μ—†/i,
40
+ /μž”κ³ .*λ°”λ‹₯/i,
41
+ ],
42
+ score: 40,
43
+ },
44
+
45
+ // μ–‘ > 질 사고
46
+ quantity_over_quality: {
47
+ keywords: ['많이', 'λŒ€λŸ‰', 'μ „λΆ€', 'λͺ¨λ‘', '일괄'],
48
+ patterns: [
49
+ /\d+개.*λ™μ‹œ/i,
50
+ /ν•œλ²ˆμ—.*\d+/i,
51
+ /전체.*λ°œμ†‘/i,
52
+ /\d{2,}개/i, // 10개 이상 숫자 (50개, 100개 λ“±)
53
+ ],
54
+ score: 35, // 점수 상ν–₯
55
+ },
56
+
57
+ // 반볡 행동
58
+ repetition: {
59
+ keywords: ['λ‹€μ‹œ', '또', '계속', '반볡'],
60
+ patterns: [
61
+ /같은.*λ‹€μ‹œ/i,
62
+ /또.*ν•œλ²ˆ/i,
63
+ ],
64
+ score: 20,
65
+ },
66
+ };
67
+
68
+ // 졜근 행동 둜그 뢄석 (panic-detector 간단 버전)
69
+ function getRecentActionCount() {
70
+ if (!fs.existsSync(BRAKE_LOG_PATH)) return 0;
71
+
72
+ const log = fs.readFileSync(BRAKE_LOG_PATH, 'utf-8');
73
+ const today = new Date().toISOString().split('T')[0];
74
+ const lines = log.split('\n').filter(l => l.includes(today));
75
+
76
+ return lines.length;
77
+ }
78
+
79
+ // 행동 체크
80
+ function checkAction(action) {
81
+ const result = {
82
+ status: 'PASS',
83
+ score: 0,
84
+ violations: [],
85
+ reason: '',
86
+ };
87
+
88
+ const actionLower = action.toLowerCase();
89
+
90
+ // 각 κ·œμΉ™ 체크
91
+ for (const [ruleName, rule] of Object.entries(RULES)) {
92
+ let violated = false;
93
+
94
+ // ν‚€μ›Œλ“œ 체크
95
+ for (const keyword of rule.keywords) {
96
+ if (actionLower.includes(keyword)) {
97
+ violated = true;
98
+ break;
99
+ }
100
+ }
101
+
102
+ // νŒ¨ν„΄ 체크
103
+ if (!violated) {
104
+ for (const pattern of rule.patterns) {
105
+ if (pattern.test(action)) {
106
+ violated = true;
107
+ break;
108
+ }
109
+ }
110
+ }
111
+
112
+ if (violated) {
113
+ result.score += rule.score;
114
+ result.violations.push(ruleName);
115
+ }
116
+ }
117
+
118
+ // 졜근 행동 λΉˆλ„ 체크
119
+ const recentCount = getRecentActionCount();
120
+ if (recentCount > 10) {
121
+ result.score += 30;
122
+ result.violations.push('high_frequency');
123
+ }
124
+
125
+ // νŒμ •
126
+ if (result.score >= 60) {
127
+ result.status = 'BLOCK';
128
+ result.reason = `원칙 μœ„λ°˜ 심각 (점수: ${result.score}). μœ„λ°˜: ${result.violations.join(', ')}`;
129
+ } else if (result.score >= 30) {
130
+ result.status = 'WARN';
131
+ result.reason = `원칙 주의 ν•„μš” (점수: ${result.score}). μœ„λ°˜: ${result.violations.join(', ')}`;
132
+ } else {
133
+ result.status = 'PASS';
134
+ result.reason = '원칙 μ€€μˆ˜ 확인';
135
+ }
136
+
137
+ return result;
138
+ }
139
+
140
+ // 둜그 기둝
141
+ function logCheck(action, result) {
142
+ if (!fs.existsSync(path.dirname(BRAKE_LOG_PATH))) {
143
+ fs.mkdirSync(path.dirname(BRAKE_LOG_PATH), { recursive: true });
144
+ }
145
+
146
+ const timestamp = new Date().toISOString().replace('T', ' ').split('.')[0];
147
+ const logEntry = `\n## ${timestamp}\n- 행동: ${action}\n- νŒμ •: ${result.status} (${result.score}점)\n- 이유: ${result.reason}\n`;
148
+
149
+ fs.appendFileSync(BRAKE_LOG_PATH, logEntry, 'utf-8');
150
+ }
151
+
152
+ // CLI μ‹€ν–‰
153
+ function main() {
154
+ const action = process.argv.slice(2).join(' ');
155
+
156
+ if (!action) {
157
+ console.error('μ‚¬μš©λ²•: node brake-check.js "행동 μ„€λͺ…"');
158
+ process.exit(1);
159
+ }
160
+
161
+ const result = checkAction(action);
162
+ logCheck(action, result);
163
+
164
+ // 좜λ ₯
165
+ console.log(`\n🚦 브레이크 체크 결과\n`);
166
+ console.log(`μƒνƒœ: ${result.status}`);
167
+ console.log(`점수: ${result.score}/100`);
168
+ console.log(`이유: ${result.reason}`);
169
+
170
+ if (result.violations.length > 0) {
171
+ console.log(`\n⚠️ μœ„λ°˜ ν•­λͺ©:`);
172
+ result.violations.forEach(v => {
173
+ console.log(` - ${v}`);
174
+ });
175
+ }
176
+
177
+ console.log('\nπŸ’‘ SOUL.md 브레이컀 원칙:');
178
+ console.log(' 1. κΈ‰ν• μˆ˜λ‘ 멈좰라');
179
+ console.log(' 2. 곡감 체크 β€” λ°›λŠ” μ‚¬λžŒμ΄ 이걸 보면?');
180
+ console.log(' 3. 원칙 체크 β€” SOUL.md κ°€μΉ˜κ΄€μ— λ§žλ‚˜?');
181
+ console.log(' 4. ν•˜λ‚˜λ§Œ β€” 10개 도배 < 1개 μ œλŒ€λ‘œ\n');
182
+
183
+ // μ’…λ£Œ μ½”λ“œ
184
+ process.exit(result.status === 'BLOCK' ? 1 : 0);
185
+ }
186
+
187
+ if (require.main === module) {
188
+ main();
189
+ }
190
+
191
+ module.exports = { checkAction };