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
@@ -12,20 +12,9 @@
12
12
  * - 报告视觉和 eval HTML 保持一致,读者无学习成本切换
13
13
  */
14
14
  import { confidenceOf } from '../observability/skill-health-analyzer.js';
15
- import { COLORS, e, layout, t } from './layout.js';
16
- const HEALTH_BAND_COLOR = {
17
- green: 'var(--green)',
18
- yellow: 'var(--yellow)',
19
- red: 'var(--red)',
20
- };
21
- const HEALTH_BAND_LABEL = {
22
- green: { zh: '健康', en: 'Healthy' },
23
- yellow: { zh: '待观察', en: 'Watch' },
24
- red: { zh: '需关注', en: 'Attention needed' },
25
- };
26
- function fmtPct(rate, digits = 0) {
27
- return `${(rate * 100).toFixed(digits)}%`;
28
- }
15
+ import { COLORS, e, t } from './layout.js';
16
+ import { icon } from './icons.js';
17
+ import { reportShell } from './report-shell.js';
29
18
  function fmtTimeRange(from, to) {
30
19
  if (!from || !to)
31
20
  return '—';
@@ -34,67 +23,27 @@ function fmtTimeRange(from, to) {
34
23
  return fromDate === toDate ? fromDate : `${fromDate} → ${toDate}`;
35
24
  }
36
25
  /**
37
- * 顶部摘要 + 水印 (spec §六 强制要求)。
26
+ * 数据来源水印 (spec §六 强制要求) + 低 N 可信度提醒。
38
27
  */
39
- function renderHeader(report, lang) {
28
+ function renderWatermark(report, lang) {
40
29
  const { meta, overall } = report;
41
- // Statistical-confidence guard: below the segment threshold a hard health band
42
- // overstates certainty (1 segment + 1 failure judged the same as 50). When the
43
- // overall confidence is not high, mute the colour and append an N caveat.
44
- // Legacy reports (pre-confidence) fall back to deriving from segmentCount, so old
45
- // JSON never renders `undefined confidence`.
46
30
  const confidence = overall.confidence ?? confidenceOf(meta.segmentCount);
47
- const lowConfidence = confidence !== 'high';
48
- const bandColor = confidence === 'underpowered'
49
- ? 'var(--text-faint)'
50
- : HEALTH_BAND_COLOR[overall.healthBand];
51
- // underpowered 时色带已静音为灰,标签也不报硬结论(需关注 / 健康),改为「样本不足」,跟灰底 + caveat 一致。
52
- const bandLabel = confidence === 'underpowered'
53
- ? (lang === 'zh' ? '样本不足' : 'Insufficient N')
54
- : HEALTH_BAND_LABEL[overall.healthBand][lang === 'zh' ? 'zh' : 'en'];
55
- const confCaveat = lowConfidence
56
- ? `<div class="card-sub" style="color:var(--text-faint)">${lang === 'zh'
31
+ const confCaveat = confidence !== 'high'
32
+ ? `<div style="color:var(--text-faint);margin-top:6px">${lang === 'zh'
57
33
  ? `⚠ 样本量 ${meta.segmentCount} 段,可信度${confidence === 'underpowered' ? '不足' : '偏低'},色带仅供参考`
58
34
  : `⚠ N=${meta.segmentCount} segments — ${confidence} confidence; band is indicative`}</div>`
59
35
  : '';
60
36
  const tracePath = e(meta.tracePath);
61
37
  const kbPath = meta.kbPath ? e(meta.kbPath) : '—';
62
- const timeRange = fmtTimeRange(meta.timeRange.from, meta.timeRange.to);
63
38
  const warning = lang === 'zh'
64
- ? '本报告仅反映指定时间窗内观察到的 skill 使用情况,不代表 skill 的绝对质量,也不能替代 offline eval 的对照验证。'
39
+ ? '本报告仅反映指定时间窗内观察到的 skill 使用情况,不代表 skill 的绝对质量,也不能替代 offline eval 的对照验证。'
65
40
  : 'Report reflects only observed skill usage in the given window. Does not imply absolute skill quality, does not replace offline eval.';
66
- return `
67
- <h1>${lang === 'zh' ? 'Skill 健康度日报' : 'Skill Health Daily'}</h1>
68
- <p class="subtitle">${lang === 'zh' ? 'omk · 生产观察' : 'omk · Production Observability'}</p>
69
-
70
- <div class="cards" style="margin-bottom:20px">
71
- <div class="card" style="flex:0 0 auto;min-width:160px;border-left:4px solid ${bandColor}">
72
- <div class="card-label">${lang === 'zh' ? '整体健康度' : 'Overall health'}</div>
73
- <div class="card-value" style="color:${bandColor}">${bandLabel}</div>
74
- <div class="card-sub">${lang === 'zh' ? '加权盲区' : 'weighted gap'} ${fmtPct(overall.weightedGapRate, 1)} · ${lang === 'zh' ? '原始盲区' : 'raw gap'} ${fmtPct(overall.gapRate, 1)}</div>
75
- ${confCaveat}
76
- </div>
77
- <div class="card">
78
- <div class="card-label">${lang === 'zh' ? '会话 / 段 / 工具调用' : 'Sessions / Segments / Tool calls'}</div>
79
- <div class="card-value" style="font-size:18px">${meta.sessionCount} / ${meta.segmentCount} / ${meta.toolCallCount}</div>
80
- <div class="card-sub">${lang === 'zh' ? '工具失败率' : 'tool fail rate'} ${fmtPct(meta.toolFailureRate, 1)} · ${meta.messageCount.toLocaleString()} ${lang === 'zh' ? '条消息' : 'messages'}</div>
81
- </div>
82
- <div class="card">
83
- <div class="card-label">${lang === 'zh' ? '时间窗' : 'Time window'}</div>
84
- <div class="card-value" style="font-size:18px">${timeRange}</div>
85
- <div class="card-sub">${lang === 'zh' ? '生成于' : 'generated'} ${new Date(meta.generatedAt).toISOString().split('T')[0]}</div>
86
- </div>
87
- </div>
88
-
89
- <div style="padding:10px 14px;background:var(--info-bg);border-left:3px solid var(--accent);border-radius:var(--radius);margin-bottom:20px;font-size:12px;line-height:1.6">
90
- <div style="color:var(--text-secondary);margin-bottom:4px"><strong>${lang === 'zh' ? '水印' : 'Watermark'}</strong> (spec §六)</div>
91
- <div style="color:var(--text-muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px">
92
- trace: ${tracePath}<br>
93
- kb: ${kbPath}
94
- </div>
41
+ return `<div class="rs-panel" style="background:var(--info-bg);font-size:12px;line-height:1.6">
42
+ <div style="color:var(--text-secondary);margin-bottom:4px;font-weight:600">${lang === 'zh' ? '数据来源' : 'Source'}</div>
43
+ <div style="color:var(--text-muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px">trace: ${tracePath}<br>kb: ${kbPath}</div>
95
44
  <div style="color:var(--text-muted);margin-top:6px;font-style:italic">${warning}</div>
96
- </div>
97
- `.trim();
45
+ ${confCaveat}
46
+ </div>`;
98
47
  }
99
48
  /**
100
49
  * 每 skill 一张 card (复用 v0.17 A 的 ki-card 结构)。
@@ -262,20 +211,48 @@ function renderDeadKbSection(report, lang) {
262
211
  * 主入口: 生成完整 HTML。
263
212
  */
264
213
  export function renderSkillHealthReport(report, lang = 'zh') {
265
- const title = lang === 'zh' ? 'Skill 健康度日报' : 'Skill Health Daily';
266
- // 按 segmentCount 降序排(使用量大的 skill 在前)
214
+ const zh = lang === 'zh';
215
+ const { meta, overall } = report;
216
+ const confidence = overall.confidence ?? confidenceOf(meta.segmentCount);
217
+ // 整体健康分 = (1 - 加权盲区) × 100;underpowered 时不给硬分。
218
+ const score = confidence === 'underpowered' ? null : Math.round((1 - overall.weightedGapRate) * 100);
219
+ const scoreLabel = score == null
220
+ ? (zh ? '样本不足' : 'Low N')
221
+ : overall.healthBand === 'green' ? (zh ? '健康' : 'Healthy')
222
+ : overall.healthBand === 'yellow' ? (zh ? '待观察' : 'Watch')
223
+ : (zh ? '需关注' : 'Attention');
267
224
  const skillsSorted = Object.values(report.bySkill).sort((a, b) => b.segmentCount - a.segmentCount);
268
225
  const cards = skillsSorted
269
226
  .map((skill, i) => renderSkillCard(skill, COLORS[i % COLORS.length], lang))
270
227
  .join('\n');
228
+ const statsBar = `<div class="rs-stats">
229
+ <div class="rs-stat rs-stat--total"><span class="rs-stat-num">${meta.sessionCount}</span><span class="rs-stat-label">${zh ? '会话' : 'Sessions'}</span></div>
230
+ <div class="rs-stat rs-stat--total"><span class="rs-stat-num">${meta.segmentCount}</span><span class="rs-stat-label">${zh ? '段' : 'Segments'}</span></div>
231
+ <div class="rs-stat rs-stat--total"><span class="rs-stat-num">${meta.toolCallCount}</span><span class="rs-stat-label">${zh ? '工具调用' : 'Tool calls'}</span></div>
232
+ <div class="rs-stat ${overall.weightedGapRate >= 0.3 ? 'rs-stat--fail' : overall.weightedGapRate >= 0.1 ? 'rs-stat--warn' : 'rs-stat--pass'}"><span class="rs-stat-num">${Math.round(overall.weightedGapRate * 100)}%</span><span class="rs-stat-label">${zh ? '加权盲区' : 'Weighted gap'}</span></div>
233
+ </div>`;
271
234
  const body = [
272
- renderHeader(report, lang),
273
- `<section style="margin-top:28px">
274
- <h2>${lang === 'zh' ? '各 skill 健康度' : 'Per-skill health'}</h2>
275
- <p class="ki-desc">${lang === 'zh' ? '按使用量降序。每个 skill 的 coverage 和 gap 独立统计。' : 'Sorted by usage. Coverage and gap are independently computed per skill.'}</p>
276
- ${cards}
277
- </section>`,
235
+ statsBar,
236
+ renderWatermark(report, lang),
237
+ `<div class="rs-panel">
238
+ <div class="rs-panel-title">${zh ? '各 skill 健康度' : 'Per-skill health'} <small>${zh ? '按使用量降序' : 'sorted by usage'}</small></div>
239
+ ${cards || `<div class="rs-empty">${zh ? '本期无 skill 数据' : 'No skill data'}</div>`}
240
+ </div>`,
278
241
  renderDeadKbSection(report, lang),
279
242
  ].filter(Boolean).join('\n');
280
- return layout(title, body, lang);
243
+ return reportShell({
244
+ dim: 'observe',
245
+ icon: '👁',
246
+ kindTitle: zh ? '生产观察报告' : 'Observe Report',
247
+ skillName: zh ? 'Skill 健康度日报' : 'Skill Health Daily',
248
+ metaItems: [
249
+ `${icon('clock', { size: 13 })} ${fmtTimeRange(meta.timeRange.from, meta.timeRange.to)}`,
250
+ `${icon('calendar', { size: 13 })} ${new Date(meta.generatedAt).toISOString().slice(0, 16).replace('T', ' ')}`,
251
+ ],
252
+ score,
253
+ scoreLabel,
254
+ backHref: `/${lang === 'zh' ? '' : '?lang=en'}`,
255
+ backLabel: zh ? '返回工作台' : 'Back to dashboard',
256
+ body,
257
+ }, lang);
281
258
  }