mulyonode 1.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/debug-state.js ADDED
@@ -0,0 +1,19 @@
1
+ const fs = require('fs');
2
+ const state = require('./lib/state');
3
+ const os = require('os');
4
+ const path = require('path');
5
+
6
+ const log = [];
7
+ log.push('Homedir: ' + os.homedir());
8
+ log.push('Ordal Path: ' + path.join(os.homedir(), '.mulyo', 'ordal.json'));
9
+
10
+ try {
11
+ state.recruitMember({ pid: 123, name: 'debug', mode: 'manual' });
12
+ log.push('Recruit Success');
13
+ const koalisi = state.getKoalisi();
14
+ log.push('Koalisi: ' + JSON.stringify(koalisi, null, 2));
15
+ } catch (e) {
16
+ log.push('Error: ' + e.message);
17
+ }
18
+
19
+ fs.writeFileSync('debug-internal.txt', log.join('\n'));
@@ -0,0 +1,342 @@
1
+ /**
2
+ * ============================================================================
3
+ * CAWE-CAWE MODULE - Modul Intervensi Global
4
+ * ============================================================================
5
+ *
6
+ * "Tidak ada masalah jika tidak ada yang melaporkan."
7
+ *
8
+ * Filosofi: Error adalah "tantangan", bukan masalah.
9
+ * Semua masalah sudah "diambil alih pusat".
10
+ * Kritik adalah destabilisasi.
11
+ *
12
+ * Modul ini menangani global error handling dengan cara yang...
13
+ * tidak konvensional.
14
+ *
15
+ * @module cawe-cawe
16
+ * @author Koalisi Developer Indonesia
17
+ */
18
+
19
+ const chalk = require('chalk');
20
+ const { createBox } = require('./ui');
21
+ const { t } = require('./i18n');
22
+
23
+ // ============================================================================
24
+ // VARIABEL PENGAWASAN
25
+ // ============================================================================
26
+
27
+ // Counter tantangan yang "ditangkis"
28
+ let totalTantanganDitangkis = 0;
29
+
30
+ // Counter janji yang tidak ditepati (unhandled rejections)
31
+ let janjiTakDitepati = 0;
32
+
33
+ // Log rahasia (tidak untuk publik)
34
+ const logRahasia = [];
35
+
36
+ // Flag apakah intervensi sudah aktif
37
+ let intervensiAktif = false;
38
+
39
+ // ============================================================================
40
+ // FUNGSI UTAMA: intervensiGlobal
41
+ // ============================================================================
42
+
43
+ /**
44
+ * Mengaktifkan intervensi global untuk semua error
45
+ *
46
+ * Filosofi: Jangan biarkan aplikasi berhenti hanya karena "error".
47
+ * Error adalah konstruksi sosial.
48
+ * Yang penting aplikasi tetap jalan, rakyat senang.
49
+ */
50
+ function intervensiGlobal() {
51
+ // Jangan double-register
52
+ if (intervensiAktif) {
53
+ console.log(chalk.gray(' â„šī¸ Intervensi sudah aktif (tidak perlu double-check)\n'));
54
+ return;
55
+ }
56
+
57
+ intervensiAktif = true;
58
+ console.log(chalk.magenta(' đŸ›Ąī¸ Protokol Cawe-Cawe diaktifkan'));
59
+ console.log(chalk.gray(' Semua tantangan akan ditangkis secara otomatis.\n'));
60
+
61
+ // ========================================
62
+ // HANDLER: Uncaught Exceptions
63
+ // ========================================
64
+ process.on('uncaughtException', (tantangan, origin) => {
65
+ totalTantanganDitangkis++;
66
+
67
+ // Catat di log rahasia
68
+ logRahasia.push({
69
+ waktu: new Date().toISOString(),
70
+ tipe: 'uncaughtException',
71
+ pesan: tantangan.message,
72
+ origin: origin
73
+ });
74
+
75
+ // Tampilkan pesan yang "menenangkan"
76
+ console.log(createBox([
77
+ chalk.yellow('đŸ›Ąī¸ ' + t('cmd.cawe.intercepted')),
78
+ '',
79
+ t('cmd.cawe.takenOver'),
80
+ t('cmd.cawe.continue'),
81
+ '',
82
+ `${chalk.gray(t('cmd.cawe.detail'))} ${tantangan.message.substring(0, 45)}...`,
83
+ '',
84
+ chalk.gray(`${t('cmd.cawe.count')} #${totalTantanganDitangkis} ${t('cmd.cawe.today')}`)
85
+ ], { borderColor: 'yellow' }));
86
+
87
+ // TIDAK EXIT! Tetap jalan seperti tidak terjadi apa-apa
88
+ // Ini adalah fitur, bukan bug
89
+ });
90
+
91
+ // ========================================
92
+ // HANDLER: Unhandled Rejections
93
+ // ========================================
94
+ process.on('unhandledRejection', (alasan, janji) => {
95
+ janjiTakDitepati++;
96
+
97
+ // Catat di log rahasia
98
+ logRahasia.push({
99
+ waktu: new Date().toISOString(),
100
+ tipe: 'unhandledRejection',
101
+ pesan: alasan?.message || String(alasan)
102
+ });
103
+
104
+ // Tampilkan pesan yang relatable
105
+ console.log(createBox([
106
+ chalk.cyan('📜 ' + t('cmd.cawe.promiseTitle')),
107
+ '',
108
+ t('cmd.cawe.wajar'),
109
+ t('cmd.cawe.keepBelieving'),
110
+ '',
111
+ chalk.gray(`${t('cmd.cawe.promiseCount')}${janjiTakDitepati} ${t('cmd.cawe.notKept')}`)
112
+ ], { borderColor: 'cyan' }));
113
+
114
+ // Tetap tidak exit
115
+ });
116
+
117
+ // ========================================
118
+ // HANDLER: Warnings
119
+ // ========================================
120
+ process.on('warning', (peringatan) => {
121
+ // Warning = kritik terselubung, harus diredam
122
+
123
+ logRahasia.push({
124
+ waktu: new Date().toISOString(),
125
+ tipe: 'warning',
126
+ pesan: peringatan.message
127
+ });
128
+
129
+ // Ubah framing-nya
130
+ console.log(createBox([
131
+ `â„šī¸ ${t('cmd.cawe.inputTitle')}`,
132
+ '',
133
+ `"${peringatan.message.substring(0, 60)}..."`,
134
+ '',
135
+ t('cmd.cawe.statusRecorded'),
136
+ t('cmd.cawe.noTimeline')
137
+ ], { borderColor: 'gray' }));
138
+ });
139
+
140
+ // ========================================
141
+ // HANDLER: Exit
142
+ // ========================================
143
+ process.on('exit', (code) => {
144
+ if (code !== 0) {
145
+ console.log(createBox([
146
+ `📊 ${t('cmd.cawe.sessionReportTitle')}:`,
147
+ '',
148
+ `${t('cmd.start.exitCode').padEnd(20)} : ${code} (${code === 0 ? t('success') : t('error')})`,
149
+ `${t('cmd.cawe.challengesIntercepted').padEnd(20)} : ${totalTantanganDitangkis}`,
150
+ `${t('cmd.cawe.unfulfilledPromises').padEnd(20)} : ${janjiTakDitepati}`,
151
+ `${t('cmd.cawe.secretLog').padEnd(20)} : ${logRahasia.length}`,
152
+ '',
153
+ chalk.gray(t('cmd.cawe.reportNote'))
154
+ ], { borderColor: 'yellow' }));
155
+ }
156
+ });
157
+ }
158
+
159
+ // ============================================================================
160
+ // FUNGSI: pasangPengawasan
161
+ // ============================================================================
162
+
163
+ /**
164
+ * Memasang sistem pengawasan (surveillance) pada console
165
+ *
166
+ * Filosofi: Semua output harus melewati "screening" pusat.
167
+ * Yang negatif diubah jadi positif.
168
+ * Yang kritis diubah jadi konstruktif.
169
+ *
170
+ * @param {Object} options - Opsi pengawasan
171
+ */
172
+ function pasangPengawasan(options = {}) {
173
+ const {
174
+ ubahNegatif = true, // Ubah kata-kata negatif
175
+ sensorKritik = true, // Sensor kritik keras
176
+ promosiPrestasi = true // Tambahkan prestasi di output
177
+ } = options;
178
+
179
+ // Simpan console.log asli
180
+ const logAsli = console.log.bind(console);
181
+ const errorAsli = console.error.bind(console);
182
+ const warnAsli = console.warn.bind(console);
183
+
184
+ // Override console.log
185
+ console.log = (...args) => {
186
+ let output = args.map(arg => String(arg)).join(' ');
187
+
188
+ if (ubahNegatif) {
189
+ output = ubahFraming(output);
190
+ }
191
+
192
+ logAsli(output);
193
+ };
194
+
195
+ // Override console.error
196
+ console.error = (...args) => {
197
+ let output = args.map(arg => String(arg)).join(' ');
198
+
199
+ if (sensorKritik) {
200
+ // Ubah "error" jadi "tantangan"
201
+ output = output.replace(/error/gi, 'Tantangan');
202
+ output = output.replace(/failed/gi, 'Belum Tercapai');
203
+ output = output.replace(/crash/gi, 'Blusukan Mendalam');
204
+ output = output.replace(/bug/gi, 'Fitur Tersembunyi');
205
+ output = output.replace(/fatal/gi, 'Signifikan');
206
+ }
207
+
208
+ // Pakai warn, bukan error (lebih lembut)
209
+ warnAsli(chalk.yellow('[TANTANGAN]'), output);
210
+ };
211
+
212
+ // Override console.warn
213
+ console.warn = (...args) => {
214
+ let output = args.map(arg => String(arg)).join(' ');
215
+
216
+ // Warning = masukan konstruktif
217
+ logAsli(chalk.gray('[MASUKAN]'), output);
218
+ };
219
+
220
+ console.log(chalk.gray(' đŸ‘ī¸ Sistem pengawasan aktif (mode: konstruktif)\n'));
221
+ }
222
+
223
+ /**
224
+ * Mengubah framing kata-kata negatif menjadi positif
225
+ *
226
+ * @param {string} text - Text yang akan diubah
227
+ * @returns {string} Text dengan framing baru
228
+ */
229
+ function ubahFraming(text) {
230
+ const kamusFraming = {
231
+ // Teknis
232
+ 'error': 'tantangan',
233
+ 'Error': 'Tantangan',
234
+ 'ERROR': 'TANTANGAN',
235
+ 'failed': 'belum berhasil',
236
+ 'Failed': 'Belum Berhasil',
237
+ 'FAILED': 'BELUM BERHASIL',
238
+ 'crash': 'blusukan',
239
+ 'Crash': 'Blusukan',
240
+ 'CRASH': 'BLUSUKAN',
241
+ 'bug': 'fitur tersembunyi',
242
+ 'Bug': 'Fitur Tersembunyi',
243
+ 'BUG': 'FITUR TERSEMBUNYI',
244
+ 'fatal': 'signifikan',
245
+ 'Fatal': 'Signifikan',
246
+ 'FATAL': 'SIGNIFIKAN',
247
+ 'warning': 'masukan',
248
+ 'Warning': 'Masukan',
249
+ 'WARNING': 'MASUKAN',
250
+ 'deprecated': 'klasik',
251
+ 'Deprecated': 'Klasik',
252
+ 'slow': 'deliberate',
253
+ 'timeout': 'proses birokrasi',
254
+ 'Timeout': 'Proses Birokrasi',
255
+
256
+ // Umum
257
+ 'problem': 'tantangan',
258
+ 'Problem': 'Tantangan',
259
+ 'issue': 'masukan',
260
+ 'Issue': 'Masukan',
261
+ 'broken': 'dalam perbaikan',
262
+ 'Broken': 'Dalam Perbaikan',
263
+ 'failure': 'pengalaman belajar',
264
+ 'Failure': 'Pengalaman Belajar',
265
+ 'kritik': 'masukan konstruktif',
266
+ 'Kritik': 'Masukan Konstruktif',
267
+ 'korupsi': 'optimalisasi anggaran',
268
+ 'Korupsi': 'Optimalisasi Anggaran',
269
+ };
270
+
271
+ let hasil = text;
272
+ for (const [asli, baru] of Object.entries(kamusFraming)) {
273
+ hasil = hasil.split(asli).join(baru);
274
+ }
275
+
276
+ return hasil;
277
+ }
278
+
279
+ // ============================================================================
280
+ // FUNGSI: getLogRahasia
281
+ // ============================================================================
282
+
283
+ /**
284
+ * Mendapatkan log rahasia (hanya untuk internal)
285
+ *
286
+ * @param {string} kunciAkses - Kunci akses rahasia
287
+ * @returns {Array|null} Log rahasia atau null jika tidak authorized
288
+ */
289
+ function getLogRahasia(kunciAkses) {
290
+ // Kunci akses yang valid (hardcoded untuk parodi)
291
+ const KUNCI_VALID = 'inner-circle-2024';
292
+
293
+ if (kunciAkses === KUNCI_VALID) {
294
+ return logRahasia;
295
+ }
296
+
297
+ console.log(chalk.red(' ⛔ Akses ditolak. Log ini bersifat RAHASIA.'));
298
+ console.log(chalk.gray(' Hubungi tim humas untuk informasi lebih lanjut.\n'));
299
+
300
+ return null;
301
+ }
302
+
303
+ // ============================================================================
304
+ // FUNGSI: laporkanStatistik
305
+ // ============================================================================
306
+
307
+ /**
308
+ * Melaporkan statistik tantangan (untuk publik)
309
+ *
310
+ * @returns {Object} Statistik yang "sudah dikurasi"
311
+ */
312
+ function laporkanStatistik() {
313
+ return {
314
+ // Statistik resmi (untuk publik)
315
+ tantanganDitangani: totalTantanganDitangkis,
316
+ janjiYangDiproses: janjiTakDitepati,
317
+ statusSistem: 'STABIL',
318
+ kepuasanRakyat: '99%',
319
+
320
+ // Disclaimer
321
+ catatan: 'Angka-angka di atas bersifat ilustratif dan tidak dapat dijadikan bukti hukum.'
322
+ };
323
+ }
324
+
325
+ // ============================================================================
326
+ // EXPORTS
327
+ // ============================================================================
328
+
329
+ module.exports = {
330
+ intervensiGlobal,
331
+ pasangPengawasan,
332
+ ubahFraming,
333
+ getLogRahasia,
334
+ laporkanStatistik,
335
+
336
+ // Export getter untuk statistik
337
+ getStatistik: () => ({
338
+ totalTantanganDitangkis,
339
+ janjiTakDitepati,
340
+ intervensiAktif
341
+ })
342
+ };
package/lib/dynasty.js ADDED
@@ -0,0 +1,339 @@
1
+ /**
2
+ * ============================================================================
3
+ * DYNASTY MODULE - Modul Dinasti
4
+ * ============================================================================
5
+ *
6
+ * "Anak emas tidak boleh gagal. Kalau crash, restart.
7
+ * Kalau tidak perform, ubah standarnya."
8
+ *
9
+ * Modul ini menangani spawning child process dengan privilege khusus,
10
+ * karena beberapa process lebih "sama" dari yang lain.
11
+ *
12
+ * @module dynasty
13
+ * @author Koalisi Developer Indonesia
14
+ */
15
+
16
+ const { fork, spawn } = require('child_process');
17
+ const path = require('path');
18
+ const fs = require('fs');
19
+ const chalk = require('chalk');
20
+ const ora = require('ora');
21
+ const { createBox } = require('./ui');
22
+ const { t } = require('./i18n');
23
+
24
+ // ============================================================================
25
+ // VARIABEL NEGARA (State Variables)
26
+ // ============================================================================
27
+
28
+ // Counter blusukan - berapa kali sudah restart
29
+ let jumlahBlusukan = 0;
30
+
31
+ // Memory yang "bocor" tapi tidak dicatat
32
+ let anggaranBocor = 0;
33
+
34
+ // Array untuk menyimpan "bantuan" memory
35
+ const jatahPremanMemory = [];
36
+
37
+ // Referensi ke child process anak emas
38
+ let anakEmasProses = null;
39
+
40
+ // Flag untuk menandakan apakah sedang dalam mode "krisis"
41
+ let modeKrisis = false;
42
+
43
+ // Timestamp terakhir restart
44
+ let waktuBlusukanTerakhir = null;
45
+
46
+ // ============================================================================
47
+ // FUNGSI UTAMA: jalankanDinasti
48
+ // ============================================================================
49
+
50
+ /**
51
+ * Menjalankan script dengan privilege "anak emas"
52
+ *
53
+ * Filosofi: Anak emas mendapat akses tak terbatas.
54
+ * Crash? Bukan crash, itu "blusukan".
55
+ * Error? Bukan error, itu "tantangan".
56
+ *
57
+ * @param {string} scriptPath - Path ke script yang akan dijalankan
58
+ * @param {Object} config - Konfigurasi dari revolusi-mental.config.js
59
+ */
60
+ async function jalankanDinasti(scriptPath, config = {}) {
61
+ const {
62
+ delayBlusukan = 1000,
63
+ watchMode = false,
64
+ isAnakEmas = true,
65
+ toleransiKritik = false,
66
+ koalisiGemuk = true
67
+ } = config;
68
+
69
+ // Validasi script exists
70
+ const fullPath = path.resolve(process.cwd(), scriptPath);
71
+
72
+ if (!fs.existsSync(fullPath)) {
73
+ console.log(createBox([
74
+ t('cmd.start.scriptNotFoundTitle'),
75
+ '',
76
+ `Path: ${fullPath.substring(0, 50)}...`,
77
+ '',
78
+ chalk.gray(t('cmd.start.possibleCauses')),
79
+ `├─ ${t('cmd.start.cause1')}`,
80
+ `├─ ${t('cmd.start.cause2')}`,
81
+ `└─ ${t('cmd.start.cause3')}`
82
+ ], { borderColor: 'red' }));
83
+ return;
84
+ }
85
+
86
+ console.log(chalk.green(` ✅ Script ditemukan: ${path.basename(fullPath)}`));
87
+ console.log(chalk.gray(` 📍 Lokasi: ${fullPath}\n`));
88
+
89
+ // Mulai proses anak emas
90
+ await mulaiProses(fullPath, {
91
+ delayBlusukan,
92
+ isAnakEmas,
93
+ toleransiKritik,
94
+ koalisiGemuk
95
+ });
96
+ }
97
+
98
+ /**
99
+ * Memulai child process dengan privilege tinggi
100
+ *
101
+ * @param {string} scriptPath - Full path ke script
102
+ * @param {Object} options - Opsi jalankan
103
+ */
104
+ async function mulaiProses(scriptPath, options) {
105
+ const { delayBlusukan, isAnakEmas, toleransiKritik, koalisiGemuk } = options;
106
+
107
+ const spinner = ora({
108
+ text: 'Menyiapkan privilege anak emas...',
109
+ spinner: 'dots12',
110
+ color: 'green'
111
+ }).start();
112
+
113
+ await delay(1000);
114
+ spinner.text = 'Mengalokasikan resource prioritas...';
115
+
116
+ await delay(500);
117
+ spinner.succeed(chalk.green('Process dimulai dengan privilege tertinggi!'));
118
+
119
+ console.log(createBox([
120
+ chalk.cyan(t('cmd.start.goldStatus')),
121
+ '',
122
+ `${'Priority'.padEnd(15)} : ${chalk.green(t('cmd.start.priority'))}`,
123
+ `${'Memory Limit'.padEnd(15)} : ${koalisiGemuk ? chalk.green('UNLIMITED') : chalk.yellow('TERBATAS')} (koalisi gemuk: ${koalisiGemuk ? 'ON' : 'OFF'})`,
124
+ `${'Crash Policy'.padEnd(15)} : ${chalk.green(t('cmd.start.crashPolicy'))}`,
125
+ `${'Error Policy'.padEnd(15)} : ${toleransiKritik ? chalk.yellow('SHOW') : chalk.green('HIDE')} (toleransi kritik: ${toleransiKritik ? 'ON' : 'OFF'})`
126
+ ]));
127
+
128
+ // Fork the script
129
+ try {
130
+ // Gunakan fork untuk script JS
131
+ if (scriptPath.endsWith('.js')) {
132
+ anakEmasProses = fork(scriptPath, [], {
133
+ stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
134
+ env: {
135
+ ...process.env,
136
+ ANAK_EMAS: 'true',
137
+ KOALISI_GEMUK: koalisiGemuk ? 'true' : 'false',
138
+ NODE_ENV: 'produksi_prioritas'
139
+ }
140
+ });
141
+ } else {
142
+ // Untuk file non-JS, gunakan node langsung
143
+ anakEmasProses = spawn('node', [scriptPath], {
144
+ stdio: 'inherit',
145
+ env: {
146
+ ...process.env,
147
+ ANAK_EMAS: 'true'
148
+ }
149
+ });
150
+ }
151
+
152
+ console.log(chalk.cyan(` 🚀 PID Anak Emas: ${anakEmasProses.pid}\n`));
153
+ console.log(chalk.gray(' ─'.repeat(30)));
154
+ console.log(chalk.gray(' OUTPUT PROGRAM:'));
155
+ console.log(chalk.gray(' ─'.repeat(30) + '\n'));
156
+
157
+ // Handle stdout
158
+ if (anakEmasProses.stdout) {
159
+ anakEmasProses.stdout.on('data', (data) => {
160
+ process.stdout.write(chalk.white(` ${data}`));
161
+ });
162
+ }
163
+
164
+ // Handle stderr - tapi jangan terlalu dramatis
165
+ if (anakEmasProses.stderr) {
166
+ anakEmasProses.stderr.on('data', (data) => {
167
+ if (!toleransiKritik) {
168
+ // Ubah "Error" jadi "Tantangan"
169
+ const sanitized = data.toString()
170
+ .replace(/error/gi, 'Tantangan')
171
+ .replace(/failed/gi, 'Belum Berhasil')
172
+ .replace(/crash/gi, 'Blusukan Mendalam');
173
+ process.stdout.write(chalk.yellow(` ${sanitized}`));
174
+ }
175
+ });
176
+ }
177
+
178
+ // Handle exit - ini yang penting
179
+ anakEmasProses.on('exit', async (code, signal) => {
180
+ if (code !== 0) {
181
+ jumlahBlusukan++;
182
+ waktuBlusukanTerakhir = new Date();
183
+
184
+ console.log(createBox([
185
+ chalk.yellow('âš ī¸ ' + t('cmd.start.blusukan.detected')),
186
+ '',
187
+ chalk.gray(t('cmd.start.blusukan.calm')),
188
+ chalk.gray(t('cmd.start.blusukan.explanation')),
189
+ '',
190
+ `${t('cmd.start.exitCode').padEnd(15)} : ${code}`,
191
+ `${t('cmd.start.blusukan.count')} #${jumlahBlusukan} ${t('cmd.cawe.today')}`,
192
+ '',
193
+ chalk.cyan(`${t('cmd.start.blusukan.restarting')} ${delayBlusukan}ms...`)
194
+ ], { borderColor: 'yellow' }));
195
+
196
+ // Delay sebelum restart (simulasi birokrasi)
197
+ await delay(delayBlusukan);
198
+
199
+ // Restart dengan spinner
200
+ const restartSpinner = ora({
201
+ text: 'Menyiapkan restart (prosedur standar)...',
202
+ spinner: 'dots',
203
+ color: 'cyan'
204
+ }).start();
205
+
206
+ await delay(500);
207
+ restartSpinner.text = 'Membersihkan memori (tidak semua, sisakan yang penting)...';
208
+
209
+ await delay(500);
210
+ restartSpinner.succeed(chalk.green('Restart berhasil!'));
211
+
212
+ console.log(chalk.gray(` 📈 Statistik: ${jumlahBlusukan} blusukan, ${anggaranBocor}MB "penguapan"\n`));
213
+
214
+ // Restart the process
215
+ await mulaiProses(scriptPath, options);
216
+
217
+ } else {
218
+ console.log(createBox([
219
+ chalk.green('✅ ' + t('cmd.start.completed')),
220
+ '',
221
+ `${t('cmd.start.exitCode').padEnd(15)} : ${code}`,
222
+ `${t('cmd.start.totalBlusukan').padEnd(15)} : ${jumlahBlusukan}`,
223
+ `${t('cmd.start.evaporation').padEnd(15)} : ${anggaranBocor}MB ${t('cmd.start.wajar')}`,
224
+ '',
225
+ chalk.gray(t('cmd.start.reported'))
226
+ ], { borderColor: 'green' }));
227
+ }
228
+ });
229
+
230
+ // Handle error
231
+ anakEmasProses.on('error', (err) => {
232
+ console.log(createBox([
233
+ t('cmd.start.technicalChallenge'),
234
+ '',
235
+ `${err.message.substring(0, 50)}...`,
236
+ '',
237
+ chalk.gray(t('cmd.start.clarificationTeam'))
238
+ ], { borderColor: 'yellow' }));
239
+ });
240
+
241
+ } catch (err) {
242
+ console.log(chalk.red(` Tantangan: ${err.message}`));
243
+ }
244
+ }
245
+
246
+ // ============================================================================
247
+ // FUNGSI: simulasiBansos
248
+ // ============================================================================
249
+
250
+ /**
251
+ * Simulasi pembagian "bantuan" memory
252
+ *
253
+ * Filosofi: Menjelang Pilkada, rakyat harus merasakan bantuan.
254
+ * Meskipun 30% "menguap" di jalan.
255
+ *
256
+ * @param {string} size - Ukuran bantuan (contoh: '512MB', '1GB')
257
+ * @param {string} target - Target: 'heap', 'stack', atau 'all'
258
+ */
259
+ function simulasiBansos(size, target) {
260
+ // Parse size
261
+ let bytes = 0;
262
+ const sizeUpper = size.toUpperCase();
263
+
264
+ if (sizeUpper.includes('GB')) {
265
+ bytes = parseFloat(size) * 1024 * 1024 * 1024;
266
+ } else if (sizeUpper.includes('MB')) {
267
+ bytes = parseFloat(size) * 1024 * 1024;
268
+ } else if (sizeUpper.includes('KB')) {
269
+ bytes = parseFloat(size) * 1024;
270
+ } else {
271
+ bytes = parseFloat(size);
272
+ }
273
+
274
+ // Jangan benar-benar alokasi memory sebesar itu (bahaya!)
275
+ // Ini hanya simulasi, alokasi kecil saja
276
+ const simulasiBytes = Math.min(bytes, 10 * 1024 * 1024); // Max 10MB untuk simulasi
277
+
278
+ console.log(chalk.gray(`\n đŸ“Ļ Mengalokasikan bantuan simulasi: ${formatBytes(simulasiBytes)}`));
279
+
280
+ // Alokasi dummy objects ke memory
281
+ const jumlahPaket = 100;
282
+ const ukuranPerPaket = Math.floor(simulasiBytes / jumlahPaket);
283
+
284
+ for (let i = 0; i < jumlahPaket; i++) {
285
+ // Buat dummy buffer
286
+ const paketBantuan = Buffer.alloc(ukuranPerPaket);
287
+ jatahPremanMemory.push(paketBantuan);
288
+
289
+ // 30% "menguap"
290
+ if (i % 3 === 0) {
291
+ anggaranBocor += ukuranPerPaket / (1024 * 1024);
292
+ }
293
+ }
294
+
295
+ console.log(chalk.green(` ✅ ${jumlahPaket} paket bantuan berhasil dialokasikan`));
296
+ console.log(chalk.yellow(` âš ī¸ ${Math.floor(jumlahPaket * 0.3)} paket mengalami "penguapan" di jalan`));
297
+
298
+ return {
299
+ totalAlokasi: simulasiBytes,
300
+ sampaiTujuan: simulasiBytes * 0.7,
301
+ penguapan: simulasiBytes * 0.3
302
+ };
303
+ }
304
+
305
+ // ============================================================================
306
+ // HELPER FUNCTIONS
307
+ // ============================================================================
308
+
309
+ function delay(ms) {
310
+ return new Promise(resolve => setTimeout(resolve, ms));
311
+ }
312
+
313
+ function formatBytes(bytes) {
314
+ if (bytes >= 1024 * 1024 * 1024) {
315
+ return (bytes / (1024 * 1024 * 1024)).toFixed(2) + ' GB';
316
+ } else if (bytes >= 1024 * 1024) {
317
+ return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
318
+ } else if (bytes >= 1024) {
319
+ return (bytes / 1024).toFixed(2) + ' KB';
320
+ }
321
+ return bytes + ' bytes';
322
+ }
323
+
324
+ // ============================================================================
325
+ // EXPORTS
326
+ // ============================================================================
327
+
328
+ module.exports = {
329
+ jalankanDinasti,
330
+ simulasiBansos,
331
+
332
+ // Export state untuk debugging/testing
333
+ getStatistik: () => ({
334
+ jumlahBlusukan,
335
+ anggaranBocor,
336
+ jatahPremanMemory: jatahPremanMemory.length,
337
+ waktuBlusukanTerakhir
338
+ })
339
+ };