ruvnet-brain 4.3.21 → 4.3.26
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 +5 -5
- package/bin/install.mjs +275 -60
- package/console/app.js +189 -9
- package/console/index.html +70 -24
- package/console/scope.css +137 -0
- package/console/scope.html +144 -0
- package/console/scope.js +209 -0
- package/console/style.css +26 -0
- package/console/tips.html +1 -0
- package/kb/corpus-release-identity.mjs +239 -0
- package/kb/update-storage-transaction.mjs +20 -3
- package/package.json +9 -2
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/commands/checkpoint.md +61 -0
- package/plugin/hooks/codex-hooks.json +64 -1
- package/plugin/hooks/hook-contracts.json +299 -6
- package/plugin/hooks/hooks.json +81 -1
- package/plugin/mcp/server.mjs +23 -0
- package/plugin/scripts/advocacy-catalog.mjs +245 -0
- package/plugin/scripts/advocacy-route.mjs +460 -0
- package/plugin/scripts/continuation-gate.mjs +25 -2
- package/plugin/scripts/continuation-objective.mjs +7 -1
- package/plugin/scripts/continuity-hook-policy.mjs +190 -15
- package/plugin/scripts/coverage-integrity.mjs +7 -0
- package/plugin/scripts/gates.mjs +113 -10
- package/plugin/scripts/grounding-turn-gate.mjs +167 -0
- package/plugin/scripts/grounding-turn-mark.mjs +91 -0
- package/plugin/scripts/hook-shim.mjs +14 -0
- package/plugin/scripts/nightly-scheduler.mjs +37 -4
- package/plugin/scripts/project-progression-checkpoint.mjs +145 -0
- package/plugin/scripts/project-progression-contract.mjs +16 -0
- package/plugin/scripts/project-progression-hook.mjs +3 -0
- package/plugin/scripts/project-progression-producer.mjs +252 -0
- package/plugin/scripts/project-progression-reader.mjs +271 -0
- package/plugin/scripts/project-progression-session-start.mjs +93 -16
- package/plugin/scripts/project-progression-sources.mjs +220 -0
- package/plugin/scripts/project-progression-store.mjs +106 -13
- package/plugin/scripts/ruvnet-gate1-pattern.mjs +29 -0
- package/plugin/scripts/session-snapshot-hook.mjs +115 -7
- package/plugin/scripts/session-start-budget.mjs +59 -0
- package/plugin/scripts/session-start-core.mjs +234 -457
- package/plugin/scripts/session-start-fsutil.mjs +61 -0
- package/plugin/scripts/session-start-health.mjs +64 -0
- package/plugin/scripts/session-start-hook-description.mjs +45 -0
- package/plugin/scripts/session-start-issue-alert.mjs +77 -0
- package/plugin/scripts/session-start-repo-identity.mjs +54 -0
- package/plugin/scripts/session-start-signals.mjs +73 -0
- package/plugin/scripts/session-start-trace.mjs +86 -0
- package/plugin/scripts/session-start-update-plane.mjs +104 -0
- package/plugin/scripts/unprompted-runtime.mjs +32 -2
- package/plugin/skills/ruvnet-brain/PLAYBOOK.md +26 -2
- package/plugin/skills/ruvnet-brain/SKILL.md +67 -2
- package/scripts/adr-072-completion.mjs +1 -1
- package/scripts/agentdb-fleet-doctor.mjs +5 -1
- package/scripts/approved-runtime.mjs +197 -0
- package/scripts/brain-novice-50.mjs +16 -1
- package/scripts/brain-score.mjs +23 -5
- package/scripts/build-bundle.mjs +971 -530
- package/scripts/build-concepts.mjs +36 -116
- package/scripts/console-engine.test.mjs +8 -7
- package/scripts/console-runtime-identity.mjs +4 -0
- package/scripts/corpus-aggregates.mjs +94 -77
- package/scripts/corpus-candidate.mjs +475 -222
- package/scripts/corpus-next-seed.mjs +225 -0
- package/scripts/corpus-promotion.mjs +58 -0
- package/scripts/corpus-reconcile.mjs +411 -105
- package/scripts/doc-currency.mjs +16 -1
- package/scripts/dual-host-deliberation.mjs +25 -2
- package/scripts/dual-host-suggest.mjs +17 -1
- package/scripts/falsify.mjs +13 -3
- package/scripts/gist-receipts.mjs +482 -87
- package/scripts/github-health-watch.mjs +12 -2
- package/scripts/handoff-asset.mjs +34 -0
- package/scripts/hook-retirement-check.mjs +8 -1
- package/scripts/host-registry.mjs +1 -1
- package/scripts/ingest-gists.mjs +74 -101
- package/scripts/job-heartbeat.sh +77 -14
- package/scripts/learning-replay-execution.mjs +10 -4
- package/scripts/nightly-gists.sh +27 -13
- package/scripts/nightly-two-run-proof.mjs +1 -1
- package/scripts/nightly-watchdog.mjs +61 -4
- package/scripts/onboarding-console.mjs +364 -28
- package/scripts/oracle/produce-questions.mjs +293 -0
- package/scripts/oracle/producer-hosts.mjs +235 -0
- package/scripts/oracle/repo-recall.mjs +448 -0
- package/scripts/oracle/retrieval-accuracy.mjs +818 -0
- package/scripts/oracle/source-tree.mjs +165 -0
- package/scripts/oracle/source-units.mjs +391 -0
- package/scripts/oracle/spike-run.mjs +98 -0
- package/scripts/oracle/unit-inventory.mjs +141 -0
- package/scripts/oracle/unit-sampling.mjs +128 -0
- package/scripts/oracle/validate-labels.mjs +250 -0
- package/scripts/private-overlay.mjs +248 -0
- package/scripts/product-integrity-contract.mjs +1 -1
- package/scripts/proxy/claude-proxied.sh +6 -0
- package/scripts/proxy/proxy-revert.sh +5 -0
- package/scripts/proxy/proxy-up.sh +6 -0
- package/scripts/proxy/proxy-verify.mjs +4 -0
- package/scripts/public-inputs.mjs +409 -0
- package/scripts/public-verification-inputs.mjs +112 -26
- package/scripts/public-verification-lane.mjs +1 -1
- package/scripts/published-surface-probe.mjs +34 -4
- package/scripts/qe/card-lane-gate.mjs +16 -1
- package/scripts/qe/session-start-gate.mjs +16 -1
- package/scripts/rebuild-gists-from-receipts.mjs +58 -78
- package/scripts/record-lesson.mjs +4 -1
- package/scripts/rehearse-corpus-pipeline.mjs +994 -0
- package/scripts/release-abort-stale.mjs +5 -1
- package/scripts/release-authority.mjs +104 -12
- package/scripts/release-channel-kind.mjs +86 -0
- package/scripts/release-convergence-watchdog.mjs +7 -2
- package/scripts/release-projection.mjs +177 -72
- package/scripts/release-transaction-provider.mjs +47 -10
- package/scripts/release-transaction.mjs +40 -11
- package/scripts/release.mjs +252 -17
- package/scripts/retrieval-canary.mjs +87 -0
- package/scripts/rvf-index-audit.mjs +573 -13
- package/scripts/rvf-wire.mjs +269 -0
- package/scripts/seal-gist-receipt.mjs +65 -0
- package/scripts/selfcheck.mjs +42 -21
- package/scripts/source-coverage.mjs +253 -24
- package/scripts/status-honesty.mjs +25 -0
- package/scripts/sync-census.mjs +0 -0
- package/scripts/sync-version.mjs +2 -0
- package/scripts/trismart.mjs +42 -0
- package/scripts/updater-manifest.mjs +162 -0
- package/scripts/verify-channels.mjs +17 -5
- package/scripts/wired-check.mjs +48 -10
- package/tri-smart-skill/QUICKSTART.md +37 -0
- package/tri-smart-skill/README.md +92 -0
- package/tri-smart-skill/install.cmd +14 -0
- package/tri-smart-skill/install.command +13 -0
- package/tri-smart-skill/install.mjs +51 -0
- package/tri-smart-skill/install.sh +9 -0
- package/tri-smart-skill/tri-smart/SKILL.md +90 -0
- package/tri-smart-skill/tri-smart/evals/evals.json +25 -0
- package/tri-smart-skill/tri-smart/references/protocol.md +25 -0
- package/tri-smart-skill/tri-smart/references/provider-cli.md +18 -0
- package/tri-smart-skill/tri-smart/scripts/review.mjs +154 -0
- package/tri-smart-skill/tri-smart/scripts/setup.mjs +97 -0
- package/tri-smart-skill/tri-smart/scripts/verify-access.mjs +107 -0
- package/scripts/corpus-seed-publish.mjs +0 -110
|
@@ -39,6 +39,7 @@ import os from 'node:os';
|
|
|
39
39
|
import { spawnSync, execFileSync } from 'node:child_process';
|
|
40
40
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
41
41
|
import { NIGHTLY_LABEL, schedulerStatus } from '../plugin/scripts/nightly-scheduler.mjs';
|
|
42
|
+
import { oldestIncompleteProgress } from '../kb/shard-progress.mjs';
|
|
42
43
|
|
|
43
44
|
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
44
45
|
const REGISTRY = process.env.WATCHDOG_REGISTRY || path.join(ROOT, 'config', 'scheduled-jobs.json');
|
|
@@ -51,6 +52,28 @@ export const MISSING = 'MISSING';
|
|
|
51
52
|
export const NEVER_RAN = 'NEVER-RAN';
|
|
52
53
|
export const STALE = 'STALE';
|
|
53
54
|
export const FAILING = 'FAILING';
|
|
55
|
+
export const STALLED = 'STALLED';
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Per-shard progress evidence for a job that declares `progressGlob` + `stallMinutes` in the
|
|
59
|
+
* registry (see kb/shard-progress.mjs, written by kb/forge-big.mjs's `embed`/`shard-all` modes).
|
|
60
|
+
*
|
|
61
|
+
* WHY THIS EXISTS (2026-09-11): a live wrapper pid proves the WRAPPER survived a run; it proves
|
|
62
|
+
* NOTHING about whether the work inside it is still moving — an 8-shard gists embed once sat at 0%
|
|
63
|
+
* CPU for six hours with `judge()`'s existing pid-liveness check reporting it OK the entire time
|
|
64
|
+
* (the pid genuinely was alive; it just was not doing anything). `job.stallMinutes` is deliberately
|
|
65
|
+
* independent of `job.maxAgeHours`/the 6h long-run branch below — a job stuck at 0% progress for 20
|
|
66
|
+
* minutes must be flagged well before its overall schedule budget or the long-run grace period would
|
|
67
|
+
* ever trip.
|
|
68
|
+
*/
|
|
69
|
+
export function readJobProgress(job, { root = ROOT } = {}) {
|
|
70
|
+
if (!job.progressGlob) return null;
|
|
71
|
+
const full = path.join(root, job.progressGlob);
|
|
72
|
+
const dir = path.dirname(full);
|
|
73
|
+
const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
74
|
+
const pattern = new RegExp(`^${path.basename(full).split('*').map(escapeRegExp).join('.*')}$`);
|
|
75
|
+
return oldestIncompleteProgress(dir, pattern);
|
|
76
|
+
}
|
|
54
77
|
|
|
55
78
|
/** Labels currently loaded in launchd. A job that isn't here CANNOT fire, whatever its plist says. */
|
|
56
79
|
export function loadedLabels(run = () => spawnSync('launchctl', ['list'], { encoding: 'utf8' }).stdout || '') {
|
|
@@ -67,7 +90,7 @@ export function loadedLabels(run = () => spawnSync('launchctl', ['list'], { enco
|
|
|
67
90
|
* Judge one job from its receipt. `hb === null` means NO RECEIPT EXISTS — which is NEVER-RAN, never OK.
|
|
68
91
|
* This single line is the whole lesson of 2026-07-13: absence of evidence is not evidence of health.
|
|
69
92
|
*/
|
|
70
|
-
export function judge(job, hb, loaded, now) {
|
|
93
|
+
export function judge(job, hb, loaded, now, { root = ROOT } = {}) {
|
|
71
94
|
if (!loaded) {
|
|
72
95
|
return { state: MISSING, detail: 'declared in the registry but NOT LOADED in launchd — it can never fire' };
|
|
73
96
|
}
|
|
@@ -80,6 +103,20 @@ export function judge(job, hb, loaded, now) {
|
|
|
80
103
|
}
|
|
81
104
|
const ageHours = (now - stamp) / HOUR;
|
|
82
105
|
|
|
106
|
+
// STALLED: checked BEFORE the long-run pid-liveness branch below, and independent of it — a live
|
|
107
|
+
// pid is not proof of progress. Only applies when the job declares a stall budget; absence of a
|
|
108
|
+
// progress file is never treated as a stall (the job may not have reached embedding yet).
|
|
109
|
+
if (hb.state === 'running' && job.stallMinutes) {
|
|
110
|
+
const progress = readJobProgress(job, { root });
|
|
111
|
+
if (progress) {
|
|
112
|
+
const staleMinutes = (now - progress.updatedAt) / 60_000;
|
|
113
|
+
if (staleMinutes > job.stallMinutes) {
|
|
114
|
+
return { state: STALLED, ageHours,
|
|
115
|
+
detail: `${progress.detail} has not advanced in ${staleMinutes.toFixed(0)}m — its stall budget is ${job.stallMinutes}m. The wrapper pid may be alive; the work is not.` };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
83
120
|
// Started and never finished? DERIVE it from process liveness, not wall-clock alone (2026-07-19):
|
|
84
121
|
// a full corpus rebuild legitimately runs 12h+ (five changed repos = a long day), and the old
|
|
85
122
|
// ">6h running ⇒ FAILING" rule false-alarmed on exactly that — a 13.5h nightly whose worker was
|
|
@@ -110,8 +147,12 @@ export function judge(job, hb, loaded, now) {
|
|
|
110
147
|
if (hb.state === 'skipped') {
|
|
111
148
|
return { state: NEVER_RAN, ageHours, detail: 'only a lock-skip receipt exists — no real run has ever recorded a result' };
|
|
112
149
|
}
|
|
113
|
-
if (hb.state === 'failed' || (typeof hb.exit_code === 'number' && hb.exit_code !== 0)) {
|
|
114
|
-
|
|
150
|
+
if (hb.state === 'failed' || hb.state === 'killed' || (typeof hb.exit_code === 'number' && hb.exit_code !== 0)) {
|
|
151
|
+
// job-heartbeat.sh distinguishes "failed" (plain non-zero exit) from "killed" (died to a
|
|
152
|
+
// signal — the wrapper's own trap, or a direct kill of the child; POSIX 128+signal) — surface
|
|
153
|
+
// which one it was rather than collapsing both into one undifferentiated exit code.
|
|
154
|
+
const how = hb.state === 'killed' ? `KILLED by signal ${hb.signal ?? '?'}` : `FAILED with exit ${hb.exit_code}`;
|
|
155
|
+
return { state: FAILING, ageHours, detail: `last run ${how} (${ageHours.toFixed(1)}h ago)` };
|
|
115
156
|
}
|
|
116
157
|
if (hb.state === 'running') {
|
|
117
158
|
return { state: OK, ageHours, detail: `running right now (started ${ageHours.toFixed(1)}h ago)` };
|
|
@@ -153,7 +194,7 @@ export function checkAll(now, { registry = REGISTRY, loaded = loadedLabels(), hb
|
|
|
153
194
|
const { jobs } = JSON.parse(fs.readFileSync(registry, 'utf8'));
|
|
154
195
|
return jobs.map((job) => {
|
|
155
196
|
const hb = readHeartbeat(job.label, hbDir) || readLegacyLog(job, root);
|
|
156
|
-
const verdict = judge(job, hb, loaded.has(job.label), now);
|
|
197
|
+
const verdict = judge(job, hb, loaded.has(job.label), now, { root });
|
|
157
198
|
if (hb?._tier2 && verdict.state === OK) verdict.detail += ' (via its log — no receipt yet; the next run writes one)';
|
|
158
199
|
return { ...job, ...verdict };
|
|
159
200
|
});
|
|
@@ -162,6 +203,22 @@ export function checkAll(now, { registry = REGISTRY, loaded = loadedLabels(), hb
|
|
|
162
203
|
export function productSchedulerVerdict(status) {
|
|
163
204
|
const base = { label: NIGHTLY_LABEL, what: 'Refreshes the installed Brain corpus and converges every detected host',
|
|
164
205
|
schedule: 'daily 03:47', maxAgeHours: 30, required: true };
|
|
206
|
+
// A 'degraded' adapter whose only defect is a NON-ZERO LAST EXIT is a job that is loaded, verified
|
|
207
|
+
// and FIRED — the exact opposite of MISSING ("not loaded — it can never fire", top of this file).
|
|
208
|
+
// Its truth is the receipt. Measured 2026-09-12 against two FAILED receipts: this projected as
|
|
209
|
+
// MISSING with the detail "LaunchAgent is loaded and runner digest verified, but last exited 1" —
|
|
210
|
+
// a contradiction in one line, and the receipt's reason never surfaced.
|
|
211
|
+
if (status?.state === 'degraded' && Number.isInteger(status.lastExitCode) && status.lastExitCode !== 0) {
|
|
212
|
+
const run = status.runHealth || null;
|
|
213
|
+
if (run?.state === 'stale') return { ...base, state: STALE, detail: run.evidence };
|
|
214
|
+
if (!run || run.state === 'never-ran') {
|
|
215
|
+
return { ...base, state: FAILING, detail: `runner last exited ${status.lastExitCode} and left no receipt — it fired and died before recording a run` };
|
|
216
|
+
}
|
|
217
|
+
if (run.state === 'ok' || run.state === 'running') {
|
|
218
|
+
return { ...base, state: FAILING, detail: `runner last exited ${status.lastExitCode} although its latest receipt reads ${run.state} — the run after that receipt died without recording one (${run.evidence})` };
|
|
219
|
+
}
|
|
220
|
+
return { ...base, state: FAILING, detail: run.evidence };
|
|
221
|
+
}
|
|
165
222
|
if (status?.state !== 'on') return { ...base, state: MISSING, detail: status?.evidence || 'scheduler is not registered' };
|
|
166
223
|
const run = status.runHealth || { state: 'never-ran', evidence: 'No nightly refresh receipt exists yet.' };
|
|
167
224
|
const mapped = run.state === 'ok' || run.state === 'running' ? OK
|