@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,243 @@
1
+ "use strict";
2
+ // =============================================================================
3
+ // The `extract` kg:eval runner (#363; docs/specs/ontology.md §6)
4
+ // =============================================================================
5
+ //
6
+ // Runs `kg.extract`'s own pure pipeline against one golden fixture, with NO
7
+ // database: fixture → `ExtractionInput` → `buildExtractionContext` →
8
+ // `assembleExtractionPrompt` + `buildExtractionOutputSchema` → ONE
9
+ // `KvoxAiPort.generateStructured` call (`createKvoxAi` over the provider
10
+ // adapters for a live run, a fake in a test) → `validateExtraction` → the deterministic Meeting
11
+ // and ATTENDED rows → `applyPrecheck` (default preferences) → a prediction.
12
+ //
13
+ // It is the production code path minus the loader and the writer, so a score
14
+ // measures the prompt, the schema and the validator the product ships.
15
+ //
16
+ // A fixture's speaker is treated as IDENTIFIED_AS the known Person whose label
17
+ // or alias is its display name — what #356's speaker naming produces — so the
18
+ // known-entity priority and the ATTENDED rows behave as they would in the app.
19
+ // The golden set labels its own Meeting entity (key `meeting`); the runner
20
+ // emits the deterministic Meeting row under the same ref.
21
+ //
22
+ // ⚠ The runner never sees a key: the port it is handed owns it (#580). A
23
+ // prediction carries `model` alone.
24
+ // =============================================================================
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.EVAL_USER_ID = exports.EVAL_CONTEXT_WINDOW_TOKENS = exports.EVAL_TIMEOUT_MS = exports.EVAL_MAX_OUTPUT_TOKENS = void 0;
27
+ exports.fixtureToInput = fixtureToInput;
28
+ exports.rowsToPrediction = rowsToPrediction;
29
+ exports.runExtraction = runExtraction;
30
+ exports.precheckToPrediction = precheckToPrediction;
31
+ exports.createExtractRunner = createExtractRunner;
32
+ const ontology_1 = require("@marinoscar/kvox-contract/ontology");
33
+ const zod_1 = require("zod");
34
+ const internals_js_1 = require("../internals.js");
35
+ const graph_extraction_1 = require("@marinoscar/kvox-api/graph-extraction");
36
+ const graph_1 = require("@marinoscar/kvox-api/graph");
37
+ const index_js_1 = require("../../fixtures/index.js");
38
+ /**
39
+ * The completion ceiling an eval run uses (a production run takes it from policy).
40
+ *
41
+ * @stability experimental
42
+ */
43
+ exports.EVAL_MAX_OUTPUT_TOKENS = 16_000;
44
+ /**
45
+ * How long one structured call may take before the run gives up on it.
46
+ *
47
+ * @stability experimental
48
+ */
49
+ exports.EVAL_TIMEOUT_MS = 180_000;
50
+ /**
51
+ * The context window an eval target reports (the port's target carries one; a direct runtime never reads it).
52
+ *
53
+ * @stability experimental
54
+ */
55
+ exports.EVAL_CONTEXT_WINDOW_TOKENS = 128_000;
56
+ /**
57
+ * The user id an eval call carries (there is no signed-in user).
58
+ *
59
+ * @stability experimental
60
+ */
61
+ exports.EVAL_USER_ID = 'kg-eval';
62
+ /**
63
+ * The one fixture → input mapping. Pure.
64
+ *
65
+ * @stability experimental
66
+ */
67
+ function fixtureToInput(fixture) {
68
+ const recordedAt = new Date(fixture.recordedAt);
69
+ const known = fixture.knownEntities.map((k) => ({
70
+ id: k.id,
71
+ type: k.type,
72
+ label: k.label,
73
+ aliases: [...k.aliases],
74
+ reviewStatus: 'accepted',
75
+ mergedIntoId: null,
76
+ orgLabel: null,
77
+ }));
78
+ const personFor = (name) => {
79
+ if (!name)
80
+ return null;
81
+ const n = (0, internals_js_1.normalizeForMatch)(name);
82
+ const hit = known.find((k) => k.type === 'Person' && [k.label, ...k.aliases].some((a) => (0, internals_js_1.normalizeForMatch)(a) === n));
83
+ return hit?.id ?? null;
84
+ };
85
+ const speakers = fixture.hasTranscript
86
+ ? fixture.speakers.map((s) => ({ id: s.id, label: s.label, displayName: s.displayName, personEntityId: personFor(s.displayName) }))
87
+ : [];
88
+ const linked = new Set(speakers.map((s) => s.personEntityId).filter((id) => id !== null));
89
+ return {
90
+ note: {
91
+ id: `${fixture.id}-note`,
92
+ title: fixture.title,
93
+ bodyAtVersion: fixture.note.body,
94
+ version: fixture.note.version,
95
+ contextText: fixture.contextText,
96
+ createdAt: recordedAt,
97
+ },
98
+ transcript: fixture.hasTranscript
99
+ ? { id: `${fixture.id}-transcript`, title: fixture.title, recordedAt, createdAt: recordedAt }
100
+ : null,
101
+ segments: fixture.hasTranscript
102
+ ? fixture.segments.map((s) => ({ id: s.id, rev: s.rev, startMs: s.startMs, endMs: s.endMs, speakerId: s.speakerId, text: s.text }))
103
+ : [],
104
+ speakers,
105
+ effectiveSchema: (0, ontology_1.computeEffectiveSchema)({ enabledDomains: (0, index_js_1.fixtureDomains)(fixture), userAttributes: [] }),
106
+ guidance: null,
107
+ knownEntityCandidates: {
108
+ pinned: [],
109
+ speakerPersons: known.filter((k) => linked.has(k.id)),
110
+ organizations: [],
111
+ contextPool: known,
112
+ recentlyMentioned: known,
113
+ },
114
+ existingMeeting: null,
115
+ };
116
+ }
117
+ const endpoint = (ref) => (ref === null ? null : 'entityId' in ref ? ref.entityId : ref.ref);
118
+ const evidenceOf = (row) => row.evidence.map((e) => e.source === 'segment'
119
+ ? { source: 'segment', segmentId: e.segmentId, quote: e.quote }
120
+ : { source: 'note', segmentId: null, quote: e.quote });
121
+ /**
122
+ * Proposal rows (with their pre-check decisions) → a kg:eval prediction. Pure.
123
+ *
124
+ * @stability experimental
125
+ */
126
+ function rowsToPrediction(fixtureId, model, rows, decisions, stats) {
127
+ const prediction = { fixtureId, model, entities: [], relations: [], items: [], stats };
128
+ rows.forEach((row, i) => {
129
+ const prechecked = decisions[i] === 'accept';
130
+ if (row.kind === 'entity') {
131
+ const linked = row.resolution?.ref ?? null;
132
+ prediction.entities.push({
133
+ ref: row.payload.ref,
134
+ type: row.payload.type,
135
+ label: row.payload.label,
136
+ aliases: [...row.payload.aliases],
137
+ resolution: linked
138
+ ? { outcome: 'linked', entityId: linked, score: row.resolution?.score ?? null, prechecked }
139
+ : { outcome: 'new', entityId: null, score: null, prechecked },
140
+ evidence: evidenceOf(row),
141
+ });
142
+ }
143
+ else if (row.kind === 'relation') {
144
+ prediction.relations.push({
145
+ type: row.payload.type,
146
+ from: endpoint(row.payload.from),
147
+ to: endpoint(row.payload.to),
148
+ validFrom: row.payload.validFrom,
149
+ validTo: row.payload.validTo,
150
+ precision: row.payload.precision,
151
+ evidence: evidenceOf(row),
152
+ });
153
+ }
154
+ else {
155
+ prediction.items.push({
156
+ kind: row.payload.kind,
157
+ subject: endpoint(row.payload.subject) ?? '',
158
+ owner: endpoint(row.payload.owner),
159
+ counterparty: endpoint(row.payload.counterparty),
160
+ title: row.payload.title,
161
+ statement: row.payload.statement,
162
+ occurredAt: row.payload.occurredAt,
163
+ dueAt: row.payload.dueAt,
164
+ sensitivity: row.payload.sensitivity,
165
+ evidence: evidenceOf(row),
166
+ });
167
+ }
168
+ });
169
+ return prediction;
170
+ }
171
+ /**
172
+ * The shared half of every runner: one `generateStructured` call and the
173
+ * validator, returning the proposal rows before any pre-check. `null` when the
174
+ * model's answer fails validation (`invalidOutput`). #364's `extract+resolve`
175
+ * runner resolves these rows before the pre-check runs.
176
+ *
177
+ * @stability experimental
178
+ */
179
+ async function runExtraction(ai, fixture, opts) {
180
+ const ctx = (0, internals_js_1.buildExtractionContext)(fixtureToInput(fixture));
181
+ // The row caps a production run at this ceiling would send (#435).
182
+ const caps = (0, internals_js_1.extractionRowCaps)(exports.EVAL_MAX_OUTPUT_TOKENS, 'none');
183
+ const prompt = (0, internals_js_1.assembleExtractionPrompt)(ctx, caps);
184
+ const schema = (0, internals_js_1.buildExtractionOutputSchema)(ctx, caps);
185
+ // `schema` is the pass-through validator: `validateExtraction` below is the
186
+ // product's own validation, exactly as in the `kg.extract` handler.
187
+ const result = await ai.generateStructured({ userId: exports.EVAL_USER_ID, orgId: null, feature: 'graph.extract', signal: AbortSignal.timeout(exports.EVAL_TIMEOUT_MS) }, {
188
+ target: {
189
+ provider: opts.provider ?? 'openai',
190
+ model: opts.model,
191
+ contextWindowTokens: exports.EVAL_CONTEXT_WINDOW_TOKENS,
192
+ maxOutputTokens: exports.EVAL_MAX_OUTPUT_TOKENS,
193
+ source: 'requested',
194
+ },
195
+ system: prompt.systemPrompt,
196
+ user: prompt.userContent,
197
+ schemaName: internals_js_1.EXTRACTION_SCHEMA_NAME,
198
+ schema: zod_1.z.unknown(),
199
+ jsonSchema: schema,
200
+ maxOutputTokens: exports.EVAL_MAX_OUTPUT_TOKENS,
201
+ });
202
+ const validated = (0, internals_js_1.validateExtraction)(result.value, ctx);
203
+ if (!validated.ok)
204
+ return null;
205
+ const final = (0, internals_js_1.addDeterministicRows)(ctx, validated);
206
+ return { rows: final.rows, stats: { ...final.stats.dropped, quoteNotLocated: final.stats.quoteNotLocated } };
207
+ }
208
+ const ALL_DOMAINS_REVIEW_ONLY = (0, graph_extraction_1.reviewOnlyTypes)((0, ontology_1.computeEffectiveSchema)({ enabledDomains: ['core', 'work', 'personal'], userAttributes: [] }));
209
+ /**
210
+ * Pre-check the rows with default preferences and turn them into a prediction.
211
+ *
212
+ * @stability experimental
213
+ */
214
+ function precheckToPrediction(fixtureId, model, rows, stats) {
215
+ const precheck = rows.map((row) => ({
216
+ kind: row.kind,
217
+ payload: row.payload,
218
+ resolution: row.resolution,
219
+ flags: row.flags,
220
+ decision: 'pending',
221
+ }));
222
+ // Every domain's review-only types: a type a fixture's domains do not
223
+ // include can never have been proposed, so listing it changes nothing.
224
+ (0, graph_extraction_1.applyPrecheck)(precheck, graph_1.GRAPH_PREFERENCE_DEFAULTS, { reviewOnlyTypes: ALL_DOMAINS_REVIEW_ONLY });
225
+ return rowsToPrediction(fixtureId, model, rows, precheck.map((p) => p.decision), stats);
226
+ }
227
+ /**
228
+ * The `extract` runner over `deps.ai`.
229
+ *
230
+ * @stability experimental
231
+ */
232
+ function createExtractRunner(deps) {
233
+ return {
234
+ name: 'extract',
235
+ async run(fixture, opts) {
236
+ const extracted = await runExtraction(deps.ai, fixture, opts);
237
+ if (!extracted) {
238
+ return { fixtureId: fixture.id, model: opts.model, entities: [], relations: [], items: [], stats: { invalidOutput: 1 } };
239
+ }
240
+ return precheckToPrediction(fixture.id, opts.model, extracted.rows, extracted.stats);
241
+ },
242
+ };
243
+ }
@@ -0,0 +1,226 @@
1
+ import type { GoldenFixture, ItemLabelKind, ValidPrecisionLabel } from '../fixtures/index.js';
2
+ import type { KgEvalPrediction } from './prediction-schema.js';
3
+ export { normalizeName } from './text.js';
4
+ /**
5
+ * The token-set Jaccard a predicted label needs against a gold name to be a match candidate.
6
+ *
7
+ * @stability experimental
8
+ */
9
+ export declare const ENTITY_MATCH_JACCARD = 0.8;
10
+ /**
11
+ * The token-set F1 a predicted item statement needs against the gold statement.
12
+ *
13
+ * @stability experimental
14
+ */
15
+ export declare const ITEM_STATEMENT_F1 = 0.5;
16
+ /**
17
+ * Report rows, fixed order. Relation rows (`relation:<TYPE>`) follow, sorted.
18
+ *
19
+ * @stability experimental
20
+ */
21
+ export declare const ENTITY_REPORT_TYPES: readonly ["Person", "Organization", "Project", "Meeting", "Interest", "Trip", "Milestone"];
22
+ /**
23
+ * The report row of each item kind.
24
+ *
25
+ * @stability experimental
26
+ */
27
+ export declare const ITEM_REPORT_TYPES: Record<ItemLabelKind, string>;
28
+ /**
29
+ * Every fixed report row: the entity types, then the item kinds.
30
+ *
31
+ * @stability experimental
32
+ */
33
+ export declare const BASE_REPORT_TYPES: string[];
34
+ /**
35
+ * True positives, false positives and false negatives of one report row.
36
+ *
37
+ * @stability experimental
38
+ */
39
+ export interface Counts {
40
+ tp: number;
41
+ fp: number;
42
+ fn: number;
43
+ }
44
+ /**
45
+ * One fixture's score: counts per type, entity coverage, auto-link precision, evidence
46
+ * validity, temporal accuracy and the prediction's dropped counts.
47
+ *
48
+ * @stability experimental
49
+ */
50
+ export interface FixtureScore {
51
+ fixtureId: string;
52
+ types: Record<string, Counts>;
53
+ coverage: {
54
+ matched: number;
55
+ total: number;
56
+ };
57
+ /** `anyResolution`: at least one prediction carried a resolution at all. */
58
+ autoLink: {
59
+ correct: number;
60
+ total: number;
61
+ anyResolution: boolean;
62
+ };
63
+ evidence: {
64
+ valid: number;
65
+ total: number;
66
+ };
67
+ temporal: {
68
+ accurate: number;
69
+ total: number;
70
+ };
71
+ stats: Record<string, number>;
72
+ }
73
+ /**
74
+ * A run's score: the fixtures' scores summed, plus each fixture's own.
75
+ *
76
+ * @stability experimental
77
+ */
78
+ export interface RunScore {
79
+ fixtures: number;
80
+ types: Record<string, Counts>;
81
+ coverage: {
82
+ matched: number;
83
+ total: number;
84
+ };
85
+ autoLink: {
86
+ correct: number;
87
+ total: number;
88
+ anyResolution: boolean;
89
+ };
90
+ evidence: {
91
+ valid: number;
92
+ total: number;
93
+ };
94
+ temporal: {
95
+ accurate: number;
96
+ total: number;
97
+ };
98
+ stats: Record<string, number>;
99
+ perFixture: FixtureScore[];
100
+ }
101
+ interface Named {
102
+ type: string;
103
+ names: Set<string>;
104
+ tokenSets: Set<string>[];
105
+ }
106
+ /**
107
+ * Similarity of one predicted label to one gold name set; 0 when not a candidate.
108
+ *
109
+ * @stability experimental
110
+ */
111
+ export declare function nameSimilarity(predLabel: string, gold: Pick<Named, 'names' | 'tokenSets'>): number;
112
+ /**
113
+ * The one-to-one assignment of predicted to gold entities (greedy by descending similarity).
114
+ *
115
+ * @param gold - the gold entities (label and aliases).
116
+ * @param preds - the predicted entities.
117
+ * @param opts - `typed`: candidates must share a type (entity coverage drops the check).
118
+ * @returns predicted index to gold index.
119
+ *
120
+ * @stability experimental
121
+ */
122
+ export declare function matchEntities(gold: ReadonlyArray<{
123
+ type: string;
124
+ label: string;
125
+ aliases: readonly string[];
126
+ }>, preds: ReadonlyArray<{
127
+ type: string;
128
+ label: string;
129
+ }>, opts: {
130
+ typed: boolean;
131
+ }): Map<number, number>;
132
+ /**
133
+ * Whether two temporal ranges are equal at the gold precision (`unknown` matches only `unknown`).
134
+ *
135
+ * @param gold - the gold bounds and precision.
136
+ * @param pred - the predicted bounds and precision.
137
+ * @returns `true` when equal.
138
+ *
139
+ * @stability experimental
140
+ */
141
+ export declare function temporalEqual(gold: {
142
+ validFrom: string | null;
143
+ validTo: string | null;
144
+ precision: ValidPrecisionLabel;
145
+ }, pred: {
146
+ validFrom: string | null;
147
+ validTo: string | null;
148
+ precision: ValidPrecisionLabel;
149
+ }): boolean;
150
+ /**
151
+ * Scores one fixture's prediction. Pure and deterministic.
152
+ *
153
+ * @param fixture - the fixture and its labels.
154
+ * @param prediction - what a run predicted for it.
155
+ * @returns the fixture's score.
156
+ *
157
+ * @stability experimental
158
+ */
159
+ export declare function scoreFixture(fixture: GoldenFixture, prediction: KgEvalPrediction): FixtureScore;
160
+ /**
161
+ * Scores every fixture of a run (a fixture with no prediction scores as empty).
162
+ *
163
+ * @param fixtures - the fixtures.
164
+ * @param predictions - the predictions by fixture id.
165
+ * @returns the run's score.
166
+ *
167
+ * @stability experimental
168
+ */
169
+ export declare function scoreRun(fixtures: readonly GoldenFixture[], predictions: ReadonlyMap<string, KgEvalPrediction>): RunScore;
170
+ /**
171
+ * `num / den`, or `null` (printed `n/a`) when `den` is 0.
172
+ *
173
+ * @stability experimental
174
+ */
175
+ export declare const ratio: (num: number, den: number) => number | null;
176
+ /**
177
+ * Precision of one row, or `null` with nothing predicted.
178
+ *
179
+ * @param c - the row's counts.
180
+ * @returns the ratio or `null`.
181
+ *
182
+ * @stability experimental
183
+ */
184
+ export declare function precisionOf(c: Counts): number | null;
185
+ /**
186
+ * Recall of one row, or `null` with nothing labelled.
187
+ *
188
+ * @param c - the row's counts.
189
+ * @returns the ratio or `null`.
190
+ *
191
+ * @stability experimental
192
+ */
193
+ export declare function recallOf(c: Counts): number | null;
194
+ /**
195
+ * F1 of one row, or `null` when precision or recall is.
196
+ *
197
+ * @param c - the row's counts.
198
+ * @returns the ratio or `null`.
199
+ *
200
+ * @stability experimental
201
+ */
202
+ export declare function f1Of(c: Counts): number | null;
203
+ /**
204
+ * Gold entities matched by any prediction, type ignored, over all gold entities (the §6 entity-coverage target).
205
+ *
206
+ * @param run - the run's coverage counts.
207
+ * @returns the ratio or `null`.
208
+ *
209
+ * @stability experimental
210
+ */
211
+ export declare function entityCoverage(run: Pick<RunScore, 'coverage'>): number | null;
212
+ /**
213
+ * Recall of the Commitment row (the §6 commitment-recall target).
214
+ *
215
+ * @param run - the run's per-type counts.
216
+ * @returns the ratio or `null`.
217
+ *
218
+ * @stability experimental
219
+ */
220
+ export declare function commitmentRecall(run: Pick<RunScore, 'types'>): number | null;
221
+ /**
222
+ * `null` (printed `n/a`) when no prediction carries a resolution, or none was a prechecked link.
223
+ *
224
+ * @stability experimental
225
+ */
226
+ export declare function autoLinkPrecision(run: Pick<RunScore, 'autoLink'>): number | null;