oh-my-knowledge 0.35.0 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +5 -3
  2. package/README.zh.md +5 -3
  3. package/dist/assets/agent-skills/omk/SKILL.md +4 -2
  4. package/dist/assets/agent-skills/omk/references/commands.md +121 -2
  5. package/dist/authoring/evolver.js +1 -1
  6. package/dist/cli/commands/doctor.js +21 -5
  7. package/dist/cli/commands/eval/index.js +7 -6
  8. package/dist/cli/commands/evolve.d.ts +11 -0
  9. package/dist/cli/commands/evolve.js +105 -5
  10. package/dist/cli/commands/list.d.ts +25 -0
  11. package/dist/cli/commands/list.js +118 -0
  12. package/dist/cli/commands/promote.d.ts +24 -0
  13. package/dist/cli/commands/promote.js +158 -0
  14. package/dist/cli/commands/rollback.d.ts +20 -0
  15. package/dist/cli/commands/rollback.js +95 -0
  16. package/dist/cli/commands/sample.d.ts +1 -0
  17. package/dist/cli/commands/sample.js +10 -4
  18. package/dist/cli/lib/cell-format.d.ts +17 -0
  19. package/dist/cli/lib/cell-format.js +19 -0
  20. package/dist/cli/lib/cmd-flags.d.ts +1 -0
  21. package/dist/cli/lib/i18n-dict/common.d.ts +1 -1
  22. package/dist/cli/lib/i18n-dict/common.js +8 -0
  23. package/dist/cli/lib/i18n-dict/list.d.ts +3 -0
  24. package/dist/cli/lib/i18n-dict/list.js +36 -0
  25. package/dist/cli/lib/i18n-dict/promote.d.ts +3 -0
  26. package/dist/cli/lib/i18n-dict/promote.js +54 -0
  27. package/dist/cli/lib/i18n-dict/rollback.d.ts +3 -0
  28. package/dist/cli/lib/i18n-dict/rollback.js +22 -0
  29. package/dist/cli/lib/i18n-dict.d.ts +4 -1
  30. package/dist/cli/lib/i18n-dict.js +6 -0
  31. package/dist/cli/lib/progress.d.ts +3 -0
  32. package/dist/cli/lib/progress.js +22 -0
  33. package/dist/cli/lib/run-tally.js +1 -1
  34. package/dist/cli/lib/shared.js +1 -1
  35. package/dist/cli/lib/source-probe.d.ts +15 -0
  36. package/dist/cli/lib/source-probe.js +129 -0
  37. package/dist/doctor/endpoint-rule.d.ts +60 -0
  38. package/dist/doctor/endpoint-rule.js +381 -0
  39. package/dist/doctor/health/load-custom-dimensions.d.ts +6 -0
  40. package/dist/doctor/health/load-custom-dimensions.js +43 -3
  41. package/dist/doctor/index.js +9 -2
  42. package/dist/eval-core/evaluation-reporting.d.ts +1 -0
  43. package/dist/eval-core/evaluation-reporting.js +6 -4
  44. package/dist/eval-workflows/batch-evaluation-workflow.js +3 -2
  45. package/dist/eval-workflows/run-evaluation.js +2 -2
  46. package/dist/executors/codex-cli.js +5 -1
  47. package/dist/inputs/skill-loader.js +6 -3
  48. package/dist/managed/index.d.ts +2 -0
  49. package/dist/managed/index.js +2 -0
  50. package/dist/managed/list-view.d.ts +58 -0
  51. package/dist/managed/list-view.js +70 -0
  52. package/dist/managed/promote-gate.d.ts +40 -0
  53. package/dist/managed/promote-gate.js +37 -0
  54. package/dist/managed/store.d.ts +25 -2
  55. package/dist/managed/store.js +137 -11
  56. package/dist/observability/experience.d.ts +2 -0
  57. package/dist/observability/experience.js +31 -2
  58. package/dist/observability/inbox.js +31 -5
  59. package/dist/observability/review-state.js +22 -11
  60. package/dist/observability/soft-standards/llm-extractor.js +3 -3
  61. package/dist/observability/soft-standards/skill-standards-store.d.ts +1 -0
  62. package/dist/observability/soft-standards/skill-standards-store.js +77 -14
  63. package/dist/observability/soft-standards/types.d.ts +2 -2
  64. package/dist/renderer/doctor-detail-renderer.d.ts +9 -0
  65. package/dist/renderer/doctor-detail-renderer.js +114 -0
  66. package/dist/renderer/html-renderer.d.ts +3 -2
  67. package/dist/renderer/html-renderer.js +102 -102
  68. package/dist/renderer/icons.d.ts +29 -0
  69. package/dist/renderer/icons.js +66 -0
  70. package/dist/renderer/layout.js +81 -68
  71. package/dist/renderer/observation-inbox/styles.d.ts +1 -1
  72. package/dist/renderer/observation-inbox/styles.js +53 -53
  73. package/dist/renderer/report-shell.d.ts +77 -0
  74. package/dist/renderer/report-shell.js +223 -0
  75. package/dist/renderer/skill-detail-renderer.js +147 -352
  76. package/dist/renderer/skill-health-renderer.js +50 -73
  77. package/dist/renderer/skill-list-renderer.js +358 -306
  78. package/dist/renderer/summary.js +272 -162
  79. package/dist/renderer/test-view.d.ts +4 -3
  80. package/dist/renderer/test-view.js +386 -135
  81. package/dist/server/report-server.js +142 -28
  82. package/dist/server/report-store.d.ts +1 -1
  83. package/dist/server/report-store.js +16 -15
  84. package/dist/server/skill-index.js +5 -4
  85. package/dist/types/doctor.d.ts +24 -2
  86. package/dist/types/doctor.js +1 -1
  87. package/dist/types/managed.d.ts +17 -3
  88. package/dist/types/observability.d.ts +6 -6
  89. package/dist/types/report.d.ts +9 -4
  90. package/package.json +1 -1
@@ -0,0 +1,66 @@
1
+ /**
2
+ * 共享单色线性 SVG 图标集(替代各处 emoji)。
3
+ *
4
+ * 设计:统一 24×24 viewBox、`stroke="currentColor"`、单一描边权重、圆角端点。
5
+ * 颜色由调用处的 CSS `color` 控制(图标自身不带色),尺寸/粗细可覆盖。
6
+ * 之所以自带一套而不用图标库:报告是离线自包含 HTML,内联 SVG 无需外链/字体。
7
+ */
8
+ /** name → viewBox 内的 path/shape 串。 */
9
+ const PATHS = {
10
+ // 品牌 / 导航
11
+ brand: '<path d="M12 3l8 4.5v9L12 21l-8-4.5v-9z"/>',
12
+ home: '<path d="M3 10l9-7 9 7v9a2 2 0 01-2 2h-4v-6H9v6H5a2 2 0 01-2-2z"/>',
13
+ search: '<circle cx="11" cy="11" r="7"/><path d="M21 21l-4-4"/>',
14
+ clock: '<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',
15
+ calendar: '<rect x="3" y="5" width="18" height="16" rx="2"/><path d="M8 3v4M16 3v4M3 11h18"/>',
16
+ chip: '<rect x="4" y="4" width="16" height="16" rx="3"/><path d="M8 12h8"/>',
17
+ 'chevron-right': '<path d="M9 6l6 6-6 6"/>',
18
+ 'chevron-left': '<path d="M15 18l-6-6 6-6"/>',
19
+ // 报告类型(= 维度)
20
+ doctor: '<path d="M3 12h4l2-6 4 14 2-8h6"/>',
21
+ eval: '<rect x="3" y="3" width="18" height="18" rx="3"/><path d="M9 11l2 2 4-4"/>',
22
+ observe: '<circle cx="12" cy="12" r="3"/><circle cx="12" cy="12" r="9"/>',
23
+ // 六维
24
+ fact: '<rect x="5" y="4" width="14" height="17" rx="2"/><path d="M8 9h8M8 13h8M8 17h5"/>',
25
+ behavior: '<circle cx="12" cy="12" r="7"/><path d="M12 2v3M12 19v3M2 12h3M19 12h3"/>',
26
+ judge: '<path d="M21 12a8 8 0 01-11.5 7.2L4 21l1.8-5.5A8 8 0 1121 12z"/>',
27
+ cost: '<ellipse cx="12" cy="6" rx="7" ry="3"/><path d="M5 6v6c0 1.7 3.1 3 7 3s7-1.3 7-3V6M5 12v6c0 1.7 3.1 3 7 3s7-1.3 7-3v-6"/>',
28
+ efficiency: '<path d="M13 2L4 14h7l-1 8 9-12h-7z"/>',
29
+ stability: '<path d="M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6z"/>',
30
+ quality: '<path d="M4 20V10M10 20V4M16 20v-7M22 20H2"/>',
31
+ // 状态
32
+ check: '<path d="M5 12l5 5L20 7"/>',
33
+ x: '<path d="M18 6L6 18M6 6l12 12"/>',
34
+ warn: '<path d="M12 9v4M12 17h.01M10.3 3.9l-8 14A2 2 0 004 21h16a2 2 0 001.7-3l-8-14a2 2 0 00-3.4 0z"/>',
35
+ bulb: '<path d="M9 18h6M10 22h4M12 2a7 7 0 00-4 12.7c.6.5 1 1.3 1 2.1V17h6v-.2c0-.8.4-1.6 1-2.1A7 7 0 0012 2z"/>',
36
+ };
37
+ /** 返回一个自包含 `<svg>` 串。未知 name 返回空串(不抛错,调用处可安全拼接)。 */
38
+ export function icon(name, opts = {}) {
39
+ const p = PATHS[name];
40
+ if (!p)
41
+ return '';
42
+ const size = opts.size ?? 16;
43
+ const cls = opts.cls ? ` class="${opts.cls}"` : '';
44
+ const style = opts.style ? ` style="${opts.style}"` : '';
45
+ const sw = opts.sw ?? 1.7;
46
+ return `<svg${cls}${style} width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="${sw}" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${p}</svg>`;
47
+ }
48
+ /** 维度 → 报告类型图标名。 */
49
+ export function dimIconName(dim) {
50
+ return dim;
51
+ }
52
+ /**
53
+ * 品牌 logo —— 圆形「omk」标记(深底 + 蓝紫渐变 o 环)。自带配色,不走 currentColor。
54
+ * 内联(不外链内网地址),保证报告离线/换机仍自包含。gradient id 用 `omkAccent` 防与页面其它 svg 撞 id。
55
+ */
56
+ const BRAND_LOGO_INNER = '<defs><linearGradient id="omkAccent" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#60a5fa"/><stop offset="100%" stop-color="#a78bfa"/></linearGradient></defs>' +
57
+ '<circle cx="60" cy="60" r="56" fill="#0f172a" stroke="#1e293b" stroke-width="1.5"/>' +
58
+ '<path d="M24 60 A12 12 0 1 1 36 72" stroke="url(#omkAccent)" stroke-width="3.5" stroke-linecap="round" fill="none"/>' +
59
+ '<path d="M56 72 V57 Q56 48 61.5 48 Q67 48 67 57 V72 M67 57 Q67 48 72.5 48 Q78 48 78 57 V72" stroke="#e2e8f0" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>' +
60
+ '<path d="M86 48 V72 M86 60 L96 48 M86 60 L96 72" stroke="#e2e8f0" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>';
61
+ /** 品牌 logo 的完整 `<svg>`(给定像素尺寸)。 */
62
+ export function brandLogo(size = 28) {
63
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 120 120" fill="none" aria-label="omk">${BRAND_LOGO_INNER}</svg>`;
64
+ }
65
+ /** 品牌 logo 的原始 `<svg>`(无尺寸,供 favicon data URI 编码用)。 */
66
+ export const BRAND_LOGO_RAW = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120" fill="none">${BRAND_LOGO_INNER}</svg>`;
@@ -1,3 +1,4 @@
1
+ import { brandLogo, BRAND_LOGO_RAW } from './icons.js';
1
2
  export function e(text) {
2
3
  return String(text)
3
4
  .replaceAll('&', '&amp;')
@@ -382,56 +383,72 @@ function langToggleButton(lang) {
382
383
  }
383
384
  export function layout(title, body, lang = DEFAULT_LANG) {
384
385
  const htmlLang = lang === 'zh' ? 'zh-CN' : 'en';
385
- 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>');
386
+ const favicon = encodeURIComponent(BRAND_LOGO_RAW);
386
387
  // 中英文切换按钮临时隐藏(URL ?lang= / localStorage 切换逻辑保留,按钮 UI 不渲染)。
387
388
  // 想恢复:在 body 模板里加回 ${langToggleButton(lang)}。
388
389
  void langToggleButton;
389
- 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>
390
+ const appBar = `<header class="app-bar"><a class="app-brand" href="/"><span class="app-brand-logo">${brandLogo(30)}</span><span class="app-brand-tag">Studio</span></a><span class="app-bar-spacer"></span></header>`;
391
+ 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 · ${e(title)}</title>
390
392
  <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,${favicon}">${globalKeyboardScript()}
391
393
  <style>
392
- /* Pantone-inspired light theme(2026-05 全站浅色化)。
393
- 设计原则:暖白底 + 哑色调,不刺眼;字号 14-15px 起;subtle box-shadow 替代 border。
394
- 旧的深色蓝灰主题已迁移,语义保留但色值翻转。 */
394
+ /* 跨文档 view transition:同源 MPA 导航(如维度 chip 跳转)淡入淡出,消除白屏闪烁(Chromium)。 */
395
+ @view-transition{navigation:auto}
396
+ /* 滚动条始终预留 gutter:短页无滚动条、长页有,切换时内容宽度会跳;stable 让宽度恒定。 */
397
+ html{scrollbar-gutter:stable}
398
+ /* 配色设计(2026-06)。
399
+ 设计原则:冷白底 + indigo 强调色 + 精确匹配参考系统色板。 */
395
400
  :root{
396
- --bg-base:#fbfaf7; /* 暖白纸感 */
401
+ --bg-base:rgb(246,248,251); /* 页面底 */
397
402
  --bg-surface:#ffffff; /* 卡片白 */
398
- --bg-elevated:rgba(58,58,58,.025);
399
- --bg-soft:rgba(58,58,58,.04);
400
- --border:#e8e3da; /* 暖灰分隔 */
401
- --border-hover:#d4ccbf;
402
- --text-primary:#3a3a3a; /* 深炭灰 */
403
- --text-secondary:#7a7a7a;
404
- --text-muted:#a8a8a8;
405
- --text-faint:#c8c8c8;
406
- --accent:#5a7a93; /* 板岩蓝(slate) */
407
- --accent-hover:#3f5d76;
408
- --green:#5e8252; /* 鼠尾草绿(sage) */
409
- --green-bg:rgba(94,130,82,.10);
410
- --red:#9c4a3f; /* 砖红土陶(terracotta) */
411
- --red-bg:rgba(156,74,63,.10);
412
- --yellow:#b08030; /* 暖琥珀 */
413
- --yellow-bg:rgba(176,128,48,.10);
414
- --info-bg:rgba(90,122,147,.08);
415
- /* 图表色 — 全部哑色调,跨色相区分但饱和度统一在 ~50% */
416
- --chart-1:#5a7a93;
417
- --chart-2:#7a6b89;
418
- --chart-3:#5e8252;
419
- --chart-4:#b08030;
420
- --chart-5:#9c6478;
421
- --chart-6:#937846;
403
+ --bg-elevated:#f8f9fd; /* 浅面板 */
404
+ --bg-soft:#f8fafc; /* 柔和背景 */
405
+ --border:#e4e8f1; /* 分隔线 */
406
+ --border-hover:#d1d5db;
407
+ --text-primary:#182033; /* 主文字 */
408
+ --text-secondary:#637083; /* 次文字 */
409
+ --text-muted:#9ca3af;
410
+ --text-faint:#b0b8c5;
411
+ --accent:#4f46e5; /* 品牌 indigo-600 */
412
+ --accent-hover:#4338ca;
413
+ --green:#1f9d63; /* 通过绿 */
414
+ --green-bg:rgba(31,157,99,.14);
415
+ --red:#dc2626; /* 失败红 */
416
+ --red-bg:rgba(220,38,38,.14);
417
+ --yellow:#d97706; /* 警告琥珀 */
418
+ --yellow-bg:rgba(217,119,6,.16);
419
+ --info-bg:rgba(79,70,229,.06);
420
+ /* 图表色 */
421
+ --chart-1:#4f46e5;
422
+ --chart-2:#d97706;
423
+ --chart-3:#059669;
424
+ --chart-4:#ec4899;
425
+ --chart-5:#06b6d4;
426
+ --chart-6:#7c3aed;
422
427
  --bg-card:#ffffff;
423
428
  --radius:8px;
424
429
  --radius-lg:12px;
425
- /* 字号上调:正文 14px / 标签 13px / 详情 13px / 微元数据 12px */
430
+ /* 字号 */
426
431
  --fs-micro:12px;
427
432
  --fs-detail:13px;
428
433
  --fs-label:13px;
429
- --fs-body:14.5px;
430
- --shadow-sm:0 1px 3px rgba(58,58,58,.06);
431
- --shadow-md:0 2px 8px rgba(58,58,58,.10);
434
+ --fs-body:14px;
435
+ --shadow-sm:0 8px 24px rgba(31,41,55,.04);
436
+ --shadow-md:0 8px 28px rgba(79,70,229,.08);
432
437
  }
433
438
  *{box-sizing:border-box;margin:0}
434
- body{font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei","Segoe UI",Roboto,sans-serif;padding:32px;background:var(--bg-base);color:var(--text-primary);min-height:100vh;line-height:1.7;max-width:1440px;margin:0 auto;font-size:var(--fs-body)}
439
+ body{font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei","Segoe UI",Roboto,sans-serif;padding:0;background:var(--bg-base);color:var(--text-primary);min-height:100vh;line-height:1.7;margin:0;font-size:var(--fs-body);letter-spacing:-.005em}
440
+
441
+ /* ── 常驻品牌栏(白玻璃,无菜单)— 让品牌身份贯穿首页与所有详情页 ── */
442
+ .app-bar{position:sticky;top:0;z-index:30;height:52px;background:rgba(255,255,255,.82);backdrop-filter:saturate(180%) blur(12px);-webkit-backdrop-filter:saturate(180%) blur(12px);border-bottom:1px solid var(--border);display:flex;align-items:center;gap:10px;padding:0 22px}
443
+ .app-brand{display:flex;align-items:center;gap:9px;font-weight:650;font-size:15px;letter-spacing:-.02em;color:var(--text-primary);text-decoration:none}
444
+ .app-brand:hover{color:var(--text-primary);text-decoration:none}
445
+ .app-brand-logo{display:inline-flex;align-items:center;flex-shrink:0}
446
+ .app-brand-logo svg{display:block;border-radius:50%}
447
+ .app-brand-tag{font-size:11px;font-weight:600;color:var(--text-muted);border:1px solid var(--border);border-radius:5px;padding:1px 7px;letter-spacing:.02em}
448
+ .app-bar-spacer{flex:1}
449
+ /* 内容容器:居中、留出页边距(原本在 body 上,现下移到 main 容器) */
450
+ .app-main{max-width:1280px;margin:0 auto;padding:18px 20px 24px}
451
+ @media(max-width:768px){.app-main{padding:14px 14px 20px}.app-bar{padding:0 14px}}
435
452
  h1{margin:0 0 8px;font-size:1.75rem;font-weight:600;color:var(--text-primary);letter-spacing:-0.01em;line-height:1.3}
436
453
  h2{margin:32px 0 12px;font-size:1.0625rem;color:var(--text-primary);font-weight:600;line-height:1.4}
437
454
  .subtitle{color:var(--text-secondary);font-size:0.875rem;margin:0 0 24px}
@@ -585,12 +602,12 @@ button.hint-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px
585
602
  颜色严格按 level 编码: PROGRESS 绿, REGRESS 红, CAUTIOUS/UNDERPOWERED 黄,
586
603
  NOISE/SOLO 用 secondary 而非 muted (深底下保证对比度). border-left 4px 是
587
604
  status 视觉信号, 不堆边框/卡片 — 整体融入页面排版. */
588
- .verdict-banner{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;padding:12px 18px;margin:12px 0 0;border-left:4px solid var(--text-secondary);background:rgba(148,163,184,0.06);border-radius:var(--radius)}
589
- .verdict-banner.verdict-PROGRESS{border-left-color:var(--green);background:rgba(74,222,128,0.07)}
590
- .verdict-banner.verdict-REGRESS{border-left-color:var(--red);background:rgba(248,113,113,0.07)}
591
- .verdict-banner.verdict-CAUTIOUS{border-left-color:var(--yellow);background:rgba(251,191,36,0.07)}
592
- .verdict-banner.verdict-UNDERPOWERED{border-left-color:var(--yellow);background:rgba(251,191,36,0.04)}
593
- .verdict-banner.verdict-NOISE{border-left-color:var(--text-secondary);background:rgba(148,163,184,0.06)}
605
+ .verdict-banner{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;padding:12px 18px;margin:12px 0 0;border-left:4px solid var(--text-secondary);background:rgba(99,112,131,.06);border-radius:var(--radius)}
606
+ .verdict-banner.verdict-PROGRESS{border-left-color:var(--green);background:rgba(31,157,99,.07)}
607
+ .verdict-banner.verdict-REGRESS{border-left-color:var(--red);background:rgba(220,38,38,.07)}
608
+ .verdict-banner.verdict-CAUTIOUS{border-left-color:var(--yellow);background:rgba(217,119,6,.07)}
609
+ .verdict-banner.verdict-UNDERPOWERED{border-left-color:var(--yellow);background:rgba(217,119,6,.04)}
610
+ .verdict-banner.verdict-NOISE{border-left-color:var(--text-secondary);background:rgba(99,112,131,.06)}
594
611
  .verdict-banner.verdict-SOLO{border-left-color:var(--border-hover);background:transparent}
595
612
  .verdict-icon{font-size:12px;line-height:1;flex-shrink:0}
596
613
  .verdict-line{font-size:14px;font-weight:500;color:var(--text-primary);line-height:1.6;letter-spacing:-0.005em}
@@ -599,32 +616,28 @@ button.hint-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px
599
616
  行 1: enum + ship-action badge (PROGRESS · SHIP) + 自然语言 ("明显更好,可以发布")
600
617
  行 2: Δ / 95% CI / N / CV — 测量学核心数字, 不需要滚到下方表才看到.
601
618
  颜色按 level 编码 (PROGRESS 绿 / REGRESS 红 / CAUTIOUS+UNDERPOWERED 黄 / NOISE+SOLO 中性). */
602
- .page-verdict{display:flex;flex-direction:column;gap:10px;margin:12px 0 18px;padding:14px 18px;border-left:4px solid var(--text-secondary);background:rgba(148,163,184,0.06);border-radius:var(--radius)}
603
- .page-verdict.verdict-PROGRESS{border-left-color:var(--green);background:rgba(74,222,128,0.07)}
604
- .page-verdict.verdict-REGRESS{border-left-color:var(--red);background:rgba(248,113,113,0.07)}
605
- .page-verdict.verdict-CAUTIOUS{border-left-color:var(--yellow);background:rgba(251,191,36,0.07)}
606
- .page-verdict.verdict-UNDERPOWERED{border-left-color:var(--yellow);background:rgba(251,191,36,0.04)}
607
- .page-verdict.verdict-NOISE{border-left-color:var(--text-secondary);background:rgba(148,163,184,0.06)}
608
- .page-verdict.verdict-SOLO{border-left-color:var(--border-hover);background:transparent}
609
- .page-verdict-head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap}
610
- .page-verdict-badge{display:inline-flex;align-items:center;gap:6px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;font-weight:700;letter-spacing:0.04em;padding:3px 10px;border-radius:14px;background:rgba(148,163,184,0.14);color:var(--text-primary);white-space:nowrap}
611
- .verdict-PROGRESS .page-verdict-badge{background:rgba(74,222,128,0.18);color:var(--green)}
612
- .verdict-REGRESS .page-verdict-badge{background:rgba(248,113,113,0.18);color:var(--red)}
619
+ /* 结论卡内的 verdict —— 不再用「卡中卡」式的 tint 盒子,改成干净的一行结论:
620
+ level 色 chip + 一句话。颜色靠 chip 传达,无外框/无左色条。 */
621
+ .page-verdict{display:flex;flex-direction:column;gap:8px;margin:0 0 14px}
622
+ .page-verdict-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
623
+ .page-verdict-badge{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;font-weight:600;padding:4px 11px;border-radius:13px;background:var(--bg-soft);color:var(--text-secondary);white-space:nowrap;letter-spacing:.01em}
624
+ .verdict-PROGRESS .page-verdict-badge{background:var(--green-bg);color:var(--green)}
625
+ .verdict-REGRESS .page-verdict-badge{background:var(--red-bg);color:var(--red)}
613
626
  .verdict-CAUTIOUS .page-verdict-badge,
614
- .verdict-UNDERPOWERED .page-verdict-badge{background:rgba(251,191,36,0.18);color:var(--yellow)}
627
+ .verdict-UNDERPOWERED .page-verdict-badge{background:var(--yellow-bg);color:var(--yellow)}
615
628
  .verdict-NOISE .page-verdict-badge,
616
- .verdict-SOLO .page-verdict-badge{background:rgba(148,163,184,0.16);color:var(--text-secondary)}
629
+ .verdict-SOLO .page-verdict-badge{background:var(--bg-soft);color:var(--text-secondary)}
617
630
  .page-verdict-badge-dot{font-size:8px;line-height:1}
618
- .page-verdict-text{font-size:15px;font-weight:500;color:var(--text-primary);line-height:1.5;flex:1 1 auto;min-width:0}
631
+ .page-verdict-text{font-size:14.5px;font-weight:500;color:var(--text-primary);line-height:1.55;flex:1 1 auto;min-width:0}
619
632
  .page-verdict-metrics{display:flex;flex-wrap:wrap;gap:10px 20px;align-items:baseline;padding-top:2px}
620
633
  .verdict-metric{display:inline-flex;align-items:baseline;gap:6px}
621
634
  .verdict-metric-label{font-size:11px;color:var(--text-secondary);text-transform:uppercase;letter-spacing:0.06em;font-weight:600}
622
635
  .verdict-metric-value{font-size:15px;font-weight:700;color:var(--text-primary);font-variant-numeric:tabular-nums;letter-spacing:-0.01em}
623
636
 
624
637
  .verdict-cta{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;padding:10px 18px;margin:0;border-left:4px solid var(--accent);background:var(--bg-surface);border-top:1px solid var(--border);border-radius:0}
625
- .verdict-cta.verdict-cta-PROGRESS{border-left-color:var(--green);background:rgba(74,222,128,0.04)}
626
- .verdict-cta.verdict-cta-REGRESS{border-left-color:var(--red);background:rgba(248,113,113,0.04)}
627
- .verdict-cta.verdict-cta-CAUTIOUS{border-left-color:var(--yellow);background:rgba(251,191,36,0.04)}
638
+ .verdict-cta.verdict-cta-PROGRESS{border-left-color:var(--green);background:rgba(31,157,99,.04)}
639
+ .verdict-cta.verdict-cta-REGRESS{border-left-color:var(--red);background:rgba(220,38,38,.04)}
640
+ .verdict-cta.verdict-cta-CAUTIOUS{border-left-color:var(--yellow);background:rgba(217,119,6,.04)}
628
641
  .verdict-cta.verdict-cta-NOISE,
629
642
  .verdict-cta.verdict-cta-UNDERPOWERED,
630
643
  .verdict-cta.verdict-cta-SOLO{border-left-color:var(--text-secondary)}
@@ -642,18 +655,18 @@ button.hint-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px
642
655
  /* v0.21 B.4 — 列表页 RUN ID 旁的 verdict status pill. inline-flex 紧凑 pill,
643
656
  颜色编码同 banner, 字号微小但对比清晰. 鼠标悬停/键盘聚焦时不抢戏 — 它只是
644
657
  "这个 run 是什么 status" 的一眼瞥. */
645
- .run-status{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:600;padding:1px 8px;border-radius:var(--radius);margin-right:8px;line-height:1.5;letter-spacing:-0.005em;white-space:nowrap;color:var(--text-secondary);background:rgba(148,163,184,0.1);vertical-align:1px}
658
+ .run-status{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:600;padding:1px 8px;border-radius:var(--radius);margin-right:8px;line-height:1.5;letter-spacing:-0.005em;white-space:nowrap;color:var(--text-secondary);background:rgba(99,112,131,.1);vertical-align:1px}
646
659
  .run-status .run-status-dot{font-size:8px;line-height:1}
647
- .run-status.verdict-PROGRESS{color:var(--green);background:rgba(74,222,128,0.12)}
648
- .run-status.verdict-REGRESS{color:var(--red);background:rgba(248,113,113,0.12)}
660
+ .run-status.verdict-PROGRESS{color:var(--green);background:rgba(31,157,99,.12)}
661
+ .run-status.verdict-REGRESS{color:var(--red);background:rgba(220,38,38,.12)}
649
662
  .run-status.verdict-CAUTIOUS{color:var(--yellow);background:rgba(251,191,36,0.12)}
650
663
  .run-status.verdict-UNDERPOWERED{color:var(--yellow);background:rgba(251,191,36,0.08)}
651
- .run-status.verdict-NOISE{color:var(--text-secondary);background:rgba(148,163,184,0.1)}
664
+ .run-status.verdict-NOISE{color:var(--text-secondary);background:rgba(99,112,131,.1)}
652
665
  .run-status.verdict-SOLO{color:var(--text-muted);background:transparent;border:1px solid var(--border)}
653
666
 
654
667
  @media print{
655
668
  .verdict-banner,.verdict-cta{break-inside:avoid;page-break-inside:avoid}
656
- .run-status{border:1px solid #cbd5e1;background:transparent !important}
669
+ .run-status{border:1px solid #d1d5db;background:transparent !important}
657
670
  }
658
671
 
659
672
  .modal-overlay{display:none;position:fixed;inset:0;z-index:999;background:rgba(0,0,0,0.6);align-items:center;justify-content:center}
@@ -689,7 +702,7 @@ th{background:var(--bg-elevated);padding:8px 12px;text-align:center;vertical-ali
689
702
  td{padding:7px 12px;border-bottom:1px solid var(--border);color:var(--text-secondary);font-variant-numeric:tabular-nums;text-align:center;vertical-align:middle}
690
703
  td:first-child, th:first-child { text-align:left }
691
704
  tr:last-child td{border-bottom:none}
692
- tr:hover td{background:rgba(148,163,184,0.04)}
705
+ tr:hover td{background:rgba(99,112,131,.04)}
693
706
 
694
707
  /* Badges */
695
708
  .badge{display:inline-block;padding:2px 8px;border-radius:var(--radius);font-size:11px;font-weight:600}
@@ -721,8 +734,8 @@ tr:hover td{background:rgba(148,163,184,0.04)}
721
734
  /* Forms */
722
735
  input[type="text"]{background:var(--bg-surface);border:1px solid var(--border);color:var(--text-primary);border-radius:var(--radius);padding:6px 12px;font-size:13px;font-family:inherit;outline:none;transition:border-color .15s,box-shadow .15s}
723
736
  input[type="text"]:focus{border-color:var(--accent);box-shadow:0 0 0 2px var(--info-bg)}
724
- /* 通用 button — 浅色主题里默认 transparent + 边框更细。子样式(.run-card-delete, .tv-vtab,
725
- .omk-view-tab, .hint-btn 等)各自有显式 reset 覆盖默认样式。 */
737
+ /* 通用 button — 浅色主题里默认 transparent + 边框更细。子样式(.run-card-delete,
738
+ .hint-btn 等)各自有显式 reset 覆盖默认样式。 */
726
739
  button{background:var(--bg-surface);border:1px solid var(--border);color:var(--text-secondary);border-radius:var(--radius);cursor:pointer;padding:6px 14px;font-size:13px;font-family:inherit;transition:border-color .15s,color .15s,background .15s;outline:none;appearance:none;-webkit-appearance:none}
727
740
  button:hover{border-color:var(--border-hover);color:var(--text-primary)}
728
741
  button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@@ -763,7 +776,7 @@ a:focus-visible,.badge:focus-visible{outline:2px solid var(--accent);outline-off
763
776
  .badge-ok,.badge-pass{background:#dcfce7;color:#166534}
764
777
  .badge-err,.badge-fail{background:#fee2e2;color:#991b1b}
765
778
  .badge-muted{background:#f8fafc;color:#94a3b8;border-color:#e2e8f0}
766
- .dim-tag{background:#f1f5f9;color:#3b82f6}
779
+ .dim-tag{background:#eef2ff;color:#6366f1}
767
780
  .meta-tag{background:#f8fafc;border-color:#e2e8f0;color:#475569}
768
781
  .bar-fill{opacity:1}
769
782
  a{color:#1e293b;text-decoration:none}
@@ -771,5 +784,5 @@ a:focus-visible,.badge:focus-visible{outline:2px solid var(--accent);outline-off
771
784
  .hint-tip{display:none}
772
785
  .footer{color:#475569}
773
786
  }
774
- </style></head><body>${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>`;
787
+ </style></head><body>${appBar}<div class="app-main">${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></div>${langToggleScript()}</body></html>`;
775
788
  }