oh-my-knowledge 0.0.1 → 0.19.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 (216) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +600 -322
  3. package/README.zh.md +724 -0
  4. package/dist/src/analysis/coverage-analyzer.d.ts +57 -0
  5. package/dist/src/analysis/coverage-analyzer.d.ts.map +1 -0
  6. package/dist/src/analysis/coverage-analyzer.js +262 -0
  7. package/dist/src/analysis/coverage-analyzer.js.map +1 -0
  8. package/dist/src/analysis/gap-analyzer.d.ts +114 -0
  9. package/dist/src/analysis/gap-analyzer.d.ts.map +1 -0
  10. package/dist/src/analysis/gap-analyzer.js +439 -0
  11. package/dist/src/analysis/gap-analyzer.js.map +1 -0
  12. package/dist/src/analysis/hedging-classifier.d.ts +34 -0
  13. package/dist/src/analysis/hedging-classifier.d.ts.map +1 -0
  14. package/dist/src/analysis/hedging-classifier.js +144 -0
  15. package/dist/src/analysis/hedging-classifier.js.map +1 -0
  16. package/dist/src/analysis/report-diagnostics.d.ts +9 -0
  17. package/dist/src/analysis/report-diagnostics.d.ts.map +1 -0
  18. package/dist/src/analysis/report-diagnostics.js +631 -0
  19. package/dist/src/analysis/report-diagnostics.js.map +1 -0
  20. package/dist/src/authoring/evolver.d.ts +64 -0
  21. package/dist/src/authoring/evolver.d.ts.map +1 -0
  22. package/dist/src/authoring/evolver.js +275 -0
  23. package/dist/src/authoring/evolver.js.map +1 -0
  24. package/dist/src/authoring/generator.d.ts +13 -0
  25. package/dist/src/authoring/generator.d.ts.map +1 -0
  26. package/dist/src/authoring/generator.js +60 -0
  27. package/dist/src/authoring/generator.js.map +1 -0
  28. package/dist/src/cli.d.ts +3 -0
  29. package/dist/src/cli.d.ts.map +1 -0
  30. package/dist/src/cli.js +1012 -0
  31. package/dist/src/cli.js.map +1 -0
  32. package/dist/src/eval-core/cache.d.ts +11 -0
  33. package/dist/src/eval-core/cache.d.ts.map +1 -0
  34. package/dist/src/eval-core/cache.js +53 -0
  35. package/dist/src/eval-core/cache.js.map +1 -0
  36. package/dist/src/eval-core/ci-gates.d.ts +17 -0
  37. package/dist/src/eval-core/ci-gates.d.ts.map +1 -0
  38. package/dist/src/eval-core/ci-gates.js +42 -0
  39. package/dist/src/eval-core/ci-gates.js.map +1 -0
  40. package/dist/src/eval-core/dependency-checker.d.ts +37 -0
  41. package/dist/src/eval-core/dependency-checker.d.ts.map +1 -0
  42. package/dist/src/eval-core/dependency-checker.js +280 -0
  43. package/dist/src/eval-core/dependency-checker.js.map +1 -0
  44. package/dist/src/eval-core/evaluation-execution.d.ts +26 -0
  45. package/dist/src/eval-core/evaluation-execution.d.ts.map +1 -0
  46. package/dist/src/eval-core/evaluation-execution.js +196 -0
  47. package/dist/src/eval-core/evaluation-execution.js.map +1 -0
  48. package/dist/src/eval-core/evaluation-job.d.ts +50 -0
  49. package/dist/src/eval-core/evaluation-job.d.ts.map +1 -0
  50. package/dist/src/eval-core/evaluation-job.js +114 -0
  51. package/dist/src/eval-core/evaluation-job.js.map +1 -0
  52. package/dist/src/eval-core/evaluation-reporting.d.ts +28 -0
  53. package/dist/src/eval-core/evaluation-reporting.d.ts.map +1 -0
  54. package/dist/src/eval-core/evaluation-reporting.js +123 -0
  55. package/dist/src/eval-core/evaluation-reporting.js.map +1 -0
  56. package/dist/src/eval-core/execution-strategy.d.ts +11 -0
  57. package/dist/src/eval-core/execution-strategy.d.ts.map +1 -0
  58. package/dist/src/eval-core/execution-strategy.js +121 -0
  59. package/dist/src/eval-core/execution-strategy.js.map +1 -0
  60. package/dist/src/eval-core/fact-checker.d.ts +25 -0
  61. package/dist/src/eval-core/fact-checker.d.ts.map +1 -0
  62. package/dist/src/eval-core/fact-checker.js +66 -0
  63. package/dist/src/eval-core/fact-checker.js.map +1 -0
  64. package/dist/src/eval-core/schema.d.ts +30 -0
  65. package/dist/src/eval-core/schema.d.ts.map +1 -0
  66. package/dist/src/eval-core/schema.js +195 -0
  67. package/dist/src/eval-core/schema.js.map +1 -0
  68. package/dist/src/eval-core/statistics.d.ts +86 -0
  69. package/dist/src/eval-core/statistics.d.ts.map +1 -0
  70. package/dist/src/eval-core/statistics.js +210 -0
  71. package/dist/src/eval-core/statistics.js.map +1 -0
  72. package/dist/src/eval-core/task-planner.d.ts +4 -0
  73. package/dist/src/eval-core/task-planner.d.ts.map +1 -0
  74. package/dist/src/eval-core/task-planner.js +33 -0
  75. package/dist/src/eval-core/task-planner.js.map +1 -0
  76. package/dist/src/eval-workflows/each-evaluation-workflow.d.ts +137 -0
  77. package/dist/src/eval-workflows/each-evaluation-workflow.d.ts.map +1 -0
  78. package/dist/src/eval-workflows/each-evaluation-workflow.js +174 -0
  79. package/dist/src/eval-workflows/each-evaluation-workflow.js.map +1 -0
  80. package/dist/src/eval-workflows/evaluation-pipeline.d.ts +42 -0
  81. package/dist/src/eval-workflows/evaluation-pipeline.d.ts.map +1 -0
  82. package/dist/src/eval-workflows/evaluation-pipeline.js +218 -0
  83. package/dist/src/eval-workflows/evaluation-pipeline.js.map +1 -0
  84. package/dist/src/eval-workflows/evaluation-preparation.d.ts +64 -0
  85. package/dist/src/eval-workflows/evaluation-preparation.d.ts.map +1 -0
  86. package/dist/src/eval-workflows/evaluation-preparation.js +90 -0
  87. package/dist/src/eval-workflows/evaluation-preparation.js.map +1 -0
  88. package/dist/src/eval-workflows/run-evaluation.d.ts +111 -0
  89. package/dist/src/eval-workflows/run-evaluation.d.ts.map +1 -0
  90. package/dist/src/eval-workflows/run-evaluation.js +272 -0
  91. package/dist/src/eval-workflows/run-evaluation.js.map +1 -0
  92. package/dist/src/executors/anthropic-api.d.ts +3 -0
  93. package/dist/src/executors/anthropic-api.d.ts.map +1 -0
  94. package/dist/src/executors/anthropic-api.js +43 -0
  95. package/dist/src/executors/anthropic-api.js.map +1 -0
  96. package/dist/src/executors/claude-cli.d.ts +3 -0
  97. package/dist/src/executors/claude-cli.d.ts.map +1 -0
  98. package/dist/src/executors/claude-cli.js +103 -0
  99. package/dist/src/executors/claude-cli.js.map +1 -0
  100. package/dist/src/executors/claude-sdk-trace.d.ts +10 -0
  101. package/dist/src/executors/claude-sdk-trace.d.ts.map +1 -0
  102. package/dist/src/executors/claude-sdk-trace.js +100 -0
  103. package/dist/src/executors/claude-sdk-trace.js.map +1 -0
  104. package/dist/src/executors/claude-sdk.d.ts +3 -0
  105. package/dist/src/executors/claude-sdk.d.ts.map +1 -0
  106. package/dist/src/executors/claude-sdk.js +160 -0
  107. package/dist/src/executors/claude-sdk.js.map +1 -0
  108. package/dist/src/executors/gemini.d.ts +3 -0
  109. package/dist/src/executors/gemini.d.ts.map +1 -0
  110. package/dist/src/executors/gemini.js +78 -0
  111. package/dist/src/executors/gemini.js.map +1 -0
  112. package/dist/src/executors/index.d.ts +7 -0
  113. package/dist/src/executors/index.d.ts.map +1 -0
  114. package/dist/src/executors/index.js +22 -0
  115. package/dist/src/executors/index.js.map +1 -0
  116. package/dist/src/executors/openai-api.d.ts +3 -0
  117. package/dist/src/executors/openai-api.d.ts.map +1 -0
  118. package/dist/src/executors/openai-api.js +40 -0
  119. package/dist/src/executors/openai-api.js.map +1 -0
  120. package/dist/src/executors/openai-cli.d.ts +3 -0
  121. package/dist/src/executors/openai-cli.d.ts.map +1 -0
  122. package/dist/src/executors/openai-cli.js +60 -0
  123. package/dist/src/executors/openai-cli.js.map +1 -0
  124. package/dist/src/executors/script.d.ts +3 -0
  125. package/dist/src/executors/script.d.ts.map +1 -0
  126. package/dist/src/executors/script.js +63 -0
  127. package/dist/src/executors/script.js.map +1 -0
  128. package/dist/src/executors/shared.d.ts +117 -0
  129. package/dist/src/executors/shared.d.ts.map +1 -0
  130. package/dist/src/executors/shared.js +49 -0
  131. package/dist/src/executors/shared.js.map +1 -0
  132. package/dist/src/grading/assertions.d.ts +18 -0
  133. package/dist/src/grading/assertions.d.ts.map +1 -0
  134. package/dist/src/grading/assertions.js +239 -0
  135. package/dist/src/grading/assertions.js.map +1 -0
  136. package/dist/src/grading/index.d.ts +26 -0
  137. package/dist/src/grading/index.d.ts.map +1 -0
  138. package/dist/src/grading/index.js +98 -0
  139. package/dist/src/grading/index.js.map +1 -0
  140. package/dist/src/grading/judge.d.ts +13 -0
  141. package/dist/src/grading/judge.d.ts.map +1 -0
  142. package/dist/src/grading/judge.js +98 -0
  143. package/dist/src/grading/judge.js.map +1 -0
  144. package/dist/src/grading/layered-scores.d.ts +13 -0
  145. package/dist/src/grading/layered-scores.d.ts.map +1 -0
  146. package/dist/src/grading/layered-scores.js +62 -0
  147. package/dist/src/grading/layered-scores.js.map +1 -0
  148. package/dist/src/inputs/eval-config.d.ts +13 -0
  149. package/dist/src/inputs/eval-config.d.ts.map +1 -0
  150. package/dist/src/inputs/eval-config.js +136 -0
  151. package/dist/src/inputs/eval-config.js.map +1 -0
  152. package/dist/src/inputs/load-samples.d.ts +16 -0
  153. package/dist/src/inputs/load-samples.d.ts.map +1 -0
  154. package/dist/src/inputs/load-samples.js +51 -0
  155. package/dist/src/inputs/load-samples.js.map +1 -0
  156. package/dist/src/inputs/mcp-resolver.d.ts +50 -0
  157. package/dist/src/inputs/mcp-resolver.d.ts.map +1 -0
  158. package/dist/src/inputs/mcp-resolver.js +307 -0
  159. package/dist/src/inputs/mcp-resolver.js.map +1 -0
  160. package/dist/src/inputs/skill-loader.d.ts +18 -0
  161. package/dist/src/inputs/skill-loader.d.ts.map +1 -0
  162. package/dist/src/inputs/skill-loader.js +222 -0
  163. package/dist/src/inputs/skill-loader.js.map +1 -0
  164. package/dist/src/inputs/url-fetcher.d.ts +19 -0
  165. package/dist/src/inputs/url-fetcher.d.ts.map +1 -0
  166. package/dist/src/inputs/url-fetcher.js +241 -0
  167. package/dist/src/inputs/url-fetcher.js.map +1 -0
  168. package/dist/src/observability/skill-health-analyzer.d.ts +83 -0
  169. package/dist/src/observability/skill-health-analyzer.d.ts.map +1 -0
  170. package/dist/src/observability/skill-health-analyzer.js +238 -0
  171. package/dist/src/observability/skill-health-analyzer.js.map +1 -0
  172. package/dist/src/observability/trace-adapter.d.ts +75 -0
  173. package/dist/src/observability/trace-adapter.d.ts.map +1 -0
  174. package/dist/src/observability/trace-adapter.js +367 -0
  175. package/dist/src/observability/trace-adapter.js.map +1 -0
  176. package/dist/src/renderer/html-renderer.d.ts +9 -0
  177. package/dist/src/renderer/html-renderer.d.ts.map +1 -0
  178. package/dist/src/renderer/html-renderer.js +360 -0
  179. package/dist/src/renderer/html-renderer.js.map +1 -0
  180. package/dist/src/renderer/layout.d.ts +13 -0
  181. package/dist/src/renderer/layout.d.ts.map +1 -0
  182. package/dist/src/renderer/layout.js +582 -0
  183. package/dist/src/renderer/layout.js.map +1 -0
  184. package/dist/src/renderer/skill-health-renderer.d.ts +20 -0
  185. package/dist/src/renderer/skill-health-renderer.d.ts.map +1 -0
  186. package/dist/src/renderer/skill-health-renderer.js +253 -0
  187. package/dist/src/renderer/skill-health-renderer.js.map +1 -0
  188. package/dist/src/renderer/summary.d.ts +21 -0
  189. package/dist/src/renderer/summary.d.ts.map +1 -0
  190. package/dist/src/renderer/summary.js +1072 -0
  191. package/dist/src/renderer/summary.js.map +1 -0
  192. package/dist/src/renderer/table.d.ts +3 -0
  193. package/dist/src/renderer/table.d.ts.map +1 -0
  194. package/dist/src/renderer/table.js +134 -0
  195. package/dist/src/renderer/table.js.map +1 -0
  196. package/dist/src/renderer/trends.d.ts +6 -0
  197. package/dist/src/renderer/trends.d.ts.map +1 -0
  198. package/dist/src/renderer/trends.js +127 -0
  199. package/dist/src/renderer/trends.js.map +1 -0
  200. package/dist/src/server/job-store.d.ts +4 -0
  201. package/dist/src/server/job-store.d.ts.map +1 -0
  202. package/dist/src/server/job-store.js +68 -0
  203. package/dist/src/server/job-store.js.map +1 -0
  204. package/dist/src/server/report-server.d.ts +17 -0
  205. package/dist/src/server/report-server.d.ts.map +1 -0
  206. package/dist/src/server/report-server.js +591 -0
  207. package/dist/src/server/report-server.js.map +1 -0
  208. package/dist/src/server/report-store.d.ts +44 -0
  209. package/dist/src/server/report-store.d.ts.map +1 -0
  210. package/dist/src/server/report-store.js +190 -0
  211. package/dist/src/server/report-store.js.map +1 -0
  212. package/dist/src/types.d.ts +559 -0
  213. package/dist/src/types.d.ts.map +1 -0
  214. package/dist/src/types.js +2 -0
  215. package/dist/src/types.js.map +1 -0
  216. package/package.json +53 -5
@@ -0,0 +1,582 @@
1
+ export function e(text) {
2
+ return String(text)
3
+ .replaceAll('&', '&')
4
+ .replaceAll('<', '&lt;')
5
+ .replaceAll('>', '&gt;')
6
+ .replaceAll('"', '&quot;')
7
+ .replaceAll("'", '&#39;');
8
+ }
9
+ export function fmtNum(n, digits = 0) {
10
+ return Number(n || 0).toLocaleString('en-US', { maximumFractionDigits: digits });
11
+ }
12
+ export function fmtDuration(ms) {
13
+ const v = Number(ms || 0);
14
+ if (v < 1000)
15
+ return `${v}ms`;
16
+ if (v < 60000)
17
+ return `${(v / 1000).toFixed(1)}s`;
18
+ const min = Math.floor(v / 60000);
19
+ const sec = Math.round((v % 60000) / 1000);
20
+ return sec > 0 ? `${min}m${sec}s` : `${min}m`;
21
+ }
22
+ export function fmtCost(usd) {
23
+ return `$${Number(usd || 0).toFixed(4)}`;
24
+ }
25
+ export function fmtLocalTime(isoStr) {
26
+ const d = new Date(isoStr);
27
+ const pad = (n) => String(n).padStart(2, '0');
28
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
29
+ }
30
+ export function delta(a, b, lowerIsBetter = false) {
31
+ if (!a || !b || a === 0)
32
+ return '';
33
+ const pct = ((b - a) / a * 100).toFixed(1);
34
+ const better = lowerIsBetter ? b < a : b > a;
35
+ const color = better ? 'var(--green)' : b === a ? 'var(--text-muted)' : 'var(--red)';
36
+ const arrow = b > a ? '↑' : b < a ? '↓' : '→';
37
+ return `<span style="color:${color};font-size:11px;margin-left:4px">${arrow}${Math.abs(Number(pct))}%</span>`;
38
+ }
39
+ export const COLORS = ['var(--chart-1)', 'var(--chart-2)', 'var(--chart-3)', 'var(--chart-4)', 'var(--chart-5)', 'var(--chart-6)'];
40
+ export const I18N = {
41
+ zh: {
42
+ title: '评测报告',
43
+ subtitle: '知识载体评测',
44
+ noRuns: '暂无评测记录。运行 <code>omk bench run --control v1 --treatment v2</code> 开始。',
45
+ runId: '报告名称', variants: '实验分组', model: '模型', samples: '样本数',
46
+ score: '分数', cost: '成本', time: '时间',
47
+ deleteBtnText: '删除', deleteConfirm: '确定删除报告', deleteFail: '删除失败',
48
+ reportTitle: '评测报告', backToList: '← 返回列表',
49
+ judge: '评委', executor: '执行器', blindLabel: '盲测', revealBlind: '显示变体对应关系',
50
+ dimFact: '📋 事实', dimFactDesc: '输出的事实声明是否正确(规则可验证:关键词匹配、格式校验等断言)',
51
+ dimBehavior: '🛠️ 行为', dimBehaviorDesc: '执行过程是否合规(规则可验证:工具调用路径、轮次限制、成本约束等断言)',
52
+ dimJudge: '💬 LLM 评价', dimJudgeDesc: '请一个 LLM 当评委,读被测模型的输出内容,按预先写好的评分规则(英文 rubric)打 1-5 分。主观但能抓到规则断言判不了的"整体好不好"',
53
+ dimQuality: '📊 质量', dimQualityDesc: '事实 + 行为 + LLM 评价的等权平均(1-5 分)。UI 已拆出三层平铺展示,composite 字段仅保留在 JSON 数据层',
54
+ dimCost: '💰 成本', dimCostDesc: '基于 Token 消耗量和模型定价计算的 API 调用费用',
55
+ dimEfficiency: '⚡ 效率', dimEfficiencyDesc: 'Skill 从发送请求到模型返回完整响应的端到端耗时',
56
+ dimStability: '🛡️ 稳定性', dimStabilityDesc: '多次运行(--repeat ≥ 2)分数一致性的 CV 变异系数,单轮显示"—"',
57
+ compositeScore: '综合分数', scoreRange: '分数范围',
58
+ assertions: '断言', assertionsDesc: '规则检查得分:通过的断言权重占比映射到 1-5 分',
59
+ llmJudge: 'LLM 评委', llmJudgeDesc: '由评委模型按预先写好的评分规则(英文叫 rubric)打出的 1-5 分',
60
+ totalCost: '总成本', inputTokens: '输入', outputTokens: '输出',
61
+ totalTokens: '总计', tokPerReq: 'tokens/次', avgLatency: '平均延迟',
62
+ successRate: '完成率', success: '成功', errors: '失败',
63
+ tokenComparison: 'Tokens 对比', latencyComparison: '延迟对比',
64
+ avgTurns: '平均轮次', turnsPerReq: '轮/次', minScore: '最低',
65
+ autoAnalysis: '自动分析',
66
+ perSampleDetail: '逐样本详情', sample: '样本',
67
+ scoreCol: '分数', tokensCol: 'Tokens', msCol: '延迟(ms)',
68
+ eachOverview: '总览', eachSkill: 'Skill', eachBaseline: '无 Skill', eachWithSkill: '有 Skill', eachImprovement: '提升',
69
+ eachSkills: '个 Skill', eachSamples: '个样本',
70
+ agentLabel: 'Agent 评测',
71
+ skillLabel: 'Skill 评测',
72
+ promptLabel: 'Prompt 评测',
73
+ workflowLabel: 'Workflow 评测',
74
+ agentOverview: 'Agent 执行概览',
75
+ agentToolCalls: '工具调用',
76
+ agentToolSuccess: '工具成功率',
77
+ agentToolDist: '工具分布',
78
+ agentAvgTurns: '平均轮次',
79
+ agentAvgTools: '平均工具调用',
80
+ traceToggle: '执行轨迹',
81
+ traceAssistant: '助手',
82
+ traceTool: '工具',
83
+ traceFullOutput: '查看完整输出',
84
+ traceExecMs: '执行',
85
+ traceGradeMs: '评分',
86
+ traceTotalMs: '总计',
87
+ variantConfig: '实验配置',
88
+ variantConfigDesc: '先看清楚在比较什么,再看分数。本表展示每个 variant 背后的 artifact 和运行环境。',
89
+ variantType: '实验类型',
90
+ variantArtifactKind: '知识类型',
91
+ variantArtifactSource: '知识来源',
92
+ variantExecutionStrategy: '执行策略',
93
+ variantRuntimeContext: '运行环境',
94
+ // --- observability (skill health / trend / diff) ---
95
+ skillHealthTitle: 'Skill 健康度日报',
96
+ noAnalyses: '暂无 skill 健康度日报。运行 <code>omk analyze &lt;trace-dir&gt;</code> 生成。',
97
+ backToEvalReports: '← 评测报告',
98
+ backToAnalyses: '← Skill 健康度日报',
99
+ analysesCompareHint: '选两个报告的 from/to 单选框,点 Compare 生成 diff。',
100
+ analysesCompareBtn: '对比 →',
101
+ analysesFromLabel: 'from',
102
+ analysesToLabel: 'to',
103
+ analysesSessions: '会话',
104
+ analysesSegs: '段',
105
+ analysesSkills: '技能',
106
+ skillTrendHeading: 'Skill 趋势',
107
+ noTrendData: '暂无趋势数据。该 skill 尚未出现在任何分析报告里。',
108
+ trendNPoints: '个时间点',
109
+ trendEarliest: '最早',
110
+ trendLatest: '最新',
111
+ trendLegendGap: 'gap rate',
112
+ trendLegendWeighted: 'weighted gap',
113
+ trendLegendFailure: 'failure rate',
114
+ trendLegendCoverage: 'coverage',
115
+ trendColTimestamp: '时间',
116
+ trendColSegs: '段数',
117
+ trendColGap: 'Gap',
118
+ trendColWeighted: '加权',
119
+ trendColFailure: '失败率',
120
+ trendColCoverage: '覆盖',
121
+ trendColTokens: 'Tokens',
122
+ trendColDuration: '耗时',
123
+ skillDiffHeading: 'Skill 健康度对比',
124
+ diffSortHint: '按 gap 变化量排序;绿色=改善,红色=恶化',
125
+ diffTagRemoved: '已消失',
126
+ diffTagNew: '新增',
127
+ diffNavFrom: '起点',
128
+ diffNavTo: '终点',
129
+ diffColSkill: 'Skill',
130
+ diffColSegments: '段数',
131
+ diffColWeightedGap: '加权 Gap',
132
+ diffColFailureRate: '失败率',
133
+ diffColCoverage: '覆盖',
134
+ viewTrendLink: '查看趋势 →',
135
+ artifactHashLabel: '版本指纹',
136
+ artifactHashTooltip: 'skill 文件内容的 SHA-256 前 12 位(不含路径/时间/git),用于辨别报告对应哪一版 skill;同文件多次跑指纹不变,改一字节就变——防止"改动效果"和"随机波动"混淆',
137
+ switchLang: 'EN',
138
+ },
139
+ en: {
140
+ title: 'Evaluation Reports',
141
+ subtitle: 'Knowledge Artifact Evaluation',
142
+ noRuns: 'No evaluation runs yet. Run <code>omk bench run --control v1 --treatment v2</code> to start.',
143
+ runId: 'Report', variants: 'Variant', model: 'Model', samples: 'Samples',
144
+ score: 'Score', cost: 'Cost', time: 'Time',
145
+ deleteBtnText: 'Delete', deleteConfirm: 'Delete report', deleteFail: 'Delete failed',
146
+ reportTitle: 'Evaluation Report', backToList: '← Back to list',
147
+ judge: 'judge', executor: 'executor', blindLabel: 'BLIND', revealBlind: 'Reveal variant mapping',
148
+ dimFact: '📋 Fact', dimFactDesc: 'Are factual claims correct (rule-verified: keyword matching, schema checks, etc.)',
149
+ dimBehavior: '🛠️ Behavior', dimBehaviorDesc: 'Is execution compliant (rule-verified: tool paths, turn limits, cost constraints)',
150
+ dimJudge: '💬 LLM judge', dimJudgeDesc: 'A separate LLM acts as judge: reads the tested model output, scores 1-5 against a predefined rubric. Subjective, catches "overall feel" rule-based assertions miss',
151
+ dimQuality: '📊 Quality', dimQualityDesc: 'Equal-weight average of Fact + Behavior + LLM judge (1-5). UI now splits the three layers into separate columns; composite lives only in JSON data',
152
+ dimCost: '💰 Cost', dimCostDesc: 'API cost calculated from token usage and model pricing',
153
+ dimEfficiency: '⚡ Efficiency', dimEfficiencyDesc: 'End-to-end latency from sending request to receiving full response',
154
+ dimStability: '🛡️ Stability', dimStabilityDesc: 'How much the score swings across repeated runs. Needs `--repeat ≥ 2`; single-run shows "—" because stability cannot be measured from one run',
155
+ compositeScore: 'composite score', scoreRange: 'Range',
156
+ assertions: 'Assertions', assertionsDesc: 'Rule-based score: passed assertion weight ratio mapped to 1-5',
157
+ llmJudge: 'LLM Judge', llmJudgeDesc: 'Score (1-5) from the judge model based on a predefined rubric (scoring criteria)',
158
+ totalCost: 'total cost', inputTokens: 'Input', outputTokens: 'Output',
159
+ totalTokens: 'Total', tokPerReq: 'tokens/req', avgLatency: 'avg latency',
160
+ successRate: 'completion rate', success: 'Success', errors: 'Errors',
161
+ tokenComparison: 'Tokens Comparison', latencyComparison: 'Latency Comparison',
162
+ avgTurns: 'Avg Turns', turnsPerReq: 'turns/req', minScore: 'Min',
163
+ autoAnalysis: 'Auto Analysis',
164
+ perSampleDetail: 'Per-Sample Detail', sample: 'Sample',
165
+ scoreCol: 'Score', tokensCol: 'Tokens', msCol: 'ms',
166
+ eachOverview: 'Overview', eachSkill: 'Skill', eachBaseline: 'Baseline', eachWithSkill: 'With Skill', eachImprovement: 'Improvement',
167
+ eachSkills: ' skills', eachSamples: ' samples',
168
+ agentLabel: 'Agent Eval',
169
+ skillLabel: 'Skill Eval',
170
+ promptLabel: 'Prompt Eval',
171
+ workflowLabel: 'Workflow Eval',
172
+ agentOverview: 'Agent Execution Overview',
173
+ agentToolCalls: 'Tool Calls',
174
+ agentToolSuccess: 'Tool Success Rate',
175
+ agentToolDist: 'Tool Distribution',
176
+ agentAvgTurns: 'Avg Turns',
177
+ agentAvgTools: 'Avg Tool Calls',
178
+ traceToggle: 'Execution Trace',
179
+ traceAssistant: 'Assistant',
180
+ traceTool: 'Tool',
181
+ traceFullOutput: 'Full Output',
182
+ traceExecMs: 'Exec',
183
+ traceGradeMs: 'Grade',
184
+ traceTotalMs: 'Total',
185
+ variantConfig: 'Experiment Setup',
186
+ variantConfigDesc: 'Confirm what is being compared before reading the score. This table explains the artifact and runtime context behind each variant.',
187
+ variantType: 'Role',
188
+ variantArtifactKind: 'Artifact Kind',
189
+ variantArtifactSource: 'Source',
190
+ variantExecutionStrategy: 'Execution Strategy',
191
+ variantRuntimeContext: 'Runtime Context',
192
+ // --- observability (skill health / trend / diff) ---
193
+ skillHealthTitle: 'Skill Health Reports',
194
+ noAnalyses: 'No skill health reports yet. Run <code>omk analyze &lt;trace-dir&gt;</code> to generate.',
195
+ backToEvalReports: '← Eval reports',
196
+ backToAnalyses: '← Skill Health Reports',
197
+ analysesCompareHint: 'Pick from/to radios on two reports, then click Compare to generate a diff.',
198
+ analysesCompareBtn: 'Compare →',
199
+ analysesFromLabel: 'from',
200
+ analysesToLabel: 'to',
201
+ analysesSessions: 'sessions',
202
+ analysesSegs: 'segs',
203
+ analysesSkills: 'skills',
204
+ skillTrendHeading: 'Skill Trend',
205
+ noTrendData: 'No trend data. This skill has not appeared in any analysis report yet.',
206
+ trendNPoints: 'data points',
207
+ trendEarliest: 'earliest',
208
+ trendLatest: 'latest',
209
+ trendLegendGap: 'gap rate',
210
+ trendLegendWeighted: 'weighted gap',
211
+ trendLegendFailure: 'failure rate',
212
+ trendLegendCoverage: 'coverage',
213
+ trendColTimestamp: 'Timestamp',
214
+ trendColSegs: 'Segs',
215
+ trendColGap: 'Gap',
216
+ trendColWeighted: 'Weighted',
217
+ trendColFailure: 'Failure',
218
+ trendColCoverage: 'Coverage',
219
+ trendColTokens: 'Tokens',
220
+ trendColDuration: 'Duration',
221
+ skillDiffHeading: 'Skill Health Diff',
222
+ diffSortHint: 'Sorted by |Δgap|; green=improved, red=regressed',
223
+ diffTagRemoved: 'removed',
224
+ diffTagNew: 'new',
225
+ diffNavFrom: 'from',
226
+ diffNavTo: 'to',
227
+ diffColSkill: 'Skill',
228
+ diffColSegments: 'Segments',
229
+ diffColWeightedGap: 'Weighted gap',
230
+ diffColFailureRate: 'Failure rate',
231
+ diffColCoverage: 'Coverage',
232
+ viewTrendLink: 'trend →',
233
+ artifactHashLabel: 'Version fingerprint',
234
+ artifactHashTooltip: 'First 12 hex chars of SHA-256 over the skill file content (content-only: no path/time/git); identifies which version of the skill this report ran — same file = same fingerprint, any byte change = different fingerprint. Keeps "intentional change" separate from "random variance"',
235
+ switchLang: '中文',
236
+ },
237
+ };
238
+ export const DEFAULT_LANG = 'zh';
239
+ export function t(key, lang = DEFAULT_LANG) {
240
+ return I18N[lang]?.[key] || I18N.en[key] || key;
241
+ }
242
+ function globalKeyboardScript() {
243
+ return `
244
+ <script>
245
+ // Global modal helpers. openModal/closeModal manage focus so the close
246
+ // button becomes the first tab stop when a modal opens.
247
+ window.openModal = function(id) {
248
+ var modal = document.getElementById(id);
249
+ if (!modal) return;
250
+ modal.style.display = 'flex';
251
+ setTimeout(function() {
252
+ var closeBtn = modal.querySelector('.modal-close');
253
+ if (closeBtn) closeBtn.focus();
254
+ }, 30);
255
+ };
256
+ window.closeModal = function(id) {
257
+ var modal = document.getElementById(id);
258
+ if (!modal) return;
259
+ modal.style.display = 'none';
260
+ };
261
+ // Global ESC to close any open modal-overlay
262
+ document.addEventListener('keydown', function(e) {
263
+ if (e.key === 'Escape') {
264
+ document.querySelectorAll('.modal-overlay').forEach(function(m) {
265
+ if (m.style.display === 'flex') m.style.display = 'none';
266
+ });
267
+ }
268
+ });
269
+ </script>`;
270
+ }
271
+ function langToggleScript() {
272
+ return `
273
+ <script>
274
+ var I18N = ${JSON.stringify(I18N)};
275
+ function switchLang() {
276
+ var cur = document.documentElement.dataset.lang || '${DEFAULT_LANG}';
277
+ var next = cur === 'zh' ? 'en' : 'zh';
278
+ document.documentElement.dataset.lang = next;
279
+ document.documentElement.lang = next === 'zh' ? 'zh-CN' : 'en';
280
+ document.querySelectorAll('[data-i18n]').forEach(function(el) {
281
+ var key = el.dataset.i18n;
282
+ if (I18N[next][key]) {
283
+ if (el.tagName === 'INPUT') { el.placeholder = I18N[next][key]; }
284
+ else { el.innerHTML = I18N[next][key]; }
285
+ }
286
+ });
287
+ document.getElementById('lang-toggle').textContent = I18N[next].switchLang;
288
+ // 同步写入 URL ?lang= 和 localStorage,让刷新/跳转保持语言选择
289
+ try {
290
+ var url = new URL(window.location.href);
291
+ url.searchParams.set('lang', next);
292
+ window.history.replaceState(null, '', url.toString());
293
+ localStorage.setItem('omk-lang', next);
294
+ } catch (e) { /* ignore */ }
295
+ }
296
+ // 页面加载时,若 URL 无 lang 但 localStorage 有,跳转到带 lang 的 URL (仅一次)
297
+ (function() {
298
+ try {
299
+ var url = new URL(window.location.href);
300
+ if (!url.searchParams.get('lang')) {
301
+ var saved = localStorage.getItem('omk-lang');
302
+ if (saved && saved !== '${DEFAULT_LANG}') {
303
+ url.searchParams.set('lang', saved);
304
+ window.location.replace(url.toString());
305
+ }
306
+ }
307
+ } catch (e) { /* ignore */ }
308
+ })();
309
+ </script>`;
310
+ }
311
+ function langToggleButton(lang) {
312
+ return `<button id="lang-toggle" onclick="switchLang()" class="lang-toggle">${t('switchLang', lang)}</button>`;
313
+ }
314
+ export function layout(title, body, lang = DEFAULT_LANG) {
315
+ const htmlLang = lang === 'zh' ? 'zh-CN' : 'en';
316
+ const favicon = encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#60a5fa"/><stop offset="100%" stop-color="#a78bfa"/></linearGradient></defs><circle cx="16" cy="16" r="15" fill="#0f172a"/><circle cx="16" cy="16" r="8" stroke="url(#g)" stroke-width="3.5" fill="none"/></svg>');
317
+ return `<!doctype html><html lang="${htmlLang}" data-lang="${lang}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>OMK · ${title}</title>
318
+ <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,${favicon}">${globalKeyboardScript()}
319
+ <style>
320
+ :root{
321
+ --bg-base:#0f172a;
322
+ --bg-surface:rgba(30,41,59,0.7);
323
+ --bg-elevated:rgba(15,23,42,0.6);
324
+ --border:rgba(148,163,184,0.1);
325
+ --border-hover:rgba(148,163,184,0.25);
326
+ --text-primary:#e2e8f0;
327
+ --text-secondary:#94a3b8;
328
+ --text-muted:#64748b;
329
+ --text-faint:#475569;
330
+ --accent:#60a5fa;
331
+ --accent-hover:#93bbfd;
332
+ --green:#4ade80;
333
+ --green-bg:rgba(34,197,94,0.12);
334
+ --red:#f87171;
335
+ --red-bg:rgba(239,68,68,0.12);
336
+ --yellow:#fbbf24;
337
+ --yellow-bg:rgba(245,158,11,0.12);
338
+ --info-bg:rgba(96,165,250,0.1);
339
+ --chart-1:#60a5fa;
340
+ --chart-2:#a78bfa;
341
+ --chart-3:#34d399;
342
+ --chart-4:#fb923c;
343
+ --chart-5:#f472b6;
344
+ --chart-6:#fbbf24;
345
+ --bg-card:#1e293b;
346
+ --radius:8px;
347
+ --radius-lg:12px;
348
+ --fs-micro:11px;
349
+ --fs-detail:12px;
350
+ --fs-label:12px;
351
+ --fs-body:13px;
352
+ }
353
+ *{box-sizing:border-box;margin:0}
354
+ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;padding:32px;background:var(--bg-base);color:var(--text-primary);min-height:100vh;line-height:1.5;max-width:1100px;margin:0 auto}
355
+ h1{margin:0 0 6px;font-size:1.5rem;font-weight:700;color:var(--text-primary);letter-spacing:-0.02em}
356
+ h2{margin:24px 0 8px;font-size:0.9375rem;color:var(--text-secondary);font-weight:600}
357
+ .subtitle{color:var(--text-muted);font-size:0.8125rem;margin:0 0 20px}
358
+ a{color:var(--accent);text-decoration:none}
359
+ a:hover{color:var(--accent-hover);text-decoration:underline}
360
+
361
+ /* Meta tags */
362
+ .meta-tags{display:flex;flex-wrap:wrap;gap:8px;margin:8px 0 20px}
363
+ .meta-tag{font-size:0.6875rem;color:var(--text-muted);padding:3px 10px;background:var(--bg-surface);border:1px solid var(--border);border-radius:20px}
364
+
365
+ /* Cards */
366
+ .cards{display:flex;gap:12px;flex-wrap:wrap;margin:10px 0}
367
+ .card{background:var(--bg-surface);border:1px solid var(--border);border-radius:var(--radius);padding:14px 18px;min-width:140px;flex:1;transition:border-color 0.15s}
368
+ .card:hover{border-color:var(--border-hover)}
369
+ .card-label{font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:2px}
370
+ .card-value{font-size:22px;font-weight:700;margin:2px 0;color:var(--text-primary);font-variant-numeric:tabular-nums}
371
+ .card-sub{font-size:11px;color:var(--text-muted)}
372
+ /* Summary table — inherits the global center + middle from the base td/th. */
373
+ .summary-cell{min-width:100px}
374
+ .summary-value-primary{font-size:1.375rem;font-weight:700;font-variant-numeric:tabular-nums;letter-spacing:-0.02em}
375
+
376
+ /* Hint tooltip (legacy span-based, kept for hover-only hints) */
377
+ .hint{position:relative;display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;font-size:10px;font-weight:600;color:var(--text-muted);border:1px solid var(--border-hover);border-radius:50%;cursor:help;margin-left:6px;vertical-align:middle}
378
+ .hint-click{cursor:pointer}
379
+
380
+ /* Hint button — accessible, keyboard-focusable replacement for click-to-open-modal hints */
381
+ button.hint-btn{display:inline-flex;align-items:center;justify-content:center;min-width:22px;min-height:22px;padding:3px;font-size:var(--fs-micro);font-weight:600;color:var(--text-muted);background:transparent;border:1px solid var(--border-hover);border-radius:50%;cursor:pointer;margin-left:6px;vertical-align:middle;line-height:1;transition:color 0.15s,border-color 0.15s}
382
+ button.hint-btn:hover{color:var(--text-primary);border-color:var(--text-primary)}
383
+ button.hint-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
384
+
385
+ /* Verdict + detail pattern used in variance & significance cells */
386
+ .verdict-line{color:var(--text-secondary);font-size:var(--fs-body)}
387
+ .detail-line{font-size:var(--fs-detail);color:var(--text-muted);margin-top:2px}
388
+
389
+ /* Modal glossary layout — grid rows with tree connectors for sub-items */
390
+ .modal-glossary-hint{font-size:var(--fs-detail);color:var(--text-muted);margin:4px 0 14px;font-style:italic}
391
+ .modal-glossary{display:flex;flex-direction:column}
392
+ .modal-glossary-row{display:grid;grid-template-columns:100px 1fr;gap:16px;padding:9px 0;border-bottom:1px solid var(--border)}
393
+ .modal-glossary-row:last-child{border-bottom:none}
394
+ .modal-glossary-label{font-size:var(--fs-body);color:var(--text-primary);font-weight:600}
395
+ .modal-glossary-desc{font-size:var(--fs-detail);color:var(--text-secondary);line-height:1.55}
396
+ .modal-glossary-sub{display:grid;grid-template-columns:86px 1fr;gap:14px;padding:6px 0 6px 28px;position:relative}
397
+ .modal-glossary-sub::before{content:'';position:absolute;left:10px;top:0;bottom:0;width:2px;background:var(--border-hover);border-radius:1px}
398
+ .modal-glossary-sub-label{font-size:var(--fs-detail);color:var(--text-secondary);font-weight:500}
399
+ .modal-glossary-sub-desc{font-size:var(--fs-detail);color:var(--text-muted);line-height:1.55}
400
+
401
+ /* Modal section divider */
402
+ .modal-section{margin-top:20px;padding-top:16px;border-top:1px solid var(--border-hover)}
403
+ .modal-section-title{font-size:var(--fs-body);font-weight:600;color:var(--text-primary);margin-bottom:10px}
404
+
405
+ /* Four-quadrant diagnostic rule cards (matches the table's icon+text style) */
406
+ .diag-rules{display:flex;flex-direction:column;gap:8px}
407
+ .diag-rule-row{display:flex;align-items:flex-start;gap:10px;padding:10px 12px;background:var(--bg-elevated);border-radius:var(--radius);border-left:3px solid var(--border-hover)}
408
+ .diag-rule-row.rule-good{border-left-color:var(--green)}
409
+ .diag-rule-row.rule-warn{border-left-color:var(--yellow)}
410
+ .diag-rule-row.rule-neutral{border-left-color:var(--text-muted)}
411
+ .diag-rule-icon{font-size:15px;flex-shrink:0;line-height:1.4}
412
+ .diag-rule-icon.rule-good{color:var(--green)}
413
+ .diag-rule-icon.rule-warn{color:var(--yellow)}
414
+ .diag-rule-icon.rule-neutral{color:var(--text-muted)}
415
+ .diag-rule-body{flex:1;min-width:0}
416
+ .diag-rule-title{font-size:var(--fs-detail);font-weight:600;color:var(--text-primary);margin-bottom:3px}
417
+ .diag-rule-desc{font-size:var(--fs-detail);color:var(--text-secondary);line-height:1.5}
418
+ .diag-rule-example{font-size:var(--fs-micro);color:var(--text-muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;margin-top:4px;opacity:0.85}
419
+
420
+ /* Variance & significance table: all cells use the global center + middle. */
421
+ .variance-table td{padding-top:12px;padding-bottom:12px}
422
+ .variance-table td.diagnostic-cell{min-width:180px}
423
+ .variance-table .diag-faded strong{opacity:0.5;font-weight:500}
424
+
425
+ /* Knowledge Interaction section (v0.17 / A):
426
+ variant card is the only visual container, two inner columns use a
427
+ single vertical divider instead of nested bg — compresses hierarchy
428
+ from 3-4 layers to 2. */
429
+ .ki-card{margin-bottom:10px;padding:12px 14px;background:var(--bg-surface);border:1px solid var(--border);border-radius:var(--radius)}
430
+ .ki-card-header{display:flex;flex-direction:column;gap:3px;margin-bottom:10px}
431
+ .ki-card-title{font-size:15px;font-weight:600;color:var(--text-primary)}
432
+ .ki-card-meta{font-size:var(--fs-micro);color:var(--text-muted);font-weight:400}
433
+ .ki-columns{display:flex;gap:0;flex-wrap:wrap}
434
+ .ki-col{flex:1;min-width:220px;padding:0 18px}
435
+ .ki-col:first-child{padding-left:0;border-right:1px solid var(--border)}
436
+ .ki-col:last-child{padding-right:0}
437
+ @media(max-width:640px){
438
+ .ki-col{padding:0;min-width:100%;border-right:none !important}
439
+ .ki-col+.ki-col{margin-top:16px;padding-top:14px;border-top:1px solid var(--border)}
440
+ }
441
+ .ki-col-header{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:8px}
442
+ .ki-col-title{font-size:13px;color:var(--text-secondary);font-weight:500}
443
+ .ki-col-value{font-size:22px;font-weight:600}
444
+ .ki-bar{height:6px;background:var(--bg-card);border-radius:4px;margin-bottom:8px;overflow:hidden}
445
+ .ki-bar-fill{height:100%;border-radius:4px;transition:width 0.2s}
446
+ .ki-inventory-item{padding:6px 10px;margin:4px 0;background:var(--bg-card);border-left:3px solid var(--border-hover);border-radius:4px;font-size:var(--fs-detail);line-height:1.5}
447
+ .ki-inventory-item[data-severity="strong"]{border-left-color:var(--red)}
448
+ .ki-inventory-item[data-severity="medium"]{border-left-color:var(--yellow)}
449
+ .ki-inventory-item[data-severity="weak"]{border-left-color:var(--text-muted)}
450
+ .ki-inventory-item-meta{color:var(--text-muted);font-size:var(--fs-micro);margin-bottom:2px}
451
+ .ki-inventory-item-ctx{color:var(--text-secondary);word-break:break-all}
452
+ .ki-desc{font-size:12px;color:var(--text-muted);margin-bottom:4px;line-height:1.6}
453
+ .ki-desc-hint{font-size:11px;color:var(--text-faint);margin-bottom:12px;line-height:1.5}
454
+ .ki-details{margin-top:8px;padding-top:8px;border-top:1px solid var(--border)}
455
+ .ki-details>summary{cursor:pointer;font-size:var(--fs-micro);color:var(--text-muted);padding:2px 0;list-style:revert;user-select:none;transition:color 0.15s}
456
+ .ki-details>summary:hover{color:var(--text-secondary)}
457
+ .ki-details[open]>summary{color:var(--text-secondary);margin-bottom:6px}
458
+
459
+ /* Three-layer independent significance breakdown (PR-2).
460
+ Default collapsed; expands inline under each comparison. */
461
+ .layer-breakdown-row>td{padding:0 !important;background:transparent;border-top:1px dashed var(--border-hover)}
462
+ .layer-breakdown{padding:10px 16px 14px 32px;background:var(--bg-elevated)}
463
+ .layer-breakdown>summary{cursor:pointer;font-size:var(--fs-detail);color:var(--text-muted);padding:4px 0;list-style:revert;user-select:none}
464
+ .layer-breakdown>summary:hover{color:var(--text-secondary)}
465
+ .layer-breakdown[open]>summary{color:var(--text-primary);margin-bottom:8px}
466
+ .layer-sub-table{margin:0;width:100%;font-size:var(--fs-detail)}
467
+ .layer-sub-table td{padding-top:8px;padding-bottom:8px}
468
+ /* Multiple-comparisons disclaimer for the three-layer breakdown (PR-2) */
469
+ .layer-breakdown-disclaimer{font-size:var(--fs-micro);color:var(--text-muted);line-height:1.5;padding:4px 8px 10px 0;font-style:italic}
470
+ .modal-overlay{display:none;position:fixed;inset:0;z-index:999;background:rgba(0,0,0,0.6);align-items:center;justify-content:center}
471
+ .modal-content{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);max-width:800px;max-height:80vh;overflow:auto;padding:24px;margin:20px;width:90%}
472
+ .modal-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}
473
+ .modal-close{cursor:pointer;background:none;border:none;color:var(--text-muted);font-size:18px;padding:8px 12px;border-radius:var(--radius);transition:background 0.15s,color 0.15s}
474
+ .modal-close:hover{color:var(--text-primary);background:var(--bg-surface)}
475
+ .modal-table{width:100%;font-size:13px;margin:12px 0;background:transparent;border:none;table-layout:auto}
476
+ .modal-table td{padding:6px 0;border:none;background:transparent;word-break:break-word;overflow-wrap:anywhere}
477
+ .modal-table td:first-child{white-space:nowrap;vertical-align:top;min-width:80px;padding-right:16px;word-break:keep-all}
478
+ /* Inline <code> inside modal text — improve readability on dark surfaces */
479
+ .modal-table code,.modal-glossary code,.modal-section code{background:var(--bg-surface);padding:1px 6px;border-radius:3px;font-size:var(--fs-micro);color:var(--text-primary);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
480
+ @media(max-width:480px){.modal-table td{display:block;padding:3px 0}.modal-table td:first-child{font-weight:600}}
481
+ .hint-tip{display:none;position:absolute;bottom:calc(100% + 6px);right:0;background:var(--bg-elevated);border:1px solid var(--border-hover);border-radius:var(--radius);padding:6px 10px;font-size:11px;font-weight:400;color:var(--text-secondary);white-space:normal;max-width:280px;width:max-content;z-index:10}
482
+ .hint:hover .hint-tip,.hint:focus .hint-tip{display:block}
483
+ .summary-value{font-size:1rem;font-weight:600;color:var(--text-primary);font-variant-numeric:tabular-nums}
484
+ .summary-detail{font-size:0.6875rem;color:var(--text-muted);margin-top:3px}
485
+ .summary-unit{font-size:0.75rem;font-weight:400;color:var(--text-muted)}
486
+ .card-detail{margin-top:8px;font-size:12px;color:var(--text-secondary)}
487
+ .card-detail div{margin:2px 0}
488
+
489
+ /* Table */
490
+ .table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:16px 0;position:relative}
491
+ /* 窄屏下 6 列宽 >700px 会横向溢出,右侧稳定性列容易被遮盖。
492
+ 加一条渐变阴影作为"可滑动"视觉提示,仅在 ≤768px 且可滚动容器里显示。 */
493
+ @media(max-width:768px){
494
+ .table-wrap::after{content:'';position:sticky;right:0;top:0;display:block;float:right;width:32px;height:100%;margin-left:-32px;margin-top:-100%;pointer-events:none;background:linear-gradient(to right,transparent,var(--bg-card) 85%);z-index:2}
495
+ }
496
+ table{border-collapse:collapse;width:100%;font-size:0.8125rem;background:var(--bg-surface);border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;line-height:1.4}
497
+ th{background:var(--bg-elevated);padding:8px 14px;text-align:center;vertical-align:middle;font-weight:500;color:var(--text-muted);border-bottom:1px solid var(--border);font-size:0.6875rem;text-transform:uppercase;letter-spacing:0.04em;white-space:nowrap}
498
+ td{padding:10px 14px;border-bottom:1px solid var(--border);color:var(--text-secondary);font-variant-numeric:tabular-nums;text-align:center;vertical-align:middle}
499
+ tr:last-child td{border-bottom:none}
500
+ tr:hover td{background:rgba(148,163,184,0.04)}
501
+
502
+ /* Badges */
503
+ .badge{display:inline-block;padding:2px 8px;border-radius:var(--radius);font-size:11px;font-weight:600}
504
+ .badge-ok{background:var(--green-bg);color:var(--green)}
505
+ .badge-err{background:var(--red-bg);color:var(--red)}
506
+ .badge-pass{background:var(--green-bg);color:var(--green)}
507
+ .badge-fail{background:var(--red-bg);color:var(--red)}
508
+ .badge-muted{background:var(--bg-surface);color:var(--text-muted);border:1px solid var(--border)}
509
+
510
+ /* Nav */
511
+ .nav{margin-bottom:24px;font-size:13px}
512
+
513
+ /* Error detail */
514
+ .error-detail{display:inline-block;font-size:11px;color:var(--red);word-break:break-all;max-width:260px}
515
+
516
+ /* Assertion & dimension tags */
517
+ .assertion-list{margin:4px 0;padding:0;list-style:none;font-size:11px}
518
+ .assertion-list li{margin:2px 0;color:var(--text-secondary)}
519
+ .dim-scores{display:flex;gap:6px;flex-wrap:wrap;margin-top:4px}
520
+ .dim-tag{font-size:10px;padding:2px 7px;border-radius:4px;background:var(--info-bg);color:var(--accent)}
521
+ .dim-desc{font-size:11px;color:var(--text-muted);font-weight:400;margin-left:6px}
522
+
523
+ /* Bar chart */
524
+ .bar-row{display:flex;align-items:center;gap:8px;margin:6px 0}
525
+ .bar-label{flex:0 0 60px;font-size:12px;color:var(--text-muted)}
526
+ .bar-fill{flex:1;height:16px;border-radius:4px;opacity:0.8}
527
+ .bar-value{flex:0 0 auto;font-size:12px;color:var(--text-secondary)}
528
+
529
+ /* Forms */
530
+ input[type="text"]{background:var(--bg-elevated);border:1px solid var(--border);color:var(--text-primary);border-radius:var(--radius);padding:4px 8px;font-size:12px}
531
+ input[type="text"]:focus{outline-color:transparent;border-color:var(--accent);box-shadow:0 0 0 2px rgba(96,165,250,0.15)}
532
+ button{background:var(--bg-surface);border:1px solid var(--border);color:var(--text-secondary);border-radius:var(--radius);cursor:pointer;padding:4px 12px;font-size:12px;transition:border-color 0.15s,color 0.15s}
533
+ button:hover{border-color:var(--border-hover);color:var(--text-primary)}
534
+ button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
535
+
536
+ /* Lang toggle */
537
+ .lang-toggle{position:fixed;top:16px;right:16px;padding:6px 14px;z-index:100;font-size:12px}
538
+
539
+ /* Misc */
540
+ .btn-danger{color:var(--red)}
541
+
542
+ /* Focus */
543
+ a:focus-visible,.badge:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:4px}
544
+
545
+ /* Responsive */
546
+ @media(max-width:768px){
547
+ body{padding:16px}
548
+ .cards{flex-direction:column}
549
+ .card{min-width:0}
550
+ h1{font-size:1.25rem}
551
+ h2{font-size:0.875rem}
552
+ .lang-toggle{top:8px;right:8px;padding:4px 10px;font-size:11px}
553
+ button{min-height:44px;padding:8px 14px}
554
+ /* Override: hint buttons stay compact so they don't dominate mobile layout */
555
+ button.hint-btn{min-width:28px;min-height:28px;padding:4px}
556
+ /* Bump detail font so secondary lines are readable on mobile */
557
+ .detail-line{font-size:var(--fs-label)}
558
+ }
559
+ @media(max-width:480px){
560
+ body{padding:12px}
561
+ td,th{padding:8px 10px;font-size:12px}
562
+ }
563
+ @media print{
564
+ body{background:#fff;color:#1e293b;padding:20px;max-width:none}
565
+ h1,h2,.card-value,.summary-value,.summary-value-primary{color:#1e293b}
566
+ .card,.summary-table,table{background:#fff;border-color:#e2e8f0}
567
+ th{background:#f8fafc;color:#475569;border-color:#e2e8f0}
568
+ td{color:#334155;border-color:#f1f5f9}
569
+ .badge-ok,.badge-pass{background:#dcfce7;color:#166534}
570
+ .badge-err,.badge-fail{background:#fee2e2;color:#991b1b}
571
+ .badge-muted{background:#f8fafc;color:#94a3b8;border-color:#e2e8f0}
572
+ .dim-tag{background:#f1f5f9;color:#3b82f6}
573
+ .meta-tag{background:#f8fafc;border-color:#e2e8f0;color:#475569}
574
+ .bar-fill{opacity:1}
575
+ a{color:#1e293b;text-decoration:none}
576
+ .lang-toggle,.btn-danger,.nav{display:none}
577
+ .hint-tip{display:none}
578
+ .footer{color:#475569}
579
+ }
580
+ </style></head><body>${langToggleButton(lang)}${body}<footer class="footer" style="margin-top:40px;padding-top:16px;border-top:1px solid var(--border);font-size:11px;color:var(--text-faint);text-align:center">Powered by oh-my-knowledge</footer>${langToggleScript()}</body></html>`;
581
+ }
582
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../../src/renderer/layout.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,CAAC,CAAC,IAAa;IAC7B,OAAO,MAAM,CAAC,IAAI,CAAC;SAChB,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,CAA4B,EAAE,SAAiB,CAAC;IACrE,OAAO,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,qBAAqB,EAAE,MAAM,EAAE,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAA6B;IACvD,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAC1B,IAAI,CAAC,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC;IAC9B,IAAI,CAAC,GAAG,KAAK;QAAE,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAClD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3C,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,GAA8B;IACpD,OAAO,IAAI,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3B,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC9D,OAAO,GAAG,CAAC,CAAC,WAAW,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC;AAC9I,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,CAA4B,EAAE,CAA4B,EAAE,gBAAyB,KAAK;IAC9G,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,YAAY,CAAC;IACrF,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IAC9C,OAAO,sBAAsB,KAAK,oCAAoC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;AAChH,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAa,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;AAE7I,MAAM,CAAC,MAAM,IAAI,GAAyC;IACxD,EAAE,EAAE;QACF,KAAK,EAAE,MAAM;QACb,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,sEAAsE;QAC9E,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK;QAC5D,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;QACnC,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM;QAChE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ;QACzC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU;QACvE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,kCAAkC;QACjE,WAAW,EAAE,QAAQ,EAAE,eAAe,EAAE,qCAAqC;QAC7E,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,2EAA2E;QAChH,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,qEAAqE;QAC1G,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,+BAA+B;QAC9D,aAAa,EAAE,MAAM,EAAE,iBAAiB,EAAE,4BAA4B;QACtE,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,0CAA0C;QACrF,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;QAC1C,UAAU,EAAE,IAAI,EAAE,cAAc,EAAE,2BAA2B;QAC7D,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,sCAAsC;QACxE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI;QACvD,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM;QAC5D,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI;QAC/C,eAAe,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM;QACvD,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI;QACpD,YAAY,EAAE,MAAM;QACpB,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI;QACtC,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ;QACpD,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,IAAI;QAChH,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK;QACzC,UAAU,EAAE,UAAU;QACtB,UAAU,EAAE,UAAU;QACtB,WAAW,EAAE,WAAW;QACxB,aAAa,EAAE,aAAa;QAC5B,aAAa,EAAE,YAAY;QAC3B,cAAc,EAAE,MAAM;QACtB,gBAAgB,EAAE,OAAO;QACzB,aAAa,EAAE,MAAM;QACrB,aAAa,EAAE,MAAM;QACrB,aAAa,EAAE,QAAQ;QACvB,WAAW,EAAE,MAAM;QACnB,cAAc,EAAE,IAAI;QACpB,SAAS,EAAE,IAAI;QACf,eAAe,EAAE,QAAQ;QACzB,WAAW,EAAE,IAAI;QACjB,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,MAAM;QACrB,iBAAiB,EAAE,mDAAmD;QACtE,WAAW,EAAE,MAAM;QACnB,mBAAmB,EAAE,MAAM;QAC3B,qBAAqB,EAAE,MAAM;QAC7B,wBAAwB,EAAE,MAAM;QAChC,qBAAqB,EAAE,MAAM;QAC7B,sDAAsD;QACtD,gBAAgB,EAAE,aAAa;QAC/B,UAAU,EAAE,kEAAkE;QAC9E,iBAAiB,EAAE,QAAQ;QAC3B,cAAc,EAAE,eAAe;QAC/B,mBAAmB,EAAE,uCAAuC;QAC5D,kBAAkB,EAAE,MAAM;QAC1B,iBAAiB,EAAE,MAAM;QACzB,eAAe,EAAE,IAAI;QACrB,gBAAgB,EAAE,IAAI;QACtB,YAAY,EAAE,GAAG;QACjB,cAAc,EAAE,IAAI;QACpB,iBAAiB,EAAE,UAAU;QAC7B,WAAW,EAAE,8BAA8B;QAC3C,YAAY,EAAE,MAAM;QACpB,aAAa,EAAE,IAAI;QACnB,WAAW,EAAE,IAAI;QACjB,cAAc,EAAE,UAAU;QAC1B,mBAAmB,EAAE,cAAc;QACnC,kBAAkB,EAAE,cAAc;QAClC,mBAAmB,EAAE,UAAU;QAC/B,iBAAiB,EAAE,IAAI;QACvB,YAAY,EAAE,IAAI;QAClB,WAAW,EAAE,KAAK;QAClB,gBAAgB,EAAE,IAAI;QACtB,eAAe,EAAE,KAAK;QACtB,gBAAgB,EAAE,IAAI;QACtB,cAAc,EAAE,QAAQ;QACxB,gBAAgB,EAAE,IAAI;QACtB,gBAAgB,EAAE,aAAa;QAC/B,YAAY,EAAE,yBAAyB;QACvC,cAAc,EAAE,KAAK;QACrB,UAAU,EAAE,IAAI;QAChB,WAAW,EAAE,IAAI;QACjB,SAAS,EAAE,IAAI;QACf,YAAY,EAAE,OAAO;QACrB,eAAe,EAAE,IAAI;QACrB,kBAAkB,EAAE,QAAQ;QAC5B,kBAAkB,EAAE,KAAK;QACzB,eAAe,EAAE,IAAI;QACrB,aAAa,EAAE,QAAQ;QACvB,iBAAiB,EAAE,MAAM;QACzB,mBAAmB,EAAE,gGAAgG;QACrH,UAAU,EAAE,IAAI;KACjB;IACD,EAAE,EAAE;QACF,KAAK,EAAE,oBAAoB;QAC3B,QAAQ,EAAE,+BAA+B;QACzC,MAAM,EAAE,8FAA8F;QACtG,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS;QACxE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;QAC1C,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,UAAU,EAAE,eAAe;QACpF,WAAW,EAAE,mBAAmB,EAAE,UAAU,EAAE,gBAAgB;QAC9D,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,wBAAwB;QAChG,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,mFAAmF;QACpH,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,mFAAmF;QACjI,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,oKAAoK;QAC5M,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,oJAAoJ;QAC9L,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,wDAAwD;QACzF,aAAa,EAAE,cAAc,EAAE,iBAAiB,EAAE,oEAAoE;QACtH,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,8IAA8I;QAC/L,cAAc,EAAE,iBAAiB,EAAE,UAAU,EAAE,OAAO;QACtD,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,+DAA+D;QACzG,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,kFAAkF;QACvH,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ;QACrE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa;QACxE,WAAW,EAAE,iBAAiB,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ;QACpE,eAAe,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,oBAAoB;QAC7E,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK;QAChE,YAAY,EAAE,eAAe;QAC7B,eAAe,EAAE,mBAAmB,EAAE,MAAM,EAAE,QAAQ;QACtD,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI;QACnD,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,aAAa;QACnI,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU;QAC9C,UAAU,EAAE,YAAY;QACxB,UAAU,EAAE,YAAY;QACxB,WAAW,EAAE,aAAa;QAC1B,aAAa,EAAE,eAAe;QAC9B,aAAa,EAAE,0BAA0B;QACzC,cAAc,EAAE,YAAY;QAC5B,gBAAgB,EAAE,mBAAmB;QACrC,aAAa,EAAE,mBAAmB;QAClC,aAAa,EAAE,WAAW;QAC1B,aAAa,EAAE,gBAAgB;QAC/B,WAAW,EAAE,iBAAiB;QAC9B,cAAc,EAAE,WAAW;QAC3B,SAAS,EAAE,MAAM;QACjB,eAAe,EAAE,aAAa;QAC9B,WAAW,EAAE,MAAM;QACnB,YAAY,EAAE,OAAO;QACrB,YAAY,EAAE,OAAO;QACrB,aAAa,EAAE,kBAAkB;QACjC,iBAAiB,EAAE,oIAAoI;QACvJ,WAAW,EAAE,MAAM;QACnB,mBAAmB,EAAE,eAAe;QACpC,qBAAqB,EAAE,QAAQ;QAC/B,wBAAwB,EAAE,oBAAoB;QAC9C,qBAAqB,EAAE,iBAAiB;QACxC,sDAAsD;QACtD,gBAAgB,EAAE,sBAAsB;QACxC,UAAU,EAAE,0FAA0F;QACtG,iBAAiB,EAAE,gBAAgB;QACnC,cAAc,EAAE,wBAAwB;QACxC,mBAAmB,EAAE,4EAA4E;QACjG,kBAAkB,EAAE,WAAW;QAC/B,iBAAiB,EAAE,MAAM;QACzB,eAAe,EAAE,IAAI;QACrB,gBAAgB,EAAE,UAAU;QAC5B,YAAY,EAAE,MAAM;QACpB,cAAc,EAAE,QAAQ;QACxB,iBAAiB,EAAE,aAAa;QAChC,WAAW,EAAE,wEAAwE;QACrF,YAAY,EAAE,aAAa;QAC3B,aAAa,EAAE,UAAU;QACzB,WAAW,EAAE,QAAQ;QACrB,cAAc,EAAE,UAAU;QAC1B,mBAAmB,EAAE,cAAc;QACnC,kBAAkB,EAAE,cAAc;QAClC,mBAAmB,EAAE,UAAU;QAC/B,iBAAiB,EAAE,WAAW;QAC9B,YAAY,EAAE,MAAM;QACpB,WAAW,EAAE,KAAK;QAClB,gBAAgB,EAAE,UAAU;QAC5B,eAAe,EAAE,SAAS;QAC1B,gBAAgB,EAAE,UAAU;QAC5B,cAAc,EAAE,QAAQ;QACxB,gBAAgB,EAAE,UAAU;QAC5B,gBAAgB,EAAE,mBAAmB;QACrC,YAAY,EAAE,iDAAiD;QAC/D,cAAc,EAAE,SAAS;QACzB,UAAU,EAAE,KAAK;QACjB,WAAW,EAAE,MAAM;QACnB,SAAS,EAAE,IAAI;QACf,YAAY,EAAE,OAAO;QACrB,eAAe,EAAE,UAAU;QAC3B,kBAAkB,EAAE,cAAc;QAClC,kBAAkB,EAAE,cAAc;QAClC,eAAe,EAAE,UAAU;QAC3B,aAAa,EAAE,SAAS;QACxB,iBAAiB,EAAE,qBAAqB;QACxC,mBAAmB,EAAE,uRAAuR;QAC5S,UAAU,EAAE,IAAI;KACjB;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAS,IAAI,CAAC;AAEvC,MAAM,UAAU,CAAC,CAAC,GAAW,EAAE,OAAa,YAAY;IACtD,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;AAClD,CAAC;AAED,SAAS,oBAAoB;IAC3B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;YA0BG,CAAC;AACb,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO;;eAEM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;;0DAEuB,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;kCA0BpC,YAAY;;;;;;;YAOlC,CAAC;AACb,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAU;IAClC,OAAO,uEAAuE,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC,WAAW,CAAC;AACjH,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,KAAa,EAAE,IAAY,EAAE,OAAa,YAAY;IAC3E,MAAM,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IAChD,MAAM,OAAO,GAAG,kBAAkB,CAAC,qWAAqW,CAAC,CAAC;IAC1Y,OAAO,8BAA8B,QAAQ,gBAAgB,IAAI,iHAAiH,KAAK;iEACxH,OAAO,KAAK,oBAAoB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAsQ5E,gBAAgB,CAAC,IAAI,CAAC,GAAG,IAAI,kMAAkM,gBAAgB,EAAE,gBAAgB,CAAC;AACzR,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Skill 健康度日报 renderer (v0.18).
3
+ *
4
+ * 输入: SkillHealthReport (from skill-health-analyzer)
5
+ * 输出: 完整 HTML 文档, 包含:
6
+ * - 顶部摘要 (trace 源水印 + overall 健康度色带)
7
+ * - 每 skill 一张 card, 复用 v0.17 A 的 ki-card 左右栏 (coverage + gap)
8
+ * - 死代码 KB section (所有 skill 都没访问过的 KB 文件)
9
+ *
10
+ * 设计复用:
11
+ * - layout.ts 的整体 HTML skeleton + CSS (ki-card / ki-col / ki-bar 全部现成)
12
+ * - 报告视觉和 bench HTML 保持一致, 读者无学习成本切换
13
+ */
14
+ import type { SkillHealthReport } from '../observability/skill-health-analyzer.js';
15
+ import type { Lang } from '../types.js';
16
+ /**
17
+ * 主入口: 生成完整 HTML。
18
+ */
19
+ export declare function renderSkillHealthReport(report: SkillHealthReport, lang?: Lang): string;
20
+ //# sourceMappingURL=skill-health-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-health-renderer.d.ts","sourceRoot":"","sources":["../../../src/renderer/skill-health-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAe,iBAAiB,EAAE,MAAM,2CAA2C,CAAC;AAChG,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAwOxC;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,EAAE,IAAI,GAAE,IAAW,GAAG,MAAM,CAmB5F"}