instar 1.3.131 → 1.3.133

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 (70) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +92 -1
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  5. package/dist/config/ConfigDefaults.js +10 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  8. package/dist/core/PostUpdateMigrator.js +35 -2
  9. package/dist/core/PostUpdateMigrator.js.map +1 -1
  10. package/dist/core/types.d.ts +12 -0
  11. package/dist/core/types.d.ts.map +1 -1
  12. package/dist/core/types.js.map +1 -1
  13. package/dist/monitoring/AgentWorktreeReaper.d.ts +103 -0
  14. package/dist/monitoring/AgentWorktreeReaper.d.ts.map +1 -0
  15. package/dist/monitoring/AgentWorktreeReaper.js +159 -0
  16. package/dist/monitoring/AgentWorktreeReaper.js.map +1 -0
  17. package/dist/monitoring/CiFailurePoller.d.ts +1 -7
  18. package/dist/monitoring/CiFailurePoller.d.ts.map +1 -1
  19. package/dist/monitoring/CiFailurePoller.js +5 -12
  20. package/dist/monitoring/CiFailurePoller.js.map +1 -1
  21. package/dist/monitoring/CorrectionAnalyzer.d.ts +65 -0
  22. package/dist/monitoring/CorrectionAnalyzer.d.ts.map +1 -0
  23. package/dist/monitoring/CorrectionAnalyzer.js +78 -0
  24. package/dist/monitoring/CorrectionAnalyzer.js.map +1 -0
  25. package/dist/monitoring/CorrectionCaptureLoop.d.ts +130 -0
  26. package/dist/monitoring/CorrectionCaptureLoop.d.ts.map +1 -0
  27. package/dist/monitoring/CorrectionCaptureLoop.js +249 -0
  28. package/dist/monitoring/CorrectionCaptureLoop.js.map +1 -0
  29. package/dist/monitoring/CorrectionLedger.d.ts +149 -0
  30. package/dist/monitoring/CorrectionLedger.d.ts.map +1 -0
  31. package/dist/monitoring/CorrectionLedger.js +386 -0
  32. package/dist/monitoring/CorrectionLedger.js.map +1 -0
  33. package/dist/monitoring/CorrectionLoopDriver.d.ts +135 -0
  34. package/dist/monitoring/CorrectionLoopDriver.d.ts.map +1 -0
  35. package/dist/monitoring/CorrectionLoopDriver.js +185 -0
  36. package/dist/monitoring/CorrectionLoopDriver.js.map +1 -0
  37. package/dist/monitoring/HumanAsDetectorLog.d.ts +31 -1
  38. package/dist/monitoring/HumanAsDetectorLog.d.ts.map +1 -1
  39. package/dist/monitoring/HumanAsDetectorLog.js +70 -0
  40. package/dist/monitoring/HumanAsDetectorLog.js.map +1 -1
  41. package/dist/monitoring/agentWorktreeGit.d.ts +43 -0
  42. package/dist/monitoring/agentWorktreeGit.d.ts.map +1 -0
  43. package/dist/monitoring/agentWorktreeGit.js +194 -0
  44. package/dist/monitoring/agentWorktreeGit.js.map +1 -0
  45. package/dist/monitoring/scrubSecrets.d.ts +23 -0
  46. package/dist/monitoring/scrubSecrets.d.ts.map +1 -0
  47. package/dist/monitoring/scrubSecrets.js +41 -0
  48. package/dist/monitoring/scrubSecrets.js.map +1 -0
  49. package/dist/scaffold/templates.d.ts.map +1 -1
  50. package/dist/scaffold/templates.js +1 -0
  51. package/dist/scaffold/templates.js.map +1 -1
  52. package/dist/server/AgentServer.d.ts +4 -0
  53. package/dist/server/AgentServer.d.ts.map +1 -1
  54. package/dist/server/AgentServer.js +20 -0
  55. package/dist/server/AgentServer.js.map +1 -1
  56. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  57. package/dist/server/CapabilityIndex.js +8 -3
  58. package/dist/server/CapabilityIndex.js.map +1 -1
  59. package/dist/server/routes.d.ts +7 -0
  60. package/dist/server/routes.d.ts.map +1 -1
  61. package/dist/server/routes.js +213 -0
  62. package/dist/server/routes.js.map +1 -1
  63. package/package.json +1 -1
  64. package/src/data/builtin-manifest.json +63 -63
  65. package/src/scaffold/templates/jobs/instar/correction-analyzer.md +32 -0
  66. package/src/scaffold/templates.ts +1 -0
  67. package/upgrades/1.3.132.md +42 -0
  68. package/upgrades/1.3.133.md +70 -0
  69. package/upgrades/side-effects/agent-worktree-reaper.md +96 -0
  70. package/upgrades/side-effects/correction-preference-learning-sentinel-slice1b.md +79 -0
@@ -0,0 +1,149 @@
1
+ /** The distilled kind. Validated against this allow-list — the LLM cannot widen it. */
2
+ export type CorrectionKind = 'infra-gap' | 'user-preference' | 'noise';
3
+ export type CorrectionStatus = 'open' | 'acted-on' | 'verified' | 'inconclusive' | 'reopened';
4
+ export interface CorrectionRecord {
5
+ id: string;
6
+ dedupeKey: string;
7
+ kind: CorrectionKind;
8
+ occurrenceCount: number;
9
+ detectedAt: string;
10
+ /** Post-scrubbed distilled lesson. INTERNAL-ONLY — never crosses HTTP. */
11
+ learning: string;
12
+ /** Post-scrubbed one-line summary. The ONLY text the API serves. */
13
+ scrubbedSummary: string;
14
+ /** UTC date bucket (YYYY-MM-DD), code-derived from detectedAt. */
15
+ dayBucket: string;
16
+ /** Layer-0 total weight at record time — the code-determined provenance. */
17
+ deterministicWeight: number;
18
+ /** LLM-assigned confidence [0,1] — ADVISORY, never alone admits a record. */
19
+ llmConfidence: number;
20
+ topicId: number | null;
21
+ sessionId: string | null;
22
+ /** Lifecycle */
23
+ status: CorrectionStatus;
24
+ routedVia?: string;
25
+ verifyWindowStart?: string;
26
+ verifyWindowEnd?: string;
27
+ reopenCount: number;
28
+ createdAt: string;
29
+ updatedAt: string;
30
+ version: number;
31
+ }
32
+ /** The shape served over HTTP — `learning` stripped, only scrubbed_summary + metadata. */
33
+ export interface CorrectionRecordApiView {
34
+ id: string;
35
+ dedupeKey: string;
36
+ kind: CorrectionKind;
37
+ occurrenceCount: number;
38
+ detectedAt: string;
39
+ scrubbedSummary: string;
40
+ dayBucket: string;
41
+ deterministicWeight: number;
42
+ llmConfidence: number;
43
+ topicId: number | null;
44
+ status: CorrectionStatus;
45
+ routedVia?: string;
46
+ verifyWindowStart?: string;
47
+ verifyWindowEnd?: string;
48
+ reopenCount: number;
49
+ createdAt: string;
50
+ updatedAt: string;
51
+ version: number;
52
+ }
53
+ export interface RecordCorrectionInput {
54
+ kind: CorrectionKind;
55
+ learning: string;
56
+ scrubbedSummary: string;
57
+ deterministicWeight: number;
58
+ llmConfidence?: number;
59
+ topicId?: number | null;
60
+ sessionId?: string | null;
61
+ detectedAt?: string;
62
+ }
63
+ export interface ListCorrectionFilter {
64
+ kind?: CorrectionKind;
65
+ status?: CorrectionStatus;
66
+ sinceMs?: number;
67
+ /** Upper-bound (exclusive): detected_at < beforeMs (keyset pagination). */
68
+ beforeMs?: number;
69
+ limit?: number;
70
+ }
71
+ export type CorrectionUpdateResult = {
72
+ ok: true;
73
+ record: CorrectionRecord;
74
+ } | {
75
+ ok: false;
76
+ conflict: true;
77
+ current?: CorrectionRecord;
78
+ } | {
79
+ ok: false;
80
+ conflict: false;
81
+ reason: string;
82
+ };
83
+ export interface CorrectionLedgerOptions {
84
+ dbPath: string;
85
+ machineId?: string;
86
+ onError?: (where: string, err: unknown) => void;
87
+ /** Cap on forensic occurrence rows per dedupeKey (default 200). */
88
+ maxOccurrencesPerKey?: number;
89
+ }
90
+ /** Default forensic-log retention per dedupeKey (mirrors FailureLedger §5). */
91
+ export declare const DEFAULT_MAX_OCCURRENCES_PER_KEY = 200;
92
+ export declare class CorrectionLedger {
93
+ private db;
94
+ private readonly machineId;
95
+ private readonly onError;
96
+ private readonly maxOccurrencesPerKey;
97
+ constructor(opts: CorrectionLedgerOptions);
98
+ /**
99
+ * Canonical normalization of a distilled learning before hashing: lowercase,
100
+ * strip punctuation, collapse whitespace, drop stop-words, sort the remaining
101
+ * tokens. Two semantically-identical learnings phrased differently collapse to
102
+ * the SAME hash. Stability is a unit-tested invariant (spec §3.4).
103
+ */
104
+ static normalizeLearning(learning: string): string;
105
+ /** SHA-256 over the canonical normalized form. */
106
+ static normalizedLearningHash(learning: string): string;
107
+ /** Deterministic dedupe key: `kind:normalizedLearningHash` (spec §3.4). */
108
+ static dedupeKey(kind: CorrectionKind, learning: string): string;
109
+ /** UTC day bucket (YYYY-MM-DD), code-derived from an ISO timestamp. */
110
+ static dayBucketOf(isoOrMs: string | number): string;
111
+ private nextId;
112
+ /**
113
+ * Record (or upsert) a distilled correction. A repeat on the same dedupeKey
114
+ * increments occurrenceCount + logs a distinct occurrence (feeds the
115
+ * distinct-day / distinct-topic gates) rather than duplicating. Fail-open:
116
+ * returns null on any storage error.
117
+ */
118
+ record(input: RecordCorrectionInput): CorrectionRecord | null;
119
+ get(id: string): CorrectionRecord | null;
120
+ getByDedupeKey(dedupeKey: string): CorrectionRecord | null;
121
+ list(filter?: ListCorrectionFilter): CorrectionRecord[];
122
+ /**
123
+ * Mutate a record's lifecycle. `ifMatch` is mandatory (OCC) — a stale version
124
+ * loses with {ok:false, conflict:true}.
125
+ */
126
+ update(id: string, patch: Partial<Pick<CorrectionRecord, 'status' | 'routedVia' | 'verifyWindowStart' | 'verifyWindowEnd' | 'reopenCount'>>, ifMatch: number): CorrectionUpdateResult;
127
+ /**
128
+ * Distinct calendar days + distinct topics for the recurrence gate (spec §3.5).
129
+ * Computed from the bounded occurrences table. Restart-proof (keys on UTC
130
+ * day_bucket, NOT a session count instar's frequent restarts would inflate).
131
+ * `qualifying` only counts occurrences whose deterministic_weight ≥ threshold
132
+ * (the code-determined provenance filter — an LLM-only-confident occurrence
133
+ * never alone admits a record to the gate).
134
+ */
135
+ distinctCounts(dedupeKey: string, weightThreshold?: number): {
136
+ distinctDays: number;
137
+ distinctTopics: number;
138
+ qualifyingOccurrences: number;
139
+ };
140
+ /** Total deduped record count — health metric for distinct-key growth (spec §3.4). */
141
+ countRecords(): number;
142
+ /** Raw forensic-log row count (observability + retention-cap test hook). */
143
+ countOccurrences(dedupeKey?: string): number;
144
+ /** Strip `learning` (raw distilled text) — the ONLY shape allowed over HTTP (spec §3.4). */
145
+ static toApiView(record: CorrectionRecord): CorrectionRecordApiView;
146
+ close(): void;
147
+ private rowToRecord;
148
+ }
149
+ //# sourceMappingURL=CorrectionLedger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CorrectionLedger.d.ts","sourceRoot":"","sources":["../../src/monitoring/CorrectionLedger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,386 @@
1
+ /**
2
+ * CorrectionLedger — distilled, scrubbed correction/preference records (spec §3.4).
3
+ *
4
+ * The conversational twin of FailureLedger. Where that ledger stores dev-process
5
+ * failures, this stores the LESSON distilled from a moment the user had to
6
+ * correct the agent — privacy-safe: ONLY the post-scrubbed `learning` +
7
+ * `scrubbed_summary` + metadata ever land here. Raw conversation never persists.
8
+ *
9
+ * Mirrors FailureLedger's discipline (spec §3.4):
10
+ * - dedupe-upsert keyed on `kind:normalizedLearningHash` so a recurring lesson
11
+ * collapses to ONE record (occurrenceCount increments) — message volume can
12
+ * never manufacture support.
13
+ * - `correction_occurrences` is a bounded forensic log (DEFAULT_MAX_OCCURRENCES_
14
+ * PER_KEY = 200, prune-in-transaction with the insert). The analyzer's
15
+ * distinct-day / distinct-topic counts are computed from this bounded table.
16
+ * - indexes idx_corr_dedupe + idx_corr_detected (explicitly required).
17
+ * - toApiView() strips everything but scrubbed_summary + metadata — the
18
+ * /corrections API never serves raw `learning` text.
19
+ * - countRecords() health metric so distinct-key growth (an unstable-hash LLM)
20
+ * is observable.
21
+ * - fail-open: a write error logs + drops; it never throws back into the
22
+ * capture/distill seam (which must keep its fire-and-forget contract).
23
+ *
24
+ * dayBucket is UTC, CODE-derived (never LLM-set). deterministicWeight is the
25
+ * Layer-0 total weight, CODE-set — it is the provenance field the analyzer's
26
+ * gate keys on (spec §3.5). llm_confidence is LLM-set + advisory only.
27
+ */
28
+ import Database from 'better-sqlite3';
29
+ import crypto from 'node:crypto';
30
+ import fs from 'node:fs';
31
+ import os from 'node:os';
32
+ import path from 'node:path';
33
+ import { NativeModuleHealer } from '../memory/NativeModuleHealer.js';
34
+ /** Default forensic-log retention per dedupeKey (mirrors FailureLedger §5). */
35
+ export const DEFAULT_MAX_OCCURRENCES_PER_KEY = 200;
36
+ /**
37
+ * Stop-words stripped before hashing so semantically-identical learnings phrased
38
+ * differently collapse to ONE dedupeKey. Conservative + deterministic — the hash
39
+ * stability is a unit-tested invariant.
40
+ */
41
+ const STOP_WORDS = new Set([
42
+ 'a', 'an', 'the', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
43
+ 'to', 'of', 'in', 'on', 'for', 'with', 'and', 'or', 'but', 'i', 'you',
44
+ 'me', 'my', 'your', 'it', 'this', 'that', 'please', 'just', 'always',
45
+ 'when', 'do', "don't", 'dont', "i'd", 'id', 'would', 'should', 'so',
46
+ 'at', 'by', 'as', 'from', 'into', 'about', 'prefer', 'rather',
47
+ ]);
48
+ // ── Schema ────────────────────────────────────────────────────────────
49
+ const SCHEMA = [
50
+ `CREATE TABLE IF NOT EXISTS correction_records (
51
+ id TEXT PRIMARY KEY,
52
+ dedupe_key TEXT NOT NULL UNIQUE,
53
+ kind TEXT NOT NULL,
54
+ occurrence_count INTEGER NOT NULL DEFAULT 1,
55
+ detected_at TEXT NOT NULL,
56
+ learning TEXT NOT NULL DEFAULT '',
57
+ scrubbed_summary TEXT NOT NULL DEFAULT '',
58
+ day_bucket TEXT NOT NULL,
59
+ deterministic_weight INTEGER NOT NULL DEFAULT 0,
60
+ llm_confidence REAL NOT NULL DEFAULT 0,
61
+ topic_id INTEGER,
62
+ session_id TEXT,
63
+ status TEXT NOT NULL DEFAULT 'open',
64
+ routed_via TEXT,
65
+ verify_window_start TEXT,
66
+ verify_window_end TEXT,
67
+ reopen_count INTEGER NOT NULL DEFAULT 0,
68
+ created_at TEXT NOT NULL,
69
+ updated_at TEXT NOT NULL,
70
+ version INTEGER NOT NULL DEFAULT 1
71
+ )`,
72
+ // Detected-at index for the analyzer's windowed scan + keyset pagination.
73
+ `CREATE INDEX IF NOT EXISTS idx_corr_detected ON correction_records(detected_at)`,
74
+ // Bounded forensic log — feeds COUNT(DISTINCT day_bucket / topic_id) for the
75
+ // analyzer's diversity prongs without growing an unbounded set on the record.
76
+ `CREATE TABLE IF NOT EXISTS correction_occurrences (
77
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
78
+ dedupe_key TEXT NOT NULL,
79
+ day_bucket TEXT NOT NULL,
80
+ topic_id INTEGER,
81
+ deterministic_weight INTEGER NOT NULL DEFAULT 0,
82
+ detected_at TEXT NOT NULL
83
+ )`,
84
+ `CREATE INDEX IF NOT EXISTS idx_corr_dedupe ON correction_occurrences(dedupe_key)`,
85
+ // Per-machine monotonic sequence for machine-scoped IDs.
86
+ `CREATE TABLE IF NOT EXISTS correction_seq (
87
+ machine_id TEXT PRIMARY KEY,
88
+ next_seq INTEGER NOT NULL DEFAULT 1
89
+ )`,
90
+ ];
91
+ // ── CorrectionLedger ──────────────────────────────────────────────────
92
+ export class CorrectionLedger {
93
+ db;
94
+ machineId;
95
+ onError;
96
+ maxOccurrencesPerKey;
97
+ constructor(opts) {
98
+ this.machineId = (opts.machineId || os.hostname() || 'local')
99
+ .replace(/[^a-zA-Z0-9]+/g, '-')
100
+ .replace(/^-+|-+$/g, '')
101
+ .slice(0, 24) || 'local';
102
+ this.maxOccurrencesPerKey =
103
+ opts.maxOccurrencesPerKey && opts.maxOccurrencesPerKey > 0
104
+ ? opts.maxOccurrencesPerKey
105
+ : DEFAULT_MAX_OCCURRENCES_PER_KEY;
106
+ this.onError =
107
+ opts.onError ?? ((where, err) => console.error(`[CorrectionLedger] ${where}:`, err));
108
+ if (opts.dbPath !== ':memory:') {
109
+ fs.mkdirSync(path.dirname(opts.dbPath), { recursive: true });
110
+ }
111
+ this.db = NativeModuleHealer.openWithHealSync('CorrectionLedger', () => new Database(opts.dbPath));
112
+ this.db.pragma('journal_mode = WAL');
113
+ this.db.pragma('synchronous = NORMAL');
114
+ for (const ddl of SCHEMA)
115
+ this.db.exec(ddl);
116
+ }
117
+ /**
118
+ * Canonical normalization of a distilled learning before hashing: lowercase,
119
+ * strip punctuation, collapse whitespace, drop stop-words, sort the remaining
120
+ * tokens. Two semantically-identical learnings phrased differently collapse to
121
+ * the SAME hash. Stability is a unit-tested invariant (spec §3.4).
122
+ */
123
+ static normalizeLearning(learning) {
124
+ const tokens = String(learning)
125
+ .toLowerCase()
126
+ .replace(/[^a-z0-9\s']/g, ' ')
127
+ .split(/\s+/)
128
+ .map((t) => t.trim())
129
+ .filter((t) => t.length > 0 && !STOP_WORDS.has(t));
130
+ return tokens.sort().join(' ');
131
+ }
132
+ /** SHA-256 over the canonical normalized form. */
133
+ static normalizedLearningHash(learning) {
134
+ return crypto.createHash('sha256').update(CorrectionLedger.normalizeLearning(learning)).digest('hex');
135
+ }
136
+ /** Deterministic dedupe key: `kind:normalizedLearningHash` (spec §3.4). */
137
+ static dedupeKey(kind, learning) {
138
+ return `${kind}:${CorrectionLedger.normalizedLearningHash(learning)}`;
139
+ }
140
+ /** UTC day bucket (YYYY-MM-DD), code-derived from an ISO timestamp. */
141
+ static dayBucketOf(isoOrMs) {
142
+ const d = typeof isoOrMs === 'number' ? new Date(isoOrMs) : new Date(isoOrMs);
143
+ return d.toISOString().slice(0, 10);
144
+ }
145
+ nextId() {
146
+ const row = this.db
147
+ .prepare(`SELECT next_seq FROM correction_seq WHERE machine_id = ?`)
148
+ .get(this.machineId);
149
+ const seq = row?.next_seq ?? 1;
150
+ this.db
151
+ .prepare(`INSERT INTO correction_seq (machine_id, next_seq) VALUES (?, ?)
152
+ ON CONFLICT(machine_id) DO UPDATE SET next_seq = ?`)
153
+ .run(this.machineId, seq + 1, seq + 1);
154
+ return `CORR-${this.machineId}-${String(seq).padStart(3, '0')}`;
155
+ }
156
+ /**
157
+ * Record (or upsert) a distilled correction. A repeat on the same dedupeKey
158
+ * increments occurrenceCount + logs a distinct occurrence (feeds the
159
+ * distinct-day / distinct-topic gates) rather than duplicating. Fail-open:
160
+ * returns null on any storage error.
161
+ */
162
+ record(input) {
163
+ try {
164
+ const dedupeKey = CorrectionLedger.dedupeKey(input.kind, input.learning);
165
+ const now = new Date().toISOString();
166
+ const detectedAt = input.detectedAt ?? now;
167
+ const dayBucket = CorrectionLedger.dayBucketOf(detectedAt);
168
+ const llmConfidence = clamp01(input.llmConfidence);
169
+ const txn = this.db.transaction(() => {
170
+ // Always log the occurrence (feeds COUNT(DISTINCT) diversity prongs).
171
+ this.db
172
+ .prepare(`INSERT INTO correction_occurrences (dedupe_key, day_bucket, topic_id, deterministic_weight, detected_at)
173
+ VALUES (?, ?, ?, ?, ?)`)
174
+ .run(dedupeKey, dayBucket, input.topicId ?? null, input.deterministicWeight, detectedAt);
175
+ // Bounded forensic log — prune occurrence rows for this key beyond the
176
+ // most-recent N. Safe: the analyzer's distinct counts are also bounded
177
+ // by N, so pruning cannot change a decision (worst case it UNDERcounts,
178
+ // the safe direction — biases toward NOT firing).
179
+ this.db
180
+ .prepare(`DELETE FROM correction_occurrences
181
+ WHERE dedupe_key = @dedupeKey
182
+ AND id NOT IN (
183
+ SELECT id FROM correction_occurrences
184
+ WHERE dedupe_key = @dedupeKey
185
+ ORDER BY id DESC LIMIT @keep)`)
186
+ .run({ dedupeKey, keep: this.maxOccurrencesPerKey });
187
+ const id = this.nextId();
188
+ const row = this.db
189
+ .prepare(`INSERT INTO correction_records
190
+ (id, dedupe_key, kind, occurrence_count, detected_at, learning, scrubbed_summary,
191
+ day_bucket, deterministic_weight, llm_confidence, topic_id, session_id,
192
+ status, reopen_count, created_at, updated_at, version)
193
+ VALUES
194
+ (@id, @dedupeKey, @kind, 1, @detectedAt, @learning, @scrubbedSummary,
195
+ @dayBucket, @deterministicWeight, @llmConfidence, @topicId, @sessionId,
196
+ 'open', 0, @createdAt, @updatedAt, 1)
197
+ ON CONFLICT(dedupe_key) DO UPDATE SET
198
+ occurrence_count = occurrence_count + 1,
199
+ detected_at = excluded.detected_at,
200
+ day_bucket = excluded.day_bucket,
201
+ -- keep the strongest deterministic weight seen for this key
202
+ deterministic_weight = MAX(deterministic_weight, excluded.deterministic_weight),
203
+ -- advisory: take the max confidence seen
204
+ llm_confidence = MAX(llm_confidence, excluded.llm_confidence),
205
+ updated_at = excluded.updated_at,
206
+ version = version + 1
207
+ RETURNING id`)
208
+ .get({
209
+ id,
210
+ dedupeKey,
211
+ kind: input.kind,
212
+ detectedAt,
213
+ learning: input.learning,
214
+ scrubbedSummary: input.scrubbedSummary,
215
+ dayBucket,
216
+ deterministicWeight: input.deterministicWeight,
217
+ llmConfidence,
218
+ topicId: input.topicId ?? null,
219
+ sessionId: input.sessionId ?? null,
220
+ createdAt: now,
221
+ updatedAt: now,
222
+ });
223
+ return row.id;
224
+ });
225
+ const id = txn();
226
+ return this.get(id);
227
+ }
228
+ catch (err) {
229
+ this.onError('record', err);
230
+ return null;
231
+ }
232
+ }
233
+ get(id) {
234
+ const row = this.db.prepare(`SELECT * FROM correction_records WHERE id = ?`).get(id);
235
+ return row ? this.rowToRecord(row) : null;
236
+ }
237
+ getByDedupeKey(dedupeKey) {
238
+ const row = this.db.prepare(`SELECT * FROM correction_records WHERE dedupe_key = ?`).get(dedupeKey);
239
+ return row ? this.rowToRecord(row) : null;
240
+ }
241
+ list(filter = {}) {
242
+ const where = [];
243
+ const params = {};
244
+ if (filter.kind) {
245
+ where.push('kind = @kind');
246
+ params.kind = filter.kind;
247
+ }
248
+ if (filter.status) {
249
+ where.push('status = @status');
250
+ params.status = filter.status;
251
+ }
252
+ if (filter.sinceMs) {
253
+ where.push('detected_at >= @since');
254
+ params.since = new Date(filter.sinceMs).toISOString();
255
+ }
256
+ if (filter.beforeMs) {
257
+ where.push('detected_at < @before');
258
+ params.before = new Date(filter.beforeMs).toISOString();
259
+ }
260
+ const limit = filter.limit && filter.limit > 0 ? Math.min(filter.limit, 1000) : 100;
261
+ const sql = `SELECT * FROM correction_records` +
262
+ (where.length ? ` WHERE ${where.join(' AND ')}` : '') +
263
+ ` ORDER BY detected_at DESC LIMIT ${limit}`;
264
+ return this.db.prepare(sql).all(params).map((r) => this.rowToRecord(r));
265
+ }
266
+ /**
267
+ * Mutate a record's lifecycle. `ifMatch` is mandatory (OCC) — a stale version
268
+ * loses with {ok:false, conflict:true}.
269
+ */
270
+ update(id, patch, ifMatch) {
271
+ try {
272
+ const current = this.get(id);
273
+ if (!current)
274
+ return { ok: false, conflict: false, reason: 'not-found' };
275
+ if (current.version !== ifMatch)
276
+ return { ok: false, conflict: true, current };
277
+ const map = {
278
+ status: 'status', routedVia: 'routed_via', verifyWindowStart: 'verify_window_start',
279
+ verifyWindowEnd: 'verify_window_end', reopenCount: 'reopen_count',
280
+ };
281
+ const cols = [];
282
+ const params = { id, ifMatch };
283
+ for (const [k, v] of Object.entries(patch)) {
284
+ const col = map[k];
285
+ if (!col)
286
+ continue;
287
+ cols.push(`${col} = @${k}`);
288
+ params[k] = v ?? null;
289
+ }
290
+ if (cols.length === 0)
291
+ return { ok: true, record: current };
292
+ const now = new Date().toISOString();
293
+ const res = this.db
294
+ .prepare(`UPDATE correction_records SET ${cols.join(', ')}, updated_at = @now, version = version + 1 WHERE id = @id AND version = @ifMatch`)
295
+ .run({ ...params, now });
296
+ if (res.changes === 0)
297
+ return { ok: false, conflict: true, current: this.get(id) ?? undefined };
298
+ return { ok: true, record: this.get(id) };
299
+ }
300
+ catch (err) {
301
+ this.onError('update', err);
302
+ return { ok: false, conflict: false, reason: 'storage-error' };
303
+ }
304
+ }
305
+ /**
306
+ * Distinct calendar days + distinct topics for the recurrence gate (spec §3.5).
307
+ * Computed from the bounded occurrences table. Restart-proof (keys on UTC
308
+ * day_bucket, NOT a session count instar's frequent restarts would inflate).
309
+ * `qualifying` only counts occurrences whose deterministic_weight ≥ threshold
310
+ * (the code-determined provenance filter — an LLM-only-confident occurrence
311
+ * never alone admits a record to the gate).
312
+ */
313
+ distinctCounts(dedupeKey, weightThreshold = 0) {
314
+ const row = this.db
315
+ .prepare(`SELECT COUNT(DISTINCT day_bucket) AS days,
316
+ COUNT(DISTINCT topic_id) AS topics,
317
+ COUNT(*) AS occ
318
+ FROM correction_occurrences
319
+ WHERE dedupe_key = @dedupeKey AND deterministic_weight >= @threshold`)
320
+ .get({ dedupeKey, threshold: weightThreshold });
321
+ return {
322
+ distinctDays: row?.days ?? 0,
323
+ distinctTopics: row?.topics ?? 0,
324
+ qualifyingOccurrences: row?.occ ?? 0,
325
+ };
326
+ }
327
+ /** Total deduped record count — health metric for distinct-key growth (spec §3.4). */
328
+ countRecords() {
329
+ const row = this.db.prepare(`SELECT COUNT(*) c FROM correction_records`).get();
330
+ return row?.c ?? 0;
331
+ }
332
+ /** Raw forensic-log row count (observability + retention-cap test hook). */
333
+ countOccurrences(dedupeKey) {
334
+ const row = dedupeKey
335
+ ? this.db.prepare(`SELECT COUNT(*) c FROM correction_occurrences WHERE dedupe_key = ?`).get(dedupeKey)
336
+ : this.db.prepare(`SELECT COUNT(*) c FROM correction_occurrences`).get();
337
+ return (row?.c) ?? 0;
338
+ }
339
+ /** Strip `learning` (raw distilled text) — the ONLY shape allowed over HTTP (spec §3.4). */
340
+ static toApiView(record) {
341
+ const { learning: _internalLearning, sessionId: _internalSession, ...rest } = record;
342
+ void _internalLearning;
343
+ void _internalSession;
344
+ return { ...rest };
345
+ }
346
+ close() {
347
+ try {
348
+ this.db.close();
349
+ }
350
+ catch { /* ignore */ }
351
+ }
352
+ rowToRecord(r) {
353
+ return {
354
+ id: r.id,
355
+ dedupeKey: r.dedupe_key,
356
+ kind: r.kind,
357
+ occurrenceCount: r.occurrence_count,
358
+ detectedAt: r.detected_at,
359
+ learning: r.learning ?? '',
360
+ scrubbedSummary: r.scrubbed_summary ?? '',
361
+ dayBucket: r.day_bucket,
362
+ deterministicWeight: r.deterministic_weight,
363
+ llmConfidence: r.llm_confidence,
364
+ topicId: r.topic_id ?? null,
365
+ sessionId: r.session_id ?? null,
366
+ status: r.status,
367
+ routedVia: r.routed_via ?? undefined,
368
+ verifyWindowStart: r.verify_window_start ?? undefined,
369
+ verifyWindowEnd: r.verify_window_end ?? undefined,
370
+ reopenCount: r.reopen_count,
371
+ createdAt: r.created_at,
372
+ updatedAt: r.updated_at,
373
+ version: r.version,
374
+ };
375
+ }
376
+ }
377
+ function clamp01(v) {
378
+ if (typeof v !== 'number' || Number.isNaN(v))
379
+ return 0;
380
+ if (v < 0)
381
+ return 0;
382
+ if (v > 1)
383
+ return 1;
384
+ return v;
385
+ }
386
+ //# sourceMappingURL=CorrectionLedger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CorrectionLedger.js","sourceRoot":"","sources":["../../src/monitoring/CorrectionLedger.ts"],"names":[],"mappings":"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"}