From c7adde3df2db10340df636b25853a9212a68ec62 Mon Sep 17 00:00:00 2001 From: Wickedness Date: Tue, 9 Jun 2026 14:43:19 +0900 Subject: [PATCH] Add one-click PoC run flow --- .../Services/PocAutomationEngine.cs | 29 ++++++++++ .../ViewModels/MainViewModel.cs | 56 ++++++++++++++++++- TornadoAce_CJOnStyle/Views/MainPage.xaml | 10 +++- docs/poc-requirements.md | 3 +- 4 files changed, 94 insertions(+), 4 deletions(-) diff --git a/TornadoAce_CJOnStyle/Services/PocAutomationEngine.cs b/TornadoAce_CJOnStyle/Services/PocAutomationEngine.cs index 194b026..7b866fd 100644 --- a/TornadoAce_CJOnStyle/Services/PocAutomationEngine.cs +++ b/TornadoAce_CJOnStyle/Services/PocAutomationEngine.cs @@ -153,6 +153,26 @@ namespace TornadoAce_CJOnStyle.Services .ToArray(); } + public PocRunResult RunFullPoc(int selectedCueSheetIndex, SceneTemplateDefinition template) + { + var selection = SelectCueSheet(selectedCueSheetIndex); + var schedule = FindSchedule(selection.Record); + var generatedScene = GenerateScene(selection.Record, template); + var mappingValidations = ValidateMappingProfile(template); + var adapterChecks = GetTornadoAdapterChecks(); + var inspectionSummary = InspectWorkspace(template); + var llmRequests = BuildLlmReviewRequests(inspectionSummary.Results); + + return new PocRunResult( + selection, + schedule, + generatedScene, + mappingValidations, + adapterChecks, + inspectionSummary, + llmRequests); + } + private InspectionResult Inspect(CueSheetRecord cueSheet, SceneDataSnapshot snapshot, SceneTemplateDefinition template) { var expectedObjects = BuildVisibleTextObjects(cueSheet, template); @@ -317,4 +337,13 @@ namespace TornadoAce_CJOnStyle.Services int PassedCount, int ReviewCount, double AverageMatchRate); + + public sealed record PocRunResult( + CueSheetSelection Selection, + ErpScheduleRecord? Schedule, + SceneDataSnapshot GeneratedScene, + IReadOnlyList MappingValidations, + IReadOnlyList AdapterChecks, + PocInspectionSummary InspectionSummary, + IReadOnlyList LlmReviewRequests); } diff --git a/TornadoAce_CJOnStyle/ViewModels/MainViewModel.cs b/TornadoAce_CJOnStyle/ViewModels/MainViewModel.cs index 71ce3e5..8acedb4 100644 --- a/TornadoAce_CJOnStyle/ViewModels/MainViewModel.cs +++ b/TornadoAce_CJOnStyle/ViewModels/MainViewModel.cs @@ -231,6 +231,37 @@ namespace TornadoAce_CJOnStyle.ViewModels LoadLlmReviewRequests(summary.Results); } + [RelayCommand] + private void RunPoc() + { + var result = automationEngine.RunFullPoc(selectedCueSheetIndex, workspace.ActiveTemplate); + activeCueSheet = result.Selection.Record; + activeSchedule = result.Schedule; + activeScene = result.GeneratedScene; + + LastCueSheetSyncText = FormatCueSheetSelection(result.Selection); + ActiveTemplateName = workspace.ActiveTemplate.TemplateName; + InspectionSummary = FormatInspectionSummary(result.InspectionSummary); + OperatorMessage = FormatPocRunSummary(result); + + StatusCards[0].Metric = result.Selection.TotalCount.ToString(); + StatusCards[0].Detail = $"ERP {FormatScheduleStatus(result.Schedule)}"; + StatusCards[1].Metric = workspace.ActiveTemplate.Mappings.Count.ToString(); + StatusCards[1].Detail = "Scene 생성 완료"; + StatusCards[2].Metric = $"{result.InspectionSummary.AverageMatchRate:0.0}%"; + StatusCards[2].Detail = $"LLM 후보 {result.LlmReviewRequests.Count}건"; + StatusCards[3].Metric = "Adapter"; + StatusCards[3].Detail = "Scene API Mock"; + + ApplySceneSnapshot(result.GeneratedScene); + LoadMappingValidation(result.MappingValidations); + LoadTornadoAdapterChecks(result.AdapterChecks); + LoadScheduleMatches(); + LoadInspectionQueue(result.InspectionSummary.Results); + LoadInspectionDetails(result.InspectionSummary.Results); + LoadLlmReviewRequests(result.InspectionSummary.Results); + } + private void LoadStatusCards() { StatusCards.Add(new StatusCardViewModel("큐시트 API", "12", "수신 대기", Symbol.Sync, Brush(0xFF45D6D1))); @@ -257,10 +288,15 @@ namespace TornadoAce_CJOnStyle.ViewModels } private void LoadMappingValidation() + { + LoadMappingValidation(automationEngine.ValidateMappingProfile(workspace.ActiveTemplate)); + } + + private void LoadMappingValidation(IEnumerable validations) { MappingValidations.Clear(); - foreach (var validation in automationEngine.ValidateMappingProfile(workspace.ActiveTemplate)) + foreach (var validation in validations) { MappingValidations.Add(new MappingValidationViewModel( validation.CheckId, @@ -280,10 +316,15 @@ namespace TornadoAce_CJOnStyle.ViewModels } private void LoadTornadoAdapterChecks() + { + LoadTornadoAdapterChecks(automationEngine.GetTornadoAdapterChecks()); + } + + private void LoadTornadoAdapterChecks(IEnumerable checks) { TornadoAdapterChecks.Clear(); - foreach (var check in automationEngine.GetTornadoAdapterChecks()) + foreach (var check in checks) { TornadoAdapterChecks.Add(new TornadoAdapterCheckViewModel( check.CheckId, @@ -404,6 +445,17 @@ namespace TornadoAce_CJOnStyle.ViewModels : $"ERP 편성 {schedule.ProgramCode}와 매칭됐습니다."; } + private static string FormatScheduleStatus(ErpScheduleRecord? schedule) + { + return schedule is null ? "대기" : "매칭"; + } + + private static string FormatPocRunSummary(PocRunResult result) + { + var scheduleText = result.Schedule is null ? "ERP 미확인" : result.Schedule.ProgramCode; + return $"PoC 실행 완료: {result.Selection.Record.CueSheetId} / {scheduleText} / {result.GeneratedScene.SceneName} / 검수 확인 {result.InspectionSummary.ReviewCount}건 / LLM 후보 {result.LlmReviewRequests.Count}건"; + } + private static SolidColorBrush SeverityBrush(string severity) { return severity switch diff --git a/TornadoAce_CJOnStyle/Views/MainPage.xaml b/TornadoAce_CJOnStyle/Views/MainPage.xaml index 7cf2166..9c0dcf9 100644 --- a/TornadoAce_CJOnStyle/Views/MainPage.xaml +++ b/TornadoAce_CJOnStyle/Views/MainPage.xaml @@ -119,6 +119,14 @@ Orientation="Horizontal" Spacing="10" VerticalAlignment="Top"> +