using ExperionCrawler.Core.Application.Feedforward; namespace ExperionCrawler.Infrastructure.Control; public sealed class FeedforwardWriteGuard : IFeedforwardWriteGuard { public WriteCheckResult Check(ColumnConfig cfg, StreamAdvisory adv, StreamConfig sc, AdvisoryResult column) { if (adv.Role != StreamRole.Commanded) return new WriteCheckResult(false, "Commanded 스트림만 SP 쓰기 대상"); if (cfg.AdvisoryOnly) return new WriteCheckResult(false, "컬럼이 AdvisoryOnly 모드"); if (adv.RecommendedSp is not double sp) return new WriteCheckResult(false, "권장 SP 없음"); if (!adv.Valid) return new WriteCheckResult(false, "Advisory 무효(전환류 오버라이드 등)"); if (adv.Grade == Confidence.C) return new WriteCheckResult(false, $"신뢰도 C — SP 쓰기 차단"); if (column.Transient) return new WriteCheckResult(false, "과도 상태 — SP 쓰기 차단"); if (sp < sc.SpMin || sp > sc.SpMax) return new WriteCheckResult(false, $"SP {sp:F2} 허용범위 [{sc.SpMin:F2}, {sc.SpMax:F2}] 벗어남"); if (double.IsNaN(sp) || double.IsInfinity(sp)) return new WriteCheckResult(false, "SP 값이 NaN/Infinity"); return new WriteCheckResult(true, null); } }