diff --git a/README.md b/README.md index be0d4c6..c280088 100644 --- a/README.md +++ b/README.md @@ -1856,3 +1856,12 @@ MIT License - 테스트로 [HtmlSkillConsultingSectionsTests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/HtmlSkillConsultingSectionsTests.cs), [ExcelSkillDashboardSummaryTests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/ExcelSkillDashboardSummaryTests.cs), [ArtifactQualityReviewServiceTests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/ArtifactQualityReviewServiceTests.cs), [PptxSkillGoldenDeckTests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/PptxSkillGoldenDeckTests.cs)를 확장했습니다. - 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_doc_next5\\ -p:IntermediateOutputPath=obj\\verify_doc_next5\\` 경고 0 / 오류 0 - 검증: `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "ArtifactQualityReviewServiceTests|ExcelSkillDashboardSummaryTests|HtmlSkillConsultingSectionsTests|HtmlSkillPrintFrameTests|DeckQualityReviewServiceTests|PptxSkillGoldenDeckTests|PptxSkillAutoRepairTests|PptxSkillConsultingDeckTests" -p:OutputPath=bin\\verify_doc_next5_tests\\ -p:IntermediateOutputPath=obj\\verify_doc_next5_tests\\` 통과 14 + +업데이트: 2026-04-14 23:58 (KST) +- 문서 공통 critic/repair 가이드를 추가했습니다. [ArtifactRepairGuideService.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/ArtifactRepairGuideService.cs)는 HTML/XLSX/DOCX 품질 리뷰 결과를 사람이 바로 이해할 수 있는 수정 방향으로 변환합니다. 이후 [HtmlSkill.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/HtmlSkill.cs), [ExcelSkill.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/ExcelSkill.cs), [DocumentAssemblerTool.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/DocumentAssemblerTool.cs)가 품질 점수 뒤에 `Repair guide:`를 함께 반환합니다. +- [ExcelSkill.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/ExcelSkill.cs)는 `dashboard_tiles`, `variance_series`를 지원하도록 확장됐습니다. `Dashboard` 시트에서 decision summary, scorecards, KPI, trend dashboard에 이어 dashboard tiles와 variance overview까지 함께 보여주는 운영 리뷰형 workbook 구성이 가능해졌습니다. +- [ArtifactQualityReviewService.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/ArtifactQualityReviewService.cs)의 workbook 리뷰는 `dashboard_tiles`, `variance_series`도 summary/dashboard 품질 신호로 인식하도록 보강했습니다. +- 목적형 스킬도 확장했습니다. [strategy-brief-html.skill.md](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/skills/strategy-brief-html.skill.md), [operating-review-xlsx.skill.md](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/skills/operating-review-xlsx.skill.md)를 추가해 HTML 전략 브리프와 Excel 운영 리뷰 워크북 생성 진입점을 바로 제공하도록 했습니다. +- 테스트로 [ArtifactRepairGuideServiceTests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/ArtifactRepairGuideServiceTests.cs)를 추가했고, [ExcelSkillDashboardSummaryTests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/ExcelSkillDashboardSummaryTests.cs), [HtmlSkillConsultingSectionsTests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/HtmlSkillConsultingSectionsTests.cs)를 확장해 새 archetype과 repair guide를 회귀 검증했습니다. +- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_doc_next6\\ -p:IntermediateOutputPath=obj\\verify_doc_next6\\` 경고 0 / 오류 0 +- 검증: `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "ArtifactQualityReviewServiceTests|ArtifactRepairGuideServiceTests|ExcelSkillDashboardSummaryTests|HtmlSkillConsultingSectionsTests|HtmlSkillPrintFrameTests|DocumentAssemblerStyleMapTests|DocumentAssemblerDocxFeaturesTests|DocumentAssemblerSemanticTests|PptxSkillGoldenDeckTests|DeckQualityReviewServiceTests" -p:OutputPath=bin\\verify_doc_next6_tests\\ -p:IntermediateOutputPath=obj\\verify_doc_next6_tests\\` 통과 17 diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 16f2029..2061619 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -929,3 +929,13 @@ UI ?붿옄???€洹쒕え 由ы뙥?좊쭅 ???꾪뿕 ?묒뾽 ??湲곕줉???덉쟾 - 테스트로 [HtmlSkillConsultingSectionsTests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/HtmlSkillConsultingSectionsTests.cs), [ExcelSkillDashboardSummaryTests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/ExcelSkillDashboardSummaryTests.cs), [ArtifactQualityReviewServiceTests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/ArtifactQualityReviewServiceTests.cs), [PptxSkillGoldenDeckTests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/PptxSkillGoldenDeckTests.cs)를 확장했습니다. - 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_doc_next5\\ -p:IntermediateOutputPath=obj\\verify_doc_next5\\` 경고 0 / 오류 0 - 검증: `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "ArtifactQualityReviewServiceTests|ExcelSkillDashboardSummaryTests|HtmlSkillConsultingSectionsTests|HtmlSkillPrintFrameTests|DeckQualityReviewServiceTests|PptxSkillGoldenDeckTests|PptxSkillAutoRepairTests|PptxSkillConsultingDeckTests" -p:OutputPath=bin\\verify_doc_next5_tests\\ -p:IntermediateOutputPath=obj\\verify_doc_next5_tests\\` 통과 14 + +업데이트: 2026-04-14 23:58 (KST) +- [ArtifactRepairGuideService.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/ArtifactRepairGuideService.cs)를 추가했습니다. 이 서비스는 [ArtifactQualityReviewService.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/ArtifactQualityReviewService.cs)가 반환한 HTML/XLSX/DOCX 품질 이슈를 읽어 `Repair guide:` 형태의 바로 실행 가능한 개선 가이드로 바꿉니다. +- [HtmlSkill.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/HtmlSkill.cs), [ExcelSkill.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/ExcelSkill.cs), [DocumentAssemblerTool.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/DocumentAssemblerTool.cs)는 이제 품질 점수 요약 뒤에 repair guide를 함께 반환합니다. 출력만 보는 사용자도 “무엇을 더 보완해야 하는지”를 바로 이해할 수 있게 정리한 변경입니다. +- [ExcelSkill.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/ExcelSkill.cs)는 `dashboard_tiles`, `variance_series`를 추가 지원합니다. `WriteDashboardSheet()` 경로는 decision summary, scorecards, KPI, trend dashboard, detail summaries 외에 dashboard tiles와 variance overview까지 함께 렌더링해 운영 리뷰형 workbook archetype을 더 명확히 만들었습니다. +- workbook 리뷰 강점 계산도 같이 넓혔습니다. [ArtifactQualityReviewService.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/ArtifactQualityReviewService.cs)의 summary/dashboard 신호 판정은 `dashboard_tiles`, `variance_series`가 들어온 workbook도 richer dashboard로 인식합니다. +- 목적형 번들 스킬을 추가했습니다. [strategy-brief-html.skill.md](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/skills/strategy-brief-html.skill.md)는 전략 브리프 HTML 생성용 진입점을 제공하고, [operating-review-xlsx.skill.md](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/skills/operating-review-xlsx.skill.md)는 Summary/Dashboard/Detail 구조의 운영 리뷰 workbook 생성 경로를 제공합니다. +- 테스트로 [ArtifactRepairGuideServiceTests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/ArtifactRepairGuideServiceTests.cs)를 추가했고, [ExcelSkillDashboardSummaryTests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/ExcelSkillDashboardSummaryTests.cs), [HtmlSkillConsultingSectionsTests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/HtmlSkillConsultingSectionsTests.cs)를 확장해 archetype과 repair guide를 함께 회귀 검증했습니다. +- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_doc_next6\\ -p:IntermediateOutputPath=obj\\verify_doc_next6\\` 경고 0 / 오류 0 +- 검증: `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "ArtifactQualityReviewServiceTests|ArtifactRepairGuideServiceTests|ExcelSkillDashboardSummaryTests|HtmlSkillConsultingSectionsTests|HtmlSkillPrintFrameTests|DocumentAssemblerStyleMapTests|DocumentAssemblerDocxFeaturesTests|DocumentAssemblerSemanticTests|PptxSkillGoldenDeckTests|DeckQualityReviewServiceTests" -p:OutputPath=bin\\verify_doc_next6_tests\\ -p:IntermediateOutputPath=obj\\verify_doc_next6_tests\\` 통과 17 diff --git a/src/AxCopilot.Tests/Services/ArtifactRepairGuideServiceTests.cs b/src/AxCopilot.Tests/Services/ArtifactRepairGuideServiceTests.cs new file mode 100644 index 0000000..d92b7e5 --- /dev/null +++ b/src/AxCopilot.Tests/Services/ArtifactRepairGuideServiceTests.cs @@ -0,0 +1,44 @@ +using AxCopilot.Services.Agent; +using FluentAssertions; +using Xunit; + +namespace AxCopilot.Tests.Services; + +public class ArtifactRepairGuideServiceTests +{ + [Fact] + public void BuildGuide_ForWorkbookIssues_ShouldReturnWorkbookActions() + { + var review = new ArtifactQualityReport( + "xlsx", + 68, + ["Includes summary sheet"], + [ + new ArtifactReviewIssue("Workbook could benefit from a dashboard sheet to summarize multi-sheet trends.", ArtifactReviewSeverity.Info), + new ArtifactReviewIssue("Summary sheet does not link to detail sheets.", ArtifactReviewSeverity.Warning) + ]); + + var guide = ArtifactRepairGuideService.BuildGuide(review); + + guide.Should().Contain("dashboard sheet"); + guide.Should().Contain("detail sheets"); + } + + [Fact] + public void BuildGuide_ForHtmlIssues_ShouldReturnHtmlActions() + { + var review = new ArtifactQualityReport( + "html", + 70, + ["Includes print-ready CSS"], + [ + new ArtifactReviewIssue("Print-ready business report would benefit from decision summary or evidence cards.", ArtifactReviewSeverity.Warning), + new ArtifactReviewIssue("Strategy brief would be stronger with a comparison or roadmap block.", ArtifactReviewSeverity.Info) + ]); + + var guide = ArtifactRepairGuideService.BuildGuide(review); + + guide.Should().Contain("decision summary"); + guide.Should().Contain("comparison or roadmap"); + } +} diff --git a/src/AxCopilot.Tests/Services/ExcelSkillDashboardSummaryTests.cs b/src/AxCopilot.Tests/Services/ExcelSkillDashboardSummaryTests.cs index 198b076..f503704 100644 --- a/src/AxCopilot.Tests/Services/ExcelSkillDashboardSummaryTests.cs +++ b/src/AxCopilot.Tests/Services/ExcelSkillDashboardSummaryTests.cs @@ -40,12 +40,18 @@ public class ExcelSkillDashboardSummaryTests "scorecards": [ { "label": "Run-rate", "value": "96%", "status": "On Track", "note": "Ahead of plan" } ], + "dashboard_tiles": [ + { "label": "Decision status", "value": "Ready", "status": "Green", "note": "Funding ask aligned" } + ], "kpis": [ { "label": "Margin", "value": "18%", "trend": "Q/Q", "note": "Recovered" } ], "trend_series": [ { "label": "Revenue", "current": "120", "target": "130", "delta": "-10", "status": "Watch" } ], + "variance_series": [ + { "label": "Opex", "actual": "84", "target": "80", "variance": "+4", "status": "Watch" } + ], "sheet_summaries": [ { "sheet": "Revenue", "status": "Watch", "summary": "SMB margin pressure", "owner": "Sales Ops" } ], @@ -66,6 +72,7 @@ public class ExcelSkillDashboardSummaryTests result.Success.Should().BeTrue(); result.Output.Should().Contain("Quality score"); + result.Output.Should().Contain("Repair guide:"); using var doc = SpreadsheetDocument.Open(Path.Combine(workDir, "dashboard-review.xlsx"), false); var workbookPart = doc.WorkbookPart!; @@ -99,6 +106,10 @@ public class ExcelSkillDashboardSummaryTests dashboardTexts.Should().Contain("Open: Revenue"); dashboardTexts.Should().Contain("Key KPIs"); dashboardTexts.Should().Contain("Margin"); + dashboardTexts.Should().Contain("Dashboard Tiles"); + dashboardTexts.Should().Contain("Decision status"); + dashboardTexts.Should().Contain("Variance Overview"); + dashboardTexts.Should().Contain("Opex"); } finally { diff --git a/src/AxCopilot.Tests/Services/HtmlSkillConsultingSectionsTests.cs b/src/AxCopilot.Tests/Services/HtmlSkillConsultingSectionsTests.cs index bebe32e..4718280 100644 --- a/src/AxCopilot.Tests/Services/HtmlSkillConsultingSectionsTests.cs +++ b/src/AxCopilot.Tests/Services/HtmlSkillConsultingSectionsTests.cs @@ -95,6 +95,7 @@ public class HtmlSkillConsultingSectionsTests var result = await tool.ExecuteAsync(args, context, CancellationToken.None); result.Success.Should().BeTrue(); + result.Output.Should().Contain("Repair guide:"); var html = File.ReadAllText(Path.Combine(workDir, "consulting.html")); html.Should().Contain("comparison-grid"); html.Should().Contain("roadmap-block"); diff --git a/src/AxCopilot/Services/Agent/ArtifactRepairGuideService.cs b/src/AxCopilot/Services/Agent/ArtifactRepairGuideService.cs new file mode 100644 index 0000000..484fa0f --- /dev/null +++ b/src/AxCopilot/Services/Agent/ArtifactRepairGuideService.cs @@ -0,0 +1,83 @@ +namespace AxCopilot.Services.Agent; + +public static class ArtifactRepairGuideService +{ + public static string BuildGuide(ArtifactQualityReport review) + { + if (review.Issues.Count == 0) + return "Repair guide: none"; + + var actions = new List(); + + foreach (var issue in review.Issues) + { + var action = review.ArtifactType switch + { + "html" => BuildHtmlAction(issue.Message), + "xlsx" => BuildWorkbookAction(issue.Message), + "docx" => BuildDocumentAction(issue.Message), + _ => null + }; + + if (!string.IsNullOrWhiteSpace(action) && !actions.Contains(action, StringComparer.OrdinalIgnoreCase)) + actions.Add(action); + + if (actions.Count >= 3) + break; + } + + if (actions.Count == 0) + return "Repair guide: review low-signal issues and tighten structure before export"; + + return "Repair guide: " + string.Join(" | ", actions); + } + + private static string? BuildHtmlAction(string message) + { + if (message.Contains("decision summary or evidence cards", StringComparison.OrdinalIgnoreCase)) + return "Add a decision summary and evidence cards near the recommendation section"; + if (message.Contains("cover page", StringComparison.OrdinalIgnoreCase)) + return "Add a cover page for print-ready or board-facing reports"; + if (message.Contains("comparison or roadmap", StringComparison.OrdinalIgnoreCase)) + return "Add comparison or roadmap blocks to make options and sequencing explicit"; + if (message.Contains("supporting paragraphs", StringComparison.OrdinalIgnoreCase)) + return "Expand the core sections with supporting paragraphs and business evidence"; + if (message.Contains("Structured visual blocks are limited", StringComparison.OrdinalIgnoreCase)) + return "Use comparison, roadmap, matrix, KPI, or evidence blocks instead of plain text only"; + if (message.Contains("Executive summary", StringComparison.OrdinalIgnoreCase)) + return "Add an Executive Summary section near the top of the report"; + return null; + } + + private static string? BuildWorkbookAction(string message) + { + if (message.Contains("dashboard sheet", StringComparison.OrdinalIgnoreCase)) + return "Add a dashboard sheet with KPI tiles, trends, and links to detail sheets"; + if (message.Contains("Summary sheet could better surface", StringComparison.OrdinalIgnoreCase)) + return "Promote KPIs, decisions, and highlights into the summary or dashboard sheet"; + if (message.Contains("data validation", StringComparison.OrdinalIgnoreCase)) + return "Add data validation rules for editable status, owner, or category columns"; + if (message.Contains("Conditional formatting", StringComparison.OrdinalIgnoreCase)) + return "Add conditional formatting to flag priority items, variances, or risks"; + if (message.Contains("more formulas or rollups", StringComparison.OrdinalIgnoreCase)) + return "Add rollup formulas or summary calculations to turn detail data into insights"; + if (message.Contains("Summary sheet does not link", StringComparison.OrdinalIgnoreCase)) + return "Link the summary/dashboard sheet to each detail sheet for faster navigation"; + return null; + } + + private static string? BuildDocumentAction(string message) + { + if (message.Contains("Executive Summary", StringComparison.OrdinalIgnoreCase)) + return "Add an Executive Summary section at the start of the document"; + if (message.Contains("Recommendation", StringComparison.OrdinalIgnoreCase)) + return "Add a recommendation or next-step section with a clear decision ask"; + if (message.Contains("Appendix", StringComparison.OrdinalIgnoreCase)) + return "Add an appendix or reference section for longer documents"; + if (message.Contains("mostly plain paragraphs", StringComparison.OrdinalIgnoreCase)) + return "Introduce tables, lists, or callout blocks to break up dense prose"; + if (message.Contains("too short", StringComparison.OrdinalIgnoreCase)) + return "Deepen the supporting analysis before export"; + return null; + } +} diff --git a/src/AxCopilot/Services/Agent/DocumentAssemblerTool.cs b/src/AxCopilot/Services/Agent/DocumentAssemblerTool.cs index d631b4c..034b408 100644 --- a/src/AxCopilot/Services/Agent/DocumentAssemblerTool.cs +++ b/src/AxCopilot/Services/Agent/DocumentAssemblerTool.cs @@ -263,7 +263,7 @@ public class DocumentAssemblerTool : IAgentTool var issues = ValidateBasic(sb.ToString()); var review = ArtifactQualityReviewService.ReviewHtml(title, sb.ToString(), !string.IsNullOrWhiteSpace(coverSubtitle), toc, printReady: true); - var reviewSummary = $" HTML 품질 리뷰: {review.Score}/100 | 강점 {review.Strengths.Count} | 이슈 {review.Issues.Count}"; + var reviewSummary = $" HTML 품질 리뷰: {review.Score}/100 | 강점 {review.Strengths.Count} | 이슈 {review.Issues.Count} | {ArtifactRepairGuideService.BuildGuide(review)}"; return issues.Count > 0 ? $"{reviewSummary} | 기본 검토 이슈 {issues.Count}건: {string.Join("; ", issues)}" : reviewSummary; @@ -546,7 +546,7 @@ public class DocumentAssemblerTool : IAgentTool headings.Any(h => ArtifactQualityReviewService.ContainsBusinessKeyword(h, "recommendation", "proposal", "next step", "action", "권고", "실행")), headings.Any(h => ArtifactQualityReviewService.ContainsBusinessKeyword(h, "appendix", "reference", "supplement", "부록", "참고")))); - return $" DOCX 품질 리뷰: {review.Score}/100 | 강점 {review.Strengths.Count} | 이슈 {review.Issues.Count}"; + return $" DOCX 품질 리뷰: {review.Score}/100 | 강점 {review.Strengths.Count} | 이슈 {review.Issues.Count} | {ArtifactRepairGuideService.BuildGuide(review)}"; void AppendStructuredContent(string rawContent) { diff --git a/src/AxCopilot/Services/Agent/ExcelSkill.cs b/src/AxCopilot/Services/Agent/ExcelSkill.cs index 4976a27..f2c57d8 100644 --- a/src/AxCopilot/Services/Agent/ExcelSkill.cs +++ b/src/AxCopilot/Services/Agent/ExcelSkill.cs @@ -223,6 +223,7 @@ public class ExcelSkill : IAgentTool false, false)); features += $"\n{review.ToToolSummary()}"; + features += $"\n{ArtifactRepairGuideService.BuildGuide(review)}"; return ToolResult.Ok( $"Excel 파일 생성 완료: {fullPath}\n시트: {sheetName}, 열: {colCount}, 행: {rowCount}{features}", @@ -329,10 +330,11 @@ public class ExcelSkill : IAgentTool hasDashboardSheet, HasSummaryItems(summarySheet, "highlights"), HasSummaryItems(summarySheet, "actions"), - HasSummaryItems(summarySheet, "scorecards") || HasSummaryItems(summarySheet, "cards") || HasSummaryItems(summarySheet, "kpis") || HasSummaryItems(summarySheet, "trend_series"), + HasSummaryItems(summarySheet, "scorecards") || HasSummaryItems(summarySheet, "cards") || HasSummaryItems(summarySheet, "kpis") || HasSummaryItems(summarySheet, "trend_series") || HasSummaryItems(summarySheet, "dashboard_tiles") || HasSummaryItems(summarySheet, "variance_series"), HasStructuredSummaryContent(summarySheet, "decision_summary"), HasSummaryItems(summarySheet, "sheet_summaries"))); features += $"\n{review.ToToolSummary()}"; + features += $"\n{ArtifactRepairGuideService.BuildGuide(review)}"; return ToolResult.Ok( $"Excel ?뚯씪 ?앹꽦 ?꾨즺: {fullPath}\n?쒗듃: {summaryName}, {sheetName}, ?? {colCount}, ?? {rowCount}{features} [?붿빟 ?쒗듃]", @@ -473,11 +475,11 @@ public class ExcelSkill : IAgentTool hasDashboardSheet, HasSummaryItems(summarySheet, "highlights"), HasSummaryItems(summarySheet, "actions"), - HasSummaryItems(summarySheet, "scorecards") || HasSummaryItems(summarySheet, "cards") || HasSummaryItems(summarySheet, "kpis") || HasSummaryItems(summarySheet, "trend_series"), + HasSummaryItems(summarySheet, "scorecards") || HasSummaryItems(summarySheet, "cards") || HasSummaryItems(summarySheet, "kpis") || HasSummaryItems(summarySheet, "trend_series") || HasSummaryItems(summarySheet, "dashboard_tiles") || HasSummaryItems(summarySheet, "variance_series"), HasStructuredSummaryContent(summarySheet, "decision_summary"), HasSummaryItems(summarySheet, "sheet_summaries"))); return ToolResult.Ok( - $"Excel 파일 생성 완료: {fullPath}\n시트: {totalSheets}개, 총 데이터 행: {totalRows}\n{review.ToToolSummary()}", + $"Excel 파일 생성 완료: {fullPath}\n시트: {totalSheets}개, 총 데이터 행: {totalRows}\n{review.ToToolSummary()}\n{ArtifactRepairGuideService.BuildGuide(review)}", fullPath); } @@ -616,8 +618,10 @@ public class ExcelSkill : IAgentTool rowIndex++; AppendDecisionSummarySection(summarySheet, sheetData, merges, ref rowIndex); + AppendDashboardTileSection(summarySheet, sheetData, ref rowIndex); AppendScorecardSection(summarySheet, sheetData, ref rowIndex); AppendTrendSection(summarySheet, sheetData, ref rowIndex); + AppendVarianceSection(summarySheet, sheetData, ref rowIndex); AppendKpiSection(summarySheet, sheetData, merges, ref rowIndex); AppendSheetSummarySection(summarySheet, sheetData, ref rowIndex); AppendSummaryTextSection(summarySheet, "highlights", "Key Highlights", sheetData, merges, ref rowIndex); @@ -729,6 +733,36 @@ public class ExcelSkill : IAgentTool rowIndex++; } + private static void AppendDashboardTileSection(JsonElement summarySheet, SheetData sheetData, ref uint rowIndex) + { + if (!summarySheet.SafeTryGetProperty("dashboard_tiles", out var tiles) + || tiles.ValueKind != JsonValueKind.Array + || tiles.GetArrayLength() == 0) + return; + + var headerRow = new Row { RowIndex = rowIndex++ }; + headerRow.Append(CreateSummaryCell("A", headerRow.RowIndex!.Value, "Dashboard Tiles", 1)); + headerRow.Append(CreateSummaryCell("B", headerRow.RowIndex!.Value, "Value", 1)); + headerRow.Append(CreateSummaryCell("C", headerRow.RowIndex!.Value, "Status", 1)); + headerRow.Append(CreateSummaryCell("D", headerRow.RowIndex!.Value, "Note", 1)); + sheetData.Append(headerRow); + + var tileIndex = 0; + foreach (var tile in tiles.EnumerateArray()) + { + var stripeStyle = tileIndex % 2 == 0 ? (uint)0 : (uint)2; + var row = new Row { RowIndex = rowIndex++ }; + row.Append(CreateSummaryCell("A", row.RowIndex!.Value, tile.SafeTryGetProperty("label", out var labelEl) ? labelEl.SafeGetString() ?? string.Empty : string.Empty, 1)); + row.Append(CreateSummaryCell("B", row.RowIndex!.Value, tile.SafeTryGetProperty("value", out var valueEl) ? valueEl.SafeGetString() ?? string.Empty : string.Empty, 3)); + row.Append(CreateSummaryCell("C", row.RowIndex!.Value, tile.SafeTryGetProperty("status", out var statusEl) ? statusEl.SafeGetString() ?? string.Empty : string.Empty, stripeStyle)); + row.Append(CreateSummaryCell("D", row.RowIndex!.Value, tile.SafeTryGetProperty("note", out var noteEl) ? noteEl.SafeGetString() ?? string.Empty : string.Empty, stripeStyle)); + sheetData.Append(row); + tileIndex++; + } + + rowIndex++; + } + private static void AppendSheetSummarySection(JsonElement summarySheet, SheetData sheetData, ref uint rowIndex) { if (!summarySheet.SafeTryGetProperty("sheet_summaries", out var sheetSummaries) @@ -791,6 +825,38 @@ public class ExcelSkill : IAgentTool rowIndex++; } + private static void AppendVarianceSection(JsonElement summarySheet, SheetData sheetData, ref uint rowIndex) + { + if (!summarySheet.SafeTryGetProperty("variance_series", out var varianceSeries) + || varianceSeries.ValueKind != JsonValueKind.Array + || varianceSeries.GetArrayLength() == 0) + return; + + var headerRow = new Row { RowIndex = rowIndex++ }; + headerRow.Append(CreateSummaryCell("A", headerRow.RowIndex!.Value, "Variance Overview", 1)); + headerRow.Append(CreateSummaryCell("B", headerRow.RowIndex!.Value, "Actual", 1)); + headerRow.Append(CreateSummaryCell("C", headerRow.RowIndex!.Value, "Target", 1)); + headerRow.Append(CreateSummaryCell("D", headerRow.RowIndex!.Value, "Variance", 1)); + headerRow.Append(CreateSummaryCell("E", headerRow.RowIndex!.Value, "Status", 1)); + sheetData.Append(headerRow); + + var index = 0; + foreach (var item in varianceSeries.EnumerateArray()) + { + var stripeStyle = index % 2 == 0 ? (uint)0 : (uint)2; + var row = new Row { RowIndex = rowIndex++ }; + row.Append(CreateSummaryCell("A", row.RowIndex!.Value, item.SafeTryGetProperty("label", out var labelEl) ? labelEl.SafeGetString() ?? string.Empty : string.Empty, 1)); + row.Append(CreateSummaryCell("B", row.RowIndex!.Value, item.SafeTryGetProperty("actual", out var actualEl) ? actualEl.SafeGetString() ?? actualEl.ToString() : string.Empty, 3)); + row.Append(CreateSummaryCell("C", row.RowIndex!.Value, item.SafeTryGetProperty("target", out var targetEl) ? targetEl.SafeGetString() ?? targetEl.ToString() : string.Empty, stripeStyle)); + row.Append(CreateSummaryCell("D", row.RowIndex!.Value, item.SafeTryGetProperty("variance", out var varianceEl) ? varianceEl.SafeGetString() ?? varianceEl.ToString() : string.Empty, stripeStyle)); + row.Append(CreateSummaryCell("E", row.RowIndex!.Value, item.SafeTryGetProperty("status", out var statusEl) ? statusEl.SafeGetString() ?? string.Empty : string.Empty, stripeStyle)); + sheetData.Append(row); + index++; + } + + rowIndex++; + } + private static void AppendKpiSection(JsonElement summarySheet, SheetData sheetData, MergeCells merges, ref uint rowIndex) { if (!summarySheet.SafeTryGetProperty("kpis", out var kpis) || kpis.ValueKind != JsonValueKind.Array || kpis.GetArrayLength() == 0) diff --git a/src/AxCopilot/Services/Agent/HtmlSkill.cs b/src/AxCopilot/Services/Agent/HtmlSkill.cs index 76beb9f..ba83970 100644 --- a/src/AxCopilot/Services/Agent/HtmlSkill.cs +++ b/src/AxCopilot/Services/Agent/HtmlSkill.cs @@ -309,6 +309,7 @@ public class HtmlSkill : IAgentTool usePrint, !string.IsNullOrWhiteSpace(printHeader) || !string.IsNullOrWhiteSpace(printFooter)); featureStr += $"\n{review.ToToolSummary()}"; + featureStr += $"\n{ArtifactRepairGuideService.BuildGuide(review)}"; return ToolResult.Ok( $"HTML 문서 생성 완료: {fullPath} (디자인: {mood}{featureStr})", diff --git a/src/AxCopilot/skills/operating-review-xlsx.skill.md b/src/AxCopilot/skills/operating-review-xlsx.skill.md new file mode 100644 index 0000000..f2d8c8d --- /dev/null +++ b/src/AxCopilot/skills/operating-review-xlsx.skill.md @@ -0,0 +1,26 @@ +--- +name: operating-review-xlsx +label: 운영 리뷰 워크북 +description: summary, dashboard, detail 시트를 갖춘 운영 리뷰용 Excel 워크북을 생성합니다. +icon: \uE9D2 +when_to_use: 월간 운영 리뷰, KPI 점검, variance 분석, 부서별 상태 추적이 필요한 Excel 워크북이 필요할 때 +argument-hint: <운영 리뷰 주제와 핵심 KPI> +allowed-tools: + - folder_map + - file_read + - document_plan + - data_pivot + - excel_create +tabs: cowork +--- + +운영 리뷰용 Excel 워크북을 작성하세요. + +작성 지침: +- `document_plan`으로 먼저 `Summary -> Dashboard -> Detail` 구조를 잡고, 필요하면 `data_pivot`으로 원본 데이터를 정리한 뒤 `excel_create`를 호출하세요. +- summary sheet에는 decision summary, highlights, actions를 포함하고 dashboard sheet에는 KPI, dashboard tiles, trend/variance overview를 포함하세요. +- detail sheet는 영역별로 나누고 summary/dashboard에서 각 시트로 바로 이동할 수 있도록 구성하세요. +- editable 컬럼이 있으면 data validation을 추가하고, 우선순위/편차/리스크가 보이는 영역에는 conditional formatting을 사용하세요. +- 결과는 단순 표가 아니라 의사결정과 운영 점검이 가능한 workbook이 되도록 구성하세요. + +결과물은 작업 폴더에 저장하고, 시트 구성과 핵심 지표를 함께 요약하세요. diff --git a/src/AxCopilot/skills/strategy-brief-html.skill.md b/src/AxCopilot/skills/strategy-brief-html.skill.md new file mode 100644 index 0000000..cc295e4 --- /dev/null +++ b/src/AxCopilot/skills/strategy-brief-html.skill.md @@ -0,0 +1,25 @@ +--- +name: strategy-brief-html +label: HTML 전략 브리프 +description: 전략 질문, 핵심 가설, 시사점, 의사결정 항목을 담은 전략 브리프 HTML 문서를 생성합니다. +icon: \uE81E +when_to_use: 경영진 검토용 전략 브리프, 방향성 정렬 문서, 옵션 비교가 필요한 HTML 전략 문서가 필요할 때 +argument-hint: <전략 질문과 핵심 가설> +allowed-tools: + - folder_map + - file_read + - document_plan + - html_create +tabs: cowork +--- + +HTML 전략 브리프를 작성하세요. + +작성 지침: +- `html_create`를 우선 사용하고 `cover`, `toc`, `print`, `sections`를 적극 활용하세요. +- 문서는 `Executive Summary -> Strategic Question -> Core Thesis -> Implications -> Decisions -> Roadmap -> Appendix` 흐름을 기본으로 잡으세요. +- `strategy_brief`, `comparison`, `roadmap`, `evidence_cards`, `decision_summary` 블록을 상황에 맞게 조합하세요. +- 단순 개요보다 전략 질문, 판단 근거, 선택지, 정렬이 필요한 의사결정을 명확히 드러내세요. +- print-ready 문서로 바로 공유할 수 있도록 cover와 print frame을 포함하는 방향을 우선 검토하세요. + +결과물은 작업 폴더에 저장하고, 문서 구조와 핵심 의사결정 포인트를 함께 요약하세요.