oh-my-knowledge 0.28.0 → 0.30.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.
- package/README.md +49 -3
- package/README.zh.md +49 -3
- package/dist/src/analysis/failure-clusterer.js +1 -1
- package/dist/src/analysis/failure-clusterer.js.map +1 -1
- package/dist/src/analysis/gap-analyzer.d.ts +8 -1
- package/dist/src/analysis/gap-analyzer.d.ts.map +1 -1
- package/dist/src/analysis/gap-analyzer.js +65 -33
- package/dist/src/analysis/gap-analyzer.js.map +1 -1
- package/dist/src/analysis/report-diagnostics.js +2 -0
- package/dist/src/analysis/report-diagnostics.js.map +1 -1
- package/dist/src/analysis/sample-diagnostics.js +14 -14
- package/dist/src/analysis/sample-diagnostics.js.map +1 -1
- package/dist/src/authoring/evolver.d.ts +7 -1
- package/dist/src/authoring/evolver.d.ts.map +1 -1
- package/dist/src/authoring/evolver.js +8 -5
- package/dist/src/authoring/evolver.js.map +1 -1
- package/dist/src/authoring/generator.d.ts +21 -23
- package/dist/src/authoring/generator.d.ts.map +1 -1
- package/dist/src/authoring/generator.js +621 -40
- package/dist/src/authoring/generator.js.map +1 -1
- package/dist/src/authoring/sample-fixer.d.ts +45 -0
- package/dist/src/authoring/sample-fixer.d.ts.map +1 -0
- package/dist/src/authoring/sample-fixer.js +186 -0
- package/dist/src/authoring/sample-fixer.js.map +1 -0
- package/dist/src/cli/commands/evolve.d.ts.map +1 -1
- package/dist/src/cli/commands/evolve.js +17 -0
- package/dist/src/cli/commands/evolve.js.map +1 -1
- package/dist/src/cli/commands/observe.d.ts.map +1 -1
- package/dist/src/cli/commands/observe.js +170 -0
- package/dist/src/cli/commands/observe.js.map +1 -1
- package/dist/src/cli/commands/registry.d.ts.map +1 -1
- package/dist/src/cli/commands/registry.js +9 -1
- package/dist/src/cli/commands/registry.js.map +1 -1
- package/dist/src/cli/commands/sample.d.ts +13 -0
- package/dist/src/cli/commands/sample.d.ts.map +1 -1
- package/dist/src/cli/commands/sample.js +307 -13
- package/dist/src/cli/commands/sample.js.map +1 -1
- package/dist/src/cli/commands/studio.d.ts.map +1 -1
- package/dist/src/cli/commands/studio.js +8 -0
- package/dist/src/cli/commands/studio.js.map +1 -1
- package/dist/src/cli/i18n-dict.d.ts +1 -1
- package/dist/src/cli/i18n-dict.d.ts.map +1 -1
- package/dist/src/cli/i18n-dict.js +189 -17
- package/dist/src/cli/i18n-dict.js.map +1 -1
- package/dist/src/cli/parse-run-config.d.ts +14 -2
- package/dist/src/cli/parse-run-config.d.ts.map +1 -1
- package/dist/src/cli/parse-run-config.js +62 -10
- package/dist/src/cli/parse-run-config.js.map +1 -1
- package/dist/src/doctor/health/builtin-dimensions.d.ts.map +1 -1
- package/dist/src/doctor/health/builtin-dimensions.js +20 -23
- package/dist/src/doctor/health/builtin-dimensions.js.map +1 -1
- package/dist/src/doctor/health/composer.d.ts.map +1 -1
- package/dist/src/doctor/health/composer.js +7 -3
- package/dist/src/doctor/health/composer.js.map +1 -1
- package/dist/src/doctor/health/dimension-spec.d.ts +1 -0
- package/dist/src/doctor/health/dimension-spec.d.ts.map +1 -1
- package/dist/src/doctor/health/parser.d.ts.map +1 -1
- package/dist/src/doctor/health/parser.js +1 -0
- package/dist/src/doctor/health/parser.js.map +1 -1
- package/dist/src/doctor/health/prompt-builder.js +25 -17
- package/dist/src/doctor/health/prompt-builder.js.map +1 -1
- package/dist/src/doctor/html-renderer.d.ts.map +1 -1
- package/dist/src/doctor/html-renderer.js +76 -66
- package/dist/src/doctor/html-renderer.js.map +1 -1
- package/dist/src/doctor/rules.d.ts.map +1 -1
- package/dist/src/doctor/rules.js +32 -0
- package/dist/src/doctor/rules.js.map +1 -1
- package/dist/src/eval-core/cache.d.ts +16 -2
- package/dist/src/eval-core/cache.d.ts.map +1 -1
- package/dist/src/eval-core/cache.js +86 -15
- package/dist/src/eval-core/cache.js.map +1 -1
- package/dist/src/eval-core/evaluation-execution.d.ts +11 -1
- package/dist/src/eval-core/evaluation-execution.d.ts.map +1 -1
- package/dist/src/eval-core/evaluation-execution.js +78 -6
- package/dist/src/eval-core/evaluation-execution.js.map +1 -1
- package/dist/src/eval-core/evaluation-job.d.ts +2 -1
- package/dist/src/eval-core/evaluation-job.d.ts.map +1 -1
- package/dist/src/eval-core/evaluation-job.js +2 -1
- package/dist/src/eval-core/evaluation-job.js.map +1 -1
- package/dist/src/eval-core/evaluation-reporting.d.ts +7 -0
- package/dist/src/eval-core/evaluation-reporting.d.ts.map +1 -1
- package/dist/src/eval-core/evaluation-reporting.js +19 -2
- package/dist/src/eval-core/evaluation-reporting.js.map +1 -1
- package/dist/src/eval-core/execution-strategy.d.ts +1 -1
- package/dist/src/eval-core/execution-strategy.d.ts.map +1 -1
- package/dist/src/eval-core/execution-strategy.js +12 -1
- package/dist/src/eval-core/execution-strategy.js.map +1 -1
- package/dist/src/eval-core/mock-hook.cjs +203 -0
- package/dist/src/eval-core/mocks-runtime.d.ts +96 -0
- package/dist/src/eval-core/mocks-runtime.d.ts.map +1 -0
- package/dist/src/eval-core/mocks-runtime.js +323 -0
- package/dist/src/eval-core/mocks-runtime.js.map +1 -0
- package/dist/src/eval-core/schema.d.ts.map +1 -1
- package/dist/src/eval-core/schema.js +18 -5
- package/dist/src/eval-core/schema.js.map +1 -1
- package/dist/src/eval-core/task-planner.d.ts +9 -1
- package/dist/src/eval-core/task-planner.d.ts.map +1 -1
- package/dist/src/eval-core/task-planner.js +40 -1
- package/dist/src/eval-core/task-planner.js.map +1 -1
- package/dist/src/eval-workflows/batch-evaluation-workflow.d.ts +5 -1
- package/dist/src/eval-workflows/batch-evaluation-workflow.d.ts.map +1 -1
- package/dist/src/eval-workflows/batch-evaluation-workflow.js +2 -1
- package/dist/src/eval-workflows/batch-evaluation-workflow.js.map +1 -1
- package/dist/src/eval-workflows/evaluation-pipeline.d.ts +22 -1
- package/dist/src/eval-workflows/evaluation-pipeline.d.ts.map +1 -1
- package/dist/src/eval-workflows/evaluation-pipeline.js +39 -12
- package/dist/src/eval-workflows/evaluation-pipeline.js.map +1 -1
- package/dist/src/eval-workflows/evaluation-preparation.d.ts +5 -0
- package/dist/src/eval-workflows/evaluation-preparation.d.ts.map +1 -1
- package/dist/src/eval-workflows/evaluation-preparation.js +3 -1
- package/dist/src/eval-workflows/evaluation-preparation.js.map +1 -1
- package/dist/src/eval-workflows/run-evaluation.d.ts +12 -2
- package/dist/src/eval-workflows/run-evaluation.d.ts.map +1 -1
- package/dist/src/eval-workflows/run-evaluation.js +17 -5
- package/dist/src/eval-workflows/run-evaluation.js.map +1 -1
- package/dist/src/executors/claude-cli.d.ts +1 -1
- package/dist/src/executors/claude-cli.d.ts.map +1 -1
- package/dist/src/executors/claude-cli.js +57 -6
- package/dist/src/executors/claude-cli.js.map +1 -1
- package/dist/src/executors/claude-sdk-trace.d.ts.map +1 -1
- package/dist/src/executors/claude-sdk-trace.js +10 -4
- package/dist/src/executors/claude-sdk-trace.js.map +1 -1
- package/dist/src/executors/claude-sdk.d.ts +1 -1
- package/dist/src/executors/claude-sdk.d.ts.map +1 -1
- package/dist/src/executors/claude-sdk.js +25 -2
- package/dist/src/executors/claude-sdk.js.map +1 -1
- package/dist/src/executors/shared.d.ts +1 -1
- package/dist/src/executors/shared.d.ts.map +1 -1
- package/dist/src/executors/shared.js +6 -1
- package/dist/src/executors/shared.js.map +1 -1
- package/dist/src/grading/assertions.d.ts +5 -0
- package/dist/src/grading/assertions.d.ts.map +1 -1
- package/dist/src/grading/assertions.js +27 -1
- package/dist/src/grading/assertions.js.map +1 -1
- package/dist/src/grading/debias-validate.js +4 -4
- package/dist/src/grading/debias-validate.js.map +1 -1
- package/dist/src/grading/diagnostic.d.ts +40 -0
- package/dist/src/grading/diagnostic.d.ts.map +1 -0
- package/dist/src/grading/diagnostic.js +450 -0
- package/dist/src/grading/diagnostic.js.map +1 -0
- package/dist/src/grading/gold-cli.js +2 -2
- package/dist/src/grading/gold-cli.js.map +1 -1
- package/dist/src/grading/index.d.ts +5 -0
- package/dist/src/grading/index.d.ts.map +1 -1
- package/dist/src/grading/judge.d.ts.map +1 -1
- package/dist/src/grading/judge.js +54 -2
- package/dist/src/grading/judge.js.map +1 -1
- package/dist/src/grading/layered-scores.d.ts.map +1 -1
- package/dist/src/grading/layered-scores.js +1 -0
- package/dist/src/grading/layered-scores.js.map +1 -1
- package/dist/src/inputs/eval-config.js +19 -0
- package/dist/src/inputs/eval-config.js.map +1 -1
- package/dist/src/inputs/load-samples.d.ts +22 -2
- package/dist/src/inputs/load-samples.d.ts.map +1 -1
- package/dist/src/inputs/load-samples.js +193 -22
- package/dist/src/inputs/load-samples.js.map +1 -1
- package/dist/src/inputs/skill-loader.d.ts.map +1 -1
- package/dist/src/inputs/skill-loader.js +11 -3
- package/dist/src/inputs/skill-loader.js.map +1 -1
- package/dist/src/observability/experience.d.ts +260 -0
- package/dist/src/observability/experience.d.ts.map +1 -0
- package/dist/src/observability/experience.js +1233 -0
- package/dist/src/observability/experience.js.map +1 -0
- package/dist/src/observability/inbox-view-model.d.ts +27 -0
- package/dist/src/observability/inbox-view-model.d.ts.map +1 -0
- package/dist/src/observability/inbox-view-model.js +135 -0
- package/dist/src/observability/inbox-view-model.js.map +1 -0
- package/dist/src/observability/inbox.d.ts +125 -0
- package/dist/src/observability/inbox.d.ts.map +1 -0
- package/dist/src/observability/inbox.js +741 -0
- package/dist/src/observability/inbox.js.map +1 -0
- package/dist/src/observability/problem-patterns.d.ts +51 -0
- package/dist/src/observability/problem-patterns.d.ts.map +1 -0
- package/dist/src/observability/problem-patterns.js +205 -0
- package/dist/src/observability/problem-patterns.js.map +1 -0
- package/dist/src/observability/review-state.d.ts +54 -0
- package/dist/src/observability/review-state.d.ts.map +1 -0
- package/dist/src/observability/review-state.js +131 -0
- package/dist/src/observability/review-state.js.map +1 -0
- package/dist/src/observability/skill-chain-advisories.d.ts +25 -0
- package/dist/src/observability/skill-chain-advisories.d.ts.map +1 -0
- package/dist/src/observability/skill-chain-advisories.js +69 -0
- package/dist/src/observability/skill-chain-advisories.js.map +1 -0
- package/dist/src/observability/skill-chain.d.ts +61 -0
- package/dist/src/observability/skill-chain.d.ts.map +1 -0
- package/dist/src/observability/skill-chain.js +233 -0
- package/dist/src/observability/skill-chain.js.map +1 -0
- package/dist/src/observability/text-signals.d.ts +7 -0
- package/dist/src/observability/text-signals.d.ts.map +1 -0
- package/dist/src/observability/text-signals.js +22 -0
- package/dist/src/observability/text-signals.js.map +1 -0
- package/dist/src/observability/trace-adapter.d.ts +12 -64
- package/dist/src/observability/trace-adapter.d.ts.map +1 -1
- package/dist/src/observability/trace-adapter.js +9 -355
- package/dist/src/observability/trace-adapter.js.map +1 -1
- package/dist/src/observability/trace-attribution.d.ts +56 -0
- package/dist/src/observability/trace-attribution.d.ts.map +1 -0
- package/dist/src/observability/trace-attribution.js +200 -0
- package/dist/src/observability/trace-attribution.js.map +1 -0
- package/dist/src/observability/trace-segmenter.d.ts +52 -0
- package/dist/src/observability/trace-segmenter.d.ts.map +1 -0
- package/dist/src/observability/trace-segmenter.js +320 -0
- package/dist/src/observability/trace-segmenter.js.map +1 -0
- package/dist/src/observability/trace-source.d.ts +99 -0
- package/dist/src/observability/trace-source.d.ts.map +1 -0
- package/dist/src/observability/trace-source.js +492 -0
- package/dist/src/observability/trace-source.js.map +1 -0
- package/dist/src/renderer/html-renderer.d.ts.map +1 -1
- package/dist/src/renderer/html-renderer.js +324 -218
- package/dist/src/renderer/html-renderer.js.map +1 -1
- package/dist/src/renderer/layout.d.ts.map +1 -1
- package/dist/src/renderer/layout.js +155 -71
- package/dist/src/renderer/layout.js.map +1 -1
- package/dist/src/renderer/observation-inbox-renderer.d.ts +4 -0
- package/dist/src/renderer/observation-inbox-renderer.d.ts.map +1 -0
- package/dist/src/renderer/observation-inbox-renderer.js +5376 -0
- package/dist/src/renderer/observation-inbox-renderer.js.map +1 -0
- package/dist/src/renderer/skill-detail-renderer.d.ts +15 -0
- package/dist/src/renderer/skill-detail-renderer.d.ts.map +1 -0
- package/dist/src/renderer/skill-detail-renderer.js +1234 -0
- package/dist/src/renderer/skill-detail-renderer.js.map +1 -0
- package/dist/src/renderer/skill-list-renderer.d.ts +4 -0
- package/dist/src/renderer/skill-list-renderer.d.ts.map +1 -0
- package/dist/src/renderer/skill-list-renderer.js +327 -0
- package/dist/src/renderer/skill-list-renderer.js.map +1 -0
- package/dist/src/renderer/summary.d.ts +17 -0
- package/dist/src/renderer/summary.d.ts.map +1 -1
- package/dist/src/renderer/summary.js +346 -74
- package/dist/src/renderer/summary.js.map +1 -1
- package/dist/src/renderer/table.d.ts.map +1 -1
- package/dist/src/renderer/table.js +213 -167
- package/dist/src/renderer/table.js.map +1 -1
- package/dist/src/renderer/test-view.d.ts +66 -0
- package/dist/src/renderer/test-view.d.ts.map +1 -0
- package/dist/src/renderer/test-view.js +905 -0
- package/dist/src/renderer/test-view.js.map +1 -0
- package/dist/src/renderer/trends.d.ts.map +1 -1
- package/dist/src/renderer/trends.js +3 -1
- package/dist/src/renderer/trends.js.map +1 -1
- package/dist/src/server/report-server.d.ts +6 -1
- package/dist/src/server/report-server.d.ts.map +1 -1
- package/dist/src/server/report-server.js +182 -6
- package/dist/src/server/report-server.js.map +1 -1
- package/dist/src/server/report-store.d.ts.map +1 -1
- package/dist/src/server/report-store.js +33 -1
- package/dist/src/server/report-store.js.map +1 -1
- package/dist/src/server/skill-index.d.ts +77 -0
- package/dist/src/server/skill-index.d.ts.map +1 -0
- package/dist/src/server/skill-index.js +331 -0
- package/dist/src/server/skill-index.js.map +1 -0
- package/dist/src/server/skill-insights.d.ts +92 -0
- package/dist/src/server/skill-insights.d.ts.map +1 -0
- package/dist/src/server/skill-insights.js +676 -0
- package/dist/src/server/skill-insights.js.map +1 -0
- package/dist/src/shared/hard-rules.d.ts +40 -0
- package/dist/src/shared/hard-rules.d.ts.map +1 -0
- package/dist/src/shared/hard-rules.js +200 -0
- package/dist/src/shared/hard-rules.js.map +1 -0
- package/dist/src/shared/time.d.ts +2 -0
- package/dist/src/shared/time.d.ts.map +1 -0
- package/dist/src/shared/time.js +10 -0
- package/dist/src/shared/time.js.map +1 -0
- package/dist/src/shared/tool-search.d.ts +9 -0
- package/dist/src/shared/tool-search.d.ts.map +1 -0
- package/dist/src/shared/tool-search.js +104 -0
- package/dist/src/shared/tool-search.js.map +1 -0
- package/dist/src/types/eval.d.ts +83 -0
- package/dist/src/types/eval.d.ts.map +1 -1
- package/dist/src/types/executor.d.ts +47 -0
- package/dist/src/types/executor.d.ts.map +1 -1
- package/dist/src/types/judge.d.ts +76 -0
- package/dist/src/types/judge.d.ts.map +1 -1
- package/dist/src/types/judge.js +3 -1
- package/dist/src/types/judge.js.map +1 -1
- package/dist/src/types/report.d.ts +63 -3
- package/dist/src/types/report.d.ts.map +1 -1
- package/dist/src/util/safe-slice.d.ts +23 -0
- package/dist/src/util/safe-slice.d.ts.map +1 -0
- package/dist/src/util/safe-slice.js +33 -0
- package/dist/src/util/safe-slice.js.map +1 -0
- package/package.json +5 -4
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Default implementation: local file system.
|
|
4
4
|
* Can be replaced with database, S3, etc.
|
|
5
5
|
*/
|
|
6
|
-
import { readdir, readFile, writeFile, unlink, access, mkdir, rename } from 'node:fs/promises';
|
|
6
|
+
import { readdir, readFile, writeFile, unlink, access, mkdir, rename, stat } from 'node:fs/promises';
|
|
7
7
|
import { join } from 'node:path';
|
|
8
8
|
// Per-id in-memory mutex for safe read-modify-write.
|
|
9
9
|
// Uses a queue to avoid the race window between checking and acquiring the lock.
|
|
@@ -66,6 +66,31 @@ export function createFileStore(dir) {
|
|
|
66
66
|
function isEvaluationReport(report) {
|
|
67
67
|
return report.kind === 'evaluation';
|
|
68
68
|
}
|
|
69
|
+
// Studio 每个 / 和 /skills/<name> 请求都调 list(),里面对每个 .json 同步 readFile +
|
|
70
|
+
// JSON.parse。报告数上来后这是主性能瓶颈。缓存策略:fingerprint = dir mtime + 文件名
|
|
71
|
+
// 排序串 + 每个文件 mtime;任一变化 invalidate。fingerprint 算 cheap(只 stat),命中后
|
|
72
|
+
// 完全跳过 readFile。
|
|
73
|
+
let cachedFingerprint = '';
|
|
74
|
+
let cachedRuns = null;
|
|
75
|
+
async function computeListFingerprint() {
|
|
76
|
+
try {
|
|
77
|
+
const dirStat = await stat(dir);
|
|
78
|
+
const files = (await readdir(dir)).filter((f) => f.endsWith('.json')).sort();
|
|
79
|
+
const parts = await Promise.all(files.map(async (f) => {
|
|
80
|
+
try {
|
|
81
|
+
const s = await stat(join(dir, f));
|
|
82
|
+
return `${f}:${s.mtimeMs}:${s.size}`;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return `${f}:?`;
|
|
86
|
+
}
|
|
87
|
+
}));
|
|
88
|
+
return `${dirStat.mtimeMs}|${parts.join(',')}`;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
69
94
|
async function list() {
|
|
70
95
|
try {
|
|
71
96
|
await access(dir);
|
|
@@ -73,6 +98,9 @@ export function createFileStore(dir) {
|
|
|
73
98
|
catch {
|
|
74
99
|
return [];
|
|
75
100
|
}
|
|
101
|
+
const fp = await computeListFingerprint();
|
|
102
|
+
if (fp != null && fp === cachedFingerprint && cachedRuns)
|
|
103
|
+
return cachedRuns;
|
|
76
104
|
const files = (await readdir(dir))
|
|
77
105
|
.filter((f) => f.endsWith('.json'))
|
|
78
106
|
.sort()
|
|
@@ -92,6 +120,10 @@ export function createFileStore(dir) {
|
|
|
92
120
|
const tb = b.meta?.timestamp || '';
|
|
93
121
|
return tb.localeCompare(ta);
|
|
94
122
|
});
|
|
123
|
+
if (fp != null) {
|
|
124
|
+
cachedFingerprint = fp;
|
|
125
|
+
cachedRuns = runs;
|
|
126
|
+
}
|
|
95
127
|
return runs;
|
|
96
128
|
}
|
|
97
129
|
async function get(id) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report-store.js","sourceRoot":"","sources":["../../../src/server/report-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"report-store.js","sourceRoot":"","sources":["../../../src/server/report-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACrG,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,qDAAqD;AACrD,iFAAiF;AACjF,MAAM,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAC;AAE/C,KAAK,UAAU,QAAQ,CAAI,EAAU,EAAE,EAAoB;IACzD,uEAAuE;IACvE,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAChD,IAAI,WAAwB,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACpB,MAAM,IAAI,CAAC;IACX,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACjB,WAAW,EAAE,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,KAAK,UAAU,SAAS;QACtB,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,SAAS,uBAAuB,CAAC,IAAa,EAAE,UAAkB;QAChE,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QACnD,MAAM,MAAM,GAAG,IAA+B,CAAC;QAC/C,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACjC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;gBAAE,OAAO,IAAI,CAAC;YACnF,OAAO,EAAE,GAAG,MAAM,EAAE,EAAE,EAAE,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,EAA+B,CAAC;QAC7H,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;YACvC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC9D,OAAO,EAAE,GAAG,MAAM,EAAE,EAAE,EAAE,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,EAA+B,CAAC;QAC7H,CAAC;QACD,IACE,MAAM,CAAC,IAAI,KAAK,SAAS;eACtB,MAAM,CAAC,QAAQ,KAAK,SAAS;eAC7B,MAAM,CAAC,SAAS,KAAK,SAAS;eAC9B,MAAM,CAAC,IAAI;eACX,MAAM,CAAC,OAAO;eACd,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAChC,CAAC;YACD,OAAO;gBACL,GAAG,MAAM;gBACT,IAAI,EAAE,YAAY;gBAClB,EAAE,EAAE,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU;aAC3C,CAAC;QACjC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,SAAS,kBAAkB,CAAC,MAAsB;QAChD,OAAO,MAAM,CAAC,IAAI,KAAK,YAAY,CAAC;IACtC,CAAC;IAED,qEAAqE;IACrE,8DAA8D;IAC9D,mEAAmE;IACnE,iBAAiB;IACjB,IAAI,iBAAiB,GAAG,EAAE,CAAC;IAC3B,IAAI,UAAU,GAA4B,IAAI,CAAC;IAC/C,KAAK,UAAU,sBAAsB;QACnC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;YAChC,MAAM,KAAK,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7E,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;gBACpD,IAAI,CAAC;oBACH,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;oBACnC,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;gBACvC,CAAC;gBAAC,MAAM,CAAC;oBAAC,OAAO,GAAG,CAAC,IAAI,CAAC;gBAAC,CAAC;YAC9B,CAAC,CAAC,CAAC,CAAC;YACJ,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;IAC1B,CAAC;IAED,KAAK,UAAU,IAAI;QACjB,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,EAAE,GAAG,MAAM,sBAAsB,EAAE,CAAC;QAC1C,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,KAAK,iBAAiB,IAAI,UAAU;YAAE,OAAO,UAAU,CAAC;QAE5E,MAAM,KAAK,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;aAC/B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;aAClC,IAAI,EAAE;aACN,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,GAAqB,EAAE,CAAC;QAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;gBAClE,MAAM,MAAM,GAAG,uBAAuB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;gBAC1E,IAAI,MAAM;oBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC,CAAC,wBAAwB,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACjB,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,SAAS,IAAI,EAAE,CAAC;YACnC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,SAAS,IAAI,EAAE,CAAC;YACnC,OAAO,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QACH,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;YACf,iBAAiB,GAAG,EAAE,CAAC;YACvB,UAAU,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,UAAU,GAAG,CAAC,EAAU;QAC3B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;YAC1E,OAAO,uBAAuB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,UAAU,IAAI,CAAC,EAAU,EAAE,MAAsB;QACpD,MAAM,SAAS,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,aAAa,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACjG,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IACjD,CAAC;IAED;;;OAGG;IACH,KAAK,UAAU,MAAM,CAAC,EAAU,EAAE,OAAyC;QACzE,OAAO,QAAQ,CAAC,EAAE,EAAE,KAAK,IAAI,EAAE;YAC7B,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC;YAC7B,IAAI,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAC;YACzB,OAAO,CAAC,MAAM,CAAC,CAAC;YAChB,MAAM,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YACvB,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,UAAU,MAAM,CAAC,EAAU;QAC9B,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;YACtC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,GAA4B,CAAC;YAC7C,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAC5C,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,KAAK,UAAU,MAAM,CAAC,EAAU;QAC9B,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;YACtC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,UAAU,aAAa,CAAC,WAAmB;QAC9C,MAAM,GAAG,GAAG,MAAM,IAAI,EAAE,CAAC;QACzB,OAAO,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;IAC/F,CAAC;IAED,KAAK,UAAU,kBAAkB,CAAC,IAAY;QAC5C,MAAM,GAAG,GAAG,MAAM,IAAI,EAAE,CAAC;QACzB,OAAO,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YACjD,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,cAAc,IAAI,EAAE,CAAC;YAC5C,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,CAAC;AACxF,CAAC;AAWD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAkB,EAAE,QAAkB,EAAE;IACzE,IAAI,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAEjC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnB,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,cAAc,KAAK,KAAK,CAAC,QAAQ,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;QACd,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAI,CAAC,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;QACxF,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,QAAkB,EAAE,EAAU;IAC3D,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC1B,CAAC;AA2BD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAwB;IACzD,OAAO,CAAC,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACjD,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;KAC1F,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,WAAwB,EAAE,EAAU;IACjE,OAAO,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,WAAwB,EAAE,WAAmB;IAC5E,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAiB,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QAC/C,MAAM,OAAO,GAA4B,MAAM,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QAC7E,MAAM,IAAI,GAAe,MAAM,CAAC,IAAI,CAAC;QACrC,OAAO;YACL,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,IAAI,IAAI;YACpD,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI;YACxC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,IAAI;YAClD,YAAY,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,WAAW,CAAC,IAAI,IAAI;YACxD,cAAc,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,IAAI,IAAI;YACjD,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,IAAI;SACxC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,OAAO,EAAE,WAAW;QACpB,MAAM;QACN,IAAI;KACL,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { ReportDocument } from '../types/index.js';
|
|
2
|
+
import type { DoctorRuleResult, DoctorSkillStatus } from '../types/doctor.js';
|
|
3
|
+
import { type Insight } from './skill-insights.js';
|
|
4
|
+
/** 测试 / 调试用:强制清掉 in-process skill-index 缓存。 */
|
|
5
|
+
export declare function _resetSkillIndexCache(): void;
|
|
6
|
+
export interface SkillDoctorSnapshot {
|
|
7
|
+
reportId: string;
|
|
8
|
+
timestamp: string;
|
|
9
|
+
status: DoctorSkillStatus;
|
|
10
|
+
passCount: number;
|
|
11
|
+
warnCount: number;
|
|
12
|
+
failCount: number;
|
|
13
|
+
results: DoctorRuleResult[];
|
|
14
|
+
}
|
|
15
|
+
export interface SkillEvalSnapshot {
|
|
16
|
+
reportId: string;
|
|
17
|
+
timestamp: string;
|
|
18
|
+
variantName: string;
|
|
19
|
+
verdictLevel: string;
|
|
20
|
+
verdictHeadline: string;
|
|
21
|
+
compositeScore: number | null;
|
|
22
|
+
passCount: number;
|
|
23
|
+
failCount: number;
|
|
24
|
+
tripwireCount: number;
|
|
25
|
+
totalSamples: number;
|
|
26
|
+
}
|
|
27
|
+
export interface SkillObserveSnapshot {
|
|
28
|
+
analysisId: string;
|
|
29
|
+
generatedAt: string;
|
|
30
|
+
healthBand: 'green' | 'yellow' | 'red';
|
|
31
|
+
failureRate: number;
|
|
32
|
+
segmentCount: number;
|
|
33
|
+
gapRate: number;
|
|
34
|
+
}
|
|
35
|
+
export interface SkillIndexEntry {
|
|
36
|
+
skillName: string;
|
|
37
|
+
/** 当前(最新)snapshot — 等价于对应 history 的最后一项,空时为 null。renderer
|
|
38
|
+
* 老路径直接读这个,不必动 history。 */
|
|
39
|
+
doctor: SkillDoctorSnapshot | null;
|
|
40
|
+
eval: SkillEvalSnapshot | null;
|
|
41
|
+
observe: SkillObserveSnapshot | null;
|
|
42
|
+
/** 历史 snapshot,chronological 升序(最早 → 最近)。renderer 用它画 sparkline 趋势。 */
|
|
43
|
+
doctorHistory: SkillDoctorSnapshot[];
|
|
44
|
+
evalHistory: SkillEvalSnapshot[];
|
|
45
|
+
observeHistory: SkillObserveSnapshot[];
|
|
46
|
+
/** 综合健康灯。doctor / eval / observe 任一红 → red;任一黄 → yellow;
|
|
47
|
+
* 全绿 → green;皆未跑 → gray。 */
|
|
48
|
+
band: 'green' | 'yellow' | 'red' | 'gray';
|
|
49
|
+
}
|
|
50
|
+
export interface SkillIndexSummary {
|
|
51
|
+
totalSkills: number;
|
|
52
|
+
withEval: number;
|
|
53
|
+
withObserve: number;
|
|
54
|
+
withDoctor: number;
|
|
55
|
+
red: number;
|
|
56
|
+
yellow: number;
|
|
57
|
+
green: number;
|
|
58
|
+
gray: number;
|
|
59
|
+
}
|
|
60
|
+
export interface SkillIndex {
|
|
61
|
+
entries: SkillIndexEntry[];
|
|
62
|
+
summary: SkillIndexSummary;
|
|
63
|
+
/** detectInsights 结果按 skillName 索引。在 buildSkillIndex 时同步算好,跟 SkillIndex
|
|
64
|
+
* 本身共享同一 fingerprint 缓存(reports 数组 + dir mtime 任一变就 invalidate)。
|
|
65
|
+
* list 页 N×detectInsights 重算的 CPU 开销由此消除。 */
|
|
66
|
+
insightsBySkill: Map<string, Insight[]>;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 扫 reports + analyses 目录,按 skill 名聚合。reports 通过 reportStore.list() 传入
|
|
70
|
+
* (避免重复读盘 + 避免再写一份 list 逻辑);analysesDir 直接扫。
|
|
71
|
+
*
|
|
72
|
+
* 同 skill 多份报告时取 timestamp 最新的一份。
|
|
73
|
+
*/
|
|
74
|
+
export declare function buildSkillIndex(reports: ReportDocument[], analysesDir: string, doctorsDir: string): SkillIndex;
|
|
75
|
+
/** 单 skill 详情查询(用于 /skills/<name> 详情页)— 复用 buildSkillIndex 的扫描结果。 */
|
|
76
|
+
export declare function getSkillEntry(idx: SkillIndex, skillName: string): SkillIndexEntry | null;
|
|
77
|
+
//# sourceMappingURL=skill-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-index.d.ts","sourceRoot":"","sources":["../../../src/server/skill-index.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,cAAc,EAAqC,MAAM,mBAAmB,CAAC;AAE3F,OAAO,KAAK,EAAgB,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5F,OAAO,EAAkB,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAC;AA8FnE,+CAA+C;AAC/C,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB;gCAC4B;IAC5B,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACnC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACrC,uEAAuE;IACvE,aAAa,EAAE,mBAAmB,EAAE,CAAC;IACrC,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,cAAc,EAAE,oBAAoB,EAAE,CAAC;IACvC;iCAC6B;IAC7B,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;CAC3C;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,OAAO,EAAE,iBAAiB,CAAC;IAC3B;;kDAE8C;IAC9C,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;CACzC;AA2ID;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,cAAc,EAAE,EACzB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,UAAU,CA+FZ;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAExF"}
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill-centric 聚合 — 顶级实体从"报告"翻成"skill",每个 skill 在 4 类报告
|
|
3
|
+
* (doctor / eval-评分 / eval-功能 / observe)上各取最新一份做 status 摘要,
|
|
4
|
+
* 给 studio 列表页用。
|
|
5
|
+
*
|
|
6
|
+
* 当前 v1 范围:
|
|
7
|
+
* - eval 报告(reportsDir):按 treatment variant 名分桶,跳过 baseline 保留字。
|
|
8
|
+
* 评分视角(verdict / 综合分)和功能视角(pass/fail/tripwire 计数)挤一份 snapshot,
|
|
9
|
+
* 因为同一份 EvaluationReport 同时驱动两个 view tab。
|
|
10
|
+
* - observe 报告(analysesDir, SkillHealthReport):data.bySkill[name] 每个键作为
|
|
11
|
+
* 一个 skill 的 observe snapshot,取最新 generatedAt。
|
|
12
|
+
* - doctor:暂无独立持久化路径(omk doctor --html 写指定路径,默认不存盘),
|
|
13
|
+
* 该字段保留 null,渲染层显示"未独立运行 omk doctor"。后续 commit 加默认
|
|
14
|
+
* ~/.oh-my-knowledge/doctors/ 持久化路径再回填。
|
|
15
|
+
*
|
|
16
|
+
* 综合 band:eval / observe 任一红 → 红,任一黄 → 黄,全绿 → 绿,皆未跑 → gray。
|
|
17
|
+
*/
|
|
18
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
19
|
+
import { join } from 'node:path';
|
|
20
|
+
import { computeVerdict } from '../eval-core/verdict.js';
|
|
21
|
+
import { detectInsights } from './skill-insights.js';
|
|
22
|
+
let _indexCache = null;
|
|
23
|
+
/**
|
|
24
|
+
* Sync 版 dir-content fingerprint helper,仿 `src/server/report-store.ts:80-92`
|
|
25
|
+
* 的 async `computeListFingerprint` — 把目录本身的 mtime 跟目录下每个 `.json`
|
|
26
|
+
* 文件的 "filename:mtimeMs:size" 三元组排序拼接成 stable 字符串作为 dir-level
|
|
27
|
+
* 的 content-aware fingerprint。
|
|
28
|
+
*
|
|
29
|
+
* - 目录下任何 .json 文件**新增 / 删除 / 重命名** → 目录 mtime 跟着变,且
|
|
30
|
+
* sorted-filenames 列表变,字符串变 → cache invalidate。
|
|
31
|
+
* - 任何**已有同名 .json 文件被外部进程原地覆写内容** → 该文件自己的 mtimeMs
|
|
32
|
+
* 跟通常情况下 size 都变(byte 长度跟内容相关),字符串里那一 entry 的后缀
|
|
33
|
+
* 变,整体字符串变 → cache invalidate。这是 pre-fix 的 fingerprint(只看
|
|
34
|
+
* dir mtime+文件数)漏掉的信号(reviewer 2026-05-11 P2-a)。
|
|
35
|
+
* - 单个文件 stat fail(临时权限错或 race condition 删除)用 `<filename>:?`
|
|
36
|
+
* 占位字面,跟 report-store.ts 那一侧的 sentinel 字面对齐。整个 dir-stat
|
|
37
|
+
* fail(目录不存在 / 权限错)返回固定 sentinel "missing",这样"目录持续不存
|
|
38
|
+
* 在"的多次连续调用 fingerprint 字符串稳定一致 cache 复用合理(行为跟旧
|
|
39
|
+
* helper 在两个 try 的 catch 分支都返 0 拼接出"0-0"的稳定 sentinel 等价)。
|
|
40
|
+
*/
|
|
41
|
+
function safeDirJsonContentFingerprint(dir) {
|
|
42
|
+
// 加入 dir 路径本身,确保不同路径即使 mtime/file-list 相同也会产生不同 fingerprint
|
|
43
|
+
let dirMtimeMs;
|
|
44
|
+
let jsonFiles;
|
|
45
|
+
try {
|
|
46
|
+
dirMtimeMs = statSync(dir).mtimeMs;
|
|
47
|
+
jsonFiles = readdirSync(dir).filter((f) => f.endsWith('.json')).sort();
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return `missing:${dir}`;
|
|
51
|
+
}
|
|
52
|
+
const fileParts = jsonFiles.map((f) => {
|
|
53
|
+
try {
|
|
54
|
+
const fStat = statSync(join(dir, f));
|
|
55
|
+
return `${f}:${fStat.mtimeMs}:${fStat.size}`;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return `${f}:?`;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
return `${dir}|${dirMtimeMs}|${fileParts.join(',')}`;
|
|
62
|
+
}
|
|
63
|
+
function buildIndexFingerprint(reports, analysesDir, doctorsDir) {
|
|
64
|
+
// `d:` 跟 `o:` 前缀("d for doctors / o for observability analyses")沿用 pre-fix
|
|
65
|
+
// 字面格式,避免外部 logging / debug 时 grep fingerprint 字符串的格式漂移。
|
|
66
|
+
// 每一段的 right-hand-side 从旧的 "{dir-mtime}-{file-count}" 双标量升级成
|
|
67
|
+
// safeDirJsonContentFingerprint 返回的 "{dir-mtime}|{file1}:{m}:{s},..."
|
|
68
|
+
// content-aware 字符串。
|
|
69
|
+
const reportIds = reports.map((r) => `${r.id}:${r.meta?.timestamp ?? ''}`).join(',');
|
|
70
|
+
const doctorsFp = safeDirJsonContentFingerprint(doctorsDir);
|
|
71
|
+
const analysesFp = safeDirJsonContentFingerprint(analysesDir);
|
|
72
|
+
return `${reportIds}|d:${doctorsFp}|o:${analysesFp}`;
|
|
73
|
+
}
|
|
74
|
+
/** 测试 / 调试用:强制清掉 in-process skill-index 缓存。 */
|
|
75
|
+
export function _resetSkillIndexCache() {
|
|
76
|
+
_indexCache = null;
|
|
77
|
+
}
|
|
78
|
+
function sampleAllPassed(details) {
|
|
79
|
+
if (!details || details.length === 0)
|
|
80
|
+
return true;
|
|
81
|
+
return details.every((d) => d.passed);
|
|
82
|
+
}
|
|
83
|
+
function buildEvalSnapshot(report, variant) {
|
|
84
|
+
const summary = report.summary?.[variant];
|
|
85
|
+
if (!summary)
|
|
86
|
+
return null;
|
|
87
|
+
let pass = 0;
|
|
88
|
+
let fail = 0;
|
|
89
|
+
let tripwire = 0;
|
|
90
|
+
for (const r of report.results) {
|
|
91
|
+
const vr = r.variants?.[variant];
|
|
92
|
+
if (!vr)
|
|
93
|
+
continue;
|
|
94
|
+
const allPassed = sampleAllPassed(vr.assertions?.details);
|
|
95
|
+
const isTripwire = report.sampleSnapshots?.[r.sample_id]?.tripwire === true
|
|
96
|
+
|| (vr.diagnostic?.rootCause || []).includes('tripwire_intentional');
|
|
97
|
+
if (allPassed)
|
|
98
|
+
pass += 1;
|
|
99
|
+
else if (isTripwire)
|
|
100
|
+
tripwire += 1;
|
|
101
|
+
else
|
|
102
|
+
fail += 1;
|
|
103
|
+
}
|
|
104
|
+
// verdict 是运行期计算的,不进 report,这里现算。
|
|
105
|
+
// multi-treatment 报告:computeVerdict 顶层 level 是 worst-of perPair,headline 也是
|
|
106
|
+
// worst pair 的描述;我们要的是"当前这个 variant 对应的 pair"。优先从 perPair 找,
|
|
107
|
+
// 找不到再 fallback report-level(单 treatment 时 perPair 也只有一条,等价)。
|
|
108
|
+
let verdictLevel = 'unknown';
|
|
109
|
+
let verdictHeadline = '';
|
|
110
|
+
try {
|
|
111
|
+
const v = computeVerdict(report);
|
|
112
|
+
const myPair = v.perPair?.find((p) => p.treatment === variant);
|
|
113
|
+
if (myPair) {
|
|
114
|
+
verdictLevel = myPair.level;
|
|
115
|
+
verdictHeadline = myPair.headline;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
verdictLevel = v.level;
|
|
119
|
+
verdictHeadline = v.headline;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch { /* 单 variant 报告 / control 缺失等情况 — 留 unknown 默认 */ }
|
|
123
|
+
return {
|
|
124
|
+
reportId: report.id,
|
|
125
|
+
timestamp: report.meta.timestamp || '',
|
|
126
|
+
variantName: variant,
|
|
127
|
+
verdictLevel,
|
|
128
|
+
verdictHeadline,
|
|
129
|
+
compositeScore: summary.avgCompositeScore ?? null,
|
|
130
|
+
passCount: pass,
|
|
131
|
+
failCount: fail,
|
|
132
|
+
tripwireCount: tripwire,
|
|
133
|
+
totalSamples: pass + fail + tripwire,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Per-skill 健康色带。**这跟 skill-health-analyzer 的 overall.healthBand 是两个视角**:
|
|
138
|
+
* - overall.healthBand(skill-health-analyzer.ts:healthBandOf):只看 weightedGapRate,
|
|
139
|
+
* 回答"用户问题是否被知识库覆盖"(对外能力,跨 skill 平均)
|
|
140
|
+
* - PER_SKILL_BAND(本函数):综合 toolFailureRate + gap,回答"这个 skill 自身跑得稳不稳"
|
|
141
|
+
* (skill 内视角,失败工具调用 + 缺知识都算)
|
|
142
|
+
* 不要把两边合并 — 语义不同,跨版本可比性也独立维护。
|
|
143
|
+
*
|
|
144
|
+
* 调整阈值会让历史 observe report 的 band 重新分类,UI 颜色变;
|
|
145
|
+
* **不算 BREAKING-COMPARABILITY**(只影响 Studio 列表视觉,不动 grading/judge 输出)。
|
|
146
|
+
*/
|
|
147
|
+
const PER_SKILL_BAND_RED_FAILURE_RATE = 0.4; // 工具失败率 ≥ 40% → red
|
|
148
|
+
const PER_SKILL_BAND_YELLOW_FAILURE_RATE = 0.2; // ≥ 20% → yellow
|
|
149
|
+
const PER_SKILL_BAND_YELLOW_GAP_RATE = 0.3; // 加权 gap ≥ 30% → yellow
|
|
150
|
+
function bandFromObserveHealth(h) {
|
|
151
|
+
if (h.toolFailureRate >= PER_SKILL_BAND_RED_FAILURE_RATE)
|
|
152
|
+
return 'red';
|
|
153
|
+
const gap = h.gap?.weightedGapRate ?? 0;
|
|
154
|
+
if (gap >= PER_SKILL_BAND_YELLOW_GAP_RATE || h.toolFailureRate >= PER_SKILL_BAND_YELLOW_FAILURE_RATE)
|
|
155
|
+
return 'yellow';
|
|
156
|
+
return 'green';
|
|
157
|
+
}
|
|
158
|
+
function combineBand(doctor, evalSnap, observe) {
|
|
159
|
+
if (!doctor && !evalSnap && !observe)
|
|
160
|
+
return 'gray';
|
|
161
|
+
// doctor band: status fail → red, warn → yellow, pass → green
|
|
162
|
+
const doctorBand = !doctor
|
|
163
|
+
? 'gray'
|
|
164
|
+
: doctor.status === 'fail' ? 'red'
|
|
165
|
+
: doctor.status === 'warn' ? 'yellow'
|
|
166
|
+
: 'green';
|
|
167
|
+
// eval band:按真实 fail 占比(诱错不算,total 不含)估色。
|
|
168
|
+
const evalDenom = evalSnap ? evalSnap.passCount + evalSnap.failCount : 0;
|
|
169
|
+
const failRatio = evalDenom > 0 ? (evalSnap.failCount / evalDenom) : 0;
|
|
170
|
+
const evalBand = !evalSnap
|
|
171
|
+
? 'gray'
|
|
172
|
+
: failRatio >= 0.5 ? 'red'
|
|
173
|
+
: failRatio >= 0.2 ? 'yellow'
|
|
174
|
+
: 'green';
|
|
175
|
+
const obsBand = observe?.healthBand ?? 'gray';
|
|
176
|
+
if (doctorBand === 'red' || evalBand === 'red' || obsBand === 'red')
|
|
177
|
+
return 'red';
|
|
178
|
+
if (doctorBand === 'yellow' || evalBand === 'yellow' || obsBand === 'yellow')
|
|
179
|
+
return 'yellow';
|
|
180
|
+
if (doctorBand === 'green' || evalBand === 'green' || obsBand === 'green')
|
|
181
|
+
return 'green';
|
|
182
|
+
return 'gray';
|
|
183
|
+
}
|
|
184
|
+
function latestActivityTs(e) {
|
|
185
|
+
const candidates = [e.doctor?.timestamp, e.eval?.timestamp, e.observe?.generatedAt]
|
|
186
|
+
.filter((s) => Boolean(s));
|
|
187
|
+
return candidates.sort().pop() || '';
|
|
188
|
+
}
|
|
189
|
+
/** 扫 doctorsDir/*.json,按 skill 名分桶,**返回该 skill 的所有历史 snapshot**(asc 时序)。
|
|
190
|
+
* renderer 用最后一项做"当前",前面项画 sparkline。 */
|
|
191
|
+
function scanDoctorReports(dir) {
|
|
192
|
+
const out = {};
|
|
193
|
+
if (!existsSync(dir))
|
|
194
|
+
return out;
|
|
195
|
+
for (const file of readdirSync(dir)) {
|
|
196
|
+
if (!file.endsWith('.json'))
|
|
197
|
+
continue;
|
|
198
|
+
try {
|
|
199
|
+
const data = JSON.parse(readFileSync(join(dir, file), 'utf-8'));
|
|
200
|
+
if (data?.kind !== 'doctor' || !Array.isArray(data.skills))
|
|
201
|
+
continue;
|
|
202
|
+
const ts = data.timestamp;
|
|
203
|
+
for (const sr of data.skills) {
|
|
204
|
+
const passN = sr.results.filter((r) => r.status === 'pass').length;
|
|
205
|
+
const warnN = sr.results.filter((r) => r.status === 'warn').length;
|
|
206
|
+
const failN = sr.results.filter((r) => r.status === 'fail').length;
|
|
207
|
+
const snap = {
|
|
208
|
+
reportId: data.id, timestamp: ts, status: sr.status,
|
|
209
|
+
passCount: passN, warnCount: warnN, failCount: failN, results: sr.results,
|
|
210
|
+
};
|
|
211
|
+
if (!out[sr.skillName])
|
|
212
|
+
out[sr.skillName] = [];
|
|
213
|
+
out[sr.skillName].push(snap);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
catch { /* skip corrupt */ }
|
|
217
|
+
}
|
|
218
|
+
for (const list of Object.values(out))
|
|
219
|
+
list.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
|
|
220
|
+
return out;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* 扫 reports + analyses 目录,按 skill 名聚合。reports 通过 reportStore.list() 传入
|
|
224
|
+
* (避免重复读盘 + 避免再写一份 list 逻辑);analysesDir 直接扫。
|
|
225
|
+
*
|
|
226
|
+
* 同 skill 多份报告时取 timestamp 最新的一份。
|
|
227
|
+
*/
|
|
228
|
+
export function buildSkillIndex(reports, analysesDir, doctorsDir) {
|
|
229
|
+
// 命中缓存就直接返回(fingerprint 覆盖 reports + 两个 dir 的变化信号)
|
|
230
|
+
const fp = buildIndexFingerprint(reports, analysesDir, doctorsDir);
|
|
231
|
+
if (_indexCache && _indexCache.fingerprint === fp) {
|
|
232
|
+
return _indexCache.result;
|
|
233
|
+
}
|
|
234
|
+
// ── eval 聚合(历史 list)─────────────────────────────────
|
|
235
|
+
const evalBy = {};
|
|
236
|
+
for (const r of reports) {
|
|
237
|
+
if (r.kind !== 'evaluation')
|
|
238
|
+
continue;
|
|
239
|
+
const variants = r.meta.variants || [];
|
|
240
|
+
for (const v of variants) {
|
|
241
|
+
if (v === 'baseline')
|
|
242
|
+
continue;
|
|
243
|
+
const snap = buildEvalSnapshot(r, v);
|
|
244
|
+
if (!snap)
|
|
245
|
+
continue;
|
|
246
|
+
if (!evalBy[v])
|
|
247
|
+
evalBy[v] = [];
|
|
248
|
+
evalBy[v].push(snap);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
for (const list of Object.values(evalBy))
|
|
252
|
+
list.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
|
|
253
|
+
// ── observe 聚合(历史 list)──────────────────────────────
|
|
254
|
+
const observeBy = {};
|
|
255
|
+
if (existsSync(analysesDir)) {
|
|
256
|
+
for (const file of readdirSync(analysesDir)) {
|
|
257
|
+
if (!file.endsWith('.json'))
|
|
258
|
+
continue;
|
|
259
|
+
try {
|
|
260
|
+
const data = JSON.parse(readFileSync(join(analysesDir, file), 'utf-8'));
|
|
261
|
+
if (!data?.bySkill || !data.meta)
|
|
262
|
+
continue;
|
|
263
|
+
const generatedAt = data.meta.generatedAt;
|
|
264
|
+
const id = file.replace(/\.json$/, '');
|
|
265
|
+
for (const [skill, h] of Object.entries(data.bySkill)) {
|
|
266
|
+
const snap = {
|
|
267
|
+
analysisId: id, generatedAt,
|
|
268
|
+
healthBand: bandFromObserveHealth(h),
|
|
269
|
+
failureRate: h.toolFailureRate,
|
|
270
|
+
segmentCount: h.segmentCount,
|
|
271
|
+
gapRate: h.gap?.weightedGapRate ?? 0,
|
|
272
|
+
};
|
|
273
|
+
if (!observeBy[skill])
|
|
274
|
+
observeBy[skill] = [];
|
|
275
|
+
observeBy[skill].push(snap);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch { /* skip corrupt */ }
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
for (const list of Object.values(observeBy))
|
|
282
|
+
list.sort((a, b) => a.generatedAt.localeCompare(b.generatedAt));
|
|
283
|
+
// ── doctor 聚合(历史 list)──────────────────────────────
|
|
284
|
+
const doctorBy = scanDoctorReports(doctorsDir);
|
|
285
|
+
// ── 合并 ──────────────────────────────────────────────────
|
|
286
|
+
const allSkills = new Set([
|
|
287
|
+
...Object.keys(evalBy), ...Object.keys(observeBy), ...Object.keys(doctorBy),
|
|
288
|
+
]);
|
|
289
|
+
const entries = [];
|
|
290
|
+
for (const name of allSkills) {
|
|
291
|
+
const doctorHistory = doctorBy[name] ?? [];
|
|
292
|
+
const evalHistory = evalBy[name] ?? [];
|
|
293
|
+
const observeHistory = observeBy[name] ?? [];
|
|
294
|
+
const doctor = doctorHistory.length > 0 ? doctorHistory[doctorHistory.length - 1] : null;
|
|
295
|
+
const evalSnap = evalHistory.length > 0 ? evalHistory[evalHistory.length - 1] : null;
|
|
296
|
+
const observe = observeHistory.length > 0 ? observeHistory[observeHistory.length - 1] : null;
|
|
297
|
+
entries.push({
|
|
298
|
+
skillName: name,
|
|
299
|
+
doctor, eval: evalSnap, observe,
|
|
300
|
+
doctorHistory, evalHistory, observeHistory,
|
|
301
|
+
band: combineBand(doctor, evalSnap, observe),
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
entries.sort((a, b) => latestActivityTs(b).localeCompare(latestActivityTs(a)));
|
|
305
|
+
// ── summary ───────────────────────────────────────────────
|
|
306
|
+
const summary = {
|
|
307
|
+
totalSkills: entries.length,
|
|
308
|
+
withEval: entries.filter((e) => e.eval).length,
|
|
309
|
+
withObserve: entries.filter((e) => e.observe).length,
|
|
310
|
+
withDoctor: entries.filter((e) => e.doctor).length,
|
|
311
|
+
red: entries.filter((e) => e.band === 'red').length,
|
|
312
|
+
yellow: entries.filter((e) => e.band === 'yellow').length,
|
|
313
|
+
green: entries.filter((e) => e.band === 'green').length,
|
|
314
|
+
gray: entries.filter((e) => e.band === 'gray').length,
|
|
315
|
+
};
|
|
316
|
+
// 跟 SkillIndex 一起算 insightsBySkill,享受同一份 fingerprint 缓存。
|
|
317
|
+
// list 页对每个 entry 跑 detectInsights 的 CPU 开销迁移到这里,只 miss 时算一次。
|
|
318
|
+
const insightsBySkill = new Map();
|
|
319
|
+
for (const ent of entries) {
|
|
320
|
+
const evalReport = ent.eval ? reports.find((r) => r.id === ent.eval.reportId && r.kind === 'evaluation') : undefined;
|
|
321
|
+
insightsBySkill.set(ent.skillName, detectInsights(ent, evalReport ?? null));
|
|
322
|
+
}
|
|
323
|
+
const result = { entries, summary, insightsBySkill };
|
|
324
|
+
_indexCache = { fingerprint: fp, result };
|
|
325
|
+
return result;
|
|
326
|
+
}
|
|
327
|
+
/** 单 skill 详情查询(用于 /skills/<name> 详情页)— 复用 buildSkillIndex 的扫描结果。 */
|
|
328
|
+
export function getSkillEntry(idx, skillName) {
|
|
329
|
+
return idx.entries.find((e) => e.skillName === skillName) ?? null;
|
|
330
|
+
}
|
|
331
|
+
//# sourceMappingURL=skill-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-index.js","sourceRoot":"","sources":["../../../src/server/skill-index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Insight detection — 把 4 类报告(doctor / eval-评分 / eval-功能 / observe)合并成
|
|
3
|
+
* 一组结构化"问题",每个 Insight 自带:
|
|
4
|
+
* - audience: 该问题主要由谁来修(skill-author / sample-author / omk-maintainer)
|
|
5
|
+
* - 多 perspective 的证据(支持现象证据 illustration: 真实 prompt / LLM 输出 / 工具调用)
|
|
6
|
+
* - 改进建议(可带可粘贴 patch 片段)
|
|
7
|
+
*
|
|
8
|
+
* 设计原则:
|
|
9
|
+
* - 用户语去黑话:title/message 写成"用户能复现的现象",不直接吐 omk 内部枚举
|
|
10
|
+
* - 受众 explicit:每条 insight 标谁该 own,UI 拆区,不让 skill 开发者看 omk 维护待办
|
|
11
|
+
* - action 错位修对:环境拦截 → sample.mocks(不是 skill);doctor 盲区 → omk(不是 skill)
|
|
12
|
+
* - 现象 > 统计:展开 1-2 条真实 sample 的 prompt/output/toolCall 让用户"看见"问题
|
|
13
|
+
* - 可粘贴 patch:推荐带文件位置 + 代码片段,不只是"改一段"的空话
|
|
14
|
+
*
|
|
15
|
+
* 6 类 detection(audience 标在每条):
|
|
16
|
+
* 1. environment-blocked-mocks sample-author 评测环境 mock 列表盖不全
|
|
17
|
+
* 2. skill-doc-gap skill-author + sample-author skill 文档某段缺/模糊 + sample environment 没声明
|
|
18
|
+
* 3. failure-mode-skill skill-author skill 写法上的反模式(硬编码/幻觉/跳步/误读)
|
|
19
|
+
* 4. coverage-gap sample-author 生产 + 评测都漏的文件
|
|
20
|
+
* 5. production-instability skill-author + sample-author 真实环境失败率高
|
|
21
|
+
* 6. skill-too-long skill-author skill 文档过长 LLM 找不到段落
|
|
22
|
+
* 7. omk-doctor-blindspot omk-maintainer doctor 应该卡却没规则的反模式
|
|
23
|
+
*/
|
|
24
|
+
import type { EvaluationReport } from '../types/index.js';
|
|
25
|
+
import type { SkillIndexEntry, SkillEvalSnapshot } from './skill-index.js';
|
|
26
|
+
export type InsightCategory = 'environment-blocked-mocks' | 'skill-doc-gap' | 'failure-mode-skill' | 'coverage-gap' | 'production-instability' | 'skill-too-long' | 'omk-doctor-blindspot' | 'other';
|
|
27
|
+
export type InsightSeverity = 'high' | 'medium' | 'low';
|
|
28
|
+
export type InsightAudience = 'skill-author' | 'sample-author' | 'omk-maintainer';
|
|
29
|
+
export type InsightPerspective = 'doctor' | 'eval-score' | 'eval-functional' | 'observe';
|
|
30
|
+
/** 现象证据:把抽象"X 模式 N 条"翻译成用户能看到的具体行为。 */
|
|
31
|
+
export interface InsightIllustration {
|
|
32
|
+
sampleId: string;
|
|
33
|
+
/** 用户给 LLM 的 prompt(截断到 ~200 字)。 */
|
|
34
|
+
samplePrompt?: string;
|
|
35
|
+
/** LLM 最终输出(截断到 ~200 字)。 */
|
|
36
|
+
llmOutput?: string;
|
|
37
|
+
/** LLM 实际调的工具(简化字符串列表,顺序保留)。 */
|
|
38
|
+
toolCalls?: string[];
|
|
39
|
+
/** 哪条 assertion 没过 + value。 */
|
|
40
|
+
failedAssertion?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface InsightEvidence {
|
|
43
|
+
perspective: InsightPerspective;
|
|
44
|
+
status: 'flagged' | 'blind' | 'silent' | 'na';
|
|
45
|
+
/** 简短说明(用户语,不堆术语)。 */
|
|
46
|
+
message: string;
|
|
47
|
+
ref?: string;
|
|
48
|
+
/** 如果有现象证据,展开看 1-2 条具体 sample 的实际 prompt/output/toolCalls。 */
|
|
49
|
+
illustrations?: InsightIllustration[];
|
|
50
|
+
}
|
|
51
|
+
/** 可粘贴的 patch 片段。target 指明改哪种文件,location 是文件/章节,snippet 是代码块。 */
|
|
52
|
+
export interface InsightPatch {
|
|
53
|
+
target: 'skill' | 'sample-environment' | 'sample-mocks' | 'doctor-rule';
|
|
54
|
+
/** 目标位置描述,如 'sample s003 的 mocks 数组' / 'SKILL.md「项目创建」节'。 */
|
|
55
|
+
location: string;
|
|
56
|
+
/** 代码块或 diff 片段。 */
|
|
57
|
+
snippet: string;
|
|
58
|
+
}
|
|
59
|
+
export interface InsightRecommendation {
|
|
60
|
+
action: string;
|
|
61
|
+
priority: InsightSeverity;
|
|
62
|
+
patch?: InsightPatch;
|
|
63
|
+
}
|
|
64
|
+
/** 该 insight 关联的具体阶段元素 — UI 渲染 timeline 时用来在阶段卡内挂 #N 徽章。 */
|
|
65
|
+
export interface InsightStageRefs {
|
|
66
|
+
doctorRuleIds?: string[];
|
|
67
|
+
evalSampleIds?: string[];
|
|
68
|
+
/** observe 信号类型标签:'high-failure-rate' / 'gap' / 'uncovered-files'。
|
|
69
|
+
* observe 内单条信号没像 doctor rule / eval sample 那么细的 id,用类型标即可。 */
|
|
70
|
+
observeRefs?: string[];
|
|
71
|
+
}
|
|
72
|
+
export interface Insight {
|
|
73
|
+
id: string;
|
|
74
|
+
category: InsightCategory;
|
|
75
|
+
audience: InsightAudience;
|
|
76
|
+
/** 用户语标题。 */
|
|
77
|
+
title: string;
|
|
78
|
+
/** 一句话现象描述(标题之外的细节)。 */
|
|
79
|
+
description?: string;
|
|
80
|
+
severity: InsightSeverity;
|
|
81
|
+
affectedCount: number;
|
|
82
|
+
evidence: InsightEvidence[];
|
|
83
|
+
recommendations: InsightRecommendation[];
|
|
84
|
+
/** 关联到 timeline 哪些阶段元素 — renderer 据此在阶段卡内插入 #N 徽章。 */
|
|
85
|
+
stageRefs?: InsightStageRefs;
|
|
86
|
+
}
|
|
87
|
+
export declare function detectInsights(entry: SkillIndexEntry, evalReport: EvaluationReport | null): Insight[];
|
|
88
|
+
export declare function flattenRecommendations(insights: Insight[]): InsightRecommendation[];
|
|
89
|
+
/** 按 audience 分桶 — UI 拆区用。 */
|
|
90
|
+
export declare function groupInsightsByAudience(insights: Insight[]): Record<InsightAudience, Insight[]>;
|
|
91
|
+
export type _SkillEvalSnapshotForInsight = SkillEvalSnapshot;
|
|
92
|
+
//# sourceMappingURL=skill-insights.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-insights.d.ts","sourceRoot":"","sources":["../../../src/server/skill-insights.ts"],"names":[],"mappings":"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"}
|