@marinoscar/kvox-eval 0.0.0-bootstrap → 0.1.0-next.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 (245) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE +21 -0
  3. package/README.md +166 -0
  4. package/dist/ask/index.d.ts +6 -0
  5. package/dist/ask/index.js +28 -0
  6. package/dist/ask/question-schema.d.ts +121 -0
  7. package/dist/ask/question-schema.js +167 -0
  8. package/dist/ask/report.d.ts +88 -0
  9. package/dist/ask/report.js +170 -0
  10. package/dist/ask/scorer.d.ts +104 -0
  11. package/dist/ask/scorer.js +164 -0
  12. package/dist/ask-run/ask-command.d.ts +62 -0
  13. package/dist/ask-run/ask-command.js +254 -0
  14. package/dist/ask-run/host/app.d.ts +65 -0
  15. package/dist/ask-run/host/app.js +146 -0
  16. package/dist/ask-run/host/db.d.ts +38 -0
  17. package/dist/ask-run/host/db.js +126 -0
  18. package/dist/ask-run/host/ports.d.ts +35 -0
  19. package/dist/ask-run/host/ports.js +113 -0
  20. package/dist/ask-run/index.d.ts +13 -0
  21. package/dist/ask-run/index.js +35 -0
  22. package/dist/ask-run/replay.d.ts +128 -0
  23. package/dist/ask-run/replay.js +212 -0
  24. package/dist/ask-run/run-ask-eval.d.ts +125 -0
  25. package/dist/ask-run/run-ask-eval.js +193 -0
  26. package/dist/ask-run/seed-golden-graph.d.ts +64 -0
  27. package/dist/ask-run/seed-golden-graph.js +495 -0
  28. package/dist/cli/index.d.ts +3 -0
  29. package/dist/cli/index.js +12 -0
  30. package/dist/cli/kg-command.d.ts +66 -0
  31. package/dist/cli/kg-command.js +238 -0
  32. package/dist/cli/main.d.ts +18 -0
  33. package/dist/cli/main.js +69 -0
  34. package/dist/fixtures/domains.d.ts +16 -0
  35. package/dist/fixtures/domains.js +33 -0
  36. package/dist/fixtures/fixture-schema.d.ts +323 -0
  37. package/dist/fixtures/fixture-schema.js +199 -0
  38. package/dist/fixtures/index.d.ts +16 -0
  39. package/dist/fixtures/index.js +40 -0
  40. package/dist/fixtures/load.d.ts +73 -0
  41. package/dist/fixtures/load.js +137 -0
  42. package/dist/fixtures/questions.d.ts +15 -0
  43. package/dist/fixtures/questions.js +26 -0
  44. package/dist/index.d.ts +20 -0
  45. package/dist/index.js +36 -0
  46. package/dist/kg/gold-runner.d.ts +13 -0
  47. package/dist/kg/gold-runner.js +57 -0
  48. package/dist/kg/index.d.ts +17 -0
  49. package/dist/kg/index.js +65 -0
  50. package/dist/kg/internals.d.ts +7 -0
  51. package/dist/kg/internals.js +17 -0
  52. package/dist/kg/prediction-schema.d.ts +245 -0
  53. package/dist/kg/prediction-schema.js +102 -0
  54. package/dist/kg/predictions.d.ts +11 -0
  55. package/dist/kg/predictions.js +49 -0
  56. package/dist/kg/report.d.ts +84 -0
  57. package/dist/kg/report.js +125 -0
  58. package/dist/kg/run-kg-eval.d.ts +77 -0
  59. package/dist/kg/run-kg-eval.js +137 -0
  60. package/dist/kg/runner.d.ts +72 -0
  61. package/dist/kg/runner.js +51 -0
  62. package/dist/kg/runners/extract-resolve-runner.d.ts +40 -0
  63. package/dist/kg/runners/extract-resolve-runner.js +199 -0
  64. package/dist/kg/runners/extract-runner.d.ts +65 -0
  65. package/dist/kg/runners/extract-runner.js +243 -0
  66. package/dist/kg/scorer.d.ts +226 -0
  67. package/dist/kg/scorer.js +463 -0
  68. package/dist/kg/targets.d.ts +17 -0
  69. package/dist/kg/targets.js +16 -0
  70. package/dist/kg/text.d.ts +45 -0
  71. package/dist/kg/text.js +100 -0
  72. package/dist/live/adapters.d.ts +16 -0
  73. package/dist/live/adapters.js +58 -0
  74. package/dist/live/env.d.ts +39 -0
  75. package/dist/live/env.js +56 -0
  76. package/dist/live/index.d.ts +6 -0
  77. package/dist/live/index.js +16 -0
  78. package/dist/live/live-ai.d.ts +104 -0
  79. package/dist/live/live-ai.js +157 -0
  80. package/dist/parity/constants.d.ts +79 -0
  81. package/dist/parity/constants.js +104 -0
  82. package/dist/parity/index.d.ts +20 -0
  83. package/dist/parity/index.js +38 -0
  84. package/dist/parity/internals.d.ts +8 -0
  85. package/dist/parity/internals.js +16 -0
  86. package/dist/parity/scenario.d.ts +45 -0
  87. package/dist/parity/scenario.js +245 -0
  88. package/dist/parity/script.d.ts +44 -0
  89. package/dist/parity/script.js +136 -0
  90. package/dist/parity/snapshot.d.ts +43 -0
  91. package/dist/parity/snapshot.js +71 -0
  92. package/dist/real-data/index.d.ts +2 -0
  93. package/dist/real-data/index.js +12 -0
  94. package/dist/real-data/real-data.d.ts +76 -0
  95. package/dist/real-data/real-data.js +156 -0
  96. package/fixtures/kg-golden/README.md +136 -0
  97. package/fixtures/kg-golden/ask-questions.json +458 -0
  98. package/fixtures/kg-golden/meetings/m01-northwind-pilot-kickoff.json +792 -0
  99. package/fixtures/kg-golden/meetings/m02-halden-migration-planning.json +814 -0
  100. package/fixtures/kg-golden/meetings/m03-larkspur-weekly-sync.json +601 -0
  101. package/fixtures/kg-golden/meetings/m04-corvid-intake-discovery.json +690 -0
  102. package/fixtures/kg-golden/meetings/m05-hosting-vendor-selection.json +631 -0
  103. package/fixtures/kg-golden/meetings/m06-northwind-floor-data-review.json +649 -0
  104. package/fixtures/kg-golden/meetings/m07-gullwing-intro-notes.json +428 -0
  105. package/fixtures/kg-golden/meetings/m08-halden-migration-checkpoint.json +672 -0
  106. package/fixtures/kg-golden/meetings/m09-northwind-platform-org-update.json +711 -0
  107. package/fixtures/kg-golden/meetings/m10-corvid-prototype-review.json +623 -0
  108. package/fixtures/kg-golden/meetings/m11-solvane-grid-dashboard-scoping.json +689 -0
  109. package/fixtures/kg-golden/meetings/m12-northwind-pilot-replan.json +681 -0
  110. package/fixtures/kg-golden/meetings/m13-halden-cutover-go-no-go.json +721 -0
  111. package/fixtures/kg-golden/meetings/m14-gullwing-discovery-readout.json +719 -0
  112. package/fixtures/kg-golden/meetings/m15-halden-handover-ravi-leaving.json +716 -0
  113. package/fixtures/kg-golden/meetings/m16-varden-claims-portal-intro.json +704 -0
  114. package/fixtures/kg-golden/meetings/m17-corvid-usability-debrief.json +572 -0
  115. package/fixtures/kg-golden/meetings/m18-hosting-decision-revisited.json +655 -0
  116. package/fixtures/kg-golden/meetings/m19-solvane-integration-kickoff.json +726 -0
  117. package/fixtures/kg-golden/meetings/m20-northwind-go-live-retro.json +673 -0
  118. package/fixtures/kg-golden/meetings/m21-quarterly-account-review.json +449 -0
  119. package/fixtures/kg-golden/meetings/m22-halden-intro-call-2020.json +558 -0
  120. package/fixtures/kg-golden/meetings/m23-gullwing-model-review.json +702 -0
  121. package/fixtures/kg-golden/meetings/m24-varden-discovery-midpoint.json +643 -0
  122. package/fixtures/kg-golden/meetings/m25-corvid-rollout-planning.json +642 -0
  123. package/fixtures/kg-golden/meetings/m26-larkspur-engineering-prep.json +695 -0
  124. package/fixtures/kg-golden/meetings/m27-solvane-phase-one-demo.json +649 -0
  125. package/fixtures/kg-golden/meetings/m28-northwind-building-5-scoping.json +715 -0
  126. package/fixtures/kg-golden/meetings/m29-halden-southern-cutover-review.json +752 -0
  127. package/fixtures/kg-golden/meetings/m30-varden-portal-build-kickoff.json +697 -0
  128. package/fixtures/kg-golden/meetings/m31-gullwing-rollout-renewal.json +681 -0
  129. package/fixtures/kg-golden/meetings/m32-brambleway-weekly-sync.json +472 -0
  130. package/fixtures/kg-golden/meetings/m33-nina-oliver-one-on-one.json +342 -0
  131. package/fixtures/kg-golden/meetings/m34-coffee-with-dana.json +249 -0
  132. package/fixtures/kg-golden/meetings/m35-brambleway-june-sync.json +553 -0
  133. package/fixtures/kg-golden/meetings/m36-copenhagen-conference-planning.json +296 -0
  134. package/host/generated/client.d.ts +1 -0
  135. package/host/generated/client.js +5 -0
  136. package/host/generated/default.d.ts +1 -0
  137. package/host/generated/default.js +5 -0
  138. package/host/generated/edge.d.ts +1 -0
  139. package/host/generated/edge.js +1658 -0
  140. package/host/generated/index-browser.js +1684 -0
  141. package/host/generated/index.d.ts +192335 -0
  142. package/host/generated/index.js +1658 -0
  143. package/host/generated/package.json +139 -0
  144. package/host/generated/query_compiler_fast_bg.js +2 -0
  145. package/host/generated/query_compiler_fast_bg.wasm +0 -0
  146. package/host/generated/query_compiler_fast_bg.wasm-base64.js +2 -0
  147. package/host/generated/runtime/client.d.ts +3433 -0
  148. package/host/generated/runtime/client.js +110 -0
  149. package/host/generated/runtime/index-browser.d.ts +90 -0
  150. package/host/generated/runtime/index-browser.js +6 -0
  151. package/host/generated/runtime/wasm-compiler-edge.js +100 -0
  152. package/host/generated/schema.prisma +6312 -0
  153. package/host/generated/wasm-edge-light-loader.mjs +5 -0
  154. package/host/generated/wasm-worker-loader.mjs +5 -0
  155. package/host/prisma/fragments/kvox.ask.prisma +126 -0
  156. package/host/prisma/fragments/kvox.graph.prisma +1073 -0
  157. package/host/prisma/fragments/kvox.notes.prisma +787 -0
  158. package/host/prisma/fragments/kvox.search.prisma +211 -0
  159. package/host/prisma/fragments/kvox.transcripts.prisma +790 -0
  160. package/host/prisma/kvox.lock +101 -0
  161. package/host/prisma/migrations/20240101000000_initial/migration.sql +297 -0
  162. package/host/prisma/migrations/20240101000001_add_personal_access_tokens/migration.sql +31 -0
  163. package/host/prisma/migrations/20240101000002_add_credentials/migration.sql +20 -0
  164. package/host/prisma/migrations/20240101000003_add_notification_deliveries/migration.sql +27 -0
  165. package/host/prisma/migrations/20240101000004_drop_stale_uuid_defaults/migration.sql +35 -0
  166. package/host/prisma/migrations/20240101000005_add_notifications/migration.sql +22 -0
  167. package/host/prisma/migrations/20240101000006_add_push_subscriptions/migration.sql +25 -0
  168. package/host/prisma/migrations/20240101000007_add_jobs/migration.sql +110 -0
  169. package/host/prisma/migrations/20240101000008_add_worker_nodes/migration.sql +90 -0
  170. package/host/prisma/migrations/20240101000009_add_database_backup_runs/migration.sql +104 -0
  171. package/host/prisma/migrations/20240101000010_add_notification_broadcasts/migration.sql +57 -0
  172. package/host/prisma/migrations/20240101000011_add_backup_run_job_link/migration.sql +87 -0
  173. package/host/prisma/migrations/20240101000012_add_job_node_secrets/migration.sql +61 -0
  174. package/host/prisma/migrations/20240101000013_add_backup_run_pg_dump_version/migration.sql +26 -0
  175. package/host/prisma/migrations/20240101000014_add_job_claim_token/migration.sql +92 -0
  176. package/host/prisma/migrations/20240101000015_add_ai_platform/migration.sql +108 -0
  177. package/host/prisma/migrations/20240101000016_revoke_viewer_ai_use/migration.sql +32 -0
  178. package/host/prisma/migrations/20240101000017_add_user_credentials/migration.sql +29 -0
  179. package/host/prisma/migrations/20240101000018_add_device_session_credential_link/migration.sql +52 -0
  180. package/host/prisma/migrations/20240101000019_add_worker_node_vitals/migration.sql +3 -0
  181. package/host/prisma/migrations/20240101000020_add_job_trace_context/migration.sql +6 -0
  182. package/host/prisma/migrations/20240101000021_add_retention_created_at_indexes/migration.sql +13 -0
  183. package/host/prisma/migrations/20240101000022_add_organizations/migration.sql +142 -0
  184. package/host/prisma/migrations/20240101000023_split_system_org_roles/migration.sql +131 -0
  185. package/host/prisma/migrations/20240101000024_org_scoped_rls/migration.sql +215 -0
  186. package/host/prisma/migrations/20240101000025_add_groups/migration.sql +165 -0
  187. package/host/prisma/migrations/20240101000026_add_grants/migration.sql +117 -0
  188. package/host/prisma/migrations/20240101000027_add_org_settings/migration.sql +49 -0
  189. package/host/prisma/migrations/20240101000028_add_org_credentials/migration.sql +54 -0
  190. package/host/prisma/migrations/20240101000029_add_jobs_org_id/migration.sql +18 -0
  191. package/host/prisma/migrations/20240101000030_add_jobs_org_id_status_index/migration.sql +6 -0
  192. package/host/prisma/migrations/20240101000031_add_broadcast_target_org/migration.sql +21 -0
  193. package/host/prisma/migrations/20240101000032_add_android_app/migration.sql +60 -0
  194. package/host/prisma/migrations/20240101000033_open_job_reason/migration.sql +16 -0
  195. package/host/prisma/migrations/20240101000034_ai_usage_feature/migration.sql +37 -0
  196. package/host/prisma/migrations/20240101000035_add_app_metadata/migration.sql +49 -0
  197. package/host/prisma/migrations/20240101000036_open_sharing_vocabularies/migration.sql +97 -0
  198. package/host/prisma/migrations/20260914130000_kvox_add_transcripts/migration.sql +322 -0
  199. package/host/prisma/migrations/20260914140000_kvox_add_notes/migration.sql +311 -0
  200. package/host/prisma/migrations/20260915120000_kvox_add_search_vectors/migration.sql +150 -0
  201. package/host/prisma/migrations/20260915130000_kvox_add_search_embeddings/migration.sql +362 -0
  202. package/host/prisma/migrations/20260915210000_kvox_add_note_title_source/migration.sql +30 -0
  203. package/host/prisma/migrations/20260923120000_kvox_add_note_generation_context_snapshot/migration.sql +24 -0
  204. package/host/prisma/migrations/20260923130000_kvox_add_user_hidden_note_templates/migration.sql +35 -0
  205. package/host/prisma/migrations/20260923140000_kvox_add_transcript_speaker_identities/migration.sql +6 -0
  206. package/host/prisma/migrations/20260923150000_kvox_transcript_name_checks/migration.sql +95 -0
  207. package/host/prisma/migrations/20260923160000_kvox_add_note_body_format/migration.sql +27 -0
  208. package/host/prisma/migrations/20260923170000_kvox_add_note_version_body_format/migration.sql +23 -0
  209. package/host/prisma/migrations/20260926012548_kvox_add_knowledge_graph/migration.sql +680 -0
  210. package/host/prisma/migrations/20260926030000_kvox_fix_kg_relations_valid_precision_chk/migration.sql +29 -0
  211. package/host/prisma/migrations/20260926030100_kvox_add_transcript_recorded_at/migration.sql +9 -0
  212. package/host/prisma/migrations/20260926030200_kvox_kg_evidence_invariant/migration.sql +60 -0
  213. package/host/prisma/migrations/20260926040000_kvox_add_kg_graph_layouts/migration.sql +30 -0
  214. package/host/prisma/migrations/20260926050000_kvox_add_ask_conversations/migration.sql +99 -0
  215. package/host/prisma/migrations/20260926231512_kvox_add_kg_exports/migration.sql +52 -0
  216. package/host/prisma/migrations/20261016120000_kvox_transcripts_org_id/migration.sql +49 -0
  217. package/host/prisma/platform.lock +319 -0
  218. package/host/prisma/schema/app.kvox.ask.prisma +110 -0
  219. package/host/prisma/schema/app.kvox.graph.prisma +1030 -0
  220. package/host/prisma/schema/app.kvox.notes.prisma +746 -0
  221. package/host/prisma/schema/app.kvox.search.prisma +208 -0
  222. package/host/prisma/schema/app.kvox.transcripts.prisma +726 -0
  223. package/host/prisma/schema/platform.ai.prisma +419 -0
  224. package/host/prisma/schema/platform.android-app.prisma +46 -0
  225. package/host/prisma/schema/platform.base.prisma +15 -0
  226. package/host/prisma/schema/platform.credentials.prisma +156 -0
  227. package/host/prisma/schema/platform.db-backup.prisma +359 -0
  228. package/host/prisma/schema/platform.identity.prisma +638 -0
  229. package/host/prisma/schema/platform.jobs.prisma +824 -0
  230. package/host/prisma/schema/platform.notifications.prisma +641 -0
  231. package/host/prisma/schema/platform.settings.prisma +53 -0
  232. package/host/prisma/schema/platform.sharing.prisma +208 -0
  233. package/host/prisma/schema/platform.storage.prisma +118 -0
  234. package/package.json +112 -1
  235. package/parity/requests.ask.json +2681 -0
  236. package/parity/requests.m01.json +1554 -0
  237. package/parity/requests.m02.json +1554 -0
  238. package/parity/requests.m03.json +1554 -0
  239. package/parity/requests.m04.json +1554 -0
  240. package/parity/requests.m05.json +1554 -0
  241. package/parity/requests.m06.json +1554 -0
  242. package/parity/requests.m07.json +1554 -0
  243. package/parity/requests.m08.json +1554 -0
  244. package/parity/requests.m09.json +1554 -0
  245. package/parity/requests.m10.json +1554 -0
@@ -0,0 +1,77 @@
1
+ import type { KvoxAiPort } from '@marinoscar/kvox-api/ports';
2
+ import { type KgEvalPrediction } from './prediction-schema.js';
3
+ import { type KgEvalReport } from './report.js';
4
+ /**
5
+ * What {@link runKgEval} is asked to do.
6
+ *
7
+ * @stability experimental
8
+ */
9
+ export interface RunKgEvalOptions {
10
+ /**
11
+ * Where predictions come from: `gold` (the default when no `predictionsDir` is
12
+ * given), or a registered live runner (`extract`, `extract-resolve` /
13
+ * `extract+resolve`, or a test's own), which needs `ai` and `model`.
14
+ */
15
+ runner?: string;
16
+ /** Score the prediction files of this directory instead of running anything. */
17
+ predictionsDir?: string;
18
+ /** The model port a live runner calls. Never needed for `gold` or `predictionsDir`. */
19
+ ai?: KvoxAiPort;
20
+ /** The model a live runner targets (required for one). */
21
+ model?: string;
22
+ /** The provider a live runner targets. Default `openai`. */
23
+ provider?: string;
24
+ /** Fixture ids to keep (`--only`); omitted or empty keeps all. */
25
+ fixtures?: readonly string[];
26
+ /** A tag every kept fixture carries (`--tag`). */
27
+ tag?: string;
28
+ /** Throw {@link KgEvalTargetsError} when a §6 target fails. Default `false` (report only). */
29
+ enforce?: boolean;
30
+ /** The directory the golden set is read from. Default the committed synthetic set. */
31
+ fixturesDir?: string;
32
+ /** Called with every prediction a live runner produced, in fixture order (the CLI writes it to `--out`). */
33
+ onPrediction?: (fixtureId: string, prediction: KgEvalPrediction) => void | Promise<void>;
34
+ /** Called for every fixture a `predictionsDir` has no file for (scored as empty). */
35
+ onMissingPrediction?: (fixtureId: string, dir: string) => void;
36
+ }
37
+ /**
38
+ * A run asked to enforce the §6 targets missed one. Carries the full report.
39
+ *
40
+ * @stability experimental
41
+ */
42
+ export declare class KgEvalTargetsError extends Error {
43
+ readonly report: KgEvalReport;
44
+ /**
45
+ * @param report - the run's report (`targetsMet` is `false`).
46
+ */
47
+ constructor(report: KgEvalReport);
48
+ }
49
+ /**
50
+ * A run that cannot start: no runner of that name, a live runner without a model
51
+ * or a port, both a runner and a predictions directory, an empty selection. The
52
+ * CLI maps it to exit code 2.
53
+ *
54
+ * @stability experimental
55
+ */
56
+ export declare class KgEvalUsageError extends Error {
57
+ }
58
+ /**
59
+ * Runs one knowledge-graph evaluation and returns its report.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * const report = await runKgEval({ runner: 'gold' });
64
+ * report.targetsMet; // true: the self-test scores 1.000 everywhere
65
+ *
66
+ * const live = await runKgEval({ runner: 'extract', ai, model: 'gpt-5-mini', fixtures: ['m01'] });
67
+ * ```
68
+ *
69
+ * @param opts - what to score and how.
70
+ * @returns the report (`formatReport` prints it).
71
+ * @throws {@link KgEvalUsageError} for a run that cannot start; `KgEvalLoadError`
72
+ * for a golden set or prediction file that does not load; {@link KgEvalTargetsError}
73
+ * with `enforce` when a target fails. A live call's failure is the port's
74
+ * `KvoxAiError`, which carries no key.
75
+ * @stability experimental
76
+ */
77
+ export declare function runKgEval(opts?: RunKgEvalOptions): Promise<KgEvalReport>;
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ // =============================================================================
3
+ // runKgEval: one knowledge-graph evaluation run, start to report (issue #580)
4
+ // =============================================================================
5
+ //
6
+ // The one code path behind `kvox-eval kg`, `npm run kg:eval` and a host that
7
+ // calls the package directly. Three ways to get the predictions it scores:
8
+ //
9
+ // gold synthesised from the labels (`goldPrediction`): the
10
+ // harness's self-test, 1.000 everywhere or a bug;
11
+ // predictionsDir `<dir>/<fixtureId>.json` written by an earlier run (a
12
+ // missing file is scored as empty, and reported);
13
+ // a live runner `extract` / `extract+resolve` over the `ai` port, one
14
+ // structured call per fixture.
15
+ //
16
+ // PURE OF ENVIRONMENT: nothing here reads `process.env`, prints, or writes a
17
+ // file. A live run is handed a `KvoxAiPort` (the CLI builds one with
18
+ // `createLiveKvoxAi`, which owns the key); the hooks tell the caller about each
19
+ // prediction and each missing file, so the CLI can persist and print them.
20
+ // =============================================================================
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.KgEvalUsageError = exports.KgEvalTargetsError = void 0;
23
+ exports.runKgEval = runKgEval;
24
+ const index_js_1 = require("../fixtures/index.js");
25
+ const gold_runner_js_1 = require("./gold-runner.js");
26
+ const prediction_schema_js_1 = require("./prediction-schema.js");
27
+ const predictions_js_1 = require("./predictions.js");
28
+ const report_js_1 = require("./report.js");
29
+ const runner_js_1 = require("./runner.js");
30
+ const scorer_js_1 = require("./scorer.js");
31
+ /**
32
+ * A run asked to enforce the §6 targets missed one. Carries the full report.
33
+ *
34
+ * @stability experimental
35
+ */
36
+ class KgEvalTargetsError extends Error {
37
+ report;
38
+ /**
39
+ * @param report - the run's report (`targetsMet` is `false`).
40
+ */
41
+ constructor(report) {
42
+ super('one or more §6 targets failed (--enforce)');
43
+ this.report = report;
44
+ }
45
+ }
46
+ exports.KgEvalTargetsError = KgEvalTargetsError;
47
+ /**
48
+ * A run that cannot start: no runner of that name, a live runner without a model
49
+ * or a port, both a runner and a predictions directory, an empty selection. The
50
+ * CLI maps it to exit code 2.
51
+ *
52
+ * @stability experimental
53
+ */
54
+ class KgEvalUsageError extends Error {
55
+ }
56
+ exports.KgEvalUsageError = KgEvalUsageError;
57
+ /**
58
+ * Runs one knowledge-graph evaluation and returns its report.
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * const report = await runKgEval({ runner: 'gold' });
63
+ * report.targetsMet; // true: the self-test scores 1.000 everywhere
64
+ *
65
+ * const live = await runKgEval({ runner: 'extract', ai, model: 'gpt-5-mini', fixtures: ['m01'] });
66
+ * ```
67
+ *
68
+ * @param opts - what to score and how.
69
+ * @returns the report (`formatReport` prints it).
70
+ * @throws {@link KgEvalUsageError} for a run that cannot start; `KgEvalLoadError`
71
+ * for a golden set or prediction file that does not load; {@link KgEvalTargetsError}
72
+ * with `enforce` when a target fails. A live call's failure is the port's
73
+ * `KvoxAiError`, which carries no key.
74
+ * @stability experimental
75
+ */
76
+ async function runKgEval(opts = {}) {
77
+ const predictionsDir = opts.predictionsDir;
78
+ const runnerArg = opts.runner ?? (predictionsDir === undefined ? 'gold' : undefined);
79
+ if (predictionsDir !== undefined && runnerArg !== undefined) {
80
+ throw new KgEvalUsageError('pass either a predictions directory or a runner, not both');
81
+ }
82
+ // An unregistered runner is reported before anything is loaded.
83
+ const live = runnerArg !== undefined && runnerArg !== 'gold' ? (0, runner_js_1.findKgEvalRunner)(runnerArg) : null;
84
+ if (runnerArg !== undefined && runnerArg !== 'gold' && live === null) {
85
+ throw new KgEvalUsageError(`no runner '${runnerArg}' registered (known: ${Object.keys(runner_js_1.KG_EVAL_RUNNERS).join(', ')})`);
86
+ }
87
+ if (live !== null && !opts.model)
88
+ throw new KgEvalUsageError(`the '${live.name}' runner needs a model`);
89
+ if (live !== null && opts.ai === undefined)
90
+ throw new KgEvalUsageError(`the '${live.name}' runner needs a model port (ai)`);
91
+ const fixtures = selectedFixtures(opts);
92
+ const predictions = new Map();
93
+ let runnerLabel;
94
+ let model = null;
95
+ if (live !== null) {
96
+ model = opts.model;
97
+ const runner = await live.factory({ ai: opts.ai });
98
+ runnerLabel = runner.name;
99
+ for (const fixture of fixtures) {
100
+ const pred = prediction_schema_js_1.kgEvalPredictionSchema.parse(await runner.run(fixture, { model, ...(opts.provider !== undefined ? { provider: opts.provider } : {}) }));
101
+ predictions.set(fixture.id, pred);
102
+ await opts.onPrediction?.(fixture.id, pred);
103
+ }
104
+ }
105
+ else if (predictionsDir === undefined) {
106
+ runnerLabel = 'gold';
107
+ for (const f of fixtures)
108
+ predictions.set(f.id, (0, gold_runner_js_1.goldPrediction)(f));
109
+ }
110
+ else {
111
+ runnerLabel = 'predictions';
112
+ for (const f of fixtures) {
113
+ const pred = (0, predictions_js_1.loadPredictionFile)(predictionsDir, f.id);
114
+ if (pred === null)
115
+ opts.onMissingPrediction?.(f.id, predictionsDir);
116
+ predictions.set(f.id, pred ?? (0, prediction_schema_js_1.emptyPrediction)(f.id));
117
+ model ??= pred?.model ?? null;
118
+ }
119
+ }
120
+ const report = (0, report_js_1.buildReport)((0, scorer_js_1.scoreRun)(fixtures, predictions), {
121
+ runner: runnerLabel,
122
+ model,
123
+ fixtureIds: fixtures.map((f) => f.id),
124
+ });
125
+ if (opts.enforce && !report.targetsMet)
126
+ throw new KgEvalTargetsError(report);
127
+ return report;
128
+ }
129
+ /** The golden set narrowed by `fixtures` and `tag`; an empty selection is a usage error. */
130
+ function selectedFixtures(opts) {
131
+ const all = (0, index_js_1.loadGoldenSet)(opts.fixturesDir ?? index_js_1.GOLDEN_MEETINGS_DIR);
132
+ const only = opts.fixtures && opts.fixtures.length > 0 ? [...opts.fixtures] : null;
133
+ const selected = (0, index_js_1.selectFixtures)(all, only, opts.tag ?? null);
134
+ if (selected.length === 0)
135
+ throw new KgEvalUsageError('no fixtures selected');
136
+ return selected;
137
+ }
@@ -0,0 +1,72 @@
1
+ import type { KvoxAiPort } from '@marinoscar/kvox-api/ports';
2
+ import type { GoldenFixture } from '../fixtures/index.js';
3
+ import type { KgEvalPrediction } from './prediction-schema.js';
4
+ /**
5
+ * What one live run is made with.
6
+ *
7
+ * @stability experimental
8
+ */
9
+ export interface KgEvalRunOptions {
10
+ /** The provider's model id. */
11
+ model: string;
12
+ /** The provider id the call targets (`openai`, `openai-compatible`). Default `openai`. */
13
+ provider?: string;
14
+ }
15
+ /**
16
+ * What a runner factory is handed.
17
+ *
18
+ * @stability experimental
19
+ */
20
+ export interface KgEvalRunnerDeps {
21
+ /** The model port every structured call goes through. */
22
+ ai: KvoxAiPort;
23
+ }
24
+ /**
25
+ * Turns one golden fixture into one prediction.
26
+ *
27
+ * @extensionPoint
28
+ * @stability experimental
29
+ */
30
+ export interface KgEvalRunner {
31
+ /** `extract` (#363), `extract+resolve` (#364): the report's `runner` column. */
32
+ readonly name: string;
33
+ /**
34
+ * One fixture's prediction.
35
+ *
36
+ * @param fixture - the fixture.
37
+ * @param opts - the model (and provider) to run on.
38
+ * @returns the prediction (it carries `model`, never a key).
39
+ */
40
+ run(fixture: GoldenFixture, opts: KgEvalRunOptions): Promise<KgEvalPrediction>;
41
+ }
42
+ /**
43
+ * A lazy runner factory.
44
+ *
45
+ * @stability experimental
46
+ */
47
+ export type KgEvalRunnerFactory = (deps: KgEvalRunnerDeps) => Promise<KgEvalRunner>;
48
+ /**
49
+ * The registered runners, by name. Lazy factories, so a `--predictions` run never
50
+ * loads the extraction code. A test may add an entry (and delete it afterwards).
51
+ *
52
+ * @stability experimental
53
+ */
54
+ export declare const KG_EVAL_RUNNERS: Record<string, KgEvalRunnerFactory>;
55
+ /**
56
+ * Spellings a command line accepts for a registered runner (`extract-resolve`,
57
+ * a shell-friendly `extract+resolve`).
58
+ *
59
+ * @stability experimental
60
+ */
61
+ export declare const KG_EVAL_RUNNER_ALIASES: Readonly<Record<string, string>>;
62
+ /**
63
+ * The registered runner a name (or an alias) means, or `null`.
64
+ *
65
+ * @param name - a runner name or alias.
66
+ * @returns the factory and the registered name, or `null` when none is registered.
67
+ * @stability experimental
68
+ */
69
+ export declare function findKgEvalRunner(name: string): {
70
+ name: string;
71
+ factory: KgEvalRunnerFactory;
72
+ } | null;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ // =============================================================================
3
+ // The kg:eval runner seam (issue #362; #580 moved it onto the model port).
4
+ //
5
+ // A runner turns one fixture into one prediction. The extraction runner
6
+ // (`extract`) is kg.extract's own pipeline (#363); resolution extends it
7
+ // (`extract+resolve`, #364). A runner registers itself by adding an entry below
8
+ // from its own file (`kg/runners/*.ts`) — a lazy factory, so a `--predictions`
9
+ // run never loads the extraction code.
10
+ //
11
+ // #580: a runner is built over a `KvoxAiPort` (`createKvoxAi` of
12
+ // `@marinoscar/kvox-ai`, or a fake in a test) and never sees a key. Whoever
13
+ // builds the port owns the key (`live/`: the environment, never a flag); a
14
+ // prediction carries `model` alone.
15
+ // =============================================================================
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.KG_EVAL_RUNNER_ALIASES = exports.KG_EVAL_RUNNERS = void 0;
18
+ exports.findKgEvalRunner = findKgEvalRunner;
19
+ /**
20
+ * The registered runners, by name. Lazy factories, so a `--predictions` run never
21
+ * loads the extraction code. A test may add an entry (and delete it afterwards).
22
+ *
23
+ * @stability experimental
24
+ */
25
+ exports.KG_EVAL_RUNNERS = {
26
+ // `require`, not `import()`: under NodeNext a dynamic import stays a native
27
+ // ESM import, which cannot load a `.ts` file through ts-node or ts-jest.
28
+ extract: async (deps) => require('./runners/extract-runner.js').createExtractRunner(deps),
29
+ // #364: extraction, then in-memory resolution against `knownEntities`.
30
+ 'extract+resolve': async (deps) => require('./runners/extract-resolve-runner.js').createExtractResolveRunner(deps),
31
+ };
32
+ /**
33
+ * Spellings a command line accepts for a registered runner (`extract-resolve`,
34
+ * a shell-friendly `extract+resolve`).
35
+ *
36
+ * @stability experimental
37
+ */
38
+ exports.KG_EVAL_RUNNER_ALIASES = Object.freeze({ 'extract-resolve': 'extract+resolve' });
39
+ /**
40
+ * The registered runner a name (or an alias) means, or `null`.
41
+ *
42
+ * @param name - a runner name or alias.
43
+ * @returns the factory and the registered name, or `null` when none is registered.
44
+ * @stability experimental
45
+ */
46
+ function findKgEvalRunner(name) {
47
+ const registered = Object.prototype.hasOwnProperty.call(exports.KG_EVAL_RUNNER_ALIASES, name) ? exports.KG_EVAL_RUNNER_ALIASES[name] : name;
48
+ if (!Object.prototype.hasOwnProperty.call(exports.KG_EVAL_RUNNERS, registered))
49
+ return null;
50
+ return { name: registered, factory: exports.KG_EVAL_RUNNERS[registered] };
51
+ }
@@ -0,0 +1,40 @@
1
+ import type { ProposedRow } from '../internals.js';
2
+ import { type GraphPreferences } from '@marinoscar/kvox-api/graph';
3
+ import type { GoldenFixture } from '../../fixtures/index.js';
4
+ import type { KgEvalRunner, KgEvalRunnerDeps } from '../runner.js';
5
+ /**
6
+ * `pg_trgm`'s `similarity(a, b)`: shared trigrams over the union.
7
+ *
8
+ * @stability experimental
9
+ */
10
+ export declare function trigramSimilarity(a: string, b: string): number;
11
+ /**
12
+ * PURE. Resolve every proposed entity row (in place, on copies) against the
13
+ * fixture's known entities. The Meeting row and anything without a type match
14
+ * keep what extraction decided.
15
+ *
16
+ * @stability experimental
17
+ */
18
+ export declare function resolveRowsInMemory(fixture: GoldenFixture, rows: readonly ProposedRow[], prefs?: GraphPreferences): ProposedRow[];
19
+ /**
20
+ * PURE. #365's relation dedup and closing plan, in memory, against the
21
+ * fixture's prior edges: `known` rows flagged (and so pre-accepted), `overlaps`
22
+ * / `unordered` copied from #353's plan, and closings counted.
23
+ *
24
+ * @stability experimental
25
+ */
26
+ export declare function applyDedupStagesInMemory(fixture: GoldenFixture, rows: readonly ProposedRow[]): {
27
+ rows: ProposedRow[];
28
+ stats: {
29
+ known: number;
30
+ closings: number;
31
+ overlaps: number;
32
+ unordered: number;
33
+ };
34
+ };
35
+ /**
36
+ * The `extract+resolve` runner over `deps.ai`.
37
+ *
38
+ * @stability experimental
39
+ */
40
+ export declare function createExtractResolveRunner(deps: KgEvalRunnerDeps): KgEvalRunner;
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ // =============================================================================
3
+ // The `extract+resolve` kg:eval runner (#364; docs/specs/ontology.md §6, §7)
4
+ // =============================================================================
5
+ //
6
+ // `extract` (#363), then resolution of every proposed entity against the
7
+ // fixture's `knownEntities` — so auto-link PRECISION is measured, the number
8
+ // that gates any future lowering of the 0.90 default (#362's target).
9
+ //
10
+ // NO DATABASE: an in-memory implementation of the candidate arms feeds the
11
+ // production `score.ts` and `decide()`:
12
+ //
13
+ // A exact — `normalizeAlias` (#355) over label + aliases, as in SQL
14
+ // B trigram — a JS port of `pg_trgm`'s `similarity()` (lowercased words,
15
+ // padded " w ", trigram-set Jaccard), threshold 0.4
16
+ // C vector — skipped (no embeddings in an eval run)
17
+ //
18
+ // Context: `sameMeeting` for a known Person a fixture speaker is identified as
19
+ // (what #356 produces); the speaker shortcut links such a Person outright, as
20
+ // production does. Adjudication is OFF — the eval measures the deterministic
21
+ // bands; a middle-band row is `possible_duplicate` and never pre-checked.
22
+ //
23
+ // #365: after resolution, the pure cores of `work-item-dedup` (relations) and
24
+ // `temporal-closing` run against the fixture's `knownRelations` through #353's
25
+ // planner, so a restated edge is `known`, an overlap is flagged and a closing
26
+ // is counted (`stats.closings`) exactly as production would propose them.
27
+ // Item dedup needs an embedding and an adjudication call, neither of which an
28
+ // eval run makes; it is covered by the stage's own tests instead.
29
+ //
30
+ // ⚠ The runner never sees a key: the port it is handed owns it (#580).
31
+ // =============================================================================
32
+ Object.defineProperty(exports, "__esModule", { value: true });
33
+ exports.trigramSimilarity = trigramSimilarity;
34
+ exports.resolveRowsInMemory = resolveRowsInMemory;
35
+ exports.applyDedupStagesInMemory = applyDedupStagesInMemory;
36
+ exports.createExtractResolveRunner = createExtractResolveRunner;
37
+ const internals_js_1 = require("../internals.js");
38
+ const ontology_1 = require("@marinoscar/kvox-contract/ontology");
39
+ const graph_1 = require("@marinoscar/kvox-api/graph");
40
+ const index_js_1 = require("../../fixtures/index.js");
41
+ const extract_runner_js_1 = require("./extract-runner.js");
42
+ const TRIGRAM_THRESHOLD = 0.4;
43
+ function trigrams(text) {
44
+ const out = new Set();
45
+ for (const word of text.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter(Boolean)) {
46
+ const padded = ` ${word} `;
47
+ for (let i = 0; i + 3 <= padded.length; i += 1)
48
+ out.add(padded.slice(i, i + 3));
49
+ }
50
+ return out;
51
+ }
52
+ /**
53
+ * `pg_trgm`'s `similarity(a, b)`: shared trigrams over the union.
54
+ *
55
+ * @stability experimental
56
+ */
57
+ function trigramSimilarity(a, b) {
58
+ const x = trigrams(a);
59
+ const y = trigrams(b);
60
+ if (x.size === 0 || y.size === 0)
61
+ return 0;
62
+ let shared = 0;
63
+ for (const t of x)
64
+ if (y.has(t))
65
+ shared += 1;
66
+ return shared / (x.size + y.size - shared);
67
+ }
68
+ function safeNormalize(name) {
69
+ try {
70
+ return (0, graph_1.normalizeAlias)(name);
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ }
76
+ /**
77
+ * PURE. Resolve every proposed entity row (in place, on copies) against the
78
+ * fixture's known entities. The Meeting row and anything without a type match
79
+ * keep what extraction decided.
80
+ *
81
+ * @stability experimental
82
+ */
83
+ function resolveRowsInMemory(fixture, rows, prefs = graph_1.GRAPH_PREFERENCE_DEFAULTS) {
84
+ const input = (0, extract_runner_js_1.fixtureToInput)(fixture);
85
+ const speakerPersons = new Set(input.speakers.map((s) => s.personEntityId).filter((id) => !!id));
86
+ const personBySpeakerName = new Map(input.speakers.filter((s) => s.personEntityId && s.displayName).map((s) => [(0, internals_js_1.normalizeForMatch)(s.displayName), s.personEntityId]));
87
+ const known = fixture.knownEntities.map((k) => ({
88
+ ...k,
89
+ names: [k.label, ...k.aliases],
90
+ normalized: new Set([k.label, ...k.aliases].map(safeNormalize).filter((n) => n !== null)),
91
+ }));
92
+ return rows.map((row) => {
93
+ if (row.kind !== 'entity' || row.payload.ref === 'meeting' || row.resolution?.source === 'meeting')
94
+ return row;
95
+ const p = row.payload;
96
+ if (p.type === 'Person') {
97
+ const speakerPerson = [p.label, ...p.aliases].map((n) => personBySpeakerName.get((0, internals_js_1.normalizeForMatch)(n))).find(Boolean);
98
+ if (speakerPerson) {
99
+ return { ...row, resolution: { ref: speakerPerson, score: 1, source: 'speaker', candidates: [], adjudication: null } };
100
+ }
101
+ }
102
+ const mentionNames = [p.label, ...p.aliases].map(safeNormalize).filter((n) => n !== null);
103
+ const scored = known
104
+ .filter((k) => k.type === p.type)
105
+ .map((k) => {
106
+ const aliasExact = mentionNames.some((n) => k.normalized.has(n));
107
+ const best = Math.max(0, ...k.names.map((n) => trigramSimilarity(p.label, n)));
108
+ return {
109
+ entityId: k.id,
110
+ label: k.label,
111
+ type: k.type,
112
+ ...(0, internals_js_1.scoreCandidate)({
113
+ aliasExact,
114
+ trigram: best >= TRIGRAM_THRESHOLD ? best : null,
115
+ cosine: null,
116
+ sameMeeting: speakerPersons.has(k.id),
117
+ orgCoMention: false,
118
+ sharedNeighbour: false,
119
+ recent: false,
120
+ }),
121
+ };
122
+ })
123
+ .filter((c) => c.arm !== null);
124
+ const ranked = (0, internals_js_1.rankCandidates)(scored, prefs.resolution);
125
+ const decision = (0, internals_js_1.decide)({ candidates: ranked.candidates, ambiguous: ranked.ambiguous, band: (0, internals_js_1.bandFor)(ranked.candidates[0]?.score ?? null, prefs.resolution) }, prefs.resolution, null);
126
+ return { ...row, resolution: decision.resolution, flags: [...new Set([...row.flags, ...decision.flags])] };
127
+ });
128
+ }
129
+ /**
130
+ * PURE. #365's relation dedup and closing plan, in memory, against the
131
+ * fixture's prior edges: `known` rows flagged (and so pre-accepted), `overlaps`
132
+ * / `unordered` copied from #353's plan, and closings counted.
133
+ *
134
+ * @stability experimental
135
+ */
136
+ function applyDedupStagesInMemory(fixture, rows) {
137
+ const schema = (0, ontology_1.computeEffectiveSchema)({ enabledDomains: (0, index_js_1.fixtureDomains)(fixture), userAttributes: [] });
138
+ const prior = fixture.knownRelations.map((r) => {
139
+ const { range, precision } = (0, internals_js_1.proposedRelationRange)(r, 'state');
140
+ return { id: r.id, type: r.type, fromId: r.from, toId: r.to, props: r.props, valid: range, precision, reviewStatus: 'accepted' };
141
+ });
142
+ const entities = new Map();
143
+ for (const row of rows)
144
+ if (row.kind === 'entity')
145
+ entities.set(row.payload.ref, (0, internals_js_1.entityView)(row.payload, row.resolution));
146
+ const stats = { known: 0, closings: 0, overlaps: 0, unordered: 0 };
147
+ const closed = new Set();
148
+ const out = rows.map((row) => {
149
+ if (row.kind !== 'relation')
150
+ return row;
151
+ const p = row.payload;
152
+ const type = schema.relationType(p.type);
153
+ const fromId = (0, internals_js_1.existingId)((0, internals_js_1.resolveEndpoint)(p.from, entities));
154
+ if (!type || !fromId)
155
+ return row;
156
+ const rule = (0, internals_js_1.ruleForEffectiveRelation)(type);
157
+ const to = (0, internals_js_1.resolveEndpoint)(p.to, entities);
158
+ const toId = (0, internals_js_1.existingId)(to);
159
+ if (toId && (0, internals_js_1.relationKnown)(prior, p, fromId, toId, rule).known) {
160
+ stats.known += 1;
161
+ return { ...row, flags: [...new Set([...row.flags, 'known'])] };
162
+ }
163
+ if (!(0, internals_js_1.isExclusiveTemporal)(rule))
164
+ return row;
165
+ const plan = (0, graph_1.planTemporalInsert)(prior, (0, internals_js_1.candidateEdge)(p, fromId, (0, internals_js_1.placeholderId)(to), rule), rule);
166
+ if (plan.action !== 'create')
167
+ return row;
168
+ for (const c of plan.closes)
169
+ if (!closed.has(c.edgeId))
170
+ closed.add(c.edgeId);
171
+ const flags = plan.flags.filter((f) => f === 'overlaps' || f === 'unordered');
172
+ if (flags.includes('overlaps'))
173
+ stats.overlaps += 1;
174
+ if (flags.includes('unordered'))
175
+ stats.unordered += 1;
176
+ return flags.length > 0 ? { ...row, flags: [...new Set([...row.flags, ...flags])] } : row;
177
+ });
178
+ stats.closings = closed.size;
179
+ return { rows: out, stats };
180
+ }
181
+ /**
182
+ * The `extract+resolve` runner over `deps.ai`.
183
+ *
184
+ * @stability experimental
185
+ */
186
+ function createExtractResolveRunner(deps) {
187
+ return {
188
+ name: 'extract+resolve',
189
+ async run(fixture, opts) {
190
+ const extracted = await (0, extract_runner_js_1.runExtraction)(deps.ai, fixture, opts);
191
+ if (!extracted) {
192
+ return { fixtureId: fixture.id, model: opts.model, entities: [], relations: [], items: [], stats: { invalidOutput: 1 } };
193
+ }
194
+ const resolved = resolveRowsInMemory(fixture, extracted.rows);
195
+ const deduped = applyDedupStagesInMemory(fixture, resolved);
196
+ return (0, extract_runner_js_1.precheckToPrediction)(fixture.id, opts.model, deduped.rows, { ...extracted.stats, ...deduped.stats });
197
+ },
198
+ };
199
+ }
@@ -0,0 +1,65 @@
1
+ import { type ExtractionInput, type ProposedRow } from '../internals.js';
2
+ import type { KvoxAiPort } from '@marinoscar/kvox-api/ports';
3
+ import type { GoldenFixture } from '../../fixtures/index.js';
4
+ import type { KgEvalPrediction } from '../prediction-schema.js';
5
+ import type { KgEvalRunner, KgEvalRunnerDeps, KgEvalRunOptions } from '../runner.js';
6
+ /**
7
+ * The completion ceiling an eval run uses (a production run takes it from policy).
8
+ *
9
+ * @stability experimental
10
+ */
11
+ export declare const EVAL_MAX_OUTPUT_TOKENS = 16000;
12
+ /**
13
+ * How long one structured call may take before the run gives up on it.
14
+ *
15
+ * @stability experimental
16
+ */
17
+ export declare const EVAL_TIMEOUT_MS = 180000;
18
+ /**
19
+ * The context window an eval target reports (the port's target carries one; a direct runtime never reads it).
20
+ *
21
+ * @stability experimental
22
+ */
23
+ export declare const EVAL_CONTEXT_WINDOW_TOKENS = 128000;
24
+ /**
25
+ * The user id an eval call carries (there is no signed-in user).
26
+ *
27
+ * @stability experimental
28
+ */
29
+ export declare const EVAL_USER_ID = "kg-eval";
30
+ /**
31
+ * The one fixture → input mapping. Pure.
32
+ *
33
+ * @stability experimental
34
+ */
35
+ export declare function fixtureToInput(fixture: GoldenFixture): ExtractionInput;
36
+ /**
37
+ * Proposal rows (with their pre-check decisions) → a kg:eval prediction. Pure.
38
+ *
39
+ * @stability experimental
40
+ */
41
+ export declare function rowsToPrediction(fixtureId: string, model: string | null, rows: ProposedRow[], decisions: string[], stats: Record<string, number>): KgEvalPrediction;
42
+ /**
43
+ * The shared half of every runner: one `generateStructured` call and the
44
+ * validator, returning the proposal rows before any pre-check. `null` when the
45
+ * model's answer fails validation (`invalidOutput`). #364's `extract+resolve`
46
+ * runner resolves these rows before the pre-check runs.
47
+ *
48
+ * @stability experimental
49
+ */
50
+ export declare function runExtraction(ai: Pick<KvoxAiPort, 'generateStructured'>, fixture: GoldenFixture, opts: KgEvalRunOptions): Promise<{
51
+ rows: ProposedRow[];
52
+ stats: Record<string, number>;
53
+ } | null>;
54
+ /**
55
+ * Pre-check the rows with default preferences and turn them into a prediction.
56
+ *
57
+ * @stability experimental
58
+ */
59
+ export declare function precheckToPrediction(fixtureId: string, model: string, rows: ProposedRow[], stats: Record<string, number>): KgEvalPrediction;
60
+ /**
61
+ * The `extract` runner over `deps.ai`.
62
+ *
63
+ * @stability experimental
64
+ */
65
+ export declare function createExtractRunner(deps: KgEvalRunnerDeps): KgEvalRunner;