oh-my-knowledge 1.0.0-beta.3 → 1.0.0-beta.4

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 (271) hide show
  1. package/README.md +2 -2
  2. package/README.zh.md +2 -2
  3. package/dist/assets/agent-skills/omk/references/commands.md +4 -3
  4. package/dist/cli/commands/eval/gold/compare.d.ts +1 -0
  5. package/dist/cli/commands/eval/gold/compare.js +25 -10
  6. package/dist/cli/commands/eval/gold/validate.js +7 -3
  7. package/dist/cli/commands/eval/index.js +4 -1
  8. package/dist/cli/commands/init.js +4 -4
  9. package/dist/cli/commands/studio.js +4 -4
  10. package/dist/cli/lib/i18n-dict/init.js +2 -2
  11. package/dist/cli/lib/i18n-dict/run.js +2 -2
  12. package/dist/cli/lib/run-core-evaluation.js +3 -0
  13. package/dist/cli/templates/init-samples.js +71 -91
  14. package/dist/dsh-plugin/core-command.js +19 -19
  15. package/dist/eval-core/analysis/builtins.d.ts +8 -0
  16. package/dist/eval-core/analysis/builtins.js +1334 -33
  17. package/dist/eval-core/analysis/decision.js +2 -2
  18. package/dist/eval-core/analysis/runtime.js +12 -2
  19. package/dist/eval-core/compiler/immutability.d.ts +1 -1
  20. package/dist/eval-core/compiler/immutability.js +1 -12
  21. package/dist/eval-core/compiler/index.d.ts +2 -2
  22. package/dist/eval-core/compiler/index.js +48 -9
  23. package/dist/eval-core/compiler/types.d.ts +9 -1
  24. package/dist/eval-core/compiler/types.js +1 -0
  25. package/dist/eval-core/compiler/validation.d.ts +3 -0
  26. package/dist/eval-core/compiler/validation.js +304 -25
  27. package/dist/eval-core/contracts/analysis-bundle.d.ts +15 -0
  28. package/dist/eval-core/contracts/analysis-bundle.js +36 -2
  29. package/dist/eval-core/contracts/analysis-input-matching.d.ts +4 -0
  30. package/dist/eval-core/contracts/analysis-input-matching.js +29 -0
  31. package/dist/eval-core/contracts/common.d.ts +5 -0
  32. package/dist/eval-core/contracts/comparability.d.ts +1 -1
  33. package/dist/eval-core/contracts/comparability.js +14 -1
  34. package/dist/eval-core/contracts/definition.d.ts +253 -7
  35. package/dist/eval-core/contracts/definition.js +29 -3
  36. package/dist/eval-core/contracts/digests.d.ts +8 -1
  37. package/dist/eval-core/contracts/digests.js +168 -5
  38. package/dist/eval-core/contracts/evaluation-bundle.js +5 -16
  39. package/dist/eval-core/contracts/execution-controls.d.ts +162 -0
  40. package/dist/eval-core/contracts/execution-controls.js +43 -1
  41. package/dist/eval-core/contracts/execution-identities.d.ts +1 -1
  42. package/dist/eval-core/contracts/execution-identities.js +33 -3
  43. package/dist/eval-core/contracts/immutability.d.ts +2 -0
  44. package/dist/eval-core/contracts/immutability.js +20 -0
  45. package/dist/eval-core/contracts/index.d.ts +1 -0
  46. package/dist/eval-core/contracts/index.js +1 -0
  47. package/dist/eval-core/contracts/json.js +3 -10
  48. package/dist/eval-core/contracts/plans.d.ts +324 -14
  49. package/dist/eval-core/contracts/plans.js +12 -6
  50. package/dist/eval-core/contracts/schemas/{v1 → v2}/execution-plan.schema.json +205 -82
  51. package/dist/eval-core/contracts/schemas/{v1 → v3}/analysis-plan.schema.json +159 -42
  52. package/dist/eval-core/contracts/schemas/{v1 → v3}/evaluation-definition.schema.json +233 -116
  53. package/dist/eval-core/contracts/schemas/v3/execution-plan.schema.json +1177 -0
  54. package/dist/eval-core/contracts/schemas/{v1 → v3}/run-plan.schema.json +594 -445
  55. package/dist/eval-core/contracts/schemas/v4/evaluation-definition.schema.json +1407 -0
  56. package/dist/eval-core/contracts/schemas/v4/execution-plan.schema.json +1221 -0
  57. package/dist/eval-core/contracts/schemas/v4/run-plan.schema.json +2710 -0
  58. package/dist/eval-core/contracts/schemas/v5/evaluation-definition.schema.json +1451 -0
  59. package/dist/eval-core/contracts/schemas/v5/run-plan.schema.json +2754 -0
  60. package/dist/eval-core/{internal → contracts}/sealed-run-plan.d.ts +2 -2
  61. package/dist/eval-core/{internal → contracts}/sealed-run-plan.js +1 -1
  62. package/dist/eval-core/contracts/series.d.ts +1 -1
  63. package/dist/eval-core/contracts/series.js +1 -1
  64. package/dist/eval-core/contracts/statistics.d.ts +2 -0
  65. package/dist/eval-core/contracts/statistics.js +19 -0
  66. package/dist/eval-core/engine/index.d.ts +21 -1
  67. package/dist/eval-core/engine/index.js +59 -25
  68. package/dist/eval-core/engine/types.d.ts +2 -0
  69. package/dist/eval-core/evaluation/runtime.js +5 -6
  70. package/dist/eval-core/execution/runtime.js +7 -3
  71. package/dist/eval-core/execution/types.d.ts +2 -0
  72. package/dist/eval-core/facade.d.ts +1 -1
  73. package/dist/eval-core/facade.js +1 -1
  74. package/dist/eval-core/index.d.ts +2 -2
  75. package/dist/eval-core/index.js +1 -1
  76. package/dist/eval-core/schemas.js +10 -0
  77. package/dist/eval-core/series/builtins.d.ts +30 -0
  78. package/dist/eval-core/series/builtins.js +226 -0
  79. package/dist/eval-core/series/index.d.ts +1 -0
  80. package/dist/eval-core/series/index.js +1 -0
  81. package/dist/eval-core/series/runtime.js +10 -1
  82. package/dist/eval-runtime/adapters/executor-fn.js +3 -3
  83. package/dist/eval-runtime/adapters/invoke-contract.d.ts +104 -2
  84. package/dist/eval-runtime/adapters/invoke-contract.js +11 -5
  85. package/dist/eval-runtime/adapters/json-executor.d.ts +56 -0
  86. package/dist/eval-runtime/adapters/json-executor.js +853 -67
  87. package/dist/eval-runtime/advanced.d.ts +11 -7
  88. package/dist/eval-runtime/advanced.js +4 -4
  89. package/dist/eval-runtime/builders/paired-comparison.js +8 -1
  90. package/dist/eval-runtime/builders/policy.d.ts +220 -4
  91. package/dist/eval-runtime/builders/policy.js +189 -33
  92. package/dist/eval-runtime/conformance/cache.d.ts +26 -0
  93. package/dist/eval-runtime/conformance/cache.js +305 -0
  94. package/dist/eval-runtime/conformance/content-store.d.ts +27 -0
  95. package/dist/eval-runtime/conformance/content-store.js +98 -0
  96. package/dist/eval-runtime/conformance/evaluator.d.ts +38 -0
  97. package/dist/eval-runtime/conformance/evaluator.js +281 -0
  98. package/dist/eval-runtime/conformance/executor.d.ts +2 -1
  99. package/dist/eval-runtime/conformance/executor.js +10 -5
  100. package/dist/eval-runtime/conformance/judge.d.ts +43 -0
  101. package/dist/eval-runtime/conformance/judge.js +276 -0
  102. package/dist/eval-runtime/conformance/runtime.d.ts +48 -0
  103. package/dist/eval-runtime/conformance/runtime.js +130 -0
  104. package/dist/eval-runtime/conformance/workspace-provider.d.ts +20 -0
  105. package/dist/eval-runtime/conformance/workspace-provider.js +260 -0
  106. package/dist/eval-runtime/custom-evaluator.d.ts +106 -0
  107. package/dist/eval-runtime/custom-evaluator.js +285 -0
  108. package/dist/eval-runtime/evaluate.d.ts +387 -37
  109. package/dist/eval-runtime/evaluate.js +2317 -249
  110. package/dist/eval-runtime/evaluators/retrieval.d.ts +30 -0
  111. package/dist/eval-runtime/evaluators/retrieval.js +172 -0
  112. package/dist/eval-runtime/evaluators/tool-trajectory.d.ts +22 -0
  113. package/dist/eval-runtime/evaluators/tool-trajectory.js +177 -0
  114. package/dist/eval-runtime/execution-controls.d.ts +6 -0
  115. package/dist/eval-runtime/execution-controls.js +57 -0
  116. package/dist/eval-runtime/identity.d.ts +22 -0
  117. package/dist/eval-runtime/identity.js +45 -17
  118. package/dist/eval-runtime/index.d.ts +22 -2
  119. package/dist/eval-runtime/index.js +5 -1
  120. package/dist/eval-runtime/infrastructure.d.ts +51 -0
  121. package/dist/eval-runtime/infrastructure.js +89 -0
  122. package/dist/eval-runtime/judges/rubric-contracts.d.ts +1 -0
  123. package/dist/eval-runtime/judges/rubric-judge.d.ts +1 -0
  124. package/dist/eval-runtime/judges/rubric-judge.js +15 -1
  125. package/dist/eval-runtime/mcp-config.d.ts +48 -0
  126. package/dist/eval-runtime/mcp-config.js +90 -0
  127. package/dist/eval-runtime/mock-interception.d.ts +65 -0
  128. package/dist/eval-runtime/mock-interception.js +109 -0
  129. package/dist/eval-runtime/result-store.d.ts +45 -0
  130. package/dist/eval-runtime/result-store.js +247 -0
  131. package/dist/eval-runtime/runner.d.ts +18 -6
  132. package/dist/eval-runtime/runner.js +50 -28
  133. package/dist/eval-runtime/series.d.ts +85 -0
  134. package/dist/eval-runtime/series.js +383 -0
  135. package/dist/eval-runtime/tool-policy.d.ts +12 -0
  136. package/dist/eval-runtime/tool-policy.js +69 -0
  137. package/dist/eval-runtime/workspace.d.ts +49 -0
  138. package/dist/eval-runtime/workspace.js +84 -0
  139. package/dist/eval-workflows/analysis/binomial-confidence.d.ts +13 -0
  140. package/dist/eval-workflows/analysis/binomial-confidence.js +122 -0
  141. package/dist/eval-workflows/analysis/bootstrap.d.ts +17 -5
  142. package/dist/eval-workflows/analysis/bootstrap.js +73 -30
  143. package/dist/eval-workflows/analysis/sample-size.d.ts +16 -0
  144. package/dist/eval-workflows/analysis/sample-size.js +83 -0
  145. package/dist/eval-workflows/artifact-store/contracts.d.ts +2 -2
  146. package/dist/eval-workflows/artifact-store/node-run-store.js +10 -1
  147. package/dist/eval-workflows/evaluation-defaults.d.ts +4 -0
  148. package/dist/eval-workflows/evaluation-defaults.js +4 -0
  149. package/dist/eval-workflows/gold/cli.d.ts +1 -1
  150. package/dist/eval-workflows/gold/cli.js +4 -4
  151. package/dist/eval-workflows/gold/dataset.d.ts +4 -0
  152. package/dist/eval-workflows/gold/dataset.js +60 -12
  153. package/dist/eval-workflows/gold/human.d.ts +56 -0
  154. package/dist/eval-workflows/gold/human.js +121 -30
  155. package/dist/eval-workflows/input-compilation/compile.js +45 -16
  156. package/dist/eval-workflows/input-compilation/parse.js +78 -2
  157. package/dist/eval-workflows/input-compilation/registry.d.ts +1 -1
  158. package/dist/eval-workflows/input-compilation/registry.js +13 -1
  159. package/dist/eval-workflows/input-compilation/types.d.ts +18 -5
  160. package/dist/eval-workflows/input-compilation/types.js +3 -3
  161. package/dist/eval-workflows/inputs/contracts/config.d.ts +14 -0
  162. package/dist/eval-workflows/inputs/contracts/sample.d.ts +9 -3
  163. package/dist/eval-workflows/inputs/contracts/schemas/{v1 → v2}/eval-sample-set.schema.json +148 -129
  164. package/dist/eval-workflows/inputs/eval-config.d.ts +1 -1
  165. package/dist/eval-workflows/inputs/eval-config.js +111 -2
  166. package/dist/eval-workflows/inputs/eval-samples.d.ts +1 -1
  167. package/dist/eval-workflows/inputs/eval-samples.js +1 -1
  168. package/dist/eval-workflows/inputs/load-samples.d.ts +1 -1
  169. package/dist/eval-workflows/inputs/load-samples.js +1 -1
  170. package/dist/eval-workflows/inputs/rubric-contract.d.ts +2 -0
  171. package/dist/eval-workflows/inputs/rubric-contract.js +2 -0
  172. package/dist/eval-workflows/inputs/sample-contract.js +14 -6
  173. package/dist/eval-workflows/inputs/schemas/json-schema.js +22 -1
  174. package/dist/eval-workflows/inputs/schemas/sample-set.d.ts +3 -2
  175. package/dist/eval-workflows/inputs/schemas/sample-set.js +18 -4
  176. package/dist/eval-workflows/instruments/contracts/config.d.ts +7 -2
  177. package/dist/eval-workflows/instruments/contracts/index.d.ts +0 -1
  178. package/dist/eval-workflows/messages.d.ts +1 -1
  179. package/dist/eval-workflows/messages.js +0 -12
  180. package/dist/eval-workflows/production-host/index.d.ts +1 -0
  181. package/dist/eval-workflows/production-host/index.js +1 -0
  182. package/dist/eval-workflows/production-host/judge-provider-identity.d.ts +9 -0
  183. package/dist/eval-workflows/production-host/judge-provider-identity.js +89 -0
  184. package/dist/eval-workflows/production-host/measurement-design.js +56 -26
  185. package/dist/eval-workflows/production-host/node-cli-composition.js +17 -26
  186. package/dist/eval-workflows/production-host/node-cli-evaluation-resolver.js +93 -14
  187. package/dist/eval-workflows/projections/contracts.d.ts +45 -8
  188. package/dist/eval-workflows/projections/contracts.js +1 -1
  189. package/dist/eval-workflows/projections/gold.d.ts +2 -0
  190. package/dist/eval-workflows/projections/gold.js +107 -14
  191. package/dist/eval-workflows/runtime-adapter/adapters/claude/cli.js +1 -1
  192. package/dist/eval-workflows/runtime-adapter/adapters/claude/resources.d.ts +2 -29
  193. package/dist/eval-workflows/runtime-adapter/adapters/claude/resources.js +150 -98
  194. package/dist/eval-workflows/runtime-adapter/adapters/custom/command.d.ts +33 -0
  195. package/dist/eval-workflows/runtime-adapter/adapters/custom/command.js +129 -5
  196. package/dist/eval-workflows/runtime-adapter/analysis/agreement-node-contract.d.ts +6 -1
  197. package/dist/eval-workflows/runtime-adapter/analysis/agreement-node-contract.js +100 -31
  198. package/dist/eval-workflows/runtime-adapter/analysis/agreement-node.d.ts +1 -1
  199. package/dist/eval-workflows/runtime-adapter/analysis/agreement-node.js +49 -4
  200. package/dist/eval-workflows/runtime-adapter/analysis/agreement-source-adapter-v1.d.ts +11 -0
  201. package/dist/eval-workflows/runtime-adapter/analysis/agreement-source-adapter-v1.js +114 -0
  202. package/dist/eval-workflows/runtime-adapter/analysis/agreement-source-adapter.js +1 -1
  203. package/dist/eval-workflows/runtime-adapter/analysis/agreement-table.d.ts +207 -1
  204. package/dist/eval-workflows/runtime-adapter/analysis/agreement-table.js +134 -5
  205. package/dist/eval-workflows/runtime-adapter/analysis/bootstrap-family-node-contract.d.ts +0 -7
  206. package/dist/eval-workflows/runtime-adapter/analysis/bootstrap-family-node-contract.js +4 -37
  207. package/dist/eval-workflows/runtime-adapter/analysis/bootstrap-family-node-support.d.ts +7 -0
  208. package/dist/eval-workflows/runtime-adapter/analysis/bootstrap-family-node-support.js +36 -0
  209. package/dist/eval-workflows/runtime-adapter/analysis/bootstrap-family-node-v2.d.ts +5 -0
  210. package/dist/eval-workflows/runtime-adapter/analysis/bootstrap-family-node-v2.js +90 -0
  211. package/dist/eval-workflows/runtime-adapter/analysis/bootstrap-family-node.js +2 -1
  212. package/dist/eval-workflows/runtime-adapter/analysis/bootstrap-family-table-v2.d.ts +320 -0
  213. package/dist/eval-workflows/runtime-adapter/analysis/bootstrap-family-table-v2.js +265 -0
  214. package/dist/eval-workflows/runtime-adapter/analysis/bootstrap-family-table.d.ts +34 -1
  215. package/dist/eval-workflows/runtime-adapter/analysis/bootstrap-family-table.js +41 -28
  216. package/dist/eval-workflows/runtime-adapter/analysis/composite-node-contract.d.ts +1 -1
  217. package/dist/eval-workflows/runtime-adapter/analysis/composite-node-contract.js +3 -3
  218. package/dist/eval-workflows/runtime-adapter/analysis/composite-source-adapter.js +1 -1
  219. package/dist/eval-workflows/runtime-adapter/analysis/dimension-node.d.ts +1 -1
  220. package/dist/eval-workflows/runtime-adapter/analysis/dimension-node.js +36 -10
  221. package/dist/eval-workflows/runtime-adapter/analysis/dimension-parameters.d.ts +8 -0
  222. package/dist/eval-workflows/runtime-adapter/analysis/dimension-parameters.js +36 -4
  223. package/dist/eval-workflows/runtime-adapter/analysis/dimension-table-v1.d.ts +135 -0
  224. package/dist/eval-workflows/runtime-adapter/analysis/dimension-table-v1.js +195 -0
  225. package/dist/eval-workflows/runtime-adapter/analysis/dimension-table.d.ts +11 -5
  226. package/dist/eval-workflows/runtime-adapter/analysis/dimension-table.js +31 -10
  227. package/dist/eval-workflows/runtime-adapter/analysis/index.d.ts +2 -0
  228. package/dist/eval-workflows/runtime-adapter/analysis/index.js +2 -0
  229. package/dist/eval-workflows/runtime-adapter/analysis/judge-agreement.d.ts +8 -0
  230. package/dist/eval-workflows/runtime-adapter/analysis/judge-agreement.js +55 -0
  231. package/dist/eval-workflows/runtime-adapter/analysis/release-decision-parameters.d.ts +109 -1
  232. package/dist/eval-workflows/runtime-adapter/analysis/release-decision-parameters.js +199 -29
  233. package/dist/eval-workflows/runtime-adapter/analysis/release-decision.d.ts +22 -3
  234. package/dist/eval-workflows/runtime-adapter/analysis/release-decision.js +505 -74
  235. package/dist/eval-workflows/runtime-adapter/assembly.js +22 -26
  236. package/dist/eval-workflows/runtime-adapter/builtins.js +2 -0
  237. package/dist/eval-workflows/runtime-adapter/composition.js +2 -0
  238. package/dist/eval-workflows/runtime-adapter/evaluators/llm-assertions.d.ts +1 -0
  239. package/dist/eval-workflows/runtime-adapter/evaluators/llm-assertions.js +12 -1
  240. package/dist/eval-workflows/runtime-adapter/evaluators/rubric-judge.js +1 -0
  241. package/dist/eval-workflows/runtime-adapter/resource-leases/access.js +7 -5
  242. package/dist/eval-workflows/runtime-adapter/resource-leases/node.js +20 -10
  243. package/dist/eval-workflows/runtime-adapter/resource-leases/types.d.ts +1 -1
  244. package/dist/evidence/storage/directories.js +5 -10
  245. package/dist/evidence/storage/directory-selection.d.ts +5 -0
  246. package/dist/evidence/storage/directory-selection.js +13 -0
  247. package/dist/knowledge-artifacts/authoring/generator.js +24 -19
  248. package/dist/knowledge-artifacts/governance/store.d.ts +1 -1
  249. package/dist/knowledge-artifacts/governance/store.js +13 -16
  250. package/dist/observability/inbox/paths.js +4 -5
  251. package/dist/studio/presentation/observation-inbox/styles/experience.d.ts +1 -0
  252. package/dist/studio/presentation/observation-inbox/styles/experience.js +943 -0
  253. package/dist/studio/presentation/observation-inbox/styles/metrics.d.ts +1 -0
  254. package/dist/studio/presentation/observation-inbox/styles/metrics.js +679 -0
  255. package/dist/studio/presentation/observation-inbox/styles/review.d.ts +1 -0
  256. package/dist/studio/presentation/observation-inbox/styles/review.js +1422 -0
  257. package/dist/studio/presentation/observation-inbox/styles/shell.d.ts +1 -0
  258. package/dist/studio/presentation/observation-inbox/styles/shell.js +844 -0
  259. package/dist/studio/presentation/observation-inbox/styles/trajectory.d.ts +1 -0
  260. package/dist/studio/presentation/observation-inbox/styles/trajectory.js +1299 -0
  261. package/dist/studio/presentation/observation-inbox/styles.d.ts +2 -1
  262. package/dist/studio/presentation/observation-inbox/styles.js +11 -5183
  263. package/package.json +5 -2
  264. package/dist/eval-runtime/engine.d.ts +0 -3
  265. package/dist/eval-runtime/engine.js +0 -3
  266. package/dist/eval-workflows/instruments/contracts/result.d.ts +0 -54
  267. package/dist/eval-workflows/instruments/contracts/result.js +0 -1
  268. package/dist/eval-workflows/instruments/judge-trace.d.ts +0 -1
  269. package/dist/eval-workflows/instruments/judge-trace.js +0 -1
  270. package/dist/eval-workflows/instruments/judge.d.ts +0 -78
  271. package/dist/eval-workflows/instruments/judge.js +0 -323
package/README.md CHANGED
@@ -55,7 +55,7 @@ export OMK_EXECUTOR=codex
55
55
 
56
56
  Without `OMK_MODEL`, omk reads the model from `~/.codex/config.toml`. You can still pass `--executor codex --model <codex-model>` per command. Pass `--judge-models` or set `OMK_JUDGE_MODELS` only when you want a different judge.
57
57
 
58
- > The default 3-case pack is a low-cost workflow check, so `UNDERPOWERED` is expected. `--samples 20` selects a first-party, difficulty-stratified starter pack that meets omk's registered sample-size floor. Its provenance is `llm-generated`: use it to learn the statistical workflow, then review and replace it with real domain cases before making a release decision.
58
+ > The default 3-case pack is a low-cost workflow check, so `UNDERPOWERED` is expected. `--samples 20` selects a first-party, difficulty-stratified starter pack that meets omk's default heuristic evidence floor; it is not an a priori power calculation. Its provenance is `llm-generated`: use it to learn the statistical workflow, then review and replace it with real domain cases before making a release decision.
59
59
 
60
60
  > The CLI notifies you when a newer version is available (at most once per 20h); set `OMK_SKIP_UPDATE_CHECK=1` to silence it permanently.
61
61
 
@@ -228,7 +228,7 @@ The full docs are published at **[oh-my-knowledge.pages.dev](https://oh-my-knowl
228
228
  - **[CLI reference](docs/reference/cli.md)** — all top-level commands with bash examples and flag tables
229
229
  - **[Migrate to the 1.0 preview](docs/guides/v1-preview-migration.md)** — install channel, storage reset, sample protocol, CLI automation, and embedded API changes since 0.54
230
230
  - **[Evaluation Core cutover](docs/guides/eval-core-cutover.md)** — `BREAKING-SCHEMA` storage, resume, Studio, Gold, managed-evidence, and evolve migration
231
- - **[Embed OMK in a service](docs/guides/eval-runtime.md)** — one `evaluate()` API for Node.js and FaaS hosts
231
+ - **[Embed OMK in a service](docs/guides/eval-runtime.md)** — canonical `evaluate()` plus repeat-run `evaluateSeries()` for Node.js and FaaS hosts
232
232
  - **[Storage layout v2](docs/specs/storage-layout-spec.md)** — project/global domains, compatibility boundary, and Git policy
233
233
  - **[Executors](docs/reference/executors.md)** & **[artifact layout](docs/reference/artifact-layout.md)** — built-in / custom executors; how `variant` resolves to an artifact + runtime context
234
234
  - **[How-to guides](docs/guides/agent-eval.md)** — [evaluate an agent](docs/guides/agent-eval.md) (project runtime context) and [use non-Claude models](docs/guides/non-claude-models.md) (GLM / Qwen / DeepSeek / Moonshot / Ollama)
package/README.zh.md CHANGED
@@ -55,7 +55,7 @@ export OMK_EXECUTOR=codex
55
55
 
56
56
  不设置 `OMK_MODEL` 时,omk 会读取 `~/.codex/config.toml` 的模型。也可以继续逐次显式传 `--executor codex --model <codex-model>`。自定义评委时再传 `--judge-models` 或设置 `OMK_JUDGE_MODELS`。
57
57
 
58
- > 默认 3 条用例是低成本流程检查,出现「数据不足(UNDERPOWERED)」符合预期。`--samples 20` 会选择经过难度分层的官方起步用例集,达到 omk 注册的样本量下限。其来源明确标记为 `llm-generated`:它适合学习统计流程,发布判断前仍应人工复核并替换为真实领域用例。
58
+ > 默认 3 条用例是低成本流程检查,出现「数据不足(UNDERPOWERED)」符合预期。`--samples 20` 会选择经过难度分层的官方起步用例集,达到 omk 默认的启发式证据下限,但这不是先验功效计算。其来源明确标记为 `llm-generated`:它适合学习统计流程,发布判断前仍应人工复核并替换为真实领域用例。
59
59
 
60
60
  > 命令行有新版本时会自动提示(每 20 小时最多一次);想永久关闭该提醒,设环境变量 `OMK_SKIP_UPDATE_CHECK=1` 即可。
61
61
 
@@ -228,7 +228,7 @@ omk-mcp
228
228
  - **[CLI 参考](docs/zh/reference/cli.md)** —— 顶层命令的 bash 示例和 flag 表
229
229
  - **[迁移到 1.0 预览版](docs/zh/guides/v1-preview-migration.md)** —— 从 `0.54` 升级时的安装渠道、存储重建、用例协议、CLI 自动化与嵌入式 API 变化
230
230
  - **[Evaluation Core 生产切换](docs/zh/guides/eval-core-cutover.md)** —— `BREAKING-SCHEMA` 存储、resume、Studio、Gold、受管证据与 evolve 迁移
231
- - **[在服务中嵌入 OMK](docs/zh/guides/eval-runtime.md)** —— 面向 Node.js 与 FaaS 宿主的单一 `evaluate()` API
231
+ - **[在服务中嵌入 OMK](docs/zh/guides/eval-runtime.md)** —— 面向 Node.js 与 FaaS 宿主的 canonical `evaluate()` 与重复运行 `evaluateSeries()`
232
232
  - **[存储布局 v2](docs/zh/specs/storage-layout-spec.md)** —— 项目/全局领域、迁移兼容与 Git 策略
233
233
  - **[执行器](docs/zh/reference/executors.md)** & **[知识载体布局](docs/zh/reference/artifact-layout.md)** —— 内置 / 自定义执行器;variant 如何解析为 artifact + runtime context
234
234
  - **[操作指南](docs/zh/guides/agent-eval.md)** —— [评测 agent](docs/zh/guides/agent-eval.md)(项目 runtime context)与[使用非 Claude 模型](docs/zh/guides/non-claude-models.md)(GLM / 通义 / DeepSeek / Moonshot / Ollama)
@@ -104,7 +104,7 @@ omk eval [flags]
104
104
  - `--no-serve` `boolean`:不启 report server
105
105
  - `--no-strict-baseline` `boolean`:关闭 baseline 隔离
106
106
  - `--output-dir` `option`:报告输出目录(默认项目级 .omk/eval)
107
- - `--repeat` `option`:每个用例重复运行 N 次
107
+ - `--repeat` `option`:预先固定 Evaluation Series 的独立 run 数
108
108
  - `--report-only` `boolean`:生成报告并打印判定,但始终 exit 0(不参与 CI gate)。
109
109
  - `--resume` `option`:复用经过完整契约校验的 Core runId;拒绝时失败关闭
110
110
  - `--retry` `option`:单用例失败重试次数
@@ -169,6 +169,7 @@ omk eval gold compare <runId> [flags]
169
169
  - `--gold-dir` `option`:gold dataset 目录,必填
170
170
  - `--lang` `option` (默认 `zh`):输出语言 zh|en,优先级 CLI > OMK_LANG env > zh。
171
171
  - `--metric` `option`:显式选择 Core metric ID。
172
+ - `--minimum-alpha` `option`:可选的一致性阈值;按 Krippendorff α 置信区间下界评估
172
173
  - `--reports-dir` `option`:只读取指定 Core 报告目录(默认当前项目 + 全局)
173
174
  - `--seed` `option`:bootstrap seed,可复现
174
175
  - `--target` `option`:显式选择 Core target ID。
@@ -274,7 +275,7 @@ omk init [targetDir] [flags]
274
275
 
275
276
  - `--force` `boolean`:允许覆盖目标目录中已有的 omk 脚手架文件
276
277
  - `--lang` `option` (默认 `zh`):输出语言 zh|en,优先级 CLI > OMK_LANG env > zh。
277
- - `--samples` `3|20` (默认 `3`):官方起步用例数量:3 条用于快速跑通,20 条用于达到注册样本量下限
278
+ - `--samples` `3|20` (默认 `3`):官方起步用例数量:3 条用于快速跑通,20 条用于达到默认启发式证据下限
278
279
 
279
280
  **示例:**
280
281
 
@@ -290,7 +291,7 @@ omk init
290
291
  omk init my-project
291
292
  ```
292
293
 
293
- > 使用达到注册样本量下限的 20 条官方用例初始化
294
+ > 使用达到默认启发式证据下限的 20 条官方用例初始化
294
295
 
295
296
  ```bash
296
297
  omk init my-project --samples 20
@@ -10,6 +10,7 @@ export default class EvalGoldCompare extends BaseCommand {
10
10
  target: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
11
  evaluator: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
12
  metric: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ 'minimum-alpha': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
14
  'trial-index': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
15
  'reports-dir': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
15
16
  'bootstrap-samples': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
@@ -2,7 +2,7 @@ import { resolve } from 'node:path';
2
2
  import { Args, Flags } from '@oclif/core';
3
3
  import { BaseCommand } from '../../../oclif/base-command.js';
4
4
  import { LANG_FLAG, bilingual } from '../../../oclif/i18n.js';
5
- import { integerStringParser } from '../../../oclif/parsers.js';
5
+ import { integerStringParser, numberStringParser } from '../../../oclif/parsers.js';
6
6
  import { CliExit } from '../../../lib/cli-exit.js';
7
7
  import { projectReportsDir, globalReportsDir } from '../../../../evidence/storage/directories.js';
8
8
  export default class EvalGoldCompare extends BaseCommand {
@@ -33,6 +33,13 @@ export default class EvalGoldCompare extends BaseCommand {
33
33
  metric: Flags.string({
34
34
  description: bilingual({ zh: '显式选择 Core metric ID。', en: 'Explicit Core metric ID.' }),
35
35
  }),
36
+ 'minimum-alpha': Flags.string({
37
+ description: bilingual({
38
+ zh: '可选的一致性阈值;按 Krippendorff α 置信区间下界评估',
39
+ en: 'Optional agreement threshold, assessed against the Krippendorff alpha CI lower bound',
40
+ }),
41
+ parse: numberStringParser('--minimum-alpha', { min: -1, max: 1 }),
42
+ }),
36
43
  'trial-index': Flags.string({
37
44
  description: bilingual({ zh: '显式选择 trial index。', en: 'Explicit trial index.' }),
38
45
  parse: integerStringParser('--trial-index', { min: 0 }),
@@ -61,26 +68,31 @@ export default class EvalGoldCompare extends BaseCommand {
61
68
  await this.runWithCliExit(async () => {
62
69
  const runId = args.runId;
63
70
  if (!runId) {
64
- console.error('Usage: omk eval gold compare <runId> --gold-dir <dir> --target <id> --evaluator <id> --metric <id>');
71
+ console.error(lang === 'zh'
72
+ ? '用法:omk eval gold compare <runId> --gold-dir <dir> --target <id> --evaluator <id> --metric <id>'
73
+ : 'Usage: omk eval gold compare <runId> --gold-dir <dir> --target <id> --evaluator <id> --metric <id>');
65
74
  throw new CliExit(1);
66
75
  }
67
76
  const goldDir = flags['gold-dir'];
68
77
  if (!goldDir) {
69
- console.error('--gold-dir is required');
78
+ console.error(lang === 'zh' ? '必须提供 --gold-dir。' : '--gold-dir is required.');
70
79
  throw new CliExit(1);
71
80
  }
72
- const { loadGoldDataset } = await import('../../../../eval-workflows/gold/dataset.js');
81
+ const { loadGoldDataset, validationIssueMessage } = await import('../../../../eval-workflows/gold/dataset.js');
73
82
  const { createNodeCoreContentStore, createNodeCoreRunArtifactStore, createOverlayCoreRunArtifactStore, } = await import('../../../../eval-workflows/artifact-store/index.js');
74
83
  const { compareGoldToCoreRun } = await import('../../../../eval-workflows/projections/gold.js');
75
84
  const { dataset, issues } = loadGoldDataset(goldDir);
76
85
  if (!dataset) {
77
- console.error('Cannot load gold dataset:');
86
+ console.error(lang === 'zh' ? '无法加载 gold dataset:' : 'Cannot load gold dataset:');
78
87
  for (const i of issues)
79
- console.error(` - ${i.message}`);
88
+ console.error(` - ${validationIssueMessage(i, lang)}`);
80
89
  throw new CliExit(1);
81
90
  }
82
- for (const i of issues)
83
- console.error(`warn: ${i.message}`);
91
+ for (const i of issues) {
92
+ console.error(lang === 'zh'
93
+ ? `警告:${validationIssueMessage(i, lang)}`
94
+ : `Warning: ${validationIssueMessage(i, lang)}`);
95
+ }
84
96
  const storeOf = (directory) => createNodeCoreRunArtifactStore(directory, {
85
97
  contentResolver: createNodeCoreContentStore(resolve(directory, 'content')),
86
98
  });
@@ -90,8 +102,8 @@ export default class EvalGoldCompare extends BaseCommand {
90
102
  const source = await store.get(runId);
91
103
  if (source === undefined) {
92
104
  console.error(lang === 'zh'
93
- ? `找不到 Core run「${runId}」;旧 evaluation report 不再支持 gold compare。`
94
- : `Core run "${runId}" was not found; legacy evaluation reports are no longer supported.`);
105
+ ? `找不到 Core run「${runId}」。`
106
+ : `Core run "${runId}" was not found.`);
95
107
  throw new CliExit(1);
96
108
  }
97
109
  if (!flags.target || !flags.evaluator || !flags.metric) {
@@ -114,6 +126,9 @@ export default class EvalGoldCompare extends BaseCommand {
114
126
  }),
115
127
  },
116
128
  bootstrapSamples: samples,
129
+ ...(flags['minimum-alpha'] === undefined ? {} : {
130
+ minimumAlpha: Number(flags['minimum-alpha']),
131
+ }),
117
132
  ...(Number.isFinite(seedVal) ? { bootstrapSeed: seedVal } : {}),
118
133
  });
119
134
  console.log(JSON.stringify(result, null, 2));
@@ -25,18 +25,22 @@ export default class EvalGoldValidate extends BaseCommand {
25
25
  await this.runWithCliExit(async () => {
26
26
  const dir = args.dir;
27
27
  if (!dir) {
28
- console.error('Usage: omk eval gold validate <dir>');
28
+ console.error(lang === 'zh'
29
+ ? '用法:omk eval gold validate <dir>'
30
+ : 'Usage: omk eval gold validate <dir>');
29
31
  throw new CliExit(1);
30
32
  }
31
33
  const { validateGoldDataset } = await import('../../../../eval-workflows/gold/cli.js');
32
- const result = validateGoldDataset(dir);
34
+ const result = validateGoldDataset(dir, lang);
33
35
  if (result.ok) {
34
36
  console.log(lang === 'zh'
35
37
  ? `✓ gold dataset OK,共 ${result.sampleCount} 条标注`
36
38
  : `✓ gold dataset OK — ${result.sampleCount} annotations`);
37
39
  return;
38
40
  }
39
- console.error(`✗ gold dataset has ${result.issues.length} issue(s):`);
41
+ console.error(lang === 'zh'
42
+ ? `✗ gold dataset 存在 ${result.issues.length} 个问题:`
43
+ : `✗ gold dataset has ${result.issues.length} issue(s):`);
40
44
  for (const msg of result.issues)
41
45
  console.error(` - ${msg}`);
42
46
  throw new CliExit(1);
@@ -333,7 +333,10 @@ export default class Eval extends BaseCommand {
333
333
  }),
334
334
  // ── eval-runner extra ──
335
335
  repeat: Flags.string({
336
- description: bilingual({ zh: '每个用例重复运行 N 次', en: 'Repeat each sample N times' }),
336
+ description: bilingual({
337
+ zh: '预先固定 Evaluation Series 的独立 run 数',
338
+ en: 'Predeclare the independent run count for the Evaluation Series',
339
+ }),
337
340
  parse: integerStringParser('--repeat', { min: 1 }),
338
341
  }),
339
342
  'holdout-ratio': Flags.string({
@@ -77,8 +77,8 @@ export default class Init extends BaseCommand {
77
77
  },
78
78
  {
79
79
  description: bilingual({
80
- zh: '使用达到注册样本量下限的 20 条官方用例初始化',
81
- en: 'Initialize with the 20 first-party samples that meet the registered sample-size floor',
80
+ zh: '使用达到默认启发式证据下限的 20 条官方用例初始化',
81
+ en: 'Initialize with 20 first-party samples that meet the default heuristic evidence floor',
82
82
  }),
83
83
  command: '<%= config.bin %> init my-project --samples 20',
84
84
  },
@@ -108,8 +108,8 @@ export default class Init extends BaseCommand {
108
108
  lang: LANG_FLAG,
109
109
  samples: Flags.string({
110
110
  description: bilingual({
111
- zh: '官方起步用例数量:3 条用于快速跑通,20 条用于达到注册样本量下限',
112
- en: 'Number of first-party starter samples: 3 for a quick run, 20 to meet the registered sample-size floor',
111
+ zh: '官方起步用例数量:3 条用于快速跑通,20 条用于达到默认启发式证据下限',
112
+ en: 'Number of first-party starter samples: 3 for a quick run, 20 to meet the default heuristic evidence floor',
113
113
  }),
114
114
  options: [String(DEFAULT_INIT_SAMPLE_COUNT), String(FULL_INIT_SAMPLE_COUNT)],
115
115
  default: String(DEFAULT_INIT_SAMPLE_COUNT),
@@ -9,11 +9,11 @@ import { resolveObserveHealthDir, projectObserveHealthDir, globalObserveHealthDi
9
9
  import { DEFAULT_GLOBAL_OBSERVATIONS_DIR } from '../../observability/inbox/index.js';
10
10
  import { openWorkbench } from '../lib/open-workbench.js';
11
11
  // dev / browser-open 测试需要 mock `node:child_process` + `node:os`,通过 in-process
12
- // import 直接调用。把业务作为 module-level helper export 从 Command file 暴露,
13
- // 既保留 test 兼容又让产品命令树语义干净(无 legacy commands directory)。
12
+ // import 直接调用。把业务作为 module-level helper export 从 Command file 暴露,
13
+ // 便于测试命令行为,同时保持产品命令树语义干净。
14
14
  export async function runStudio(_args, flags, lang) {
15
- // reports 读取目录:显式 --reports-dir 固定该目录;--global 钉全局;默认只聚合
16
- // 当前项目 + 全局 Core run。旧 eval report index 已删除,不再扫描其它项目。
15
+ // reports 读取目录:显式 --reports-dir 固定该目录;--global 钉全局;默认聚合
16
+ // 当前项目与全局 Core run。
17
17
  const reportsDirOpt = flags['reports-dir']
18
18
  ? resolve(flags['reports-dir'])
19
19
  : flags.global
@@ -27,8 +27,8 @@ export const initDict = {
27
27
  en: ' 2. Read the report verdict and Next line: 3 samples only prove the workflow, so UNDERPOWERED is expected; use --samples 20 in a new empty directory for the full starter set.',
28
28
  },
29
29
  'cli.init.next_step_report_full': {
30
- zh: ' 2. 看报告里的 verdict 和“下一步”:20 条用例达到注册样本量下限,但来源是 llm-generated;用于理解统计流程,发布前应人工复核并替换为真实领域用例。',
31
- en: ' 2. Read the report verdict and Next line: 20 samples meet the registered sample-size floor but are llm-generated; use them to learn the statistical workflow, then review and replace them with real domain cases before release.',
30
+ zh: ' 2. 看报告里的 verdict 和“下一步”:20 条用例达到默认启发式证据下限,但不等于完成先验功效规划;其来源是 llm-generated,发布前应人工复核并替换为真实领域用例。',
31
+ en: ' 2. Read the report verdict and Next line: 20 samples meet the default heuristic evidence floor, not an a priori power plan; they are llm-generated and must be reviewed or replaced with real domain cases before release.',
32
32
  },
33
33
  'cli.init.next_step_executor': {
34
34
  zh: ' executor / judge 会按运行环境选择;Codex 任务自动使用本机 Codex 配置。也可用 OMK_EXECUTOR / OMK_MODEL 固定环境偏好,详见 https://oh-my-knowledge.pages.dev/zh/reference/executors。',
@@ -64,8 +64,8 @@ export const runDict = {
64
64
  en: '⚠ --bootstrap-samples "{value}" is invalid (expected an integer ≥ 100), falling back to 1000\n',
65
65
  },
66
66
  'cli.run.bootstrap_samples_too_large': {
67
- zh: '⚠ --bootstrap-samples {n} 较大, 可能耗时数秒。1000 是业内标准, 通常已够用。\n',
68
- en: '⚠ --bootstrap-samples {n} is large and may take several seconds. 1000 is the industry standard and usually sufficient.\n',
67
+ zh: '⚠ --bootstrap-samples {n} 较大,可能耗时数秒。有限重采样误差会单独进入显著性证据。\n',
68
+ en: '⚠ --bootstrap-samples {n} is large and may take several seconds. Finite-resampling error is reported separately in significance evidence.\n',
69
69
  },
70
70
  'cli.run.dry_run_no_scores': {
71
71
  zh: 'eval dry-run:仅预览任务,不检查分数。下一步:确认任务无误后,去掉 --dry-run 运行正式评测。',
@@ -45,6 +45,9 @@ function requestFor(input, projectRoot) {
45
45
  judgeMembers: input.config.judgeModels.map((judge) => ({
46
46
  executorId: judge.executor,
47
47
  model: judge.model,
48
+ ...(judge.deploymentRevision === undefined
49
+ ? {}
50
+ : { deploymentRevision: judge.deploymentRevision }),
48
51
  })),
49
52
  presentation: {
50
53
  projectOutputDirectoryLocator: projectReportsDir(),
@@ -12,14 +12,13 @@ const INIT_CURATED_SAMPLES = [
12
12
  sample_id: 's001',
13
13
  prompt: '审查以下代码',
14
14
  context: "function authenticate(username, password) {\n const query = `SELECT * FROM users WHERE name='${username}' AND pass='${password}'`;\n return db.execute(query);\n}",
15
- rubric: '满分标准:必须识别 SQL 注入风险、说明攻击影响、给出参数化查询修复,并标注合理的严重程度。',
15
+ rubric: {
16
+ security: { criterion: '是否准确识别 SQL 注入漏洞并说明攻击影响', weight: 0.5 },
17
+ actionability: { criterion: '是否给出可直接采用的参数化查询修复', weight: 0.5 },
18
+ },
16
19
  assertions: [
17
20
  { type: 'contains', value: 'SQL', weight: 1 },
18
21
  ],
19
- dimensions: {
20
- security: '是否准确识别 SQL 注入漏洞并说明攻击影响',
21
- actionability: '是否给出可直接采用的参数化查询修复',
22
- },
23
22
  capability: ['security-review'],
24
23
  difficulty: 'easy',
25
24
  construct: 'quality',
@@ -29,14 +28,13 @@ const INIT_CURATED_SAMPLES = [
29
28
  sample_id: 's002',
30
29
  prompt: '审查以下代码',
31
30
  context: 'async function fetchData(url) {\n const res = await fetch(url);\n const data = await res.json();\n return data;\n}',
32
- rubric: '满分标准:必须覆盖网络异常、HTTP 错误状态和非 JSON 响应,并给出结构清晰的错误处理方案。',
31
+ rubric: {
32
+ robustness: { criterion: '是否覆盖主要失败路径并区分错误来源', weight: 0.5 },
33
+ actionability: { criterion: '是否给出完整且不过度复杂的修复方案', weight: 0.5 },
34
+ },
33
35
  assertions: [
34
36
  { type: 'regex', pattern: 'try[\\s\\S]*catch|res\\.ok|status', flags: 'i', weight: 1 },
35
37
  ],
36
- dimensions: {
37
- robustness: '是否覆盖主要失败路径并区分错误来源',
38
- actionability: '是否给出完整且不过度复杂的修复方案',
39
- },
40
38
  capability: ['robustness-review'],
41
39
  difficulty: 'easy',
42
40
  construct: 'quality',
@@ -46,15 +44,14 @@ const INIT_CURATED_SAMPLES = [
46
44
  sample_id: 's003',
47
45
  prompt: '审查以下代码',
48
46
  context: "function renderComment(comment) {\n document.getElementById('output').innerHTML = '<p>' + comment + '</p>';\n}",
49
- rubric: '满分标准:必须识别 XSS 风险、解释不可信输入如何进入 HTML,并建议 textContent 或可靠转义。',
47
+ rubric: {
48
+ security: { criterion: '是否准确识别 XSS 漏洞及其数据流', weight: 0.5 },
49
+ actionability: { criterion: '是否给出安全且适配当前场景的渲染方式', weight: 0.5 },
50
+ },
50
51
  assertions: [
51
52
  { type: 'contains', value: 'XSS', weight: 1 },
52
53
  { type: 'contains', value: 'innerHTML', weight: 0.5 },
53
54
  ],
54
- dimensions: {
55
- security: '是否准确识别 XSS 漏洞及其数据流',
56
- actionability: '是否给出安全且适配当前场景的渲染方式',
57
- },
58
55
  capability: ['security-review'],
59
56
  difficulty: 'easy',
60
57
  construct: 'quality',
@@ -64,14 +61,13 @@ const INIT_CURATED_SAMPLES = [
64
61
  sample_id: 's004',
65
62
  prompt: '审查以下代码',
66
63
  context: "import { exec } from 'node:child_process';\n\nexport function archive(name) {\n exec(`tar -czf ${name}.tgz uploads/${name}`);\n}",
67
- rubric: '满分标准:必须识别命令注入和参数边界问题,说明 shell 拼接风险,并给出不经 shell 的参数化调用方案。',
64
+ rubric: {
65
+ security: { criterion: '是否识别出模板字符串进入 shell 的命令注入路径', weight: 0.5 },
66
+ actionability: { criterion: '是否使用参数数组和输入约束消除注入面', weight: 0.5 },
67
+ },
68
68
  assertions: [
69
69
  { type: 'regex', pattern: 'execFile|spawn', flags: 'i', weight: 1 },
70
70
  ],
71
- dimensions: {
72
- security: '是否识别出模板字符串进入 shell 的命令注入路径',
73
- actionability: '是否使用参数数组和输入约束消除注入面',
74
- },
75
71
  capability: ['security-review'],
76
72
  difficulty: 'medium',
77
73
  construct: 'quality',
@@ -81,14 +77,13 @@ const INIT_CURATED_SAMPLES = [
81
77
  sample_id: 's005',
82
78
  prompt: '审查以下代码',
83
79
  context: "import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport async function download(req) {\n return readFile(join('/srv/files', req.query.name));\n}",
84
- rubric: '满分标准:必须识别目录穿越风险,解释简单 join 不能建立目录边界,并给出规范化后校验根目录的修复。',
80
+ rubric: {
81
+ security: { criterion: '是否识别编码、绝对路径和上级目录绕过风险', weight: 0.5 },
82
+ actionability: { criterion: '是否给出基于解析后路径的边界校验', weight: 0.5 },
83
+ },
85
84
  assertions: [
86
85
  { type: 'regex', pattern: 'resolve|normalize|relative', flags: 'i', weight: 1 },
87
86
  ],
88
- dimensions: {
89
- security: '是否识别编码、绝对路径和上级目录绕过风险',
90
- actionability: '是否给出基于解析后路径的边界校验',
91
- },
92
87
  capability: ['security-review'],
93
88
  difficulty: 'hard',
94
89
  construct: 'quality',
@@ -98,10 +93,9 @@ const INIT_CURATED_SAMPLES = [
98
93
  sample_id: 's006',
99
94
  prompt: '审查以下代码',
100
95
  context: "export async function findUser(db, email) {\n return db.query('SELECT id, name FROM users WHERE email = ?', [email]);\n}",
101
- rubric: '满分标准:应确认参数化查询已经隔离输入;可以提出有依据的次要建议,但不得虚构 SQL 注入漏洞。',
102
- dimensions: {
103
- precision: '是否避免把安全的参数化查询误报为注入漏洞',
104
- reasoning: '是否区分确定缺陷、条件性风险和可选改进',
96
+ rubric: {
97
+ precision: { criterion: '是否避免把安全的参数化查询误报为注入漏洞', weight: 0.5 },
98
+ reasoning: { criterion: '是否区分确定缺陷、条件性风险和可选改进', weight: 0.5 },
105
99
  },
106
100
  capability: ['security-review'],
107
101
  difficulty: 'medium',
@@ -112,10 +106,9 @@ const INIT_CURATED_SAMPLES = [
112
106
  sample_id: 's007',
113
107
  prompt: '审查以下代码',
114
108
  context: 'function displayName(user) {\n return user.profile.name.trim();\n}',
115
- rubric: '满分标准:必须识别空值链路导致的运行时异常,说明哪些对象可能缺失,并给出契合业务语义的防御方案。',
116
- dimensions: {
117
- robustness: '是否完整定位 user、profile、name 的空值边界',
118
- actionability: '是否给出默认值、显式校验或可选链的合理选择',
109
+ rubric: {
110
+ robustness: { criterion: '是否完整定位 user、profile、name 的空值边界', weight: 0.5 },
111
+ actionability: { criterion: '是否给出默认值、显式校验或可选链的合理选择', weight: 0.5 },
119
112
  },
120
113
  capability: ['robustness-review'],
121
114
  difficulty: 'easy',
@@ -126,14 +119,13 @@ const INIT_CURATED_SAMPLES = [
126
119
  sample_id: 's008',
127
120
  prompt: '审查以下代码',
128
121
  context: "export function loadConfig(raw) {\n const config = JSON.parse(raw);\n return config.database.host.toLowerCase();\n}",
129
- rubric: '满分标准:必须区分 JSON 语法错误与结构不符合预期两类失败,并建议在使用前进行清晰的 schema 校验。',
122
+ rubric: {
123
+ robustness: { criterion: '是否覆盖解析失败和解析成功但结构错误两类路径', weight: 0.5 },
124
+ actionability: { criterion: '是否提供可定位字段问题的校验与错误信息', weight: 0.5 },
125
+ },
130
126
  assertions: [
131
127
  { type: 'contains', value: 'JSON.parse', weight: 1 },
132
128
  ],
133
- dimensions: {
134
- robustness: '是否覆盖解析失败和解析成功但结构错误两类路径',
135
- actionability: '是否提供可定位字段问题的校验与错误信息',
136
- },
137
129
  capability: ['robustness-review'],
138
130
  difficulty: 'medium',
139
131
  construct: 'quality',
@@ -143,14 +135,13 @@ const INIT_CURATED_SAMPLES = [
143
135
  sample_id: 's009',
144
136
  prompt: '审查以下代码',
145
137
  context: 'export async function getProfile(id) {\n for (;;) {\n try {\n return await fetch(`/profiles/${id}`).then(r => r.json());\n } catch {}\n }\n}',
146
- rubric: '满分标准:必须识别无限重试、吞掉错误、缺少超时与退避等问题,并给出有上限且可取消的重试策略。',
138
+ rubric: {
139
+ robustness: { criterion: '是否覆盖无限循环、错误可观测性和服务放大效应', weight: 0.5 },
140
+ actionability: { criterion: '是否给出上限、退避、超时和取消的完整策略', weight: 0.5 },
141
+ },
147
142
  assertions: [
148
143
  { type: 'contains', value: 'AbortController', weight: 1 },
149
144
  ],
150
- dimensions: {
151
- robustness: '是否覆盖无限循环、错误可观测性和服务放大效应',
152
- actionability: '是否给出上限、退避、超时和取消的完整策略',
153
- },
154
145
  capability: ['robustness-review'],
155
146
  difficulty: 'hard',
156
147
  construct: 'quality',
@@ -160,10 +151,9 @@ const INIT_CURATED_SAMPLES = [
160
151
  sample_id: 's010',
161
152
  prompt: '审查以下代码',
162
153
  context: "export async function loadUser(id, signal) {\n const res = await fetch(`/users/${encodeURIComponent(id)}`, { signal });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return await res.json();\n}",
163
- rubric: '满分标准:应认可现有编码、取消和状态检查;可指出 JSON 契约校验是条件性增强,但不得声称完全缺少错误处理。',
164
- dimensions: {
165
- precision: '是否避免否定代码已经具备的健壮性措施',
166
- reasoning: '是否把确定事实与依赖业务上下文的增强建议分开',
154
+ rubric: {
155
+ precision: { criterion: '是否避免否定代码已经具备的健壮性措施', weight: 0.5 },
156
+ reasoning: { criterion: '是否把确定事实与依赖业务上下文的增强建议分开', weight: 0.5 },
167
157
  },
168
158
  capability: ['robustness-review'],
169
159
  difficulty: 'medium',
@@ -174,10 +164,9 @@ const INIT_CURATED_SAMPLES = [
174
164
  sample_id: 's011',
175
165
  prompt: '审查以下代码',
176
166
  context: 'function shippingFee(weight) {\n if (weight > 30) return 999;\n return weight * 7.35 + 12;\n}',
177
- rubric: '满分标准:必须指出业务魔数和单位不透明造成的维护风险,并建议用有领域含义的常量或配置表达规则。',
178
- dimensions: {
179
- maintainability: '是否解释 30、999、7.35、12 的语义和变更风险',
180
- actionability: '是否给出命名、单位和规则归位的具体方案',
167
+ rubric: {
168
+ maintainability: { criterion: '是否解释 30、999、7.35、12 的语义和变更风险', weight: 0.5 },
169
+ actionability: { criterion: '是否给出命名、单位和规则归位的具体方案', weight: 0.5 },
181
170
  },
182
171
  capability: ['maintainability-review'],
183
172
  difficulty: 'easy',
@@ -188,10 +177,9 @@ const INIT_CURATED_SAMPLES = [
188
177
  sample_id: 's012',
189
178
  prompt: '审查以下代码',
190
179
  context: "function createUser(input) {\n if (!input.email.includes('@')) throw new Error('bad email');\n return db.users.insert(input);\n}\nfunction updateUser(input) {\n if (!input.email.includes('@')) throw new Error('bad email');\n return db.users.update(input);\n}",
191
- rubric: '满分标准:必须识别重复且薄弱的校验逻辑,说明规则漂移风险,并建议抽取单一、可测试的验证边界。',
192
- dimensions: {
193
- maintainability: '是否识别重复逻辑与未来规则不一致的风险',
194
- actionability: '是否提出职责清晰、易测试且不过度抽象的重构',
180
+ rubric: {
181
+ maintainability: { criterion: '是否识别重复逻辑与未来规则不一致的风险', weight: 0.5 },
182
+ actionability: { criterion: '是否提出职责清晰、易测试且不过度抽象的重构', weight: 0.5 },
195
183
  },
196
184
  capability: ['maintainability-review'],
197
185
  difficulty: 'medium',
@@ -202,10 +190,9 @@ const INIT_CURATED_SAMPLES = [
202
190
  sample_id: 's013',
203
191
  prompt: '审查以下代码',
204
192
  context: "export async function completeOrder(order, user) {\n if (!user.admin && user.id !== order.userId) throw new Error('forbidden');\n order.status = 'complete';\n await db.orders.save(order);\n await mail.send(user.email, renderReceipt(order));\n metrics.increment('orders.complete');\n return JSON.stringify(order);\n}",
205
- rubric: '满分标准:必须识别授权、状态变更、持久化、通知、指标和序列化混在单函数中的耦合,并提出保留事务语义的拆分。',
206
- dimensions: {
207
- maintainability: '是否识别职责耦合以及失败时产生的部分完成状态',
208
- actionability: '是否在拆分职责的同时保留事务和副作用顺序',
193
+ rubric: {
194
+ maintainability: { criterion: '是否识别职责耦合以及失败时产生的部分完成状态', weight: 0.5 },
195
+ actionability: { criterion: '是否在拆分职责的同时保留事务和副作用顺序', weight: 0.5 },
209
196
  },
210
197
  capability: ['maintainability-review'],
211
198
  difficulty: 'hard',
@@ -216,14 +203,13 @@ const INIT_CURATED_SAMPLES = [
216
203
  sample_id: 's014',
217
204
  prompt: '审查以下代码',
218
205
  context: 'function renderReport(data, compact, includeHeader, sortDescending, useUtc) {\n // formatting logic\n}',
219
- rubric: '满分标准:必须指出多个布尔位置参数难以理解和扩展,并建议使用命名 options 对象及合理默认值。',
206
+ rubric: {
207
+ maintainability: { criterion: '是否解释调用点可读性和新增选项时的演进问题', weight: 0.5 },
208
+ actionability: { criterion: '是否给出类型明确且可兼容默认值的参数设计', weight: 0.5 },
209
+ },
220
210
  assertions: [
221
211
  { type: 'contains', value: 'options', weight: 1 },
222
212
  ],
223
- dimensions: {
224
- maintainability: '是否解释调用点可读性和新增选项时的演进问题',
225
- actionability: '是否给出类型明确且可兼容默认值的参数设计',
226
- },
227
213
  capability: ['maintainability-review'],
228
214
  difficulty: 'medium',
229
215
  construct: 'quality',
@@ -233,10 +219,9 @@ const INIT_CURATED_SAMPLES = [
233
219
  sample_id: 's015',
234
220
  prompt: '审查以下代码',
235
221
  context: 'export function clamp(value, min, max) {\n return Math.min(max, Math.max(min, value));\n}',
236
- rubric: '满分标准:应认可实现对普通数值输入足够简洁;可以询问 min 大于 max 或 NaN 的业务约定,但不得强行引入复杂架构。',
237
- dimensions: {
238
- precision: '是否避免为了展示审查深度而虚构维护性问题',
239
- proportionality: '建议的复杂度是否与这个小型纯函数相称',
222
+ rubric: {
223
+ precision: { criterion: '是否避免为了展示审查深度而虚构维护性问题', weight: 0.5 },
224
+ proportionality: { criterion: '建议的复杂度是否与这个小型纯函数相称', weight: 0.5 },
240
225
  },
241
226
  capability: ['maintainability-review'],
242
227
  difficulty: 'easy',
@@ -247,14 +232,13 @@ const INIT_CURATED_SAMPLES = [
247
232
  sample_id: 's016',
248
233
  prompt: '审查以下代码',
249
234
  context: 'export async function listOrders(users) {\n const rows = [];\n for (const user of users) {\n rows.push(...await db.orders.findByUser(user.id));\n }\n return rows;\n}',
250
- rubric: '满分标准:必须识别循环内逐用户查询形成的 N+1 和串行等待,并建议批量查询或有边界的并发方案。',
235
+ rubric: {
236
+ performance: { criterion: '是否识别查询次数和串行延迟随用户数增长的问题', weight: 0.5 },
237
+ actionability: { criterion: '是否给出符合数据库边界的批量读取方案', weight: 0.5 },
238
+ },
251
239
  assertions: [
252
240
  { type: 'contains', value: 'N+1', weight: 1 },
253
241
  ],
254
- dimensions: {
255
- performance: '是否识别查询次数和串行延迟随用户数增长的问题',
256
- actionability: '是否给出符合数据库边界的批量读取方案',
257
- },
258
242
  capability: ['performance-review'],
259
243
  difficulty: 'easy',
260
244
  construct: 'quality',
@@ -264,14 +248,13 @@ const INIT_CURATED_SAMPLES = [
264
248
  sample_id: 's017',
265
249
  prompt: '审查以下代码',
266
250
  context: 'export async function hydrate(ids) {\n const result = [];\n for (const id of ids) {\n result.push(await fetch(`/items/${id}`).then(r => r.json()));\n }\n return result;\n}',
267
- rubric: '满分标准:必须指出无依赖请求被串行化的延迟问题,同时说明无限 Promise.all 的压力,并给出受控并发方案。',
251
+ rubric: {
252
+ performance: { criterion: '是否同时看见串行瓶颈和无界并发的反向风险', weight: 0.5 },
253
+ actionability: { criterion: '是否给出可调并发度、错误策略和顺序语义', weight: 0.5 },
254
+ },
268
255
  assertions: [
269
256
  { type: 'contains', value: 'Promise.all', weight: 1 },
270
257
  ],
271
- dimensions: {
272
- performance: '是否同时看见串行瓶颈和无界并发的反向风险',
273
- actionability: '是否给出可调并发度、错误策略和顺序语义',
274
- },
275
258
  capability: ['performance-review'],
276
259
  difficulty: 'medium',
277
260
  construct: 'quality',
@@ -281,14 +264,13 @@ const INIT_CURATED_SAMPLES = [
281
264
  sample_id: 's018',
282
265
  prompt: '审查以下代码',
283
266
  context: 'function commonIds(left, right) {\n return left.filter(item => right.some(other => other.id === item.id));\n}',
284
- rubric: '满分标准:必须识别双层扫描的时间复杂度,说明数据规模前提,并建议用 Set 或 Map 建立线性查找索引。',
267
+ rubric: {
268
+ performance: { criterion: '是否准确分析时间复杂度而不是泛泛声称性能差', weight: 0.5 },
269
+ actionability: { criterion: '是否根据唯一性和内存取舍选择合适索引结构', weight: 0.5 },
270
+ },
285
271
  assertions: [
286
272
  { type: 'regex', pattern: 'Set|Map', weight: 1 },
287
273
  ],
288
- dimensions: {
289
- performance: '是否准确分析时间复杂度而不是泛泛声称性能差',
290
- actionability: '是否根据唯一性和内存取舍选择合适索引结构',
291
- },
292
274
  capability: ['performance-review'],
293
275
  difficulty: 'hard',
294
276
  construct: 'quality',
@@ -298,10 +280,9 @@ const INIT_CURATED_SAMPLES = [
298
280
  sample_id: 's019',
299
281
  prompt: '审查以下代码',
300
282
  context: 'const cache = new Map();\nexport async function resolveTenant(id) {\n if (!cache.has(id)) cache.set(id, await loadTenant(id));\n return cache.get(id);\n}',
301
- rubric: '满分标准:必须识别多租户键空间下缓存无限增长和并发重复加载风险,并给出容量、淘汰与请求合并策略。',
302
- dimensions: {
303
- performance: '是否覆盖内存增长与并发 cache miss 两个独立问题',
304
- actionability: '是否给出与数据新鲜度和容量约束匹配的缓存策略',
283
+ rubric: {
284
+ performance: { criterion: '是否覆盖内存增长与并发 cache miss 两个独立问题', weight: 0.5 },
285
+ actionability: { criterion: '是否给出与数据新鲜度和容量约束匹配的缓存策略', weight: 0.5 },
305
286
  },
306
287
  capability: ['performance-review'],
307
288
  difficulty: 'hard',
@@ -312,10 +293,9 @@ const INIT_CURATED_SAMPLES = [
312
293
  sample_id: 's020',
313
294
  prompt: '审查以下代码',
314
295
  context: 'export function indexById(items) {\n const index = new Map();\n for (const item of items) index.set(item.id, item);\n return index;\n}',
315
- rubric: '满分标准:应认可这是清晰的线性构建过程;可以说明重复 id 的覆盖语义,但不得虚构嵌套循环或明显性能瓶颈。',
316
- dimensions: {
317
- precision: '是否避免把正常的 O(n) 工作误报为性能缺陷',
318
- reasoning: '是否把重复键语义作为条件性业务问题而非确定 bug',
296
+ rubric: {
297
+ precision: { criterion: '是否避免把正常的 O(n) 工作误报为性能缺陷', weight: 0.5 },
298
+ reasoning: { criterion: '是否把重复键语义作为条件性业务问题而非确定 bug', weight: 0.5 },
319
299
  },
320
300
  capability: ['performance-review'],
321
301
  difficulty: 'medium',