oh-my-knowledge 0.31.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1128) hide show
  1. package/README.md +38 -847
  2. package/README.zh.md +49 -858
  3. package/dist/analysis/coverage-analyzer.d.ts.map +1 -0
  4. package/dist/analysis/coverage-analyzer.js.map +1 -0
  5. package/dist/analysis/failure-clusterer.d.ts.map +1 -0
  6. package/dist/analysis/failure-clusterer.js.map +1 -0
  7. package/dist/analysis/gap-analyzer.d.ts +121 -0
  8. package/dist/analysis/gap-analyzer.d.ts.map +1 -0
  9. package/dist/analysis/gap-analyzer.js +471 -0
  10. package/dist/analysis/gap-analyzer.js.map +1 -0
  11. package/dist/analysis/hedging-classifier.d.ts.map +1 -0
  12. package/dist/analysis/hedging-classifier.js.map +1 -0
  13. package/dist/analysis/report-diagnostics.d.ts +34 -0
  14. package/dist/analysis/report-diagnostics.d.ts.map +1 -0
  15. package/dist/analysis/report-diagnostics.js +753 -0
  16. package/dist/analysis/report-diagnostics.js.map +1 -0
  17. package/dist/analysis/sample-diagnostics.d.ts.map +1 -0
  18. package/dist/analysis/sample-diagnostics.js.map +1 -0
  19. package/dist/analysis/saturation.d.ts +93 -0
  20. package/dist/analysis/saturation.d.ts.map +1 -0
  21. package/dist/analysis/saturation.js +182 -0
  22. package/dist/analysis/saturation.js.map +1 -0
  23. package/dist/authoring/evolver.d.ts +143 -0
  24. package/dist/authoring/evolver.d.ts.map +1 -0
  25. package/dist/authoring/evolver.js +764 -0
  26. package/dist/authoring/evolver.js.map +1 -0
  27. package/dist/authoring/generator.d.ts +66 -0
  28. package/dist/authoring/generator.d.ts.map +1 -0
  29. package/dist/authoring/generator.js +833 -0
  30. package/dist/authoring/generator.js.map +1 -0
  31. package/dist/authoring/sample-fixer.d.ts.map +1 -0
  32. package/dist/authoring/sample-fixer.js.map +1 -0
  33. package/dist/cli/commands/doctor.d.ts +28 -0
  34. package/dist/cli/commands/doctor.d.ts.map +1 -0
  35. package/dist/cli/commands/doctor.js +321 -0
  36. package/dist/cli/commands/doctor.js.map +1 -0
  37. package/dist/cli/commands/eval/gold/compare.d.ts.map +1 -0
  38. package/dist/cli/commands/eval/gold/compare.js.map +1 -0
  39. package/dist/cli/commands/eval/gold/index.d.ts.map +1 -0
  40. package/dist/cli/commands/eval/gold/index.js.map +1 -0
  41. package/dist/cli/commands/eval/gold/init.d.ts.map +1 -0
  42. package/dist/cli/commands/eval/gold/init.js.map +1 -0
  43. package/dist/cli/commands/eval/gold/validate.d.ts.map +1 -0
  44. package/dist/cli/commands/eval/gold/validate.js.map +1 -0
  45. package/dist/cli/commands/eval/index.d.ts.map +1 -0
  46. package/dist/cli/commands/eval/index.js +466 -0
  47. package/dist/cli/commands/eval/index.js.map +1 -0
  48. package/dist/cli/commands/evolve.d.ts +38 -0
  49. package/dist/cli/commands/evolve.d.ts.map +1 -0
  50. package/dist/cli/commands/evolve.js +299 -0
  51. package/dist/cli/commands/evolve.js.map +1 -0
  52. package/dist/cli/commands/init.d.ts.map +1 -0
  53. package/dist/cli/commands/init.js.map +1 -0
  54. package/dist/cli/commands/observe/inbox.d.ts.map +1 -0
  55. package/dist/cli/commands/observe/inbox.js +260 -0
  56. package/dist/cli/commands/observe/inbox.js.map +1 -0
  57. package/dist/cli/commands/observe/index.d.ts.map +1 -0
  58. package/dist/cli/commands/observe/index.js +122 -0
  59. package/dist/cli/commands/observe/index.js.map +1 -0
  60. package/dist/cli/commands/observe/ingest.d.ts.map +1 -0
  61. package/dist/cli/commands/observe/ingest.js +71 -0
  62. package/dist/cli/commands/observe/ingest.js.map +1 -0
  63. package/dist/cli/commands/observe/show.d.ts.map +1 -0
  64. package/dist/cli/commands/observe/show.js.map +1 -0
  65. package/dist/cli/commands/sample.d.ts +40 -0
  66. package/dist/cli/commands/sample.d.ts.map +1 -0
  67. package/dist/cli/commands/sample.js +579 -0
  68. package/dist/cli/commands/sample.js.map +1 -0
  69. package/dist/cli/commands/studio.d.ts.map +1 -0
  70. package/dist/cli/commands/studio.js +158 -0
  71. package/dist/cli/commands/studio.js.map +1 -0
  72. package/dist/cli/index.d.ts.map +1 -0
  73. package/dist/cli/index.js.map +1 -0
  74. package/dist/cli/lib/cli-exit.d.ts.map +1 -0
  75. package/dist/cli/lib/cli-exit.js.map +1 -0
  76. package/dist/cli/lib/cmd-flags.d.ts +229 -0
  77. package/dist/cli/lib/cmd-flags.d.ts.map +1 -0
  78. package/dist/cli/lib/cmd-flags.js.map +1 -0
  79. package/dist/cli/lib/i18n-dict/common.d.ts +4 -0
  80. package/dist/cli/lib/i18n-dict/common.d.ts.map +1 -0
  81. package/dist/cli/lib/i18n-dict/common.js +83 -0
  82. package/dist/cli/lib/i18n-dict/common.js.map +1 -0
  83. package/dist/cli/lib/i18n-dict/evolve.d.ts +4 -0
  84. package/dist/cli/lib/i18n-dict/evolve.d.ts.map +1 -0
  85. package/dist/cli/lib/i18n-dict/evolve.js +51 -0
  86. package/dist/cli/lib/i18n-dict/evolve.js.map +1 -0
  87. package/dist/cli/lib/i18n-dict/gen.d.ts +4 -0
  88. package/dist/cli/lib/i18n-dict/gen.d.ts.map +1 -0
  89. package/dist/cli/lib/i18n-dict/gen.js +63 -0
  90. package/dist/cli/lib/i18n-dict/gen.js.map +1 -0
  91. package/dist/cli/lib/i18n-dict/help.d.ts +4 -0
  92. package/dist/cli/lib/i18n-dict/help.d.ts.map +1 -0
  93. package/dist/cli/lib/i18n-dict/help.js +281 -0
  94. package/dist/cli/lib/i18n-dict/help.js.map +1 -0
  95. package/dist/cli/lib/i18n-dict/init.d.ts +4 -0
  96. package/dist/cli/lib/i18n-dict/init.d.ts.map +1 -0
  97. package/dist/cli/lib/i18n-dict/init.js +27 -0
  98. package/dist/cli/lib/i18n-dict/init.js.map +1 -0
  99. package/dist/cli/lib/i18n-dict/run.d.ts +4 -0
  100. package/dist/cli/lib/i18n-dict/run.d.ts.map +1 -0
  101. package/dist/cli/lib/i18n-dict/run.js +143 -0
  102. package/dist/cli/lib/i18n-dict/run.js.map +1 -0
  103. package/dist/cli/lib/i18n-dict/types.d.ts +5 -0
  104. package/dist/cli/lib/i18n-dict/types.d.ts.map +1 -0
  105. package/dist/cli/lib/i18n-dict/types.js +2 -0
  106. package/dist/cli/lib/i18n-dict/types.js.map +1 -0
  107. package/dist/cli/lib/i18n-dict.d.ts +63 -0
  108. package/dist/cli/lib/i18n-dict.d.ts.map +1 -0
  109. package/dist/cli/lib/i18n-dict.js +67 -0
  110. package/dist/cli/lib/i18n-dict.js.map +1 -0
  111. package/dist/cli/lib/i18n.d.ts.map +1 -0
  112. package/dist/cli/lib/i18n.js.map +1 -0
  113. package/dist/cli/lib/parse-run-config/judge-models.d.ts +24 -0
  114. package/dist/cli/lib/parse-run-config/judge-models.d.ts.map +1 -0
  115. package/dist/cli/lib/parse-run-config/judge-models.js +55 -0
  116. package/dist/cli/lib/parse-run-config/judge-models.js.map +1 -0
  117. package/dist/cli/lib/parse-run-config/samples-discovery.d.ts +19 -0
  118. package/dist/cli/lib/parse-run-config/samples-discovery.d.ts.map +1 -0
  119. package/dist/cli/lib/parse-run-config/samples-discovery.js +53 -0
  120. package/dist/cli/lib/parse-run-config/samples-discovery.js.map +1 -0
  121. package/dist/cli/lib/parse-run-config/variant-resolution.d.ts +23 -0
  122. package/dist/cli/lib/parse-run-config/variant-resolution.d.ts.map +1 -0
  123. package/dist/cli/lib/parse-run-config/variant-resolution.js +65 -0
  124. package/dist/cli/lib/parse-run-config/variant-resolution.js.map +1 -0
  125. package/dist/cli/lib/parse-run-config.d.ts +93 -0
  126. package/dist/cli/lib/parse-run-config.d.ts.map +1 -0
  127. package/dist/cli/lib/parse-run-config.js +157 -0
  128. package/dist/cli/lib/parse-run-config.js.map +1 -0
  129. package/dist/cli/lib/progress.d.ts.map +1 -0
  130. package/dist/cli/lib/progress.js.map +1 -0
  131. package/dist/cli/lib/resolve-skill-input.d.ts +8 -0
  132. package/dist/cli/lib/resolve-skill-input.d.ts.map +1 -0
  133. package/dist/cli/lib/resolve-skill-input.js +40 -0
  134. package/dist/cli/lib/resolve-skill-input.js.map +1 -0
  135. package/dist/cli/lib/run-tally.d.ts.map +1 -0
  136. package/dist/cli/lib/run-tally.js.map +1 -0
  137. package/dist/cli/lib/shared.d.ts.map +1 -0
  138. package/dist/cli/lib/shared.js.map +1 -0
  139. package/dist/cli/lib/update-check.d.ts +74 -0
  140. package/dist/cli/lib/update-check.d.ts.map +1 -0
  141. package/dist/cli/lib/update-check.js +302 -0
  142. package/dist/cli/lib/update-check.js.map +1 -0
  143. package/dist/cli/lib/update-fetch-worker.d.ts +2 -0
  144. package/dist/cli/lib/update-fetch-worker.d.ts.map +1 -0
  145. package/dist/cli/lib/update-fetch-worker.js +35 -0
  146. package/dist/cli/lib/update-fetch-worker.js.map +1 -0
  147. package/dist/cli/oclif/base-command.d.ts.map +1 -0
  148. package/dist/cli/oclif/base-command.js.map +1 -0
  149. package/dist/cli/oclif/help.d.ts.map +1 -0
  150. package/dist/cli/oclif/help.js.map +1 -0
  151. package/dist/cli/oclif/i18n.d.ts.map +1 -0
  152. package/dist/cli/oclif/i18n.js.map +1 -0
  153. package/dist/cli/oclif/parsers.d.ts.map +1 -0
  154. package/dist/cli/oclif/parsers.js.map +1 -0
  155. package/dist/cli/oclif/projection.d.ts.map +1 -0
  156. package/dist/cli/oclif/projection.js.map +1 -0
  157. package/dist/cli/oclif/run.d.ts.map +1 -0
  158. package/dist/cli/oclif/run.js +11 -0
  159. package/dist/cli/oclif/run.js.map +1 -0
  160. package/dist/diagnosis/observe-mapper.d.ts.map +1 -0
  161. package/dist/diagnosis/observe-mapper.js.map +1 -0
  162. package/dist/diagnosis/observe-producer.d.ts.map +1 -0
  163. package/dist/diagnosis/observe-producer.js +199 -0
  164. package/dist/diagnosis/observe-producer.js.map +1 -0
  165. package/dist/diagnosis/studio-projection.d.ts +7 -0
  166. package/dist/diagnosis/studio-projection.d.ts.map +1 -0
  167. package/dist/diagnosis/studio-projection.js.map +1 -0
  168. package/dist/diagnosis/types.d.ts +4 -0
  169. package/dist/diagnosis/types.d.ts.map +1 -0
  170. package/dist/diagnosis/types.js +20 -0
  171. package/dist/diagnosis/types.js.map +1 -0
  172. package/dist/doctor/fixer.d.ts.map +1 -0
  173. package/dist/doctor/fixer.js.map +1 -0
  174. package/dist/doctor/health/builtin-dimensions.d.ts.map +1 -0
  175. package/dist/doctor/health/builtin-dimensions.js.map +1 -0
  176. package/dist/doctor/health/composer.d.ts.map +1 -0
  177. package/dist/doctor/health/composer.js +296 -0
  178. package/dist/doctor/health/composer.js.map +1 -0
  179. package/dist/doctor/health/dimension-registry.d.ts.map +1 -0
  180. package/dist/doctor/health/dimension-registry.js.map +1 -0
  181. package/dist/doctor/health/dimension-spec.d.ts +47 -0
  182. package/dist/doctor/health/dimension-spec.d.ts.map +1 -0
  183. package/dist/doctor/health/dimension-spec.js.map +1 -0
  184. package/dist/doctor/health/load-custom-dimensions.d.ts +2 -0
  185. package/dist/doctor/health/load-custom-dimensions.d.ts.map +1 -0
  186. package/dist/doctor/health/load-custom-dimensions.js +31 -0
  187. package/dist/doctor/health/load-custom-dimensions.js.map +1 -0
  188. package/dist/doctor/health/parser.d.ts.map +1 -0
  189. package/dist/doctor/health/parser.js.map +1 -0
  190. package/dist/doctor/health/prompt-builder.d.ts.map +1 -0
  191. package/dist/doctor/health/prompt-builder.js.map +1 -0
  192. package/dist/doctor/health/register.d.ts.map +1 -0
  193. package/dist/doctor/health/register.js.map +1 -0
  194. package/dist/doctor/index.d.ts.map +1 -0
  195. package/dist/doctor/index.js.map +1 -0
  196. package/dist/doctor/messages.d.ts +21 -0
  197. package/dist/doctor/messages.d.ts.map +1 -0
  198. package/dist/doctor/messages.js +217 -0
  199. package/dist/doctor/messages.js.map +1 -0
  200. package/dist/doctor/preflight.d.ts.map +1 -0
  201. package/dist/doctor/preflight.js.map +1 -0
  202. package/dist/doctor/renderer.d.ts +17 -0
  203. package/dist/doctor/renderer.d.ts.map +1 -0
  204. package/dist/doctor/renderer.js +122 -0
  205. package/dist/doctor/renderer.js.map +1 -0
  206. package/dist/doctor/rules.d.ts.map +1 -0
  207. package/dist/doctor/rules.js +289 -0
  208. package/dist/doctor/rules.js.map +1 -0
  209. package/dist/eval-core/bootstrap.d.ts +80 -0
  210. package/dist/eval-core/bootstrap.d.ts.map +1 -0
  211. package/dist/eval-core/bootstrap.js +182 -0
  212. package/dist/eval-core/bootstrap.js.map +1 -0
  213. package/dist/eval-core/cache.d.ts.map +1 -0
  214. package/dist/eval-core/cache.js.map +1 -0
  215. package/dist/eval-core/comparability.d.ts.map +1 -0
  216. package/dist/eval-core/comparability.js.map +1 -0
  217. package/dist/eval-core/dependency-checker.d.ts +37 -0
  218. package/dist/eval-core/dependency-checker.d.ts.map +1 -0
  219. package/dist/eval-core/dependency-checker.js.map +1 -0
  220. package/dist/eval-core/evaluation-execution.d.ts.map +1 -0
  221. package/dist/eval-core/evaluation-execution.js.map +1 -0
  222. package/dist/eval-core/evaluation-job.d.ts.map +1 -0
  223. package/dist/eval-core/evaluation-job.js.map +1 -0
  224. package/dist/eval-core/evaluation-reporting.d.ts.map +1 -0
  225. package/dist/eval-core/evaluation-reporting.js +292 -0
  226. package/dist/eval-core/evaluation-reporting.js.map +1 -0
  227. package/dist/eval-core/execution-strategy.d.ts.map +1 -0
  228. package/dist/eval-core/execution-strategy.js +165 -0
  229. package/dist/eval-core/execution-strategy.js.map +1 -0
  230. package/dist/eval-core/fact-checker.d.ts.map +1 -0
  231. package/dist/eval-core/fact-checker.js.map +1 -0
  232. package/dist/eval-core/layer-gates.d.ts.map +1 -0
  233. package/dist/eval-core/layer-gates.js.map +1 -0
  234. package/dist/eval-core/mocks-runtime.d.ts.map +1 -0
  235. package/dist/eval-core/mocks-runtime.js +559 -0
  236. package/dist/eval-core/mocks-runtime.js.map +1 -0
  237. package/dist/eval-core/schema.d.ts.map +1 -0
  238. package/dist/eval-core/schema.js.map +1 -0
  239. package/dist/eval-core/statistics.d.ts.map +1 -0
  240. package/dist/eval-core/statistics.js.map +1 -0
  241. package/dist/eval-core/task-planner.d.ts.map +1 -0
  242. package/dist/eval-core/task-planner.js.map +1 -0
  243. package/dist/eval-core/verdict.d.ts +95 -0
  244. package/dist/eval-core/verdict.d.ts.map +1 -0
  245. package/dist/eval-core/verdict.js +372 -0
  246. package/dist/eval-core/verdict.js.map +1 -0
  247. package/dist/eval-workflows/batch-evaluation-workflow.d.ts.map +1 -0
  248. package/dist/eval-workflows/batch-evaluation-workflow.js.map +1 -0
  249. package/dist/eval-workflows/evaluation-pipeline/preflight-warnings.d.ts +22 -0
  250. package/dist/eval-workflows/evaluation-pipeline/preflight-warnings.d.ts.map +1 -0
  251. package/dist/eval-workflows/evaluation-pipeline/preflight-warnings.js +67 -0
  252. package/dist/eval-workflows/evaluation-pipeline/preflight-warnings.js.map +1 -0
  253. package/dist/eval-workflows/evaluation-pipeline/report-finalize.d.ts +32 -0
  254. package/dist/eval-workflows/evaluation-pipeline/report-finalize.d.ts.map +1 -0
  255. package/dist/eval-workflows/evaluation-pipeline/report-finalize.js +57 -0
  256. package/dist/eval-workflows/evaluation-pipeline/report-finalize.js.map +1 -0
  257. package/dist/eval-workflows/evaluation-pipeline/run-state.d.ts +60 -0
  258. package/dist/eval-workflows/evaluation-pipeline/run-state.d.ts.map +1 -0
  259. package/dist/eval-workflows/evaluation-pipeline/run-state.js +88 -0
  260. package/dist/eval-workflows/evaluation-pipeline/run-state.js.map +1 -0
  261. package/dist/eval-workflows/evaluation-pipeline/test-set-hash.d.ts +21 -0
  262. package/dist/eval-workflows/evaluation-pipeline/test-set-hash.d.ts.map +1 -0
  263. package/dist/eval-workflows/evaluation-pipeline/test-set-hash.js +46 -0
  264. package/dist/eval-workflows/evaluation-pipeline/test-set-hash.js.map +1 -0
  265. package/dist/eval-workflows/evaluation-pipeline.d.ts +97 -0
  266. package/dist/eval-workflows/evaluation-pipeline.d.ts.map +1 -0
  267. package/dist/eval-workflows/evaluation-pipeline.js +179 -0
  268. package/dist/eval-workflows/evaluation-pipeline.js.map +1 -0
  269. package/dist/eval-workflows/evaluation-preparation.d.ts.map +1 -0
  270. package/dist/eval-workflows/evaluation-preparation.js +105 -0
  271. package/dist/eval-workflows/evaluation-preparation.js.map +1 -0
  272. package/dist/eval-workflows/messages.d.ts +4 -0
  273. package/dist/eval-workflows/messages.d.ts.map +1 -0
  274. package/dist/eval-workflows/messages.js +30 -0
  275. package/dist/eval-workflows/messages.js.map +1 -0
  276. package/dist/eval-workflows/run-evaluation.d.ts +151 -0
  277. package/dist/eval-workflows/run-evaluation.d.ts.map +1 -0
  278. package/dist/eval-workflows/run-evaluation.js +528 -0
  279. package/dist/eval-workflows/run-evaluation.js.map +1 -0
  280. package/dist/executors/anthropic-api.d.ts.map +1 -0
  281. package/dist/executors/anthropic-api.js.map +1 -0
  282. package/dist/executors/claude-cli.d.ts.map +1 -0
  283. package/dist/executors/claude-cli.js.map +1 -0
  284. package/dist/executors/claude-sdk-trace.d.ts.map +1 -0
  285. package/dist/executors/claude-sdk-trace.js.map +1 -0
  286. package/dist/executors/claude-sdk.d.ts.map +1 -0
  287. package/dist/executors/claude-sdk.js.map +1 -0
  288. package/dist/executors/codex-cli-trace.d.ts.map +1 -0
  289. package/dist/executors/codex-cli-trace.js.map +1 -0
  290. package/dist/executors/codex-cli.d.ts.map +1 -0
  291. package/dist/executors/codex-cli.js.map +1 -0
  292. package/dist/executors/codex-sdk.d.ts.map +1 -0
  293. package/dist/executors/codex-sdk.js.map +1 -0
  294. package/dist/executors/gemini.d.ts.map +1 -0
  295. package/dist/executors/gemini.js.map +1 -0
  296. package/dist/executors/index.d.ts.map +1 -0
  297. package/dist/executors/index.js.map +1 -0
  298. package/dist/executors/openai-api.d.ts.map +1 -0
  299. package/dist/executors/openai-api.js.map +1 -0
  300. package/dist/executors/runtime-fingerprint.d.ts.map +1 -0
  301. package/dist/executors/runtime-fingerprint.js.map +1 -0
  302. package/dist/executors/script.d.ts.map +1 -0
  303. package/dist/executors/script.js.map +1 -0
  304. package/dist/executors/shared.d.ts +194 -0
  305. package/dist/executors/shared.d.ts.map +1 -0
  306. package/dist/executors/shared.js +253 -0
  307. package/dist/executors/shared.js.map +1 -0
  308. package/dist/grading/assertions.d.ts.map +1 -0
  309. package/dist/grading/assertions.js.map +1 -0
  310. package/dist/grading/debias-validate.d.ts.map +1 -0
  311. package/dist/grading/debias-validate.js.map +1 -0
  312. package/dist/grading/diagnostic.d.ts.map +1 -0
  313. package/dist/grading/diagnostic.js.map +1 -0
  314. package/dist/grading/gold-cli.d.ts.map +1 -0
  315. package/dist/grading/gold-cli.js.map +1 -0
  316. package/dist/grading/gold-dataset.d.ts.map +1 -0
  317. package/dist/grading/gold-dataset.js.map +1 -0
  318. package/dist/grading/human-gold.d.ts.map +1 -0
  319. package/dist/grading/human-gold.js.map +1 -0
  320. package/dist/grading/index.d.ts.map +1 -0
  321. package/dist/grading/index.js.map +1 -0
  322. package/dist/grading/judge.d.ts.map +1 -0
  323. package/dist/grading/judge.js.map +1 -0
  324. package/dist/grading/layered-scores.d.ts.map +1 -0
  325. package/dist/grading/layered-scores.js.map +1 -0
  326. package/dist/inputs/eval-config.d.ts.map +1 -0
  327. package/dist/inputs/eval-config.js +252 -0
  328. package/dist/inputs/eval-config.js.map +1 -0
  329. package/dist/inputs/load-samples.d.ts.map +1 -0
  330. package/dist/inputs/load-samples.js.map +1 -0
  331. package/dist/inputs/mcp-resolver.d.ts.map +1 -0
  332. package/dist/inputs/mcp-resolver.js.map +1 -0
  333. package/dist/inputs/skill-loader.d.ts +49 -0
  334. package/dist/inputs/skill-loader.d.ts.map +1 -0
  335. package/dist/inputs/skill-loader.js +420 -0
  336. package/dist/inputs/skill-loader.js.map +1 -0
  337. package/dist/inputs/url-fetcher.d.ts.map +1 -0
  338. package/dist/inputs/url-fetcher.js.map +1 -0
  339. package/dist/observability/experience-frontmatter.d.ts +37 -0
  340. package/dist/observability/experience-frontmatter.d.ts.map +1 -0
  341. package/dist/observability/experience-frontmatter.js +100 -0
  342. package/dist/observability/experience-frontmatter.js.map +1 -0
  343. package/dist/observability/experience.d.ts +23 -0
  344. package/dist/observability/experience.d.ts.map +1 -0
  345. package/dist/observability/experience.js +3438 -0
  346. package/dist/observability/experience.js.map +1 -0
  347. package/dist/observability/feedback-matchers.d.ts +37 -0
  348. package/dist/observability/feedback-matchers.d.ts.map +1 -0
  349. package/dist/observability/feedback-matchers.js +232 -0
  350. package/dist/observability/feedback-matchers.js.map +1 -0
  351. package/dist/observability/feedback-projection.d.ts +21 -0
  352. package/dist/observability/feedback-projection.d.ts.map +1 -0
  353. package/dist/observability/feedback-projection.js +20 -0
  354. package/dist/observability/feedback-projection.js.map +1 -0
  355. package/dist/observability/inbox-view-model.d.ts +43 -0
  356. package/dist/observability/inbox-view-model.d.ts.map +1 -0
  357. package/dist/observability/inbox-view-model.js +180 -0
  358. package/dist/observability/inbox-view-model.js.map +1 -0
  359. package/dist/observability/inbox.d.ts +28 -0
  360. package/dist/observability/inbox.d.ts.map +1 -0
  361. package/dist/observability/inbox.js +765 -0
  362. package/dist/observability/inbox.js.map +1 -0
  363. package/dist/observability/problem-patterns.d.ts +12 -0
  364. package/dist/observability/problem-patterns.d.ts.map +1 -0
  365. package/dist/observability/problem-patterns.js +244 -0
  366. package/dist/observability/problem-patterns.js.map +1 -0
  367. package/dist/observability/prompts/llm-enhanced-review.prompt.md +224 -0
  368. package/dist/observability/resolved-review.d.ts +37 -0
  369. package/dist/observability/resolved-review.d.ts.map +1 -0
  370. package/dist/observability/resolved-review.js +552 -0
  371. package/dist/observability/resolved-review.js.map +1 -0
  372. package/dist/observability/review-state.d.ts +20 -0
  373. package/dist/observability/review-state.d.ts.map +1 -0
  374. package/dist/observability/review-state.js.map +1 -0
  375. package/dist/observability/skill-chain-advisories.d.ts +16 -0
  376. package/dist/observability/skill-chain-advisories.d.ts.map +1 -0
  377. package/dist/observability/skill-chain-advisories.js.map +1 -0
  378. package/dist/observability/skill-chain.d.ts +7 -0
  379. package/dist/observability/skill-chain.d.ts.map +1 -0
  380. package/dist/observability/skill-chain.js +474 -0
  381. package/dist/observability/skill-chain.js.map +1 -0
  382. package/dist/observability/skill-health-analyzer.d.ts +96 -0
  383. package/dist/observability/skill-health-analyzer.d.ts.map +1 -0
  384. package/dist/observability/skill-health-analyzer.js +253 -0
  385. package/dist/observability/skill-health-analyzer.js.map +1 -0
  386. package/dist/observability/soft-standards/constants.d.ts +5 -0
  387. package/dist/observability/soft-standards/constants.d.ts.map +1 -0
  388. package/dist/observability/soft-standards/constants.js +10 -0
  389. package/dist/observability/soft-standards/constants.js.map +1 -0
  390. package/dist/observability/soft-standards/index.d.ts +16 -0
  391. package/dist/observability/soft-standards/index.d.ts.map +1 -0
  392. package/dist/observability/soft-standards/index.js +15 -0
  393. package/dist/observability/soft-standards/index.js.map +1 -0
  394. package/dist/observability/soft-standards/llm-extractor.d.ts +6 -0
  395. package/dist/observability/soft-standards/llm-extractor.d.ts.map +1 -0
  396. package/dist/observability/soft-standards/llm-extractor.js +692 -0
  397. package/dist/observability/soft-standards/llm-extractor.js.map +1 -0
  398. package/dist/observability/soft-standards/runtime-evaluator.d.ts +12 -0
  399. package/dist/observability/soft-standards/runtime-evaluator.d.ts.map +1 -0
  400. package/dist/observability/soft-standards/runtime-evaluator.js +385 -0
  401. package/dist/observability/soft-standards/runtime-evaluator.js.map +1 -0
  402. package/dist/observability/soft-standards/skill-standards-store.d.ts +11 -0
  403. package/dist/observability/soft-standards/skill-standards-store.d.ts.map +1 -0
  404. package/dist/observability/soft-standards/skill-standards-store.js +158 -0
  405. package/dist/observability/soft-standards/skill-standards-store.js.map +1 -0
  406. package/dist/observability/soft-standards/types.d.ts +212 -0
  407. package/dist/observability/soft-standards/types.d.ts.map +1 -0
  408. package/dist/observability/soft-standards/types.js +2 -0
  409. package/dist/observability/soft-standards/types.js.map +1 -0
  410. package/dist/observability/text-signals.d.ts +14 -0
  411. package/dist/observability/text-signals.d.ts.map +1 -0
  412. package/dist/observability/text-signals.js +116 -0
  413. package/dist/observability/text-signals.js.map +1 -0
  414. package/dist/observability/trace-adapter.d.ts.map +1 -0
  415. package/dist/observability/trace-adapter.js.map +1 -0
  416. package/dist/observability/trace-attribution.d.ts +56 -0
  417. package/dist/observability/trace-attribution.d.ts.map +1 -0
  418. package/dist/observability/trace-attribution.js +200 -0
  419. package/dist/observability/trace-attribution.js.map +1 -0
  420. package/dist/observability/trace-segmenter.d.ts +52 -0
  421. package/dist/observability/trace-segmenter.d.ts.map +1 -0
  422. package/dist/observability/trace-segmenter.js +322 -0
  423. package/dist/observability/trace-segmenter.js.map +1 -0
  424. package/dist/observability/trace-source.d.ts +92 -0
  425. package/dist/observability/trace-source.d.ts.map +1 -0
  426. package/dist/observability/trace-source.js +502 -0
  427. package/dist/observability/trace-source.js.map +1 -0
  428. package/dist/renderer/html-renderer.d.ts.map +1 -0
  429. package/dist/renderer/html-renderer.js.map +1 -0
  430. package/dist/renderer/layout.d.ts.map +1 -0
  431. package/dist/renderer/layout.js +776 -0
  432. package/dist/renderer/layout.js.map +1 -0
  433. package/dist/renderer/observation-inbox/helpers.d.ts +14 -0
  434. package/dist/renderer/observation-inbox/helpers.d.ts.map +1 -0
  435. package/dist/renderer/observation-inbox/helpers.js +75 -0
  436. package/dist/renderer/observation-inbox/helpers.js.map +1 -0
  437. package/dist/renderer/observation-inbox/styles.d.ts +2 -0
  438. package/dist/renderer/observation-inbox/styles.d.ts.map +1 -0
  439. package/dist/renderer/observation-inbox/styles.js +5184 -0
  440. package/dist/renderer/observation-inbox/styles.js.map +1 -0
  441. package/dist/renderer/observation-inbox-renderer.d.ts +5 -0
  442. package/dist/renderer/observation-inbox-renderer.d.ts.map +1 -0
  443. package/dist/renderer/observation-inbox-renderer.js +7182 -0
  444. package/dist/renderer/observation-inbox-renderer.js.map +1 -0
  445. package/dist/renderer/skill-detail-renderer.d.ts +13 -0
  446. package/dist/renderer/skill-detail-renderer.d.ts.map +1 -0
  447. package/dist/renderer/skill-detail-renderer.js +1323 -0
  448. package/dist/renderer/skill-detail-renderer.js.map +1 -0
  449. package/dist/renderer/skill-health-renderer.d.ts.map +1 -0
  450. package/dist/renderer/skill-health-renderer.js +282 -0
  451. package/dist/renderer/skill-health-renderer.js.map +1 -0
  452. package/dist/renderer/skill-list-renderer.d.ts +3 -0
  453. package/dist/renderer/skill-list-renderer.d.ts.map +1 -0
  454. package/dist/renderer/skill-list-renderer.js +346 -0
  455. package/dist/renderer/skill-list-renderer.js.map +1 -0
  456. package/dist/renderer/summary.d.ts +68 -0
  457. package/dist/renderer/summary.d.ts.map +1 -0
  458. package/dist/renderer/summary.js +1908 -0
  459. package/dist/renderer/summary.js.map +1 -0
  460. package/dist/renderer/table.d.ts.map +1 -0
  461. package/dist/renderer/table.js.map +1 -0
  462. package/dist/renderer/test-view.d.ts.map +1 -0
  463. package/dist/renderer/test-view.js.map +1 -0
  464. package/dist/renderer/trends.d.ts.map +1 -0
  465. package/dist/renderer/trends.js.map +1 -0
  466. package/dist/server/job-store.d.ts.map +1 -0
  467. package/dist/server/job-store.js.map +1 -0
  468. package/dist/server/report-server.d.ts.map +1 -0
  469. package/dist/server/report-server.js +899 -0
  470. package/dist/server/report-server.js.map +1 -0
  471. package/dist/server/report-store.d.ts.map +1 -0
  472. package/dist/server/report-store.js.map +1 -0
  473. package/dist/server/skill-index.d.ts +14 -0
  474. package/dist/server/skill-index.d.ts.map +1 -0
  475. package/dist/server/skill-index.js +384 -0
  476. package/dist/server/skill-index.js.map +1 -0
  477. package/dist/server/skill-insights.d.ts +32 -0
  478. package/dist/server/skill-insights.d.ts.map +1 -0
  479. package/dist/server/skill-insights.js +816 -0
  480. package/dist/server/skill-insights.js.map +1 -0
  481. package/dist/shared/hard-rules.d.ts.map +1 -0
  482. package/dist/shared/hard-rules.js.map +1 -0
  483. package/dist/shared/llm-prompts/index.d.ts +14 -0
  484. package/dist/shared/llm-prompts/index.d.ts.map +1 -0
  485. package/dist/shared/llm-prompts/index.js +22 -0
  486. package/dist/shared/llm-prompts/index.js.map +1 -0
  487. package/dist/shared/llm-prompts/skill-health.d.ts.map +1 -0
  488. package/dist/shared/llm-prompts/skill-health.js.map +1 -0
  489. package/dist/shared/time.d.ts.map +1 -0
  490. package/dist/shared/time.js.map +1 -0
  491. package/dist/shared/tool-search.d.ts.map +1 -0
  492. package/dist/shared/tool-search.js.map +1 -0
  493. package/dist/types/dependencies.d.ts +23 -0
  494. package/dist/types/dependencies.d.ts.map +1 -0
  495. package/dist/types/dependencies.js +2 -0
  496. package/dist/types/dependencies.js.map +1 -0
  497. package/dist/types/diagnosis.d.ts +88 -0
  498. package/dist/types/diagnosis.d.ts.map +1 -0
  499. package/dist/types/diagnosis.js +2 -0
  500. package/dist/types/diagnosis.js.map +1 -0
  501. package/dist/types/doctor.d.ts +157 -0
  502. package/dist/types/doctor.d.ts.map +1 -0
  503. package/dist/types/doctor.js.map +1 -0
  504. package/dist/types/eval.d.ts +378 -0
  505. package/dist/types/eval.d.ts.map +1 -0
  506. package/dist/types/eval.js.map +1 -0
  507. package/dist/types/executor.d.ts.map +1 -0
  508. package/dist/types/executor.js.map +1 -0
  509. package/dist/types/index.d.ts +12 -0
  510. package/dist/types/index.d.ts.map +1 -0
  511. package/dist/types/index.js +12 -0
  512. package/dist/types/index.js.map +1 -0
  513. package/dist/types/judge.d.ts.map +1 -0
  514. package/dist/types/judge.js.map +1 -0
  515. package/dist/types/observability.d.ts +865 -0
  516. package/dist/types/observability.d.ts.map +1 -0
  517. package/dist/types/observability.js +14 -0
  518. package/dist/types/observability.js.map +1 -0
  519. package/dist/types/report.d.ts +560 -0
  520. package/dist/types/report.d.ts.map +1 -0
  521. package/dist/types/report.js.map +1 -0
  522. package/dist/types/shared.d.ts.map +1 -0
  523. package/dist/types/shared.js.map +1 -0
  524. package/dist/types/skill-index.d.ts +145 -0
  525. package/dist/types/skill-index.d.ts.map +1 -0
  526. package/dist/types/skill-index.js +2 -0
  527. package/dist/types/skill-index.js.map +1 -0
  528. package/dist/types/storage.d.ts.map +1 -0
  529. package/dist/types/storage.js.map +1 -0
  530. package/dist/util/safe-slice.d.ts +23 -0
  531. package/dist/util/safe-slice.d.ts.map +1 -0
  532. package/dist/util/safe-slice.js +33 -0
  533. package/dist/util/safe-slice.js.map +1 -0
  534. package/package.json +23 -16
  535. package/dist/src/analysis/coverage-analyzer.d.ts.map +0 -1
  536. package/dist/src/analysis/coverage-analyzer.js.map +0 -1
  537. package/dist/src/analysis/failure-clusterer.d.ts.map +0 -1
  538. package/dist/src/analysis/failure-clusterer.js.map +0 -1
  539. package/dist/src/analysis/gap-analyzer.d.ts +0 -121
  540. package/dist/src/analysis/gap-analyzer.d.ts.map +0 -1
  541. package/dist/src/analysis/gap-analyzer.js +0 -471
  542. package/dist/src/analysis/gap-analyzer.js.map +0 -1
  543. package/dist/src/analysis/hedging-classifier.d.ts.map +0 -1
  544. package/dist/src/analysis/hedging-classifier.js.map +0 -1
  545. package/dist/src/analysis/report-diagnostics.d.ts +0 -34
  546. package/dist/src/analysis/report-diagnostics.d.ts.map +0 -1
  547. package/dist/src/analysis/report-diagnostics.js +0 -753
  548. package/dist/src/analysis/report-diagnostics.js.map +0 -1
  549. package/dist/src/analysis/sample-diagnostics.d.ts.map +0 -1
  550. package/dist/src/analysis/sample-diagnostics.js.map +0 -1
  551. package/dist/src/analysis/saturation.d.ts +0 -85
  552. package/dist/src/analysis/saturation.d.ts.map +0 -1
  553. package/dist/src/analysis/saturation.js +0 -174
  554. package/dist/src/analysis/saturation.js.map +0 -1
  555. package/dist/src/authoring/evolver.d.ts +0 -102
  556. package/dist/src/authoring/evolver.d.ts.map +0 -1
  557. package/dist/src/authoring/evolver.js +0 -681
  558. package/dist/src/authoring/evolver.js.map +0 -1
  559. package/dist/src/authoring/generator.d.ts +0 -38
  560. package/dist/src/authoring/generator.d.ts.map +0 -1
  561. package/dist/src/authoring/generator.js +0 -720
  562. package/dist/src/authoring/generator.js.map +0 -1
  563. package/dist/src/authoring/sample-fixer.d.ts.map +0 -1
  564. package/dist/src/authoring/sample-fixer.js.map +0 -1
  565. package/dist/src/cli/commands/doctor.d.ts +0 -26
  566. package/dist/src/cli/commands/doctor.d.ts.map +0 -1
  567. package/dist/src/cli/commands/doctor.js +0 -283
  568. package/dist/src/cli/commands/doctor.js.map +0 -1
  569. package/dist/src/cli/commands/eval/gold/compare.d.ts.map +0 -1
  570. package/dist/src/cli/commands/eval/gold/compare.js.map +0 -1
  571. package/dist/src/cli/commands/eval/gold/index.d.ts.map +0 -1
  572. package/dist/src/cli/commands/eval/gold/index.js.map +0 -1
  573. package/dist/src/cli/commands/eval/gold/init.d.ts.map +0 -1
  574. package/dist/src/cli/commands/eval/gold/init.js.map +0 -1
  575. package/dist/src/cli/commands/eval/gold/validate.d.ts.map +0 -1
  576. package/dist/src/cli/commands/eval/gold/validate.js.map +0 -1
  577. package/dist/src/cli/commands/eval/index.d.ts.map +0 -1
  578. package/dist/src/cli/commands/eval/index.js +0 -465
  579. package/dist/src/cli/commands/eval/index.js.map +0 -1
  580. package/dist/src/cli/commands/evolve.d.ts +0 -37
  581. package/dist/src/cli/commands/evolve.d.ts.map +0 -1
  582. package/dist/src/cli/commands/evolve.js +0 -276
  583. package/dist/src/cli/commands/evolve.js.map +0 -1
  584. package/dist/src/cli/commands/init.d.ts.map +0 -1
  585. package/dist/src/cli/commands/init.js.map +0 -1
  586. package/dist/src/cli/commands/observe/inbox.d.ts.map +0 -1
  587. package/dist/src/cli/commands/observe/inbox.js +0 -258
  588. package/dist/src/cli/commands/observe/inbox.js.map +0 -1
  589. package/dist/src/cli/commands/observe/index.d.ts.map +0 -1
  590. package/dist/src/cli/commands/observe/index.js +0 -118
  591. package/dist/src/cli/commands/observe/index.js.map +0 -1
  592. package/dist/src/cli/commands/observe/ingest.d.ts.map +0 -1
  593. package/dist/src/cli/commands/observe/ingest.js +0 -69
  594. package/dist/src/cli/commands/observe/ingest.js.map +0 -1
  595. package/dist/src/cli/commands/observe/show.d.ts.map +0 -1
  596. package/dist/src/cli/commands/observe/show.js.map +0 -1
  597. package/dist/src/cli/commands/sample.d.ts +0 -38
  598. package/dist/src/cli/commands/sample.d.ts.map +0 -1
  599. package/dist/src/cli/commands/sample.js +0 -488
  600. package/dist/src/cli/commands/sample.js.map +0 -1
  601. package/dist/src/cli/commands/skill-extract.d.ts +0 -20
  602. package/dist/src/cli/commands/skill-extract.d.ts.map +0 -1
  603. package/dist/src/cli/commands/skill-extract.js +0 -84
  604. package/dist/src/cli/commands/skill-extract.js.map +0 -1
  605. package/dist/src/cli/commands/studio.d.ts.map +0 -1
  606. package/dist/src/cli/commands/studio.js +0 -158
  607. package/dist/src/cli/commands/studio.js.map +0 -1
  608. package/dist/src/cli/index.d.ts.map +0 -1
  609. package/dist/src/cli/index.js.map +0 -1
  610. package/dist/src/cli/lib/cli-exit.d.ts.map +0 -1
  611. package/dist/src/cli/lib/cli-exit.js.map +0 -1
  612. package/dist/src/cli/lib/cmd-flags.d.ts +0 -236
  613. package/dist/src/cli/lib/cmd-flags.d.ts.map +0 -1
  614. package/dist/src/cli/lib/cmd-flags.js.map +0 -1
  615. package/dist/src/cli/lib/i18n-dict.d.ts +0 -54
  616. package/dist/src/cli/lib/i18n-dict.d.ts.map +0 -1
  617. package/dist/src/cli/lib/i18n-dict.js +0 -900
  618. package/dist/src/cli/lib/i18n-dict.js.map +0 -1
  619. package/dist/src/cli/lib/i18n.d.ts.map +0 -1
  620. package/dist/src/cli/lib/i18n.js.map +0 -1
  621. package/dist/src/cli/lib/parse-run-config.d.ts +0 -89
  622. package/dist/src/cli/lib/parse-run-config.d.ts.map +0 -1
  623. package/dist/src/cli/lib/parse-run-config.js +0 -252
  624. package/dist/src/cli/lib/parse-run-config.js.map +0 -1
  625. package/dist/src/cli/lib/progress.d.ts.map +0 -1
  626. package/dist/src/cli/lib/progress.js.map +0 -1
  627. package/dist/src/cli/lib/run-tally.d.ts.map +0 -1
  628. package/dist/src/cli/lib/run-tally.js.map +0 -1
  629. package/dist/src/cli/lib/shared.d.ts.map +0 -1
  630. package/dist/src/cli/lib/shared.js.map +0 -1
  631. package/dist/src/cli/lib/update-check.d.ts +0 -3
  632. package/dist/src/cli/lib/update-check.d.ts.map +0 -1
  633. package/dist/src/cli/lib/update-check.js +0 -37
  634. package/dist/src/cli/lib/update-check.js.map +0 -1
  635. package/dist/src/cli/oclif/base-command.d.ts.map +0 -1
  636. package/dist/src/cli/oclif/base-command.js.map +0 -1
  637. package/dist/src/cli/oclif/help.d.ts.map +0 -1
  638. package/dist/src/cli/oclif/help.js.map +0 -1
  639. package/dist/src/cli/oclif/i18n.d.ts.map +0 -1
  640. package/dist/src/cli/oclif/i18n.js.map +0 -1
  641. package/dist/src/cli/oclif/parsers.d.ts.map +0 -1
  642. package/dist/src/cli/oclif/parsers.js.map +0 -1
  643. package/dist/src/cli/oclif/projection.d.ts.map +0 -1
  644. package/dist/src/cli/oclif/projection.js.map +0 -1
  645. package/dist/src/cli/oclif/run.d.ts.map +0 -1
  646. package/dist/src/cli/oclif/run.js +0 -11
  647. package/dist/src/cli/oclif/run.js.map +0 -1
  648. package/dist/src/diagnosis/observe-mapper.d.ts.map +0 -1
  649. package/dist/src/diagnosis/observe-mapper.js.map +0 -1
  650. package/dist/src/diagnosis/observe-producer.d.ts.map +0 -1
  651. package/dist/src/diagnosis/observe-producer.js +0 -197
  652. package/dist/src/diagnosis/observe-producer.js.map +0 -1
  653. package/dist/src/diagnosis/studio-projection.d.ts +0 -14
  654. package/dist/src/diagnosis/studio-projection.d.ts.map +0 -1
  655. package/dist/src/diagnosis/studio-projection.js.map +0 -1
  656. package/dist/src/diagnosis/types.d.ts +0 -79
  657. package/dist/src/diagnosis/types.d.ts.map +0 -1
  658. package/dist/src/diagnosis/types.js +0 -20
  659. package/dist/src/diagnosis/types.js.map +0 -1
  660. package/dist/src/doctor/fixer.d.ts.map +0 -1
  661. package/dist/src/doctor/fixer.js.map +0 -1
  662. package/dist/src/doctor/health/builtin-dimensions.d.ts.map +0 -1
  663. package/dist/src/doctor/health/builtin-dimensions.js.map +0 -1
  664. package/dist/src/doctor/health/composer.d.ts.map +0 -1
  665. package/dist/src/doctor/health/composer.js +0 -296
  666. package/dist/src/doctor/health/composer.js.map +0 -1
  667. package/dist/src/doctor/health/dimension-registry.d.ts.map +0 -1
  668. package/dist/src/doctor/health/dimension-registry.js.map +0 -1
  669. package/dist/src/doctor/health/dimension-spec.d.ts +0 -47
  670. package/dist/src/doctor/health/dimension-spec.d.ts.map +0 -1
  671. package/dist/src/doctor/health/dimension-spec.js.map +0 -1
  672. package/dist/src/doctor/health/parser.d.ts.map +0 -1
  673. package/dist/src/doctor/health/parser.js.map +0 -1
  674. package/dist/src/doctor/health/prompt-builder.d.ts.map +0 -1
  675. package/dist/src/doctor/health/prompt-builder.js.map +0 -1
  676. package/dist/src/doctor/health/register.d.ts.map +0 -1
  677. package/dist/src/doctor/health/register.js.map +0 -1
  678. package/dist/src/doctor/html-renderer.d.ts +0 -20
  679. package/dist/src/doctor/html-renderer.d.ts.map +0 -1
  680. package/dist/src/doctor/html-renderer.js +0 -376
  681. package/dist/src/doctor/html-renderer.js.map +0 -1
  682. package/dist/src/doctor/index.d.ts.map +0 -1
  683. package/dist/src/doctor/index.js.map +0 -1
  684. package/dist/src/doctor/preflight.d.ts.map +0 -1
  685. package/dist/src/doctor/preflight.js.map +0 -1
  686. package/dist/src/doctor/renderer.d.ts +0 -17
  687. package/dist/src/doctor/renderer.d.ts.map +0 -1
  688. package/dist/src/doctor/renderer.js +0 -123
  689. package/dist/src/doctor/renderer.js.map +0 -1
  690. package/dist/src/doctor/rules.d.ts.map +0 -1
  691. package/dist/src/doctor/rules.js +0 -289
  692. package/dist/src/doctor/rules.js.map +0 -1
  693. package/dist/src/eval-core/bootstrap.d.ts +0 -72
  694. package/dist/src/eval-core/bootstrap.d.ts.map +0 -1
  695. package/dist/src/eval-core/bootstrap.js +0 -174
  696. package/dist/src/eval-core/bootstrap.js.map +0 -1
  697. package/dist/src/eval-core/cache.d.ts.map +0 -1
  698. package/dist/src/eval-core/cache.js.map +0 -1
  699. package/dist/src/eval-core/comparability.d.ts.map +0 -1
  700. package/dist/src/eval-core/comparability.js.map +0 -1
  701. package/dist/src/eval-core/dependency-checker.d.ts +0 -58
  702. package/dist/src/eval-core/dependency-checker.d.ts.map +0 -1
  703. package/dist/src/eval-core/dependency-checker.js.map +0 -1
  704. package/dist/src/eval-core/evaluation-execution.d.ts.map +0 -1
  705. package/dist/src/eval-core/evaluation-execution.js.map +0 -1
  706. package/dist/src/eval-core/evaluation-job.d.ts.map +0 -1
  707. package/dist/src/eval-core/evaluation-job.js.map +0 -1
  708. package/dist/src/eval-core/evaluation-reporting.d.ts.map +0 -1
  709. package/dist/src/eval-core/evaluation-reporting.js +0 -292
  710. package/dist/src/eval-core/evaluation-reporting.js.map +0 -1
  711. package/dist/src/eval-core/execution-strategy.d.ts.map +0 -1
  712. package/dist/src/eval-core/execution-strategy.js +0 -165
  713. package/dist/src/eval-core/execution-strategy.js.map +0 -1
  714. package/dist/src/eval-core/fact-checker.d.ts.map +0 -1
  715. package/dist/src/eval-core/fact-checker.js.map +0 -1
  716. package/dist/src/eval-core/layer-gates.d.ts.map +0 -1
  717. package/dist/src/eval-core/layer-gates.js.map +0 -1
  718. package/dist/src/eval-core/mocks-runtime.d.ts.map +0 -1
  719. package/dist/src/eval-core/mocks-runtime.js +0 -559
  720. package/dist/src/eval-core/mocks-runtime.js.map +0 -1
  721. package/dist/src/eval-core/schema.d.ts.map +0 -1
  722. package/dist/src/eval-core/schema.js.map +0 -1
  723. package/dist/src/eval-core/statistics.d.ts.map +0 -1
  724. package/dist/src/eval-core/statistics.js.map +0 -1
  725. package/dist/src/eval-core/task-planner.d.ts.map +0 -1
  726. package/dist/src/eval-core/task-planner.js.map +0 -1
  727. package/dist/src/eval-core/verdict.d.ts +0 -77
  728. package/dist/src/eval-core/verdict.d.ts.map +0 -1
  729. package/dist/src/eval-core/verdict.js +0 -322
  730. package/dist/src/eval-core/verdict.js.map +0 -1
  731. package/dist/src/eval-workflows/batch-evaluation-workflow.d.ts.map +0 -1
  732. package/dist/src/eval-workflows/batch-evaluation-workflow.js.map +0 -1
  733. package/dist/src/eval-workflows/evaluation-pipeline.d.ts +0 -109
  734. package/dist/src/eval-workflows/evaluation-pipeline.d.ts.map +0 -1
  735. package/dist/src/eval-workflows/evaluation-pipeline.js +0 -373
  736. package/dist/src/eval-workflows/evaluation-pipeline.js.map +0 -1
  737. package/dist/src/eval-workflows/evaluation-preparation.d.ts.map +0 -1
  738. package/dist/src/eval-workflows/evaluation-preparation.js +0 -77
  739. package/dist/src/eval-workflows/evaluation-preparation.js.map +0 -1
  740. package/dist/src/eval-workflows/run-evaluation.d.ts +0 -151
  741. package/dist/src/eval-workflows/run-evaluation.d.ts.map +0 -1
  742. package/dist/src/eval-workflows/run-evaluation.js +0 -528
  743. package/dist/src/eval-workflows/run-evaluation.js.map +0 -1
  744. package/dist/src/executors/anthropic-api.d.ts.map +0 -1
  745. package/dist/src/executors/anthropic-api.js.map +0 -1
  746. package/dist/src/executors/claude-cli.d.ts.map +0 -1
  747. package/dist/src/executors/claude-cli.js.map +0 -1
  748. package/dist/src/executors/claude-sdk-trace.d.ts.map +0 -1
  749. package/dist/src/executors/claude-sdk-trace.js.map +0 -1
  750. package/dist/src/executors/claude-sdk.d.ts.map +0 -1
  751. package/dist/src/executors/claude-sdk.js.map +0 -1
  752. package/dist/src/executors/codex-cli-trace.d.ts.map +0 -1
  753. package/dist/src/executors/codex-cli-trace.js.map +0 -1
  754. package/dist/src/executors/codex-cli.d.ts.map +0 -1
  755. package/dist/src/executors/codex-cli.js.map +0 -1
  756. package/dist/src/executors/codex-sdk.d.ts.map +0 -1
  757. package/dist/src/executors/codex-sdk.js.map +0 -1
  758. package/dist/src/executors/gemini.d.ts.map +0 -1
  759. package/dist/src/executors/gemini.js.map +0 -1
  760. package/dist/src/executors/index.d.ts.map +0 -1
  761. package/dist/src/executors/index.js.map +0 -1
  762. package/dist/src/executors/openai-api.d.ts.map +0 -1
  763. package/dist/src/executors/openai-api.js.map +0 -1
  764. package/dist/src/executors/runtime-fingerprint.d.ts.map +0 -1
  765. package/dist/src/executors/runtime-fingerprint.js.map +0 -1
  766. package/dist/src/executors/script.d.ts.map +0 -1
  767. package/dist/src/executors/script.js.map +0 -1
  768. package/dist/src/executors/shared.d.ts +0 -194
  769. package/dist/src/executors/shared.d.ts.map +0 -1
  770. package/dist/src/executors/shared.js +0 -256
  771. package/dist/src/executors/shared.js.map +0 -1
  772. package/dist/src/grading/assertions.d.ts.map +0 -1
  773. package/dist/src/grading/assertions.js.map +0 -1
  774. package/dist/src/grading/debias-validate.d.ts.map +0 -1
  775. package/dist/src/grading/debias-validate.js.map +0 -1
  776. package/dist/src/grading/diagnostic.d.ts.map +0 -1
  777. package/dist/src/grading/diagnostic.js.map +0 -1
  778. package/dist/src/grading/gold-cli.d.ts.map +0 -1
  779. package/dist/src/grading/gold-cli.js.map +0 -1
  780. package/dist/src/grading/gold-dataset.d.ts.map +0 -1
  781. package/dist/src/grading/gold-dataset.js.map +0 -1
  782. package/dist/src/grading/human-gold.d.ts.map +0 -1
  783. package/dist/src/grading/human-gold.js.map +0 -1
  784. package/dist/src/grading/index.d.ts.map +0 -1
  785. package/dist/src/grading/index.js.map +0 -1
  786. package/dist/src/grading/judge.d.ts.map +0 -1
  787. package/dist/src/grading/judge.js.map +0 -1
  788. package/dist/src/grading/layered-scores.d.ts.map +0 -1
  789. package/dist/src/grading/layered-scores.js.map +0 -1
  790. package/dist/src/inputs/eval-config.d.ts.map +0 -1
  791. package/dist/src/inputs/eval-config.js +0 -251
  792. package/dist/src/inputs/eval-config.js.map +0 -1
  793. package/dist/src/inputs/load-samples.d.ts.map +0 -1
  794. package/dist/src/inputs/load-samples.js.map +0 -1
  795. package/dist/src/inputs/mcp-resolver.d.ts.map +0 -1
  796. package/dist/src/inputs/mcp-resolver.js.map +0 -1
  797. package/dist/src/inputs/skill-loader.d.ts +0 -27
  798. package/dist/src/inputs/skill-loader.d.ts.map +0 -1
  799. package/dist/src/inputs/skill-loader.js +0 -253
  800. package/dist/src/inputs/skill-loader.js.map +0 -1
  801. package/dist/src/inputs/url-fetcher.d.ts.map +0 -1
  802. package/dist/src/inputs/url-fetcher.js.map +0 -1
  803. package/dist/src/observability/experience.d.ts +0 -441
  804. package/dist/src/observability/experience.d.ts.map +0 -1
  805. package/dist/src/observability/experience.js +0 -2400
  806. package/dist/src/observability/experience.js.map +0 -1
  807. package/dist/src/observability/inbox-view-model.d.ts +0 -30
  808. package/dist/src/observability/inbox-view-model.d.ts.map +0 -1
  809. package/dist/src/observability/inbox-view-model.js +0 -144
  810. package/dist/src/observability/inbox-view-model.js.map +0 -1
  811. package/dist/src/observability/inbox.d.ts +0 -127
  812. package/dist/src/observability/inbox.d.ts.map +0 -1
  813. package/dist/src/observability/inbox.js +0 -755
  814. package/dist/src/observability/inbox.js.map +0 -1
  815. package/dist/src/observability/problem-patterns.d.ts +0 -52
  816. package/dist/src/observability/problem-patterns.d.ts.map +0 -1
  817. package/dist/src/observability/problem-patterns.js +0 -205
  818. package/dist/src/observability/problem-patterns.js.map +0 -1
  819. package/dist/src/observability/resolved-review.d.ts +0 -25
  820. package/dist/src/observability/resolved-review.d.ts.map +0 -1
  821. package/dist/src/observability/resolved-review.js +0 -231
  822. package/dist/src/observability/resolved-review.js.map +0 -1
  823. package/dist/src/observability/review-state.d.ts +0 -61
  824. package/dist/src/observability/review-state.d.ts.map +0 -1
  825. package/dist/src/observability/review-state.js.map +0 -1
  826. package/dist/src/observability/skill-chain-advisories.d.ts +0 -25
  827. package/dist/src/observability/skill-chain-advisories.d.ts.map +0 -1
  828. package/dist/src/observability/skill-chain-advisories.js.map +0 -1
  829. package/dist/src/observability/skill-chain.d.ts +0 -62
  830. package/dist/src/observability/skill-chain.d.ts.map +0 -1
  831. package/dist/src/observability/skill-chain.js +0 -270
  832. package/dist/src/observability/skill-chain.js.map +0 -1
  833. package/dist/src/observability/skill-health-analyzer.d.ts +0 -83
  834. package/dist/src/observability/skill-health-analyzer.d.ts.map +0 -1
  835. package/dist/src/observability/skill-health-analyzer.js +0 -238
  836. package/dist/src/observability/skill-health-analyzer.js.map +0 -1
  837. package/dist/src/observability/soft-standards.d.ts +0 -130
  838. package/dist/src/observability/soft-standards.d.ts.map +0 -1
  839. package/dist/src/observability/soft-standards.js +0 -426
  840. package/dist/src/observability/soft-standards.js.map +0 -1
  841. package/dist/src/observability/text-signals.d.ts +0 -14
  842. package/dist/src/observability/text-signals.d.ts.map +0 -1
  843. package/dist/src/observability/text-signals.js +0 -106
  844. package/dist/src/observability/text-signals.js.map +0 -1
  845. package/dist/src/observability/trace-adapter.d.ts.map +0 -1
  846. package/dist/src/observability/trace-adapter.js.map +0 -1
  847. package/dist/src/observability/trace-attribution.d.ts +0 -56
  848. package/dist/src/observability/trace-attribution.d.ts.map +0 -1
  849. package/dist/src/observability/trace-attribution.js +0 -200
  850. package/dist/src/observability/trace-attribution.js.map +0 -1
  851. package/dist/src/observability/trace-segmenter.d.ts +0 -52
  852. package/dist/src/observability/trace-segmenter.d.ts.map +0 -1
  853. package/dist/src/observability/trace-segmenter.js +0 -322
  854. package/dist/src/observability/trace-segmenter.js.map +0 -1
  855. package/dist/src/observability/trace-source.d.ts +0 -99
  856. package/dist/src/observability/trace-source.d.ts.map +0 -1
  857. package/dist/src/observability/trace-source.js +0 -502
  858. package/dist/src/observability/trace-source.js.map +0 -1
  859. package/dist/src/renderer/html-renderer.d.ts.map +0 -1
  860. package/dist/src/renderer/html-renderer.js.map +0 -1
  861. package/dist/src/renderer/layout.d.ts.map +0 -1
  862. package/dist/src/renderer/layout.js +0 -774
  863. package/dist/src/renderer/layout.js.map +0 -1
  864. package/dist/src/renderer/observation-inbox-renderer.d.ts +0 -4
  865. package/dist/src/renderer/observation-inbox-renderer.d.ts.map +0 -1
  866. package/dist/src/renderer/observation-inbox-renderer.js +0 -10366
  867. package/dist/src/renderer/observation-inbox-renderer.js.map +0 -1
  868. package/dist/src/renderer/skill-detail-renderer.d.ts +0 -15
  869. package/dist/src/renderer/skill-detail-renderer.d.ts.map +0 -1
  870. package/dist/src/renderer/skill-detail-renderer.js +0 -1244
  871. package/dist/src/renderer/skill-detail-renderer.js.map +0 -1
  872. package/dist/src/renderer/skill-health-renderer.d.ts.map +0 -1
  873. package/dist/src/renderer/skill-health-renderer.js +0 -253
  874. package/dist/src/renderer/skill-health-renderer.js.map +0 -1
  875. package/dist/src/renderer/skill-list-renderer.d.ts +0 -4
  876. package/dist/src/renderer/skill-list-renderer.d.ts.map +0 -1
  877. package/dist/src/renderer/skill-list-renderer.js +0 -334
  878. package/dist/src/renderer/skill-list-renderer.js.map +0 -1
  879. package/dist/src/renderer/summary.d.ts +0 -68
  880. package/dist/src/renderer/summary.d.ts.map +0 -1
  881. package/dist/src/renderer/summary.js +0 -1896
  882. package/dist/src/renderer/summary.js.map +0 -1
  883. package/dist/src/renderer/table.d.ts.map +0 -1
  884. package/dist/src/renderer/table.js.map +0 -1
  885. package/dist/src/renderer/test-view.d.ts.map +0 -1
  886. package/dist/src/renderer/test-view.js.map +0 -1
  887. package/dist/src/renderer/trends.d.ts.map +0 -1
  888. package/dist/src/renderer/trends.js.map +0 -1
  889. package/dist/src/server/job-store.d.ts.map +0 -1
  890. package/dist/src/server/job-store.js.map +0 -1
  891. package/dist/src/server/report-server.d.ts.map +0 -1
  892. package/dist/src/server/report-server.js +0 -894
  893. package/dist/src/server/report-server.js.map +0 -1
  894. package/dist/src/server/report-store.d.ts.map +0 -1
  895. package/dist/src/server/report-store.js.map +0 -1
  896. package/dist/src/server/skill-index.d.ts +0 -81
  897. package/dist/src/server/skill-index.d.ts.map +0 -1
  898. package/dist/src/server/skill-index.js +0 -377
  899. package/dist/src/server/skill-index.js.map +0 -1
  900. package/dist/src/server/skill-insights.d.ts +0 -101
  901. package/dist/src/server/skill-insights.d.ts.map +0 -1
  902. package/dist/src/server/skill-insights.js +0 -788
  903. package/dist/src/server/skill-insights.js.map +0 -1
  904. package/dist/src/shared/hard-rules.d.ts.map +0 -1
  905. package/dist/src/shared/hard-rules.js.map +0 -1
  906. package/dist/src/shared/llm-prompts/index.d.ts +0 -14
  907. package/dist/src/shared/llm-prompts/index.d.ts.map +0 -1
  908. package/dist/src/shared/llm-prompts/index.js +0 -35
  909. package/dist/src/shared/llm-prompts/index.js.map +0 -1
  910. package/dist/src/shared/llm-prompts/skill-health.d.ts.map +0 -1
  911. package/dist/src/shared/llm-prompts/skill-health.js.map +0 -1
  912. package/dist/src/shared/time.d.ts.map +0 -1
  913. package/dist/src/shared/time.js.map +0 -1
  914. package/dist/src/shared/tool-search.d.ts.map +0 -1
  915. package/dist/src/shared/tool-search.js.map +0 -1
  916. package/dist/src/types/doctor.d.ts +0 -157
  917. package/dist/src/types/doctor.d.ts.map +0 -1
  918. package/dist/src/types/doctor.js.map +0 -1
  919. package/dist/src/types/eval.d.ts +0 -377
  920. package/dist/src/types/eval.d.ts.map +0 -1
  921. package/dist/src/types/eval.js.map +0 -1
  922. package/dist/src/types/executor.d.ts.map +0 -1
  923. package/dist/src/types/executor.js.map +0 -1
  924. package/dist/src/types/index.d.ts +0 -8
  925. package/dist/src/types/index.d.ts.map +0 -1
  926. package/dist/src/types/index.js +0 -8
  927. package/dist/src/types/index.js.map +0 -1
  928. package/dist/src/types/judge.d.ts.map +0 -1
  929. package/dist/src/types/judge.js.map +0 -1
  930. package/dist/src/types/report.d.ts +0 -557
  931. package/dist/src/types/report.d.ts.map +0 -1
  932. package/dist/src/types/report.js.map +0 -1
  933. package/dist/src/types/shared.d.ts.map +0 -1
  934. package/dist/src/types/shared.js.map +0 -1
  935. package/dist/src/types/storage.d.ts.map +0 -1
  936. package/dist/src/types/storage.js.map +0 -1
  937. package/dist/src/util/safe-slice.d.ts +0 -23
  938. package/dist/src/util/safe-slice.d.ts.map +0 -1
  939. package/dist/src/util/safe-slice.js +0 -33
  940. package/dist/src/util/safe-slice.js.map +0 -1
  941. package/docs/prompts/llm-enhanced-review.prompt.md +0 -111
  942. /package/dist/{src/analysis → analysis}/coverage-analyzer.d.ts +0 -0
  943. /package/dist/{src/analysis → analysis}/coverage-analyzer.js +0 -0
  944. /package/dist/{src/analysis → analysis}/failure-clusterer.d.ts +0 -0
  945. /package/dist/{src/analysis → analysis}/failure-clusterer.js +0 -0
  946. /package/dist/{src/analysis → analysis}/hedging-classifier.d.ts +0 -0
  947. /package/dist/{src/analysis → analysis}/hedging-classifier.js +0 -0
  948. /package/dist/{src/analysis → analysis}/sample-diagnostics.d.ts +0 -0
  949. /package/dist/{src/analysis → analysis}/sample-diagnostics.js +0 -0
  950. /package/dist/{src/authoring → authoring}/sample-fixer.d.ts +0 -0
  951. /package/dist/{src/authoring → authoring}/sample-fixer.js +0 -0
  952. /package/dist/{src/cli → cli}/commands/eval/gold/compare.d.ts +0 -0
  953. /package/dist/{src/cli → cli}/commands/eval/gold/compare.js +0 -0
  954. /package/dist/{src/cli → cli}/commands/eval/gold/index.d.ts +0 -0
  955. /package/dist/{src/cli → cli}/commands/eval/gold/index.js +0 -0
  956. /package/dist/{src/cli → cli}/commands/eval/gold/init.d.ts +0 -0
  957. /package/dist/{src/cli → cli}/commands/eval/gold/init.js +0 -0
  958. /package/dist/{src/cli → cli}/commands/eval/gold/validate.d.ts +0 -0
  959. /package/dist/{src/cli → cli}/commands/eval/gold/validate.js +0 -0
  960. /package/dist/{src/cli → cli}/commands/eval/index.d.ts +0 -0
  961. /package/dist/{src/cli → cli}/commands/init.d.ts +0 -0
  962. /package/dist/{src/cli → cli}/commands/init.js +0 -0
  963. /package/dist/{src/cli → cli}/commands/observe/inbox.d.ts +0 -0
  964. /package/dist/{src/cli → cli}/commands/observe/index.d.ts +0 -0
  965. /package/dist/{src/cli → cli}/commands/observe/ingest.d.ts +0 -0
  966. /package/dist/{src/cli → cli}/commands/observe/show.d.ts +0 -0
  967. /package/dist/{src/cli → cli}/commands/observe/show.js +0 -0
  968. /package/dist/{src/cli → cli}/commands/studio.d.ts +0 -0
  969. /package/dist/{src/cli → cli}/index.d.ts +0 -0
  970. /package/dist/{src/cli → cli}/index.js +0 -0
  971. /package/dist/{src/cli → cli}/lib/cli-exit.d.ts +0 -0
  972. /package/dist/{src/cli → cli}/lib/cli-exit.js +0 -0
  973. /package/dist/{src/cli → cli}/lib/cmd-flags.js +0 -0
  974. /package/dist/{src/cli → cli}/lib/i18n.d.ts +0 -0
  975. /package/dist/{src/cli → cli}/lib/i18n.js +0 -0
  976. /package/dist/{src/cli → cli}/lib/progress.d.ts +0 -0
  977. /package/dist/{src/cli → cli}/lib/progress.js +0 -0
  978. /package/dist/{src/cli → cli}/lib/run-tally.d.ts +0 -0
  979. /package/dist/{src/cli → cli}/lib/run-tally.js +0 -0
  980. /package/dist/{src/cli → cli}/lib/shared.d.ts +0 -0
  981. /package/dist/{src/cli → cli}/lib/shared.js +0 -0
  982. /package/dist/{src/cli → cli}/oclif/base-command.d.ts +0 -0
  983. /package/dist/{src/cli → cli}/oclif/base-command.js +0 -0
  984. /package/dist/{src/cli → cli}/oclif/help.d.ts +0 -0
  985. /package/dist/{src/cli → cli}/oclif/help.js +0 -0
  986. /package/dist/{src/cli → cli}/oclif/i18n.d.ts +0 -0
  987. /package/dist/{src/cli → cli}/oclif/i18n.js +0 -0
  988. /package/dist/{src/cli → cli}/oclif/parsers.d.ts +0 -0
  989. /package/dist/{src/cli → cli}/oclif/parsers.js +0 -0
  990. /package/dist/{src/cli → cli}/oclif/projection.d.ts +0 -0
  991. /package/dist/{src/cli → cli}/oclif/projection.js +0 -0
  992. /package/dist/{src/cli → cli}/oclif/run.d.ts +0 -0
  993. /package/dist/{src/diagnosis → diagnosis}/observe-mapper.d.ts +0 -0
  994. /package/dist/{src/diagnosis → diagnosis}/observe-mapper.js +0 -0
  995. /package/dist/{src/diagnosis → diagnosis}/observe-producer.d.ts +0 -0
  996. /package/dist/{src/diagnosis → diagnosis}/studio-projection.js +0 -0
  997. /package/dist/{src/doctor → doctor}/fixer.d.ts +0 -0
  998. /package/dist/{src/doctor → doctor}/fixer.js +0 -0
  999. /package/dist/{src/doctor → doctor}/health/builtin-dimensions.d.ts +0 -0
  1000. /package/dist/{src/doctor → doctor}/health/builtin-dimensions.js +0 -0
  1001. /package/dist/{src/doctor → doctor}/health/composer.d.ts +0 -0
  1002. /package/dist/{src/doctor → doctor}/health/dimension-registry.d.ts +0 -0
  1003. /package/dist/{src/doctor → doctor}/health/dimension-registry.js +0 -0
  1004. /package/dist/{src/doctor → doctor}/health/dimension-spec.js +0 -0
  1005. /package/dist/{src/doctor → doctor}/health/parser.d.ts +0 -0
  1006. /package/dist/{src/doctor → doctor}/health/parser.js +0 -0
  1007. /package/dist/{src/doctor → doctor}/health/prompt-builder.d.ts +0 -0
  1008. /package/dist/{src/doctor → doctor}/health/prompt-builder.js +0 -0
  1009. /package/dist/{src/doctor → doctor}/health/register.d.ts +0 -0
  1010. /package/dist/{src/doctor → doctor}/health/register.js +0 -0
  1011. /package/dist/{src/doctor → doctor}/index.d.ts +0 -0
  1012. /package/dist/{src/doctor → doctor}/index.js +0 -0
  1013. /package/dist/{src/doctor → doctor}/preflight.d.ts +0 -0
  1014. /package/dist/{src/doctor → doctor}/preflight.js +0 -0
  1015. /package/dist/{src/doctor → doctor}/rules.d.ts +0 -0
  1016. /package/dist/{src/eval-core → eval-core}/cache.d.ts +0 -0
  1017. /package/dist/{src/eval-core → eval-core}/cache.js +0 -0
  1018. /package/dist/{src/eval-core → eval-core}/comparability.d.ts +0 -0
  1019. /package/dist/{src/eval-core → eval-core}/comparability.js +0 -0
  1020. /package/dist/{src/eval-core → eval-core}/dependency-checker.js +0 -0
  1021. /package/dist/{src/eval-core → eval-core}/evaluation-execution.d.ts +0 -0
  1022. /package/dist/{src/eval-core → eval-core}/evaluation-execution.js +0 -0
  1023. /package/dist/{src/eval-core → eval-core}/evaluation-job.d.ts +0 -0
  1024. /package/dist/{src/eval-core → eval-core}/evaluation-job.js +0 -0
  1025. /package/dist/{src/eval-core → eval-core}/evaluation-reporting.d.ts +0 -0
  1026. /package/dist/{src/eval-core → eval-core}/execution-strategy.d.ts +0 -0
  1027. /package/dist/{src/eval-core → eval-core}/fact-checker.d.ts +0 -0
  1028. /package/dist/{src/eval-core → eval-core}/fact-checker.js +0 -0
  1029. /package/dist/{src/eval-core → eval-core}/layer-gates.d.ts +0 -0
  1030. /package/dist/{src/eval-core → eval-core}/layer-gates.js +0 -0
  1031. /package/dist/{src/eval-core → eval-core}/mock-hook.cjs +0 -0
  1032. /package/dist/{src/eval-core → eval-core}/mocks-runtime.d.ts +0 -0
  1033. /package/dist/{src/eval-core → eval-core}/schema.d.ts +0 -0
  1034. /package/dist/{src/eval-core → eval-core}/schema.js +0 -0
  1035. /package/dist/{src/eval-core → eval-core}/statistics.d.ts +0 -0
  1036. /package/dist/{src/eval-core → eval-core}/statistics.js +0 -0
  1037. /package/dist/{src/eval-core → eval-core}/task-planner.d.ts +0 -0
  1038. /package/dist/{src/eval-core → eval-core}/task-planner.js +0 -0
  1039. /package/dist/{src/eval-workflows → eval-workflows}/batch-evaluation-workflow.d.ts +0 -0
  1040. /package/dist/{src/eval-workflows → eval-workflows}/batch-evaluation-workflow.js +0 -0
  1041. /package/dist/{src/eval-workflows → eval-workflows}/evaluation-preparation.d.ts +0 -0
  1042. /package/dist/{src/executors → executors}/anthropic-api.d.ts +0 -0
  1043. /package/dist/{src/executors → executors}/anthropic-api.js +0 -0
  1044. /package/dist/{src/executors → executors}/claude-cli.d.ts +0 -0
  1045. /package/dist/{src/executors → executors}/claude-cli.js +0 -0
  1046. /package/dist/{src/executors → executors}/claude-sdk-trace.d.ts +0 -0
  1047. /package/dist/{src/executors → executors}/claude-sdk-trace.js +0 -0
  1048. /package/dist/{src/executors → executors}/claude-sdk.d.ts +0 -0
  1049. /package/dist/{src/executors → executors}/claude-sdk.js +0 -0
  1050. /package/dist/{src/executors → executors}/codex-cli-trace.d.ts +0 -0
  1051. /package/dist/{src/executors → executors}/codex-cli-trace.js +0 -0
  1052. /package/dist/{src/executors → executors}/codex-cli.d.ts +0 -0
  1053. /package/dist/{src/executors → executors}/codex-cli.js +0 -0
  1054. /package/dist/{src/executors → executors}/codex-sdk.d.ts +0 -0
  1055. /package/dist/{src/executors → executors}/codex-sdk.js +0 -0
  1056. /package/dist/{src/executors → executors}/gemini.d.ts +0 -0
  1057. /package/dist/{src/executors → executors}/gemini.js +0 -0
  1058. /package/dist/{src/executors → executors}/index.d.ts +0 -0
  1059. /package/dist/{src/executors → executors}/index.js +0 -0
  1060. /package/dist/{src/executors → executors}/openai-api.d.ts +0 -0
  1061. /package/dist/{src/executors → executors}/openai-api.js +0 -0
  1062. /package/dist/{src/executors → executors}/runtime-fingerprint.d.ts +0 -0
  1063. /package/dist/{src/executors → executors}/runtime-fingerprint.js +0 -0
  1064. /package/dist/{src/executors → executors}/script.d.ts +0 -0
  1065. /package/dist/{src/executors → executors}/script.js +0 -0
  1066. /package/dist/{src/grading → grading}/assertions.d.ts +0 -0
  1067. /package/dist/{src/grading → grading}/assertions.js +0 -0
  1068. /package/dist/{src/grading → grading}/debias-validate.d.ts +0 -0
  1069. /package/dist/{src/grading → grading}/debias-validate.js +0 -0
  1070. /package/dist/{src/grading → grading}/diagnostic.d.ts +0 -0
  1071. /package/dist/{src/grading → grading}/diagnostic.js +0 -0
  1072. /package/dist/{src/grading → grading}/gold-cli.d.ts +0 -0
  1073. /package/dist/{src/grading → grading}/gold-cli.js +0 -0
  1074. /package/dist/{src/grading → grading}/gold-dataset.d.ts +0 -0
  1075. /package/dist/{src/grading → grading}/gold-dataset.js +0 -0
  1076. /package/dist/{src/grading → grading}/human-gold.d.ts +0 -0
  1077. /package/dist/{src/grading → grading}/human-gold.js +0 -0
  1078. /package/dist/{src/grading → grading}/index.d.ts +0 -0
  1079. /package/dist/{src/grading → grading}/index.js +0 -0
  1080. /package/dist/{src/grading → grading}/judge.d.ts +0 -0
  1081. /package/dist/{src/grading → grading}/judge.js +0 -0
  1082. /package/dist/{src/grading → grading}/layered-scores.d.ts +0 -0
  1083. /package/dist/{src/grading → grading}/layered-scores.js +0 -0
  1084. /package/dist/{src/inputs → inputs}/eval-config.d.ts +0 -0
  1085. /package/dist/{src/inputs → inputs}/load-samples.d.ts +0 -0
  1086. /package/dist/{src/inputs → inputs}/load-samples.js +0 -0
  1087. /package/dist/{src/inputs → inputs}/mcp-resolver.d.ts +0 -0
  1088. /package/dist/{src/inputs → inputs}/mcp-resolver.js +0 -0
  1089. /package/dist/{src/inputs → inputs}/url-fetcher.d.ts +0 -0
  1090. /package/dist/{src/inputs → inputs}/url-fetcher.js +0 -0
  1091. /package/dist/{src/observability → observability}/review-state.js +0 -0
  1092. /package/dist/{src/observability → observability}/skill-chain-advisories.js +0 -0
  1093. /package/dist/{src/observability → observability}/trace-adapter.d.ts +0 -0
  1094. /package/dist/{src/observability → observability}/trace-adapter.js +0 -0
  1095. /package/dist/{src/renderer → renderer}/html-renderer.d.ts +0 -0
  1096. /package/dist/{src/renderer → renderer}/html-renderer.js +0 -0
  1097. /package/dist/{src/renderer → renderer}/layout.d.ts +0 -0
  1098. /package/dist/{src/renderer → renderer}/skill-health-renderer.d.ts +0 -0
  1099. /package/dist/{src/renderer → renderer}/table.d.ts +0 -0
  1100. /package/dist/{src/renderer → renderer}/table.js +0 -0
  1101. /package/dist/{src/renderer → renderer}/test-view.d.ts +0 -0
  1102. /package/dist/{src/renderer → renderer}/test-view.js +0 -0
  1103. /package/dist/{src/renderer → renderer}/trends.d.ts +0 -0
  1104. /package/dist/{src/renderer → renderer}/trends.js +0 -0
  1105. /package/dist/{src/server → server}/job-store.d.ts +0 -0
  1106. /package/dist/{src/server → server}/job-store.js +0 -0
  1107. /package/dist/{src/server → server}/report-server.d.ts +0 -0
  1108. /package/dist/{src/server → server}/report-store.d.ts +0 -0
  1109. /package/dist/{src/server → server}/report-store.js +0 -0
  1110. /package/dist/{src/shared → shared}/hard-rules.d.ts +0 -0
  1111. /package/dist/{src/shared → shared}/hard-rules.js +0 -0
  1112. /package/dist/{src/shared → shared}/llm-prompts/skill-health.d.ts +0 -0
  1113. /package/dist/{src/shared → shared}/llm-prompts/skill-health.js +0 -0
  1114. /package/dist/{src/shared → shared}/time.d.ts +0 -0
  1115. /package/dist/{src/shared → shared}/time.js +0 -0
  1116. /package/dist/{src/shared → shared}/tool-search.d.ts +0 -0
  1117. /package/dist/{src/shared → shared}/tool-search.js +0 -0
  1118. /package/dist/{src/types → types}/doctor.js +0 -0
  1119. /package/dist/{src/types → types}/eval.js +0 -0
  1120. /package/dist/{src/types → types}/executor.d.ts +0 -0
  1121. /package/dist/{src/types → types}/executor.js +0 -0
  1122. /package/dist/{src/types → types}/judge.d.ts +0 -0
  1123. /package/dist/{src/types → types}/judge.js +0 -0
  1124. /package/dist/{src/types → types}/report.js +0 -0
  1125. /package/dist/{src/types → types}/shared.d.ts +0 -0
  1126. /package/dist/{src/types → types}/shared.js +0 -0
  1127. /package/dist/{src/types → types}/storage.d.ts +0 -0
  1128. /package/dist/{src/types → types}/storage.js +0 -0
@@ -0,0 +1,1323 @@
1
+ /**
2
+ * Skill 详情页 — 问题优先,扁平 1-2 屏。
3
+ *
4
+ * ┌─ skill 名 + band + 健康摘要一句话 ──────────────┐
5
+ * │ 关键问题(按受众分组,默认全展开)│ 健康趋势(chart.js 折线)│
6
+ * │ #1 [高 / Skill] 标题 … │ ─── 三条线 ────────── │
7
+ * │ #2 [高 / Skill] 标题 … │ 🩺 Doctor 7✓ 1⚠ │
8
+ * │ #3 [中 / 用例] 标题 … │ 🧪 Eval 80% │
9
+ * │ 单条点击 → modal │ 👁 Observe 稳定 │
10
+ * │ │ 阶段卡点击 → modal │
11
+ * └────────────────────────────────────────────────────────┘
12
+ * 隐藏 modal:每条 insight 一个 + 3 个阶段全量明细各一个
13
+ */
14
+ import { layout, e, DEFAULT_LANG } from './layout.js';
15
+ const BAND_DOT = {
16
+ green: '🟢', yellow: '🟡', red: '🔴', gray: '⚪',
17
+ };
18
+ // v6 之前的 insight × audience × 三视角 抽象在 v7 详情页砍掉了,只保留 sample 维度
19
+ // (renderEvalSection 直接读 evalReport.results,不再走 detectInsights / audience 分组)。
20
+ // 相关常量(SEVERITY_ICON / AUDIENCE_INFO_* / PATCH_TARGET_*)等以后做调试 UI
21
+ // 需要时再恢复。
22
+ function relTime(ts, lang) {
23
+ if (!ts)
24
+ return lang === 'zh' ? '未跑' : 'never';
25
+ try {
26
+ const past = new Date(ts).getTime();
27
+ const diff = Math.max(0, Date.now() - past);
28
+ const mins = Math.floor(diff / 60000);
29
+ if (mins < 60)
30
+ return lang === 'zh' ? `${mins} 分钟前` : `${mins}m ago`;
31
+ const hours = Math.floor(mins / 60);
32
+ if (hours < 24)
33
+ return lang === 'zh' ? `${hours} 小时前` : `${hours}h ago`;
34
+ return lang === 'zh' ? `${Math.floor(hours / 24)} 天前` : `${Math.floor(hours / 24)}d ago`;
35
+ }
36
+ catch {
37
+ return '';
38
+ }
39
+ }
40
+ function fmtDateShort(ts) {
41
+ if (!ts)
42
+ return '';
43
+ try {
44
+ const d = new Date(ts);
45
+ return `${String(d.getMonth() + 1).padStart(2, '0')}/${String(d.getDate()).padStart(2, '0')}`;
46
+ }
47
+ catch {
48
+ return '';
49
+ }
50
+ }
51
+ /** Underpowered observe (very few segments) must not paint a hard red/yellow band — the
52
+ * analyzer's confidence guard means the band is indicative only, so Studio treats it as
53
+ * a neutral (gray) signal with a caveat rather than a hard health verdict. */
54
+ function effectiveObserveBand(observe) {
55
+ if (!observe)
56
+ return 'gray';
57
+ return observe.confidence === 'underpowered' ? 'gray' : observe.healthBand;
58
+ }
59
+ export function assessHealth(entry, insights, lang) {
60
+ // underpowered observe 的色带仅供参考,不能算作一个「可信维度」:否则只有 observe、且段数过少时,
61
+ // 要么被 hasFail 硬标红,要么在去掉 band 惩罚后从 excellent 兜底翻成硬绿「健康」—— 两个方向都是
62
+ // 拿低 N 数据下硬结论。没有任何可信维度时,诚实口径是中性灰「未评估」,把判断权交回给 Diagnosis 信号。
63
+ const obsTrustworthy = entry.observe != null && entry.observe.confidence !== 'underpowered';
64
+ const ran = [entry.doctor, entry.eval, obsTrustworthy ? entry.observe : null].filter(Boolean).length;
65
+ // 没有任何可信维度时,如果 Diagnosis 已经给出 high/medium 信号(例如只跑了 `omk observe ingest`
66
+ // 拿到 `skill_md_not_found`),仍然要把卡片标红/黄,而不是落到灰色「未评估」。
67
+ // 否则 Diagnosis 作为 Studio 数据源的价值会被 UI 口径吞掉:红色筛选筛不到,
68
+ // 用户看不到「这个 skill 有待优化项,但卡片仍灰」的矛盾态。
69
+ const highCount = insights.filter((i) => i.severity === 'high').length;
70
+ const medCount = insights.filter((i) => i.severity === 'medium').length;
71
+ if (ran === 0) {
72
+ if (highCount > 0) {
73
+ return { grade: 'unhealthy', score: null, label: lang === 'zh' ? '不健康' : 'Unhealthy', emoji: '🔴', color: 'red' };
74
+ }
75
+ if (medCount > 0) {
76
+ return { grade: 'fair', score: null, label: lang === 'zh' ? '待改进' : 'Fair', emoji: '🟡', color: 'yellow' };
77
+ }
78
+ return { grade: 'unscored', score: null, label: lang === 'zh' ? '未评估' : 'Unscored', emoji: '⚪', color: 'gray' };
79
+ }
80
+ let doctorPct = null;
81
+ if (entry.doctor) {
82
+ const total = entry.doctor.passCount + entry.doctor.warnCount + entry.doctor.failCount;
83
+ doctorPct = total > 0
84
+ ? ((entry.doctor.passCount + entry.doctor.warnCount * 0.5) / total) * 100
85
+ : 100;
86
+ }
87
+ let evalPct = null;
88
+ if (entry.eval) {
89
+ if (entry.eval.compositeScore != null) {
90
+ evalPct = (entry.eval.compositeScore / 5) * 100;
91
+ }
92
+ else {
93
+ const total = entry.eval.passCount + entry.eval.failCount;
94
+ if (total > 0)
95
+ evalPct = (entry.eval.passCount / total) * 100;
96
+ }
97
+ }
98
+ let observePct = null;
99
+ if (entry.observe && obsTrustworthy) {
100
+ // underpowered observe 不进参考分:低 N 的 coverage / band 都仅供参考,平均进硬分会污染口径。
101
+ const coverage = (1 - entry.observe.gapRate) * 100;
102
+ const obsBand = effectiveObserveBand(entry.observe);
103
+ const bandMul = obsBand === 'red' ? 0.6 : obsBand === 'yellow' ? 0.85 : 1;
104
+ observePct = coverage * bandMul;
105
+ }
106
+ const dims = [doctorPct, evalPct, observePct].filter((x) => x != null);
107
+ const score = dims.length > 0 ? Math.round(dims.reduce((s, x) => s + x, 0) / dims.length) : null;
108
+ const hasFail = (entry.doctor != null && entry.doctor.failCount > 0)
109
+ || (entry.eval != null && entry.eval.failCount > 0)
110
+ || (effectiveObserveBand(entry.observe) === 'red');
111
+ const hasWarn = (entry.doctor != null && entry.doctor.warnCount > 0)
112
+ || (entry.eval != null && entry.eval.compositeScore != null && entry.eval.compositeScore < 3.5)
113
+ || (effectiveObserveBand(entry.observe) === 'yellow');
114
+ if (highCount > 0 || hasFail) {
115
+ return { grade: 'unhealthy', score, label: lang === 'zh' ? '不健康' : 'Unhealthy', emoji: '🔴', color: 'red' };
116
+ }
117
+ if (medCount > 0 || hasWarn) {
118
+ return { grade: 'fair', score, label: lang === 'zh' ? '待改进' : 'Fair', emoji: '🟡', color: 'yellow' };
119
+ }
120
+ if (insights.length === 0 && !hasWarn) {
121
+ return { grade: 'excellent', score, label: lang === 'zh' ? '健康' : 'Excellent', emoji: '🟢', color: 'green' };
122
+ }
123
+ return { grade: 'good', score, label: lang === 'zh' ? '良好' : 'Good', emoji: '🟢', color: 'green' };
124
+ }
125
+ // ────────── Hero:健康等级 + 名称 + 摘要 ──────────
126
+ function renderHero(entry, insights, lastTs, reportCount, lang) {
127
+ const h = assessHealth(entry, insights, lang);
128
+ const scoreTip = lang === 'zh'
129
+ ? '参考分:doctor 通过率、eval 综合分、observe 稳定度归一到 0-100 后取平均(warn/告警按 0.5 折算)。同一 skill 跨时间可比;不同 skill 之间因 sample 难度不同不严格可比'
130
+ : 'Reference score: average of doctor pass-rate, eval composite, and observe stability normalized to 0-100. Comparable within a skill over time; not strictly comparable across skills (sample difficulty differs)';
131
+ const scoreBlock = h.score != null
132
+ ? `<span class="si-hero-score" title="${e(scoreTip)}"><span class="si-hero-score-num">${h.score}</span><span class="si-hero-score-unit">/100</span></span>`
133
+ : `<span class="si-hero-score si-hero-score--empty" title="${e(scoreTip)}">—</span>`;
134
+ return `<div class="si-hero">
135
+ <div class="si-hero-grade si-hero-grade--${h.color}">
136
+ <span class="si-hero-grade-emoji">${h.emoji}</span>
137
+ <span class="si-hero-grade-label">${e(h.label)}</span>
138
+ ${scoreBlock}
139
+ </div>
140
+ <div class="si-hero-info">
141
+ <div class="si-hero-name">${e(entry.skillName)}</div>
142
+ <div class="si-hero-summary">${renderHealthSummary(entry, insights, lang)}</div>
143
+ </div>
144
+ <div class="si-hero-meta">${reportCount}/3 · ${relTime(lastTs, lang)}</div>
145
+ </div>`;
146
+ }
147
+ function renderHealthSummary(entry, insights, lang) {
148
+ const issues = [];
149
+ if (entry.doctor) {
150
+ if (entry.doctor.failCount > 0)
151
+ issues.push(lang === 'zh' ? `doctor ${entry.doctor.failCount} 项不通过` : `doctor ${entry.doctor.failCount} fail`);
152
+ else if (entry.doctor.warnCount > 0)
153
+ issues.push(lang === 'zh' ? `doctor ${entry.doctor.warnCount} 项告警` : `doctor ${entry.doctor.warnCount} warn`);
154
+ }
155
+ if (entry.eval) {
156
+ const total = entry.eval.passCount + entry.eval.failCount;
157
+ if (total > 0) {
158
+ const pct = Math.round((entry.eval.passCount / total) * 100);
159
+ if (entry.eval.failCount > 0)
160
+ issues.push(lang === 'zh' ? `eval 通过率 ${pct}%(${entry.eval.failCount} 条挂)` : `eval ${pct}% pass (${entry.eval.failCount} fail)`);
161
+ }
162
+ }
163
+ const obIssueBand = effectiveObserveBand(entry.observe);
164
+ if (entry.observe && obIssueBand !== 'green' && obIssueBand !== 'gray') {
165
+ issues.push(lang === 'zh' ? `observe ${BAND_DOT[obIssueBand]}` : `observe ${BAND_DOT[obIssueBand]}`);
166
+ }
167
+ if (entry.observe && entry.observe.confidence === 'underpowered') {
168
+ // 低 N observe 既不算「全绿」也不下硬结论,跟列表口径一致标注仅供参考,避免摘要谎报三视角全绿。
169
+ issues.push(lang === 'zh' ? 'observe 样本不足(仅供参考)' : 'observe low N (indicative)');
170
+ }
171
+ const high = insights.filter((i) => i.severity === 'high').length;
172
+ const med = insights.filter((i) => i.severity === 'medium').length;
173
+ if (high > 0 || med > 0) {
174
+ const parts = [];
175
+ if (high > 0)
176
+ parts.push(lang === 'zh' ? `${high} 个高优` : `${high} high`);
177
+ if (med > 0)
178
+ parts.push(lang === 'zh' ? `${med} 个中优` : `${med} medium`);
179
+ issues.push(lang === 'zh' ? `检出 ${insights.length} 个待优化(${parts.join(',')})` : `${insights.length} issue(s) (${parts.join(', ')})`);
180
+ }
181
+ if (issues.length === 0) {
182
+ const ran = [entry.doctor, entry.eval, entry.observe].filter(Boolean).length;
183
+ if (ran === 0)
184
+ return lang === 'zh' ? '尚未运行任何检查' : 'No checks run yet';
185
+ return lang === 'zh' ? '✅ 三视角全绿,无告警' : '✅ All three views green';
186
+ }
187
+ return issues.join(lang === 'zh' ? ',' : ', ');
188
+ }
189
+ function buildTrendData(entry) {
190
+ const dateMap = new Map();
191
+ const dateOf = (ts) => ts.slice(0, 10);
192
+ const get = (date) => {
193
+ if (!dateMap.has(date)) {
194
+ dateMap.set(date, { x: date, doctorPct: null, evalPct: null, observePct: null, doctorReportId: null, evalReportId: null, observeAnalysisId: null });
195
+ }
196
+ return dateMap.get(date);
197
+ };
198
+ for (const h of entry.doctorHistory) {
199
+ const total = h.passCount + h.warnCount + h.failCount;
200
+ const d = get(dateOf(h.timestamp));
201
+ d.doctorPct = total > 0 ? (h.passCount / total) * 100 : null;
202
+ d.doctorReportId = h.reportId;
203
+ }
204
+ for (const h of entry.evalHistory) {
205
+ const c = h.compositeScore;
206
+ const d = get(dateOf(h.timestamp));
207
+ d.evalPct = c != null ? (c / 5) * 100 : null;
208
+ d.evalReportId = h.reportId;
209
+ }
210
+ for (const h of entry.observeHistory) {
211
+ const d = get(dateOf(h.generatedAt));
212
+ d.observePct = (1 - h.gapRate) * 100;
213
+ d.observeAnalysisId = h.analysisId;
214
+ }
215
+ return Array.from(dateMap.values()).sort((a, b) => a.x.localeCompare(b.x));
216
+ }
217
+ function renderTrendChart(entry, langQ, lang) {
218
+ const data = buildTrendData(entry);
219
+ const labelDoctor = lang === 'zh' ? '🩺 健康度' : '🩺 Structure';
220
+ const labelEval = lang === 'zh' ? '🧪 评测结果' : '🧪 Test score';
221
+ const labelObserve = lang === 'zh' ? '👁 线上观测' : '👁 Live stability';
222
+ if (data.length < 2) {
223
+ return `<div class="si-trend-empty">${lang === 'zh' ? '📈 还没有足够的历史数据画趋势(至少 2 个时间点)' : '📈 Need at least 2 data points for trend'}</div>`;
224
+ }
225
+ const linksDoctor = data.map(() => null);
226
+ const linksEval = data.map((d) => d.evalReportId ? `/reports/${d.evalReportId}${langQ}` : null);
227
+ const linksObserve = data.map((d) => d.observeAnalysisId ? `/analyses/${d.observeAnalysisId}${langQ}` : null);
228
+ const explainDoctor = lang === 'zh' ? 'omk doctor 通过率' : 'omk doctor pass-rate';
229
+ const explainEval = lang === 'zh' ? 'omk eval 综合分(归一)' : 'omk eval composite (normalized)';
230
+ const explainObserve = lang === 'zh' ? 'omk observe 真实使用稳定度' : 'omk observe production stability';
231
+ const json = JSON.stringify({
232
+ labels: data.map((d) => fmtDateShort(d.x)),
233
+ datasets: [
234
+ { label: labelDoctor, data: data.map((d) => d.doctorPct), borderColor: '#5e8252', backgroundColor: 'rgba(94,130,82,.1)', tension: 0.3, spanGaps: true, _hint: explainDoctor },
235
+ { label: labelEval, data: data.map((d) => d.evalPct), borderColor: '#5a7a93', backgroundColor: 'rgba(90,122,147,.1)', tension: 0.3, spanGaps: true, _hint: explainEval },
236
+ { label: labelObserve, data: data.map((d) => d.observePct), borderColor: '#b08030', backgroundColor: 'rgba(176,128,48,.1)', tension: 0.3, spanGaps: true, _hint: explainObserve },
237
+ ],
238
+ });
239
+ const links = JSON.stringify([linksDoctor, linksEval, linksObserve]);
240
+ return `<div class="si-trend-canvas-wrap">
241
+ <canvas id="trend-chart" data-chart='${json.replace(/'/g, '&#39;')}' data-links='${links.replace(/'/g, '&#39;')}'></canvas>
242
+ </div>`;
243
+ }
244
+ /** 给一个 insight,从 stageRefs.evalSampleIds + evalReport 拿完整的失败样本详情。
245
+ * illustration 是 detector 挑出的(最多 2 条)代表性样本,带 prompt/output/工具调用;
246
+ * diagnostic.expected / actual 是诊断 LLM 写的"期望 vs 实际"对照,用户最想看的。 */
247
+ function renderSampleBody(s, lang) {
248
+ const block = (icon, label, text, cls = '') => {
249
+ if (!text || !text.trim())
250
+ return '';
251
+ return `<div class="si-sb-block si-sb-block--${cls}">
252
+ <div class="si-sb-label">${icon} ${e(label)}</div>
253
+ <div class="si-sb-text">${e(text)}</div>
254
+ </div>`;
255
+ };
256
+ // 拼 suggestion:skill / sample 两段都可能空,只显示有的。
257
+ // diagnostic LLM 偶尔会输出截断的垃圾(如单字"在"),用最小长度 8 字符过滤。
258
+ const isMeaningful = (text) => text.trim().length >= 8;
259
+ const sugParts = [];
260
+ if (isMeaningful(s.suggestionSkill)) {
261
+ sugParts.push(`<div class="si-sb-sugrow"><span class="si-sb-sugtag">改 SKILL.md</span><span>${e(s.suggestionSkill)}</span></div>`);
262
+ }
263
+ if (isMeaningful(s.suggestionSample)) {
264
+ sugParts.push(`<div class="si-sb-sugrow"><span class="si-sb-sugtag">改 sample</span><span>${e(s.suggestionSample)}</span></div>`);
265
+ }
266
+ const suggestionBlock = sugParts.length > 0
267
+ ? `<div class="si-sb-block si-sb-block--suggest">
268
+ <div class="si-sb-label">💡 ${lang === 'zh' ? '建议(针对这条样本)' : 'Suggestion (per-sample)'}</div>
269
+ <div class="si-sb-text">${sugParts.join('')}</div>
270
+ </div>`
271
+ : `<div class="si-sb-block si-sb-block--suggest si-sb-block--empty">
272
+ <div class="si-sb-label">💡 ${lang === 'zh' ? '建议(针对这条样本)' : 'Suggestion (per-sample)'}</div>
273
+ <div class="si-sb-text si-sb-empty">${lang === 'zh' ? '诊断 LLM 没给出针对这条样本的建议(可能输出截断或样本本身是诱错样本,无需改动)' : 'Diagnostic LLM did not return a per-sample suggestion'}</div>
274
+ </div>`;
275
+ return `<div class="si-sb">
276
+ ${block('📝', lang === 'zh' ? '用例 prompt' : 'Prompt', s.prompt, 'prompt')}
277
+ ${block('🎯', lang === 'zh' ? '期望' : 'Expected', s.expected, 'expected')}
278
+ ${block('⚠️', lang === 'zh' ? '实际' : 'Actual', s.actual, 'actual')}
279
+ ${suggestionBlock}
280
+ </div>`;
281
+ }
282
+ /** 失败用例 section v6:默认全折叠,每条 summary 完整展示一行;
283
+ * 点开看 prompt / 期望 / 实际 / per-sample 建议 */
284
+ // ────────── CSS ──────────
285
+ const SKILL_DETAIL_CSS = `
286
+ .si-back { display:inline-block;margin-bottom:8px;color:var(--text-muted);font-size:13px;text-decoration:none }
287
+ .si-back:hover { color:var(--text-primary) }
288
+
289
+ /* Hero — grade 卡 + 信息块,grid 布局让 grade 卡固定宽度 */
290
+ .si-hero { display:grid;grid-template-columns:auto 1fr auto;gap:18px;align-items:center;padding:14px 18px;background:var(--bg-surface);border-radius:8px;box-shadow:var(--shadow-sm);margin:8px 0 14px }
291
+ @media(max-width:640px){ .si-hero { grid-template-columns:auto 1fr;gap:12px } .si-hero-meta { grid-column:1/-1;text-align:right } }
292
+
293
+ /* 健康等级卡 — 左侧色卡,emoji + 等级 + 参考分纵向堆叠 */
294
+ .si-hero-grade { display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;min-width:96px;padding:10px 14px;border-radius:8px;background:var(--bg-soft);border-left:4px solid var(--border) }
295
+ .si-hero-grade--green { border-left-color:#5e8252;background:rgba(94,130,82,.08) }
296
+ .si-hero-grade--yellow { border-left-color:#b08030;background:rgba(176,128,48,.08) }
297
+ .si-hero-grade--red { border-left-color:#9c4a3f;background:rgba(156,74,63,.08) }
298
+ .si-hero-grade--gray { border-left-color:var(--border);background:var(--bg-soft) }
299
+ .si-hero-grade-emoji { font-size:20px;line-height:1 }
300
+ .si-hero-grade-label { font-size:13px;font-weight:600;color:var(--text-primary);letter-spacing:0.02em }
301
+ .si-hero-score { font-variant-numeric:tabular-nums;cursor:help;display:flex;align-items:baseline;gap:1px;margin-top:1px }
302
+ .si-hero-score-num { font-size:22px;font-weight:700;line-height:1 }
303
+ .si-hero-grade--green .si-hero-score-num { color:#5e8252 }
304
+ .si-hero-grade--yellow .si-hero-score-num { color:#b08030 }
305
+ .si-hero-grade--red .si-hero-score-num { color:#9c4a3f }
306
+ .si-hero-grade--gray .si-hero-score-num { color:var(--text-muted) }
307
+ .si-hero-score-unit { font-size:11px;color:var(--text-muted);font-weight:500 }
308
+ .si-hero-score--empty { font-size:18px;color:var(--text-muted) }
309
+
310
+ .si-hero-info { display:flex;flex-direction:column;gap:4px;min-width:0 }
311
+ .si-hero-name { font-size:20px;font-weight:600;color:var(--text-primary);line-height:1.3 }
312
+ .si-hero-summary { color:var(--text-secondary);font-size:13px;line-height:1.5 }
313
+ .si-hero-meta { color:var(--text-muted);font-size:12px;font-variant-numeric:tabular-nums;align-self:center }
314
+
315
+ /* 主网格:左 6/12 右 6/12,移动端单列 */
316
+ .si-grid { display:grid;grid-template-columns:1fr 1fr;gap:14px;align-items:start }
317
+ @media(max-width:880px){ .si-grid { grid-template-columns:1fr } }
318
+
319
+ /* 左栏:问题列表 */
320
+ .si-list { background:var(--bg-surface);border-radius:8px;padding:12px 14px;box-shadow:var(--shadow-sm) }
321
+
322
+ /* 空态 — 不喊"恭喜",用已有数据证明它健康 + 给可补充的下一步,有视觉重量 */
323
+ .si-empty { display:flex;flex-direction:column;gap:14px;padding:6px 4px }
324
+ .si-empty-h { display:flex;align-items:center;gap:10px;padding:10px 14px;background:rgba(94,130,82,.08);border-left:3px solid #5e8252;border-radius:6px }
325
+ .si-empty-emoji { font-size:22px;line-height:1 }
326
+ .si-empty-title { font-size:14px;font-weight:600;color:var(--text-primary) }
327
+ .si-empty-section-h { font-size:11.5px;font-weight:600;color:var(--text-muted);letter-spacing:0.04em;margin-bottom:6px;text-transform:uppercase }
328
+ .si-empty-list { margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:6px }
329
+ .si-empty-list li { display:grid;grid-template-columns:18px 1fr;gap:8px;align-items:start;font-size:13px;line-height:1.55;color:var(--text-primary) }
330
+ .si-empty-list code { background:var(--bg-soft);padding:1px 6px;border-radius:3px;font-family:"SF Mono",Menlo,monospace;font-size:11.5px;color:var(--text-primary) }
331
+ .si-empty-icon { font-weight:700;text-align:center }
332
+ .si-empty-list--pass .si-empty-icon { color:#5e8252 }
333
+ .si-empty-list--next .si-empty-icon { color:var(--accent) }
334
+ .si-aud { margin-bottom:12px }
335
+ .si-aud:last-child { margin-bottom:0 }
336
+ .si-aud-h { display:flex;align-items:center;gap:8px;padding:6px 8px;background:var(--bg-soft);border-radius:5px;margin-bottom:6px }
337
+ .si-aud-icon { font-size:14px }
338
+ .si-aud-title { font-size:13px;font-weight:600;color:var(--text-primary) }
339
+ .si-aud-count { padding:1px 7px;border-radius:9px;background:var(--bg-surface);font-size:11px;color:var(--text-secondary);font-weight:600 }
340
+ .si-aud-sub { color:var(--text-muted);font-size:11px;margin-left:auto }
341
+ .si-aud-rows { display:flex;flex-direction:column;gap:3px }
342
+
343
+ .si-row { all:unset;cursor:pointer;display:grid;grid-template-columns:auto auto 1fr auto auto;gap:8px;align-items:center;padding:8px 10px;border-radius:5px;border:1px solid transparent;transition:border-color .12s,background .12s;text-align:left }
344
+ .si-row:hover { border-color:var(--border-hover);background:var(--bg-soft) }
345
+ .si-row:focus-visible { outline:2px solid var(--accent);outline-offset:1px }
346
+ .si-row-num { font-size:11px;font-weight:700;color:var(--text-muted);font-variant-numeric:tabular-nums;background:var(--bg-soft);padding:1px 6px;border-radius:3px;min-width:28px;text-align:center }
347
+ .si-row-sev { font-size:10.5px;font-weight:700;padding:1px 7px;border-radius:8px;letter-spacing:0.02em }
348
+ .si-row-sev--high { background:rgba(156,74,63,.16);color:#9c4a3f }
349
+ .si-row-sev--medium { background:rgba(176,128,48,.14);color:#b08030 }
350
+ .si-row-sev--low { background:rgba(94,130,82,.16);color:#5e8252 }
351
+ .si-row-title { font-size:13.5px;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap }
352
+ .si-row-meta { font-size:11px;color:var(--text-muted);font-variant-numeric:tabular-nums }
353
+ .si-row-arrow { color:var(--text-muted);font-size:14px;font-weight:300 }
354
+ .si-row--high { border-left:3px solid #9c4a3f;padding-left:7px }
355
+
356
+ /* 右栏 */
357
+ .si-right { display:flex;flex-direction:column;gap:12px }
358
+ .si-trend { background:var(--bg-surface);border-radius:8px;padding:14px 16px;box-shadow:var(--shadow-sm) }
359
+ .si-trend-h { display:flex;align-items:center;gap:8px;font-size:13px;font-weight:600;color:var(--text-primary);margin-bottom:8px }
360
+ .si-trend-empty { padding:24px;text-align:center;color:var(--text-muted);font-size:13px;display:flex;align-items:center;justify-content:center;min-height:200px }
361
+ /* chart.js responsive 要求父容器有确定的高度,否则 canvas 会无限拉高(每次 resize 让父元素变大,触发新 resize)。
362
+ 用 position:relative + 固定 height,让 canvas 在内部以 absolute 填充。 */
363
+ .si-trend-canvas-wrap { position:relative;width:100%;height:200px }
364
+ .si-trend-canvas-wrap > canvas { position:absolute;left:0;top:0;width:100% !important;height:100% !important }
365
+ .si-trend-hint { font-size:10.5px;color:var(--text-muted);text-align:center;margin-top:6px;font-style:italic }
366
+ .si-trend-fallback { position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;background:var(--bg-soft);border-radius:6px;padding:14px;text-align:center }
367
+ .si-trend-fallback-icon { font-size:24px;line-height:1 }
368
+ .si-trend-fallback-msg { font-size:13px;font-weight:600;color:#9c4a3f }
369
+ .si-trend-fallback-hint { font-size:11px;color:var(--text-muted);max-width:80% }
370
+
371
+ /* 三视角当前状态区:跟趋势图区域并列,加标题让用户一眼知道这是"当前快照速览" */
372
+ .si-stages-block { background:var(--bg-surface);border-radius:8px;padding:12px 14px;box-shadow:var(--shadow-sm) }
373
+ .si-stages-h { display:flex;flex-direction:column;gap:1px;margin-bottom:10px }
374
+ .si-stages-title { font-size:13px;font-weight:600;color:var(--text-primary) }
375
+ .si-stages-sub { font-size:11px;color:var(--text-muted);font-style:italic }
376
+ .si-stagecards { display:flex;flex-direction:column;gap:8px }
377
+ .si-stages-block .si-stagecard { box-shadow:none;background:var(--bg-soft) }
378
+ .si-stages-block .si-stagecard:hover { box-shadow:var(--shadow-sm) }
379
+ .si-stagecard { all:unset;cursor:pointer;display:grid;grid-template-columns:32px 1fr auto auto;gap:10px;align-items:center;padding:10px 14px;background:var(--bg-surface);border-radius:7px;box-shadow:var(--shadow-sm);transition:transform .12s,box-shadow .12s;border-left:4px solid var(--border) }
380
+ .si-stagecard:hover { transform:translateX(2px);box-shadow:var(--shadow-md) }
381
+ .si-stagecard:focus-visible { outline:2px solid var(--accent);outline-offset:1px }
382
+ .si-stagecard--green { border-left-color:#5e8252 }
383
+ .si-stagecard--yellow { border-left-color:#b08030 }
384
+ .si-stagecard--red { border-left-color:#9c4a3f }
385
+ .si-stagecard--gray { border-left-color:var(--border) }
386
+ .si-stagecard-icon { font-size:22px;line-height:1 }
387
+ .si-stagecard-body { display:flex;flex-direction:column;gap:2px }
388
+ .si-stagecard-name { font-size:14px;font-weight:600;color:var(--text-primary) }
389
+ .si-stagecard-status { font-size:12px;color:var(--text-secondary);font-variant-numeric:tabular-nums }
390
+ .si-stagecard-meta { font-size:11px;color:var(--text-muted);font-variant-numeric:tabular-nums }
391
+ .si-stagecard-arrow { color:var(--text-muted);font-size:16px;font-weight:300 }
392
+
393
+ /* ── Insight modal v4:极简 — 只展示问题 + 解决 ──────────
394
+ * 顺序:title + desc(问题) → 失败用例(具体哪些用例 + 错因) → 怎么改(建议 + patch)
395
+ * 删:严重度 tag / audience tag / 影响数 / 主推动作卡 / 三视角折叠
396
+ * 第一条 recommendation 加 ⭐ 推荐标记
397
+ */
398
+
399
+ /* 失败用例 section(sample 视角主信息)*/
400
+ .si-failures { margin:14px 0;padding:12px 14px;background:var(--bg-soft);border-radius:6px }
401
+ .si-failures-h { font-size:13px;font-weight:600;color:var(--text-primary);margin-bottom:10px }
402
+ .si-failure-item { background:rgba(156,74,63,.04);border-radius:5px;margin-bottom:8px;border-left:3px solid #9c4a3f }
403
+ .si-failure-item:last-child { margin-bottom:0 }
404
+ /* 两行布局:第一行 id + tags + 右对齐 trace;第二行 summary 独占 */
405
+ .si-failure-head { display:flex;flex-direction:column;gap:6px;padding:10px 12px;cursor:default }
406
+ details.si-failure-item > summary.si-failure-head { cursor:pointer;list-style:none;user-select:none }
407
+ details.si-failure-item > summary.si-failure-head::-webkit-details-marker { display:none }
408
+ .si-failure-row1 { display:flex;align-items:center;gap:8px;flex-wrap:wrap }
409
+ .si-failure-row1::before { content:'▸ ';color:var(--text-muted);font-size:11px;margin-right:-4px }
410
+ details.si-failure-item[open] > summary > .si-failure-row1::before { content:'▾ ' }
411
+ .si-failure-row2 { font-size:14px;color:var(--text-secondary);line-height:1.55;padding-left:16px;white-space:pre-wrap;word-break:break-word }
412
+ .si-failure-spacer { flex:1 }
413
+ .si-failure-id { font-size:12.5px;font-weight:600;color:#9c4a3f;background:var(--bg-soft);padding:2px 8px;border-radius:3px;font-family:"SF Mono",Menlo,monospace }
414
+ .si-failure-modes { display:flex;gap:4px;flex-wrap:wrap }
415
+ .si-failure-mode { font-size:12px;color:#b08030;background:rgba(176,128,48,.14);padding:2px 8px;border-radius:8px;font-weight:500;white-space:nowrap }
416
+ .si-failure-trace { font-size:12px;color:var(--accent);text-decoration:none;font-weight:500;white-space:nowrap }
417
+ .si-failure-trace:hover { text-decoration:underline }
418
+
419
+ /* 通过 / 诱错 sample 紧凑行 */
420
+ .si-pass-item { display:flex;gap:10px;align-items:center;padding:5px 8px;border-radius:4px;font-size:14px;line-height:1.5 }
421
+ .si-pass-item:hover { background:var(--bg-soft) }
422
+ .si-pass-card { background:var(--bg-surface);border-radius:5px;margin-bottom:6px;border-left:3px solid #5e8252 }
423
+ .si-pass-card > summary { list-style:none;cursor:pointer;user-select:none }
424
+ .si-pass-card > summary::-webkit-details-marker { display:none }
425
+ .si-pass-head { display:flex;flex-direction:column;gap:4px;padding:8px 12px }
426
+ .si-pass-row1 { display:flex;align-items:center;gap:8px;flex-wrap:wrap }
427
+ .si-pass-row1::before { content:'▸ ';color:var(--text-muted);font-size:11px;margin-right:-4px }
428
+ details.si-pass-card[open] > summary > .si-pass-row1::before { content:'▾ ' }
429
+ .si-pass-id { font-size:12px;font-weight:600;color:#5e8252;background:var(--bg-soft);padding:2px 8px;border-radius:3px;font-family:"SF Mono",Menlo,monospace;flex-shrink:0 }
430
+ .si-pass-score { font-size:12px;font-weight:600;color:#5e8252;background:rgba(94,130,82,.1);padding:1px 7px;border-radius:10px }
431
+ .si-pass-prompt-preview { font-size:13px;color:var(--text-secondary);padding-left:16px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis }
432
+ .si-pass-body { padding:0 12px 10px 28px;display:flex;flex-direction:column;gap:8px }
433
+ .si-pass-section { }
434
+ .si-pass-label { font-size:12px;font-weight:600;color:var(--text-muted);margin-bottom:4px }
435
+ .si-pass-content { font-size:14px;color:var(--text-primary);line-height:1.6;white-space:pre-wrap;word-break:break-word;background:var(--bg-soft);padding:8px 12px;border-radius:4px }
436
+ .si-sample-dot { font-size:10px;line-height:1;flex-shrink:0 }
437
+ .se-scores { margin-bottom:12px;padding:12px 14px;background:var(--bg-soft);border-radius:8px }
438
+ .se-scores-hero { display:flex;align-items:baseline;gap:8px;margin-bottom:10px }
439
+ .se-hero-label { font-size:14px;font-weight:600;color:var(--text-primary) }
440
+ .se-hero-val { font-size:28px;font-weight:700;color:var(--text-primary);line-height:1 }
441
+ .se-hero-max { font-size:14px;font-weight:400;color:var(--text-muted) }
442
+ .se-hero-link { font-size:12px;color:var(--accent);text-decoration:none;font-weight:500;margin-left:auto }
443
+ .se-hero-link:hover { text-decoration:underline }
444
+ .se-scores-grid { display:grid;grid-template-columns:repeat(3,1fr);gap:8px }
445
+ @media(max-width:600px) { .se-scores-grid { grid-template-columns:repeat(2,1fr) } }
446
+ .se-score-card { padding:8px 10px;background:var(--bg-surface);border-radius:6px }
447
+ .se-score-label { font-size:12px;color:var(--text-muted);margin-bottom:4px }
448
+ .se-score-bar { height:4px;background:var(--border);border-radius:2px;overflow:hidden;margin-bottom:4px }
449
+ .se-score-fill { height:100%;border-radius:2px }
450
+ .se-score-fill--good { background:#5e8252 }
451
+ .se-score-fill--mid { background:#b08030 }
452
+ .se-score-fill--low { background:#9c4a3f }
453
+ .se-score-val { font-size:16px;font-weight:600;color:var(--text-primary) }
454
+ .se-score-max { font-size:12px;font-weight:400;color:var(--text-muted) }
455
+ .si-pass-preview { flex:1;color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0 }
456
+ .si-failure-trace:hover { text-decoration:underline }
457
+ .si-failure-detail { padding:0 12px 10px;border-top:1px solid var(--border) }
458
+ .si-failure-detail .si-illustration { border-left:none;background:transparent;padding:8px 0 0 0 }
459
+ .si-failure-no-detail { padding:6px 0;font-size:13px;color:var(--text-muted);font-style:italic }
460
+
461
+ /* v7:顶部全景区 — 左 3 个 donut ring + 右趋势图,两栏同高 */
462
+ .si-overview { display:grid;grid-template-columns:3fr 2fr;gap:18px;margin:10px 0 22px;align-items:stretch }
463
+ @media(max-width:880px){ .si-overview { grid-template-columns:1fr } }
464
+ .si-overview-cards { background:var(--bg-surface);border-radius:10px;padding:18px 14px;box-shadow:var(--shadow-sm);display:flex;align-items:center;justify-content:space-around;gap:8px }
465
+ .si-overview-trend { background:var(--bg-surface);border-radius:10px;padding:14px 16px;box-shadow:var(--shadow-sm);display:flex;flex-direction:column }
466
+
467
+ /* 三视角 ring + label(锚定到下面对应 section);内容自身居中,被 cards 容器垂直拉伸时上下留白对称 */
468
+ .si-vs { flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:8px;padding:8px 4px;text-decoration:none;color:var(--text-primary);border-radius:8px;transition:background .15s }
469
+ .si-vs:hover { background:var(--bg-soft);text-decoration:none }
470
+ .si-ring { display:block }
471
+ .si-vs-h { display:flex;align-items:baseline;gap:4px;flex-wrap:wrap;justify-content:center;margin-top:4px }
472
+ .si-vs-icon { font-size:15px;line-height:1 }
473
+ .si-vs-label { font-size:13.5px;font-weight:600;color:var(--text-primary) }
474
+ .si-vs-sublabel { font-size:11px;color:var(--text-muted) }
475
+ .si-vs-stat { font-size:12.5px;color:var(--text-secondary);font-variant-numeric:tabular-nums;line-height:1.45 }
476
+ .si-vs-spark { display:block;margin-top:2px }
477
+ @media(max-width:560px){
478
+ .si-overview-cards { flex-direction:column;align-items:stretch }
479
+ .si-vs { flex-direction:row;justify-content:flex-start;text-align:left;gap:14px;align-items:center }
480
+ .si-vs-h, .si-vs-stat, .si-vs-spark { margin:0 }
481
+ }
482
+
483
+ /* 三视角 section(下方主体) */
484
+ .si-sect { background:var(--bg-surface);border-radius:8px;padding:14px 18px;box-shadow:var(--shadow-sm);margin-bottom:14px;border-left:4px solid var(--border);scroll-margin-top:16px }
485
+ .si-sect--green { border-left-color:#5e8252 }
486
+ .si-sect--yellow { border-left-color:#b08030 }
487
+ .si-sect--red { border-left-color:#9c4a3f }
488
+ .si-sect--gray { border-left-color:var(--border) }
489
+ .si-sect-h { display:flex;justify-content:space-between;align-items:baseline;gap:12px;margin-bottom:10px;flex-wrap:wrap }
490
+ .si-sect-title { font-size:15px;font-weight:600;color:var(--text-primary) }
491
+ .si-sect-meta { font-size:11.5px;color:var(--text-muted);font-variant-numeric:tabular-nums }
492
+ .si-sect-body { display:flex;flex-direction:column;gap:6px }
493
+ .si-sect-empty { font-size:13px;color:var(--text-muted);font-style:italic;padding:8px 0 }
494
+ .si-sect-line { font-size:14px;color:var(--text-secondary);margin-bottom:4px }
495
+ .si-sect-allpass { font-size:14px;color:#5e8252;padding:6px 10px;background:rgba(94,130,82,.07);border-radius:4px }
496
+ .si-sect-link { display:inline-block;margin-top:8px;font-size:12px;color:var(--accent);text-decoration:none;font-weight:500 }
497
+ .si-sect-link:hover { text-decoration:underline }
498
+ .si-sect-fold { margin-top:8px;border-top:1px dashed var(--border);padding-top:6px }
499
+ .si-sect-fold > summary { cursor:pointer;font-size:11.5px;color:var(--text-muted);user-select:none;list-style:none;padding:4px 0 }
500
+ .si-sect-fold > summary::-webkit-details-marker { display:none }
501
+ .si-sect-fold > summary:hover { color:var(--text-secondary) }
502
+ .si-sect-fold-body { padding-top:6px;display:flex;flex-direction:column;gap:5px }
503
+ .si-sect-skipped { font-size:11px;color:var(--text-muted);font-style:italic;margin-top:6px }
504
+
505
+ /* doctor 规则展示(用在 doctor section 和 observe section) */
506
+ .sd-grid { display:flex;flex-direction:column;gap:4px }
507
+ .sd-dim { border-radius:6px;border:1px solid var(--border);overflow:hidden }
508
+ .sd-dim--err { border-color:rgba(156,74,63,.3) }
509
+ .sd-dim--warn { border-color:rgba(176,128,48,.3) }
510
+ .sd-dim--pass { border-color:rgba(94,130,82,.25);background:rgba(94,130,82,.04) }
511
+ .sd-dim--skip { border-color:var(--border);opacity:.6 }
512
+ .sd-dim > summary { list-style:none;cursor:pointer }
513
+ .sd-dim > summary::-webkit-details-marker { display:none }
514
+ .sd-dim-header { display:flex;align-items:center;gap:8px;padding:8px 12px;font-size:14px }
515
+ .sd-dim-dot { flex-shrink:0;font-size:10px;line-height:1 }
516
+ .sd-dim-name { font-weight:600;color:var(--text-primary);flex:1;min-width:0 }
517
+ .sd-dim-badges { display:flex;gap:6px;flex-shrink:0 }
518
+ .sd-badge { font-size:12px;padding:1px 7px;border-radius:10px;font-weight:500 }
519
+ .sd-badge--err { background:rgba(156,74,63,.1);color:#9c4a3f }
520
+ .sd-badge--warn { background:rgba(176,128,48,.1);color:#b08030 }
521
+ .sd-dim-body { padding:0 12px 10px;display:flex;flex-direction:column;gap:6px }
522
+ .sd-item { padding:8px 10px;border-radius:4px;font-size:14px;line-height:1.6 }
523
+ .sd-item--err { background:rgba(156,74,63,.05);border-left:2px solid #9c4a3f }
524
+ .sd-item--warn { background:rgba(176,128,48,.05);border-left:2px solid #b08030 }
525
+ .sd-item-desc { color:var(--text-primary);word-break:break-word }
526
+ .sd-item-sug { margin-top:4px;font-size:13px;color:var(--text-secondary);padding:4px 8px;background:rgba(94,130,82,.05);border-radius:4px;word-break:break-word }
527
+ .sd-warn-fold { margin-top:6px }
528
+ .sd-warn-list { display:flex;flex-direction:column;gap:6px;margin-top:6px }
529
+ .sd-warn-toggle { cursor:pointer;font-size:13px;color:var(--text-muted);user-select:none;list-style:none;padding:2px 0 }
530
+ .sd-warn-toggle::-webkit-details-marker { display:none }
531
+ .sd-warn-toggle::before { content:'▸ ';font-size:10px }
532
+ details[open] > .sd-warn-toggle::before { content:'▾ ' }
533
+ .sd-warn-toggle:hover { color:var(--text-secondary) }
534
+ .sd-pass-fold { margin-top:6px }
535
+ .sd-pass-fold > .sd-dim + .sd-dim { margin-top:4px }
536
+ .sd-pass-toggle { cursor:pointer;font-size:13px;color:var(--text-muted);user-select:none;list-style:none;padding:6px 0 }
537
+ .sd-pass-toggle::-webkit-details-marker { display:none }
538
+ .sd-pass-toggle:hover { color:var(--text-secondary) }
539
+ .si-rule-hint { margin-top:4px;font-size:12px;color:var(--text-secondary);line-height:1.55 }
540
+
541
+ /* 单条 sample 展开后的 4 段(modal v6:用例 prompt / 期望 / 实际 / 建议)*/
542
+ .si-sb { display:flex;flex-direction:column;gap:10px;padding:10px 0 }
543
+ .si-sb-block { padding:10px 12px;border-radius:5px;background:var(--bg-soft) }
544
+ .si-sb-block--prompt { background:var(--bg-soft) }
545
+ .si-sb-block--expected { background:rgba(94,130,82,.06) }
546
+ .si-sb-block--actual { background:rgba(176,128,48,.07) }
547
+ .si-sb-block--suggest { background:rgba(122,107,137,.07) }
548
+ .si-sb-label { font-size:12px;font-weight:700;color:var(--text-secondary);letter-spacing:0.02em;margin-bottom:5px }
549
+ .si-sb-block--expected .si-sb-label { color:#5e8252 }
550
+ .si-sb-block--actual .si-sb-label { color:#b08030 }
551
+ .si-sb-block--suggest .si-sb-label { color:#7a6b89 }
552
+ .si-sb-text { font-size:13px;color:var(--text-primary);line-height:1.6;white-space:pre-wrap;word-break:break-word }
553
+ .si-sb-block--prompt .si-sb-text { font-family:"SF Mono",Menlo,monospace;font-size:12.5px;max-height:200px;overflow-y:auto }
554
+ .si-sb-sugrow { display:grid;grid-template-columns:90px 1fr;gap:8px;padding:4px 0;align-items:start }
555
+ .si-sb-sugrow:not(:first-child) { border-top:1px dashed var(--border) }
556
+ .si-sb-sugtag { font-size:11px;color:#7a6b89;background:var(--bg-surface);padding:2px 8px;border-radius:8px;font-weight:600;width:fit-content;height:fit-content }
557
+ .si-sb-block--empty { opacity:.75 }
558
+ .si-sb-empty { color:var(--text-muted);font-style:italic;font-size:12.5px }
559
+
560
+ /* 单条 sample 的"期望 vs 实际 vs 卡在哪"diff 对照视图(已被 v6 sb 视图替代,保留 placeholder)*/
561
+ .si-diff { display:flex;flex-direction:column;gap:8px;padding:10px 0 }
562
+ .si-diff-row { display:grid;grid-template-columns:24px 50px 1fr;gap:10px;align-items:start;padding:8px 12px;border-radius:5px;line-height:1.55 }
563
+ .si-diff-row--expected { background:rgba(94,130,82,.07);border-left:3px solid #5e8252 }
564
+ .si-diff-row--actual { background:rgba(176,128,48,.08);border-left:3px solid #b08030 }
565
+ .si-diff-row--failed { background:rgba(156,74,63,.07);border-left:3px solid #9c4a3f }
566
+ .si-diff-icon { font-size:14px;line-height:1.5 }
567
+ .si-diff-label { font-size:11.5px;font-weight:700;letter-spacing:0.04em;color:var(--text-secondary);padding-top:2px }
568
+ .si-diff-row--expected .si-diff-label { color:#5e8252 }
569
+ .si-diff-row--actual .si-diff-label { color:#b08030 }
570
+ .si-diff-row--failed .si-diff-label { color:#9c4a3f }
571
+ .si-diff-text { color:var(--text-primary);font-size:13px;word-break:break-word }
572
+ .si-diff-text--mono { font-family:"SF Mono",Menlo,monospace;font-size:12px;background:var(--bg-surface);padding:2px 7px;border-radius:3px;width:fit-content }
573
+ /* 原始 prompt/output 降级到二级折叠 */
574
+ .si-diff-raw { margin-top:6px;border-top:1px dashed var(--border);padding-top:8px }
575
+ .si-diff-raw > summary { cursor:pointer;font-size:11.5px;color:var(--text-muted);user-select:none;list-style:none }
576
+ .si-diff-raw > summary::-webkit-details-marker { display:none }
577
+ .si-diff-raw > summary:hover { color:var(--text-secondary) }
578
+ .si-diff-raw-body { padding:6px 0 }
579
+
580
+ /* 占位符标识 */
581
+ .si-placeholder { background:rgba(176,128,48,.20);color:#7a5810;padding:1px 4px;border-radius:3px;font-weight:600;font-style:italic }
582
+ .si-rec-patch-hint { font-size:11.5px;color:#7a5810;background:rgba(176,128,48,.10);padding:6px 10px;border-radius:4px;margin-bottom:6px;line-height:1.5 }
583
+ .si-rec-patch-hint .si-placeholder { background:rgba(176,128,48,.30) }
584
+
585
+ /* 第一条建议的"⭐ 推荐先做"标记 */
586
+ .si-rec-item--primary { border-left-color:#5e8252;background:rgba(94,130,82,.06) }
587
+ .si-rec-star { font-size:10.5px;font-weight:700;color:#5e8252;background:rgba(94,130,82,.16);padding:2px 8px;border-radius:9px;letter-spacing:0.02em;flex-shrink:0 }
588
+
589
+ /* 建议 + patch 直接铺(去掉 details 折叠)*/
590
+ .si-recs { margin:14px 0 }
591
+ .si-recs-h { font-size:13px;font-weight:600;color:var(--text-primary);margin-bottom:10px }
592
+ .si-rec-item { background:var(--bg-soft);border-radius:6px;padding:10px 12px;margin-bottom:8px;border-left:3px solid var(--accent) }
593
+ .si-rec-item:last-child { margin-bottom:0 }
594
+ .si-rec-head { display:flex;align-items:flex-start;gap:8px;margin-bottom:8px }
595
+ .si-rec-num { font-size:11px;font-weight:700;color:var(--text-muted);background:var(--bg-surface);padding:1px 7px;border-radius:9px;flex-shrink:0;margin-top:1px;font-variant-numeric:tabular-nums }
596
+ .si-rec-pri { padding:1px 7px;border-radius:8px;font-size:10.5px;font-weight:600;flex-shrink:0;margin-top:1px }
597
+ .si-rec-pri--high { background:rgba(156,74,63,.14);color:#9c4a3f }
598
+ .si-rec-pri--medium { background:rgba(176,128,48,.12);color:#b08030 }
599
+ .si-rec-pri--low { background:rgba(94,130,82,.14);color:#5e8252 }
600
+ .si-rec-action { flex:1;color:var(--text-primary);font-size:13px;line-height:1.55 }
601
+ .si-rec-patch { margin-left:0 }
602
+ .si-rec-patch-meta { display:flex;gap:8px;align-items:center;font-size:11px;color:var(--text-muted);margin-bottom:5px;flex-wrap:wrap }
603
+ .si-rec-patch-target { font-weight:600;color:var(--text-secondary) }
604
+ .si-rec-patch-loc { font-family:"SF Mono",Menlo,monospace;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap }
605
+ .si-rec-patch-copy { background:var(--accent);color:#fff;border:none;border-radius:4px;padding:3px 10px;font-size:11px;cursor:pointer;font-weight:500;transition:background .1s;flex-shrink:0 }
606
+ .si-rec-patch-copy:hover { background:var(--accent-hover) }
607
+ .si-rec-patch-copy.copied { background:#5e8252 }
608
+ .si-rec-patch-snippet { background:var(--bg-surface);padding:10px 12px;border-radius:4px;border-left:2px solid var(--accent);font-size:11.5px;line-height:1.55;overflow-x:auto;margin:0 }
609
+ .si-rec-patch-snippet code { font-family:"SF Mono",Menlo,monospace;color:var(--text-primary);white-space:pre;display:block }
610
+
611
+ /* 三视角细节折叠(底部)*/
612
+ .si-modal-detail { margin-top:14px;border-top:1px solid var(--border);padding-top:10px }
613
+ .si-modal-detail > summary { cursor:pointer;font-size:12px;font-weight:600;color:var(--text-secondary);user-select:none;list-style:none;padding:4px 0 }
614
+ .si-modal-detail > summary::-webkit-details-marker { display:none }
615
+ .si-modal-detail > summary:hover { color:var(--text-primary) }
616
+ .si-modal-detail-body { margin-top:8px;padding:8px 10px;background:var(--bg-soft);border-radius:5px }
617
+
618
+ /* Modal 内的样式(沿用 modal-overlay/modal-content,只补本页特有的)*/
619
+ .si-modal { max-width:760px;width:90% }
620
+ .si-modal-h { display:flex;align-items:center;gap:10px;flex-wrap:wrap }
621
+ .si-modal-num { font-size:12px;font-weight:700;color:var(--text-muted);background:var(--bg-soft);padding:2px 8px;border-radius:4px }
622
+ .si-modal-sev { font-size:18px }
623
+ .si-modal-title { margin:0;font-size:17px;font-weight:600;color:var(--text-primary) }
624
+ /* si-modal-tags / si-modal-affect / si-aud-tag — modal v4 极简后不再使用,保留 placeholder 防回退 */
625
+ .si-modal-desc { color:var(--text-secondary);font-size:13px;line-height:1.6;margin:0 0 14px }
626
+ .si-modal-purpose { color:var(--text-secondary);font-size:13px;line-height:1.6;margin:6px 0 12px;font-style:italic }
627
+ .si-modal-stats { color:var(--text-secondary);font-size:13px;margin-bottom:14px;padding:8px 12px;background:var(--bg-soft);border-radius:5px;font-variant-numeric:tabular-nums }
628
+ .si-modal-empty { color:var(--text-muted);font-size:13px;padding:18px;text-align:center;font-style:italic }
629
+
630
+ .si-sev-tag { padding:2px 9px;border-radius:11px;font-size:11px;font-weight:600 }
631
+ .si-sev-tag--high { background:rgba(156,74,63,.14);color:#9c4a3f }
632
+ .si-sev-tag--medium { background:rgba(176,128,48,.12);color:#b08030 }
633
+ .si-sev-tag--low { background:rgba(94,130,82,.14);color:#5e8252 }
634
+
635
+ /* 证据 */
636
+ .si-evidence { background:var(--bg-soft);padding:10px 12px;border-radius:6px;margin-bottom:12px }
637
+ .si-evidence-h { font-size:12px;font-weight:600;color:var(--text-secondary);margin-bottom:8px }
638
+ .si-ev { padding:4px 0;font-size:13px;line-height:1.55 }
639
+ .si-ev-line { display:grid;grid-template-columns:24px 100px 1fr;gap:10px;align-items:start }
640
+ .si-ev-icon { text-align:center;font-weight:600 }
641
+ .si-ev--flagged .si-ev-icon { color:#9c4a3f }
642
+ .si-ev--blind .si-ev-icon { color:#7a6b89 }
643
+ .si-ev--silent .si-ev-icon { color:#7a9270 }
644
+ .si-ev--na .si-ev-icon { color:var(--text-muted) }
645
+ .si-ev-perspective { color:var(--text-secondary);font-weight:500 }
646
+ .si-ev-msg { color:var(--text-primary) }
647
+ .si-ev-ill { margin-top:4px;margin-left:34px }
648
+ .si-ev-ill > summary { cursor:pointer;font-size:11.5px;color:var(--accent);list-style:none;padding:2px 0 }
649
+ .si-ev-ill > summary::-webkit-details-marker { display:none }
650
+ .si-ev-ill > summary::before { content:'▸ ';color:var(--text-muted) }
651
+ .si-ev-ill[open] > summary::before { content:'▾ ' }
652
+ .si-ev-ill-body { padding:6px 0;display:flex;flex-direction:column;gap:8px }
653
+ .si-illustration { background:var(--bg-surface);border-left:2px solid var(--border);padding:6px 10px;border-radius:4px;font-size:11.5px }
654
+ .si-ill-h { margin-bottom:4px }
655
+ .si-ill-h code { background:var(--bg-soft);padding:1px 5px;border-radius:3px;font-size:11px }
656
+ .si-ill-row { display:grid;grid-template-columns:80px 1fr;gap:8px;align-items:start;margin-bottom:3px }
657
+ .si-ill-label { color:var(--text-muted);font-size:10.5px;font-weight:500 }
658
+ .si-ill-text { color:var(--text-primary);font-size:11.5px;background:var(--bg-soft);padding:3px 6px;border-radius:3px;white-space:pre-wrap;word-break:break-word }
659
+ .si-ill-text--mono { font-family:"SF Mono",Menlo,monospace;background:rgba(156,74,63,.10);color:#9c4a3f }
660
+ .si-ill-tools { margin:0;padding-left:0;list-style:none;display:flex;flex-direction:column;gap:2px }
661
+ .si-ill-tools li { font-family:"SF Mono",Menlo,monospace;font-size:10.5px;background:var(--bg-soft);padding:2px 5px;border-radius:3px }
662
+
663
+ /* 推荐 */
664
+ .si-recs ul { margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:10px }
665
+ .si-recs li { font-size:13px;line-height:1.55 }
666
+ .si-rec-line { display:flex;gap:8px;align-items:flex-start }
667
+ .si-rec-pri { padding:1px 7px;border-radius:8px;font-size:10.5px;font-weight:600;flex-shrink:0;margin-top:1px }
668
+ .si-rec-pri--high { background:rgba(156,74,63,.14);color:#9c4a3f }
669
+ .si-rec-pri--medium { background:rgba(176,128,48,.12);color:#b08030 }
670
+ .si-rec-pri--low { background:rgba(94,130,82,.14);color:#5e8252 }
671
+ .si-rec-action { color:var(--text-primary);flex:1 }
672
+ .si-recs-h { font-size:12px;font-weight:600;color:var(--text-secondary);margin-bottom:8px;margin-top:0 }
673
+ .si-patch { margin-top:6px;margin-left:24px }
674
+ .si-patch > summary { cursor:pointer;font-size:11.5px;color:var(--accent);list-style:none;padding:2px 0 }
675
+ .si-patch > summary::-webkit-details-marker { display:none }
676
+ .si-patch > summary::before { content:'▸ ';color:var(--text-muted) }
677
+ .si-patch[open] > summary::before { content:'▾ ' }
678
+ .si-patch-body { padding:6px 0 }
679
+ .si-patch-meta { display:flex;gap:8px;margin-bottom:6px;font-size:11px;color:var(--text-muted);align-items:center }
680
+ .si-patch-target { font-weight:600;color:var(--text-secondary) }
681
+ .si-patch-loc { font-family:"SF Mono",Menlo,monospace }
682
+ .si-patch-snippet { background:var(--bg-soft);padding:10px 12px;border-radius:4px;border-left:2px solid var(--accent);font-size:11.5px;line-height:1.55;overflow-x:auto;margin:0 }
683
+ .si-patch-snippet code { font-family:"SF Mono",Menlo,monospace;color:var(--text-primary);white-space:pre;display:block }
684
+
685
+ /* Modal 内的 doctor rule list */
686
+ .si-rules { list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:4px }
687
+ .si-rule { display:flex;gap:10px;font-size:13px;line-height:1.55;align-items:flex-start;padding:8px 10px;border-radius:4px }
688
+ .si-rule--warn { background:rgba(176,128,48,.07) }
689
+ .si-rule--fail { background:rgba(156,74,63,.08) }
690
+ .si-rule-icon { flex-shrink:0;font-weight:700;width:16px;text-align:center;font-size:14px }
691
+ .si-rule--pass .si-rule-icon { color:#5e8252 }
692
+ .si-rule--warn .si-rule-icon { color:#b08030 }
693
+ .si-rule--fail .si-rule-icon { color:#9c4a3f }
694
+ .si-rule-body { flex:1;min-width:0 }
695
+ .si-rule-id { font-size:11px;color:var(--text-muted);background:var(--bg-soft);padding:1px 5px;border-radius:3px;margin-right:6px }
696
+ .si-rule-msg { color:var(--text-primary) }
697
+ .si-rule-hint { font-size:12px;color:var(--text-secondary);margin-top:3px;line-height:1.55 }
698
+
699
+ /* Sample list (eval modal — 全部用例清单)。复用 si-history-row 大部分样式,只重写 grid */
700
+ .si-sample-list { max-height:340px;overflow-y:auto }
701
+ .si-sample-row { grid-template-columns:18px 100px 56px 1fr auto !important;gap:8px !important }
702
+ .si-sample-row--pass { background:rgba(94,130,82,.06) }
703
+ .si-sample-row--fail { background:rgba(156,74,63,.06);border-left:2px solid #9c4a3f }
704
+ .si-sample-row--tripwire { background:rgba(122,107,137,.06);border-left:2px solid #7a6b89 }
705
+ .si-sample-icon { font-weight:700;text-align:center;font-size:13px }
706
+ .si-sample-icon--pass { color:#5e8252 }
707
+ .si-sample-icon--fail { color:#9c4a3f }
708
+ .si-sample-icon--tripwire { color:#7a6b89 }
709
+ .si-sample-id { font-size:11px;color:var(--text-secondary);background:transparent;padding:0;font-family:"SF Mono",Menlo,monospace;font-weight:600 }
710
+ .si-sample-score { font-variant-numeric:tabular-nums;font-size:12px;color:var(--text-secondary);font-weight:600;text-align:right }
711
+ .si-sample-desc { color:var(--text-secondary);font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0 }
712
+ @media(max-width:640px){
713
+ .si-sample-row { grid-template-columns:18px 1fr auto !important }
714
+ .si-sample-id { grid-column:2/3 }
715
+ .si-sample-score, .si-sample-desc { display:none }
716
+ }
717
+
718
+ /* History section in stage modals */
719
+ .si-history { margin-top:14px;border-top:1px solid var(--border);padding-top:10px }
720
+ .si-history > summary { cursor:pointer;list-style:none;padding:6px 4px;font-size:12.5px;font-weight:600;color:var(--text-secondary);user-select:none;display:flex;align-items:center;gap:6px }
721
+ .si-history > summary::-webkit-details-marker { display:none }
722
+ .si-history > summary::before { content:'▸ ';color:var(--text-muted);font-size:11px }
723
+ .si-history[open] > summary::before { content:'▾ ' }
724
+ .si-history > summary:hover { color:var(--text-primary) }
725
+ .si-history-list { margin:6px 0 0;padding:0;list-style:none;display:flex;flex-direction:column;gap:4px }
726
+ .si-history-list li { padding:0;background:transparent }
727
+ /* 整行可点击:eval/observe 用 <a>,doctor 历史用 <button>(走 inline modal),样式完全一致 */
728
+ .si-history-row { all:unset;cursor:pointer;display:grid;grid-template-columns:64px 1fr auto auto;gap:10px;align-items:center;padding:7px 10px;background:var(--bg-soft);border-radius:5px;font-size:12.5px;line-height:1.45;transition:background .12s,transform .12s;text-align:left;width:100%;box-sizing:border-box;color:var(--text-primary) }
729
+ .si-history-row:hover { background:var(--bg-elevated);transform:translateX(2px) }
730
+ .si-history-row:focus-visible { outline:2px solid var(--accent);outline-offset:1px }
731
+ .si-history-date { font-variant-numeric:tabular-nums;font-weight:600;color:var(--text-secondary) }
732
+ .si-history-meta { color:var(--text-secondary);font-variant-numeric:tabular-nums }
733
+ .si-history-status { font-size:10.5px;font-weight:700;padding:1px 7px;border-radius:8px;letter-spacing:0.02em;justify-self:end }
734
+ .si-history-status--green { background:rgba(94,130,82,.18);color:#5e8252 }
735
+ .si-history-status--yellow { background:rgba(176,128,48,.16);color:#b08030 }
736
+ .si-history-status--red { background:rgba(156,74,63,.18);color:#9c4a3f }
737
+ .si-history-arrow { color:var(--text-muted);font-size:14px;font-weight:300 }
738
+ @media(max-width:640px){
739
+ .si-history-row { grid-template-columns:56px 1fr auto;gap:6px }
740
+ .si-history-arrow { display:none }
741
+ }
742
+
743
+ /* Eval modal blocks */
744
+ .si-eval-block { background:var(--bg-soft);padding:12px 14px;border-radius:6px;margin-bottom:12px }
745
+ .si-eval-block:last-child { margin-bottom:0 }
746
+ .si-eval-h { margin:0 0 10px;font-size:13px;font-weight:600;color:var(--text-primary) }
747
+ .si-eval-score-row { display:flex;gap:14px;align-items:flex-end;margin-bottom:10px }
748
+ .si-eval-composite { font-size:30px;font-weight:700;color:var(--text-primary);font-variant-numeric:tabular-nums;line-height:1 }
749
+ .si-eval-composite-sub { font-size:11.5px;color:var(--text-muted);margin-left:4px;font-weight:normal }
750
+ .si-eval-headline { color:var(--text-secondary);font-size:12.5px;line-height:1.5;margin:0;font-style:italic }
751
+ .si-layers { display:flex;flex-direction:column;gap:5px;margin-bottom:8px }
752
+ .si-layer { display:grid;grid-template-columns:80px 1fr 50px;gap:10px;align-items:center;font-size:12.5px }
753
+ .si-layer-lbl { color:var(--text-secondary) }
754
+ .si-layer-bar { background:var(--bg-surface);border-radius:4px;height:8px;overflow:hidden }
755
+ .si-layer-fill { height:100%;border-radius:4px }
756
+ .si-layer-fill--pass { background:#5e8252 }
757
+ .si-layer-fill--warn { background:#b08030 }
758
+ .si-layer-fill--fail { background:#9c4a3f }
759
+ .si-layer-num { font-variant-numeric:tabular-nums;font-weight:600;text-align:right;font-size:12px }
760
+ .si-layer-num--pass { color:#5e8252 }
761
+ .si-layer-num--warn { color:#b08030 }
762
+ .si-layer-num--fail { color:#9c4a3f }
763
+ .si-eval-link { display:inline-block;color:var(--accent);font-size:12.5px;text-decoration:none;font-weight:500 }
764
+ .si-eval-link:hover { text-decoration:underline }
765
+ .si-failed-list { margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:6px }
766
+ .si-failed-list li { font-size:12.5px;line-height:1.55;display:flex;flex-wrap:wrap;gap:6px;align-items:baseline;padding:8px 10px;border-radius:4px;background:rgba(156,74,63,.06);border-left:2px solid #9c4a3f }
767
+ .si-fs-id { font-size:11px;background:var(--bg-surface);padding:1px 5px;border-radius:3px;color:#9c4a3f;font-weight:600 }
768
+ .si-fs-mode { font-size:10.5px;color:#b08030;background:rgba(176,128,48,.14);padding:1px 6px;border-radius:8px;font-weight:500 }
769
+ .si-fs-summary { color:var(--text-secondary);font-size:12px;flex-basis:100% }
770
+
771
+ /* Eval history table */
772
+ .si-eval-history-table { width:100%;border-collapse:collapse;font-size:13px;margin-top:8px }
773
+ .si-eval-history-table th { text-align:left;padding:6px 10px;border-bottom:2px solid var(--border);color:var(--text-muted);font-weight:500 }
774
+ .si-eval-history-table td { padding:6px 10px;border-bottom:1px solid var(--border-soft) }
775
+ .si-eval-history-table tr:hover td { background:var(--bg-soft) }
776
+ .si-eval-history-table a { color:var(--link);text-decoration:none;font-size:12px }
777
+ .si-eval-history-table a:hover { text-decoration:underline }
778
+ `;
779
+ // ────────── chart.js init script ──────────
780
+ const TREND_INIT_SCRIPT = `
781
+ <script src="/static/chart.js" onerror="window.__omkChartLoadError=true"></script>
782
+ <script>
783
+ (function(){
784
+ var L = (document.documentElement.dataset.lang || 'zh');
785
+ function showFallback(canvas, msg){
786
+ if (!canvas) return;
787
+ var wrap = canvas.parentElement;
788
+ if (!wrap || wrap.dataset.omkFallback === '1') return;
789
+ wrap.dataset.omkFallback = '1'; // 防止异步路径多次写入
790
+ wrap.innerHTML = '<div class="si-trend-fallback">' +
791
+ '<div class="si-trend-fallback-icon">📉</div>' +
792
+ '<div class="si-trend-fallback-msg">' + msg + '</div>' +
793
+ '<div class="si-trend-fallback-hint">' + (L === 'en' ? 'Check browser console for details.' : '数据仍可从下方指标速览看,或在浏览器控制台看具体错误。') + '</div>' +
794
+ '</div>';
795
+ }
796
+ // 异步兜底:Chart 内部 RAF / setTimeout 抛错会冒泡到 window.error,这里捕获后
797
+ // 把 trend canvas 区域降级,不让"图表 init 看似成功但渲染失败"留出空白。
798
+ window.addEventListener('error', function(ev){
799
+ var canvas = document.getElementById('trend-chart');
800
+ if (!canvas) return;
801
+ var msg = (ev && ev.message) || '';
802
+ if (/chart/i.test(msg) || (ev.filename && /chart\\.js$/i.test(ev.filename))) {
803
+ showFallback(canvas, L === 'en' ? 'Trend chart error' : '趋势图渲染异常');
804
+ }
805
+ });
806
+ function init(){
807
+ var canvas = document.getElementById('trend-chart');
808
+ if (!canvas) return;
809
+ if (window.__omkChartLoadError || !window.Chart) {
810
+ showFallback(canvas, L === 'en' ? 'Chart failed to load' : '趋势图加载失败');
811
+ return;
812
+ }
813
+ var raw = canvas.getAttribute('data-chart');
814
+ var rawLinks = canvas.getAttribute('data-links');
815
+ if (!raw) return;
816
+ try {
817
+ var data = JSON.parse(raw);
818
+ var links = rawLinks ? JSON.parse(rawLinks) : null;
819
+ // 防御:dataset data 长度跟 labels 严重不一致直接降级,别让 chart 静默画空 canvas
820
+ if (data && Array.isArray(data.labels) && Array.isArray(data.datasets)) {
821
+ var bad = data.datasets.some(function(ds){
822
+ return !Array.isArray(ds.data) || ds.data.length !== data.labels.length;
823
+ });
824
+ if (bad) {
825
+ showFallback(canvas, L === 'en' ? 'Chart data format error' : '趋势图数据格式异常');
826
+ return;
827
+ }
828
+ }
829
+ new Chart(canvas, {
830
+ type: 'line',
831
+ data: data,
832
+ options: {
833
+ responsive: true, maintainAspectRatio: false,
834
+ plugins: {
835
+ legend: { position: 'bottom', labels: { boxWidth: 10, font: { size: 11 }, color: '#7a7a7a' } },
836
+ tooltip: { callbacks: {
837
+ label: function(ctx){ return ctx.dataset.label + ': ' + (ctx.parsed.y == null ? '—' : ctx.parsed.y.toFixed(1) + '%'); },
838
+ afterLabel: function(ctx){
839
+ var hint = ctx.dataset._hint || '';
840
+ var lines = hint ? [hint] : [];
841
+ if (links) {
842
+ var url = links[ctx.datasetIndex] && links[ctx.datasetIndex][ctx.dataIndex];
843
+ if (url) lines.push(L === 'en' ? '→ Click to view report' : '→ 点击看那期报告');
844
+ }
845
+ return lines;
846
+ }
847
+ } }
848
+ },
849
+ scales: {
850
+ y: { min: 0, max: 100, ticks: { callback: function(v){ return v === 0 || v === 100 ? v + '%' : ''; }, color: '#a8a8a8', font: { size: 10 }, stepSize: 25 }, grid: { color: 'rgba(58,58,58,.06)' } },
851
+ x: { ticks: { color: '#a8a8a8', font: { size: 10 } }, grid: { display: false } }
852
+ },
853
+ elements: { point: { radius: 3, hoverRadius: 5 } },
854
+ onClick: function(_evt, elements){
855
+ if (!links || !elements || elements.length === 0) return;
856
+ var el = elements[0];
857
+ var url = links[el.datasetIndex] && links[el.datasetIndex][el.index];
858
+ if (url) window.location.href = url;
859
+ },
860
+ onHover: function(evt, elements){
861
+ if (!links) return;
862
+ var any = elements && elements.some(function(el){ return links[el.datasetIndex] && links[el.datasetIndex][el.index]; });
863
+ evt.native.target.style.cursor = any ? 'pointer' : 'default';
864
+ }
865
+ }
866
+ });
867
+ } catch(e) {
868
+ console.warn('trend chart init failed:', e);
869
+ showFallback(canvas, L === 'en' ? 'Trend chart error' : '趋势图渲染异常');
870
+ }
871
+ }
872
+ if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
873
+ else init();
874
+ })();
875
+ </script>`;
876
+ // ────────── v7:三视角顶层全景 + 各 section 直铺 ──────────
877
+ /** 紧凑 inline sparkline(供顶部速览卡每张里用,显示该视角历史走向)。
878
+ * values 是 0-100 归一化数组(空数组返回占位)。 */
879
+ function renderInlineSpark(values, color) {
880
+ if (!values || values.length === 0) {
881
+ return `<svg class="si-vs-spark" width="80" height="22" viewBox="0 0 80 22" xmlns="http://www.w3.org/2000/svg"><text x="50%" y="55%" text-anchor="middle" fill="#a8a8a8" font-size="9">no data</text></svg>`;
882
+ }
883
+ const w = 80, h = 22, pad = 2;
884
+ const min = Math.min(...values, 0);
885
+ const max = Math.max(...values, 100);
886
+ const range = (max - min) || 1;
887
+ const dx = values.length > 1 ? (w - 2 * pad) / (values.length - 1) : 0;
888
+ const pts = values.map((v, i) => {
889
+ const x = pad + i * dx;
890
+ const y = pad + (h - 2 * pad) * (1 - (v - min) / range);
891
+ return `${x.toFixed(1)},${y.toFixed(1)}`;
892
+ }).join(' ');
893
+ return `<svg class="si-vs-spark" width="${w}" height="${h}" viewBox="0 0 ${w} ${h}" xmlns="http://www.w3.org/2000/svg">
894
+ <polyline points="${pts}" fill="none" stroke="${color}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
895
+ </svg>`;
896
+ }
897
+ /** Donut ring SVG:中央显示百分比,弧色按 band。半径 38,周长 ~239。 */
898
+ function renderDonutRing(pct, color, label) {
899
+ const r = 38, c = 2 * Math.PI * r;
900
+ const safePct = pct == null ? 0 : Math.max(0, Math.min(100, pct));
901
+ const dashOffset = c * (1 - safePct / 100);
902
+ const centerText = pct == null ? '—' : `${Math.round(safePct)}%`;
903
+ return `<svg class="si-ring" width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="${e(label)}">
904
+ <circle cx="50" cy="50" r="${r}" fill="none" stroke="var(--bg-soft)" stroke-width="8"/>
905
+ ${pct != null ? `<circle cx="50" cy="50" r="${r}" fill="none" stroke="${color}" stroke-width="8"
906
+ stroke-dasharray="${c.toFixed(2)}" stroke-dashoffset="${dashOffset.toFixed(2)}"
907
+ stroke-linecap="round" transform="rotate(-90 50 50)"/>` : ''}
908
+ <text x="50" y="56" text-anchor="middle" font-size="19" font-weight="700" fill="${pct == null ? 'var(--text-muted)' : color}" font-family="-apple-system,BlinkMacSystemFont,sans-serif">${centerText}</text>
909
+ </svg>`;
910
+ }
911
+ /** 三视角顶部全景:3 个 Apple-watch 风 donut ring,每个 ring 下面带 emoji + label + 状态 + sparkline */
912
+ function renderViewSummaryCards(entry, lang) {
913
+ // doctor
914
+ const docBand = entry.doctor
915
+ ? (entry.doctor.status === 'fail' ? 'red' : entry.doctor.status === 'warn' ? 'yellow' : 'green') : 'gray';
916
+ const docColor = docBand === 'green' ? '#5e8252' : docBand === 'yellow' ? '#b08030' : docBand === 'red' ? '#9c4a3f' : '#a8a8a8';
917
+ const docPct = entry.doctor && (entry.doctor.passCount + entry.doctor.warnCount + entry.doctor.failCount) > 0
918
+ ? (entry.doctor.passCount / (entry.doctor.passCount + entry.doctor.warnCount + entry.doctor.failCount)) * 100
919
+ : null;
920
+ const docPassRates = entry.doctorHistory.map((h) => {
921
+ const tot = h.passCount + h.warnCount + h.failCount;
922
+ return tot > 0 ? (h.passCount / tot) * 100 : 0;
923
+ });
924
+ const docStat = entry.doctor
925
+ ? `${entry.doctor.passCount}✓ ${entry.doctor.warnCount}⚠ ${entry.doctor.failCount}✗`
926
+ : (lang === 'zh' ? '未运行' : 'not run');
927
+ // eval
928
+ const evalBand = entry.eval
929
+ ? (entry.eval.failCount === 0 ? 'green' : entry.eval.passCount === 0 ? 'red' : 'yellow') : 'gray';
930
+ const evalColor = evalBand === 'green' ? '#5e8252' : evalBand === 'yellow' ? '#b08030' : evalBand === 'red' ? '#9c4a3f' : '#a8a8a8';
931
+ const evalPct = entry.eval && entry.eval.compositeScore != null
932
+ ? (entry.eval.compositeScore / 5) * 100
933
+ : null;
934
+ const evalCompositeRates = entry.evalHistory.map((h) => (h.compositeScore ?? 0) / 5 * 100);
935
+ const evalStat = entry.eval && (entry.eval.passCount + entry.eval.failCount) > 0
936
+ ? `${entry.eval.totalSamples} ${lang === 'zh' ? '用例' : 'samples'} · ${Math.round((entry.eval.passCount / (entry.eval.passCount + entry.eval.failCount)) * 100)}%${entry.eval.compositeScore != null ? ` · ${entry.eval.compositeScore.toFixed(2)}/5` : ''}`
937
+ : (lang === 'zh' ? '未运行' : 'not run');
938
+ // observe
939
+ const obsBand = effectiveObserveBand(entry.observe);
940
+ const obsColor = obsBand === 'green' ? '#5e8252' : obsBand === 'yellow' ? '#b08030' : obsBand === 'red' ? '#9c4a3f' : '#a8a8a8';
941
+ const obsPct = entry.observe ? (1 - entry.observe.gapRate) * 100 : null;
942
+ // underpowered 历史点不进趋势 spark:低 N 的 stability 仅供参考,不该当作可信趋势顶点(口径同参考分)。
943
+ const obsStabilityRates = entry.observeHistory
944
+ .filter((h) => h.confidence !== 'underpowered')
945
+ .map((h) => (1 - h.gapRate) * 100);
946
+ const obsStat = !entry.observe
947
+ ? (lang === 'zh' ? '未运行' : 'not run')
948
+ // 低 N 不报「X% 稳定」硬指标,只标段数 + 仅供参考,跟列表卡口径一致。
949
+ : entry.observe.confidence === 'underpowered'
950
+ ? `${entry.observe.segmentCount} ${lang === 'zh' ? '段 · 样本不足' : 'segs · low N'}`
951
+ : `${entry.observe.segmentCount} ${lang === 'zh' ? '段' : 'segs'} · ${((1 - entry.observe.gapRate) * 100).toFixed(0)}% ${lang === 'zh' ? '稳定' : 'stable'}`;
952
+ const node = (icon, label, sublabel, band, pct, color, stat, sparkRates, anchor) => `<a class="si-vs si-vs--${band}" href="#${anchor}">
953
+ ${renderDonutRing(pct, color, `${label} ${sublabel}`)}
954
+ <div class="si-vs-h">
955
+ <span class="si-vs-icon">${icon}</span>
956
+ <span class="si-vs-label">${e(label)}</span>
957
+ <span class="si-vs-sublabel">${e(sublabel)}</span>
958
+ </div>
959
+ <div class="si-vs-stat">${e(stat)}</div>
960
+ ${renderInlineSpark(sparkRates, color)}
961
+ </a>`;
962
+ return `${node('🩺', lang === 'zh' ? '健康度' : 'Structure', '(doctor)', docBand, docPct, docColor, docStat, docPassRates, 'section-doctor')}
963
+ ${node('🧪', lang === 'zh' ? '评测结果' : 'Test score', '(eval)', evalBand, evalPct, evalColor, evalStat, evalCompositeRates, 'section-eval')}
964
+ ${node('👁', lang === 'zh' ? '线上观测' : 'Live stability', '(observe)', obsBand, obsPct, obsColor, obsStat, obsStabilityRates, 'section-observe')}`;
965
+ }
966
+ /** doctor section:展示告警 / 失败规则;通过的规则折叠到底部 */
967
+ function renderDoctorSection(snap, history, lang) {
968
+ if (!snap) {
969
+ return `<section id="section-doctor" class="si-sect si-sect--gray">
970
+ <div class="si-sect-h">🩺 ${lang === 'zh' ? '健康度 (doctor)' : 'Structure (doctor)'}</div>
971
+ <div class="si-sect-empty">${lang === 'zh' ? '未运行 omk doctor' : 'doctor not run yet'}</div>
972
+ </section>`;
973
+ }
974
+ const getDet = (r) => r.detail;
975
+ const SORT_ORDER = { fail: 0, warn: 1, skipped: 2, pass: 3 };
976
+ const dims = snap.results
977
+ .filter((r) => !r.ruleId.endsWith(':_summary'))
978
+ .sort((a, b) => (SORT_ORDER[a.status] ?? 9) - (SORT_ORDER[b.status] ?? 9));
979
+ const STATUS_CFG = {
980
+ fail: { dot: '🔴', label: lang === 'zh' ? '不通过' : 'fail', cls: 'err' },
981
+ warn: { dot: '🟡', label: lang === 'zh' ? '告警' : 'warn', cls: 'warn' },
982
+ pass: { dot: '🟢', label: lang === 'zh' ? '通过' : 'pass', cls: 'pass' },
983
+ skipped: { dot: '⚪', label: lang === 'zh' ? '跳过' : 'skip', cls: 'skip' },
984
+ };
985
+ const renderDimRow = (r) => {
986
+ const det = getDet(r);
987
+ const name = det?.displayName ?? r.ruleId;
988
+ const cfg = STATUS_CFG[r.status] ?? STATUS_CFG.pass;
989
+ const findings = det?.findings ?? [];
990
+ const errors = findings.filter((f) => f.level === '错误');
991
+ const warnings = findings.filter((f) => f.level === '警告');
992
+ const hasDetails = errors.length > 0 || warnings.length > 0;
993
+ const badge = (count, type) => {
994
+ if (!count)
995
+ return '';
996
+ const label = type === 'err' ? (lang === 'zh' ? '错误' : 'err') : (lang === 'zh' ? '警告' : 'warn');
997
+ return `<span class="sd-badge sd-badge--${type}">${count} ${label}</span>`;
998
+ };
999
+ const header = `<div class="sd-dim-header">
1000
+ <span class="sd-dim-dot">${cfg.dot}</span>
1001
+ <span class="sd-dim-name">${e(name)}</span>
1002
+ <span class="sd-dim-badges">${badge(errors.length, 'err')}${badge(warnings.length, 'warn')}</span>
1003
+ </div>`;
1004
+ if (!hasDetails)
1005
+ return `<div class="sd-dim sd-dim--${cfg.cls}">${header}</div>`;
1006
+ let body = '';
1007
+ if (errors.length > 0) {
1008
+ body += errors.map((f) => `<div class="sd-item sd-item--err">
1009
+ <div class="sd-item-desc">❌ ${e(f.description ?? '')}</div>
1010
+ ${f.suggestion ? `<div class="sd-item-sug">💡 ${e(f.suggestion)}</div>` : ''}
1011
+ </div>`).join('');
1012
+ }
1013
+ if (warnings.length > 0) {
1014
+ body += `<details class="sd-warn-fold"><summary class="sd-warn-toggle">${lang === 'zh' ? `${warnings.length} 条警告` : `${warnings.length} warning(s)`}</summary>`;
1015
+ body += `<div class="sd-warn-list">${warnings.map((f) => `<div class="sd-item sd-item--warn">
1016
+ <div class="sd-item-desc">⚠️ ${e(f.description ?? '')}</div>
1017
+ ${f.suggestion ? `<div class="sd-item-sug">💡 ${e(f.suggestion)}</div>` : ''}
1018
+ </div>`).join('')}</div>`;
1019
+ body += `</details>`;
1020
+ }
1021
+ return `<details class="sd-dim sd-dim--${cfg.cls}" ${errors.length > 0 ? 'open' : ''}>
1022
+ <summary>${header}</summary>
1023
+ <div class="sd-dim-body">${body}</div>
1024
+ </details>`;
1025
+ };
1026
+ return `<section id="section-doctor" class="si-sect si-sect--${snap.status === 'fail' ? 'red' : snap.status === 'warn' ? 'yellow' : 'green'}">
1027
+ <div class="si-sect-h">
1028
+ <span class="si-sect-title">🩺 ${lang === 'zh' ? '健康度 (doctor)' : 'Structure (doctor)'}</span>
1029
+ <span class="si-sect-meta">${snap.passCount}✓ ${snap.warnCount}⚠ ${snap.failCount}✗ · ${relTime(snap.timestamp, lang)}</span>
1030
+ </div>
1031
+ <div class="sd-grid">
1032
+ ${dims.filter((r) => r.status === 'fail' || r.status === 'warn').map(renderDimRow).join('')}
1033
+ ${dims.filter((r) => r.status === 'pass' || r.status === 'skipped').length > 0
1034
+ ? `<details class="sd-pass-fold"><summary class="sd-pass-toggle">${lang === 'zh'
1035
+ ? `▸ ${dims.filter((r) => r.status === 'pass' || r.status === 'skipped').length} 项通过`
1036
+ : `▸ ${dims.filter((r) => r.status === 'pass' || r.status === 'skipped').length} passed`}</summary>
1037
+ ${dims.filter((r) => r.status === 'pass' || r.status === 'skipped').map(renderDimRow).join('')}
1038
+ </details>`
1039
+ : ''}
1040
+ </div>
1041
+ ${renderDoctorHistory(history, lang)}
1042
+ </section>`;
1043
+ }
1044
+ /** eval history: 历史评测记录列表(折叠) */
1045
+ function renderEvalHistory(history, langQ, lang) {
1046
+ if (history.length < 2)
1047
+ return '';
1048
+ const rows = [...history].reverse().map((h) => {
1049
+ const date = h.timestamp ? new Date(h.timestamp).toLocaleString(lang === 'zh' ? 'zh-CN' : 'en-US', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }) : '-';
1050
+ const score = h.compositeScore != null ? h.compositeScore.toFixed(2) : '-';
1051
+ const status = h.failCount === 0 ? '✅' : `❌ ${h.failCount} fail`;
1052
+ const link = `<a href="/reports/${e(h.reportId)}${langQ}">${e(h.reportId)}</a>`;
1053
+ return `<tr><td>${date}</td><td>${score}</td><td>${h.passCount}/${h.totalSamples}</td><td>${status}</td><td>${link}</td></tr>`;
1054
+ }).join('\n');
1055
+ return `<details class="si-sect-fold">
1056
+ <summary>${lang === 'zh' ? `▸ 历史评测记录 (${history.length} 次)` : `▸ Eval history (${history.length} runs)`}</summary>
1057
+ <div class="si-sect-fold-body">
1058
+ <table class="si-eval-history-table">
1059
+ <thead><tr><th>${lang === 'zh' ? '时间' : 'Time'}</th><th>${lang === 'zh' ? '分数' : 'Score'}</th><th>${lang === 'zh' ? '通过' : 'Pass'}</th><th>${lang === 'zh' ? '状态' : 'Status'}</th><th>${lang === 'zh' ? '报告' : 'Report'}</th></tr></thead>
1060
+ <tbody>${rows}</tbody>
1061
+ </table>
1062
+ </div>
1063
+ </details>`;
1064
+ }
1065
+ /** doctor history: 历史检查记录列表(折叠) */
1066
+ function renderDoctorHistory(history, lang) {
1067
+ if (history.length < 2)
1068
+ return '';
1069
+ const rows = [...history].reverse().map((h) => {
1070
+ const date = h.timestamp ? new Date(h.timestamp).toLocaleString(lang === 'zh' ? 'zh-CN' : 'en-US', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }) : '-';
1071
+ const statusIcon = h.status === 'pass' ? '✅' : h.status === 'warn' ? '⚠️' : '❌';
1072
+ const detail = `${h.passCount}✓ ${h.warnCount}⚠ ${h.failCount}✗`;
1073
+ return `<tr><td>${date}</td><td>${statusIcon} ${e(h.status)}</td><td>${detail}</td></tr>`;
1074
+ }).join('\n');
1075
+ return `<details class="si-sect-fold">
1076
+ <summary>${lang === 'zh' ? `▸ 历史检查记录 (${history.length} 次)` : `▸ Doctor history (${history.length} runs)`}</summary>
1077
+ <div class="si-sect-fold-body">
1078
+ <table class="si-eval-history-table">
1079
+ <thead><tr><th>${lang === 'zh' ? '时间' : 'Time'}</th><th>${lang === 'zh' ? '状态' : 'Status'}</th><th>${lang === 'zh' ? '明细' : 'Detail'}</th></tr></thead>
1080
+ <tbody>${rows}</tbody>
1081
+ </table>
1082
+ </div>
1083
+ </details>`;
1084
+ }
1085
+ /** eval section:失败 sample 列表(默认折叠,展开看 prompt/期望/实际/建议) */
1086
+ function renderEvalSection(snap, evalReport, history, langQ, lang) {
1087
+ if (!snap) {
1088
+ return `<section id="section-eval" class="si-sect si-sect--gray">
1089
+ <div class="si-sect-h">🧪 ${lang === 'zh' ? '评测结果 (eval)' : 'Test score (eval)'}</div>
1090
+ <div class="si-sect-empty">${lang === 'zh' ? '未运行 omk eval' : 'eval not run yet'}</div>
1091
+ </section>`;
1092
+ }
1093
+ const failedSamples = [];
1094
+ const passedSamples = [];
1095
+ const tripwireSamples = [];
1096
+ if (evalReport && snap.variantName) {
1097
+ const variant = snap.variantName;
1098
+ for (const r of evalReport.results) {
1099
+ const v = r.variants?.[variant];
1100
+ if (!v)
1101
+ continue;
1102
+ const sid = r.sample_id;
1103
+ const prompt = evalReport.sampleSnapshots?.[sid]?.prompt ?? '';
1104
+ const promptPreview = prompt.slice(0, 80).replace(/\n+/g, ' ');
1105
+ const passed = (v.assertions?.details ?? []).every((d) => d.passed);
1106
+ const isTripwire = (v.diagnostic?.rootCause ?? []).includes('tripwire_intentional')
1107
+ || evalReport.sampleSnapshots?.[sid]?.tripwire === true;
1108
+ if (isTripwire) {
1109
+ tripwireSamples.push({ sampleId: sid, prompt, promptPreview });
1110
+ }
1111
+ else if (passed) {
1112
+ passedSamples.push({
1113
+ sampleId: sid, prompt, promptPreview, score: v.compositeScore ?? null,
1114
+ rubric: evalReport.sampleSnapshots?.[sid]?.rubric ?? '',
1115
+ output: v.outputPreview ?? '',
1116
+ });
1117
+ }
1118
+ else {
1119
+ failedSamples.push({
1120
+ sampleId: sid,
1121
+ diagnosticSummary: v.diagnostic?.summary ?? '',
1122
+ prompt,
1123
+ expected: v.diagnostic?.expected ?? '',
1124
+ actual: v.diagnostic?.actual ?? '',
1125
+ suggestionSkill: v.diagnostic?.suggestion?.skill ?? '',
1126
+ suggestionSample: v.diagnostic?.suggestion?.sample ?? '',
1127
+ failureModes: (v.diagnostic?.failureModes ?? []),
1128
+ illustration: null,
1129
+ });
1130
+ }
1131
+ }
1132
+ }
1133
+ const total = snap.passCount + snap.failCount;
1134
+ const pct = total > 0 ? Math.round((snap.passCount / total) * 100) : 0;
1135
+ const sectBand = snap.failCount === 0 ? 'green' : snap.passCount === 0 ? 'red' : 'yellow';
1136
+ const failedBlock = failedSamples.length > 0
1137
+ ? failedSamples.map((s) => {
1138
+ const summary = s.diagnosticSummary || (lang === 'zh' ? '(无诊断摘要)' : '(no summary)');
1139
+ const modes = s.failureModes.length > 0
1140
+ ? `<span class="si-failure-modes">${s.failureModes.map((m) => `<span class="si-failure-mode">${e(m)}</span>`).join('')}</span>`
1141
+ : '';
1142
+ const traceLink = `<a class="si-failure-trace" href="/reports/${e(snap.reportId)}${langQ}#sample-${e(s.sampleId)}" onclick="event.stopPropagation()">${lang === 'zh' ? '完整 trace →' : 'full trace →'}</a>`;
1143
+ return `<details class="si-failure-item">
1144
+ <summary class="si-failure-head">
1145
+ <div class="si-failure-row1">
1146
+ <span class="si-sample-dot si-sample-dot--fail">🔴</span>
1147
+ <code class="si-failure-id">${e(s.sampleId)}</code>
1148
+ ${modes}
1149
+ <span class="si-failure-spacer"></span>
1150
+ ${traceLink}
1151
+ </div>
1152
+ <div class="si-failure-row2">${e(summary)}</div>
1153
+ </summary>
1154
+ <div class="si-failure-detail">${renderSampleBody(s, lang)}</div>
1155
+ </details>`;
1156
+ }).join('')
1157
+ : '';
1158
+ // 通过 sample: 可展开看 prompt 全文 + 得分 + trace 链接
1159
+ const renderPassedSample = (s) => {
1160
+ const traceLink = `<a class="si-failure-trace" href="/reports/${e(snap.reportId)}${langQ}#sample-${e(s.sampleId)}" onclick="event.stopPropagation()">${lang === 'zh' ? '完整 trace →' : 'full trace →'}</a>`;
1161
+ const scoreText = s.score != null ? `${s.score.toFixed(1)}/5` : '';
1162
+ return `<details class="si-pass-card">
1163
+ <summary class="si-pass-head">
1164
+ <div class="si-pass-row1">
1165
+ <span class="si-sample-dot">🟢</span>
1166
+ <code class="si-pass-id">${e(s.sampleId)}</code>
1167
+ ${scoreText ? `<span class="si-pass-score">${scoreText}</span>` : ''}
1168
+ <span class="si-failure-spacer"></span>
1169
+ ${traceLink}
1170
+ </div>
1171
+ <div class="si-pass-prompt-preview">${e(s.promptPreview)}${s.prompt.length > 80 ? '…' : ''}</div>
1172
+ </summary>
1173
+ <div class="si-pass-body">
1174
+ <div class="si-pass-section">
1175
+ <div class="si-pass-label">${lang === 'zh' ? '📝 用例 Prompt' : '📝 Prompt'}</div>
1176
+ <div class="si-pass-content">${e(s.prompt)}</div>
1177
+ </div>
1178
+ ${s.rubric ? `<div class="si-pass-section">
1179
+ <div class="si-pass-label">${lang === 'zh' ? '🎯 期望' : '🎯 Expected'}</div>
1180
+ <div class="si-pass-content">${e(s.rubric)}</div>
1181
+ </div>` : ''}
1182
+ ${s.output ? `<div class="si-pass-section">
1183
+ <div class="si-pass-label">${lang === 'zh' ? '✅ 实际输出' : '✅ Actual'}</div>
1184
+ <div class="si-pass-content">${e(s.output)}</div>
1185
+ </div>` : ''}
1186
+ </div>
1187
+ </details>`;
1188
+ };
1189
+ const passedFold = passedSamples.length > 0
1190
+ ? `<details class="si-sect-fold">
1191
+ <summary>${lang === 'zh' ? `▸ 已通过 ${passedSamples.length} 条用例` : `▸ ${passedSamples.length} samples passed`}</summary>
1192
+ <div class="si-sect-fold-body">${passedSamples.map(renderPassedSample).join('')}</div>
1193
+ </details>`
1194
+ : '';
1195
+ const tripwireFold = tripwireSamples.length > 0
1196
+ ? `<details class="si-sect-fold">
1197
+ <summary>${lang === 'zh' ? `▸ 诱错样本 ${tripwireSamples.length} 条(按设计应该失败)` : `▸ ${tripwireSamples.length} tripwire samples (designed to fail)`}</summary>
1198
+ <div class="si-sect-fold-body">${tripwireSamples.map(renderPassedSample).join('')}</div>
1199
+ </details>`
1200
+ : '';
1201
+ const failedHeading = failedSamples.length > 0
1202
+ ? `<div class="si-sect-line">${lang === 'zh' ? `${failedSamples.length} 条用例失败:` : `${failedSamples.length} samples failed:`}</div>`
1203
+ : `<div class="si-sect-allpass">✓ ${lang === 'zh' ? '所有用例通过' : 'all samples pass'}</div>`;
1204
+ // 综合得分 + 六维雷达
1205
+ const variantSummary = evalReport?.summary?.[snap.variantName];
1206
+ const scoreCard = (label, value, max) => {
1207
+ if (value == null)
1208
+ return '';
1209
+ const pctW = Math.round((value / max) * 100);
1210
+ const cls = pctW >= 80 ? 'good' : pctW >= 60 ? 'mid' : 'low';
1211
+ return `<div class="se-score-card">
1212
+ <div class="se-score-label">${e(label)}</div>
1213
+ <div class="se-score-bar"><div class="se-score-fill se-score-fill--${cls}" style="width:${pctW}%"></div></div>
1214
+ <div class="se-score-val">${value.toFixed(2)}<span class="se-score-max">/${max}</span></div>
1215
+ </div>`;
1216
+ };
1217
+ const scoreSummary = variantSummary ? `<div class="se-scores">
1218
+ <div class="se-scores-hero">
1219
+ <div class="se-hero-label">${lang === 'zh' ? '综合得分' : 'Composite'}</div>
1220
+ <div class="se-hero-val">${(variantSummary.avgCompositeScore ?? 0).toFixed(2)}<span class="se-hero-max">/5</span></div>
1221
+ <a class="se-hero-link" href="/reports/${e(snap.reportId)}${langQ}">${lang === 'zh' ? '查看详情 →' : 'Details →'}</a>
1222
+ </div>
1223
+ <div class="se-scores-grid">
1224
+ ${scoreCard(lang === 'zh' ? '事实 / Fact' : 'Fact', variantSummary.avgFactScore, 5)}
1225
+ ${scoreCard(lang === 'zh' ? '行为 / Behavior' : 'Behavior', variantSummary.avgAssertionScore, 5)}
1226
+ ${scoreCard(lang === 'zh' ? 'LLM 评价 / Judge' : 'Judge', variantSummary.avgJudgeScore, 5)}
1227
+ ${scoreCard(lang === 'zh' ? '工具成功率' : 'Tool success', variantSummary.toolSuccessRate != null ? variantSummary.toolSuccessRate * 100 : null, 100)}
1228
+ ${scoreCard(lang === 'zh' ? 'Trace 覆盖率' : 'Trace coverage', variantSummary.traceCoverageRate != null ? variantSummary.traceCoverageRate * 100 : null, 100)}
1229
+ ${scoreCard(lang === 'zh' ? '平均轮次' : 'Avg turns', variantSummary.avgNumTurns, 20)}
1230
+ </div>
1231
+ </div>` : '';
1232
+ return `<section id="section-eval" class="si-sect si-sect--${sectBand}">
1233
+ <div class="si-sect-h">
1234
+ <span class="si-sect-title">🧪 ${lang === 'zh' ? '评测结果 (eval)' : 'Test score (eval)'}</span>
1235
+ <span class="si-sect-meta">${snap.totalSamples} ${lang === 'zh' ? '用例' : 'samples'} · ${pct}% ${lang === 'zh' ? '通过' : 'pass'}${snap.compositeScore != null ? ` · ${snap.compositeScore.toFixed(2)}/5` : ''} · ${relTime(snap.timestamp, lang)}</span>
1236
+ </div>
1237
+ <div class="si-sect-body">
1238
+ ${scoreSummary}
1239
+ ${failedHeading}
1240
+ ${failedBlock}
1241
+ ${passedFold}
1242
+ ${tripwireFold}
1243
+ ${renderEvalHistory(history, langQ, lang)}
1244
+ <a class="si-sect-link" href="/reports/${e(snap.reportId)}${langQ}">${lang === 'zh' ? '完整 A/B 报告 →' : 'Full A/B report →'}</a>
1245
+ </div>
1246
+ </section>`;
1247
+ }
1248
+ /** observe section:展示异常指标(gap / 工具失败率) */
1249
+ function renderObserveSection(snap, langQ, lang) {
1250
+ if (!snap) {
1251
+ return `<section id="section-observe" class="si-sect si-sect--gray">
1252
+ <div class="si-sect-h">👁 ${lang === 'zh' ? '线上观测 (observe)' : 'Live stability (observe)'}</div>
1253
+ <div class="si-sect-empty">${lang === 'zh' ? '未跑 omk observe' : 'observe not run yet'}</div>
1254
+ </section>`;
1255
+ }
1256
+ const gapPct = (snap.gapRate * 100).toFixed(0);
1257
+ const failPct = (snap.failureRate * 100).toFixed(1);
1258
+ const alerts = [];
1259
+ if (snap.gapRate >= 0.2) {
1260
+ alerts.push(`<div class="si-rule si-rule--warn">
1261
+ <div class="si-rule-head">
1262
+ <span class="si-rule-icon">⚠</span>
1263
+ <code class="si-rule-id">${lang === 'zh' ? '知识库 gap' : 'KB gap'}</code>
1264
+ <span class="si-rule-msg">${gapPct}% ${lang === 'zh' ? '段命中知识库 gap — LLM 找不到该读哪段' : 'segments hit knowledge gap'}</span>
1265
+ </div>
1266
+ </div>`);
1267
+ }
1268
+ if (snap.failureRate >= 0.2) {
1269
+ alerts.push(`<div class="si-rule si-rule--warn">
1270
+ <div class="si-rule-head">
1271
+ <span class="si-rule-icon">⚠</span>
1272
+ <code class="si-rule-id">${lang === 'zh' ? '工具失败率' : 'tool fail rate'}</code>
1273
+ <span class="si-rule-msg">${failPct}% ${lang === 'zh' ? '工具调用失败 — 可能环境问题或 skill 让 LLM 走错路径' : 'tool calls failing'}</span>
1274
+ </div>
1275
+ </div>`);
1276
+ }
1277
+ const body = alerts.length > 0
1278
+ ? alerts.join('')
1279
+ : `<div class="si-sect-allpass">✓ ${lang === 'zh' ? '生产观测健康' : 'production observation healthy'}</div>`;
1280
+ const obsCaveat = snap.confidence === 'underpowered'
1281
+ ? (lang === 'zh' ? ' · ⚠ 样本不足,色带仅供参考' : ' · ⚠ low N, band indicative')
1282
+ : '';
1283
+ return `<section id="section-observe" class="si-sect si-sect--${effectiveObserveBand(snap)}">
1284
+ <div class="si-sect-h">
1285
+ <span class="si-sect-title">👁 ${lang === 'zh' ? '线上观测 (observe)' : 'Live stability (observe)'}</span>
1286
+ <span class="si-sect-meta">${snap.segmentCount} ${lang === 'zh' ? '段' : 'segs'} · gap ${gapPct}% · ${lang === 'zh' ? '工具失败率' : 'tool fail'} ${failPct}% · ${relTime(snap.generatedAt, lang)}${obsCaveat}</span>
1287
+ </div>
1288
+ <div class="si-sect-body">
1289
+ ${body}
1290
+ <a class="si-sect-link" href="/analyses/${e(snap.analysisId)}${langQ}">${lang === 'zh' ? '完整观测报告 →' : 'Full observation report →'}</a>
1291
+ </div>
1292
+ </section>`;
1293
+ }
1294
+ // ────────── 主入口 ──────────
1295
+ export function renderSkillDetail(entry, evalReport, lang = DEFAULT_LANG, insights = []) {
1296
+ const langQ = lang === DEFAULT_LANG ? '' : `?lang=${lang}`;
1297
+ const reportCount = [entry.doctor, entry.eval, entry.observe].filter(Boolean).length;
1298
+ const lastTs = [entry.doctor?.timestamp, entry.eval?.timestamp, entry.observe?.generatedAt]
1299
+ .filter((s) => Boolean(s)).sort().pop();
1300
+ return layout(entry.skillName, `
1301
+ <main>
1302
+ <a class="si-back" href="/${langQ}">${lang === 'zh' ? '← 返回 Skills' : '← Back to Skills'}</a>
1303
+ ${renderHero(entry, insights, lastTs, reportCount, lang)}
1304
+
1305
+ <div class="si-overview">
1306
+ <section class="si-overview-cards" aria-label="${lang === 'zh' ? '三视角速览' : 'View summary'}">
1307
+ ${renderViewSummaryCards(entry, lang)}
1308
+ </section>
1309
+ <section class="si-overview-trend">
1310
+ <div class="si-trend-h">📈 ${lang === 'zh' ? '健康趋势(0-100%)' : 'Trend (0-100%)'}</div>
1311
+ ${renderTrendChart(entry, langQ, lang)}
1312
+ </section>
1313
+ </div>
1314
+
1315
+ ${renderDoctorSection(entry.doctor, entry.doctorHistory, lang)}
1316
+ ${renderEvalSection(entry.eval, evalReport, entry.evalHistory, langQ, lang)}
1317
+ ${renderObserveSection(entry.observe, langQ, lang)}
1318
+ </main>
1319
+ <style>${SKILL_DETAIL_CSS}</style>
1320
+ ${TREND_INIT_SCRIPT}
1321
+ `, lang);
1322
+ }
1323
+ //# sourceMappingURL=skill-detail-renderer.js.map