@triflux/core 10.50.1 → 10.51.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 (90) hide show
  1. package/hooks/agy-session-hook.mjs +11 -56
  2. package/hooks/codex-session-hook.mjs +11 -101
  3. package/hub/bridge.mjs +1 -79
  4. package/hub/cli-adapter-base.mjs +12 -90
  5. package/hub/codex-adapter.mjs +0 -1
  6. package/hub/codex-preflight.mjs +5 -28
  7. package/hub/index.mjs +3 -9
  8. package/hub/lib/cto-env.mjs +0 -23
  9. package/hub/lib/known-errors.json +2 -2
  10. package/hub/lib/process-utils.mjs +0 -123
  11. package/hub/lib/spawn-trace.mjs +3 -2
  12. package/hub/lib/timeout-defaults.mjs +0 -1
  13. package/hub/paths.mjs +0 -6
  14. package/hub/pipeline/index.mjs +0 -190
  15. package/hub/pipeline/transitions.mjs +0 -10
  16. package/hub/reflexion.mjs +1 -84
  17. package/hub/role-contract.mjs +0 -2
  18. package/hud/cli-policy.mjs +0 -26
  19. package/hud/colors.mjs +0 -13
  20. package/hud/constants.mjs +7 -153
  21. package/hud/context-monitor.mjs +3 -64
  22. package/hud/hud-qos-status.mjs +54 -264
  23. package/hud/providers/claude.mjs +4 -16
  24. package/hud/providers/gemini.mjs +83 -689
  25. package/hud/renderers.mjs +59 -367
  26. package/hud/terminal.mjs +1 -63
  27. package/hud/utils.mjs +2 -26
  28. package/package.json +1 -4
  29. package/scripts/lib/agent-route-policy.mjs +162 -14
  30. package/scripts/lib/claudemd-scanner.mjs +2 -199
  31. package/scripts/lib/cli-claude.mjs +0 -2
  32. package/scripts/lib/context.mjs +3 -19
  33. package/scripts/lib/env-probe.mjs +5 -64
  34. package/scripts/lib/gemini-profiles.mjs +2 -69
  35. package/scripts/lib/legacy-mcp-cleanup.mjs +14 -3
  36. package/scripts/lib/machine-profile.mjs +3 -17
  37. package/scripts/lib/mcp-filter.mjs +109 -53
  38. package/scripts/lib/mcp-health.mjs +2 -2
  39. package/scripts/lib/mcp-server-catalog.mjs +2 -2
  40. package/scripts/lib/psmux-info.mjs +25 -104
  41. package/scripts/lib/session-presence.mjs +1 -1
  42. package/scripts/lib/skill-template.mjs +0 -271
  43. package/hub/codex-compat.mjs +0 -12
  44. package/hub/dynamic-routing-engine.mjs +0 -511
  45. package/hub/fullcycle.mjs +0 -113
  46. package/hub/gemini-adapter.mjs +0 -174
  47. package/hub/intent.mjs +0 -321
  48. package/hub/lib/mcp-response-cache.mjs +0 -239
  49. package/hub/lib/path-utils.mjs +0 -165
  50. package/hub/lib/risk-tier.mjs +0 -53
  51. package/hub/lib/ssh-command.mjs +0 -231
  52. package/hub/lib/staged-file-detect.mjs +0 -43
  53. package/hub/lib/tfx-route-args.mjs +0 -353
  54. package/hub/lib/timeline-adapter.mjs +0 -190
  55. package/hub/pipeline/gates/confidence.mjs +0 -75
  56. package/hub/pipeline/gates/consensus.mjs +0 -106
  57. package/hub/pipeline/gates/index.mjs +0 -9
  58. package/hub/pipeline/gates/selfcheck.mjs +0 -120
  59. package/hub/quality/deslop.mjs +0 -274
  60. package/hub/research.mjs +0 -155
  61. package/hub/role-control-events.mjs +0 -113
  62. package/hub/routing/complexity.mjs +0 -269
  63. package/hub/routing/index.mjs +0 -122
  64. package/hub/routing/q-learning.mjs +0 -387
  65. package/hub/routing-snapshot.mjs +0 -261
  66. package/hub/token-mode.mjs +0 -228
  67. package/hud/mission-board.mjs +0 -56
  68. package/hud/providers/cto.mjs +0 -76
  69. package/mesh/index.mjs +0 -69
  70. package/mesh/mesh-budget.mjs +0 -137
  71. package/mesh/mesh-heartbeat.mjs +0 -100
  72. package/mesh/mesh-protocol.mjs +0 -96
  73. package/mesh/mesh-queue.mjs +0 -163
  74. package/mesh/mesh-registry.mjs +0 -78
  75. package/mesh/mesh-router.mjs +0 -77
  76. package/scripts/lib/agent-json.mjs +0 -27
  77. package/scripts/lib/async.mjs +0 -174
  78. package/scripts/lib/cli-agy.mjs +0 -85
  79. package/scripts/lib/cli-codex.mjs +0 -62
  80. package/scripts/lib/cli-gemini.mjs +0 -37
  81. package/scripts/lib/dynamic-route-cli.mjs +0 -107
  82. package/scripts/lib/env.mjs +0 -14
  83. package/scripts/lib/hub.mjs +0 -48
  84. package/scripts/lib/pid.mjs +0 -63
  85. package/scripts/lib/quota.mjs +0 -47
  86. package/scripts/lib/skill-state.mjs +0 -220
  87. package/scripts/lib/team.mjs +0 -75
  88. package/scripts/lib/timeout.mjs +0 -66
  89. package/scripts/lib/tmp.mjs +0 -26
  90. package/scripts/lib/toml.mjs +0 -132
@@ -488,68 +488,6 @@ function hasExactGbrainServe(commandLine) {
488
488
  );
489
489
  }
490
490
 
491
- function hasGbrainServeCommand(commandLine) {
492
- return /(^|\s)gbrain\s+serve(\s|$)/i.test(commandLine.trim());
493
- }
494
-
495
- function hasFsmonitorDaemonCommand(commandLine) {
496
- return FSMONITOR_DAEMON_PATTERN.test(commandLine);
497
- }
498
-
499
- function categoryForShardProcess(proc, context) {
500
- const name = normalizeName(proc.name);
501
- const commandLine = normalizeCommandLine(proc.commandLine);
502
- const worktreePath = normalizeCommandLine(context.worktreePath || "");
503
- const shardMarker = context.shardName
504
- ? `.codex-swarm\\wt-${context.shardName}`
505
- : "";
506
- const hasWorktree = worktreePath && commandLine.includes(worktreePath);
507
- const hasShardMarker = shardMarker && commandLine.includes(shardMarker);
508
-
509
- if (name === "node.exe" || name === "node") {
510
- if (hasWorktree || hasShardMarker) return "node";
511
- }
512
-
513
- if (name === "bash.exe" || name === "bash" || name === "sh") {
514
- if (hasWorktree) return "bash";
515
- }
516
-
517
- if (name === "conhost.exe" || name === "conhost") {
518
- if (
519
- context.sessionIds?.length > 0 &&
520
- context.sessionIds.some((id) => id && commandLine.includes(id))
521
- ) {
522
- return "conhost";
523
- }
524
- }
525
-
526
- if (name === "bun.exe" || name === "bun") {
527
- if ((hasWorktree || hasShardMarker) && hasGbrainServeCommand(commandLine)) {
528
- return "bun";
529
- }
530
- }
531
-
532
- if (name === "git.exe" || name === "git") {
533
- if (
534
- (hasWorktree || hasShardMarker) &&
535
- hasFsmonitorDaemonCommand(commandLine)
536
- ) {
537
- return "git";
538
- }
539
- }
540
-
541
- return null;
542
- }
543
-
544
- function killPid(
545
- pid,
546
- { killFn = process.kill, protectedPids = new Set() } = {},
547
- ) {
548
- if (protectedPids.has(pid)) return false;
549
- killFn(pid, "SIGKILL");
550
- return true;
551
- }
552
-
553
491
  /**
554
492
  * Return a process tree rooted at `rootPid`.
555
493
  *
@@ -730,67 +668,6 @@ export function findProcessesByCommandLine(
730
668
  });
731
669
  }
732
670
 
733
- /**
734
- * Cleanup processes associated with a swarm shard.
735
- *
736
- * Sequence: kill known top PID snapshots, scan scoped command lines, skip
737
- * protected PIDs, and kill only narrowly gated runtime categories.
738
- *
739
- * @param {{worktreePath?: string, sessionIds?: string[], topPids?: Array<number | {pid: number}>, runId?: string, shardName?: string, dryRun?: boolean, isWindows?: boolean, spawnSyncFn?: typeof spawnSync, killFn?: typeof process.kill, protectedPids?: Set<number>}} opts
740
- * @returns {{killed: number, scanned: number, skipped: number, byCategory: {node: number, bash: number, conhost: number, bun: number, git: number}}}
741
- */
742
- export function cleanupShardProcesses({
743
- worktreePath,
744
- sessionIds = [],
745
- topPids = [],
746
- runId,
747
- shardName,
748
- dryRun = false,
749
- isWindows = IS_WINDOWS,
750
- spawnSyncFn = spawnSync,
751
- killFn = process.kill,
752
- protectedPids,
753
- } = {}) {
754
- const protectedSet = getProtectedPids({
755
- protectedPids,
756
- isWindows,
757
- spawnSyncFn,
758
- includeAncestorScan: true,
759
- });
760
- const byCategory = { node: 0, bash: 0, conhost: 0, bun: 0, git: 0 };
761
- let killed = 0;
762
- let skipped = 0;
763
-
764
- if (!dryRun && topPids.length > 0) {
765
- killed += killProcessTreeSnapshot(topPids, {
766
- killFn,
767
- protectedPids: protectedSet,
768
- }).killed;
769
- }
770
-
771
- const scanned = getProcessSnapshot({ isWindows, spawnSyncFn });
772
-
773
- for (const proc of scanned) {
774
- const category = categoryForShardProcess(proc, {
775
- worktreePath,
776
- sessionIds,
777
- shardName,
778
- });
779
- if (!category) continue;
780
- byCategory[category]++;
781
- if (protectedSet.has(proc.pid)) {
782
- skipped++;
783
- continue;
784
- }
785
- if (dryRun) continue;
786
- try {
787
- if (killPid(proc.pid, { killFn, protectedPids: protectedSet })) killed++;
788
- } catch {}
789
- }
790
-
791
- return { killed, scanned: scanned.length, skipped, byCategory };
792
- }
793
-
794
671
  /**
795
672
  * Cleanup narrowly gated orphan runtime processes.
796
673
  *
@@ -7,13 +7,14 @@ import { join } from "node:path";
7
7
  const LOG_DIR = join(homedir(), ".triflux", "logs");
8
8
  const DEDUPE_WINDOW_MS = 5_000;
9
9
  const RATE_WINDOW_MS = 1_000;
10
+ const DEFAULT_MAX_SPAWN_PER_SEC = 100;
10
11
  // multi-worker headless dispatch 가 1 초 안에 ~25-30+ psmux/tmux 명령을 호출한다.
11
12
  // 2-worker dispatchBatch 가 default 30 limit 을 초과해 `rate_limit` throw 로 mac
12
13
  // 호환성 회귀 (smoke test 발견, 2026-05-15). 100 으로 상향 — 폭주 안전망은
13
14
  // 여전히 (default 100/sec) 유지, env override 로 보수 설정 가능.
14
15
  export let MAX_SPAWN_PER_SEC = resolvePositiveInteger(
15
16
  process.env.TRIFLUX_MAX_SPAWN_RATE,
16
- 100,
17
+ DEFAULT_MAX_SPAWN_PER_SEC,
17
18
  );
18
19
  export const MAX_TOTAL_DESCENDANTS = resolvePositiveInteger(
19
20
  process.env.TRIFLUX_MAX_DESCENDANTS,
@@ -160,7 +161,7 @@ export function getMaxSpawnPerSec() {
160
161
  export function reload() {
161
162
  MAX_SPAWN_PER_SEC = resolvePositiveInteger(
162
163
  process.env.TRIFLUX_MAX_SPAWN_RATE,
163
- 30,
164
+ DEFAULT_MAX_SPAWN_PER_SEC,
164
165
  );
165
166
  return getMaxSpawnPerSec();
166
167
  }
@@ -5,7 +5,6 @@ export const MAX_DURATION_MS = 86_400_000;
5
5
  export const DEFAULT_ASSIGN_TIMEOUT_MS = 600_000;
6
6
  export const DEFAULT_ASSIGN_TTL_MS = 600_000;
7
7
  export const DEFAULT_HANDOFF_TTL_MS = 600_000;
8
- export const DEFAULT_SWARM_LOCK_TTL_MS = 600_000;
9
8
  export const DEFAULT_REGISTER_TIMEOUT_SEC = 600;
10
9
  export const REGISTER_HEARTBEAT_GRACE_MS = 120_000;
11
10
  export const DEFAULT_STALL_INTERVENTION_SEC = 1_200;
package/hub/paths.mjs CHANGED
@@ -6,10 +6,7 @@ import { join } from "node:path";
6
6
  export const TFX_WORK_DIR = ".tfx";
7
7
  export const TFX_PLANS_DIR = join(TFX_WORK_DIR, "plans");
8
8
  export const TFX_REPORTS_DIR = join(TFX_WORK_DIR, "reports");
9
- export const TFX_HANDOFFS_DIR = join(TFX_WORK_DIR, "handoffs");
10
- export const TFX_LOGS_DIR = join(TFX_WORK_DIR, "logs");
11
9
  export const TFX_STATE_DIR = join(TFX_WORK_DIR, "state");
12
- export const TFX_FULLCYCLE_DIR = join(TFX_WORK_DIR, "fullcycle");
13
10
 
14
11
  /**
15
12
  * triflux 워킹 디렉토리 구조를 보장한다.
@@ -20,10 +17,7 @@ export function ensureTfxDirs(baseDir) {
20
17
  TFX_WORK_DIR,
21
18
  TFX_PLANS_DIR,
22
19
  TFX_REPORTS_DIR,
23
- TFX_HANDOFFS_DIR,
24
- TFX_LOGS_DIR,
25
20
  TFX_STATE_DIR,
26
- TFX_FULLCYCLE_DIR,
27
21
  ]) {
28
22
  mkdirSync(join(baseDir, relativeDir), { recursive: true });
29
23
  }
@@ -3,11 +3,7 @@
3
3
  // 상태(state.mjs) + 전이(transitions.mjs) 통합 인터페이스
4
4
 
5
5
  import { mkdirSync, writeFileSync } from "node:fs";
6
- import { homedir } from "node:os";
7
6
  import { join, resolve } from "node:path";
8
- import { classifyIntent as _classifyIntent } from "../intent.mjs";
9
- import { runConfidenceCheck } from "./gates/confidence.mjs";
10
- import { runSelfCheck } from "./gates/selfcheck.mjs";
11
7
  import {
12
8
  ensurePipelineTable,
13
9
  initPipelineState,
@@ -21,7 +17,6 @@ import {
21
17
  TERMINAL,
22
18
  transitionPhase,
23
19
  } from "./transitions.mjs";
24
- // deslop gate: 호출자가 scanDirectory/detectSlop 결과를 전달
25
20
 
26
21
  /**
27
22
  * 파이프라인 매니저 생성
@@ -162,192 +157,7 @@ export function createPipeline(db, teamName, opts = {}) {
162
157
  remove() {
163
158
  return removePipelineState(db, teamName);
164
159
  },
165
-
166
- /**
167
- * Confidence Gate 실행 + 자동 전이
168
- * prd → confidence → exec/failed
169
- * @param {string|object} planArtifact
170
- * @param {object} context - { checks?, codebaseFiles?, existingTests? }
171
- * @returns {{ ok: boolean, gate: object, state?: object, error?: string }}
172
- */
173
- runConfidenceGate(planArtifact, context = {}) {
174
- const current = readPipelineState(db, teamName);
175
- if (!current) return { ok: false, error: `파이프라인 없음: ${teamName}` };
176
-
177
- if (current.phase !== "confidence") {
178
- return {
179
- ok: false,
180
- error: `confidence gate는 confidence 단계에서만 실행 가능 (현재: ${current.phase})`,
181
- };
182
- }
183
-
184
- const gate = runConfidenceCheck(planArtifact, context);
185
- this.setArtifact("confidence_result", gate);
186
-
187
- if (gate.decision === "abort") {
188
- const result = this.advance("failed");
189
- return { ok: true, gate, state: result.state };
190
- }
191
-
192
- // proceed 또는 alternative → exec로 전이
193
- const result = this.advance("exec");
194
- return { ok: result.ok, gate, state: result.state, error: result.error };
195
- },
196
-
197
- /**
198
- * Deslop Gate 실행 + 자동 전이
199
- * exec → deslop → verify
200
- * 호출자가 미리 deslop 결과를 생성하여 전달.
201
- * @param {object} [deslopResult] - scanDirectory() 또는 detectSlop() 결과
202
- * @returns {{ ok: boolean, gate: object, state?: object, error?: string }}
203
- */
204
- runDeslopGate(deslopResult = null) {
205
- const current = readPipelineState(db, teamName);
206
- if (!current) return { ok: false, error: `파이프라인 없음: ${teamName}` };
207
-
208
- if (current.phase !== "deslop") {
209
- return {
210
- ok: false,
211
- error: `deslop gate는 deslop 단계에서만 실행 가능 (현재: ${current.phase})`,
212
- };
213
- }
214
-
215
- const gate = deslopResult || {
216
- files: [],
217
- summary: { total: 0, clean: 0 },
218
- };
219
- this.setArtifact("deslop_result", gate);
220
-
221
- // deslop은 항상 verify로 전이 (정보 제공 게이트, 차단 없음)
222
- const result = this.advance("verify");
223
- return { ok: result.ok, gate, state: result.state, error: result.error };
224
- },
225
-
226
- /**
227
- * Self-Check Gate 실행 + 자동 전이
228
- * verify → selfcheck → complete/fix
229
- * @param {string|object} execResult
230
- * @param {string|object} verifyResult
231
- * @param {object} requirements - { hasDiff?, evidence? }
232
- * @returns {{ ok: boolean, gate: object, state?: object, error?: string }}
233
- */
234
- runSelfCheckGate(execResult, verifyResult, requirements = {}) {
235
- const current = readPipelineState(db, teamName);
236
- if (!current) return { ok: false, error: `파이프라인 없음: ${teamName}` };
237
-
238
- if (current.phase !== "selfcheck") {
239
- return {
240
- ok: false,
241
- error: `selfcheck gate는 selfcheck 단계에서만 실행 가능 (현재: ${current.phase})`,
242
- };
243
- }
244
-
245
- const gate = runSelfCheck(execResult, verifyResult, requirements);
246
- this.setArtifact("selfcheck_result", gate);
247
-
248
- if (gate.passed) {
249
- const result = this.advance("complete");
250
- return {
251
- ok: result.ok,
252
- gate,
253
- state: result.state,
254
- error: result.error,
255
- };
256
- }
257
-
258
- // Red Flag 탐지 또는 필수 질문 실패 → fix
259
- const result = this.advance("fix");
260
- return { ok: result.ok, gate, state: result.state, error: result.error };
261
- },
262
160
  };
263
161
  }
264
-
265
- // ── 토큰 벤치마크 훅 ──
266
-
267
- let _tokenSnapshotMod = null;
268
-
269
- async function loadTokenSnapshot() {
270
- if (_tokenSnapshotMod) return _tokenSnapshotMod;
271
- try {
272
- _tokenSnapshotMod = await import("../../scripts/token-snapshot.mjs");
273
- } catch {
274
- _tokenSnapshotMod = null;
275
- }
276
- return _tokenSnapshotMod;
277
- }
278
-
279
- /**
280
- * 파이프라인 시작 시 토큰 스냅샷 캡처
281
- * @param {string} label - 스냅샷 라벨 (e.g. teamName + timestamp)
282
- * @returns {Promise<{label: string, snapshot: object}|null>}
283
- */
284
- export async function benchmarkStart(label) {
285
- const mod = await loadTokenSnapshot();
286
- if (!mod?.takeSnapshot) return null;
287
- try {
288
- const snapshot = mod.takeSnapshot(label);
289
- return { label, snapshot };
290
- } catch {
291
- return null;
292
- }
293
- }
294
-
295
- /**
296
- * 파이프라인 종료 시 diff 계산 + 결과 저장
297
- * @param {string} preLabel - 시작 스냅샷 라벨
298
- * @param {string} postLabel - 종료 스냅샷 라벨
299
- * @param {object} options - { agent?, cli?, id? }
300
- * @returns {Promise<object|null>} diff 결과
301
- */
302
- export async function benchmarkEnd(preLabel, postLabel, options = {}) {
303
- const mod = await loadTokenSnapshot();
304
- if (!mod?.takeSnapshot || !mod?.computeDiff) return null;
305
- try {
306
- // 종료 스냅샷 캡처
307
- mod.takeSnapshot(postLabel);
308
- // diff 계산 (결과는 DIFFS_DIR에 자동 저장됨)
309
- const diff = mod.computeDiff(preLabel, postLabel, options);
310
-
311
- // 추가로 타임스탬프 기반 사본 저장
312
- const diffsDir = join(
313
- homedir(),
314
- ".omc",
315
- "state",
316
- "cx-auto-tokens",
317
- "diffs",
318
- );
319
- mkdirSync(diffsDir, { recursive: true });
320
- const ts = new Date().toISOString().replace(/[:.]/g, "-");
321
- const outPath = join(diffsDir, `${ts}.json`);
322
- writeFileSync(outPath, JSON.stringify(diff, null, 2));
323
-
324
- return diff;
325
- } catch {
326
- return null;
327
- }
328
- }
329
-
330
- /**
331
- * 트리아지 통합: quickClassify 고신뢰 시 Codex 분류 스킵 판정
332
- * @param {string} prompt
333
- * @param {number} [threshold=0.8]
334
- * @returns {{ skip: boolean, routing: object|null, classification: object }}
335
- */
336
- export function triageWithIntent(prompt, threshold = 0.8) {
337
- const classification = _classifyIntent(prompt);
338
- if (classification.confidence >= threshold) {
339
- return { skip: true, routing: classification.routing, classification };
340
- }
341
- return { skip: false, routing: null, classification };
342
- }
343
-
344
- export {
345
- classifyIntent,
346
- INTENT_CATEGORIES,
347
- quickClassify,
348
- } from "../intent.mjs";
349
- export { autoFixSlop, detectSlop, scanDirectory } from "../quality/deslop.mjs";
350
- export { CRITERIA, runConfidenceCheck } from "./gates/confidence.mjs";
351
- export { QUESTIONS, RED_FLAGS, runSelfCheck } from "./gates/selfcheck.mjs";
352
162
  export { ensurePipelineTable } from "./state.mjs";
353
163
  export { ALLOWED, canTransition, PHASES, TERMINAL } from "./transitions.mjs";
@@ -73,19 +73,9 @@ export function transitionPhase(state, nextPhase) {
73
73
  }
74
74
  }
75
75
 
76
- // fix → exec 재진입 시 (fix 후 재실행)
77
- if (current === "fix" && nextPhase === "exec") {
78
- // fix_attempt 유지 (이미 fix 진입 시 증가됨)
79
- }
80
-
81
76
  // verify → fix → ... → verify 반복 후 fix_max 초과 시 ralph loop
82
77
  if (nextPhase === "failed" && current === "fix") {
83
- // ralph loop 반복 증가
84
78
  next.ralph_iteration = (state.ralph_iteration || 0) + 1;
85
- if (next.ralph_iteration > (state.ralph_max || 10)) {
86
- // 최종 실패 — ralph loop도 초과
87
- next.phase = "failed";
88
- }
89
79
  }
90
80
 
91
81
  // phase_history 기록
package/hub/reflexion.mjs CHANGED
@@ -1,10 +1,7 @@
1
- // hub/reflexion.mjs — Cross-Session Error Learning Engine
2
- // 에러를 구조화 저장 → 다음 세션에서 유사 에러 패턴 매칭 → 자동 솔루션 적용
1
+ // 오류 패턴 정규화 및 adaptive rule 관리
3
2
 
4
- const DEFAULT_REFLEXION_TYPE = "reflexion";
5
3
  export const ADAPTIVE_RULE_TYPE = "adaptive";
6
4
  const DEFAULT_CONFIDENCE = 0.5;
7
- const ACTIVE_RULE_CONFIDENCE = 0.5;
8
5
  const ADAPTIVE_PROMOTION_STEP = 0.1;
9
6
  const ADAPTIVE_DECAY_STEP = 0.1;
10
7
  const ADAPTIVE_DELETE_THRESHOLD = 0.3;
@@ -100,12 +97,6 @@ function buildAdaptiveSolution(errorContext = {}, errorText = "") {
100
97
  return `${toolName} 재시도 전 실패 원인을 검증하세요: ${summary}`;
101
98
  }
102
99
 
103
- function filterEntriesByType(entries, type) {
104
- return entries.filter(
105
- (entry) => (entry.type || DEFAULT_REFLEXION_TYPE) === type,
106
- );
107
- }
108
-
109
100
  function parseAdaptiveRuleId(ruleId, projectSlug = "") {
110
101
  const value = pickString(ruleId);
111
102
  if (!value) return null;
@@ -187,68 +178,6 @@ export function normalizeError(errorMessage) {
187
178
  return p.toLowerCase().replace(/\s+/g, " ").trim();
188
179
  }
189
180
 
190
- /**
191
- * 에러에 대한 기존 솔루션 검색
192
- * @deprecated reflexion_entries 기반. adaptive_rules로 통합 예정. 현재 런타임 호출 없음.
193
- * @param {object} store - createStore() 반환 객체
194
- * @param {string} errorMessage - 원본 에러 메시지
195
- * @param {object} [context={}] - { file, function, cli, agent }
196
- * @returns {{ found: boolean, entries: Array, bestMatch: object|null }}
197
- */
198
- export function lookupSolution(store, errorMessage, context = {}) {
199
- const pattern = normalizeError(errorMessage);
200
- if (!pattern) return { found: false, entries: [], bestMatch: null };
201
- const entries = store.findReflexion(pattern, context);
202
- if (!entries.length) return { found: false, entries: [], bestMatch: null };
203
- return { found: true, entries, bestMatch: entries[0] };
204
- }
205
-
206
- /**
207
- * 에러 해결 후 학습 저장
208
- * @deprecated reflexion_entries 기반. adaptive_rules로 통합 예정. 현재 런타임 호출 없음.
209
- * 동일 패턴이 존재하면 hit 업데이트, 없으면 새로 생성
210
- * @param {object} store
211
- * @param {{ error: string, solution: string, context?: object, success?: boolean }} opts
212
- * @returns {object|null}
213
- */
214
- export function learnFromError(
215
- store,
216
- { error, solution, context = {}, success = false },
217
- ) {
218
- const pattern = normalizeError(error);
219
- if (!pattern || !solution) return null;
220
- const existing = filterEntriesByType(
221
- store.findReflexion(pattern, context),
222
- DEFAULT_REFLEXION_TYPE,
223
- );
224
- if (existing.length && existing[0].error_pattern === pattern) {
225
- return store.updateReflexionHit(existing[0].id, success);
226
- }
227
- const newEntry = store.addReflexion({
228
- type: DEFAULT_REFLEXION_TYPE,
229
- error_pattern: pattern,
230
- error_message: error,
231
- context,
232
- solution,
233
- solution_code: null,
234
- });
235
- return success && newEntry
236
- ? store.updateReflexionHit(newEntry.id, true)
237
- : newEntry;
238
- }
239
-
240
- /**
241
- * 솔루션 적용 결과 피드백
242
- * @deprecated reflexion_entries 기반. adaptive_rules로 통합 예정. 현재 런타임 호출 없음.
243
- * @param {object} store
244
- * @param {string} entryId
245
- * @param {boolean} success
246
- * @returns {object|null}
247
- */
248
- export function reportOutcome(store, entryId, success) {
249
- return store.updateReflexionHit(entryId, success);
250
- }
251
-
252
181
  /**
253
182
  * PostToolUseFailure 컨텍스트에서 adaptive rule payload 생성
254
183
  * @param {object} errorContext
@@ -347,18 +276,6 @@ export function decayRules(store, _sessionCount, projectSlug) {
347
276
  return result;
348
277
  }
349
278
 
350
- /**
351
- * 현재 활성화된 adaptive rules 조회
352
- * @param {object} store — store-adapter 인스턴스 (listAdaptiveRules 필요)
353
- * @param {string} projectSlug
354
- * @returns {Array}
355
- */
356
- export function getActiveAdaptiveRules(store, projectSlug) {
357
- return listAdaptiveRulesFromStore(store, projectSlug).filter(
358
- (rule) => rule.confidence >= ACTIVE_RULE_CONFIDENCE,
359
- );
360
- }
361
-
362
279
  /**
363
280
  * 신뢰도 자동 조정 (success_count / hit_count, 샘플 크기 기반 감쇠)
364
281
  * hit_count가 작으면 0.5(기본값)쪽으로 보수적으로 수렴
@@ -216,8 +216,6 @@ export function reduceRoleReachabilityTransition(state, trigger) {
216
216
  : { state: transition.to, action: transition.action };
217
217
  }
218
218
 
219
- export const reduceRoleReachability = reduceRoleReachabilityTransition;
220
-
221
219
  function snapshotLegacyDetails(snapshot) {
222
220
  const legacy = isRecord(snapshot.legacy) ? snapshot.legacy : {};
223
221
  return {
@@ -41,29 +41,3 @@ export function resolveHudCliVisibility(env = process.env, opts = {}) {
41
41
  return { showCodex: true, antigravityAllowed: true, policy: null };
42
42
  }
43
43
  }
44
-
45
- /**
46
- * antigravity / gemini 슬롯 행을 그릴지 판정한다.
47
- *
48
- * antigravity 가 허용이면 기존 동작 그대로 항상 그린다. 정책으로 꺼졌을 때만
49
- * gemini 폴백 정보가 하나라도 있는지 보고, 전부 비어 있으면 행을 생략한다.
50
- *
51
- * @param {{
52
- * antigravityAllowed?: boolean,
53
- * antigravityReady?: boolean,
54
- * geminiEmail?: unknown,
55
- * geminiBucket?: unknown,
56
- * geminiSession?: unknown,
57
- * }} [args]
58
- * @returns {boolean}
59
- */
60
- export function shouldRenderGeminiFallbackRow({
61
- antigravityAllowed = true,
62
- antigravityReady = false,
63
- geminiEmail = null,
64
- geminiBucket = null,
65
- geminiSession = null,
66
- } = {}) {
67
- if (antigravityAllowed || antigravityReady) return true;
68
- return Boolean(geminiEmail || geminiBucket || geminiSession);
69
- }
package/hud/colors.mjs CHANGED
@@ -47,20 +47,7 @@ export function colorByPercent(value, text) {
47
47
  return green(text);
48
48
  }
49
49
 
50
- export function colorCooldown(seconds, text) {
51
- if (seconds > 120) return red(text);
52
- if (seconds > 0) return yellow(text);
53
- return dim(text);
54
- }
55
-
56
- export function colorParallel(current, cap) {
57
- if (current >= cap) return green(`${current}/${cap}`);
58
- if (current > 1) return yellow(`${current}/${cap}`);
59
- return red(`${current}/${cap}`);
60
- }
61
-
62
50
  export const GAUGE_WIDTH = 5;
63
- export const GAUGE_BLOCKS = ["░", "▒", "▓", "█"]; // 밝기 0~3
64
51
 
65
52
  export function coloredBar(percent, width = GAUGE_WIDTH, baseColor = null) {
66
53
  const safePercent = Math.min(100, Math.max(0, percent));