@dsh-enhanced/preference-learning 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/service.js ADDED
@@ -0,0 +1,260 @@
1
+ import { Context, Service } from '@deepseek-ai/cordis';
2
+ import Schema from '@deepseek-ai/schemastery';
3
+ import { PreferenceStore, canonicalPreferenceScope } from './store.js';
4
+ import { registerPreferenceTools } from './tools.js';
5
+ const configSchema = Schema.object({
6
+ enabled: Schema.boolean().default(true),
7
+ databasePath: Schema.string().required(),
8
+ signalTtlMs: Schema.number().step(1).min(86_400_000).max(31_536_000_000).default(7_776_000_000),
9
+ hypothesisTtlMs: Schema.number().step(1).min(3_600_000).max(2_592_000_000).default(2_592_000_000),
10
+ minSignalsForActivation: Schema.number().step(1).min(2).max(20).default(2),
11
+ minConfidenceBps: Schema.number().step(1).min(6_000).max(9_500).default(7_500),
12
+ maxContradictionBps: Schema.number().step(1).min(0).max(4_000).default(2_500),
13
+ maxActiveOverlays: Schema.number().step(1).min(1).max(8).default(6),
14
+ maxReviewHypotheses: Schema.number().step(1).min(1).max(50).default(20),
15
+ maxOverlayBytes: Schema.number().step(1).min(256).max(2_048).default(2_048),
16
+ maintenanceIntervalMs: Schema.number().step(1).min(60_000).max(86_400_000).default(3_600_000),
17
+ maintenanceBatchSize: Schema.number().step(1).min(1).max(5_000).default(500),
18
+ });
19
+ export class PreferenceLearningError extends Error {
20
+ code;
21
+ constructor(code, message) {
22
+ super(message);
23
+ this.code = code;
24
+ this.name = 'PreferenceLearningError';
25
+ }
26
+ }
27
+ function decisionError(decision) {
28
+ return new PreferenceLearningError('policy-denied', `preference access denied: ${decision.reasonCode}`);
29
+ }
30
+ export class PreferenceLearningService extends Service {
31
+ static Config = configSchema;
32
+ static inject = ['assistantPolicy', 'systemPrompt'];
33
+ store;
34
+ policy;
35
+ config;
36
+ active = true;
37
+ constructor(ctx, input, options = {}) {
38
+ super(ctx, 'assistantPreferenceLearning');
39
+ try {
40
+ this.config = configSchema(input);
41
+ }
42
+ catch (error) {
43
+ throw new Error(`preference-learning: invalid configuration: ${String(error)}`, { cause: error });
44
+ }
45
+ if (this.config.hypothesisTtlMs > this.config.signalTtlMs) {
46
+ throw new Error('preference-learning: hypothesisTtlMs must not exceed signalTtlMs');
47
+ }
48
+ const policy = ctx.get('assistantPolicy');
49
+ if (policy === undefined)
50
+ throw new Error('preference-learning: assistantPolicy service is required');
51
+ this.policy = policy;
52
+ this.store = new PreferenceStore({
53
+ path: this.config.databasePath,
54
+ ...(options.now === undefined ? {} : { now: options.now }),
55
+ signalTtlMs: this.config.signalTtlMs,
56
+ hypothesisTtlMs: this.config.hypothesisTtlMs,
57
+ minSignalsForActivation: this.config.minSignalsForActivation,
58
+ minConfidenceBps: this.config.minConfidenceBps,
59
+ maxContradictionBps: this.config.maxContradictionBps,
60
+ maxActiveOverlays: this.config.maxActiveOverlays,
61
+ maxReviewHypotheses: this.config.maxReviewHypotheses,
62
+ maxOverlayBytes: this.config.maxOverlayBytes,
63
+ });
64
+ // Runtime context is re-evaluated before every model step. The AgentLoop
65
+ // projection replaces or clears its prior snapshot, so rollback, expiry,
66
+ // forget, disable/unload, and resumed sessions cannot retain stale policy.
67
+ ctx.systemPrompt.context({
68
+ name: 'preference-learning:active-overlay',
69
+ order: 250,
70
+ text: ({ agent }) => this.dynamicOverlay(agent),
71
+ });
72
+ ctx.inject(['assistantDelivery'], deliveryCtx => {
73
+ if (!this.config.enabled)
74
+ return;
75
+ const delivery = deliveryCtx.get('assistantDelivery');
76
+ if (delivery === undefined || typeof delivery.subscribePreferenceFeedback !== 'function')
77
+ return;
78
+ return delivery.subscribePreferenceFeedback(events => this.appendDeliveryFeedbackBatch(events));
79
+ });
80
+ const registeredTools = ctx.get('tools');
81
+ const disposeCurrentTools = registeredTools === undefined
82
+ ? undefined
83
+ : registerPreferenceTools(registeredTools, this);
84
+ ctx.inject(['tools'], toolsCtx => {
85
+ const tools = toolsCtx.tools;
86
+ if (tools === registeredTools)
87
+ return;
88
+ return registerPreferenceTools(tools, this);
89
+ });
90
+ this.store.maintain(this.config.maintenanceBatchSize);
91
+ const maintenanceTimer = setInterval(() => {
92
+ if (!this.active)
93
+ return;
94
+ try {
95
+ this.store.maintain(this.config.maintenanceBatchSize);
96
+ }
97
+ catch {
98
+ ctx.logger.warn('preference-learning: bounded retention maintenance failed');
99
+ }
100
+ }, this.config.maintenanceIntervalMs);
101
+ maintenanceTimer.unref();
102
+ ctx.effect(() => () => {
103
+ this.active = false;
104
+ clearInterval(maintenanceTimer);
105
+ disposeCurrentTools?.();
106
+ this.store.close();
107
+ }, 'preference-learning.database');
108
+ }
109
+ /**
110
+ * Unprivileged observation seam. Actor/source authority is assigned here;
111
+ * callers cannot use it to claim owner feedback or unlock an effect.
112
+ */
113
+ appendObservation(input) {
114
+ this.assertActive();
115
+ this.assertEnabled();
116
+ if (input.interpretationTrust !== 'behavioral-inference'
117
+ && input.interpretationTrust !== 'model-inference') {
118
+ throw new PreferenceLearningError('unattested-signal', 'unattested observations cannot claim explicit or typed owner feedback');
119
+ }
120
+ if (!['delivery-observation', 'evaluation-outcome', 'system-observation'].includes(input.source)) {
121
+ throw new PreferenceLearningError('unattested-signal', 'unattested observations cannot claim an authenticated feedback source');
122
+ }
123
+ return this.store.appendSignal({
124
+ ...input,
125
+ actorTrust: 'system-attested',
126
+ idempotencyKey: `unattested-observation:${input.idempotencyKey}`,
127
+ });
128
+ }
129
+ review(agent, limit) {
130
+ this.assertActive();
131
+ const scope = this.authorizedScope(agent, 'review', 'hypotheses');
132
+ const hypotheses = this.store.list(scope, limit);
133
+ return Object.freeze({
134
+ hypotheses: Object.freeze(hypotheses),
135
+ activeOverlay: this.config.enabled ? this.store.overlay(scope) : undefined,
136
+ });
137
+ }
138
+ activate(agent, hypothesisId, expectedVersion) {
139
+ this.assertActive();
140
+ this.assertEnabled();
141
+ const scope = this.authorizedScope(agent, 'activate', hypothesisId);
142
+ return this.store.activate(scope, hypothesisId, expectedVersion);
143
+ }
144
+ rollback(agent, hypothesisId, expectedVersion, reason) {
145
+ this.assertActive();
146
+ const scope = this.authorizedScope(agent, 'rollback', hypothesisId);
147
+ return this.store.rollback(scope, hypothesisId, expectedVersion, reason);
148
+ }
149
+ /** Host-only privacy seam. It removes exact-scope rows and retains only a scope digest tombstone. */
150
+ forgetScope(scope, idempotencyKey) {
151
+ this.assertActive();
152
+ return this.store.forgetScope(scope, idempotencyKey);
153
+ }
154
+ health() {
155
+ this.assertActive();
156
+ return Object.freeze({ ...this.store.health(), enabled: this.config.enabled });
157
+ }
158
+ limits() {
159
+ this.assertActive();
160
+ return Object.freeze({
161
+ signalTtlMs: this.config.signalTtlMs,
162
+ hypothesisTtlMs: this.config.hypothesisTtlMs,
163
+ minSignalsForActivation: this.config.minSignalsForActivation,
164
+ minConfidenceBps: this.config.minConfidenceBps,
165
+ maxContradictionBps: this.config.maxContradictionBps,
166
+ maxActiveOverlays: this.config.maxActiveOverlays,
167
+ maxReviewHypotheses: this.config.maxReviewHypotheses,
168
+ maxOverlayBytes: this.config.maxOverlayBytes,
169
+ maintenanceIntervalMs: this.config.maintenanceIntervalMs,
170
+ maintenanceBatchSize: this.config.maintenanceBatchSize,
171
+ });
172
+ }
173
+ /** Safe bounded maintenance seam used by health jobs and deterministic tests. */
174
+ maintain() {
175
+ this.assertActive();
176
+ return this.store.maintain(this.config.maintenanceBatchSize);
177
+ }
178
+ /** Host integration seam for foreground prompt composition. */
179
+ overlayForAgent(agent) {
180
+ this.assertActive();
181
+ if (!this.config.enabled)
182
+ return undefined;
183
+ const scope = this.authorizedScope(agent, 'snapshot', 'active');
184
+ return this.store.overlay(scope);
185
+ }
186
+ dynamicOverlay(agent) {
187
+ if (!this.config.enabled || agent === undefined)
188
+ return '';
189
+ try {
190
+ return this.overlayForAgent(agent) ?? '';
191
+ }
192
+ catch {
193
+ this.ctx.logger.warn('preference-learning: current scoped overlay is unavailable');
194
+ return '';
195
+ }
196
+ }
197
+ /**
198
+ * The closure is registered directly with Assistant Delivery. No public
199
+ * service method accepts owner-authenticated provenance.
200
+ */
201
+ appendDeliveryFeedbackBatch(events) {
202
+ this.assertActive();
203
+ this.assertEnabled();
204
+ if (!Array.isArray(events) || events.length < 1 || events.length > 16) {
205
+ throw new PreferenceLearningError('unattested-signal', 'delivery feedback batch is invalid');
206
+ }
207
+ const signals = events.map(event => {
208
+ if (event.stance !== 'support'
209
+ || event.actorTrust !== 'owner-authenticated'
210
+ || event.interpretationTrust !== 'typed-feedback'
211
+ || event.source !== 'direct-owner-feedback') {
212
+ throw new PreferenceLearningError('unattested-signal', 'delivery feedback attestation is invalid');
213
+ }
214
+ return {
215
+ scope: { workspace: event.scope.workspace, preset: event.scope.preset },
216
+ preferenceKey: event.preferenceKey,
217
+ candidateValue: event.candidateValue,
218
+ stance: 'support',
219
+ actorTrust: 'owner-authenticated',
220
+ interpretationTrust: 'typed-feedback',
221
+ source: 'direct-owner-feedback',
222
+ occurredAt: event.occurredAt,
223
+ idempotencyKey: `assistant-delivery:${event.idempotencyKey}`,
224
+ };
225
+ });
226
+ this.store.appendSignals(signals);
227
+ return Object.freeze(events.map(event => Object.freeze({
228
+ idempotencyKey: event.idempotencyKey,
229
+ status: 'recorded',
230
+ })));
231
+ }
232
+ authorizedScope(agent, action, resourceId) {
233
+ const header = agent?.session?.header;
234
+ if (agent === undefined || header === undefined
235
+ || typeof header.cwd !== 'string' || typeof header.agentPreset !== 'string') {
236
+ throw new PreferenceLearningError('missing-agent', `missing-agent: preference ${action} requires a trusted Agent`);
237
+ }
238
+ let scope;
239
+ try {
240
+ scope = canonicalPreferenceScope({ workspace: header.cwd, preset: header.agentPreset }).scope;
241
+ }
242
+ catch {
243
+ throw new PreferenceLearningError('missing-agent', `missing-agent: preference ${action} requires a valid scope`);
244
+ }
245
+ const decision = this.policy.authorizeAgent(agent, action, { kind: 'preference', id: resourceId }, { idempotencyKey: `preference:${action}:${agent.id}:${resourceId}` });
246
+ if (decision.effect !== 'allow')
247
+ throw decisionError(decision);
248
+ return scope;
249
+ }
250
+ assertEnabled() {
251
+ if (!this.config.enabled)
252
+ throw new PreferenceLearningError('disabled', 'preference learning is disabled');
253
+ }
254
+ assertActive() {
255
+ if (!this.active)
256
+ throw new PreferenceLearningError('disposed', 'preference-learning service is disposed');
257
+ }
258
+ }
259
+ export const Config = configSchema;
260
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { DatabaseSync } from 'node:sqlite';
2
+ export declare const preferenceSchemaVersion = 1;
3
+ export type PreferenceDatabaseErrorCode = 'invalid-path' | 'unsafe-file' | 'schema-too-new';
4
+ export declare class PreferenceDatabaseError extends Error {
5
+ readonly code: PreferenceDatabaseErrorCode;
6
+ constructor(code: PreferenceDatabaseErrorCode, message: string);
7
+ }
8
+ export declare function openPreferenceDatabase(path: string): DatabaseSync;
9
+ //# sourceMappingURL=sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC,MAAM,MAAM,2BAA2B,GAAG,cAAc,GAAG,aAAa,GAAG,gBAAgB,CAAA;AAE3F,qBAAa,uBAAwB,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,2BAA2B;gBAAjC,IAAI,EAAE,2BAA2B,EAAE,OAAO,EAAE,MAAM;CAIxE;AAwLD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAqBjE"}
package/lib/sqlite.js ADDED
@@ -0,0 +1,214 @@
1
+ import { chmodSync, closeSync, constants, lstatSync, mkdirSync, openSync, } from 'node:fs';
2
+ import { dirname, isAbsolute } from 'node:path';
3
+ import { DatabaseSync } from 'node:sqlite';
4
+ export const preferenceSchemaVersion = 1;
5
+ export class PreferenceDatabaseError extends Error {
6
+ code;
7
+ constructor(code, message) {
8
+ super(message);
9
+ this.code = code;
10
+ this.name = 'PreferenceDatabaseError';
11
+ }
12
+ }
13
+ function assertSafeFile(path) {
14
+ const stat = lstatSync(path);
15
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1) {
16
+ throw new PreferenceDatabaseError('unsafe-file', 'preference database must be one regular, unlinked file');
17
+ }
18
+ if ((stat.mode & 0o077) !== 0) {
19
+ throw new PreferenceDatabaseError('unsafe-file', 'preference 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 PreferenceDatabaseError('unsafe-file', 'preference database must be owned by the current OS user');
24
+ }
25
+ }
26
+ function preparePrivateFile(path) {
27
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
28
+ try {
29
+ const descriptor = openSync(path, constants.O_CREAT | constants.O_EXCL | constants.O_RDWR, 0o600);
30
+ closeSync(descriptor);
31
+ }
32
+ catch (error) {
33
+ if (!(error instanceof Error && 'code' in error && error.code === 'EEXIST'))
34
+ throw error;
35
+ }
36
+ assertSafeFile(path);
37
+ }
38
+ function userVersion(database) {
39
+ return database.prepare('PRAGMA user_version').get().user_version;
40
+ }
41
+ function migrate(database) {
42
+ let transactionStarted = false;
43
+ try {
44
+ database.exec('BEGIN IMMEDIATE');
45
+ transactionStarted = true;
46
+ // The version must be read while holding the write reservation. Another process may
47
+ // have completed the same migration while this connection was waiting for the lock.
48
+ const current = userVersion(database);
49
+ if (current > preferenceSchemaVersion) {
50
+ throw new PreferenceDatabaseError('schema-too-new', `preference schema ${current} is newer than supported schema ${preferenceSchemaVersion}`);
51
+ }
52
+ if (current === preferenceSchemaVersion) {
53
+ database.exec('COMMIT');
54
+ transactionStarted = false;
55
+ return;
56
+ }
57
+ database.exec(`
58
+ CREATE TABLE preference_schema_meta (
59
+ key TEXT PRIMARY KEY,
60
+ value TEXT NOT NULL
61
+ ) STRICT;
62
+
63
+ CREATE TABLE preference_signals (
64
+ id TEXT PRIMARY KEY,
65
+ idempotency_key TEXT NOT NULL UNIQUE,
66
+ payload_hash TEXT NOT NULL,
67
+ scope_key TEXT NOT NULL,
68
+ workspace TEXT NOT NULL,
69
+ preset TEXT NOT NULL,
70
+ preference_key TEXT NOT NULL,
71
+ candidate_value TEXT NOT NULL,
72
+ risk_tier TEXT NOT NULL CHECK (risk_tier IN ('T0', 'T1', 'T2', 'T3')),
73
+ stance TEXT NOT NULL CHECK (stance IN ('support', 'contradict')),
74
+ actor_trust TEXT NOT NULL CHECK (actor_trust IN (
75
+ 'owner-authenticated', 'delegated-authenticated', 'system-attested', 'unverified'
76
+ )),
77
+ interpretation_trust TEXT NOT NULL CHECK (interpretation_trust IN (
78
+ 'explicit-selection', 'typed-feedback', 'behavioral-inference', 'model-inference'
79
+ )),
80
+ source TEXT NOT NULL CHECK (source IN (
81
+ 'direct-owner-feedback', 'signed-ui-feedback', 'delivery-observation',
82
+ 'evaluation-outcome', 'system-observation'
83
+ )),
84
+ occurred_at INTEGER NOT NULL,
85
+ recorded_at INTEGER NOT NULL
86
+ ) STRICT;
87
+ CREATE INDEX preference_signals_scope_key_time
88
+ ON preference_signals(scope_key, preference_key, occurred_at DESC, id DESC);
89
+
90
+ CREATE TABLE preference_hypotheses (
91
+ id TEXT PRIMARY KEY,
92
+ scope_key TEXT NOT NULL,
93
+ workspace TEXT NOT NULL,
94
+ preset TEXT NOT NULL,
95
+ preference_key TEXT NOT NULL,
96
+ candidate_value TEXT NOT NULL,
97
+ risk_tier TEXT NOT NULL CHECK (risk_tier IN ('T1', 'T2')),
98
+ claim_state TEXT NOT NULL CHECK (claim_state IN (
99
+ 'tentative', 'proposed', 'confirmed', 'rejected', 'expired'
100
+ )),
101
+ effect_state TEXT NOT NULL CHECK (effect_state IN (
102
+ 'shadow', 'active', 'suppressed', 'rolled-back', 'inactive'
103
+ )),
104
+ confidence_bps INTEGER NOT NULL,
105
+ contradiction_bps INTEGER NOT NULL,
106
+ supporting_signals INTEGER NOT NULL,
107
+ contradicting_signals INTEGER NOT NULL,
108
+ evidence_mass INTEGER NOT NULL,
109
+ expires_at INTEGER NOT NULL,
110
+ activated_at INTEGER,
111
+ rolled_back_at INTEGER,
112
+ version INTEGER NOT NULL,
113
+ created_at INTEGER NOT NULL,
114
+ updated_at INTEGER NOT NULL,
115
+ UNIQUE(scope_key, preference_key, candidate_value)
116
+ ) STRICT;
117
+ CREATE INDEX preference_hypotheses_scope_state
118
+ ON preference_hypotheses(scope_key, effect_state, updated_at DESC, id DESC);
119
+ CREATE UNIQUE INDEX preference_hypotheses_one_active_key
120
+ ON preference_hypotheses(scope_key, preference_key) WHERE effect_state = 'active';
121
+
122
+ CREATE TABLE preference_transitions (
123
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
124
+ hypothesis_id TEXT NOT NULL,
125
+ from_claim_state TEXT,
126
+ to_claim_state TEXT NOT NULL,
127
+ from_effect_state TEXT,
128
+ to_effect_state TEXT NOT NULL,
129
+ reason TEXT NOT NULL CHECK (reason IN (
130
+ 'created', 'evidence-updated', 'activated', 'owner-rejected', 'contradicted',
131
+ 'regression', 'expired', 'superseded', 'operator-request'
132
+ )),
133
+ version INTEGER NOT NULL,
134
+ occurred_at INTEGER NOT NULL,
135
+ FOREIGN KEY (hypothesis_id) REFERENCES preference_hypotheses(id) ON DELETE RESTRICT
136
+ ) STRICT;
137
+ CREATE INDEX preference_transitions_hypothesis
138
+ ON preference_transitions(hypothesis_id, version DESC, id DESC);
139
+
140
+ CREATE TABLE preference_scope_tombstones (
141
+ id TEXT PRIMARY KEY,
142
+ scope_digest TEXT NOT NULL,
143
+ idempotency_key TEXT NOT NULL UNIQUE,
144
+ payload_hash TEXT NOT NULL,
145
+ forgotten_through INTEGER NOT NULL,
146
+ recorded_at INTEGER NOT NULL,
147
+ deleted_signals INTEGER NOT NULL,
148
+ deleted_hypotheses INTEGER NOT NULL
149
+ ) STRICT;
150
+ CREATE INDEX preference_scope_tombstones_scope
151
+ ON preference_scope_tombstones(scope_digest, forgotten_through DESC, id DESC);
152
+
153
+ INSERT INTO preference_schema_meta(key, value) VALUES ('schema-version', '1');
154
+ PRAGMA user_version = 1;
155
+ `);
156
+ database.exec('COMMIT');
157
+ transactionStarted = false;
158
+ }
159
+ catch (error) {
160
+ if (transactionStarted) {
161
+ try {
162
+ database.exec('ROLLBACK');
163
+ }
164
+ catch (rollbackError) {
165
+ throw new AggregateError([error, rollbackError], 'preference schema migration and rollback failed');
166
+ }
167
+ }
168
+ throw error;
169
+ }
170
+ }
171
+ const walRetryWait = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
172
+ function enableWal(database) {
173
+ const deadline = Date.now() + 5_000;
174
+ while (true) {
175
+ try {
176
+ const row = database.prepare('PRAGMA journal_mode = WAL').get();
177
+ if (row.journal_mode.toLowerCase() !== 'wal') {
178
+ throw new Error(`preference database refused WAL mode: ${row.journal_mode}`);
179
+ }
180
+ return;
181
+ }
182
+ catch (error) {
183
+ const retryable = error instanceof Error && /database is (?:busy|locked)/i.test(error.message);
184
+ if (!retryable || Date.now() >= deadline)
185
+ throw error;
186
+ Atomics.wait(walRetryWait, 0, 0, 10);
187
+ }
188
+ }
189
+ }
190
+ export function openPreferenceDatabase(path) {
191
+ if (path !== ':memory:' && !isAbsolute(path)) {
192
+ throw new PreferenceDatabaseError('invalid-path', 'preference database path must be absolute');
193
+ }
194
+ if (path !== ':memory:')
195
+ preparePrivateFile(path);
196
+ const database = new DatabaseSync(path);
197
+ try {
198
+ database.exec('PRAGMA foreign_keys = ON');
199
+ database.exec('PRAGMA busy_timeout = 5000');
200
+ database.exec('PRAGMA synchronous = FULL');
201
+ database.exec('PRAGMA secure_delete = ON');
202
+ migrate(database);
203
+ if (path !== ':memory:') {
204
+ enableWal(database);
205
+ chmodSync(path, 0o600);
206
+ }
207
+ return database;
208
+ }
209
+ catch (error) {
210
+ database.close();
211
+ throw error;
212
+ }
213
+ }
214
+ //# 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,47 @@
1
+ import type { PreferenceHealth, PreferenceHypothesis, PreferenceMaintenanceResult, PreferenceRollbackReason, PreferenceScope, PreferenceSignalInput, StoredPreferenceSignal } from './types.js';
2
+ export type PreferenceStoreErrorCode = 'conflict' | 'disabled' | 'forbidden-tier' | 'idempotency-conflict' | 'invalid-input' | 'not-found' | 'not-ready' | 'privacy-purge-pending' | 'scope-forgotten';
3
+ export declare class PreferenceStoreError extends Error {
4
+ readonly code: PreferenceStoreErrorCode;
5
+ constructor(code: PreferenceStoreErrorCode, message: string);
6
+ }
7
+ export interface PreferenceStoreOptions {
8
+ path: string;
9
+ now?: () => number;
10
+ signalTtlMs: number;
11
+ hypothesisTtlMs: number;
12
+ minSignalsForActivation: number;
13
+ minConfidenceBps: number;
14
+ maxContradictionBps: number;
15
+ maxActiveOverlays: number;
16
+ maxReviewHypotheses: number;
17
+ maxOverlayBytes: number;
18
+ }
19
+ export interface PreferenceForgetResult {
20
+ replayed: boolean;
21
+ forgottenThrough: number;
22
+ deletedSignals: number;
23
+ deletedHypotheses: number;
24
+ }
25
+ export declare function canonicalPreferenceScope(input: PreferenceScope): {
26
+ scope: PreferenceScope;
27
+ scopeKey: string;
28
+ scopeDigest: string;
29
+ };
30
+ export declare class PreferenceStore {
31
+ #private;
32
+ constructor(options: PreferenceStoreOptions);
33
+ appendSignal(input: PreferenceSignalInput): StoredPreferenceSignal;
34
+ /** Atomically record one small producer batch and reconcile each affected key once. */
35
+ appendSignals(inputs: readonly PreferenceSignalInput[]): StoredPreferenceSignal[];
36
+ list(scopeInput: PreferenceScope, limit?: number): PreferenceHypothesis[];
37
+ get(scopeInput: PreferenceScope, hypothesisIdInput: string): PreferenceHypothesis | undefined;
38
+ activate(scopeInput: PreferenceScope, hypothesisIdInput: string, expectedVersion: number): PreferenceHypothesis;
39
+ rollback(scopeInput: PreferenceScope, hypothesisIdInput: string, expectedVersion: number, reasonInput: PreferenceRollbackReason): PreferenceHypothesis;
40
+ overlay(scopeInput: PreferenceScope): string | undefined;
41
+ forgetScope(scopeInput: PreferenceScope, idempotencyKeyInput: string): PreferenceForgetResult;
42
+ health(): PreferenceHealth;
43
+ /** Delete one bounded batch whose evidence-retention window has elapsed. */
44
+ maintain(limit?: number): PreferenceMaintenanceResult;
45
+ close(): void;
46
+ }
47
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAIV,gBAAgB,EAChB,oBAAoB,EAEpB,2BAA2B,EAC3B,wBAAwB,EACxB,eAAe,EACf,qBAAqB,EAGrB,sBAAsB,EACvB,MAAM,YAAY,CAAA;AAEnB,MAAM,MAAM,wBAAwB,GAChC,UAAU,GACV,UAAU,GACV,gBAAgB,GAChB,sBAAsB,GACtB,eAAe,GACf,WAAW,GACX,WAAW,GACX,uBAAuB,GACvB,iBAAiB,CAAA;AAErB,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,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,gBAAgB,EAAE,MAAM,CAAA;IACxB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,iBAAiB,EAAE,MAAM,CAAA;IACzB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,OAAO,CAAA;IACjB,gBAAgB,EAAE,MAAM,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;CAC1B;AAuFD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,eAAe,GAAG;IAChE,KAAK,EAAE,eAAe,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB,CAaA;AAkFD,qBAAa,eAAe;;gBAMd,OAAO,EAAE,sBAAsB;IAe3C,YAAY,CAAC,KAAK,EAAE,qBAAqB,GAAG,sBAAsB;IAIlE,uFAAuF;IACvF,aAAa,CAAC,MAAM,EAAE,SAAS,qBAAqB,EAAE,GAAG,sBAAsB,EAAE;IAkFjF,IAAI,CAAC,UAAU,EAAE,eAAe,EAAE,KAAK,SAAoC,GAAG,oBAAoB,EAAE;IAsBpG,GAAG,CAAC,UAAU,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS;IAW7F,QAAQ,CAAC,UAAU,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,oBAAoB;IAkE/G,QAAQ,CACN,UAAU,EAAE,eAAe,EAC3B,iBAAiB,EAAE,MAAM,EACzB,eAAe,EAAE,MAAM,EACvB,WAAW,EAAE,wBAAwB,GACpC,oBAAoB;IAoCvB,OAAO,CAAC,UAAU,EAAE,eAAe,GAAG,MAAM,GAAG,SAAS;IAwBxD,WAAW,CACT,UAAU,EAAE,eAAe,EAC3B,mBAAmB,EAAE,MAAM,GAC1B,sBAAsB;IAsEzB,MAAM,IAAI,gBAAgB;IAiC1B,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,SAAM,GAAG,2BAA2B;IA8BlD,KAAK,IAAI,IAAI;CAgUd"}