@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.
- package/CHANGELOG.md +14 -0
- package/LICENSE +21 -0
- package/README.md +166 -0
- package/dist/ask/index.d.ts +6 -0
- package/dist/ask/index.js +28 -0
- package/dist/ask/question-schema.d.ts +121 -0
- package/dist/ask/question-schema.js +167 -0
- package/dist/ask/report.d.ts +88 -0
- package/dist/ask/report.js +170 -0
- package/dist/ask/scorer.d.ts +104 -0
- package/dist/ask/scorer.js +164 -0
- package/dist/ask-run/ask-command.d.ts +62 -0
- package/dist/ask-run/ask-command.js +254 -0
- package/dist/ask-run/host/app.d.ts +65 -0
- package/dist/ask-run/host/app.js +146 -0
- package/dist/ask-run/host/db.d.ts +38 -0
- package/dist/ask-run/host/db.js +126 -0
- package/dist/ask-run/host/ports.d.ts +35 -0
- package/dist/ask-run/host/ports.js +113 -0
- package/dist/ask-run/index.d.ts +13 -0
- package/dist/ask-run/index.js +35 -0
- package/dist/ask-run/replay.d.ts +128 -0
- package/dist/ask-run/replay.js +212 -0
- package/dist/ask-run/run-ask-eval.d.ts +125 -0
- package/dist/ask-run/run-ask-eval.js +193 -0
- package/dist/ask-run/seed-golden-graph.d.ts +64 -0
- package/dist/ask-run/seed-golden-graph.js +495 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +12 -0
- package/dist/cli/kg-command.d.ts +66 -0
- package/dist/cli/kg-command.js +238 -0
- package/dist/cli/main.d.ts +18 -0
- package/dist/cli/main.js +69 -0
- package/dist/fixtures/domains.d.ts +16 -0
- package/dist/fixtures/domains.js +33 -0
- package/dist/fixtures/fixture-schema.d.ts +323 -0
- package/dist/fixtures/fixture-schema.js +199 -0
- package/dist/fixtures/index.d.ts +16 -0
- package/dist/fixtures/index.js +40 -0
- package/dist/fixtures/load.d.ts +73 -0
- package/dist/fixtures/load.js +137 -0
- package/dist/fixtures/questions.d.ts +15 -0
- package/dist/fixtures/questions.js +26 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +36 -0
- package/dist/kg/gold-runner.d.ts +13 -0
- package/dist/kg/gold-runner.js +57 -0
- package/dist/kg/index.d.ts +17 -0
- package/dist/kg/index.js +65 -0
- package/dist/kg/internals.d.ts +7 -0
- package/dist/kg/internals.js +17 -0
- package/dist/kg/prediction-schema.d.ts +245 -0
- package/dist/kg/prediction-schema.js +102 -0
- package/dist/kg/predictions.d.ts +11 -0
- package/dist/kg/predictions.js +49 -0
- package/dist/kg/report.d.ts +84 -0
- package/dist/kg/report.js +125 -0
- package/dist/kg/run-kg-eval.d.ts +77 -0
- package/dist/kg/run-kg-eval.js +137 -0
- package/dist/kg/runner.d.ts +72 -0
- package/dist/kg/runner.js +51 -0
- package/dist/kg/runners/extract-resolve-runner.d.ts +40 -0
- package/dist/kg/runners/extract-resolve-runner.js +199 -0
- package/dist/kg/runners/extract-runner.d.ts +65 -0
- package/dist/kg/runners/extract-runner.js +243 -0
- package/dist/kg/scorer.d.ts +226 -0
- package/dist/kg/scorer.js +463 -0
- package/dist/kg/targets.d.ts +17 -0
- package/dist/kg/targets.js +16 -0
- package/dist/kg/text.d.ts +45 -0
- package/dist/kg/text.js +100 -0
- package/dist/live/adapters.d.ts +16 -0
- package/dist/live/adapters.js +58 -0
- package/dist/live/env.d.ts +39 -0
- package/dist/live/env.js +56 -0
- package/dist/live/index.d.ts +6 -0
- package/dist/live/index.js +16 -0
- package/dist/live/live-ai.d.ts +104 -0
- package/dist/live/live-ai.js +157 -0
- package/dist/parity/constants.d.ts +79 -0
- package/dist/parity/constants.js +104 -0
- package/dist/parity/index.d.ts +20 -0
- package/dist/parity/index.js +38 -0
- package/dist/parity/internals.d.ts +8 -0
- package/dist/parity/internals.js +16 -0
- package/dist/parity/scenario.d.ts +45 -0
- package/dist/parity/scenario.js +245 -0
- package/dist/parity/script.d.ts +44 -0
- package/dist/parity/script.js +136 -0
- package/dist/parity/snapshot.d.ts +43 -0
- package/dist/parity/snapshot.js +71 -0
- package/dist/real-data/index.d.ts +2 -0
- package/dist/real-data/index.js +12 -0
- package/dist/real-data/real-data.d.ts +76 -0
- package/dist/real-data/real-data.js +156 -0
- package/fixtures/kg-golden/README.md +136 -0
- package/fixtures/kg-golden/ask-questions.json +458 -0
- package/fixtures/kg-golden/meetings/m01-northwind-pilot-kickoff.json +792 -0
- package/fixtures/kg-golden/meetings/m02-halden-migration-planning.json +814 -0
- package/fixtures/kg-golden/meetings/m03-larkspur-weekly-sync.json +601 -0
- package/fixtures/kg-golden/meetings/m04-corvid-intake-discovery.json +690 -0
- package/fixtures/kg-golden/meetings/m05-hosting-vendor-selection.json +631 -0
- package/fixtures/kg-golden/meetings/m06-northwind-floor-data-review.json +649 -0
- package/fixtures/kg-golden/meetings/m07-gullwing-intro-notes.json +428 -0
- package/fixtures/kg-golden/meetings/m08-halden-migration-checkpoint.json +672 -0
- package/fixtures/kg-golden/meetings/m09-northwind-platform-org-update.json +711 -0
- package/fixtures/kg-golden/meetings/m10-corvid-prototype-review.json +623 -0
- package/fixtures/kg-golden/meetings/m11-solvane-grid-dashboard-scoping.json +689 -0
- package/fixtures/kg-golden/meetings/m12-northwind-pilot-replan.json +681 -0
- package/fixtures/kg-golden/meetings/m13-halden-cutover-go-no-go.json +721 -0
- package/fixtures/kg-golden/meetings/m14-gullwing-discovery-readout.json +719 -0
- package/fixtures/kg-golden/meetings/m15-halden-handover-ravi-leaving.json +716 -0
- package/fixtures/kg-golden/meetings/m16-varden-claims-portal-intro.json +704 -0
- package/fixtures/kg-golden/meetings/m17-corvid-usability-debrief.json +572 -0
- package/fixtures/kg-golden/meetings/m18-hosting-decision-revisited.json +655 -0
- package/fixtures/kg-golden/meetings/m19-solvane-integration-kickoff.json +726 -0
- package/fixtures/kg-golden/meetings/m20-northwind-go-live-retro.json +673 -0
- package/fixtures/kg-golden/meetings/m21-quarterly-account-review.json +449 -0
- package/fixtures/kg-golden/meetings/m22-halden-intro-call-2020.json +558 -0
- package/fixtures/kg-golden/meetings/m23-gullwing-model-review.json +702 -0
- package/fixtures/kg-golden/meetings/m24-varden-discovery-midpoint.json +643 -0
- package/fixtures/kg-golden/meetings/m25-corvid-rollout-planning.json +642 -0
- package/fixtures/kg-golden/meetings/m26-larkspur-engineering-prep.json +695 -0
- package/fixtures/kg-golden/meetings/m27-solvane-phase-one-demo.json +649 -0
- package/fixtures/kg-golden/meetings/m28-northwind-building-5-scoping.json +715 -0
- package/fixtures/kg-golden/meetings/m29-halden-southern-cutover-review.json +752 -0
- package/fixtures/kg-golden/meetings/m30-varden-portal-build-kickoff.json +697 -0
- package/fixtures/kg-golden/meetings/m31-gullwing-rollout-renewal.json +681 -0
- package/fixtures/kg-golden/meetings/m32-brambleway-weekly-sync.json +472 -0
- package/fixtures/kg-golden/meetings/m33-nina-oliver-one-on-one.json +342 -0
- package/fixtures/kg-golden/meetings/m34-coffee-with-dana.json +249 -0
- package/fixtures/kg-golden/meetings/m35-brambleway-june-sync.json +553 -0
- package/fixtures/kg-golden/meetings/m36-copenhagen-conference-planning.json +296 -0
- package/host/generated/client.d.ts +1 -0
- package/host/generated/client.js +5 -0
- package/host/generated/default.d.ts +1 -0
- package/host/generated/default.js +5 -0
- package/host/generated/edge.d.ts +1 -0
- package/host/generated/edge.js +1658 -0
- package/host/generated/index-browser.js +1684 -0
- package/host/generated/index.d.ts +192335 -0
- package/host/generated/index.js +1658 -0
- package/host/generated/package.json +139 -0
- package/host/generated/query_compiler_fast_bg.js +2 -0
- package/host/generated/query_compiler_fast_bg.wasm +0 -0
- package/host/generated/query_compiler_fast_bg.wasm-base64.js +2 -0
- package/host/generated/runtime/client.d.ts +3433 -0
- package/host/generated/runtime/client.js +110 -0
- package/host/generated/runtime/index-browser.d.ts +90 -0
- package/host/generated/runtime/index-browser.js +6 -0
- package/host/generated/runtime/wasm-compiler-edge.js +100 -0
- package/host/generated/schema.prisma +6312 -0
- package/host/generated/wasm-edge-light-loader.mjs +5 -0
- package/host/generated/wasm-worker-loader.mjs +5 -0
- package/host/prisma/fragments/kvox.ask.prisma +126 -0
- package/host/prisma/fragments/kvox.graph.prisma +1073 -0
- package/host/prisma/fragments/kvox.notes.prisma +787 -0
- package/host/prisma/fragments/kvox.search.prisma +211 -0
- package/host/prisma/fragments/kvox.transcripts.prisma +790 -0
- package/host/prisma/kvox.lock +101 -0
- package/host/prisma/migrations/20240101000000_initial/migration.sql +297 -0
- package/host/prisma/migrations/20240101000001_add_personal_access_tokens/migration.sql +31 -0
- package/host/prisma/migrations/20240101000002_add_credentials/migration.sql +20 -0
- package/host/prisma/migrations/20240101000003_add_notification_deliveries/migration.sql +27 -0
- package/host/prisma/migrations/20240101000004_drop_stale_uuid_defaults/migration.sql +35 -0
- package/host/prisma/migrations/20240101000005_add_notifications/migration.sql +22 -0
- package/host/prisma/migrations/20240101000006_add_push_subscriptions/migration.sql +25 -0
- package/host/prisma/migrations/20240101000007_add_jobs/migration.sql +110 -0
- package/host/prisma/migrations/20240101000008_add_worker_nodes/migration.sql +90 -0
- package/host/prisma/migrations/20240101000009_add_database_backup_runs/migration.sql +104 -0
- package/host/prisma/migrations/20240101000010_add_notification_broadcasts/migration.sql +57 -0
- package/host/prisma/migrations/20240101000011_add_backup_run_job_link/migration.sql +87 -0
- package/host/prisma/migrations/20240101000012_add_job_node_secrets/migration.sql +61 -0
- package/host/prisma/migrations/20240101000013_add_backup_run_pg_dump_version/migration.sql +26 -0
- package/host/prisma/migrations/20240101000014_add_job_claim_token/migration.sql +92 -0
- package/host/prisma/migrations/20240101000015_add_ai_platform/migration.sql +108 -0
- package/host/prisma/migrations/20240101000016_revoke_viewer_ai_use/migration.sql +32 -0
- package/host/prisma/migrations/20240101000017_add_user_credentials/migration.sql +29 -0
- package/host/prisma/migrations/20240101000018_add_device_session_credential_link/migration.sql +52 -0
- package/host/prisma/migrations/20240101000019_add_worker_node_vitals/migration.sql +3 -0
- package/host/prisma/migrations/20240101000020_add_job_trace_context/migration.sql +6 -0
- package/host/prisma/migrations/20240101000021_add_retention_created_at_indexes/migration.sql +13 -0
- package/host/prisma/migrations/20240101000022_add_organizations/migration.sql +142 -0
- package/host/prisma/migrations/20240101000023_split_system_org_roles/migration.sql +131 -0
- package/host/prisma/migrations/20240101000024_org_scoped_rls/migration.sql +215 -0
- package/host/prisma/migrations/20240101000025_add_groups/migration.sql +165 -0
- package/host/prisma/migrations/20240101000026_add_grants/migration.sql +117 -0
- package/host/prisma/migrations/20240101000027_add_org_settings/migration.sql +49 -0
- package/host/prisma/migrations/20240101000028_add_org_credentials/migration.sql +54 -0
- package/host/prisma/migrations/20240101000029_add_jobs_org_id/migration.sql +18 -0
- package/host/prisma/migrations/20240101000030_add_jobs_org_id_status_index/migration.sql +6 -0
- package/host/prisma/migrations/20240101000031_add_broadcast_target_org/migration.sql +21 -0
- package/host/prisma/migrations/20240101000032_add_android_app/migration.sql +60 -0
- package/host/prisma/migrations/20240101000033_open_job_reason/migration.sql +16 -0
- package/host/prisma/migrations/20240101000034_ai_usage_feature/migration.sql +37 -0
- package/host/prisma/migrations/20240101000035_add_app_metadata/migration.sql +49 -0
- package/host/prisma/migrations/20240101000036_open_sharing_vocabularies/migration.sql +97 -0
- package/host/prisma/migrations/20260914130000_kvox_add_transcripts/migration.sql +322 -0
- package/host/prisma/migrations/20260914140000_kvox_add_notes/migration.sql +311 -0
- package/host/prisma/migrations/20260915120000_kvox_add_search_vectors/migration.sql +150 -0
- package/host/prisma/migrations/20260915130000_kvox_add_search_embeddings/migration.sql +362 -0
- package/host/prisma/migrations/20260915210000_kvox_add_note_title_source/migration.sql +30 -0
- package/host/prisma/migrations/20260923120000_kvox_add_note_generation_context_snapshot/migration.sql +24 -0
- package/host/prisma/migrations/20260923130000_kvox_add_user_hidden_note_templates/migration.sql +35 -0
- package/host/prisma/migrations/20260923140000_kvox_add_transcript_speaker_identities/migration.sql +6 -0
- package/host/prisma/migrations/20260923150000_kvox_transcript_name_checks/migration.sql +95 -0
- package/host/prisma/migrations/20260923160000_kvox_add_note_body_format/migration.sql +27 -0
- package/host/prisma/migrations/20260923170000_kvox_add_note_version_body_format/migration.sql +23 -0
- package/host/prisma/migrations/20260926012548_kvox_add_knowledge_graph/migration.sql +680 -0
- package/host/prisma/migrations/20260926030000_kvox_fix_kg_relations_valid_precision_chk/migration.sql +29 -0
- package/host/prisma/migrations/20260926030100_kvox_add_transcript_recorded_at/migration.sql +9 -0
- package/host/prisma/migrations/20260926030200_kvox_kg_evidence_invariant/migration.sql +60 -0
- package/host/prisma/migrations/20260926040000_kvox_add_kg_graph_layouts/migration.sql +30 -0
- package/host/prisma/migrations/20260926050000_kvox_add_ask_conversations/migration.sql +99 -0
- package/host/prisma/migrations/20260926231512_kvox_add_kg_exports/migration.sql +52 -0
- package/host/prisma/migrations/20261016120000_kvox_transcripts_org_id/migration.sql +49 -0
- package/host/prisma/platform.lock +319 -0
- package/host/prisma/schema/app.kvox.ask.prisma +110 -0
- package/host/prisma/schema/app.kvox.graph.prisma +1030 -0
- package/host/prisma/schema/app.kvox.notes.prisma +746 -0
- package/host/prisma/schema/app.kvox.search.prisma +208 -0
- package/host/prisma/schema/app.kvox.transcripts.prisma +726 -0
- package/host/prisma/schema/platform.ai.prisma +419 -0
- package/host/prisma/schema/platform.android-app.prisma +46 -0
- package/host/prisma/schema/platform.base.prisma +15 -0
- package/host/prisma/schema/platform.credentials.prisma +156 -0
- package/host/prisma/schema/platform.db-backup.prisma +359 -0
- package/host/prisma/schema/platform.identity.prisma +638 -0
- package/host/prisma/schema/platform.jobs.prisma +824 -0
- package/host/prisma/schema/platform.notifications.prisma +641 -0
- package/host/prisma/schema/platform.settings.prisma +53 -0
- package/host/prisma/schema/platform.sharing.prisma +208 -0
- package/host/prisma/schema/platform.storage.prisma +118 -0
- package/package.json +112 -1
- package/parity/requests.ask.json +2681 -0
- package/parity/requests.m01.json +1554 -0
- package/parity/requests.m02.json +1554 -0
- package/parity/requests.m03.json +1554 -0
- package/parity/requests.m04.json +1554 -0
- package/parity/requests.m05.json +1554 -0
- package/parity/requests.m06.json +1554 -0
- package/parity/requests.m07.json +1554 -0
- package/parity/requests.m08.json +1554 -0
- package/parity/requests.m09.json +1554 -0
- 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.
|