autonomous-flow-daemon 1.6.0 → 1.9.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +85 -85
  2. package/LICENSE +21 -21
  3. package/README-ko.md +282 -0
  4. package/README.md +282 -266
  5. package/mcp-config.json +10 -10
  6. package/package.json +4 -2
  7. package/src/adapters/index.ts +370 -370
  8. package/src/cli.ts +162 -127
  9. package/src/commands/benchmark.ts +187 -187
  10. package/src/commands/correlate.ts +180 -0
  11. package/src/commands/dashboard.ts +404 -0
  12. package/src/commands/evolution.ts +84 -1
  13. package/src/commands/fix.ts +158 -158
  14. package/src/commands/lang.ts +41 -41
  15. package/src/commands/plugin.ts +110 -0
  16. package/src/commands/restart.ts +14 -14
  17. package/src/commands/score.ts +276 -276
  18. package/src/commands/start.ts +155 -155
  19. package/src/commands/status.ts +157 -157
  20. package/src/commands/stop.ts +68 -68
  21. package/src/commands/suggest.ts +211 -0
  22. package/src/commands/sync.ts +329 -16
  23. package/src/constants.ts +32 -32
  24. package/src/core/boast.ts +280 -280
  25. package/src/core/config.ts +49 -49
  26. package/src/core/correlation-engine.ts +265 -0
  27. package/src/core/db.ts +145 -117
  28. package/src/core/discovery.ts +65 -65
  29. package/src/core/federation.ts +129 -0
  30. package/src/core/hologram/engine.ts +71 -71
  31. package/src/core/hologram/fallback.ts +11 -11
  32. package/src/core/hologram/go-extractor.ts +203 -0
  33. package/src/core/hologram/incremental.ts +227 -227
  34. package/src/core/hologram/py-extractor.ts +132 -132
  35. package/src/core/hologram/rust-extractor.ts +244 -0
  36. package/src/core/hologram/ts-extractor.ts +406 -320
  37. package/src/core/hologram/types.ts +27 -25
  38. package/src/core/hologram.ts +73 -71
  39. package/src/core/i18n/messages.ts +309 -309
  40. package/src/core/locale.ts +88 -88
  41. package/src/core/log-rotate.ts +33 -33
  42. package/src/core/log-utils.ts +38 -38
  43. package/src/core/lru-map.ts +61 -61
  44. package/src/core/notify.ts +74 -74
  45. package/src/core/plugin-manager.ts +225 -0
  46. package/src/core/rule-suggestion.ts +127 -0
  47. package/src/core/validator-generator.ts +224 -0
  48. package/src/core/workspace.ts +28 -28
  49. package/src/daemon/client.ts +78 -65
  50. package/src/daemon/event-batcher.ts +108 -108
  51. package/src/daemon/guards.ts +13 -13
  52. package/src/daemon/http-routes.ts +376 -293
  53. package/src/daemon/mcp-handler.ts +575 -270
  54. package/src/daemon/mcp-subscriptions.ts +81 -0
  55. package/src/daemon/mesh.ts +51 -0
  56. package/src/daemon/server.ts +655 -590
  57. package/src/daemon/types.ts +121 -100
  58. package/src/daemon/workspace-map.ts +104 -92
  59. package/src/platform.ts +60 -60
  60. package/src/version.ts +15 -15
  61. package/README.ko.md +0 -266
@@ -1,276 +1,276 @@
1
- import { daemonRequest } from "../daemon/client";
2
- import { fmtNum, visualWidth, localizedBoast } from "../core/boast";
3
- import type { ShiftSummary } from "../core/boast";
4
- import { getSystemLanguage } from "../core/locale";
5
- import { getMessages, t } from "../core/i18n/messages";
6
-
7
- interface HologramEntry {
8
- requests: number;
9
- originalChars: number;
10
- hologramChars: number;
11
- savings: number;
12
- }
13
-
14
- interface HologramDailyRow {
15
- date: string;
16
- requests: number;
17
- originalChars: number;
18
- hologramChars: number;
19
- }
20
-
21
- interface HologramScore {
22
- lifetime: HologramEntry;
23
- today: HologramEntry | null;
24
- daily: HologramDailyRow[];
25
- }
26
-
27
- interface AutoHealEntry {
28
- id: string;
29
- at: number;
30
- }
31
-
32
- interface ImmuneScore {
33
- antibodies: number;
34
- autoHealed: number;
35
- lastAutoHeal: AutoHealEntry | null;
36
- }
37
-
38
- interface EcosystemEntry {
39
- name: string;
40
- confidence: string;
41
- }
42
-
43
- interface EcosystemScore {
44
- detected: EcosystemEntry[];
45
- primary: string;
46
- }
47
-
48
- interface SuppressionScore {
49
- massEventsSkipped: number;
50
- dormantTransitions: number;
51
- activeTaps: number;
52
- }
53
-
54
- interface DynamicImmuneScore {
55
- activeValidators: number;
56
- validatorNames: string[];
57
- }
58
-
59
- interface ScoreData {
60
- uptime: number;
61
- filesDetected: number;
62
- totalEvents: number;
63
- lastEvent: string | null;
64
- lastEventAt: number | null;
65
- watchedFiles: string[];
66
- watchTargets: string[];
67
- hologram: HologramScore;
68
- immune: ImmuneScore;
69
- ecosystem: EcosystemScore;
70
- suppression: SuppressionScore;
71
- dynamicImmune?: DynamicImmuneScore;
72
- }
73
-
74
- // ── ANSI helpers ──
75
- const C = {
76
- reset: "\x1b[0m",
77
- bold: "\x1b[1m",
78
- dim: "\x1b[2m",
79
- red: "\x1b[31m",
80
- green: "\x1b[32m",
81
- yellow: "\x1b[33m",
82
- blue: "\x1b[34m",
83
- magenta: "\x1b[35m",
84
- cyan: "\x1b[36m",
85
- white: "\x1b[37m",
86
- bgRed: "\x1b[41m",
87
- bgGreen: "\x1b[42m",
88
- bgYellow: "\x1b[43m",
89
- };
90
-
91
- function formatUptime(seconds: number): string {
92
- if (seconds < 60) return `${seconds}s`;
93
- if (seconds < 3600) return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
94
- const h = Math.floor(seconds / 3600);
95
- const m = Math.floor((seconds % 3600) / 60);
96
- return `${h}h ${m}m`;
97
- }
98
-
99
- function gaugeBar(value: number, max: number, width = 20): string {
100
- const ratio = Math.min(value / Math.max(max, 1), 1);
101
- const filled = Math.round(ratio * width);
102
- const empty = width - filled;
103
- const color = ratio >= 0.7 ? C.green : ratio >= 0.4 ? C.yellow : C.red;
104
- const pct = Math.round(ratio * 100);
105
- return `${color}${"█".repeat(filled)}${C.dim}${"░".repeat(empty)}${C.reset} ${pct}%`;
106
- }
107
-
108
- function formatChars(n: number): string {
109
- if (n < 1000) return `${n}`;
110
- if (n < 1_000_000) return `${(n / 1000).toFixed(1)}K`;
111
- return `${(n / 1_000_000).toFixed(1)}M`;
112
- }
113
-
114
- const W = 52;
115
- const line = "─".repeat(W);
116
-
117
- function row(content: string): string {
118
- // Strip ANSI for width calculation
119
- const stripped = content.replace(/\x1b\[[0-9;]*m/g, "");
120
- const vw = visualWidth(stripped);
121
- const padSize = Math.max(0, W - vw);
122
- return `│${content}${" ".repeat(padSize)}│`;
123
- }
124
-
125
- function section(title: string): string {
126
- return row(` ${C.bold}${C.cyan}${title}${C.reset}`);
127
- }
128
-
129
- function kv(label: string, value: string): string {
130
- const stripped = label.replace(/\x1b\[[0-9;]*m/g, "");
131
- const gap = 18 - visualWidth(stripped);
132
- return row(` ${C.dim}${label}${C.reset}${" ".repeat(Math.max(1, gap))}${value}`);
133
- }
134
-
135
- function guardianGrade(antibodies: number, heals: number, holoSavings: number): { grade: string; label: string; color: string } {
136
- const score = Math.min(antibodies * 15, 40) + Math.min(heals * 10, 30) + Math.min(holoSavings * 0.3, 30);
137
- if (score >= 80) return { grade: "A+", label: "FORTIFIED", color: C.green };
138
- if (score >= 60) return { grade: "A", label: "GUARDED", color: C.green };
139
- if (score >= 40) return { grade: "B", label: "LEARNING", color: C.yellow };
140
- if (score >= 20) return { grade: "C", label: "EXPOSED", color: C.yellow };
141
- return { grade: "D", label: "VULNERABLE", color: C.red };
142
- }
143
-
144
- export async function scoreCommand() {
145
- const lang = getSystemLanguage();
146
- const i18n = getMessages(lang);
147
-
148
- try {
149
- const data = await daemonRequest<ScoreData>("/score");
150
- const h = data.hologram;
151
- const holoSav = h.lifetime.savings;
152
- const grade = guardianGrade(data.immune.antibodies, data.immune.autoHealed, holoSav);
153
-
154
- const out: string[] = [];
155
-
156
- // ── Header ──
157
- out.push(`┌${line}┐`);
158
- out.push(row(` ${C.bold}🛡️ Guardian Status${C.reset} ${grade.color}${C.bold}[ ${grade.grade} ]${C.reset} ${grade.color}${grade.label}${C.reset}`));
159
- out.push(`├${line}┤`);
160
-
161
- // ── Health Gauge ──
162
- const healthPct = Math.min(data.immune.antibodies * 15 + data.immune.autoHealed * 10 + holoSav * 0.3, 100);
163
- out.push(row(` ${gaugeBar(healthPct, 100, 30)}`));
164
- out.push(`├${line}┤`);
165
-
166
- // ── System Info ──
167
- out.push(section(lang === "ko" ? "시스템 정보" : "System Info"));
168
- out.push(kv(i18n.SCORE_ECOSYSTEM, `${C.white}${C.bold}${data.ecosystem.primary}${C.reset}`));
169
- if (data.ecosystem.detected.length > 1) {
170
- const others = data.ecosystem.detected.slice(1).map(e => e.name).join(", ");
171
- out.push(kv(i18n.SCORE_ALSO_FOUND, `${C.dim}${others}${C.reset}`));
172
- }
173
- out.push(kv(i18n.SCORE_UPTIME, `${C.green}${formatUptime(data.uptime)}${C.reset}`));
174
- out.push(kv(i18n.SCORE_EVENTS, `${data.totalEvents}`));
175
- out.push(kv(i18n.SCORE_FILES_FOUND, `${data.watchedFiles.length}`));
176
-
177
- // ── Immune System ──
178
- out.push(`├${line}┤`);
179
- out.push(section(lang === "ko" ? "면역 시스템" : "Immune System"));
180
- const ab = data.immune.antibodies;
181
- const ah = data.immune.autoHealed;
182
- out.push(kv(i18n.SCORE_ANTIBODIES, `${C.bold}${ab}${C.reset}`));
183
- out.push(row(` ${lang === "ko" ? "면역력" : "Immunity"} ${gaugeBar(ab, 10, 20)}`));
184
- out.push(kv(lang === "ko" ? "차단 횟수" : "Prevented", `${C.bold}${C.green}${ah}${C.reset}${C.dim} disaster${ah !== 1 ? "s" : ""}${C.reset}`));
185
- if (data.immune.lastAutoHeal) {
186
- const ago = formatUptime(Math.floor((Date.now() - data.immune.lastAutoHeal.at) / 1000));
187
- out.push(kv(lang === "ko" ? "마지막 치유" : "Last Heal", `${data.immune.lastAutoHeal.id} ${C.dim}(${ago} ago)${C.reset}`));
188
- }
189
-
190
- // ── Dynamic Immune Synthesis ──
191
- if (data.dynamicImmune && data.dynamicImmune.activeValidators > 0) {
192
- out.push(`├${line}┤`);
193
- out.push(section(lang === "ko" ? "진화 상태 (동적 면역)" : "Evolution (Dynamic Immune)"));
194
- out.push(kv(
195
- lang === "ko" ? "활성 검증기" : "Validators",
196
- `${C.bold}${C.green}${data.dynamicImmune.activeValidators} Active${C.reset}`
197
- ));
198
- const names = data.dynamicImmune.validatorNames.slice(0, 3).join(", ");
199
- const extra = data.dynamicImmune.validatorNames.length > 3
200
- ? ` ${C.dim}+${data.dynamicImmune.validatorNames.length - 3} more${C.reset}`
201
- : "";
202
- out.push(kv(
203
- lang === "ko" ? "스크립트" : "Scripts",
204
- `${C.dim}${names}${C.reset}${extra}`
205
- ));
206
- }
207
-
208
- // ── Hologram Efficiency ──
209
- out.push(`├${line}┤`);
210
- out.push(section(lang === "ko" ? "토큰 효율 (홀로그램)" : "Token Efficiency (Hologram)"));
211
- const lt = h.lifetime;
212
- if (lt.requests > 0) {
213
- const ltSaved = lt.originalChars - lt.hologramChars;
214
- out.push(kv(lang === "ko" ? "총 요청" : "Requests", `${lt.requests}`));
215
- out.push(kv(lang === "ko" ? "절약된 컨텍스트" : "Saved Context", `${C.green}${formatChars(ltSaved)} chars${C.reset}`));
216
- out.push(row(` ${lang === "ko" ? "효율" : "Efficiency"} ${gaugeBar(lt.savings, 100, 20)}`));
217
- if (h.today && h.today.requests > 0) {
218
- const todaySaved = h.today.originalChars - h.today.hologramChars;
219
- out.push(kv(lang === "ko" ? "오늘" : "Today", `${h.today.requests} req / ${C.green}${formatChars(todaySaved)} saved${C.reset}`));
220
- }
221
- } else {
222
- out.push(row(` ${C.dim}${i18n.SCORE_HOLOGRAM_EMPTY}${C.reset}`));
223
- out.push(row(` ${C.dim}${i18n.SCORE_HOLOGRAM_HINT}${C.reset}`));
224
- }
225
-
226
- // ── Value Delivered (ROI) ──
227
- try {
228
- const summary = await daemonRequest<ShiftSummary>("/shift-summary");
229
- out.push(`├${line}┤`);
230
- out.push(section(lang === "ko" ? "전달된 가치 (ROI)" : "Value Delivered (ROI)"));
231
-
232
- // Breakdown: Auto-Heal
233
- if (summary.healTokensSaved > 0) {
234
- out.push(kv(
235
- lang === "ko" ? "🩹 치유 절약" : "🩹 Heal Saved",
236
- `${C.dim}~${fmtNum(summary.healTokensSaved)} tok / $${summary.healCostSaved.toFixed(2)}${C.reset}`
237
- ));
238
- }
239
-
240
- // Breakdown: Hologram
241
- if (summary.hologramTokensSaved > 0) {
242
- out.push(kv(
243
- lang === "ko" ? "💎 홀로그램" : "💎 Hologram",
244
- `${C.dim}~${fmtNum(summary.hologramTokensSaved)} tok / $${summary.hologramCostSaved.toFixed(2)}${C.reset}`
245
- ));
246
- }
247
-
248
- // Total
249
- out.push(kv(
250
- lang === "ko" ? "총 절약 토큰" : "Total Tokens",
251
- `${C.bold}${C.green}~${fmtNum(summary.totalTokensSaved)}${C.reset}`
252
- ));
253
- out.push(kv(lang === "ko" ? "절약 시간" : "Time Saved", `${C.green}~${summary.totalMinutesSaved} min${C.reset}`));
254
- out.push(kv(
255
- lang === "ko" ? "총 절약 비용" : "Total Cost",
256
- `${C.bold}${C.green}~$${summary.totalCostSaved.toFixed(2)}${C.reset}`
257
- ));
258
- if (summary.suppressionsSkipped > 0) {
259
- out.push(kv(lang === "ko" ? "억제 횟수" : "Suppressed", `${summary.suppressionsSkipped}`));
260
- }
261
- } catch { /* non-fatal */ }
262
-
263
- // ── Boast ──
264
- out.push(`├${line}┤`);
265
- const boast = localizedBoast(lang);
266
- const truncBoast = boast.length > W - 6 ? boast.slice(0, W - 9) + "..." : boast;
267
- out.push(row(` ${C.magenta}🗣️ ${truncBoast}${C.reset}`));
268
- out.push(`└${line}┘`);
269
-
270
- console.log(out.join("\n"));
271
- } catch (err: unknown) {
272
- const msg = err instanceof Error ? err.message : String(err);
273
- console.error(`${C.red}[afd] ${msg}${C.reset}`);
274
- process.exit(1);
275
- }
276
- }
1
+ import { daemonRequest } from "../daemon/client";
2
+ import { fmtNum, visualWidth, localizedBoast } from "../core/boast";
3
+ import type { ShiftSummary } from "../core/boast";
4
+ import { getSystemLanguage } from "../core/locale";
5
+ import { getMessages, t } from "../core/i18n/messages";
6
+
7
+ interface HologramEntry {
8
+ requests: number;
9
+ originalChars: number;
10
+ hologramChars: number;
11
+ savings: number;
12
+ }
13
+
14
+ interface HologramDailyRow {
15
+ date: string;
16
+ requests: number;
17
+ originalChars: number;
18
+ hologramChars: number;
19
+ }
20
+
21
+ interface HologramScore {
22
+ lifetime: HologramEntry;
23
+ today: HologramEntry | null;
24
+ daily: HologramDailyRow[];
25
+ }
26
+
27
+ interface AutoHealEntry {
28
+ id: string;
29
+ at: number;
30
+ }
31
+
32
+ interface ImmuneScore {
33
+ antibodies: number;
34
+ autoHealed: number;
35
+ lastAutoHeal: AutoHealEntry | null;
36
+ }
37
+
38
+ interface EcosystemEntry {
39
+ name: string;
40
+ confidence: string;
41
+ }
42
+
43
+ interface EcosystemScore {
44
+ detected: EcosystemEntry[];
45
+ primary: string;
46
+ }
47
+
48
+ interface SuppressionScore {
49
+ massEventsSkipped: number;
50
+ dormantTransitions: number;
51
+ activeTaps: number;
52
+ }
53
+
54
+ interface DynamicImmuneScore {
55
+ activeValidators: number;
56
+ validatorNames: string[];
57
+ }
58
+
59
+ interface ScoreData {
60
+ uptime: number;
61
+ filesDetected: number;
62
+ totalEvents: number;
63
+ lastEvent: string | null;
64
+ lastEventAt: number | null;
65
+ watchedFiles: string[];
66
+ watchTargets: string[];
67
+ hologram: HologramScore;
68
+ immune: ImmuneScore;
69
+ ecosystem: EcosystemScore;
70
+ suppression: SuppressionScore;
71
+ dynamicImmune?: DynamicImmuneScore;
72
+ }
73
+
74
+ // ── ANSI helpers ──
75
+ const C = {
76
+ reset: "\x1b[0m",
77
+ bold: "\x1b[1m",
78
+ dim: "\x1b[2m",
79
+ red: "\x1b[31m",
80
+ green: "\x1b[32m",
81
+ yellow: "\x1b[33m",
82
+ blue: "\x1b[34m",
83
+ magenta: "\x1b[35m",
84
+ cyan: "\x1b[36m",
85
+ white: "\x1b[37m",
86
+ bgRed: "\x1b[41m",
87
+ bgGreen: "\x1b[42m",
88
+ bgYellow: "\x1b[43m",
89
+ };
90
+
91
+ function formatUptime(seconds: number): string {
92
+ if (seconds < 60) return `${seconds}s`;
93
+ if (seconds < 3600) return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
94
+ const h = Math.floor(seconds / 3600);
95
+ const m = Math.floor((seconds % 3600) / 60);
96
+ return `${h}h ${m}m`;
97
+ }
98
+
99
+ function gaugeBar(value: number, max: number, width = 20): string {
100
+ const ratio = Math.min(value / Math.max(max, 1), 1);
101
+ const filled = Math.round(ratio * width);
102
+ const empty = width - filled;
103
+ const color = ratio >= 0.7 ? C.green : ratio >= 0.4 ? C.yellow : C.red;
104
+ const pct = Math.round(ratio * 100);
105
+ return `${color}${"█".repeat(filled)}${C.dim}${"░".repeat(empty)}${C.reset} ${pct}%`;
106
+ }
107
+
108
+ function formatChars(n: number): string {
109
+ if (n < 1000) return `${n}`;
110
+ if (n < 1_000_000) return `${(n / 1000).toFixed(1)}K`;
111
+ return `${(n / 1_000_000).toFixed(1)}M`;
112
+ }
113
+
114
+ const W = 52;
115
+ const line = "─".repeat(W);
116
+
117
+ function row(content: string): string {
118
+ // Strip ANSI for width calculation
119
+ const stripped = content.replace(/\x1b\[[0-9;]*m/g, "");
120
+ const vw = visualWidth(stripped);
121
+ const padSize = Math.max(0, W - vw);
122
+ return `│${content}${" ".repeat(padSize)}│`;
123
+ }
124
+
125
+ function section(title: string): string {
126
+ return row(` ${C.bold}${C.cyan}${title}${C.reset}`);
127
+ }
128
+
129
+ function kv(label: string, value: string): string {
130
+ const stripped = label.replace(/\x1b\[[0-9;]*m/g, "");
131
+ const gap = 18 - visualWidth(stripped);
132
+ return row(` ${C.dim}${label}${C.reset}${" ".repeat(Math.max(1, gap))}${value}`);
133
+ }
134
+
135
+ function guardianGrade(antibodies: number, heals: number, holoSavings: number): { grade: string; label: string; color: string } {
136
+ const score = Math.min(antibodies * 15, 40) + Math.min(heals * 10, 30) + Math.min(holoSavings * 0.3, 30);
137
+ if (score >= 80) return { grade: "A+", label: "FORTIFIED", color: C.green };
138
+ if (score >= 60) return { grade: "A", label: "GUARDED", color: C.green };
139
+ if (score >= 40) return { grade: "B", label: "LEARNING", color: C.yellow };
140
+ if (score >= 20) return { grade: "C", label: "EXPOSED", color: C.yellow };
141
+ return { grade: "D", label: "VULNERABLE", color: C.red };
142
+ }
143
+
144
+ export async function scoreCommand() {
145
+ const lang = getSystemLanguage();
146
+ const i18n = getMessages(lang);
147
+
148
+ try {
149
+ const data = await daemonRequest<ScoreData>("/score");
150
+ const h = data.hologram;
151
+ const holoSav = h.lifetime.savings;
152
+ const grade = guardianGrade(data.immune.antibodies, data.immune.autoHealed, holoSav);
153
+
154
+ const out: string[] = [];
155
+
156
+ // ── Header ──
157
+ out.push(`┌${line}┐`);
158
+ out.push(row(` ${C.bold}🛡️ Guardian Status${C.reset} ${grade.color}${C.bold}[ ${grade.grade} ]${C.reset} ${grade.color}${grade.label}${C.reset}`));
159
+ out.push(`├${line}┤`);
160
+
161
+ // ── Health Gauge ──
162
+ const healthPct = Math.min(data.immune.antibodies * 15 + data.immune.autoHealed * 10 + holoSav * 0.3, 100);
163
+ out.push(row(` ${gaugeBar(healthPct, 100, 30)}`));
164
+ out.push(`├${line}┤`);
165
+
166
+ // ── System Info ──
167
+ out.push(section(lang === "ko" ? "시스템 정보" : "System Info"));
168
+ out.push(kv(i18n.SCORE_ECOSYSTEM, `${C.white}${C.bold}${data.ecosystem.primary}${C.reset}`));
169
+ if (data.ecosystem.detected.length > 1) {
170
+ const others = data.ecosystem.detected.slice(1).map(e => e.name).join(", ");
171
+ out.push(kv(i18n.SCORE_ALSO_FOUND, `${C.dim}${others}${C.reset}`));
172
+ }
173
+ out.push(kv(i18n.SCORE_UPTIME, `${C.green}${formatUptime(data.uptime)}${C.reset}`));
174
+ out.push(kv(i18n.SCORE_EVENTS, `${data.totalEvents}`));
175
+ out.push(kv(i18n.SCORE_FILES_FOUND, `${data.watchedFiles.length}`));
176
+
177
+ // ── Immune System ──
178
+ out.push(`├${line}┤`);
179
+ out.push(section(lang === "ko" ? "면역 시스템" : "Immune System"));
180
+ const ab = data.immune.antibodies;
181
+ const ah = data.immune.autoHealed;
182
+ out.push(kv(i18n.SCORE_ANTIBODIES, `${C.bold}${ab}${C.reset}`));
183
+ out.push(row(` ${lang === "ko" ? "면역력" : "Immunity"} ${gaugeBar(ab, 10, 20)}`));
184
+ out.push(kv(lang === "ko" ? "차단 횟수" : "Prevented", `${C.bold}${C.green}${ah}${C.reset}${C.dim} disaster${ah !== 1 ? "s" : ""}${C.reset}`));
185
+ if (data.immune.lastAutoHeal) {
186
+ const ago = formatUptime(Math.floor((Date.now() - data.immune.lastAutoHeal.at) / 1000));
187
+ out.push(kv(lang === "ko" ? "마지막 치유" : "Last Heal", `${data.immune.lastAutoHeal.id} ${C.dim}(${ago} ago)${C.reset}`));
188
+ }
189
+
190
+ // ── Dynamic Immune Synthesis ──
191
+ if (data.dynamicImmune && data.dynamicImmune.activeValidators > 0) {
192
+ out.push(`├${line}┤`);
193
+ out.push(section(lang === "ko" ? "진화 상태 (동적 면역)" : "Evolution (Dynamic Immune)"));
194
+ out.push(kv(
195
+ lang === "ko" ? "활성 검증기" : "Validators",
196
+ `${C.bold}${C.green}${data.dynamicImmune.activeValidators} Active${C.reset}`
197
+ ));
198
+ const names = data.dynamicImmune.validatorNames.slice(0, 3).join(", ");
199
+ const extra = data.dynamicImmune.validatorNames.length > 3
200
+ ? ` ${C.dim}+${data.dynamicImmune.validatorNames.length - 3} more${C.reset}`
201
+ : "";
202
+ out.push(kv(
203
+ lang === "ko" ? "스크립트" : "Scripts",
204
+ `${C.dim}${names}${C.reset}${extra}`
205
+ ));
206
+ }
207
+
208
+ // ── Hologram Efficiency ──
209
+ out.push(`├${line}┤`);
210
+ out.push(section(lang === "ko" ? "토큰 효율 (홀로그램)" : "Token Efficiency (Hologram)"));
211
+ const lt = h.lifetime;
212
+ if (lt.requests > 0) {
213
+ const ltSaved = lt.originalChars - lt.hologramChars;
214
+ out.push(kv(lang === "ko" ? "총 요청" : "Requests", `${lt.requests}`));
215
+ out.push(kv(lang === "ko" ? "절약된 컨텍스트" : "Saved Context", `${C.green}${formatChars(ltSaved)} chars${C.reset}`));
216
+ out.push(row(` ${lang === "ko" ? "효율" : "Efficiency"} ${gaugeBar(lt.savings, 100, 20)}`));
217
+ if (h.today && h.today.requests > 0) {
218
+ const todaySaved = h.today.originalChars - h.today.hologramChars;
219
+ out.push(kv(lang === "ko" ? "오늘" : "Today", `${h.today.requests} req / ${C.green}${formatChars(todaySaved)} saved${C.reset}`));
220
+ }
221
+ } else {
222
+ out.push(row(` ${C.dim}${i18n.SCORE_HOLOGRAM_EMPTY}${C.reset}`));
223
+ out.push(row(` ${C.dim}${i18n.SCORE_HOLOGRAM_HINT}${C.reset}`));
224
+ }
225
+
226
+ // ── Value Delivered (ROI) ──
227
+ try {
228
+ const summary = await daemonRequest<ShiftSummary>("/shift-summary");
229
+ out.push(`├${line}┤`);
230
+ out.push(section(lang === "ko" ? "전달된 가치 (ROI)" : "Value Delivered (ROI)"));
231
+
232
+ // Breakdown: Auto-Heal
233
+ if (summary.healTokensSaved > 0) {
234
+ out.push(kv(
235
+ lang === "ko" ? "🩹 치유 절약" : "🩹 Heal Saved",
236
+ `${C.dim}~${fmtNum(summary.healTokensSaved)} tok / $${summary.healCostSaved.toFixed(2)}${C.reset}`
237
+ ));
238
+ }
239
+
240
+ // Breakdown: Hologram
241
+ if (summary.hologramTokensSaved > 0) {
242
+ out.push(kv(
243
+ lang === "ko" ? "💎 홀로그램" : "💎 Hologram",
244
+ `${C.dim}~${fmtNum(summary.hologramTokensSaved)} tok / $${summary.hologramCostSaved.toFixed(2)}${C.reset}`
245
+ ));
246
+ }
247
+
248
+ // Total
249
+ out.push(kv(
250
+ lang === "ko" ? "총 절약 토큰" : "Total Tokens",
251
+ `${C.bold}${C.green}~${fmtNum(summary.totalTokensSaved)}${C.reset}`
252
+ ));
253
+ out.push(kv(lang === "ko" ? "절약 시간" : "Time Saved", `${C.green}~${summary.totalMinutesSaved} min${C.reset}`));
254
+ out.push(kv(
255
+ lang === "ko" ? "총 절약 비용" : "Total Cost",
256
+ `${C.bold}${C.green}~$${summary.totalCostSaved.toFixed(2)}${C.reset}`
257
+ ));
258
+ if (summary.suppressionsSkipped > 0) {
259
+ out.push(kv(lang === "ko" ? "억제 횟수" : "Suppressed", `${summary.suppressionsSkipped}`));
260
+ }
261
+ } catch { /* non-fatal */ }
262
+
263
+ // ── Boast ──
264
+ out.push(`├${line}┤`);
265
+ const boast = localizedBoast(lang);
266
+ const truncBoast = boast.length > W - 6 ? boast.slice(0, W - 9) + "..." : boast;
267
+ out.push(row(` ${C.magenta}🗣️ ${truncBoast}${C.reset}`));
268
+ out.push(`└${line}┘`);
269
+
270
+ console.log(out.join("\n"));
271
+ } catch (err: unknown) {
272
+ const msg = err instanceof Error ? err.message : String(err);
273
+ console.error(`${C.red}[afd] ${msg}${C.reset}`);
274
+ process.exit(1);
275
+ }
276
+ }