ruvnet-brain 4.0.12 → 4.0.24
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/README.md +3 -3
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/scripts/advocacy-outcomes.mjs +808 -0
- package/plugin/scripts/anticipate.sh +80 -14
- package/plugin/scripts/capability-registry.mjs +994 -0
- package/plugin/scripts/codex-hook-wrapper.mjs +1 -0
- package/plugin/scripts/continuation-gate.mjs +129 -1
- package/plugin/scripts/gates.mjs +146 -0
- package/plugin/scripts/goal-match.mjs +398 -0
- package/plugin/scripts/hijack-ruvnet.sh +69 -1
- package/plugin/scripts/hook-registry.mjs +616 -0
- package/plugin/scripts/hook-shim.mjs +13 -2
- package/plugin/scripts/learning-enable.mjs +382 -0
- package/plugin/scripts/lesson-promote.mjs +262 -0
- package/plugin/scripts/lesson-provenance.mjs +43 -0
- package/plugin/scripts/lesson-store.mjs +67 -56
- package/plugin/scripts/memory-doctor.mjs +345 -0
- package/plugin/scripts/nightly-controller.mjs +98 -0
- package/plugin/scripts/runtime-preferences.mjs +18 -0
- package/plugin/scripts/unprompted-runtime.mjs +22 -7
- package/plugin/scripts/user-settings.mjs +672 -0
- package/plugin/skills/ruvnet-brain/SKILL.md +2 -2
- package/scripts/advocacy-outcomes.mjs +4 -808
- package/scripts/capability-registry.mjs +4 -876
- package/scripts/corpus-qa.mjs +44 -6
- package/scripts/doc-currency.mjs +30 -2
- package/scripts/gates.mjs +4 -146
- package/scripts/goal-match.mjs +4 -398
- package/scripts/hook-registry.mjs +4 -567
- package/scripts/issue-watch.mjs +108 -0
- package/scripts/learning-enable.mjs +4 -380
- package/scripts/lesson-promote.mjs +4 -262
- package/scripts/memory-doctor.mjs +4 -345
- package/scripts/nightly-controller.mjs +4 -66
- package/scripts/nightly-wrapper.sh +23 -1
- package/scripts/proactivity-metrics.mjs +8 -1
- package/scripts/qe/ux-suite.mjs +72 -1
- package/scripts/release-abort-stale.mjs +111 -0
- package/scripts/release-convergence-watchdog.mjs +119 -0
- package/scripts/release-transaction-provider.mjs +46 -6
- package/scripts/release-transaction.mjs +55 -17
- package/scripts/self-update.mjs +63 -10
- package/scripts/user-settings.mjs +4 -640
package/scripts/self-update.mjs
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import fs from 'node:fs';
|
|
17
17
|
import os from 'node:os';
|
|
18
18
|
import path from 'node:path';
|
|
19
|
-
import { execFileSync } from 'node:child_process';
|
|
19
|
+
import { execFileSync, spawnSync } from 'node:child_process';
|
|
20
20
|
import { fileURLToPath } from 'node:url';
|
|
21
21
|
import { FULL_HINTS, KEEP_DIRS } from './full-hints.mjs';
|
|
22
22
|
import { withSubmoduleSymlinksDetached } from './git-clone-refresh.mjs';
|
|
@@ -228,6 +228,42 @@ if (!APPLY) {
|
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
const NOTIFY = (t, m, p) => { try { execFileSync('sh', [path.join(ROOT, 'scripts/notify.sh'), t, m, p || 'default']); } catch { /* alerting never breaks the pipeline */ } };
|
|
231
|
+
|
|
232
|
+
// ---- child steps that can explain themselves -------------------------------------------------
|
|
233
|
+
// With stdio:'inherit' a failing child's Error carries NO output: e.stdout and e.stderr are both
|
|
234
|
+
// null and e.message is only "Command failed: <argv>" (verified 2026-08-06). That empty reason is
|
|
235
|
+
// what propagated into the [FATAL] summary, which is in turn what nightly-wrapper.sh samples for
|
|
236
|
+
// the escalation — so six identical nightly failures escalated saying nothing, while the log had
|
|
237
|
+
// the answer the whole time.
|
|
238
|
+
//
|
|
239
|
+
// Capture, then RE-EMIT verbatim so the log is byte-identical to what stdio:'inherit' produced,
|
|
240
|
+
// and keep a tail for the failure record.
|
|
241
|
+
// captureStdout=false (clone/fetch/reset/symbols): stdout stays inherited so those steps stream
|
|
242
|
+
// live and survive a kill; only stderr is buffered (small: stacks and warnings).
|
|
243
|
+
// captureStdout=true (every step that carries a corpus-QA verdict — [refresh] and [qa]): BOTH
|
|
244
|
+
// streams, because corpus-qa prints its verdict table and every '↳ <reason>' line via
|
|
245
|
+
// console.log — i.e. on STDOUT. Capturing stderr alone would have captured nothing for the
|
|
246
|
+
// exact failure this exists to explain. Measured output is ~34 lines/step, so it costs nothing.
|
|
247
|
+
const STEP_TAIL_LINES = 14;
|
|
248
|
+
function runStep(label, file, args, opts = {}, { captureStdout = false } = {}) {
|
|
249
|
+
const r = spawnSync(file, args, {
|
|
250
|
+
...opts,
|
|
251
|
+
stdio: ['inherit', captureStdout ? 'pipe' : 'inherit', 'pipe'],
|
|
252
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
253
|
+
});
|
|
254
|
+
if (r.stdout?.length) process.stdout.write(r.stdout);
|
|
255
|
+
if (r.stderr?.length) process.stderr.write(r.stderr);
|
|
256
|
+
if (r.error) { r.error.step = label; throw r.error; }
|
|
257
|
+
if (r.status !== 0) {
|
|
258
|
+
const tail = Buffer.concat([r.stdout || Buffer.alloc(0), r.stderr || Buffer.alloc(0)]).toString()
|
|
259
|
+
.split('\n').map((l) => l.trim()).filter(Boolean).slice(-STEP_TAIL_LINES).join(' | ');
|
|
260
|
+
const err = new Error(`${label} exited ${r.status}${tail ? ` — ${tail}` : ' — (child produced no output)'}`);
|
|
261
|
+
err.step = label;
|
|
262
|
+
err.status = r.status;
|
|
263
|
+
err.output = tail;
|
|
264
|
+
throw err;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
231
267
|
const failures = []; // per-repo build failures collected here; ANY failure aborts before publish (see below)
|
|
232
268
|
for (const p of todo) {
|
|
233
269
|
const dir = clonePath(p.name);
|
|
@@ -235,15 +271,15 @@ for (const p of todo) {
|
|
|
235
271
|
if (!fs.existsSync(path.join(dir, '.git'))) {
|
|
236
272
|
console.log(`[clone] ${p.name}`);
|
|
237
273
|
fs.mkdirSync(CLONE_DIR, { recursive: true });
|
|
238
|
-
|
|
274
|
+
runStep(`[clone] ${p.name}`, 'git', ['clone', '--depth', '1', `https://github.com/${p.owner || p.org || 'ruvnet'}/${p.repo || p.name}`, dir]);
|
|
239
275
|
} else {
|
|
240
276
|
// Some cached clones deduplicate large submodules with symlinks to another clone. Git refuses
|
|
241
277
|
// even a fetch when a gitlink path is a symlink ("expected submodule path ... not to be a
|
|
242
278
|
// symbolic link"). Detach only those declared submodule symlinks for fetch/reset, then restore
|
|
243
279
|
// them in finally so a network/reset failure cannot strand the cache in a half-repaired state.
|
|
244
280
|
withSubmoduleSymlinksDetached(dir, () => {
|
|
245
|
-
|
|
246
|
-
|
|
281
|
+
runStep(`[fetch] ${p.name}`, 'git', ['-C', dir, 'fetch', '--depth', '1', 'origin']);
|
|
282
|
+
runStep(`[reset] ${p.name}`, 'git', ['-C', dir, 'reset', '--hard', 'origin/HEAD']);
|
|
247
283
|
});
|
|
248
284
|
}
|
|
249
285
|
const env = { ...process.env, KB_MODEL_CACHE: MODEL_CACHE };
|
|
@@ -255,26 +291,43 @@ for (const p of todo) {
|
|
|
255
291
|
if (full) buildArgs.push('--full', full);
|
|
256
292
|
if (keep) buildArgs.push('--keep', keep);
|
|
257
293
|
console.log(`[refresh] ${kb}`);
|
|
258
|
-
|
|
294
|
+
// captureStdout: forge-refresh runs corpus-qa against its CANDIDATE dir and refuses to promote
|
|
295
|
+
// on a FAIL — so this step, not the [qa] step below, is where the six 2026-08-03..08-06 nightly
|
|
296
|
+
// failures actually died, and the verdict table naming the offending chunk is on ITS stdout.
|
|
297
|
+
// Steps produce ~34 lines at most (largest measured [refresh] section in logs/nightly.log), so
|
|
298
|
+
// buffering costs nothing; the tradeoff is that the log flushes at step end rather than live.
|
|
299
|
+
runStep(`[refresh] ${kb}`, NODE, buildArgs, { cwd: path.join(ROOT, 'kb'), env }, { captureStdout: true });
|
|
259
300
|
console.log(`[symbols] ${kb}`);
|
|
260
|
-
|
|
301
|
+
runStep(`[symbols] ${kb}`, NODE, ['scripts/build-symbols.mjs', '--name', kb], { cwd: ROOT, env });
|
|
261
302
|
// Corpus QA gate (scripts/corpus-qa.mjs): structural (passages>0, full-bodies>0 where
|
|
262
303
|
// FULL_HINTS demands them, vectors==passages, embed.json present) + deterministic
|
|
263
304
|
// self-retrieval round trip on every canonical store. Non-zero exit throws -> failures[] ->
|
|
264
305
|
// the run aborts before stamp/bundle/publish. This is the machine version of the
|
|
265
306
|
// 2026-07-10 hand-verification: a store that embeds wrong or reads wrong cannot ship.
|
|
266
307
|
console.log(`[qa] ${kb}`);
|
|
267
|
-
|
|
268
|
-
|
|
308
|
+
// captureStdout: corpus-qa's verdict table and its '↳ <reason>' lines go to stdout.
|
|
309
|
+
runStep(`[qa] ${kb}`, NODE, ['scripts/corpus-qa.mjs', '--store', kb], { cwd: ROOT, env }, { captureStdout: true });
|
|
310
|
+
} catch (e) {
|
|
311
|
+
console.error(`[FAIL] ${p.name}: ${e.message}`);
|
|
312
|
+
failures.push({ name: p.name, step: e.step || '(unknown step)', error: e.message, reason: e.output || '' });
|
|
313
|
+
}
|
|
269
314
|
}
|
|
270
315
|
|
|
271
316
|
// A per-repo build failure used to be logged and swallowed before the run re-stamped and re-bundled
|
|
272
317
|
// partial data. Fail loud: if ANY repo failed, abort before stamp/bundle. This rebuild process has no
|
|
273
318
|
// publication authority; a later protected release may consume only a fully prepared candidate.
|
|
274
319
|
if (failures.length) {
|
|
275
|
-
|
|
320
|
+
// Carry the REASON, not just the count. The wrapper samples this block's tail for the push
|
|
321
|
+
// escalation, so whatever is not printed here is not in the alert either.
|
|
322
|
+
const first = failures[0];
|
|
323
|
+
NOTIFY('🔴 Nightly brain rebuild ABORTED',
|
|
324
|
+
`${failures.length} repo build(s) failed — no candidate prepared. First: ${first.name} ${first.step} — ${first.reason || first.error}`,
|
|
325
|
+
'urgent');
|
|
276
326
|
console.error(`\n[FATAL] ${failures.length} repo build(s) failed this run — aborting before stamp/bundle. No candidate prepared:`);
|
|
277
|
-
for (const f of failures)
|
|
327
|
+
for (const f of failures) {
|
|
328
|
+
console.error(` - ${f.name} ${f.step}: ${f.error}`);
|
|
329
|
+
if (f.reason) console.error(` reason: ${f.reason}`);
|
|
330
|
+
}
|
|
278
331
|
console.error('Fix the failing repo(s) and re-run.');
|
|
279
332
|
process.exit(1);
|
|
280
333
|
}
|