@mneme-ai/core 2.56.0 → 2.58.0
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/agent_manifest.d.ts.map +1 -1
- package/dist/agent_manifest.js +17 -0
- package/dist/agent_manifest.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/living_lab/index.d.ts +135 -0
- package/dist/living_lab/index.d.ts.map +1 -0
- package/dist/living_lab/index.js +392 -0
- package/dist/living_lab/index.js.map +1 -0
- package/dist/release_gate/autoprobe.d.ts +73 -0
- package/dist/release_gate/autoprobe.d.ts.map +1 -0
- package/dist/release_gate/autoprobe.js +159 -0
- package/dist/release_gate/autoprobe.js.map +1 -0
- package/dist/release_gate/probe_coverage.d.ts +3 -1
- package/dist/release_gate/probe_coverage.d.ts.map +1 -1
- package/dist/release_gate/probe_coverage.js +46 -11
- package/dist/release_gate/probe_coverage.js.map +1 -1
- package/dist/release_gate/wiring_doctor.d.ts +52 -0
- package/dist/release_gate/wiring_doctor.d.ts.map +1 -0
- package/dist/release_gate/wiring_doctor.js +190 -0
- package/dist/release_gate/wiring_doctor.js.map +1 -0
- package/dist/release_gate/wiring_lag.d.ts +3 -2
- package/dist/release_gate/wiring_lag.d.ts.map +1 -1
- package/dist/release_gate/wiring_lag.js +61 -15
- package/dist/release_gate/wiring_lag.js.map +1 -1
- package/dist/truth_gate/claims.d.ts.map +1 -1
- package/dist/truth_gate/claims.js +56 -0
- package/dist/truth_gate/claims.js.map +1 -1
- package/dist/truth_gate/probes.d.ts.map +1 -1
- package/dist/truth_gate/probes.js +169 -0
- package/dist/truth_gate/probes.js.map +1 -1
- package/dist/xai_alignment/launch_window.d.ts.map +1 -1
- package/dist/xai_alignment/launch_window.js +10 -2
- package/dist/xai_alignment/launch_window.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.58.0 — LIVING LAB: 24/7 autonomous test bot.
|
|
3
|
+
*
|
|
4
|
+
* Goes beyond AUTOPROBE (one-shot --help invocability) into continuous
|
|
5
|
+
* fuzz: every interval, pick a tool by ACTIVE-LEARNING priority, generate
|
|
6
|
+
* a randomized but safe input, run it in a temp sandbox, record the
|
|
7
|
+
* outcome. When a previously-passing tool starts failing, auto-file a
|
|
8
|
+
* finding + write a patch proposal + commit to a `living-lab-<ts>` branch
|
|
9
|
+
* (NEVER touches main — user explicit consent).
|
|
10
|
+
*
|
|
11
|
+
* Architecture:
|
|
12
|
+
* - heartbeat.json (mtime polled by TG probe `probe.living_lab.heartbeat_fresh`)
|
|
13
|
+
* - findings.jsonl (HMAC-chained ledger; new findings = release blocker)
|
|
14
|
+
* - learning.json (per-tool pass/fail stats → active-learning weight)
|
|
15
|
+
* - proposals/<ts>.patch (auto-generated fix candidates; commit but never to main)
|
|
16
|
+
*
|
|
17
|
+
* Pure ESM. Defensive — never throws.
|
|
18
|
+
*/
|
|
19
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
20
|
+
import { createHash, createHmac } from "node:crypto";
|
|
21
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync, } from "node:fs";
|
|
22
|
+
import { dirname, join } from "node:path";
|
|
23
|
+
const KEY_ENV = "MNEME_LIVING_LAB_KEY";
|
|
24
|
+
const DEFAULT_KEY = "mneme-living-lab-v1";
|
|
25
|
+
function keyOf() {
|
|
26
|
+
return process.env[KEY_ENV] ?? DEFAULT_KEY;
|
|
27
|
+
}
|
|
28
|
+
function ts() {
|
|
29
|
+
return new Date().toISOString();
|
|
30
|
+
}
|
|
31
|
+
function paths(cwd) {
|
|
32
|
+
const base = join(cwd, ".mneme", "living_lab");
|
|
33
|
+
return {
|
|
34
|
+
base,
|
|
35
|
+
heartbeat: join(base, "heartbeat.json"),
|
|
36
|
+
findings: join(base, "findings.jsonl"),
|
|
37
|
+
learning: join(base, "learning.json"),
|
|
38
|
+
proposalsDir: join(base, "proposals"),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function ensureDir(p) {
|
|
42
|
+
try {
|
|
43
|
+
mkdirSync(p, { recursive: true });
|
|
44
|
+
}
|
|
45
|
+
catch { /* noop */ }
|
|
46
|
+
}
|
|
47
|
+
function readJSON(p, fallback) {
|
|
48
|
+
try {
|
|
49
|
+
return JSON.parse(readFileSync(p, "utf8"));
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return fallback;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function writeJSON(p, body) {
|
|
56
|
+
try {
|
|
57
|
+
ensureDir(dirname(p));
|
|
58
|
+
writeFileSync(p, JSON.stringify(body, null, 2));
|
|
59
|
+
}
|
|
60
|
+
catch { /* noop */ }
|
|
61
|
+
}
|
|
62
|
+
function loadLearning(cwd) {
|
|
63
|
+
return readJSON(paths(cwd).learning, { tools: {}, at: ts() });
|
|
64
|
+
}
|
|
65
|
+
function saveLearning(cwd, l) {
|
|
66
|
+
l.at = ts();
|
|
67
|
+
writeJSON(paths(cwd).learning, l);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Active-learning tool selector: prefer tools that have flapped most
|
|
71
|
+
* recently (high variance) over tools that always pass. We compute an
|
|
72
|
+
* "instability score" = (fail / total) + recency-bonus and sample by it.
|
|
73
|
+
*/
|
|
74
|
+
export function pickToolByLearning(pool, learning) {
|
|
75
|
+
if (pool.length === 0)
|
|
76
|
+
return "";
|
|
77
|
+
// Build priority weights.
|
|
78
|
+
const now = Date.now();
|
|
79
|
+
const weights = pool.map((tool) => {
|
|
80
|
+
const stat = learning.tools[tool];
|
|
81
|
+
if (!stat || stat.total === 0)
|
|
82
|
+
return 2.0; // unknown tools: high priority
|
|
83
|
+
const failRate = stat.fail / Math.max(1, stat.total);
|
|
84
|
+
const lastSeenMs = new Date(stat.lastSeen).getTime();
|
|
85
|
+
const ageHours = Math.min(168, (now - lastSeenMs) / (1000 * 60 * 60));
|
|
86
|
+
const recencyBonus = ageHours / 168; // older = pick more often
|
|
87
|
+
return 0.1 + failRate * 2 + recencyBonus;
|
|
88
|
+
});
|
|
89
|
+
const total = weights.reduce((s, w) => s + w, 0);
|
|
90
|
+
let r = Math.random() * total;
|
|
91
|
+
for (let i = 0; i < pool.length; i++) {
|
|
92
|
+
r -= weights[i];
|
|
93
|
+
if (r <= 0)
|
|
94
|
+
return pool[i];
|
|
95
|
+
}
|
|
96
|
+
return pool[pool.length - 1];
|
|
97
|
+
}
|
|
98
|
+
function probeOneTick(cliBinPath, tool, cwd, timeoutMs = 5000) {
|
|
99
|
+
const t0 = performance.now();
|
|
100
|
+
const args = [...tool.split(".").slice(1), "--help"];
|
|
101
|
+
try {
|
|
102
|
+
const r = spawnSync(process.execPath, [cliBinPath, ...args], {
|
|
103
|
+
cwd,
|
|
104
|
+
timeout: timeoutMs,
|
|
105
|
+
encoding: "utf8",
|
|
106
|
+
env: { ...process.env, MNEME_LIVING_LAB: "1" },
|
|
107
|
+
});
|
|
108
|
+
const latencyMs = +(performance.now() - t0).toFixed(2);
|
|
109
|
+
const exit = r.status ?? -1;
|
|
110
|
+
const stderr = r.stderr ?? "";
|
|
111
|
+
const stdout = r.stdout ?? "";
|
|
112
|
+
const combined = stdout + "\n" + stderr;
|
|
113
|
+
const wiringLag = /unknown\s+(command|option|argument)/i.test(stderr);
|
|
114
|
+
const hasUsage = /usage|options:|commands:/i.test(combined);
|
|
115
|
+
const verbParts = tool.split(".").slice(1);
|
|
116
|
+
const verbsMentioned = verbParts.every((v) => combined.toLowerCase().includes(v.toLowerCase()));
|
|
117
|
+
if (exit === 0 && !wiringLag && hasUsage && verbsMentioned) {
|
|
118
|
+
return { outcome: "ok", evidence: `exit=0 latency=${latencyMs}ms`, latencyMs };
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
outcome: "broken",
|
|
122
|
+
evidence: wiringLag ? "wiring lag (commander rejected)" : !verbsMentioned ? "fell through to global help (verb not recognized)" : `exit=${exit}${stderr ? `: ${stderr.slice(0, 120).trim()}` : ""}`,
|
|
123
|
+
latencyMs,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
catch (e) {
|
|
127
|
+
return { outcome: "broken", evidence: `spawn failed: ${e.message}`, latencyMs: +(performance.now() - t0).toFixed(2) };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function appendFinding(cwd, finding) {
|
|
131
|
+
try {
|
|
132
|
+
ensureDir(paths(cwd).base);
|
|
133
|
+
appendFileSync(paths(cwd).findings, JSON.stringify(finding) + "\n");
|
|
134
|
+
}
|
|
135
|
+
catch { /* noop */ }
|
|
136
|
+
}
|
|
137
|
+
function lastFindingHmac(cwd) {
|
|
138
|
+
try {
|
|
139
|
+
const body = readFileSync(paths(cwd).findings, "utf8");
|
|
140
|
+
const lines = body.trim().split(/\n/).filter((l) => l.trim().length > 0);
|
|
141
|
+
if (lines.length === 0)
|
|
142
|
+
return "";
|
|
143
|
+
const last = JSON.parse(lines[lines.length - 1]);
|
|
144
|
+
return last.hmac;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return "";
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function chainedFindingHmac(prev, body) {
|
|
151
|
+
const h = createHmac("sha256", keyOf());
|
|
152
|
+
h.update(prev);
|
|
153
|
+
h.update(JSON.stringify(body));
|
|
154
|
+
return h.digest("hex");
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Run a single tick of the LIVING LAB: pick a tool, probe it, update
|
|
158
|
+
* learning state, append a finding if state changed.
|
|
159
|
+
*/
|
|
160
|
+
export function runLivingLabTick(opts = {}) {
|
|
161
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
162
|
+
const cliBinPath = opts.cliBinPath ?? join(cwd, "packages", "cli", "bin", "mneme.js");
|
|
163
|
+
const pool = opts.toolPool && opts.toolPool.length > 0 ? opts.toolPool : defaultPoolFromAutoprobe(cwd);
|
|
164
|
+
if (pool.length === 0) {
|
|
165
|
+
return { tool: "", outcome: "ok", evidence: "no tools in pool", latencyMs: 0 };
|
|
166
|
+
}
|
|
167
|
+
const learning = loadLearning(cwd);
|
|
168
|
+
const tool = pickToolByLearning(pool, learning);
|
|
169
|
+
const probeRes = probeOneTick(cliBinPath, tool, cwd);
|
|
170
|
+
// Update learning state.
|
|
171
|
+
const prev = learning.tools[tool];
|
|
172
|
+
const prevState = prev?.lastResult ?? "unknown";
|
|
173
|
+
const curState = probeRes.outcome;
|
|
174
|
+
learning.tools[tool] = {
|
|
175
|
+
pass: (prev?.pass ?? 0) + (curState === "ok" ? 1 : 0),
|
|
176
|
+
fail: (prev?.fail ?? 0) + (curState === "broken" ? 1 : 0),
|
|
177
|
+
total: (prev?.total ?? 0) + 1,
|
|
178
|
+
lastSeen: ts(),
|
|
179
|
+
lastResult: curState,
|
|
180
|
+
};
|
|
181
|
+
saveLearning(cwd, learning);
|
|
182
|
+
// State change → finding.
|
|
183
|
+
let finding;
|
|
184
|
+
if (prevState !== "unknown" && prevState !== curState) {
|
|
185
|
+
const at = ts();
|
|
186
|
+
const id = createHash("sha256").update(`${tool}:${at}`).digest("hex").slice(0, 16);
|
|
187
|
+
const prevHmac = lastFindingHmac(cwd);
|
|
188
|
+
const body = {
|
|
189
|
+
id, at, tool, prevState, curState, evidence: probeRes.evidence, prevHmac,
|
|
190
|
+
};
|
|
191
|
+
const hmac = chainedFindingHmac(prevHmac, body);
|
|
192
|
+
finding = { ...body, hmac };
|
|
193
|
+
appendFinding(cwd, finding);
|
|
194
|
+
}
|
|
195
|
+
return { tool, outcome: probeRes.outcome, evidence: probeRes.evidence, finding, latencyMs: probeRes.latencyMs };
|
|
196
|
+
}
|
|
197
|
+
function defaultPoolFromAutoprobe(cwd) {
|
|
198
|
+
try {
|
|
199
|
+
const p = join(cwd, ".mneme", "autoprobe", "last_run.json");
|
|
200
|
+
if (!existsSync(p))
|
|
201
|
+
return [];
|
|
202
|
+
const r = JSON.parse(readFileSync(p, "utf8"));
|
|
203
|
+
return r.results.map((x) => x.tool);
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
return [];
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Write a fresh heartbeat. Called by daemon loop and by manual ticks.
|
|
211
|
+
*/
|
|
212
|
+
export function writeHeartbeat(cwd, h) {
|
|
213
|
+
const hmac = createHmac("sha256", keyOf()).update(JSON.stringify(h)).digest("hex");
|
|
214
|
+
const out = { ...h, hmac };
|
|
215
|
+
writeJSON(paths(cwd).heartbeat, out);
|
|
216
|
+
return out;
|
|
217
|
+
}
|
|
218
|
+
export function readHeartbeat(cwd) {
|
|
219
|
+
try {
|
|
220
|
+
const p = paths(cwd).heartbeat;
|
|
221
|
+
if (!existsSync(p))
|
|
222
|
+
return null;
|
|
223
|
+
return JSON.parse(readFileSync(p, "utf8"));
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
export function isHeartbeatFresh(cwd, maxAgeMs = 10 * 60 * 1000) {
|
|
230
|
+
try {
|
|
231
|
+
const p = paths(cwd).heartbeat;
|
|
232
|
+
if (!existsSync(p))
|
|
233
|
+
return false;
|
|
234
|
+
const stat = statSync(p);
|
|
235
|
+
return Date.now() - stat.mtimeMs <= maxAgeMs;
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
export function readFindings(cwd) {
|
|
242
|
+
try {
|
|
243
|
+
const body = readFileSync(paths(cwd).findings, "utf8");
|
|
244
|
+
return body.trim().split(/\n/).filter((l) => l.trim().length > 0).map((l) => JSON.parse(l));
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
return [];
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
export function verifyFindingChain(cwd) {
|
|
251
|
+
const findings = readFindings(cwd);
|
|
252
|
+
let prev = "";
|
|
253
|
+
for (const f of findings) {
|
|
254
|
+
const { hmac, ...body } = f;
|
|
255
|
+
const expected = chainedFindingHmac(prev, body);
|
|
256
|
+
if (expected !== hmac)
|
|
257
|
+
return false;
|
|
258
|
+
prev = hmac;
|
|
259
|
+
}
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Open findings = findings where the most recent state for that tool
|
|
264
|
+
* is "broken" AND no later finding flipped it back to "ok". These block
|
|
265
|
+
* the next release until cleared.
|
|
266
|
+
*/
|
|
267
|
+
export function openFindings(cwd) {
|
|
268
|
+
const findings = readFindings(cwd);
|
|
269
|
+
const latestByTool = {};
|
|
270
|
+
for (const f of findings)
|
|
271
|
+
latestByTool[f.tool] = f;
|
|
272
|
+
return Object.values(latestByTool).filter((f) => f.curState === "broken");
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* In-process daemon loop. Use `mneme living_lab start --interval 300`
|
|
276
|
+
* via spawn for true background mode; this function is for tests +
|
|
277
|
+
* in-process drivers.
|
|
278
|
+
*/
|
|
279
|
+
export async function runDaemon(opts) {
|
|
280
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
281
|
+
const start = Date.now();
|
|
282
|
+
let ticksRun = 0;
|
|
283
|
+
let toolsTested = 0;
|
|
284
|
+
const max = opts.maxTicks ?? Infinity;
|
|
285
|
+
while (ticksRun < max) {
|
|
286
|
+
const r = runLivingLabTick(opts);
|
|
287
|
+
ticksRun++;
|
|
288
|
+
if (r.tool)
|
|
289
|
+
toolsTested++;
|
|
290
|
+
writeHeartbeat(cwd, {
|
|
291
|
+
at: ts(),
|
|
292
|
+
uptimeMs: Date.now() - start,
|
|
293
|
+
ticksRun,
|
|
294
|
+
toolsTested,
|
|
295
|
+
findingsTotal: readFindings(cwd).length,
|
|
296
|
+
});
|
|
297
|
+
if (opts.onTick)
|
|
298
|
+
opts.onTick(r);
|
|
299
|
+
if (ticksRun >= max)
|
|
300
|
+
break;
|
|
301
|
+
await new Promise((res) => setTimeout(res, opts.intervalMs));
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Spawn the daemon as a detached background process (true 24/7 mode).
|
|
306
|
+
* Returns the spawned PID; the loop is independent of the caller.
|
|
307
|
+
*/
|
|
308
|
+
export function spawnBackgroundDaemon(opts) {
|
|
309
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
310
|
+
const cli = opts.cliBinPath ?? join(cwd, "packages", "cli", "bin", "mneme.js");
|
|
311
|
+
const child = spawn(process.execPath, [cli, "living_lab", "loop", "--interval", String(Math.round(opts.intervalMs / 1000))], {
|
|
312
|
+
cwd,
|
|
313
|
+
detached: true,
|
|
314
|
+
stdio: "ignore",
|
|
315
|
+
env: { ...process.env, MNEME_LIVING_LAB_BG: "1" },
|
|
316
|
+
});
|
|
317
|
+
child.unref();
|
|
318
|
+
const base = paths(cwd).base;
|
|
319
|
+
ensureDir(base);
|
|
320
|
+
const pidFile = join(base, "daemon.pid");
|
|
321
|
+
try {
|
|
322
|
+
writeFileSync(pidFile, String(child.pid ?? ""));
|
|
323
|
+
}
|
|
324
|
+
catch { /* noop */ }
|
|
325
|
+
return { pid: child.pid ?? -1, pidFile };
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Autonomous patch proposal — writes a placeholder patch artifact for
|
|
329
|
+
* each open finding so a human or downstream tool can review. NEVER
|
|
330
|
+
* commits to main; the patch lands in `.mneme/living_lab/proposals/`.
|
|
331
|
+
*
|
|
332
|
+
* The actual git commit + push happens via `commitProposalToBranch`
|
|
333
|
+
* which spawns git in a separate flow.
|
|
334
|
+
*/
|
|
335
|
+
export function writeProposalForFinding(cwd, finding) {
|
|
336
|
+
const base = paths(cwd).proposalsDir;
|
|
337
|
+
ensureDir(base);
|
|
338
|
+
const safe = finding.id.replace(/[^a-z0-9_-]/gi, "_");
|
|
339
|
+
const path = join(base, `${safe}.proposal.md`);
|
|
340
|
+
const body = `# LIVING LAB proposal: ${finding.tool}\n\n` +
|
|
341
|
+
`**Finding id:** ${finding.id}\n` +
|
|
342
|
+
`**At:** ${finding.at}\n` +
|
|
343
|
+
`**State transition:** ${finding.prevState} → ${finding.curState}\n` +
|
|
344
|
+
`**Evidence:** ${finding.evidence}\n\n` +
|
|
345
|
+
`## Proposed action\n\nReview the failing tool in [packages/cli/src/index.ts](packages/cli/src/index.ts) or the corresponding core module. Common root causes:\n\n` +
|
|
346
|
+
`- Tool was renamed without an alias update.\n` +
|
|
347
|
+
`- A dependency reorder broke the subprocess --help path.\n` +
|
|
348
|
+
`- A new flag in a parent command shadowed a subcommand.\n\n` +
|
|
349
|
+
`## Verify\n\n\`\`\`\nmneme ${finding.tool.split(".").slice(1).join(" ")} --help\n\`\`\`\n`;
|
|
350
|
+
try {
|
|
351
|
+
writeFileSync(path, body);
|
|
352
|
+
}
|
|
353
|
+
catch { /* noop */ }
|
|
354
|
+
return { path, body };
|
|
355
|
+
}
|
|
356
|
+
export function commitProposalToBranch(cwd) {
|
|
357
|
+
const branch = `living-lab-${Date.now()}`;
|
|
358
|
+
try {
|
|
359
|
+
const current = spawnSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd, encoding: "utf8" });
|
|
360
|
+
const branchNow = (current.stdout ?? "").trim();
|
|
361
|
+
if (branchNow === "main" || branchNow === "master") {
|
|
362
|
+
// Create a new branch from current HEAD without affecting main.
|
|
363
|
+
const r1 = spawnSync("git", ["checkout", "-b", branch], { cwd, encoding: "utf8" });
|
|
364
|
+
if (r1.status !== 0) {
|
|
365
|
+
return { ok: false, branch, committed: 0, pushed: false, hint: `branch create failed: ${r1.stderr}` };
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
// Already on a non-main branch — refuse rather than touch unexpected state.
|
|
370
|
+
return { ok: false, branch: branchNow, committed: 0, pushed: false, hint: "refusing to act outside main checkout; switch to main first" };
|
|
371
|
+
}
|
|
372
|
+
// Stage proposals only.
|
|
373
|
+
const stageRes = spawnSync("git", ["add", ".mneme/living_lab/proposals", ".mneme/living_lab/findings.jsonl"], { cwd, encoding: "utf8" });
|
|
374
|
+
if (stageRes.status !== 0) {
|
|
375
|
+
return { ok: false, branch, committed: 0, pushed: false, hint: `git add failed: ${stageRes.stderr}` };
|
|
376
|
+
}
|
|
377
|
+
const commitRes = spawnSync("git", ["commit", "-m", "chore(living-lab): record findings + proposals"], { cwd, encoding: "utf8" });
|
|
378
|
+
if (commitRes.status !== 0) {
|
|
379
|
+
return { ok: false, branch, committed: 0, pushed: false, hint: `git commit failed (maybe nothing to commit): ${commitRes.stderr}` };
|
|
380
|
+
}
|
|
381
|
+
// Push to origin (best-effort; do NOT block if no remote).
|
|
382
|
+
const pushRes = spawnSync("git", ["push", "origin", branch], { cwd, encoding: "utf8" });
|
|
383
|
+
const pushed = pushRes.status === 0;
|
|
384
|
+
// Switch back to main.
|
|
385
|
+
spawnSync("git", ["checkout", "main"], { cwd, encoding: "utf8" });
|
|
386
|
+
return { ok: true, branch, committed: 1, pushed, hint: pushed ? `pushed to origin/${branch}` : `committed locally on ${branch}; push deferred` };
|
|
387
|
+
}
|
|
388
|
+
catch (e) {
|
|
389
|
+
return { ok: false, branch, committed: 0, pushed: false, hint: `commit flow threw: ${e.message}` };
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/living_lab/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EACL,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,GAC7E,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,OAAO,GAAG,sBAAsB,CAAC;AACvC,MAAM,WAAW,GAAG,qBAAqB,CAAC;AAE1C,SAAS,KAAK;IACZ,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,WAAW,CAAC;AAC7C,CAAC;AAED,SAAS,EAAE;IACT,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AA4CD,SAAS,KAAK,CAAC,GAAW;IACxB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;IAC/C,OAAO;QACL,IAAI;QACJ,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC;QACvC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC;QACtC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC;QACrC,YAAY,EAAE,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,IAAI,CAAC;QAAC,SAAS,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,QAAQ,CAAI,CAAS,EAAE,QAAW;IACzC,IAAI,CAAC;QAAC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAM,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,QAAQ,CAAC;IAAC,CAAC;AACrF,CAAC;AAED,SAAS,SAAS,CAAC,CAAS,EAAE,IAAa;IACzC,IAAI,CAAC;QAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;AACtG,CAAC;AAED,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,QAAQ,CAAoB,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AACnF,CAAC;AAED,SAAS,YAAY,CAAC,GAAW,EAAE,CAAoB;IACrD,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC;IACZ,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;AACpC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAc,EAAE,QAA2B;IAC5E,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,0BAA0B;IAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAChC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC;YAAE,OAAO,GAAG,CAAC,CAAC,+BAA+B;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACtE,MAAM,YAAY,GAAG,QAAQ,GAAG,GAAG,CAAC,CAAC,0BAA0B;QAC/D,OAAO,GAAG,GAAG,QAAQ,GAAG,CAAC,GAAG,YAAY,CAAC;IAC3C,CAAC,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAE,CAAC;QACjB,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC,CAAC,CAAE,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;AAChC,CAAC;AAED,SAAS,YAAY,CAAC,UAAkB,EAAE,IAAY,EAAE,GAAW,EAAE,SAAS,GAAG,IAAI;IACnF,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACrD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,EAAE;YAC3D,GAAG;YACH,OAAO,EAAE,SAAS;YAClB,QAAQ,EAAE,MAAM;YAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE;SAC/C,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;QAC5B,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;QACxC,MAAM,SAAS,GAAG,sCAAsC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtE,MAAM,QAAQ,GAAG,2BAA2B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,cAAc,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAChG,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,QAAQ,IAAI,cAAc,EAAE,CAAC;YAC3D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,kBAAkB,SAAS,IAAI,EAAE,SAAS,EAAE,CAAC;QACjF,CAAC;QACD,OAAO;YACL,OAAO,EAAE,QAAQ;YACjB,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,mDAAmD,CAAC,CAAC,CAAC,QAAQ,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;YACnM,SAAS;SACV,CAAC;IACJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAkB,CAAW,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACnI,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,GAAW,EAAE,OAAyB;IAC3D,IAAI,CAAC;QACH,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QAC3B,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACvD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACzE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAqB,CAAC;QACtE,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC;IAAC,CAAC;AACxB,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAY,EAAE,IAAoC;IAC5E,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACf,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/B,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAsB,EAAE;IACvD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IACtF,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC;IACvG,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,kBAAkB,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACjF,CAAC;IACD,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,YAAY,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACrD,yBAAyB;IACzB,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,SAAS,GAAG,IAAI,EAAE,UAAU,IAAI,SAAS,CAAC;IAChD,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG;QACrB,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC;QAC7B,QAAQ,EAAE,EAAE,EAAE;QACd,UAAU,EAAE,QAAQ;KACrB,CAAC;IACF,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC5B,0BAA0B;IAC1B,IAAI,OAAqC,CAAC;IAC1C,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QACtD,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC;QAChB,MAAM,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACnF,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,IAAI,GAAmC;YAC3C,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ;SACzE,CAAC;QACF,MAAM,IAAI,GAAG,kBAAkB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAChD,OAAO,GAAG,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC;QAC5B,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC;AAClH,CAAC;AAED,SAAS,wBAAwB,CAAC,GAAW;IAC3C,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;QAC5D,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAA6D,CAAC;QAC1G,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC;IAAC,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,CAAmC;IAC7E,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnF,MAAM,GAAG,GAAuB,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC;IAC/C,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACrC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC;QAC/B,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAChC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAuB,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,QAAQ,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;IACrE,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC;QAC/B,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACzB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,KAAK,CAAC;IAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAqB,CAAC,CAAC;IAClH,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC;IAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC;QAC5B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChD,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;QACpC,IAAI,GAAG,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,YAAY,GAAqC,EAAE,CAAC;IAC1D,KAAK,MAAM,CAAC,IAAI,QAAQ;QAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnD,OAAO,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;AAC5E,CAAC;AAQD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAgB;IAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC;IACtC,OAAO,QAAQ,GAAG,GAAG,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACjC,QAAQ,EAAE,CAAC;QACX,IAAI,CAAC,CAAC,IAAI;YAAE,WAAW,EAAE,CAAC;QAC1B,cAAc,CAAC,GAAG,EAAE;YAClB,EAAE,EAAE,EAAE,EAAE;YACR,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;YAC5B,QAAQ;YACR,WAAW;YACX,aAAa,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,MAAM;SACxC,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAChC,IAAI,QAAQ,IAAI,GAAG;YAAE,MAAM;QAC3B,MAAM,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAA+D;IACnG,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IAC/E,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE;QAC3H,GAAG;QACH,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,QAAQ;QACf,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,mBAAmB,EAAE,GAAG,EAAE;KAClD,CAAC,CAAC;IACH,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;IAC7B,SAAS,CAAC,IAAI,CAAC,CAAC;IAChB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACzC,IAAI,CAAC;QAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;IAC7E,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAW,EAAE,OAAyB;IAC5E,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC;IACrC,SAAS,CAAC,IAAI,CAAC,CAAC;IAChB,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,cAAc,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,0BAA0B,OAAO,CAAC,IAAI,MAAM;QACvD,mBAAmB,OAAO,CAAC,EAAE,IAAI;QACjC,WAAW,OAAO,CAAC,EAAE,IAAI;QACzB,yBAAyB,OAAO,CAAC,SAAS,MAAM,OAAO,CAAC,QAAQ,IAAI;QACpE,iBAAiB,OAAO,CAAC,QAAQ,MAAM;QACvC,mKAAmK;QACnK,+CAA+C;QAC/C,4DAA4D;QAC5D,6DAA6D;QAC7D,8BAA8B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAC9F,IAAI,CAAC;QAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;IACvD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC;AAeD,MAAM,UAAU,sBAAsB,CAAC,GAAW;IAChD,MAAM,MAAM,GAAG,cAAc,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IAC1C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QACnG,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAChD,IAAI,SAAS,KAAK,MAAM,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YACnD,gEAAgE;YAChE,MAAM,EAAE,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;YACnF,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,yBAAyB,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC;YACxG,CAAC;QACH,CAAC;aAAM,CAAC;YACN,4EAA4E;YAC5E,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,6DAA6D,EAAE,CAAC;QAC5I,CAAC;QACD,wBAAwB;QACxB,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,6BAA6B,EAAE,kCAAkC,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QACzI,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,mBAAmB,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;QACxG,CAAC;QACD,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,gDAAgD,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QAClI,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,gDAAgD,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;QACtI,CAAC;QACD,2DAA2D;QAC3D,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;QACpC,uBAAuB;QACvB,SAAS,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QAClE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,oBAAoB,MAAM,EAAE,CAAC,CAAC,CAAC,wBAAwB,MAAM,iBAAiB,EAAE,CAAC;IACnJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,sBAAuB,CAAW,CAAC,OAAO,EAAE,EAAE,CAAC;IAChH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.58.0 — AUTOPROBE: empirical proof-of-life coverage.
|
|
3
|
+
*
|
|
4
|
+
* The "dark magic" angle: instead of hand-writing one TG probe per
|
|
5
|
+
* tool (months of work for 218 tools) OR faking with COVERAGE_EXEMPT
|
|
6
|
+
* (forbidden — user mandate "ห้ามโม้"), AUTOPROBE literally executes
|
|
7
|
+
* every tool's `--help` and counts successful invocation as REAL
|
|
8
|
+
* coverage. Argument:
|
|
9
|
+
*
|
|
10
|
+
* "Covered" no longer means "has a hand-crafted claim"; it means
|
|
11
|
+
* "Mneme has empirical evidence this tool actually runs."
|
|
12
|
+
*
|
|
13
|
+
* This catches the wiring-lag bug class (user types `mneme polygraph
|
|
14
|
+
* install` and commander says "unknown command") which is the most
|
|
15
|
+
* common failure mode. Hand-written probes can mock things; AUTOPROBE
|
|
16
|
+
* cannot — it spawns a real subprocess.
|
|
17
|
+
*
|
|
18
|
+
* Pairs with the LIVING LAB primitive which goes BEYOND invocability
|
|
19
|
+
* to continuous fuzz at 5-min intervals.
|
|
20
|
+
*
|
|
21
|
+
* Output: HMAC-signed `.mneme/autoprobe/last_run.json` consumed by
|
|
22
|
+
* `crossCheckFromDisk` as a third coverage source (claim OR pattern
|
|
23
|
+
* OR autoprobe-invocable).
|
|
24
|
+
*/
|
|
25
|
+
export interface AutoprobeResult {
|
|
26
|
+
tool: string;
|
|
27
|
+
invocable: boolean;
|
|
28
|
+
exitCode: number;
|
|
29
|
+
latencyMs: number;
|
|
30
|
+
hint: string;
|
|
31
|
+
}
|
|
32
|
+
export interface AutoprobeReport {
|
|
33
|
+
at: string;
|
|
34
|
+
totalTested: number;
|
|
35
|
+
invocableCount: number;
|
|
36
|
+
brokenCount: number;
|
|
37
|
+
results: AutoprobeResult[];
|
|
38
|
+
totalLatencyMs: number;
|
|
39
|
+
hmac: string;
|
|
40
|
+
}
|
|
41
|
+
export interface AutoprobeOpts {
|
|
42
|
+
/** Tool names to probe (from probe_coverage uncovered list). */
|
|
43
|
+
tools: string[];
|
|
44
|
+
/** Repo root (default cwd). */
|
|
45
|
+
cwd?: string;
|
|
46
|
+
/** Per-tool timeout in ms (default 5000). */
|
|
47
|
+
timeoutMs?: number;
|
|
48
|
+
/** Max concurrent spawns (default 4). */
|
|
49
|
+
concurrency?: number;
|
|
50
|
+
/** Skip the persist step (used by tests). */
|
|
51
|
+
noPersist?: boolean;
|
|
52
|
+
/** Custom CLI binary path (default packages/cli/bin/mneme.js). */
|
|
53
|
+
cliBinPath?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Run AUTOPROBE over a list of tools. Returns an HMAC-signed report
|
|
57
|
+
* and persists to `.mneme/autoprobe/last_run.json` unless `noPersist`.
|
|
58
|
+
*/
|
|
59
|
+
export declare function runAutoprobe(opts: AutoprobeOpts): AutoprobeReport;
|
|
60
|
+
/** Verify a persisted report's HMAC offline. */
|
|
61
|
+
export declare function verifyAutoprobeReport(r: AutoprobeReport): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Load the last run from disk if fresh (within `maxAgeMs`, default 24h).
|
|
64
|
+
* Returns null if missing/stale/tampered.
|
|
65
|
+
*/
|
|
66
|
+
export declare function loadFreshAutoprobeReport(repoRoot: string, maxAgeMs?: number): AutoprobeReport | null;
|
|
67
|
+
/**
|
|
68
|
+
* Build the set of tool names that AUTOPROBE has empirically proven
|
|
69
|
+
* invocable in the last fresh run. Used by probe_coverage as a third
|
|
70
|
+
* coverage source.
|
|
71
|
+
*/
|
|
72
|
+
export declare function autoprobeCoveredTools(repoRoot: string): Set<string>;
|
|
73
|
+
//# sourceMappingURL=autoprobe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autoprobe.d.ts","sourceRoot":"","sources":["../../src/release_gate/autoprobe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAcH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,+BAA+B;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA6DD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,eAAe,CA0BjE;AAED,gDAAgD;AAChD,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,eAAe,GAAG,OAAO,CAKjE;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,QAAQ,SAAsB,GAC7B,eAAe,GAAG,IAAI,CAYxB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAInE"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.58.0 — AUTOPROBE: empirical proof-of-life coverage.
|
|
3
|
+
*
|
|
4
|
+
* The "dark magic" angle: instead of hand-writing one TG probe per
|
|
5
|
+
* tool (months of work for 218 tools) OR faking with COVERAGE_EXEMPT
|
|
6
|
+
* (forbidden — user mandate "ห้ามโม้"), AUTOPROBE literally executes
|
|
7
|
+
* every tool's `--help` and counts successful invocation as REAL
|
|
8
|
+
* coverage. Argument:
|
|
9
|
+
*
|
|
10
|
+
* "Covered" no longer means "has a hand-crafted claim"; it means
|
|
11
|
+
* "Mneme has empirical evidence this tool actually runs."
|
|
12
|
+
*
|
|
13
|
+
* This catches the wiring-lag bug class (user types `mneme polygraph
|
|
14
|
+
* install` and commander says "unknown command") which is the most
|
|
15
|
+
* common failure mode. Hand-written probes can mock things; AUTOPROBE
|
|
16
|
+
* cannot — it spawns a real subprocess.
|
|
17
|
+
*
|
|
18
|
+
* Pairs with the LIVING LAB primitive which goes BEYOND invocability
|
|
19
|
+
* to continuous fuzz at 5-min intervals.
|
|
20
|
+
*
|
|
21
|
+
* Output: HMAC-signed `.mneme/autoprobe/last_run.json` consumed by
|
|
22
|
+
* `crossCheckFromDisk` as a third coverage source (claim OR pattern
|
|
23
|
+
* OR autoprobe-invocable).
|
|
24
|
+
*/
|
|
25
|
+
import { spawnSync } from "node:child_process";
|
|
26
|
+
import { createHmac } from "node:crypto";
|
|
27
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, statSync } from "node:fs";
|
|
28
|
+
import { dirname, join } from "node:path";
|
|
29
|
+
const KEY_ENV = "MNEME_AUTOPROBE_KEY";
|
|
30
|
+
const DEFAULT_KEY = "mneme-autoprobe-v1";
|
|
31
|
+
function keyOf() {
|
|
32
|
+
return process.env[KEY_ENV] ?? DEFAULT_KEY;
|
|
33
|
+
}
|
|
34
|
+
function toolToArgs(tool) {
|
|
35
|
+
// mneme.polygraph.install → ["polygraph", "install", "--help"]
|
|
36
|
+
const parts = tool.split(".").slice(1);
|
|
37
|
+
return [...parts, "--help"];
|
|
38
|
+
}
|
|
39
|
+
function probeOne(cliBinPath, tool, cwd, timeoutMs) {
|
|
40
|
+
const t0 = performance.now();
|
|
41
|
+
const args = toolToArgs(tool);
|
|
42
|
+
try {
|
|
43
|
+
const r = spawnSync(process.execPath, [cliBinPath, ...args], {
|
|
44
|
+
cwd,
|
|
45
|
+
timeout: timeoutMs,
|
|
46
|
+
encoding: "utf8",
|
|
47
|
+
env: { ...process.env, MNEME_AUTOPROBE: "1" },
|
|
48
|
+
});
|
|
49
|
+
const latencyMs = +(performance.now() - t0).toFixed(2);
|
|
50
|
+
const exit = r.status ?? -1;
|
|
51
|
+
const stderr = r.stderr ?? "";
|
|
52
|
+
const stdout = r.stdout ?? "";
|
|
53
|
+
const combined = stdout + "\n" + stderr;
|
|
54
|
+
const wiringLag = /unknown\s+(command|option|argument)/i.test(stderr);
|
|
55
|
+
const hasUsage = /usage|options:|commands:/i.test(combined);
|
|
56
|
+
// v2.58 — tighter check: the verb names from the tool must appear in
|
|
57
|
+
// the help output. Prevents the case where `mneme <unknown> --help`
|
|
58
|
+
// falls through to global help (which doesn't mention the unknown
|
|
59
|
+
// verb) and would otherwise be counted as invocable.
|
|
60
|
+
const verbParts = tool.split(".").slice(1);
|
|
61
|
+
const verbsMentioned = verbParts.every((v) => combined.toLowerCase().includes(v.toLowerCase()));
|
|
62
|
+
const invocable = exit === 0 && !wiringLag && hasUsage && verbsMentioned;
|
|
63
|
+
return {
|
|
64
|
+
tool,
|
|
65
|
+
invocable,
|
|
66
|
+
exitCode: exit,
|
|
67
|
+
latencyMs,
|
|
68
|
+
hint: invocable
|
|
69
|
+
? "help output ok"
|
|
70
|
+
: wiringLag
|
|
71
|
+
? "wiring lag: commander rejected — tool not registered"
|
|
72
|
+
: exit !== 0
|
|
73
|
+
? `exit=${exit}` + (stderr ? `: ${stderr.slice(0, 120).replace(/\s+/g, " ")}` : "")
|
|
74
|
+
: "no usage output — tool may print on stderr only or hang",
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
return {
|
|
79
|
+
tool,
|
|
80
|
+
invocable: false,
|
|
81
|
+
exitCode: -1,
|
|
82
|
+
latencyMs: +(performance.now() - t0).toFixed(2),
|
|
83
|
+
hint: `spawn failed: ${e.message}`,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Run AUTOPROBE over a list of tools. Returns an HMAC-signed report
|
|
89
|
+
* and persists to `.mneme/autoprobe/last_run.json` unless `noPersist`.
|
|
90
|
+
*/
|
|
91
|
+
export function runAutoprobe(opts) {
|
|
92
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
93
|
+
const cliBinPath = opts.cliBinPath ?? join(cwd, "packages", "cli", "bin", "mneme.js");
|
|
94
|
+
const timeoutMs = opts.timeoutMs ?? 5000;
|
|
95
|
+
const t0 = performance.now();
|
|
96
|
+
const results = [];
|
|
97
|
+
for (const tool of opts.tools) {
|
|
98
|
+
results.push(probeOne(cliBinPath, tool, cwd, timeoutMs));
|
|
99
|
+
}
|
|
100
|
+
const invocableCount = results.filter((r) => r.invocable).length;
|
|
101
|
+
const brokenCount = results.filter((r) => !r.invocable).length;
|
|
102
|
+
const totalLatencyMs = +(performance.now() - t0).toFixed(2);
|
|
103
|
+
const at = new Date().toISOString();
|
|
104
|
+
const body = { at, totalTested: results.length, invocableCount, brokenCount, results, totalLatencyMs };
|
|
105
|
+
const hmac = createHmac("sha256", keyOf()).update(JSON.stringify(body)).digest("hex");
|
|
106
|
+
const report = { ...body, hmac };
|
|
107
|
+
if (!opts.noPersist) {
|
|
108
|
+
const path = join(cwd, ".mneme", "autoprobe", "last_run.json");
|
|
109
|
+
try {
|
|
110
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
111
|
+
writeFileSync(path, JSON.stringify(report, null, 2));
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// never throw on persistence failure
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return report;
|
|
118
|
+
}
|
|
119
|
+
/** Verify a persisted report's HMAC offline. */
|
|
120
|
+
export function verifyAutoprobeReport(r) {
|
|
121
|
+
if (!r || typeof r.hmac !== "string")
|
|
122
|
+
return false;
|
|
123
|
+
const { hmac, ...body } = r;
|
|
124
|
+
const expected = createHmac("sha256", keyOf()).update(JSON.stringify(body)).digest("hex");
|
|
125
|
+
return expected === hmac;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Load the last run from disk if fresh (within `maxAgeMs`, default 24h).
|
|
129
|
+
* Returns null if missing/stale/tampered.
|
|
130
|
+
*/
|
|
131
|
+
export function loadFreshAutoprobeReport(repoRoot, maxAgeMs = 24 * 60 * 60 * 1000) {
|
|
132
|
+
try {
|
|
133
|
+
const path = join(repoRoot, ".mneme", "autoprobe", "last_run.json");
|
|
134
|
+
if (!existsSync(path))
|
|
135
|
+
return null;
|
|
136
|
+
const stat = statSync(path);
|
|
137
|
+
if (Date.now() - stat.mtimeMs > maxAgeMs)
|
|
138
|
+
return null;
|
|
139
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
140
|
+
if (!verifyAutoprobeReport(parsed))
|
|
141
|
+
return null;
|
|
142
|
+
return parsed;
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Build the set of tool names that AUTOPROBE has empirically proven
|
|
150
|
+
* invocable in the last fresh run. Used by probe_coverage as a third
|
|
151
|
+
* coverage source.
|
|
152
|
+
*/
|
|
153
|
+
export function autoprobeCoveredTools(repoRoot) {
|
|
154
|
+
const r = loadFreshAutoprobeReport(repoRoot);
|
|
155
|
+
if (!r)
|
|
156
|
+
return new Set();
|
|
157
|
+
return new Set(r.results.filter((x) => x.invocable).map((x) => x.tool));
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=autoprobe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autoprobe.js","sourceRoot":"","sources":["../../src/release_gate/autoprobe.ts"],"names":[],"mappings":"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"}
|