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.
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +92 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +10 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +35 -2
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/types.d.ts +12 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/AgentWorktreeReaper.d.ts +103 -0
- package/dist/monitoring/AgentWorktreeReaper.d.ts.map +1 -0
- package/dist/monitoring/AgentWorktreeReaper.js +159 -0
- package/dist/monitoring/AgentWorktreeReaper.js.map +1 -0
- package/dist/monitoring/CiFailurePoller.d.ts +1 -7
- package/dist/monitoring/CiFailurePoller.d.ts.map +1 -1
- package/dist/monitoring/CiFailurePoller.js +5 -12
- package/dist/monitoring/CiFailurePoller.js.map +1 -1
- package/dist/monitoring/CorrectionAnalyzer.d.ts +65 -0
- package/dist/monitoring/CorrectionAnalyzer.d.ts.map +1 -0
- package/dist/monitoring/CorrectionAnalyzer.js +78 -0
- package/dist/monitoring/CorrectionAnalyzer.js.map +1 -0
- package/dist/monitoring/CorrectionCaptureLoop.d.ts +130 -0
- package/dist/monitoring/CorrectionCaptureLoop.d.ts.map +1 -0
- package/dist/monitoring/CorrectionCaptureLoop.js +249 -0
- package/dist/monitoring/CorrectionCaptureLoop.js.map +1 -0
- package/dist/monitoring/CorrectionLedger.d.ts +149 -0
- package/dist/monitoring/CorrectionLedger.d.ts.map +1 -0
- package/dist/monitoring/CorrectionLedger.js +386 -0
- package/dist/monitoring/CorrectionLedger.js.map +1 -0
- package/dist/monitoring/CorrectionLoopDriver.d.ts +135 -0
- package/dist/monitoring/CorrectionLoopDriver.d.ts.map +1 -0
- package/dist/monitoring/CorrectionLoopDriver.js +185 -0
- package/dist/monitoring/CorrectionLoopDriver.js.map +1 -0
- package/dist/monitoring/HumanAsDetectorLog.d.ts +31 -1
- package/dist/monitoring/HumanAsDetectorLog.d.ts.map +1 -1
- package/dist/monitoring/HumanAsDetectorLog.js +70 -0
- package/dist/monitoring/HumanAsDetectorLog.js.map +1 -1
- package/dist/monitoring/agentWorktreeGit.d.ts +43 -0
- package/dist/monitoring/agentWorktreeGit.d.ts.map +1 -0
- package/dist/monitoring/agentWorktreeGit.js +194 -0
- package/dist/monitoring/agentWorktreeGit.js.map +1 -0
- package/dist/monitoring/scrubSecrets.d.ts +23 -0
- package/dist/monitoring/scrubSecrets.d.ts.map +1 -0
- package/dist/monitoring/scrubSecrets.js +41 -0
- package/dist/monitoring/scrubSecrets.js.map +1 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +1 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +4 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +20 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +8 -3
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts +7 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +213 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +63 -63
- package/src/scaffold/templates/jobs/instar/correction-analyzer.md +32 -0
- package/src/scaffold/templates.ts +1 -0
- package/upgrades/1.3.132.md +42 -0
- package/upgrades/1.3.133.md +70 -0
- package/upgrades/side-effects/agent-worktree-reaper.md +96 -0
- 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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"}
|