oh-my-knowledge 0.24.0 → 0.25.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 +84 -21
- package/README.zh.md +81 -21
- package/dist/src/analysis/saturation.d.ts +2 -2
- package/dist/src/analysis/saturation.js +2 -2
- package/dist/src/authoring/evolver.d.ts +7 -4
- package/dist/src/authoring/evolver.d.ts.map +1 -1
- package/dist/src/authoring/evolver.js +15 -7
- package/dist/src/authoring/evolver.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 +213 -40
- package/dist/src/cli/i18n-dict.js.map +1 -1
- package/dist/src/cli/index.js +188 -87
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/cli/parse-run-config.d.ts +32 -9
- package/dist/src/cli/parse-run-config.d.ts.map +1 -1
- package/dist/src/cli/parse-run-config.js +76 -21
- package/dist/src/cli/parse-run-config.js.map +1 -1
- package/dist/src/cli/parse-strict.d.ts +20 -0
- package/dist/src/cli/parse-strict.d.ts.map +1 -0
- package/dist/src/cli/parse-strict.js +25 -0
- package/dist/src/cli/parse-strict.js.map +1 -0
- package/dist/src/doctor/index.d.ts +19 -0
- package/dist/src/doctor/index.d.ts.map +1 -0
- package/dist/src/doctor/index.js +182 -0
- package/dist/src/doctor/index.js.map +1 -0
- package/dist/src/doctor/preflight.d.ts +32 -0
- package/dist/src/doctor/preflight.d.ts.map +1 -0
- package/dist/src/doctor/preflight.js +32 -0
- package/dist/src/doctor/preflight.js.map +1 -0
- package/dist/src/doctor/renderer.d.ts +13 -0
- package/dist/src/doctor/renderer.d.ts.map +1 -0
- package/dist/src/doctor/renderer.js +69 -0
- package/dist/src/doctor/renderer.js.map +1 -0
- package/dist/src/doctor/rules.d.ts +30 -0
- package/dist/src/doctor/rules.d.ts.map +1 -0
- package/dist/src/doctor/rules.js +216 -0
- package/dist/src/doctor/rules.js.map +1 -0
- package/dist/src/eval-core/bootstrap.d.ts +1 -1
- package/dist/src/eval-core/bootstrap.js +1 -1
- package/dist/src/eval-core/comparability.d.ts.map +1 -1
- package/dist/src/eval-core/comparability.js +82 -57
- package/dist/src/eval-core/comparability.js.map +1 -1
- package/dist/src/eval-core/dependency-checker.js +1 -1
- package/dist/src/eval-core/dependency-checker.js.map +1 -1
- package/dist/src/eval-core/evaluation-execution.d.ts +20 -7
- package/dist/src/eval-core/evaluation-execution.d.ts.map +1 -1
- package/dist/src/eval-core/evaluation-execution.js +29 -5
- package/dist/src/eval-core/evaluation-execution.js.map +1 -1
- package/dist/src/eval-core/evaluation-job.d.ts +2 -4
- package/dist/src/eval-core/evaluation-job.d.ts.map +1 -1
- package/dist/src/eval-core/evaluation-job.js +1 -3
- package/dist/src/eval-core/evaluation-job.js.map +1 -1
- package/dist/src/eval-core/evaluation-reporting.d.ts.map +1 -1
- package/dist/src/eval-core/evaluation-reporting.js +12 -14
- package/dist/src/eval-core/evaluation-reporting.js.map +1 -1
- package/dist/src/eval-core/schema.d.ts.map +1 -1
- package/dist/src/eval-core/schema.js +7 -2
- package/dist/src/eval-core/schema.js.map +1 -1
- package/dist/src/eval-workflows/batch-evaluation-workflow.d.ts +6 -4
- package/dist/src/eval-workflows/batch-evaluation-workflow.d.ts.map +1 -1
- package/dist/src/eval-workflows/batch-evaluation-workflow.js +14 -12
- package/dist/src/eval-workflows/batch-evaluation-workflow.js.map +1 -1
- package/dist/src/eval-workflows/evaluation-pipeline.d.ts +2 -2
- package/dist/src/eval-workflows/evaluation-pipeline.d.ts.map +1 -1
- package/dist/src/eval-workflows/evaluation-pipeline.js +39 -34
- package/dist/src/eval-workflows/evaluation-pipeline.js.map +1 -1
- package/dist/src/eval-workflows/evaluation-preparation.d.ts +5 -20
- package/dist/src/eval-workflows/evaluation-preparation.d.ts.map +1 -1
- package/dist/src/eval-workflows/evaluation-preparation.js +2 -21
- package/dist/src/eval-workflows/evaluation-preparation.js.map +1 -1
- package/dist/src/eval-workflows/run-evaluation.d.ts +11 -10
- package/dist/src/eval-workflows/run-evaluation.d.ts.map +1 -1
- package/dist/src/eval-workflows/run-evaluation.js +123 -16
- package/dist/src/eval-workflows/run-evaluation.js.map +1 -1
- package/dist/src/grading/assertions.js +4 -4
- package/dist/src/grading/assertions.js.map +1 -1
- package/dist/src/grading/gold-cli.js +4 -4
- package/dist/src/grading/gold-cli.js.map +1 -1
- package/dist/src/grading/human-gold.d.ts +1 -1
- package/dist/src/grading/human-gold.js +1 -1
- package/dist/src/grading/index.d.ts +20 -15
- package/dist/src/grading/index.d.ts.map +1 -1
- package/dist/src/grading/index.js +29 -16
- package/dist/src/grading/index.js.map +1 -1
- package/dist/src/grading/judge.d.ts +1 -1
- package/dist/src/grading/judge.js +1 -1
- package/dist/src/inputs/eval-config.js +65 -7
- package/dist/src/inputs/eval-config.js.map +1 -1
- package/dist/src/renderer/html-renderer.d.ts.map +1 -1
- package/dist/src/renderer/html-renderer.js +32 -12
- package/dist/src/renderer/html-renderer.js.map +1 -1
- package/dist/src/renderer/summary.js +1 -1
- package/dist/src/renderer/summary.js.map +1 -1
- package/dist/src/types/doctor.d.ts +95 -0
- package/dist/src/types/doctor.d.ts.map +1 -0
- package/dist/src/types/doctor.js +2 -0
- package/dist/src/types/doctor.js.map +1 -0
- package/dist/src/types/eval.d.ts +36 -17
- package/dist/src/types/eval.d.ts.map +1 -1
- package/dist/src/types/executor.d.ts +33 -0
- package/dist/src/types/executor.d.ts.map +1 -1
- package/dist/src/types/index.d.ts +1 -0
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/index.js +1 -0
- package/dist/src/types/index.js.map +1 -1
- package/dist/src/types/judge.d.ts +11 -0
- package/dist/src/types/judge.d.ts.map +1 -1
- package/dist/src/types/report.d.ts +21 -52
- package/dist/src/types/report.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* parseArgs strict:true wrapper, catch unknown option throw 转友好 stderr + exit 2。
|
|
3
|
+
*
|
|
4
|
+
* 收口理由: parseArgs strict:false 让未声明的 flag 被静默吞掉, 用户写错 flag
|
|
5
|
+
* 名 (或传已删除 flag) 时命令 exit 0 但什么都没生效, 比 fail 还危险。所有
|
|
6
|
+
* 子命令统一走这层, "未知就报错" 一致语义。
|
|
7
|
+
*
|
|
8
|
+
* exit 2 区分于业务 failure 的 exit 1 (doctor / gate / verdict 等), CI 可分别处理。
|
|
9
|
+
*
|
|
10
|
+
* 类型 cast: strict:true 模式下 parseArgs 返回 values 含 array possible (因为
|
|
11
|
+
* options 可声明 multiple)。omk 现有 options 都不用 multiple, 直接 cast 收回
|
|
12
|
+
* 简单类型, caller 解构干净。后续若用 multiple 需要放宽这个 cast。
|
|
13
|
+
*/
|
|
14
|
+
import type { ParseArgsConfig } from 'node:util';
|
|
15
|
+
export interface StrictParsedArgs {
|
|
16
|
+
values: Record<string, string | boolean | undefined>;
|
|
17
|
+
positionals: string[];
|
|
18
|
+
}
|
|
19
|
+
export declare function parseArgsStrictOrExit(opts: Omit<ParseArgsConfig, 'strict'>): StrictParsedArgs;
|
|
20
|
+
//# sourceMappingURL=parse-strict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-strict.d.ts","sourceRoot":"","sources":["../../../src/cli/parse-strict.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;IACrD,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,GAAG,gBAAgB,CAQ7F"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* parseArgs strict:true wrapper, catch unknown option throw 转友好 stderr + exit 2。
|
|
3
|
+
*
|
|
4
|
+
* 收口理由: parseArgs strict:false 让未声明的 flag 被静默吞掉, 用户写错 flag
|
|
5
|
+
* 名 (或传已删除 flag) 时命令 exit 0 但什么都没生效, 比 fail 还危险。所有
|
|
6
|
+
* 子命令统一走这层, "未知就报错" 一致语义。
|
|
7
|
+
*
|
|
8
|
+
* exit 2 区分于业务 failure 的 exit 1 (doctor / gate / verdict 等), CI 可分别处理。
|
|
9
|
+
*
|
|
10
|
+
* 类型 cast: strict:true 模式下 parseArgs 返回 values 含 array possible (因为
|
|
11
|
+
* options 可声明 multiple)。omk 现有 options 都不用 multiple, 直接 cast 收回
|
|
12
|
+
* 简单类型, caller 解构干净。后续若用 multiple 需要放宽这个 cast。
|
|
13
|
+
*/
|
|
14
|
+
import { parseArgs } from 'node:util';
|
|
15
|
+
export function parseArgsStrictOrExit(opts) {
|
|
16
|
+
try {
|
|
17
|
+
const result = parseArgs({ ...opts, strict: true });
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
process.stderr.write(`error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
22
|
+
process.exit(2);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=parse-strict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-strict.js","sourceRoot":"","sources":["../../../src/cli/parse-strict.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAQtC,MAAM,UAAU,qBAAqB,CAAC,IAAqC;IACzE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,OAAO,MAAqC,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* omk doctor 引擎入口。
|
|
3
|
+
*
|
|
4
|
+
* runDoctor() 接受 target(单文件 / 目录 / null=cwd 默认),解析出 Artifact 列表,
|
|
5
|
+
* 对每个 artifact 顺序跑全部 rules,聚合为 DoctorReport。
|
|
6
|
+
*
|
|
7
|
+
* fatal-fail 不中断后续 rule 执行(让用户一次看到全貌),但 report.failed=true,
|
|
8
|
+
* CLI 据此 exit 1 / abort bench run。
|
|
9
|
+
*/
|
|
10
|
+
import type { Artifact, DoctorReport, DoctorRunOptions } from '../types/index.js';
|
|
11
|
+
/**
|
|
12
|
+
* 把 doctor 的 target 参数解析成 Artifact 列表。
|
|
13
|
+
* - null/undefined: 默认在 cwd/skills 下批量;若不存在则在 cwd 自身找
|
|
14
|
+
* - 文件 (.md): 单 artifact,用 file-path 模式
|
|
15
|
+
* - 目录: discoverVariants 后批量
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveDoctorTargets(target: string | null | undefined, cwd: string): Artifact[];
|
|
18
|
+
export declare function runDoctor(opts: DoctorRunOptions): Promise<DoctorReport>;
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/doctor/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EACV,QAAQ,EAER,YAAY,EAGZ,gBAAgB,EAGjB,MAAM,mBAAmB,CAAC;AAO3B;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,EAAE,CAkC/F;AA4ED,wBAAsB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CA4D7E"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* omk doctor 引擎入口。
|
|
3
|
+
*
|
|
4
|
+
* runDoctor() 接受 target(单文件 / 目录 / null=cwd 默认),解析出 Artifact 列表,
|
|
5
|
+
* 对每个 artifact 顺序跑全部 rules,聚合为 DoctorReport。
|
|
6
|
+
*
|
|
7
|
+
* fatal-fail 不中断后续 rule 执行(让用户一次看到全貌),但 report.failed=true,
|
|
8
|
+
* CLI 据此 exit 1 / abort bench run。
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, statSync } from 'node:fs';
|
|
11
|
+
import { basename, dirname, join, resolve } from 'node:path';
|
|
12
|
+
import { discoverVariants, resolveArtifacts } from '../inputs/skill-loader.js';
|
|
13
|
+
import { getRegisteredRules } from './rules.js';
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Target resolution
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
/**
|
|
18
|
+
* 把 doctor 的 target 参数解析成 Artifact 列表。
|
|
19
|
+
* - null/undefined: 默认在 cwd/skills 下批量;若不存在则在 cwd 自身找
|
|
20
|
+
* - 文件 (.md): 单 artifact,用 file-path 模式
|
|
21
|
+
* - 目录: discoverVariants 后批量
|
|
22
|
+
*/
|
|
23
|
+
export function resolveDoctorTargets(target, cwd) {
|
|
24
|
+
if (target == null) {
|
|
25
|
+
const skillsDir = join(cwd, 'skills');
|
|
26
|
+
if (existsSync(skillsDir) && statSync(skillsDir).isDirectory()) {
|
|
27
|
+
const variants = discoverVariants(skillsDir).filter((v) => v !== 'baseline');
|
|
28
|
+
return variants.length > 0 ? resolveArtifacts(skillsDir, variants, { strictBaseline: false }) : [];
|
|
29
|
+
}
|
|
30
|
+
const variants = discoverVariants(cwd).filter((v) => v !== 'baseline');
|
|
31
|
+
return variants.length > 0 ? resolveArtifacts(cwd, variants, { strictBaseline: false }) : [];
|
|
32
|
+
}
|
|
33
|
+
const absTarget = resolve(target);
|
|
34
|
+
if (!existsSync(absTarget)) {
|
|
35
|
+
throw new Error(`doctor target not found: ${target}`);
|
|
36
|
+
}
|
|
37
|
+
const stat = statSync(absTarget);
|
|
38
|
+
if (stat.isFile() && absTarget.endsWith('.md')) {
|
|
39
|
+
// 单文件:用 file-path 模式(走 resolveArtifacts 的 "包含 /" 分支)
|
|
40
|
+
return resolveArtifacts(dirname(absTarget), [absTarget], { strictBaseline: false });
|
|
41
|
+
}
|
|
42
|
+
if (stat.isDirectory()) {
|
|
43
|
+
// 目录自身就是 directory-skill (含 SKILL.md): 按单个 skill 解析,
|
|
44
|
+
// 让 skill-loader 的 directory-skill 分支命中 (设 skillRoot,
|
|
45
|
+
// 让相对路径 asset 能锚到 skill 根目录)。
|
|
46
|
+
// 否则 discoverVariants 会把 SKILL.md 当成名为 SKILL 的 variant,
|
|
47
|
+
// skillRoot 丢失,assets/foo.md 这类相对依赖会锚到 doctor 的 cwd 而不是
|
|
48
|
+
// skill 目录, 误报缺文件。
|
|
49
|
+
if (existsSync(join(absTarget, 'SKILL.md'))) {
|
|
50
|
+
return resolveArtifacts(dirname(absTarget), [basename(absTarget)], { strictBaseline: false });
|
|
51
|
+
}
|
|
52
|
+
const variants = discoverVariants(absTarget).filter((v) => v !== 'baseline');
|
|
53
|
+
return variants.length > 0 ? resolveArtifacts(absTarget, variants, { strictBaseline: false }) : [];
|
|
54
|
+
}
|
|
55
|
+
throw new Error(`doctor target must be a .md file or directory: ${target}`);
|
|
56
|
+
}
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// Rule execution
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
function classifySkillStatus(results) {
|
|
61
|
+
let hasFatalFail = false;
|
|
62
|
+
let hasWarn = false;
|
|
63
|
+
for (const r of results) {
|
|
64
|
+
if (r.severity === 'fatal' && r.status === 'fail')
|
|
65
|
+
hasFatalFail = true;
|
|
66
|
+
if (r.status === 'warn')
|
|
67
|
+
hasWarn = true;
|
|
68
|
+
}
|
|
69
|
+
if (hasFatalFail)
|
|
70
|
+
return 'fail';
|
|
71
|
+
if (hasWarn)
|
|
72
|
+
return 'warn';
|
|
73
|
+
return 'pass';
|
|
74
|
+
}
|
|
75
|
+
async function runRulesOnArtifact(artifact, rules, ctxBase) {
|
|
76
|
+
const results = [];
|
|
77
|
+
for (const rule of rules) {
|
|
78
|
+
const start = Date.now();
|
|
79
|
+
try {
|
|
80
|
+
const outcome = await rule.check({ ...ctxBase, artifact });
|
|
81
|
+
results.push({
|
|
82
|
+
ruleId: rule.id,
|
|
83
|
+
severity: rule.severity,
|
|
84
|
+
labelKey: rule.labelKey,
|
|
85
|
+
durationMs: Date.now() - start,
|
|
86
|
+
...outcome,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
91
|
+
// rule 自身崩溃也算 fail,不让 doctor 整体挂掉
|
|
92
|
+
results.push({
|
|
93
|
+
ruleId: rule.id,
|
|
94
|
+
severity: rule.severity,
|
|
95
|
+
labelKey: rule.labelKey,
|
|
96
|
+
status: 'fail',
|
|
97
|
+
message: `rule crashed: ${message.slice(0, 160)}`,
|
|
98
|
+
hint: undefined,
|
|
99
|
+
detail: { ruleCrash: true, error: message },
|
|
100
|
+
durationMs: Date.now() - start,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return results;
|
|
105
|
+
}
|
|
106
|
+
function inferSkillPath(artifact, baseDir) {
|
|
107
|
+
if (artifact.locator)
|
|
108
|
+
return artifact.locator;
|
|
109
|
+
if (artifact.skillRoot)
|
|
110
|
+
return artifact.skillRoot;
|
|
111
|
+
// fallback: 拼一个推断路径(用于 report 显示,不参与 io)
|
|
112
|
+
return join(baseDir, artifact.name.endsWith('.md') ? artifact.name : `${artifact.name}.md`);
|
|
113
|
+
}
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// Public entry
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
let reportIdCounter = 0;
|
|
118
|
+
function nextReportId() {
|
|
119
|
+
reportIdCounter += 1;
|
|
120
|
+
const ts = new Date().toISOString().replace(/[-:.]/g, '').slice(0, 15);
|
|
121
|
+
return `doctor-${ts}-${reportIdCounter}`;
|
|
122
|
+
}
|
|
123
|
+
function readCliVersion() {
|
|
124
|
+
// 不依赖 package.json import(避免 type 解析复杂度);用环境变量或退回 'unknown'
|
|
125
|
+
return process.env.npm_package_version ?? '0.0.0';
|
|
126
|
+
}
|
|
127
|
+
export async function runDoctor(opts) {
|
|
128
|
+
// 默认规则 = 内置 + registerRule() 注册的 custom。test 注入走 opts.rules。
|
|
129
|
+
const effectiveRules = opts.rules && opts.rules.length > 0 ? opts.rules : getRegisteredRules();
|
|
130
|
+
// artifacts 显式提供时跳过 target 解析(嵌入 bench run/gate 的路径用,
|
|
131
|
+
// 避免扫整个 skillDir)。空数组合法且明确 — 表示"本次评测没 skill 需要 doctor"
|
|
132
|
+
// (e.g. baseline-only 或纯 runtime-context-only run), doctor 不该再扫
|
|
133
|
+
// skillDir 找无关草稿。只有 artifacts 完全 undefined 时才 fallback 到 target 解析。
|
|
134
|
+
const artifacts = opts.artifacts !== undefined
|
|
135
|
+
? opts.artifacts
|
|
136
|
+
: resolveDoctorTargets(opts.target, opts.cwd);
|
|
137
|
+
// dependencyCwd 选择优先级与 evaluation-pipeline.ts 的 dependency check 规则
|
|
138
|
+
// 严格对齐: artifact.cwd > opts.dependencyCwd (CLI 传 skillDir) > opts.cwd。
|
|
139
|
+
// 不对齐会让 requires.files / requires.preflight 在 doctor 和 eval 之间产生
|
|
140
|
+
// false-positive (文件在 skillDir 存在 doctor 误 fail) 或 false-negative
|
|
141
|
+
// (文件只在项目 cwd 存在 doctor pass 但 eval fail) 不一致。
|
|
142
|
+
const dependencyCwd = artifacts.find((a) => a.cwd)?.cwd
|
|
143
|
+
?? opts.dependencyCwd
|
|
144
|
+
?? opts.cwd;
|
|
145
|
+
const ctxBase = {
|
|
146
|
+
samples: opts.samples,
|
|
147
|
+
requires: opts.requires,
|
|
148
|
+
executorName: opts.executorName,
|
|
149
|
+
model: opts.model,
|
|
150
|
+
cwd: opts.cwd,
|
|
151
|
+
dependencyCwd,
|
|
152
|
+
lang: opts.lang,
|
|
153
|
+
timeoutMs: opts.timeoutMs,
|
|
154
|
+
};
|
|
155
|
+
const skillReports = [];
|
|
156
|
+
const totals = { pass: 0, warn: 0, fail: 0 };
|
|
157
|
+
for (const artifact of artifacts) {
|
|
158
|
+
const results = await runRulesOnArtifact(artifact, effectiveRules, ctxBase);
|
|
159
|
+
const status = classifySkillStatus(results);
|
|
160
|
+
skillReports.push({
|
|
161
|
+
skillName: basename(artifact.name).replace(/\.md$/, ''),
|
|
162
|
+
skillPath: inferSkillPath(artifact, opts.cwd),
|
|
163
|
+
results,
|
|
164
|
+
status,
|
|
165
|
+
});
|
|
166
|
+
totals[status] += 1;
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
kind: 'doctor',
|
|
170
|
+
id: nextReportId(),
|
|
171
|
+
timestamp: new Date().toISOString(),
|
|
172
|
+
cliVersion: readCliVersion(),
|
|
173
|
+
cwd: opts.cwd,
|
|
174
|
+
executorName: opts.executorName,
|
|
175
|
+
model: opts.model,
|
|
176
|
+
skills: skillReports,
|
|
177
|
+
failed: totals.fail > 0,
|
|
178
|
+
warned: totals.warn > 0,
|
|
179
|
+
totals,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/doctor/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAW/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAiC,EAAE,GAAW;IACjF,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;QACnB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACtC,IAAI,UAAU,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YAC/D,MAAM,QAAQ,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC;YAC7E,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACrG,CAAC;QACD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC;QACvE,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/F,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,4BAA4B,MAAM,EAAE,CAAC,CAAC;IACxD,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IACjC,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,qDAAqD;QACrD,OAAO,gBAAgB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACvB,qDAAqD;QACrD,sDAAsD;QACtD,8BAA8B;QAC9B,wDAAwD;QACxD,wDAAwD;QACxD,mBAAmB;QACnB,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;YAC5C,OAAO,gBAAgB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;QAChG,CAAC;QACD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC;QAC7E,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACrG,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,kDAAkD,MAAM,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,SAAS,mBAAmB,CAAC,OAA2B;IACtD,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;YAAE,YAAY,GAAG,IAAI,CAAC;QACvE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO,GAAG,IAAI,CAAC;IAC1C,CAAC;IACD,IAAI,YAAY;QAAE,OAAO,MAAM,CAAC;IAChC,IAAI,OAAO;QAAE,OAAO,MAAM,CAAC;IAC3B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,QAAkB,EAClB,KAAmB,EACnB,OAAwC;IAExC,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;gBAC9B,GAAG,OAAO;aACX,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,kCAAkC;YAClC,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,iBAAiB,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;gBACjD,IAAI,EAAE,SAAS;gBACf,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE;gBAC3C,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;aAC/B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,cAAc,CAAC,QAAkB,EAAE,OAAe;IACzD,IAAI,QAAQ,CAAC,OAAO;QAAE,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC9C,IAAI,QAAQ,CAAC,SAAS;QAAE,OAAO,QAAQ,CAAC,SAAS,CAAC;IAClD,yCAAyC;IACzC,OAAO,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,KAAK,CAAC,CAAC;AAC9F,CAAC;AAED,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E,IAAI,eAAe,GAAG,CAAC,CAAC;AACxB,SAAS,YAAY;IACnB,eAAe,IAAI,CAAC,CAAC;IACrB,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvE,OAAO,UAAU,EAAE,IAAI,eAAe,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,cAAc;IACrB,4DAA4D;IAC5D,OAAO,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAsB;IACpD,6DAA6D;IAC7D,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC;IAE/F,sDAAsD;IACtD,uDAAuD;IACvD,gEAAgE;IAChE,oEAAoE;IACpE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,KAAK,SAAS;QAC5C,CAAC,CAAC,IAAI,CAAC,SAAS;QAChB,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IAEhD,oEAAoE;IACpE,uEAAuE;IACvE,iEAAiE;IACjE,kEAAkE;IAClE,+CAA+C;IAC/C,MAAM,aAAa,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG;WAClD,IAAI,CAAC,aAAa;WAClB,IAAI,CAAC,GAAG,CAAC;IAEd,MAAM,OAAO,GAAoC;QAC/C,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,aAAa;QACb,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC;IAEF,MAAM,YAAY,GAAwB,EAAE,CAAC;IAC7C,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAE7C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAC5E,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC5C,YAAY,CAAC,IAAI,CAAC;YAChB,SAAS,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YACvD,SAAS,EAAE,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC;YAC7C,OAAO;YACP,MAAM;SACP,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,EAAE,EAAE,YAAY,EAAE;QAClB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,UAAU,EAAE,cAAc,EAAE;QAC5B,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,MAAM,EAAE,YAAY;QACpB,MAAM,EAAE,MAAM,CAAC,IAAI,GAAG,CAAC;QACvB,MAAM,EAAE,MAAM,CAAC,IAAI,GAAG,CAAC;QACvB,MAAM;KACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* doctor preflight context builder。
|
|
3
|
+
*
|
|
4
|
+
* 把「评测前 doctor 要检查什么 + 路径上下文锚到哪里」从评测引擎里抽出来,
|
|
5
|
+
* 让 doctor engine 只消费 ctx, 不再自己猜 bench 的路径语义。
|
|
6
|
+
*
|
|
7
|
+
* Bench 路径语义本来就复杂(.md / SKILL.md 目录 / git: / 绝对路径 / name@cwd /
|
|
8
|
+
* runtime-context-only / batch paired samples), doctor 嵌入需要用而不是旁路重建。
|
|
9
|
+
* 任何 bench 路径推断的边界变化,只需改这一处, doctor engine 零修改。
|
|
10
|
+
*
|
|
11
|
+
* 不服务 standalone `omk doctor [path]` — 那条路径是用户视角的 target 解析,
|
|
12
|
+
* 由 src/doctor/index.ts:resolveDoctorTargets() 单独负责。
|
|
13
|
+
*/
|
|
14
|
+
import type { DependencyRequirements } from '../eval-core/dependency-checker.js';
|
|
15
|
+
import type { Artifact, Sample } from '../types/index.js';
|
|
16
|
+
export interface DoctorPreflightContext {
|
|
17
|
+
/** 过滤掉 baseline-kind 后的 artifact 列表; doctor 只检查实际被测的 skill。 */
|
|
18
|
+
doctorArtifacts: Artifact[];
|
|
19
|
+
/** dependency / preflight 路径基准。
|
|
20
|
+
* 解析规则与 src/eval-workflows/evaluation-pipeline.ts 的 dependency check 严格对齐:
|
|
21
|
+
* artifacts.find(a => a.cwd)?.cwd > resolve(skillDir) > process.cwd()。 */
|
|
22
|
+
dependencyCwd: string;
|
|
23
|
+
samples?: Sample[];
|
|
24
|
+
requires?: DependencyRequirements;
|
|
25
|
+
}
|
|
26
|
+
export declare function buildDoctorPreflightContext(input: {
|
|
27
|
+
artifacts: Artifact[];
|
|
28
|
+
samples?: Sample[];
|
|
29
|
+
requires?: DependencyRequirements;
|
|
30
|
+
skillDir: string;
|
|
31
|
+
}): DoctorPreflightContext | null;
|
|
32
|
+
//# sourceMappingURL=preflight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../../../src/doctor/preflight.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,WAAW,sBAAsB;IACrC,+DAA+D;IAC/D,eAAe,EAAE,QAAQ,EAAE,CAAC;IAC5B;;+EAE2E;IAC3E,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,sBAAsB,CAAC;CACnC;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE;IACjD,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,sBAAsB,GAAG,IAAI,CAiBhC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* doctor preflight context builder。
|
|
3
|
+
*
|
|
4
|
+
* 把「评测前 doctor 要检查什么 + 路径上下文锚到哪里」从评测引擎里抽出来,
|
|
5
|
+
* 让 doctor engine 只消费 ctx, 不再自己猜 bench 的路径语义。
|
|
6
|
+
*
|
|
7
|
+
* Bench 路径语义本来就复杂(.md / SKILL.md 目录 / git: / 绝对路径 / name@cwd /
|
|
8
|
+
* runtime-context-only / batch paired samples), doctor 嵌入需要用而不是旁路重建。
|
|
9
|
+
* 任何 bench 路径推断的边界变化,只需改这一处, doctor engine 零修改。
|
|
10
|
+
*
|
|
11
|
+
* 不服务 standalone `omk doctor [path]` — 那条路径是用户视角的 target 解析,
|
|
12
|
+
* 由 src/doctor/index.ts:resolveDoctorTargets() 单独负责。
|
|
13
|
+
*/
|
|
14
|
+
import { resolve } from 'node:path';
|
|
15
|
+
export function buildDoctorPreflightContext(input) {
|
|
16
|
+
const doctorArtifacts = input.artifacts.filter((a) => a.kind !== 'baseline');
|
|
17
|
+
if (doctorArtifacts.length === 0)
|
|
18
|
+
return null; // baseline-only run, doctor skip
|
|
19
|
+
// dependencyCwd 解析必须看完整 input.artifacts(包括 baseline-kind),
|
|
20
|
+
// 因为 `project-env@/repo` 这类 runtime-context-only 在 skill-loader.ts:242
|
|
21
|
+
// 会被生成成 kind:'baseline' 但带 cwd。如果只看 doctorArtifacts 就会丢这个
|
|
22
|
+
// cwd, 让 requires.files / preflight 错锚到 skillDir, false-fail 用户。
|
|
23
|
+
const dependencyCwd = input.artifacts.find((a) => a.cwd)?.cwd
|
|
24
|
+
?? resolve(input.skillDir);
|
|
25
|
+
return {
|
|
26
|
+
doctorArtifacts,
|
|
27
|
+
dependencyCwd,
|
|
28
|
+
samples: input.samples,
|
|
29
|
+
requires: input.requires,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=preflight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../../src/doctor/preflight.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC,MAAM,UAAU,2BAA2B,CAAC,KAK3C;IACC,MAAM,eAAe,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAC7E,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,iCAAiC;IAEhF,2DAA2D;IAC3D,uEAAuE;IACvE,0DAA0D;IAC1D,iEAAiE;IACjE,MAAM,aAAa,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG;WACxD,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAE7B,OAAO;QACL,eAAe;QACf,aAAa;QACb,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* omk doctor 输出渲染器。
|
|
3
|
+
*
|
|
4
|
+
* 双形态:
|
|
5
|
+
* - renderDoctorReportText: 终端友好,符号 + 标签 + 消息 + hint。stream 写到给定
|
|
6
|
+
* write 函数(默认 stderr,因为 doctor 用 --json 模式时 stdout 应该是结构化 JSON)。
|
|
7
|
+
* - renderDoctorReportJson: 直接 JSON.stringify。CI 消费。
|
|
8
|
+
*/
|
|
9
|
+
import { type CliLang } from '../cli/i18n.js';
|
|
10
|
+
import type { DoctorReport } from '../types/index.js';
|
|
11
|
+
export declare function renderDoctorReportText(report: DoctorReport, lang: CliLang, write?: (s: string) => void): void;
|
|
12
|
+
export declare function renderDoctorReportJson(report: DoctorReport): string;
|
|
13
|
+
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../src/doctor/renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,KAAK,EACV,YAAY,EAGb,MAAM,mBAAmB,CAAC;AA2B3B,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,OAAO,EACb,KAAK,GAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAqC,GAC1D,IAAI,CAyBN;AAaD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAEnE"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* omk doctor 输出渲染器。
|
|
3
|
+
*
|
|
4
|
+
* 双形态:
|
|
5
|
+
* - renderDoctorReportText: 终端友好,符号 + 标签 + 消息 + hint。stream 写到给定
|
|
6
|
+
* write 函数(默认 stderr,因为 doctor 用 --json 模式时 stdout 应该是结构化 JSON)。
|
|
7
|
+
* - renderDoctorReportJson: 直接 JSON.stringify。CI 消费。
|
|
8
|
+
*/
|
|
9
|
+
import { tCli } from '../cli/i18n.js';
|
|
10
|
+
import { CLI_DICT } from './../cli/i18n-dict.js';
|
|
11
|
+
const STATUS_SYMBOL = {
|
|
12
|
+
pass: '✓',
|
|
13
|
+
warn: '⚠',
|
|
14
|
+
fail: '✗',
|
|
15
|
+
skipped: '⊙',
|
|
16
|
+
};
|
|
17
|
+
function statusLabel(status, lang) {
|
|
18
|
+
if (lang === 'zh') {
|
|
19
|
+
return { pass: '通过', warn: '警告', fail: '失败', skipped: '跳过' }[status];
|
|
20
|
+
}
|
|
21
|
+
return { pass: 'PASS', warn: 'WARN', fail: 'FAIL', skipped: 'SKIP' }[status];
|
|
22
|
+
}
|
|
23
|
+
function renderRuleLine(result, ruleLabel, lang) {
|
|
24
|
+
const sym = STATUS_SYMBOL[result.status];
|
|
25
|
+
const sLabel = statusLabel(result.status, lang);
|
|
26
|
+
// 主行: ✓ [PASS] skill 文件可读 — skill 内容长度 28 字符
|
|
27
|
+
let line = ` ${sym} [${sLabel}] ${ruleLabel} — ${result.message}`;
|
|
28
|
+
if (result.hint) {
|
|
29
|
+
line += `\n 💡 ${result.hint}`;
|
|
30
|
+
}
|
|
31
|
+
return line;
|
|
32
|
+
}
|
|
33
|
+
export function renderDoctorReportText(report, lang, write = (s) => process.stderr.write(s)) {
|
|
34
|
+
const header = lang === 'zh'
|
|
35
|
+
? `omk doctor 健康检查 — ${report.cwd}`
|
|
36
|
+
: `omk doctor health check — ${report.cwd}`;
|
|
37
|
+
write(`\n${header}\n`);
|
|
38
|
+
write('─'.repeat(Math.min(70, header.length + 10)) + '\n');
|
|
39
|
+
if (report.skills.length === 0) {
|
|
40
|
+
write(lang === 'zh' ? '\n未发现 skill。\n' : '\nNo skills found.\n');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
for (const skill of report.skills) {
|
|
44
|
+
write(`\n[${skill.skillName}] ${skill.skillPath}\n`);
|
|
45
|
+
for (const result of skill.results) {
|
|
46
|
+
const ruleLabel = renderRuleLabel(result, lang);
|
|
47
|
+
write(renderRuleLine(result, ruleLabel, lang) + '\n');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// 总览
|
|
51
|
+
const summary = lang === 'zh'
|
|
52
|
+
? `\n总览: ${report.totals.pass} 通过 / ${report.totals.warn} 警告 / ${report.totals.fail} 失败\n`
|
|
53
|
+
: `\nSummary: ${report.totals.pass} pass / ${report.totals.warn} warn / ${report.totals.fail} fail\n`;
|
|
54
|
+
write(summary);
|
|
55
|
+
}
|
|
56
|
+
/** 用 result.labelKey 翻译 rule 标题。已知 i18n key 走 tCli; 自定义 rule 用未注册的
|
|
57
|
+
* key 时直接显示 ruleId 作为 fallback (而不是错挂到 skill_readable 的标题)。 */
|
|
58
|
+
function renderRuleLabel(result, lang) {
|
|
59
|
+
const key = result.labelKey;
|
|
60
|
+
// labelKey 是已注册的 CliMessageKey 时走 i18n; 否则 fallback 用 ruleId
|
|
61
|
+
if (key in CLI_DICT) {
|
|
62
|
+
return tCli(key, lang);
|
|
63
|
+
}
|
|
64
|
+
return result.ruleId;
|
|
65
|
+
}
|
|
66
|
+
export function renderDoctorReportJson(report) {
|
|
67
|
+
return JSON.stringify(report, null, 2);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../../src/doctor/renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* omk doctor 内置规则注册表。
|
|
3
|
+
*
|
|
4
|
+
* doctor 是**纯静态/低成本检查**, 不碰 LLM 连通性 — executor / judge 连通性由
|
|
5
|
+
* evaluation preflight 负责。边界清晰: doctor 静态(零 LLM 调用), eval 动态。
|
|
6
|
+
*
|
|
7
|
+
* 每条 rule 回答一个独立的「skill 能不能被有意义评测」子问题:
|
|
8
|
+
* - skill_readable: 文件能读、内容非空且有最小长度
|
|
9
|
+
* - skill_metadata: front-matter(若有) YAML 合法、directory-skill 有 SKILL.md
|
|
10
|
+
* - dependencies: 引用的 tool / file / env / preflight 完整(复用 preflightDependencies)
|
|
11
|
+
* - samples_contract: 仅在传 samples 时跑,warn 级,校验 samples 非空 + 含 prompt
|
|
12
|
+
*
|
|
13
|
+
* fatal-fail 时 rule 引擎不中断后续 rule 执行(让用户一次看到全貌),
|
|
14
|
+
* 但 DoctorReport.failed 会置 true。
|
|
15
|
+
*
|
|
16
|
+
* 扩展接口预留: registerRule() 允许业务方注入自定义 rule(v0.22 不暴露 CLI flag,
|
|
17
|
+
* 仅作为 library API 占位)。
|
|
18
|
+
*/
|
|
19
|
+
import type { DoctorRule } from '../types/doctor.js';
|
|
20
|
+
export declare const skillReadableRule: DoctorRule;
|
|
21
|
+
export declare const skillMetadataRule: DoctorRule;
|
|
22
|
+
export declare const dependenciesPresentRule: DoctorRule;
|
|
23
|
+
export declare const samplesContractAlignedRule: DoctorRule;
|
|
24
|
+
/** v0.22 内置规则注册表。执行顺序即此处定义顺序。
|
|
25
|
+
* doctor 不包含 executor 连通性检查 — 该职责属于 evaluation preflight。 */
|
|
26
|
+
export declare const BUILTIN_RULES: DoctorRule[];
|
|
27
|
+
export declare function registerRule(rule: DoctorRule): void;
|
|
28
|
+
export declare function getRegisteredRules(): DoctorRule[];
|
|
29
|
+
export declare function __resetCustomRulesForTest(): void;
|
|
30
|
+
//# sourceMappingURL=rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/doctor/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAQH,OAAO,KAAK,EACV,UAAU,EAGX,MAAM,oBAAoB,CAAC;AA8C5B,eAAO,MAAM,iBAAiB,EAAE,UAqC/B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,UAiC/B,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,UA2BrC,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,UAkCxC,CAAC;AAMF;8DAC8D;AAC9D,eAAO,MAAM,aAAa,EAAE,UAAU,EAKrC,CAAC;AAKF,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAKnD;AAED,wBAAgB,kBAAkB,IAAI,UAAU,EAAE,CAEjD;AAED,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}
|