instar 1.3.26 → 1.3.28
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/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +11 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +268 -196
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/types.d.ts +17 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/FailureAnalyzer.d.ts +47 -0
- package/dist/monitoring/FailureAnalyzer.d.ts.map +1 -0
- package/dist/monitoring/FailureAnalyzer.js +77 -0
- package/dist/monitoring/FailureAnalyzer.js.map +1 -0
- package/dist/monitoring/FailureAttributionEngine.d.ts +89 -0
- package/dist/monitoring/FailureAttributionEngine.d.ts.map +1 -0
- package/dist/monitoring/FailureAttributionEngine.js +106 -0
- package/dist/monitoring/FailureAttributionEngine.js.map +1 -0
- package/dist/monitoring/FailureLedger.d.ts +207 -0
- package/dist/monitoring/FailureLedger.d.ts.map +1 -0
- package/dist/monitoring/FailureLedger.js +524 -0
- package/dist/monitoring/FailureLedger.js.map +1 -0
- package/dist/monitoring/FailureLoopDriver.d.ts +92 -0
- package/dist/monitoring/FailureLoopDriver.d.ts.map +1 -0
- package/dist/monitoring/FailureLoopDriver.js +101 -0
- package/dist/monitoring/FailureLoopDriver.js.map +1 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +7 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/scheduler/AgentMdJobLoader.d.ts.map +1 -1
- package/dist/scheduler/AgentMdJobLoader.js +33 -4
- package/dist/scheduler/AgentMdJobLoader.js.map +1 -1
- package/dist/server/AgentServer.d.ts +2 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +53 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +16 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts +4 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +149 -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/failure-analyzer.md +32 -0
- package/src/scaffold/templates.ts +7 -0
- package/upgrades/1.3.27.md +45 -0
- package/upgrades/1.3.28.md +30 -0
- package/upgrades/side-effects/agentmd-frontmatter-scheduling-vocabulary.md +66 -0
- package/upgrades/side-effects/esm-safe-instar-hooks.md +33 -0
- package/upgrades/side-effects/failure-learning-loop.md +131 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FailureLedger — dev-process failure forensics for instar self-hosting.
|
|
3
|
+
*
|
|
4
|
+
* Records failures that trace back to something we built, attributes each to
|
|
5
|
+
* the spec / initiative / project AND the dev toolchain that produced it, and
|
|
6
|
+
* exposes the data to the analyzer + dashboard. Part of the Failure-Learning
|
|
7
|
+
* Loop (docs/specs/FAILURE-LEARNING-LOOP-SPEC.md, converged + approved
|
|
8
|
+
* 2026-05-26).
|
|
9
|
+
*
|
|
10
|
+
* Storage (spec §4.2, round-3 decision): a DEDICATED SQLite table with
|
|
11
|
+
* first-class indexed columns (build_skill, category, initiative_id,
|
|
12
|
+
* detected_at, attribution, provenance) — explicitly NOT the TaskFlow `flows`
|
|
13
|
+
* blob, so the analyzer's group-by queries are indexed rather than a
|
|
14
|
+
* cache-rebuild + JS filter. Append/upsert-only, no flow lifecycle.
|
|
15
|
+
*
|
|
16
|
+
* Key invariants:
|
|
17
|
+
* - dedupeKey upsert (spec §4.2 M5): a repeat of the same
|
|
18
|
+
* (source, causeCommitOid, category) increments occurrenceCount instead of
|
|
19
|
+
* duplicating, so a flapping/flaky source can never manufacture support.
|
|
20
|
+
* - mandatory ifMatch OCC (spec §4.2 M4): every mutation supplies the prior
|
|
21
|
+
* version; a stale write loses (conflict) — no last-writer-win.
|
|
22
|
+
* - COUNT(DISTINCT) diversity (spec §4.4): distinct sessions / cause-commits
|
|
23
|
+
* for the source-diversity gate are computed over a bounded occurrences
|
|
24
|
+
* table, never an unbounded set stored on the record.
|
|
25
|
+
* - redaction (spec §4.8 C7): detail.full is internal-only — toApiView() and
|
|
26
|
+
* every route serve detail.redacted ONLY. full never leaves over HTTP.
|
|
27
|
+
* - fail-open (spec §4.2 m9): a write error logs and drops; it never throws
|
|
28
|
+
* back into the commit / reconciler / route that observed the failure.
|
|
29
|
+
*/
|
|
30
|
+
import Database from 'better-sqlite3';
|
|
31
|
+
import fs from 'node:fs';
|
|
32
|
+
import os from 'node:os';
|
|
33
|
+
import path from 'node:path';
|
|
34
|
+
import { NativeModuleHealer } from '../memory/NativeModuleHealer.js';
|
|
35
|
+
// ── Schema ────────────────────────────────────────────────────────────
|
|
36
|
+
const SCHEMA = [
|
|
37
|
+
`CREATE TABLE IF NOT EXISTS failure_records (
|
|
38
|
+
id TEXT PRIMARY KEY,
|
|
39
|
+
dedupe_key TEXT NOT NULL UNIQUE,
|
|
40
|
+
occurrence_count INTEGER NOT NULL DEFAULT 1,
|
|
41
|
+
detected_at TEXT NOT NULL,
|
|
42
|
+
filed_by TEXT NOT NULL,
|
|
43
|
+
source TEXT NOT NULL,
|
|
44
|
+
severity TEXT NOT NULL,
|
|
45
|
+
summary TEXT NOT NULL,
|
|
46
|
+
detail_redacted TEXT NOT NULL DEFAULT '',
|
|
47
|
+
detail_full TEXT NOT NULL DEFAULT '',
|
|
48
|
+
category TEXT NOT NULL DEFAULT 'unknown',
|
|
49
|
+
initiative_id TEXT,
|
|
50
|
+
project_id TEXT,
|
|
51
|
+
spec_path TEXT,
|
|
52
|
+
cause_commit_oid TEXT,
|
|
53
|
+
fix_commit_oid TEXT,
|
|
54
|
+
pr_number INTEGER,
|
|
55
|
+
toolchain_ref TEXT,
|
|
56
|
+
build_skill TEXT,
|
|
57
|
+
provenance TEXT NOT NULL DEFAULT 'unknown',
|
|
58
|
+
attribution TEXT NOT NULL DEFAULT 'inferred',
|
|
59
|
+
attribution_confidence REAL NOT NULL DEFAULT 0,
|
|
60
|
+
status TEXT NOT NULL DEFAULT 'open',
|
|
61
|
+
learning_id TEXT,
|
|
62
|
+
created_at TEXT NOT NULL,
|
|
63
|
+
updated_at TEXT NOT NULL,
|
|
64
|
+
version INTEGER NOT NULL DEFAULT 1
|
|
65
|
+
)`,
|
|
66
|
+
// First-class indexes for the analyzer's group-by query path (spec §4.4):
|
|
67
|
+
`CREATE INDEX IF NOT EXISTS idx_failure_detected ON failure_records(detected_at)`,
|
|
68
|
+
`CREATE INDEX IF NOT EXISTS idx_failure_category ON failure_records(category)`,
|
|
69
|
+
`CREATE INDEX IF NOT EXISTS idx_failure_initiative ON failure_records(initiative_id)`,
|
|
70
|
+
`CREATE INDEX IF NOT EXISTS idx_failure_buildskill ON failure_records(build_skill)`,
|
|
71
|
+
`CREATE INDEX IF NOT EXISTS idx_failure_attribution ON failure_records(attribution, provenance)`,
|
|
72
|
+
// Bounded occurrence log — feeds COUNT(DISTINCT) for the diversity gate
|
|
73
|
+
// (spec §4.4) without growing an unbounded set on the deduped record.
|
|
74
|
+
`CREATE TABLE IF NOT EXISTS failure_occurrences (
|
|
75
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
76
|
+
dedupe_key TEXT NOT NULL,
|
|
77
|
+
filed_by TEXT NOT NULL,
|
|
78
|
+
cause_commit TEXT,
|
|
79
|
+
detected_at TEXT NOT NULL
|
|
80
|
+
)`,
|
|
81
|
+
`CREATE INDEX IF NOT EXISTS idx_occ_dedupe ON failure_occurrences(dedupe_key)`,
|
|
82
|
+
// Per-machine monotonic sequence for machine-scoped IDs.
|
|
83
|
+
`CREATE TABLE IF NOT EXISTS failure_seq (
|
|
84
|
+
machine_id TEXT PRIMARY KEY,
|
|
85
|
+
next_seq INTEGER NOT NULL DEFAULT 1
|
|
86
|
+
)`,
|
|
87
|
+
// Discovered process-gap insights (spec §4.4/§4.6.1). identity_key is
|
|
88
|
+
// content-stable across analyzer runs so the same pattern is updated, never
|
|
89
|
+
// re-announced (the tunnel-spam stable-key lesson).
|
|
90
|
+
`CREATE TABLE IF NOT EXISTS failure_insights (
|
|
91
|
+
id TEXT PRIMARY KEY,
|
|
92
|
+
identity_key TEXT NOT NULL UNIQUE,
|
|
93
|
+
discovered_at TEXT NOT NULL,
|
|
94
|
+
summary TEXT NOT NULL,
|
|
95
|
+
recommendation TEXT NOT NULL DEFAULT '',
|
|
96
|
+
supporting_failure_ids TEXT NOT NULL DEFAULT '[]',
|
|
97
|
+
distinct_sessions INTEGER NOT NULL DEFAULT 0,
|
|
98
|
+
distinct_cause_commits INTEGER NOT NULL DEFAULT 0,
|
|
99
|
+
status TEXT NOT NULL DEFAULT 'discovered',
|
|
100
|
+
acted_on_via TEXT,
|
|
101
|
+
verify_window_start TEXT,
|
|
102
|
+
verify_window_end TEXT,
|
|
103
|
+
target_category TEXT,
|
|
104
|
+
baseline_rate REAL,
|
|
105
|
+
reopen_count INTEGER NOT NULL DEFAULT 0,
|
|
106
|
+
verified_outcome TEXT NOT NULL DEFAULT 'pending',
|
|
107
|
+
announced INTEGER NOT NULL DEFAULT 0,
|
|
108
|
+
created_at TEXT NOT NULL,
|
|
109
|
+
updated_at TEXT NOT NULL,
|
|
110
|
+
version INTEGER NOT NULL DEFAULT 1
|
|
111
|
+
)`,
|
|
112
|
+
];
|
|
113
|
+
// ── FailureLedger ─────────────────────────────────────────────────────
|
|
114
|
+
export class FailureLedger {
|
|
115
|
+
db;
|
|
116
|
+
machineId;
|
|
117
|
+
onError;
|
|
118
|
+
constructor(opts) {
|
|
119
|
+
this.machineId = (opts.machineId || os.hostname() || 'local')
|
|
120
|
+
.replace(/[^a-zA-Z0-9]+/g, '-')
|
|
121
|
+
.replace(/^-+|-+$/g, '')
|
|
122
|
+
.slice(0, 24) || 'local';
|
|
123
|
+
this.onError =
|
|
124
|
+
opts.onError ?? ((where, err) => console.error(`[FailureLedger] ${where}:`, err));
|
|
125
|
+
if (opts.dbPath !== ':memory:') {
|
|
126
|
+
fs.mkdirSync(path.dirname(opts.dbPath), { recursive: true });
|
|
127
|
+
}
|
|
128
|
+
this.db = NativeModuleHealer.openWithHealSync('FailureLedger', () => new Database(opts.dbPath));
|
|
129
|
+
this.db.pragma('journal_mode = WAL');
|
|
130
|
+
this.db.pragma('synchronous = NORMAL');
|
|
131
|
+
for (const ddl of SCHEMA)
|
|
132
|
+
this.db.exec(ddl);
|
|
133
|
+
}
|
|
134
|
+
/** Deterministic dedupe key (spec §4.2 M5). */
|
|
135
|
+
static dedupeKey(source, causeCommitOid, category) {
|
|
136
|
+
return `${source}:${causeCommitOid || 'null'}:${category}`;
|
|
137
|
+
}
|
|
138
|
+
nextId() {
|
|
139
|
+
const row = this.db
|
|
140
|
+
.prepare(`SELECT next_seq FROM failure_seq WHERE machine_id = ?`)
|
|
141
|
+
.get(this.machineId);
|
|
142
|
+
const seq = row?.next_seq ?? 1;
|
|
143
|
+
this.db
|
|
144
|
+
.prepare(`INSERT INTO failure_seq (machine_id, next_seq) VALUES (?, ?)
|
|
145
|
+
ON CONFLICT(machine_id) DO UPDATE SET next_seq = ?`)
|
|
146
|
+
.run(this.machineId, seq + 1, seq + 1);
|
|
147
|
+
return `FAIL-${this.machineId}-${String(seq).padStart(3, '0')}`;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Open (or upsert) a failure record. A repeat on the same dedupeKey
|
|
151
|
+
* increments occurrenceCount and logs a distinct occurrence rather than
|
|
152
|
+
* duplicating. Fail-open: returns null on any storage error.
|
|
153
|
+
*/
|
|
154
|
+
open(input) {
|
|
155
|
+
try {
|
|
156
|
+
const category = input.category ?? 'unknown';
|
|
157
|
+
const dedupeKey = FailureLedger.dedupeKey(input.source, input.causeCommitOid, category);
|
|
158
|
+
const now = new Date().toISOString();
|
|
159
|
+
const detectedAt = input.detectedAt ?? now;
|
|
160
|
+
const txn = this.db.transaction(() => {
|
|
161
|
+
// Always log the occurrence (feeds COUNT(DISTINCT) diversity gate).
|
|
162
|
+
this.db
|
|
163
|
+
.prepare(`INSERT INTO failure_occurrences (dedupe_key, filed_by, cause_commit, detected_at)
|
|
164
|
+
VALUES (?, ?, ?, ?)`)
|
|
165
|
+
.run(dedupeKey, input.filedBy, input.causeCommitOid ?? null, detectedAt);
|
|
166
|
+
const existing = this.db
|
|
167
|
+
.prepare(`SELECT id FROM failure_records WHERE dedupe_key = ?`)
|
|
168
|
+
.get(dedupeKey);
|
|
169
|
+
if (existing) {
|
|
170
|
+
this.db
|
|
171
|
+
.prepare(`UPDATE failure_records
|
|
172
|
+
SET occurrence_count = occurrence_count + 1, updated_at = ?, version = version + 1
|
|
173
|
+
WHERE id = ?`)
|
|
174
|
+
.run(now, existing.id);
|
|
175
|
+
return existing.id;
|
|
176
|
+
}
|
|
177
|
+
const id = this.nextId();
|
|
178
|
+
this.db
|
|
179
|
+
.prepare(`INSERT INTO failure_records
|
|
180
|
+
(id, dedupe_key, occurrence_count, detected_at, filed_by, source, severity,
|
|
181
|
+
summary, detail_redacted, detail_full, category, initiative_id, project_id,
|
|
182
|
+
spec_path, cause_commit_oid, pr_number, toolchain_ref, build_skill, provenance,
|
|
183
|
+
attribution, attribution_confidence, status, created_at, updated_at, version)
|
|
184
|
+
VALUES
|
|
185
|
+
(@id, @dedupeKey, 1, @detectedAt, @filedBy, @source, @severity,
|
|
186
|
+
@summary, @detailRedacted, @detailFull, @category, @initiativeId, @projectId,
|
|
187
|
+
@specPath, @causeCommitOid, @prNumber, @toolchainRef, @buildSkill, @provenance,
|
|
188
|
+
@attribution, @attributionConfidence, 'open', @createdAt, @updatedAt, 1)`)
|
|
189
|
+
.run({
|
|
190
|
+
id,
|
|
191
|
+
dedupeKey,
|
|
192
|
+
detectedAt,
|
|
193
|
+
filedBy: input.filedBy,
|
|
194
|
+
source: input.source,
|
|
195
|
+
severity: input.severity,
|
|
196
|
+
summary: input.summary,
|
|
197
|
+
detailRedacted: input.detail.redacted,
|
|
198
|
+
detailFull: input.detail.full,
|
|
199
|
+
category,
|
|
200
|
+
initiativeId: input.initiativeId ?? null,
|
|
201
|
+
projectId: input.projectId ?? null,
|
|
202
|
+
specPath: input.specPath ?? null,
|
|
203
|
+
causeCommitOid: input.causeCommitOid ?? null,
|
|
204
|
+
prNumber: input.prNumber ?? null,
|
|
205
|
+
toolchainRef: input.toolchainRef ?? null,
|
|
206
|
+
buildSkill: input.buildSkill ?? null,
|
|
207
|
+
provenance: input.provenance ?? 'unknown',
|
|
208
|
+
attribution: input.attribution,
|
|
209
|
+
attributionConfidence: input.attributionConfidence ?? 0,
|
|
210
|
+
createdAt: now,
|
|
211
|
+
updatedAt: now,
|
|
212
|
+
});
|
|
213
|
+
return id;
|
|
214
|
+
});
|
|
215
|
+
const id = txn();
|
|
216
|
+
return this.get(id);
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
this.onError('open', err);
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
get(id) {
|
|
224
|
+
const row = this.db.prepare(`SELECT * FROM failure_records WHERE id = ?`).get(id);
|
|
225
|
+
return row ? this.rowToRecord(row) : null;
|
|
226
|
+
}
|
|
227
|
+
getByDedupeKey(dedupeKey) {
|
|
228
|
+
const row = this.db
|
|
229
|
+
.prepare(`SELECT * FROM failure_records WHERE dedupe_key = ?`)
|
|
230
|
+
.get(dedupeKey);
|
|
231
|
+
return row ? this.rowToRecord(row) : null;
|
|
232
|
+
}
|
|
233
|
+
list(filter = {}) {
|
|
234
|
+
const where = [];
|
|
235
|
+
const params = {};
|
|
236
|
+
if (filter.source) {
|
|
237
|
+
where.push('source = @source');
|
|
238
|
+
params.source = filter.source;
|
|
239
|
+
}
|
|
240
|
+
if (filter.category) {
|
|
241
|
+
where.push('category = @category');
|
|
242
|
+
params.category = filter.category;
|
|
243
|
+
}
|
|
244
|
+
if (filter.initiativeId) {
|
|
245
|
+
where.push('initiative_id = @initiativeId');
|
|
246
|
+
params.initiativeId = filter.initiativeId;
|
|
247
|
+
}
|
|
248
|
+
if (filter.attribution) {
|
|
249
|
+
where.push('attribution = @attribution');
|
|
250
|
+
params.attribution = filter.attribution;
|
|
251
|
+
}
|
|
252
|
+
if (filter.status) {
|
|
253
|
+
where.push('status = @status');
|
|
254
|
+
params.status = filter.status;
|
|
255
|
+
}
|
|
256
|
+
if (filter.sinceMs) {
|
|
257
|
+
where.push('detected_at >= @since');
|
|
258
|
+
params.since = new Date(filter.sinceMs).toISOString();
|
|
259
|
+
}
|
|
260
|
+
const limit = filter.limit && filter.limit > 0 ? Math.min(filter.limit, 1000) : 200;
|
|
261
|
+
const sql = `SELECT * FROM failure_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. `ifMatch` is MANDATORY (spec §4.2 M4) — a stale version
|
|
268
|
+
* loses with {ok:false, conflict:true}. Caller retries (bounded).
|
|
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 cols = [];
|
|
278
|
+
const params = { id, ifMatch };
|
|
279
|
+
const map = {
|
|
280
|
+
status: 'status', category: 'category', fixCommitOid: 'fix_commit_oid',
|
|
281
|
+
learningId: 'learning_id', attribution: 'attribution',
|
|
282
|
+
attributionConfidence: 'attribution_confidence', provenance: 'provenance',
|
|
283
|
+
buildSkill: 'build_skill', initiativeId: 'initiative_id',
|
|
284
|
+
projectId: 'project_id', specPath: 'spec_path', toolchainRef: 'toolchain_ref',
|
|
285
|
+
};
|
|
286
|
+
for (const [k, v] of Object.entries(patch)) {
|
|
287
|
+
const col = map[k];
|
|
288
|
+
if (!col)
|
|
289
|
+
continue;
|
|
290
|
+
cols.push(`${col} = @${k}`);
|
|
291
|
+
params[k] = v ?? null;
|
|
292
|
+
}
|
|
293
|
+
if (cols.length === 0)
|
|
294
|
+
return { ok: true, record: current };
|
|
295
|
+
const now = new Date().toISOString();
|
|
296
|
+
const res = this.db
|
|
297
|
+
.prepare(`UPDATE failure_records SET ${cols.join(', ')}, updated_at = @now, version = version + 1
|
|
298
|
+
WHERE id = @id AND version = @ifMatch`)
|
|
299
|
+
.run({ ...params, now });
|
|
300
|
+
if (res.changes === 0)
|
|
301
|
+
return { ok: false, conflict: true, current: this.get(id) ?? undefined };
|
|
302
|
+
return { ok: true, record: this.get(id) };
|
|
303
|
+
}
|
|
304
|
+
catch (err) {
|
|
305
|
+
this.onError('update', err);
|
|
306
|
+
return { ok: false, conflict: false, reason: 'storage-error' };
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/** Distinct sessions + cause-commits for the diversity gate (spec §4.4). */
|
|
310
|
+
distinctCounts(dedupeKey) {
|
|
311
|
+
const row = this.db
|
|
312
|
+
.prepare(`SELECT COUNT(DISTINCT filed_by) AS sessions,
|
|
313
|
+
COUNT(DISTINCT cause_commit) AS commits
|
|
314
|
+
FROM failure_occurrences WHERE dedupe_key = ?`)
|
|
315
|
+
.get(dedupeKey);
|
|
316
|
+
return { sessions: row?.sessions ?? 0, causeCommits: row?.commits ?? 0 };
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Analyzer query path (spec §4.4): indexed group-bys directly in SQL, never a
|
|
320
|
+
* full cache-rebuild + JS filter. Toolchain-blame counts are restricted to
|
|
321
|
+
* `verified`-provenance, `automatic`-attribution records (claimed / one-tap /
|
|
322
|
+
* inferred are excluded from blame aggregates). Also reports coverage so a
|
|
323
|
+
* low-attribution rate reads as low-confidence, not as the rate.
|
|
324
|
+
*/
|
|
325
|
+
analyze(opts = {}) {
|
|
326
|
+
const sinceClause = opts.sinceMs ? ` AND detected_at >= @since` : '';
|
|
327
|
+
const params = opts.sinceMs ? { since: new Date(opts.sinceMs).toISOString() } : {};
|
|
328
|
+
const total = this.db.prepare(`SELECT COUNT(*) c FROM failure_records WHERE 1=1${sinceClause}`).get(params).c;
|
|
329
|
+
const attributed = this.db.prepare(`SELECT COUNT(*) c FROM failure_records WHERE attribution = 'automatic'${sinceClause}`).get(params).c;
|
|
330
|
+
const byCategory = {};
|
|
331
|
+
for (const r of this.db.prepare(`SELECT category, COUNT(*) c FROM failure_records WHERE 1=1${sinceClause} GROUP BY category`).all(params)) {
|
|
332
|
+
byCategory[r.category] = r.c;
|
|
333
|
+
}
|
|
334
|
+
// Toolchain-blame: verified provenance + automatic attribution only.
|
|
335
|
+
const byBuildSkill = {};
|
|
336
|
+
for (const r of this.db.prepare(`SELECT build_skill bs, COUNT(*) c FROM failure_records WHERE provenance = 'verified' AND attribution = 'automatic' AND build_skill IS NOT NULL${sinceClause} GROUP BY build_skill`).all(params)) {
|
|
337
|
+
byBuildSkill[r.bs] = r.c;
|
|
338
|
+
}
|
|
339
|
+
// Coverage-integrity (spec §4.4, round-3 R2-sec-omit): unknown-toolchain by author.
|
|
340
|
+
const unknownToolchainByAuthor = {};
|
|
341
|
+
for (const r of this.db.prepare(`SELECT filed_by fb, COUNT(*) c FROM failure_records WHERE provenance = 'unknown'${sinceClause} GROUP BY filed_by`).all(params)) {
|
|
342
|
+
unknownToolchainByAuthor[r.fb] = r.c;
|
|
343
|
+
}
|
|
344
|
+
const noFeatureLink = this.db.prepare(`SELECT COUNT(*) c FROM failure_records WHERE initiative_id IS NULL${sinceClause}`).get(params).c;
|
|
345
|
+
return { total, attributed, byCategory, byBuildSkill, unknownToolchainByAuthor, noFeatureLink };
|
|
346
|
+
}
|
|
347
|
+
// ── Insights (spec §4.4 / §4.6.1) ────────────────────────────────────
|
|
348
|
+
/**
|
|
349
|
+
* Upsert an insight keyed on its content-stable identityKey. A re-discovery
|
|
350
|
+
* UPDATES the existing record (refreshes evidence + counts) but PRESERVES its
|
|
351
|
+
* lifecycle (status/actedOnVia/verify window/announced) — so a pattern is
|
|
352
|
+
* never re-announced and an in-flight loop is never reset (spec §4.5 stable-key).
|
|
353
|
+
* Returns the resulting insight (fail-open: null on storage error).
|
|
354
|
+
*/
|
|
355
|
+
upsertInsight(input) {
|
|
356
|
+
try {
|
|
357
|
+
const now = new Date().toISOString();
|
|
358
|
+
const existing = this.getInsightByIdentity(input.identityKey);
|
|
359
|
+
if (existing) {
|
|
360
|
+
this.db
|
|
361
|
+
.prepare(`UPDATE failure_insights
|
|
362
|
+
SET summary=@summary, recommendation=@recommendation,
|
|
363
|
+
supporting_failure_ids=@ids, distinct_sessions=@ds,
|
|
364
|
+
distinct_cause_commits=@dc, target_category=@tc,
|
|
365
|
+
baseline_rate=@br, updated_at=@now, version=version+1
|
|
366
|
+
WHERE id=@id`)
|
|
367
|
+
.run({
|
|
368
|
+
id: existing.id, summary: input.summary, recommendation: input.recommendation,
|
|
369
|
+
ids: JSON.stringify(input.supportingFailureIds), ds: input.distinctSessions,
|
|
370
|
+
dc: input.distinctCauseCommits, tc: input.targetCategory ?? null,
|
|
371
|
+
br: input.baselineRate ?? null, now,
|
|
372
|
+
});
|
|
373
|
+
return this.getInsight(existing.id);
|
|
374
|
+
}
|
|
375
|
+
const id = `INS-${this.machineId}-${this.nextInsightSeq()}`;
|
|
376
|
+
this.db
|
|
377
|
+
.prepare(`INSERT INTO failure_insights
|
|
378
|
+
(id, identity_key, discovered_at, summary, recommendation,
|
|
379
|
+
supporting_failure_ids, distinct_sessions, distinct_cause_commits,
|
|
380
|
+
target_category, baseline_rate,
|
|
381
|
+
status, reopen_count, verified_outcome, announced, created_at, updated_at, version)
|
|
382
|
+
VALUES (@id,@ik,@now,@summary,@rec,@ids,@ds,@dc,@tc,@br,'discovered',0,'pending',0,@now,@now,1)`)
|
|
383
|
+
.run({
|
|
384
|
+
id, ik: input.identityKey, now, summary: input.summary, rec: input.recommendation,
|
|
385
|
+
ids: JSON.stringify(input.supportingFailureIds), ds: input.distinctSessions, dc: input.distinctCauseCommits,
|
|
386
|
+
tc: input.targetCategory ?? null, br: input.baselineRate ?? null,
|
|
387
|
+
});
|
|
388
|
+
return this.getInsight(id);
|
|
389
|
+
}
|
|
390
|
+
catch (err) {
|
|
391
|
+
this.onError('upsertInsight', err);
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
nextInsightSeq() {
|
|
396
|
+
const key = `insight:${this.machineId}`;
|
|
397
|
+
const row = this.db.prepare(`SELECT next_seq FROM failure_seq WHERE machine_id = ?`).get(key);
|
|
398
|
+
const seq = row?.next_seq ?? 1;
|
|
399
|
+
this.db.prepare(`INSERT INTO failure_seq (machine_id, next_seq) VALUES (?, ?) ON CONFLICT(machine_id) DO UPDATE SET next_seq = ?`).run(key, seq + 1, seq + 1);
|
|
400
|
+
return String(seq).padStart(3, '0');
|
|
401
|
+
}
|
|
402
|
+
getInsight(id) {
|
|
403
|
+
const row = this.db.prepare(`SELECT * FROM failure_insights WHERE id = ?`).get(id);
|
|
404
|
+
return row ? this.rowToInsight(row) : null;
|
|
405
|
+
}
|
|
406
|
+
getInsightByIdentity(identityKey) {
|
|
407
|
+
const row = this.db.prepare(`SELECT * FROM failure_insights WHERE identity_key = ?`).get(identityKey);
|
|
408
|
+
return row ? this.rowToInsight(row) : null;
|
|
409
|
+
}
|
|
410
|
+
listInsights(filter = {}) {
|
|
411
|
+
const sql = filter.status
|
|
412
|
+
? `SELECT * FROM failure_insights WHERE status = ? ORDER BY discovered_at DESC`
|
|
413
|
+
: `SELECT * FROM failure_insights ORDER BY discovered_at DESC`;
|
|
414
|
+
const rows = (filter.status ? this.db.prepare(sql).all(filter.status) : this.db.prepare(sql).all());
|
|
415
|
+
return rows.map((r) => this.rowToInsight(r));
|
|
416
|
+
}
|
|
417
|
+
updateInsight(id, patch, ifMatch) {
|
|
418
|
+
try {
|
|
419
|
+
const current = this.getInsight(id);
|
|
420
|
+
if (!current)
|
|
421
|
+
return { ok: false, conflict: false, reason: 'not-found' };
|
|
422
|
+
if (current.version !== ifMatch)
|
|
423
|
+
return { ok: false, conflict: true, current };
|
|
424
|
+
const map = {
|
|
425
|
+
status: 'status', actedOnVia: 'acted_on_via', verifyWindowStart: 'verify_window_start',
|
|
426
|
+
verifyWindowEnd: 'verify_window_end', targetCategory: 'target_category', baselineRate: 'baseline_rate',
|
|
427
|
+
reopenCount: 'reopen_count', verifiedOutcome: 'verified_outcome', announced: 'announced',
|
|
428
|
+
};
|
|
429
|
+
const cols = [];
|
|
430
|
+
const params = { id, ifMatch };
|
|
431
|
+
for (const [k, v] of Object.entries(patch)) {
|
|
432
|
+
const col = map[k];
|
|
433
|
+
if (!col)
|
|
434
|
+
continue;
|
|
435
|
+
cols.push(`${col} = @${k}`);
|
|
436
|
+
params[k] = k === 'announced' ? (v ? 1 : 0) : (v ?? null);
|
|
437
|
+
}
|
|
438
|
+
if (cols.length === 0)
|
|
439
|
+
return { ok: true, record: current };
|
|
440
|
+
const now = new Date().toISOString();
|
|
441
|
+
const res = this.db.prepare(`UPDATE failure_insights SET ${cols.join(', ')}, updated_at=@now, version=version+1 WHERE id=@id AND version=@ifMatch`).run({ ...params, now });
|
|
442
|
+
if (res.changes === 0)
|
|
443
|
+
return { ok: false, conflict: true, current: this.getInsight(id) ?? undefined };
|
|
444
|
+
return { ok: true, record: this.getInsight(id) };
|
|
445
|
+
}
|
|
446
|
+
catch (err) {
|
|
447
|
+
this.onError('updateInsight', err);
|
|
448
|
+
return { ok: false, conflict: false, reason: 'storage-error' };
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
rowToInsight(r) {
|
|
452
|
+
let ids = [];
|
|
453
|
+
try {
|
|
454
|
+
ids = JSON.parse(r.supporting_failure_ids || '[]');
|
|
455
|
+
}
|
|
456
|
+
catch {
|
|
457
|
+
ids = [];
|
|
458
|
+
}
|
|
459
|
+
return {
|
|
460
|
+
id: r.id,
|
|
461
|
+
identityKey: r.identity_key,
|
|
462
|
+
discoveredAt: r.discovered_at,
|
|
463
|
+
summary: r.summary,
|
|
464
|
+
recommendation: r.recommendation ?? '',
|
|
465
|
+
supportingFailureIds: ids,
|
|
466
|
+
distinctSessions: r.distinct_sessions,
|
|
467
|
+
distinctCauseCommits: r.distinct_cause_commits,
|
|
468
|
+
status: r.status,
|
|
469
|
+
actedOnVia: r.acted_on_via ?? undefined,
|
|
470
|
+
verifyWindowStart: r.verify_window_start ?? undefined,
|
|
471
|
+
verifyWindowEnd: r.verify_window_end ?? undefined,
|
|
472
|
+
targetCategory: r.target_category ?? undefined,
|
|
473
|
+
baselineRate: r.baseline_rate ?? undefined,
|
|
474
|
+
reopenCount: r.reopen_count,
|
|
475
|
+
verifiedOutcome: r.verified_outcome,
|
|
476
|
+
announced: !!r.announced,
|
|
477
|
+
createdAt: r.created_at,
|
|
478
|
+
updatedAt: r.updated_at,
|
|
479
|
+
version: r.version,
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
/** Strip detail.full — the ONLY shape that may cross an HTTP boundary (spec §4.8). */
|
|
483
|
+
static toApiView(record) {
|
|
484
|
+
const { detail, ...rest } = record;
|
|
485
|
+
return { ...rest, detail: { redacted: detail.redacted } };
|
|
486
|
+
}
|
|
487
|
+
close() {
|
|
488
|
+
try {
|
|
489
|
+
this.db.close();
|
|
490
|
+
}
|
|
491
|
+
catch { /* ignore */ }
|
|
492
|
+
}
|
|
493
|
+
rowToRecord(r) {
|
|
494
|
+
return {
|
|
495
|
+
id: r.id,
|
|
496
|
+
dedupeKey: r.dedupe_key,
|
|
497
|
+
occurrenceCount: r.occurrence_count,
|
|
498
|
+
detectedAt: r.detected_at,
|
|
499
|
+
filedBy: r.filed_by,
|
|
500
|
+
source: r.source,
|
|
501
|
+
severity: r.severity,
|
|
502
|
+
summary: r.summary,
|
|
503
|
+
detail: { redacted: r.detail_redacted ?? '', full: r.detail_full ?? '' },
|
|
504
|
+
category: r.category,
|
|
505
|
+
initiativeId: r.initiative_id ?? undefined,
|
|
506
|
+
projectId: r.project_id ?? undefined,
|
|
507
|
+
specPath: r.spec_path ?? undefined,
|
|
508
|
+
causeCommitOid: r.cause_commit_oid ?? undefined,
|
|
509
|
+
fixCommitOid: r.fix_commit_oid ?? undefined,
|
|
510
|
+
prNumber: r.pr_number ?? undefined,
|
|
511
|
+
toolchainRef: r.toolchain_ref ?? undefined,
|
|
512
|
+
buildSkill: r.build_skill ?? undefined,
|
|
513
|
+
provenance: r.provenance ?? 'unknown',
|
|
514
|
+
attribution: r.attribution,
|
|
515
|
+
attributionConfidence: r.attribution_confidence,
|
|
516
|
+
status: r.status,
|
|
517
|
+
learningId: r.learning_id ?? undefined,
|
|
518
|
+
createdAt: r.created_at,
|
|
519
|
+
updatedAt: r.updated_at,
|
|
520
|
+
version: r.version,
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
//# sourceMappingURL=FailureLedger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FailureLedger.js","sourceRoot":"","sources":["../../src/monitoring/FailureLedger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FailureLoopDriver — the closed self-improvement loop (spec §4.6.1).
|
|
3
|
+
*
|
|
4
|
+
* discover (FailureAnalyzer) → IMPLEMENT (this: open a tracked item) →
|
|
5
|
+
* deploy (normal spec→build→rollout, human-driven) → VERIFY (this).
|
|
6
|
+
*
|
|
7
|
+
* The headline safety property — "the loop can never change the process on its
|
|
8
|
+
* own" — is enforced BY CONSTRUCTION (spec §4.6.1 step 3, round-2 BL-2):
|
|
9
|
+
*
|
|
10
|
+
* The driver's injected capabilities are ONLY `addAction` (an Evolution
|
|
11
|
+
* Action) and `createInitiative` (a draft Initiative in `needs-user`). It is
|
|
12
|
+
* given NO ability to create an EvolutionProposal — and a proposal is the
|
|
13
|
+
* ONLY thing the autonomous auto-implement evaluator acts on. So an
|
|
14
|
+
* auto-implemented process change is unreachable for anything this loop
|
|
15
|
+
* produces, regardless of `evolutionApprovalMode`. There is no field to forge
|
|
16
|
+
* and no layer to misplace: the capability simply isn't wired in.
|
|
17
|
+
*
|
|
18
|
+
* Verify (step 5): on an `acted-on` insight past its verification window, the
|
|
19
|
+
* driver computes the post-change rate of the targeted failure category and
|
|
20
|
+
* sets the outcome — labeled CORRELATIONAL, never causal. It requires a minimum
|
|
21
|
+
* post-window exposure before concluding (else `insufficient-exposure` → extend
|
|
22
|
+
* once → `inconclusive`), and caps reopens so a non-droppable class can never
|
|
23
|
+
* churn forever (spec §4.6.1 M3).
|
|
24
|
+
*
|
|
25
|
+
* NOTE (v1 simplification, tracked): "exposure normalization" here is the raw
|
|
26
|
+
* post-window category count vs. baseline. The full features-of-category-shipped
|
|
27
|
+
* denominator is a later refinement — it can only make the outcome MORE
|
|
28
|
+
* conservative, never auto-implement anything (the authority guard is unaffected).
|
|
29
|
+
*/
|
|
30
|
+
import type { FailureLedger, InsightRecord } from './FailureLedger.js';
|
|
31
|
+
/** The ONLY mutation capabilities the loop is given. Deliberately excludes any
|
|
32
|
+
* proposal-creation path (that's the by-construction authority guard). */
|
|
33
|
+
export interface LoopDeps {
|
|
34
|
+
/** Open an Evolution Action (tracked self-improvement to-do). */
|
|
35
|
+
addAction: (opts: {
|
|
36
|
+
title: string;
|
|
37
|
+
description: string;
|
|
38
|
+
priority?: 'critical' | 'high' | 'medium' | 'low';
|
|
39
|
+
source?: string;
|
|
40
|
+
tags?: string[];
|
|
41
|
+
}) => {
|
|
42
|
+
id: string;
|
|
43
|
+
};
|
|
44
|
+
/** Open a draft Initiative in needs-user (a human approves turning it real). */
|
|
45
|
+
createInitiative: (input: {
|
|
46
|
+
id: string;
|
|
47
|
+
title: string;
|
|
48
|
+
description: string;
|
|
49
|
+
phases: {
|
|
50
|
+
name: string;
|
|
51
|
+
status: string;
|
|
52
|
+
}[];
|
|
53
|
+
needsUser: boolean;
|
|
54
|
+
needsUserReason?: string;
|
|
55
|
+
}) => Promise<{
|
|
56
|
+
id: string;
|
|
57
|
+
}>;
|
|
58
|
+
now?: () => number;
|
|
59
|
+
/** Days to watch the targeted failure class after the fix ships (default 42 = 6 weeks). */
|
|
60
|
+
verifyWindowDays?: number;
|
|
61
|
+
/** Max reopens before terminal `inconclusive` (default 2). */
|
|
62
|
+
maxReopens?: number;
|
|
63
|
+
/** Minimum post-window category activity required to conclude (default 1). */
|
|
64
|
+
minPostExposure?: number;
|
|
65
|
+
}
|
|
66
|
+
export interface ActResult {
|
|
67
|
+
actedOn: InsightRecord[];
|
|
68
|
+
}
|
|
69
|
+
export interface VerifyResult {
|
|
70
|
+
evaluated: InsightRecord[];
|
|
71
|
+
}
|
|
72
|
+
export declare class FailureLoopDriver {
|
|
73
|
+
private readonly ledger;
|
|
74
|
+
private readonly deps;
|
|
75
|
+
constructor(ledger: FailureLedger, deps: LoopDeps);
|
|
76
|
+
private now;
|
|
77
|
+
/**
|
|
78
|
+
* IMPLEMENT step: for each newly-`discovered` insight, open a tracked Action +
|
|
79
|
+
* a draft Initiative (needs-user) and move it to `acted-on` with a verification
|
|
80
|
+
* window. Never mints a proposal (see class docs). Idempotent: an insight
|
|
81
|
+
* already past `discovered` is skipped.
|
|
82
|
+
*/
|
|
83
|
+
actOnNewInsights(): Promise<ActResult>;
|
|
84
|
+
/**
|
|
85
|
+
* VERIFY step: for each `acted-on` insight whose window has elapsed, decide
|
|
86
|
+
* the (correlational) outcome. Drop below baseline → verified-effective;
|
|
87
|
+
* no drop → verified-ineffective + reopen (capped → inconclusive); too little
|
|
88
|
+
* post-window activity → insufficient-exposure (extend once → inconclusive).
|
|
89
|
+
*/
|
|
90
|
+
runVerification(): VerifyResult;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=FailureLoopDriver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FailureLoopDriver.d.ts","sourceRoot":"","sources":["../../src/monitoring/FailureLoopDriver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAmB,MAAM,oBAAoB,CAAC;AAExF;2EAC2E;AAC3E,MAAM,WAAW,QAAQ;IACvB,iEAAiE;IACjE,SAAS,EAAE,CAAC,IAAI,EAAE;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;QAClD,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;KACjB,KAAK;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACrB,gFAAgF;IAChF,gBAAgB,EAAE,CAAC,KAAK,EAAE;QACxB,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAC3C,SAAS,EAAE,OAAO,CAAC;QACnB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,KAAK,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,2FAA2F;IAC3F,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,SAAS;IAAG,OAAO,EAAE,aAAa,EAAE,CAAC;CAAE;AACxD,MAAM,WAAW,YAAY;IAAG,SAAS,EAAE,aAAa,EAAE,CAAC;CAAE;AAE7D,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAiB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAA5C,MAAM,EAAE,aAAa,EAAmB,IAAI,EAAE,QAAQ;IAEnF,OAAO,CAAC,GAAG;IAEX;;;;;OAKG;IACG,gBAAgB,IAAI,OAAO,CAAC,SAAS,CAAC;IAoC5C;;;;;OAKG;IACH,eAAe,IAAI,YAAY;CA0ChC"}
|