@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,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.repositoryRoots = exports.RealDataPathError = exports.REAL_DATA_REFUSAL = exports.nextRealFixtureId = exports.isInside = exports.canonicalPath = exports.assertOutsideRepo = void 0;
4
+ // The real-data slice's public surface (re-exported by the package root).
5
+ var real_data_js_1 = require("./real-data.js");
6
+ Object.defineProperty(exports, "assertOutsideRepo", { enumerable: true, get: function () { return real_data_js_1.assertOutsideRepo; } });
7
+ Object.defineProperty(exports, "canonicalPath", { enumerable: true, get: function () { return real_data_js_1.canonicalPath; } });
8
+ Object.defineProperty(exports, "isInside", { enumerable: true, get: function () { return real_data_js_1.isInside; } });
9
+ Object.defineProperty(exports, "nextRealFixtureId", { enumerable: true, get: function () { return real_data_js_1.nextRealFixtureId; } });
10
+ Object.defineProperty(exports, "REAL_DATA_REFUSAL", { enumerable: true, get: function () { return real_data_js_1.REAL_DATA_REFUSAL; } });
11
+ Object.defineProperty(exports, "RealDataPathError", { enumerable: true, get: function () { return real_data_js_1.RealDataPathError; } });
12
+ Object.defineProperty(exports, "repositoryRoots", { enumerable: true, get: function () { return real_data_js_1.repositoryRoots; } });
@@ -0,0 +1,76 @@
1
+ /**
2
+ * The refusal every real-data path guard prints (exit code 3).
3
+ *
4
+ * @stability experimental
5
+ */
6
+ export declare const REAL_DATA_REFUSAL = "real meeting data must never be written inside the repository";
7
+ /**
8
+ * A real-data path inside the repository: refused, exit code 3.
9
+ *
10
+ * @stability experimental
11
+ */
12
+ export declare class RealDataPathError extends Error {
13
+ readonly path: string;
14
+ /**
15
+ * @param path - the refused path, canonicalized.
16
+ */
17
+ constructor(path: string);
18
+ }
19
+ /**
20
+ * Absolute, with symlinks resolved on the longest prefix that exists.
21
+ *
22
+ * @param p - a path, relative to the working directory or absolute.
23
+ * @returns the canonical path.
24
+ * @stability experimental
25
+ */
26
+ export declare function canonicalPath(p: string): string;
27
+ /**
28
+ * Whether `child` is `parent` or below it (both already canonical).
29
+ *
30
+ * @param child - the candidate path.
31
+ * @param parent - the directory.
32
+ * @returns `true` when inside.
33
+ * @stability experimental
34
+ */
35
+ export declare function isInside(child: string, parent: string): boolean;
36
+ /**
37
+ * The repository root(s): git's answer from this file's folder and from the
38
+ * working directory, plus the package's own grandparent as a fallback (the
39
+ * monorepo root when the package is not installed from the registry).
40
+ *
41
+ * @returns canonical roots, deduplicated.
42
+ * @stability experimental
43
+ */
44
+ export declare function repositoryRoots(): string[];
45
+ /**
46
+ * What {@link assertOutsideRepo} may let through.
47
+ *
48
+ * @stability experimental
49
+ */
50
+ export interface AssertOutsideRepoOptions {
51
+ /**
52
+ * A directory inside the repository a path may still be under: the caller's
53
+ * git-ignored scratch directory. Pass it ONLY for output of a run over the
54
+ * committed synthetic set.
55
+ */
56
+ allowInside?: string | null;
57
+ }
58
+ /**
59
+ * Refuses a path inside the repository (symlinks resolved).
60
+ *
61
+ * @param p - the path a real-data run would read or write.
62
+ * @param opts - the one directory that may be let through.
63
+ * @returns the canonical path.
64
+ * @throws {@link RealDataPathError} when it is inside the repository.
65
+ * @stability experimental
66
+ */
67
+ export declare function assertOutsideRepo(p: string, opts?: AssertOutsideRepoOptions): string;
68
+ /**
69
+ * The next free `m9NN` id in a real directory (real ids never collide with the
70
+ * committed m01…).
71
+ *
72
+ * @param realDir - the developer's real-data directory.
73
+ * @returns an id such as `m901`.
74
+ * @stability experimental
75
+ */
76
+ export declare function nextRealFixtureId(realDir: string): string;
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ // =============================================================================
3
+ // The real-data path guard (issue #362; moved into the package by #580).
4
+ //
5
+ // Real meetings are private conversations — there is no `transcripts:read_any`
6
+ // for exactly that reason — so nothing from a run over them may ever land
7
+ // inside the repository. The one security control is `assertOutsideRepo`:
8
+ // every path a real-data run writes to or reads a real set from is resolved
9
+ // (symlinks included) and refused when it falls inside the git work tree. The
10
+ // single exception is a scratch directory the CALLER names (`allowInside`;
11
+ // the web app passes its git-ignored `apps/api/.kg-eval/`), and only for runs
12
+ // over the committed SYNTHETIC set.
13
+ //
14
+ // PURE of the database: exporting a real note as a skeleton reads the app's
15
+ // own tables and stays in the app (`apps/api/scripts/kg-eval/real-data.ts`).
16
+ // =============================================================================
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.RealDataPathError = exports.REAL_DATA_REFUSAL = void 0;
19
+ exports.canonicalPath = canonicalPath;
20
+ exports.isInside = isInside;
21
+ exports.repositoryRoots = repositoryRoots;
22
+ exports.assertOutsideRepo = assertOutsideRepo;
23
+ exports.nextRealFixtureId = nextRealFixtureId;
24
+ const child_process_1 = require("child_process");
25
+ const fs_1 = require("fs");
26
+ const path_1 = require("path");
27
+ /**
28
+ * The refusal every real-data path guard prints (exit code 3).
29
+ *
30
+ * @stability experimental
31
+ */
32
+ exports.REAL_DATA_REFUSAL = 'real meeting data must never be written inside the repository';
33
+ /**
34
+ * A real-data path inside the repository: refused, exit code 3.
35
+ *
36
+ * @stability experimental
37
+ */
38
+ class RealDataPathError extends Error {
39
+ path;
40
+ /**
41
+ * @param path - the refused path, canonicalized.
42
+ */
43
+ constructor(path) {
44
+ super(`${exports.REAL_DATA_REFUSAL}: ${path}`);
45
+ this.path = path;
46
+ }
47
+ }
48
+ exports.RealDataPathError = RealDataPathError;
49
+ /**
50
+ * Absolute, with symlinks resolved on the longest prefix that exists.
51
+ *
52
+ * @param p - a path, relative to the working directory or absolute.
53
+ * @returns the canonical path.
54
+ * @stability experimental
55
+ */
56
+ function canonicalPath(p) {
57
+ const abs = (0, path_1.resolve)(p);
58
+ let existing = abs;
59
+ const rest = [];
60
+ while (!(0, fs_1.existsSync)(existing)) {
61
+ const parent = (0, path_1.dirname)(existing);
62
+ if (parent === existing)
63
+ break;
64
+ rest.unshift((0, path_1.basename)(existing));
65
+ existing = parent;
66
+ }
67
+ let real = existing;
68
+ try {
69
+ real = (0, fs_1.realpathSync)(existing);
70
+ }
71
+ catch {
72
+ // keep the unresolved prefix
73
+ }
74
+ return rest.length > 0 ? (0, path_1.join)(real, ...rest) : real;
75
+ }
76
+ /**
77
+ * Whether `child` is `parent` or below it (both already canonical).
78
+ *
79
+ * @param child - the candidate path.
80
+ * @param parent - the directory.
81
+ * @returns `true` when inside.
82
+ * @stability experimental
83
+ */
84
+ function isInside(child, parent) {
85
+ const rel = (0, path_1.relative)(parent, child);
86
+ return rel === '' || (!rel.startsWith('..') && !(0, path_1.isAbsolute)(rel));
87
+ }
88
+ /**
89
+ * The repository root(s): git's answer from this file's folder and from the
90
+ * working directory, plus the package's own grandparent as a fallback (the
91
+ * monorepo root when the package is not installed from the registry).
92
+ *
93
+ * @returns canonical roots, deduplicated.
94
+ * @stability experimental
95
+ */
96
+ function repositoryRoots() {
97
+ const roots = new Set();
98
+ // src/real-data (or dist/real-data) → package → packages → <root>
99
+ roots.add(canonicalPath((0, path_1.resolve)(__dirname, '..', '..', '..', '..')));
100
+ for (const cwd of [__dirname, process.cwd()]) {
101
+ try {
102
+ const top = (0, child_process_1.execFileSync)('git', ['rev-parse', '--show-toplevel'], {
103
+ cwd,
104
+ encoding: 'utf8',
105
+ stdio: ['ignore', 'pipe', 'ignore'],
106
+ }).trim();
107
+ if (top)
108
+ roots.add(canonicalPath(top));
109
+ }
110
+ catch {
111
+ // Not a git checkout (or no git binary): the fallback above still applies.
112
+ }
113
+ }
114
+ return [...roots];
115
+ }
116
+ /**
117
+ * Refuses a path inside the repository (symlinks resolved).
118
+ *
119
+ * @param p - the path a real-data run would read or write.
120
+ * @param opts - the one directory that may be let through.
121
+ * @returns the canonical path.
122
+ * @throws {@link RealDataPathError} when it is inside the repository.
123
+ * @stability experimental
124
+ */
125
+ function assertOutsideRepo(p, opts = {}) {
126
+ const abs = canonicalPath(p);
127
+ if (opts.allowInside && isInside(abs, canonicalPath(opts.allowInside)))
128
+ return abs;
129
+ for (const root of repositoryRoots()) {
130
+ if (isInside(abs, root))
131
+ throw new RealDataPathError(abs);
132
+ }
133
+ return abs;
134
+ }
135
+ /**
136
+ * The next free `m9NN` id in a real directory (real ids never collide with the
137
+ * committed m01…).
138
+ *
139
+ * @param realDir - the developer's real-data directory.
140
+ * @returns an id such as `m901`.
141
+ * @stability experimental
142
+ */
143
+ function nextRealFixtureId(realDir) {
144
+ const used = new Set();
145
+ if ((0, fs_1.existsSync)(realDir)) {
146
+ for (const f of (0, fs_1.readdirSync)(realDir)) {
147
+ const m = /^m(\d{2,3})/.exec(f);
148
+ if (m)
149
+ used.add(Number(m[1]));
150
+ }
151
+ }
152
+ let n = 901;
153
+ while (used.has(n))
154
+ n += 1;
155
+ return `m${n}`;
156
+ }
@@ -0,0 +1,136 @@
1
+ # Knowledge-graph golden set
2
+
3
+ The labelled meetings that `kg.extract` (and later `kg.resolve`) are measured
4
+ against — `docs/specs/ontology.md` §6, issue #362. Shipped in
5
+ `@marinoscar/kvox-eval` (#580, `@marinoscar/kvox-eval/fixtures`); scored by
6
+ `kvox-eval kg` (or `npm run kg:eval --workspace=api`); validated by
7
+ `packages/kvox-eval/test/kg-golden-fixtures.spec.ts`, which asserts every rule
8
+ on this page.
9
+
10
+ ## Synthetic only — the one rule that is never relaxed
11
+
12
+ Every meeting here is **invented**. No real recording, transcript, note, name,
13
+ company, email address or phone number belongs in this directory, anonymised or
14
+ not: speech re-identifies people (voices, employers, events), and a private
15
+ conversation is exactly what this product never exposes to anyone else. Names
16
+ and organisations are made up (Larkspur Labs, Northwind Robotics, Halden
17
+ Freight, …); an email address, if one is ever needed, uses `@example.com`; the
18
+ product's own name never appears. The fixture test enforces the email, phone
19
+ and product-name rules with regexes.
20
+
21
+ To evaluate against **your own** real notes, use the local, opt-in mode:
22
+
23
+ ```bash
24
+ # Export one of your notes as an UNLABELLED skeleton (read-only; your note only)
25
+ npm run kg:eval --workspace=api -- --real-dir ~/kg-real --export-note <noteId> --user <you@…>
26
+ # Label it by hand in ~/kg-real, then score a run against it
27
+ npm run kg:eval --workspace=api -- --real-dir ~/kg-real --predictions <dir>
28
+ ```
29
+
30
+ `--real-dir`, `--out` and `--export-note` refuse (exit 3) any path inside the
31
+ git work tree, symlinks included. `KG_EVAL_REAL_DIR` may stand in for
32
+ `--real-dir`. Nothing from a real run is ever collected or committed.
33
+
34
+ ## File format
35
+
36
+ One JSON file per meeting: `meetings/mNN-<slug>.json`, where `NN` is the
37
+ fixture `id` (`m01`…). The contract is `goldenFixtureSchema` in
38
+ `packages/kvox-eval/src/fixtures/fixture-schema.ts`; in outline:
39
+
40
+ | Field | Meaning |
41
+ |---|---|
42
+ | `id`, `title`, `tags` | Identity and scenario tags (see coverage below). |
43
+ | `recordedAt` | The meeting date — every relative date ("next Tuesday", "in three weeks") resolves against it (§5.4). |
44
+ | `contextText` | What the user typed into the note's Context field, or `null`. |
45
+ | `hasTranscript` | `false` for a note-only meeting: no `speakers`, no `segments`, and every citation is `source: "note"`. |
46
+ | `speakers`, `segments` | Diarized speakers and their lines. Segment ids are `<id>-sNNN`, unique across the set, sorted and non-overlapping. 20–120 segments per transcript. |
47
+ | `note.body` | The generated note, written the way `note.generate` writes one: `# Title`, a `**Date:**` and an `**Attendees:**` line, then sections. 200–700 words. |
48
+ | `knownEntities` | The graph as it stood **before** this meeting (ids like `g-person-sarah-chen`), with aliases and the earlier fixtures each attended. What resolution may link to. |
49
+ | `labels.entities` | Gold `Person` / `Organization` / `Project` / `Meeting` rows. `key` is local to the file; `existingId` says which known entity the mention must link to. Every fixture labels its own `Meeting` (key `meeting`). |
50
+ | `labels.relations` | Gold edges, using only the ontology's extractable relation types. `from`/`to` are keys or known ids. Temporal types carry `validFrom`/`validTo`/`precision` per §5.4 (half-open; month/year bounds on the first of the unit; `unknown` means both bounds `null`). Non-temporal ones are `unknown` with `null` bounds. |
51
+ | `labels.items` | Gold `commitment` / `decision` / `claim` / `person_fact`. `owner` and `counterparty` are the `ASSIGNED_TO`/`OWED_TO` columns; `status` only on commitments; `sensitivity` only on person facts. `supersedesLabel` names an earlier item as `<fixtureId>#<kind>-<n>` (`n` = 1-based position among that fixture's items of that kind), e.g. `m01#claim-1`. |
52
+ | `labels.negatives` | Text a correct extractor must **not** turn into a row (§5.1), each with why. |
53
+
54
+ Every label carries `evidence`: `{ source: "segment", segmentId, quote }` or
55
+ `{ source: "note", quote }`. A quote must appear **verbatim** (after whitespace
56
+ collapse) in that segment or in the note body. Every type key must exist in the
57
+ ontology registry's `core ∪ work` schema — or, for a fixture tagged
58
+ `personal`, `core ∪ work ∪ personal` (#383: the story of a user who turned the
59
+ `personal` domain on; `packages/kvox-eval/src/fixtures/domains.ts`) — and every
60
+ endpoint must satisfy its relation's `from`/`to` lists — both are read from
61
+ `@marinoscar/kvox-contract/ontology`, never from a list in the test. A personal type in an
62
+ untagged fixture fails the test: the untagged set is what proves a user who
63
+ never enables `personal` is offered none of it.
64
+
65
+ ## Adding a fixture
66
+
67
+ 1. Pick the next free id and write `meetings/mNN-<slug>.json`. Keep it
68
+ plausible: a real meeting's texture, distinct content, invented people.
69
+ 2. Reuse the existing cast where the story continues (the `g-…` ids in other
70
+ files' `knownEntities`), so resolution traps stay meaningful.
71
+ 3. Label what a careful human reviewer would accept, and nothing else. When in
72
+ doubt, prefer `unknown` precision to a guessed date, and a negative example
73
+ to a force-fitted commitment.
74
+ 4. Run `npm run test:run -w @marinoscar/kvox-eval -- kg-golden-fixtures` and
75
+ `npm run kg:eval --workspace=api -- --predictions gold` (or
76
+ `kvox-eval kg --predictions gold`), which must print 1.000 everywhere.
77
+
78
+ ## Coverage the set must keep (asserted by the fixture test)
79
+
80
+ - ≥ 30 fixtures; ≥ 10 gold instances of each entity type (Person, Organization,
81
+ Project, Meeting); ≥ 15 of each item kind; ≥ 3 of every extractable relation
82
+ type and of each item-column relation (owner, counterparty, supersedes …);
83
+ ≥ 10 labels with `existingId`.
84
+ - Temporal (§5.4): a promotion (`HAS_ROLE` change, tag `promotion`), a manager
85
+ change (`REPORTS_TO`, tag `manager-change`), a company change with an open
86
+ commitment owned by the leaver (`company-change`), an out-of-order 2020
87
+ meeting arriving after 2026 ones (`out-of-order`), an "in 2026" year-precision
88
+ fact, relative dates resolved against `recordedAt` (`relative-date`), and
89
+ ≥ 3 `unknown`-precision facts.
90
+ - §5.1 negatives, each in `labels.negatives`: a role ("the CIO",
91
+ `negative-role`), "whoever's on call" (`negative-on-call`), a team mentioned
92
+ in passing (`negative-passing-team`), a recurring topic that is not a
93
+ Project (`negative-topic`), "we should probably look into that"
94
+ (`negative-vague-task`).
95
+ - `PersonFact` at all three sensitivity levels, ≥ 3 `sensitive`.
96
+ - Resolution traps: two different Sarahs at different organisations
97
+ (`two-sarahs`), a misspelling ("Sara Chen", `misspelling`), a nickname
98
+ matching a known alias ("JJ", `nickname`), an abbreviation ("NWR" /
99
+ "Northwind Robotics", `abbreviation`).
100
+ - Supersedes chains: a decision reversed in a later fixture, and "the pilot
101
+ moved to Q2" after "the pilot is scheduled for Q1".
102
+ - ≥ 2 note-only meetings (`note-only`).
103
+ - Personal domain (#383), in fixtures tagged `personal` (≥ 5): every
104
+ `personal` type and relation labelled at least once — a spouse, parents and
105
+ children, a friendship, a trip with dates, a birthday `Milestone` — a known
106
+ symmetric relation restated the other way round (it must dedup to the one
107
+ stored edge), and a work trip that must not become a `Trip`
108
+ (`negative-work-trip`, in `labels.negatives`).
109
+
110
+ ## The Ask evaluation's question file (issue #382, epic #348)
111
+
112
+ `ask-questions.json` (beside this README) is a **separate** golden set, over
113
+ the **same** meetings: ≥ 40 hand-written questions with expectations, scored
114
+ against the Ask agent (#377/#378) rather than against extraction. It is
115
+ validated by `packages/kvox-eval/test/ask-eval-questions.spec.ts`, scored by
116
+ `kvox-eval ask` (headless; `npm run ask:eval --workspace=api` is a wrapper), and its schema lives in
117
+ `packages/kvox-eval/src/ask/question-schema.ts`. See that file's own comments
118
+ for the full contract (`category`, `expected.{entities,answerAll,answerNone,
119
+ citeFrom,notFound}`); the short version:
120
+
121
+ - `citeFrom` names a segment id **exactly as this set's own `mNN-sNNN` ids
122
+ read** (e.g. `"m01-s009"`), or `"mNN#note"` for a meeting's note — never a
123
+ new naming scheme.
124
+ - A question's `id` (`q01`, `q02`, …) is **permanent** once committed, for the
125
+ identical reason a fixture's `id` is: a report stays comparable run over
126
+ run. Retire a question by noting it here, never by renumbering.
127
+ - The seeder (`seedGoldenGraph` in `packages/kvox-eval/src/ask-run/seed-golden-graph.ts`) always loads **every**
128
+ fixture in this directory and writes the meetings' hand LABELS (never a
129
+ model's extraction) as the graph the agent is asked about — so a question's
130
+ `fixtures` field is provenance for a reviewer, not a scoping instruction.
131
+ - Adding a fixture here (a new meeting) is safe and additive: it does not
132
+ break an existing question's `citeFrom`/entity expectations, because those
133
+ reference specific ids this set already has. Adding a QUESTION instead
134
+ requires only that its `citeFrom`/`entities` name real ids/labels somewhere
135
+ in this directory — `ask-eval-questions.spec.ts` checks that referential
136
+ integrity on every run.