@dsh-enhanced/assistant-evaluation 0.1.7

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/lib/sqlite.js ADDED
@@ -0,0 +1,177 @@
1
+ import { chmodSync, closeSync, constants, existsSync, lstatSync, mkdirSync, openSync, } from 'node:fs';
2
+ import { dirname, isAbsolute } from 'node:path';
3
+ import { DatabaseSync } from 'node:sqlite';
4
+ export const evaluationSchemaVersion = 2;
5
+ export class EvaluationDatabaseError extends Error {
6
+ code;
7
+ constructor(code, message) {
8
+ super(message);
9
+ this.code = code;
10
+ this.name = 'EvaluationDatabaseError';
11
+ }
12
+ }
13
+ function assertSafeFile(path) {
14
+ const stat = lstatSync(path);
15
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1) {
16
+ throw new EvaluationDatabaseError('unsafe-file', 'evaluation database must be one regular, unlinked file');
17
+ }
18
+ if ((stat.mode & 0o077) !== 0) {
19
+ throw new EvaluationDatabaseError('unsafe-file', 'evaluation database permissions must not allow group or other access');
20
+ }
21
+ const uid = process.getuid?.();
22
+ if (uid !== undefined && stat.uid !== uid) {
23
+ throw new EvaluationDatabaseError('unsafe-file', 'evaluation database must be owned by the current OS user');
24
+ }
25
+ }
26
+ function preparePrivateFile(path) {
27
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
28
+ if (!existsSync(path)) {
29
+ const descriptor = openSync(path, constants.O_CREAT | constants.O_EXCL | constants.O_RDWR, 0o600);
30
+ closeSync(descriptor);
31
+ }
32
+ assertSafeFile(path);
33
+ }
34
+ function schemaVersion(database) {
35
+ return database.prepare('PRAGMA user_version').get().user_version;
36
+ }
37
+ const selfAssessmentSchema = `
38
+ CREATE TABLE evaluation_self_assessments (
39
+ id TEXT PRIMARY KEY,
40
+ outcome_id TEXT NOT NULL,
41
+ idempotency_key TEXT NOT NULL UNIQUE,
42
+ payload_hash TEXT NOT NULL,
43
+ scope_key TEXT NOT NULL,
44
+ objective_status TEXT NOT NULL
45
+ CHECK (objective_status IN ('achieved', 'partial', 'not-achieved', 'unknown')),
46
+ evidence_json TEXT NOT NULL,
47
+ occurred_at INTEGER NOT NULL,
48
+ recorded_at INTEGER NOT NULL,
49
+ evaluator_id TEXT NOT NULL,
50
+ evaluator_version TEXT NOT NULL,
51
+ FOREIGN KEY (outcome_id) REFERENCES evaluation_outcomes(id) ON DELETE RESTRICT
52
+ ) STRICT;
53
+ CREATE INDEX evaluation_self_assessments_scope_time
54
+ ON evaluation_self_assessments(scope_key, occurred_at DESC, id DESC);
55
+ CREATE INDEX evaluation_self_assessments_outcome_time
56
+ ON evaluation_self_assessments(outcome_id, occurred_at DESC, id DESC);
57
+ `;
58
+ function migrate(database) {
59
+ const initial = schemaVersion(database);
60
+ if (initial > evaluationSchemaVersion) {
61
+ throw new EvaluationDatabaseError('schema-too-new', `evaluation schema ${initial} is newer than supported schema ${evaluationSchemaVersion}`);
62
+ }
63
+ if (initial === evaluationSchemaVersion)
64
+ return;
65
+ database.exec('BEGIN IMMEDIATE');
66
+ try {
67
+ if (schemaVersion(database) === 0) {
68
+ database.exec(`
69
+ CREATE TABLE evaluation_schema_meta (
70
+ key TEXT PRIMARY KEY,
71
+ value TEXT NOT NULL
72
+ ) STRICT;
73
+
74
+ CREATE TABLE evaluation_outcomes (
75
+ id TEXT PRIMARY KEY,
76
+ idempotency_key TEXT NOT NULL UNIQUE,
77
+ payload_hash TEXT NOT NULL,
78
+ scope_key TEXT NOT NULL,
79
+ workspace TEXT NOT NULL,
80
+ preset TEXT NOT NULL,
81
+ situation TEXT NOT NULL,
82
+ execution_status TEXT NOT NULL
83
+ CHECK (execution_status IN ('succeeded', 'failed', 'timed-out', 'cancelled', 'unknown')),
84
+ objective_status TEXT NOT NULL
85
+ CHECK (objective_status IN ('achieved', 'partial', 'not-achieved', 'unknown')),
86
+ delivery_status TEXT NOT NULL
87
+ CHECK (delivery_status IN ('delivered', 'failed', 'not-required', 'unknown')),
88
+ source_kind TEXT NOT NULL
89
+ CHECK (source_kind IN ('automation', 'foreground', 'delivery', 'user-feedback', 'system', 'evaluator', 'import')),
90
+ source_id TEXT NOT NULL,
91
+ trust TEXT NOT NULL CHECK (trust IN ('trusted', 'self-reported', 'external')),
92
+ evidence_json TEXT NOT NULL,
93
+ metrics_json TEXT NOT NULL,
94
+ cost_usd_micros INTEGER,
95
+ latency_ms INTEGER,
96
+ input_tokens INTEGER,
97
+ output_tokens INTEGER,
98
+ tool_calls INTEGER,
99
+ occurred_at INTEGER NOT NULL,
100
+ recorded_at INTEGER NOT NULL,
101
+ evaluator_id TEXT NOT NULL,
102
+ evaluator_version TEXT NOT NULL
103
+ ) STRICT;
104
+
105
+ CREATE INDEX evaluation_outcomes_scope_time
106
+ ON evaluation_outcomes(scope_key, occurred_at DESC, id DESC);
107
+ CREATE INDEX evaluation_outcomes_scope_situation_time
108
+ ON evaluation_outcomes(scope_key, situation, occurred_at DESC, id DESC);
109
+ CREATE INDEX evaluation_outcomes_summary
110
+ ON evaluation_outcomes(scope_key, occurred_at, situation, trust);
111
+
112
+ ${selfAssessmentSchema}
113
+
114
+ INSERT INTO evaluation_schema_meta(key, value) VALUES ('schema-version', '2');
115
+ PRAGMA user_version = 2;
116
+ `);
117
+ }
118
+ if (schemaVersion(database) === 1) {
119
+ database.exec(`
120
+ ${selfAssessmentSchema}
121
+ UPDATE evaluation_schema_meta SET value = '2' WHERE key = 'schema-version';
122
+ PRAGMA user_version = 2;
123
+ `);
124
+ }
125
+ if (schemaVersion(database) !== evaluationSchemaVersion) {
126
+ throw new Error('evaluation migration did not reach the current schema');
127
+ }
128
+ database.exec('COMMIT');
129
+ }
130
+ catch (error) {
131
+ database.exec('ROLLBACK');
132
+ throw error;
133
+ }
134
+ }
135
+ const walRetryWait = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
136
+ function enableWal(database) {
137
+ const deadline = Date.now() + 5_000;
138
+ while (true) {
139
+ try {
140
+ const row = database.prepare('PRAGMA journal_mode = WAL').get();
141
+ if (row.journal_mode.toLowerCase() !== 'wal') {
142
+ throw new Error(`evaluation database refused WAL mode: ${row.journal_mode}`);
143
+ }
144
+ return;
145
+ }
146
+ catch (error) {
147
+ const retryable = error instanceof Error && /database is (?:busy|locked)/i.test(error.message);
148
+ if (!retryable || Date.now() >= deadline)
149
+ throw error;
150
+ Atomics.wait(walRetryWait, 0, 0, 10);
151
+ }
152
+ }
153
+ }
154
+ export function openEvaluationDatabase(path) {
155
+ if (path !== ':memory:' && !isAbsolute(path)) {
156
+ throw new EvaluationDatabaseError('invalid-path', 'evaluation database path must be absolute');
157
+ }
158
+ if (path !== ':memory:')
159
+ preparePrivateFile(path);
160
+ const database = new DatabaseSync(path);
161
+ try {
162
+ database.exec('PRAGMA foreign_keys = ON');
163
+ database.exec('PRAGMA busy_timeout = 5000');
164
+ database.exec('PRAGMA synchronous = FULL');
165
+ migrate(database);
166
+ if (path !== ':memory:') {
167
+ enableWal(database);
168
+ chmodSync(path, 0o600);
169
+ }
170
+ return database;
171
+ }
172
+ catch (error) {
173
+ database.close();
174
+ throw error;
175
+ }
176
+ }
177
+ //# sourceMappingURL=sqlite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"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"}
package/lib/store.d.ts ADDED
@@ -0,0 +1,39 @@
1
+ import type { EvaluationHealth, EvaluationScope, OutcomeEnvelope, OutcomeQuery, OutcomeSummary, OutcomeSummaryQuery, SelfAssessmentInput, StoredSelfAssessment, StoredOutcome } from './types.js';
2
+ export type EvaluationStoreErrorCode = 'idempotency-conflict' | 'invalid-input' | 'not-found';
3
+ export declare class EvaluationStoreError extends Error {
4
+ readonly code: EvaluationStoreErrorCode;
5
+ constructor(code: EvaluationStoreErrorCode, message: string);
6
+ }
7
+ export interface EvaluationStoreOptions {
8
+ path: string;
9
+ now?: () => number;
10
+ maxQueryLimit?: number;
11
+ maxSituationBytes?: number;
12
+ maxMetricsBytes?: number;
13
+ maxEvidenceRefs?: number;
14
+ maxSummaryWindowMs?: number;
15
+ defaultSummaryWindowMs?: number;
16
+ }
17
+ export declare function canonicalEvaluationScope(input: EvaluationScope): {
18
+ scope: EvaluationScope;
19
+ scopeKey: string;
20
+ };
21
+ export declare class EvaluationStore {
22
+ #private;
23
+ constructor(options: EvaluationStoreOptions);
24
+ close(): void;
25
+ getOutcome(scopeInput: EvaluationScope, outcomeIdInput: string): StoredOutcome | undefined;
26
+ append(input: OutcomeEnvelope): StoredOutcome;
27
+ /**
28
+ * Append a self-reported objective judgement linked to an immutable Host
29
+ * outcome. Execution and delivery are inherited, metrics are not copied, and
30
+ * the assessment never participates in the trusted outcome count.
31
+ */
32
+ appendSelfAssessment(input: SelfAssessmentInput): StoredSelfAssessment;
33
+ /** Latest self-report for each requested parent, preserving parent order. */
34
+ latestSelfAssessments(scopeInput: EvaluationScope, outcomeIdsInput: readonly string[]): StoredSelfAssessment[];
35
+ query(input: OutcomeQuery): StoredOutcome[];
36
+ summary(input: OutcomeSummaryQuery): OutcomeSummary;
37
+ health(): EvaluationHealth;
38
+ }
39
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAGV,gBAAgB,EAGhB,eAAe,EAGf,eAAe,EACf,YAAY,EAEZ,cAAc,EACd,mBAAmB,EAEnB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACd,MAAM,YAAY,CAAA;AAEnB,MAAM,MAAM,wBAAwB,GAAG,sBAAsB,GAAG,eAAe,GAAG,WAAW,CAAA;AAE7F,qBAAa,oBAAqB,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,wBAAwB;gBAA9B,IAAI,EAAE,wBAAwB,EAAE,OAAO,EAAE,MAAM;CAIrE;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,sBAAsB,CAAC,EAAE,MAAM,CAAA;CAChC;AAmED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,eAAe,GAAG;IAAE,KAAK,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAO7G;AAwID,qBAAa,eAAe;;gBAUd,OAAO,EAAE,sBAAsB;IA0B3C,KAAK,IAAI,IAAI;IAEb,UAAU,CAAC,UAAU,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAS1F,MAAM,CAAC,KAAK,EAAE,eAAe,GAAG,aAAa;IAmC7C;;;;OAIG;IACH,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,GAAG,oBAAoB;IA2DtE,6EAA6E;IAC7E,qBAAqB,CACnB,UAAU,EAAE,eAAe,EAC3B,eAAe,EAAE,SAAS,MAAM,EAAE,GACjC,oBAAoB,EAAE;IA6BzB,KAAK,CAAC,KAAK,EAAE,YAAY,GAAG,aAAa,EAAE;IAuC3C,OAAO,CAAC,KAAK,EAAE,mBAAmB,GAAG,cAAc;IA8EnD,MAAM,IAAI,gBAAgB;CAmE3B"}