@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,238 @@
1
+ "use strict";
2
+ // =============================================================================
3
+ // `kvox-eval kg` — score knowledge-graph extraction against the golden set
4
+ // (issue #362; the package command since #580)
5
+ // =============================================================================
6
+ //
7
+ // kvox-eval kg --predictions gold
8
+ // kvox-eval kg --predictions <dir> [--only m01,m07] [--tag promotion]
9
+ // kvox-eval kg --runner extract --provider openai --model <id> [--out <dir>]
10
+ // kvox-eval kg --runner extract --provider openai-compatible --base-url <url> --model <id>
11
+ // kvox-eval kg --real-dir <dir outside the repo> --predictions <dir>
12
+ //
13
+ // Flags: --json <file> also writes the report as JSON; --enforce exits 1 when a
14
+ // §6 target (docs/specs/ontology.md) fails — for local use, CI reports only.
15
+ // `--run` is accepted for `--runner` (the web app's `npm run kg:eval` spelling).
16
+ //
17
+ // Exit codes: 0 ok · 1 --enforce and a target failed · 2 usage/runner/load
18
+ // error (a refused provider and a failed live call included) · 3 a real-data
19
+ // path inside the repository (refused).
20
+ //
21
+ // The API key for a live runner comes from KVOX_EVAL_OPENAI_API_KEY only
22
+ // (KG_EVAL_OPENAI_API_KEY and ASK_EVAL_OPENAI_API_KEY for one more release),
23
+ // never a flag, and is never printed or written anywhere. A failed live call
24
+ // is reported by its error class, code and HTTP status only.
25
+ //
26
+ // `runKgCommand` takes its output streams and environment as arguments, so a
27
+ // test (and the web app's thin `scripts/kg-eval.ts` wrapper) drives it in
28
+ // process.
29
+ // =============================================================================
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ exports.KG_COMMAND_USAGE = exports.KG_EVAL_EXIT = void 0;
32
+ exports.runKgCommand = runKgCommand;
33
+ const fs_1 = require("fs");
34
+ const os_1 = require("os");
35
+ const path_1 = require("path");
36
+ const util_1 = require("util");
37
+ const ports_1 = require("@marinoscar/kvox-api/ports");
38
+ const index_js_1 = require("../fixtures/index.js");
39
+ const index_js_2 = require("../kg/index.js");
40
+ const index_js_3 = require("../kg/index.js");
41
+ const index_js_4 = require("../kg/index.js");
42
+ const index_js_5 = require("../live/index.js");
43
+ const index_js_6 = require("../live/index.js");
44
+ const index_js_7 = require("../real-data/index.js");
45
+ /**
46
+ * The exit codes of `kvox-eval kg` (and of the web app's `npm run kg:eval`).
47
+ *
48
+ * @stability experimental
49
+ */
50
+ exports.KG_EVAL_EXIT = Object.freeze({ ok: 0, targetsFailed: 1, usage: 2, pathRefused: 3 });
51
+ /**
52
+ * The usage text of `kvox-eval kg`.
53
+ *
54
+ * @stability experimental
55
+ */
56
+ exports.KG_COMMAND_USAGE = `usage: kvox-eval kg (--predictions <dir|gold> | --runner extract|extract-resolve --model <id>)
57
+ [--provider openai|openai-compatible|copilot] [--base-url <url>] [--out <dir>]
58
+ [--only m01,m07] [--tag <tag>] [--json <file>] [--enforce] [--real-dir <dir>]
59
+ reads a live runner's API key from ${index_js_5.KVOX_EVAL_API_KEY_ENV} (never a flag)`;
60
+ /** A command line that cannot run; printed with the usage text. */
61
+ class UsageError extends Error {
62
+ }
63
+ /** A live call that failed; printed by class, code and status only. */
64
+ class LiveCallError extends Error {
65
+ }
66
+ /**
67
+ * Runs `kvox-eval kg` with the given arguments (everything after `kg`).
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * const code = await runKgCommand(['--predictions', 'gold'], { out: console.log, err: console.error, env: process.env });
72
+ * ```
73
+ *
74
+ * @param argv - the arguments.
75
+ * @param io - output streams and environment.
76
+ * @param options - the host's name, usage text, scratch directory and adapters.
77
+ * @returns the exit code ({@link KG_EVAL_EXIT}).
78
+ * @stability experimental
79
+ */
80
+ async function runKgCommand(argv, io, options = {}) {
81
+ const name = options.name ?? 'kvox-eval kg';
82
+ const usage = options.usage ?? exports.KG_COMMAND_USAGE;
83
+ try {
84
+ return await run(argv, io, options, name, usage);
85
+ }
86
+ catch (err) {
87
+ if (err instanceof index_js_7.RealDataPathError) {
88
+ io.err(`${name}: ${err.message}`);
89
+ return exports.KG_EVAL_EXIT.pathRefused;
90
+ }
91
+ if (err instanceof UsageError || err instanceof index_js_3.KgEvalUsageError) {
92
+ io.err(`${name}: ${err.message}`);
93
+ io.err(usage);
94
+ return exports.KG_EVAL_EXIT.usage;
95
+ }
96
+ if (err instanceof index_js_1.KgEvalLoadError || err instanceof index_js_6.LiveProviderError || err instanceof LiveCallError) {
97
+ io.err(`${name}: ${err.message}`);
98
+ return exports.KG_EVAL_EXIT.usage;
99
+ }
100
+ throw err;
101
+ }
102
+ }
103
+ async function run(argv, io, options, name, usage) {
104
+ let values;
105
+ try {
106
+ ({ values } = (0, util_1.parseArgs)({
107
+ args: argv,
108
+ strict: true,
109
+ allowPositionals: false,
110
+ options: {
111
+ predictions: { type: 'string' },
112
+ runner: { type: 'string' },
113
+ run: { type: 'string' },
114
+ provider: { type: 'string' },
115
+ model: { type: 'string' },
116
+ 'base-url': { type: 'string' },
117
+ out: { type: 'string' },
118
+ only: { type: 'string' },
119
+ tag: { type: 'string' },
120
+ json: { type: 'string' },
121
+ enforce: { type: 'boolean' },
122
+ 'real-dir': { type: 'string' },
123
+ help: { type: 'boolean' },
124
+ },
125
+ }));
126
+ }
127
+ catch (err) {
128
+ throw new UsageError(err.message);
129
+ }
130
+ const str = (k) => (typeof values[k] === 'string' ? values[k] : undefined);
131
+ if (values.help) {
132
+ io.out(usage);
133
+ return exports.KG_EVAL_EXIT.ok;
134
+ }
135
+ // Real-data mode: the path guard runs before anything is read or written.
136
+ const realDirArg = str('real-dir') ?? (io.env.KG_EVAL_REAL_DIR || undefined);
137
+ const realDir = realDirArg ? (0, index_js_7.assertOutsideRepo)(realDirArg) : null;
138
+ if (str('runner') !== undefined && str('run') !== undefined)
139
+ throw new UsageError('pass --runner or --run, not both');
140
+ const runnerFlag = str('runner') !== undefined ? '--runner' : '--run';
141
+ const runnerName = str('runner') ?? str('run');
142
+ const predictionsArg = str('predictions');
143
+ if ((predictionsArg === undefined) === (runnerName === undefined)) {
144
+ throw new UsageError(`pass exactly one of --predictions <dir|gold> or ${runnerFlag} <runner>`);
145
+ }
146
+ // An unregistered runner is reported before anything is loaded or written.
147
+ const live = runnerName !== undefined ? (0, index_js_4.findKgEvalRunner)(runnerName) : null;
148
+ if (runnerName !== undefined && live === null) {
149
+ io.err(`${name}: no runner '${runnerName}' registered (known: ${Object.keys(index_js_4.KG_EVAL_RUNNERS).join(', ')})`);
150
+ return exports.KG_EVAL_EXIT.usage;
151
+ }
152
+ // The output guard runs before anything is loaded: a run over real data may
153
+ // never write inside the repository, not even into the git-ignored scratch dir.
154
+ let outDir = null;
155
+ if (live !== null) {
156
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-');
157
+ const synthetic = options.syntheticRunsDir ?? null;
158
+ const outArg = str('out') ??
159
+ (realDir ? (0, path_1.join)(realDir, 'runs', stamp) : synthetic ? (0, path_1.join)(synthetic, 'runs', stamp) : (0, path_1.join)((0, os_1.tmpdir)(), 'kvox-eval', 'runs', stamp));
160
+ outDir = (0, index_js_7.assertOutsideRepo)(outArg, { allowInside: realDir === null ? synthetic : null });
161
+ }
162
+ const only = str('only')
163
+ ?.split(',')
164
+ .map((s) => s.trim())
165
+ .filter(Boolean);
166
+ const selection = {
167
+ ...(only ? { fixtures: only } : {}),
168
+ ...(str('tag') !== undefined ? { tag: str('tag') } : {}),
169
+ ...(realDir ? { fixturesDir: realDir } : {}),
170
+ };
171
+ let report;
172
+ if (live !== null) {
173
+ // The provider is refused (copilot, an unknown id) before the key is looked for.
174
+ const provider = str('provider') ?? 'openai';
175
+ (0, index_js_6.assertLiveProvider)(provider);
176
+ const model = str('model');
177
+ if (!model)
178
+ throw new UsageError(`${runnerFlag} requires --model <id>`);
179
+ const key = (0, index_js_5.readEvalApiKey)(io.env, io.err);
180
+ if (key === null && provider === 'openai') {
181
+ throw new UsageError(`${runnerFlag} reads its API key from ${index_js_5.KVOX_EVAL_API_KEY_ENV}; it is not set`);
182
+ }
183
+ const baseUrl = str('base-url');
184
+ const { ai, failures } = (0, index_js_6.createLiveKvoxAi)({
185
+ provider,
186
+ model,
187
+ apiKey: key?.apiKey ?? null,
188
+ ...(baseUrl !== undefined ? { baseUrl } : {}),
189
+ ...(options.adapters !== undefined ? { adapters: options.adapters } : {}),
190
+ });
191
+ const dir = outDir;
192
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
193
+ try {
194
+ report = await (0, index_js_3.runKgEval)({
195
+ runner: live.name,
196
+ ai,
197
+ model,
198
+ provider,
199
+ ...selection,
200
+ onPrediction: (fixtureId, pred) => (0, fs_1.writeFileSync)((0, path_1.join)(dir, `${fixtureId}.json`), `${JSON.stringify(pred, null, 2)}\n`),
201
+ });
202
+ }
203
+ catch (err) {
204
+ if (err instanceof ports_1.KvoxAiError)
205
+ throw new LiveCallError(describeLiveFailure(err, failures));
206
+ throw err;
207
+ }
208
+ io.err(`${name}: predictions written to ${dir}`);
209
+ }
210
+ else if (predictionsArg === 'gold') {
211
+ report = await (0, index_js_3.runKgEval)({ runner: 'gold', ...selection });
212
+ }
213
+ else {
214
+ report = await (0, index_js_3.runKgEval)({
215
+ predictionsDir: (0, path_1.resolve)(predictionsArg),
216
+ ...selection,
217
+ onMissingPrediction: (fixtureId, dir) => io.err(`${name}: no prediction for ${fixtureId} in ${dir} (scored as empty)`),
218
+ });
219
+ }
220
+ io.out((0, index_js_2.formatReport)(report));
221
+ const jsonPath = str('json');
222
+ if (jsonPath) {
223
+ const abs = (0, path_1.resolve)(jsonPath);
224
+ (0, fs_1.mkdirSync)((0, path_1.dirname)(abs), { recursive: true });
225
+ (0, fs_1.writeFileSync)(abs, `${JSON.stringify(report, null, 2)}\n`);
226
+ }
227
+ if (values.enforce && !report.targetsMet) {
228
+ io.err(`${name}: one or more §6 targets failed (--enforce)`);
229
+ return exports.KG_EVAL_EXIT.targetsFailed;
230
+ }
231
+ return exports.KG_EVAL_EXIT.ok;
232
+ }
233
+ /** `the live call failed (auth; AI_KEY_INVALID, HTTP 400)`: class, code, status. Never a message body. */
234
+ function describeLiveFailure(err, failures) {
235
+ const last = failures[failures.length - 1];
236
+ const detail = last ? `; ${last.code}${last.status !== null ? `, HTTP ${last.status}` : ''}` : '';
237
+ return `the live call failed (${err.errorClass}${detail})`;
238
+ }
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ import { type EvalCommandIo, type KgCommandOptions } from './kg-command.js';
3
+ /**
4
+ * The usage text of `kvox-eval`.
5
+ *
6
+ * @stability experimental
7
+ */
8
+ export declare const KVOX_EVAL_USAGE = "usage: kvox-eval kg [flags] score knowledge-graph extraction against the golden set\n kvox-eval ask [flags] run the Ask evaluation headless (in-memory database, live model)\n kvox-eval ask --replay the Ask harness's scripted self-test (no model, no key)\n kvox-eval kg --help the kg flags\n kvox-eval ask --help the ask flags";
9
+ /**
10
+ * Runs `kvox-eval` with the given arguments (everything after the command name).
11
+ *
12
+ * @param argv - the arguments, the subcommand first.
13
+ * @param io - output streams and environment.
14
+ * @param options - passed to the kg command (the ask command takes its defaults).
15
+ * @returns the exit code.
16
+ * @stability experimental
17
+ */
18
+ export declare function main(argv: string[], io?: EvalCommandIo, options?: KgCommandOptions): Promise<number>;
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ // =============================================================================
4
+ // The `kvox-eval` command (issue #580)
5
+ // =============================================================================
6
+ //
7
+ // kvox-eval kg ... score knowledge-graph extraction (see kg-command.ts)
8
+ // kvox-eval ask ... the Ask evaluation, headless (see ask-command.ts): an
9
+ // in-memory PostgreSQL, the golden graph, the real
10
+ // `ask.respond` handler; `--replay` needs no model or key
11
+ // =============================================================================
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.KVOX_EVAL_USAGE = void 0;
14
+ exports.main = main;
15
+ const kg_command_js_1 = require("./kg-command.js");
16
+ /**
17
+ * The usage text of `kvox-eval`.
18
+ *
19
+ * @stability experimental
20
+ */
21
+ exports.KVOX_EVAL_USAGE = `usage: kvox-eval kg [flags] score knowledge-graph extraction against the golden set
22
+ kvox-eval ask [flags] run the Ask evaluation headless (in-memory database, live model)
23
+ kvox-eval ask --replay the Ask harness's scripted self-test (no model, no key)
24
+ kvox-eval kg --help the kg flags
25
+ kvox-eval ask --help the ask flags`;
26
+ /**
27
+ * Runs `kvox-eval` with the given arguments (everything after the command name).
28
+ *
29
+ * @param argv - the arguments, the subcommand first.
30
+ * @param io - output streams and environment.
31
+ * @param options - passed to the kg command (the ask command takes its defaults).
32
+ * @returns the exit code.
33
+ * @stability experimental
34
+ */
35
+ async function main(argv, io = defaultIo(), options = {}) {
36
+ const [command, ...rest] = argv;
37
+ if (command === 'kg')
38
+ return (0, kg_command_js_1.runKgCommand)(rest, io, options);
39
+ if (command === 'ask') {
40
+ // Loaded only here: the ask command brings Nest, the domain slices, PGlite and
41
+ // the generated Prisma client, which `kvox-eval kg` and `--help` never need.
42
+ const { runAskCommand } = require('../ask-run/index.js');
43
+ return runAskCommand(rest, io);
44
+ }
45
+ if (command === '--help' || command === '-h' || command === 'help') {
46
+ io.out(exports.KVOX_EVAL_USAGE);
47
+ return kg_command_js_1.KG_EVAL_EXIT.ok;
48
+ }
49
+ io.err(command === undefined ? 'kvox-eval: no command given' : `kvox-eval: unknown command '${command}'`);
50
+ io.err(exports.KVOX_EVAL_USAGE);
51
+ return kg_command_js_1.KG_EVAL_EXIT.usage;
52
+ }
53
+ function defaultIo() {
54
+ return {
55
+ out: (s) => process.stdout.write(`${s}\n`),
56
+ err: (s) => process.stderr.write(`${s}\n`),
57
+ env: process.env,
58
+ };
59
+ }
60
+ if (require.main === module) {
61
+ main(process.argv.slice(2)).then((code) => {
62
+ process.exitCode = code;
63
+ }, (err) => {
64
+ // A KvoxAiError never reaches here (the kg command reports it by class);
65
+ // anything else is a bug, and its stack is the useful part.
66
+ process.stderr.write(`kvox-eval: ${err.stack ?? String(err)}\n`);
67
+ process.exitCode = kg_command_js_1.KG_EVAL_EXIT.usage;
68
+ });
69
+ }
@@ -0,0 +1,16 @@
1
+ import type { DomainKey } from '@marinoscar/kvox-contract/ontology';
2
+ import type { GoldenFixture } from './fixture-schema.js';
3
+ /**
4
+ * The tag that marks a fixture as written for a user with `personal` enabled.
5
+ *
6
+ * @stability experimental
7
+ */
8
+ export declare const PERSONAL_FIXTURE_TAG = "personal";
9
+ /**
10
+ * The ontology domains a fixture is extracted and validated against.
11
+ *
12
+ * @param fixture - the fixture (its tags).
13
+ * @returns `core ∪ work`, plus `personal` for a fixture tagged {@link PERSONAL_FIXTURE_TAG}.
14
+ * @stability experimental
15
+ */
16
+ export declare function fixtureDomains(fixture: Pick<GoldenFixture, 'tags'>): DomainKey[];
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ // =============================================================================
3
+ // Which ontology domains a golden fixture is extracted and validated against
4
+ // (issue #383). PURE.
5
+ // =============================================================================
6
+ //
7
+ // Every fixture is `core ∪ work` — the default a user who never touched the
8
+ // setting has. A fixture tagged `personal` is the story of a user who turned
9
+ // the `personal` domain on (docs/specs/ontology.md §17.2, §16 P6), so it is
10
+ // read against `core ∪ work ∪ personal`: its labels may use Interest, Trip,
11
+ // Milestone and the personal relations, and an extraction run over it is
12
+ // offered them. Keeping the default fixtures on `core ∪ work` is what proves a
13
+ // user who never enables `personal` sees no personal type anywhere.
14
+ // =============================================================================
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.PERSONAL_FIXTURE_TAG = void 0;
17
+ exports.fixtureDomains = fixtureDomains;
18
+ /**
19
+ * The tag that marks a fixture as written for a user with `personal` enabled.
20
+ *
21
+ * @stability experimental
22
+ */
23
+ exports.PERSONAL_FIXTURE_TAG = 'personal';
24
+ /**
25
+ * The ontology domains a fixture is extracted and validated against.
26
+ *
27
+ * @param fixture - the fixture (its tags).
28
+ * @returns `core ∪ work`, plus `personal` for a fixture tagged {@link PERSONAL_FIXTURE_TAG}.
29
+ * @stability experimental
30
+ */
31
+ function fixtureDomains(fixture) {
32
+ return fixture.tags.includes(exports.PERSONAL_FIXTURE_TAG) ? ['core', 'work', 'personal'] : ['core', 'work'];
33
+ }