ruvnet-brain 4.0.1 → 4.0.2
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/.claude-plugin/marketplace.json +1 -0
- package/README.md +4 -4
- package/bin/install.mjs +100 -5
- package/console/CONTRACT.md +172 -0
- package/console/activity.js +753 -0
- package/console/app.js +4189 -0
- package/console/architecture.html +1221 -0
- package/console/assets/depth-1.webp +0 -0
- package/console/assets/depth-2.webp +0 -0
- package/console/assets/depth-3.webp +0 -0
- package/console/assets/harness-vs-plain.svg +259 -0
- package/console/assets/hero.webp +0 -0
- package/console/assets/memory.webp +0 -0
- package/console/assets/metaharness.svg +247 -0
- package/console/index.html +777 -0
- package/console/install-architecture.html +162 -0
- package/console/install-mockup.html +543 -0
- package/console/style.css +2144 -0
- package/console/tips.css +926 -0
- package/console/tips.html +858 -0
- package/console/tips.js +128 -0
- package/docs/RELEASE-NOTES-4.0.md +88 -0
- package/kb/model-requirements.mjs +37 -6
- package/keys/ruvnet-brain-signing.pub.pem +3 -0
- package/package.json +8 -22
- package/plugin/.claude-plugin/marketplace.json +1 -0
- package/plugin/.claude-plugin/plugin.json +2 -3
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/commands/brain-console.md +2 -2
- package/plugin/commands/configure.md +3 -2
- package/plugin/commands/rvbc.md +4 -3
- package/plugin/commands/rvcb.md +2 -2
- package/plugin/hooks/hooks.json +1 -2
- package/plugin/mcp/managed-cli-interface.mjs +47 -4
- package/plugin/mcp/server.mjs +21 -0
- package/plugin/scripts/detach.mjs +14 -0
- package/plugin/scripts/first-session-worker.mjs +38 -0
- package/plugin/scripts/ground-ruvnet.sh +16 -6
- package/plugin/scripts/hook-shim.mjs +7 -7
- package/plugin/scripts/learn-capture.sh +22 -3
- package/plugin/scripts/learn-flush.mjs +21 -4
- package/plugin/scripts/runtime-preferences.mjs +269 -0
- package/plugin/scripts/session-start-core.mjs +477 -0
- package/plugin/scripts/session-start.sh +3 -858
- package/plugin/skills/brain-console/SKILL.md +4 -2
- package/plugin/skills/release-proof/SKILL.md +81 -0
- package/plugin/skills/release-proof/agents/openai.yaml +4 -0
- package/plugin/skills/release-proof/references/receipt-contract.md +38 -0
- package/plugin/skills/release-proof/scripts/release-proof.mjs +210 -0
- package/plugin/skills/ruvnet-brain/PLAYBOOK.md +5 -1
- package/plugin/skills/rvbc/SKILL.md +9 -6
- package/scripts/adr-backfill.mjs +107 -0
- package/scripts/advocacy-outcomes.mjs +808 -0
- package/scripts/agentdb-context.mjs +216 -0
- package/scripts/agentdb-fleet-doctor.mjs +101 -0
- package/scripts/ascii-drift.mjs +236 -0
- package/scripts/behavioral-l1-l4.mjs +210 -0
- package/scripts/brain-capability-check.mjs +72 -0
- package/scripts/brain-grade-groundtruth.mjs +100 -0
- package/scripts/brain-latency-50.mjs +227 -0
- package/scripts/brain-novice-50.mjs +189 -0
- package/scripts/brain-stamp.mjs +94 -0
- package/scripts/brain-state.mjs +212 -0
- package/scripts/build-bundle.mjs +522 -0
- package/scripts/build-concepts.mjs +132 -0
- package/scripts/build-l2.mjs +71 -0
- package/scripts/build-primer.mjs +73 -0
- package/scripts/build-symbols.mjs +68 -0
- package/scripts/calibrate-router.mjs +97 -0
- package/scripts/capability-audit.mjs +321 -0
- package/scripts/capability-registry.mjs +876 -0
- package/scripts/check-indexation.mjs +108 -0
- package/scripts/check-legibility.mjs +189 -0
- package/scripts/ci/build-fixture-kb.mjs +67 -0
- package/scripts/ci/learning-replay-codex-adapter.mjs +62 -0
- package/scripts/ci/learning-replay-recorder.mjs +59 -0
- package/scripts/ci/mutate-hook-timeout.mjs +70 -0
- package/scripts/ci/stranger-fixture-stage.mjs +17 -0
- package/scripts/ci/stranger-scenario.mjs +228 -0
- package/scripts/ci/stranger-timeout.mjs +25 -0
- package/scripts/ci-verdict.mjs +29 -0
- package/scripts/claims-verify.mjs +710 -0
- package/scripts/clear-claude-tmp.sh +31 -0
- package/scripts/console-engine.mjs +434 -0
- package/scripts/console-engine.test.mjs +125 -0
- package/scripts/corpus-qa.mjs +250 -0
- package/scripts/correction-detect-embed.mjs +346 -0
- package/scripts/correction-detect-measure.mjs +270 -0
- package/scripts/correction-detect.mjs +686 -0
- package/scripts/count-chunks.mjs +54 -0
- package/scripts/described-questions.json +30 -0
- package/scripts/design-grade.mjs +58 -0
- package/scripts/dev-plugin-link.sh +105 -0
- package/scripts/distill-project.mjs +200 -0
- package/scripts/doc-currency.mjs +801 -0
- package/scripts/eval-brain.mjs +244 -0
- package/scripts/fix-metaharness-memretrieve.mjs +121 -0
- package/scripts/full-hints.mjs +87 -0
- package/scripts/gate.sh +39 -0
- package/scripts/gates.mjs +146 -0
- package/scripts/gen-console-images.mjs +54 -0
- package/scripts/gen-images.mjs +47 -0
- package/scripts/git-clone-refresh.mjs +52 -0
- package/scripts/git-hooks/pre-push +126 -0
- package/scripts/goal-match.mjs +398 -0
- package/scripts/goldie-research.mjs +223 -0
- package/scripts/goldie-weekly.sh +67 -0
- package/scripts/health-repair.mjs +250 -0
- package/scripts/helix-scenario-questions.json +10 -0
- package/scripts/ingest-gists.mjs +230 -0
- package/scripts/ingest-meeting.mjs +115 -0
- package/scripts/ingest-repo.mjs +79 -0
- package/scripts/install-npx-witness.sh +49 -0
- package/scripts/issue-fix.mjs +639 -0
- package/scripts/issue-watch.mjs +276 -0
- package/scripts/issue4-close-note.md +31 -0
- package/scripts/key-canary.mjs +91 -0
- package/scripts/latency-to-surface.mjs +233 -0
- package/scripts/learning-enable.mjs +380 -0
- package/scripts/learning-replay.mjs +1570 -0
- package/scripts/learnings.mjs +62 -0
- package/scripts/lesson-gate.mjs +680 -0
- package/scripts/lesson-lifecycle.mjs +449 -0
- package/scripts/lesson-promote.mjs +262 -0
- package/scripts/lesson-ratify.mjs +98 -0
- package/scripts/lesson-seed.mjs +252 -0
- package/scripts/lesson-store.mjs +447 -0
- package/scripts/loop-checkpoint.mjs +86 -0
- package/scripts/memdb-health.sh +14 -0
- package/scripts/memory-doctor.mjs +271 -0
- package/scripts/model-catalog.mjs +79 -0
- package/scripts/nightly-controller.mjs +66 -0
- package/scripts/nightly-gists.sh +72 -0
- package/scripts/nightly-wrapper.sh +180 -0
- package/scripts/notify.sh +12 -0
- package/scripts/npx-witness.sh +56 -0
- package/scripts/onboarding-console.mjs +2749 -0
- package/scripts/private-fence.mjs +69 -0
- package/scripts/proactivity-metrics.mjs +118 -0
- package/scripts/proof-questions.json +56 -0
- package/scripts/prove.mjs +95 -0
- package/scripts/proxy/claude-proxied.sh +57 -0
- package/scripts/proxy/proxy-revert.sh +59 -0
- package/scripts/proxy/proxy-up.sh +60 -0
- package/scripts/proxy/proxy-verify.mjs +142 -0
- package/scripts/published-surface-probe.mjs +241 -0
- package/scripts/qe/card-lane-gate.mjs +162 -0
- package/scripts/qe/session-start-gate.mjs +229 -0
- package/scripts/qe/ux-suite.mjs +323 -0
- package/scripts/reconcile-project.mjs +0 -0
- package/scripts/record-lesson.mjs +113 -0
- package/scripts/refresh-model-catalog.mjs +99 -0
- package/scripts/release-proof.mjs +9 -0
- package/scripts/release-vector.mjs +281 -0
- package/scripts/release.mjs +395 -0
- package/scripts/remedy-registry.mjs +247 -0
- package/scripts/rerank-cap-eval.mjs +265 -0
- package/scripts/rerank-cap-warm-ab.mjs +129 -0
- package/scripts/route-cheap.mjs +20 -15
- package/scripts/router-utilization.mjs +182 -0
- package/scripts/routing-flywheel.mjs +596 -0
- package/scripts/rvf-generation.mjs +104 -0
- package/scripts/rvf-index-audit.mjs +138 -0
- package/scripts/self-update.mjs +508 -0
- package/scripts/selfcheck.mjs +7 -1
- package/scripts/sign-bundle.mjs +69 -0
- package/scripts/signal-watch.mjs +171 -0
- package/scripts/stack-sync.mjs +469 -0
- package/scripts/stamp-existing-rvf-generations.mjs +53 -0
- package/scripts/stamp-sweep.mjs +144 -0
- package/scripts/status-honesty.mjs +102 -0
- package/scripts/sync-version.mjs +217 -0
- package/scripts/token-report.mjs +102 -0
- package/scripts/top100-benchmark.mjs +479 -0
- package/scripts/top100-corpus.mjs +112 -0
- package/scripts/top100-semantic-assertions.mjs +449 -0
- package/scripts/update-apply.mjs +9 -0
- package/scripts/upgrade-notice.mjs +14 -0
- package/scripts/verify-bundle.mjs +51 -0
- package/scripts/verify-channels.mjs +184 -0
- package/scripts/verify-model-catalog.mjs +104 -0
- package/scripts/verify-nightly-close-issue4.sh +31 -0
- package/scripts/version.mjs +40 -0
- package/scripts/wired-check.mjs +864 -0
- package/plugin/scripts/finalize-token-meter.mjs +0 -25
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ingest-meeting.mjs — turn a Read.ai meeting transcript into brain passages (the ruv-meetings store).
|
|
3
|
+
//
|
|
4
|
+
// WHY (2026-07-17, Stuart): rUv's community calls are where he explains HOW HE THINKS — the
|
|
5
|
+
// doctrine behind the repos (meta-proxy load balancing, flywheel economics, oracle memory,
|
|
6
|
+
// harness-vs-model philosophy). The repos hold the WHAT; the calls hold the WHY. This makes them
|
|
7
|
+
// citable: search_ruvnet returns "ruv-meetings/<date>-<slug>" passages alongside source code.
|
|
8
|
+
//
|
|
9
|
+
// PRIVACY — this store is PRIVATE BY CONSTRUCTION and that is load-bearing:
|
|
10
|
+
// • kb/ruv-meetings.* is gitignored (never committed to the public repo)
|
|
11
|
+
// • "ruv-meetings" is listed in kb/PRIVATE-STORES.json, so scripts/build-bundle.mjs excludes it
|
|
12
|
+
// from every publishable bundle (same fail-closed fence as the cognitum stores)
|
|
13
|
+
// Participants of a community call did not consent to public redistribution. Local brain only.
|
|
14
|
+
//
|
|
15
|
+
// Output contract mirrors ingest-gists.mjs: kb/ruv-meetings.passages.jsonl (+ .meta.json), then:
|
|
16
|
+
// node kb/forge-big.mjs both --dir kb --name ruv-meetings
|
|
17
|
+
//
|
|
18
|
+
// Usage:
|
|
19
|
+
// node scripts/ingest-meeting.mjs --file "docs/Ruv_advice/Ruv hackerspace Transcript.txt" \
|
|
20
|
+
// --title "Ruv hackerspace" --date 2026-07-16 [--append]
|
|
21
|
+
// --append keeps existing passages (multi-meeting store grows over time); default rebuilds.
|
|
22
|
+
|
|
23
|
+
import fs from 'node:fs';
|
|
24
|
+
import path from 'node:path';
|
|
25
|
+
import { fileURLToPath } from 'node:url';
|
|
26
|
+
|
|
27
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
28
|
+
const KB = path.join(path.dirname(__dirname), 'kb');
|
|
29
|
+
const OUT_PASSAGES = path.join(KB, 'ruv-meetings.passages.jsonl');
|
|
30
|
+
const OUT_META = path.join(KB, 'ruv-meetings.meta.json');
|
|
31
|
+
|
|
32
|
+
const args = process.argv.slice(2);
|
|
33
|
+
const get = (k) => { const i = args.indexOf('--' + k); return i >= 0 ? args[i + 1] : null; };
|
|
34
|
+
const file = get('file');
|
|
35
|
+
const title = get('title') || 'community call';
|
|
36
|
+
const date = get('date') || 'unknown-date';
|
|
37
|
+
const APPEND = args.includes('--append');
|
|
38
|
+
if (!file || !fs.existsSync(file)) { console.error('need --file <transcript.txt>'); process.exit(2); }
|
|
39
|
+
|
|
40
|
+
const raw = fs.readFileSync(file, 'utf8');
|
|
41
|
+
|
|
42
|
+
// Read.ai format: blocks of "H:MM(:SS) - Speaker Name\n<text>\n". Parse into turns, then pack turns
|
|
43
|
+
// into passages of ~2,200 chars, never splitting inside a turn — a speaker's thought stays whole
|
|
44
|
+
// (the same clean-thought law the explainer's line breaks follow).
|
|
45
|
+
const turnRe = /^(\d{1,2}:\d{2}(?::\d{2})?) - (.+)$/;
|
|
46
|
+
const lines = raw.split('\n');
|
|
47
|
+
const turns = [];
|
|
48
|
+
let cur = null;
|
|
49
|
+
for (const line of lines) {
|
|
50
|
+
const m = line.match(turnRe);
|
|
51
|
+
if (m) {
|
|
52
|
+
if (cur && cur.text.trim()) turns.push(cur);
|
|
53
|
+
cur = { ts: m[1], speaker: m[2].trim(), text: '' };
|
|
54
|
+
} else if (cur) {
|
|
55
|
+
cur.text += (cur.text ? '\n' : '') + line;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (cur && cur.text.trim()) turns.push(cur);
|
|
59
|
+
|
|
60
|
+
const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
61
|
+
const HEADER = `SOURCE: rUv community call — "${title}" (${date}), Read.ai transcript.\n`
|
|
62
|
+
+ `STATUS: spoken, informal — rUv's live thinking and practice. Treat as INTENT and doctrine;\n`
|
|
63
|
+
+ `verify shipped behavior against repo source before asserting a capability exists.\n`;
|
|
64
|
+
|
|
65
|
+
const TARGET = 2200;
|
|
66
|
+
const passages = [];
|
|
67
|
+
let buf = [];
|
|
68
|
+
let bufLen = 0;
|
|
69
|
+
let firstTs = null;
|
|
70
|
+
const flush = () => {
|
|
71
|
+
if (!buf.length) return;
|
|
72
|
+
const seg = String(passages.length).padStart(4, '0');
|
|
73
|
+
passages.push({
|
|
74
|
+
id: String(passages.length),
|
|
75
|
+
// UNIQUE path per segment (verified fix, 2026-07-19). A shared path made forge-ask.mjs doc-collapse
|
|
76
|
+
// crush every segment of a meeting into ONE ~12k window — the 317-passages→4-paths collapse that
|
|
77
|
+
// made meeting recall unretrievable (facts were IN the corpus but never surfaced; meeting recall
|
|
78
|
+
// 3/28). One path = one segment, the same granular convention ingest-gists.mjs uses (gist-id/file#N).
|
|
79
|
+
// With this + the reader's transcript-store BM25 candidates, meeting recall went 3/28 → 25/28. See
|
|
80
|
+
// docs/adr/0025.
|
|
81
|
+
path: `ruv-meetings/${date}/${slug}-seg-${seg}`,
|
|
82
|
+
title: `${title} — ${firstTs}`,
|
|
83
|
+
text: `${HEADER}segment starting ${firstTs} —\n\n` + buf.join('\n\n'),
|
|
84
|
+
meeting: slug, date, ts: firstTs,
|
|
85
|
+
});
|
|
86
|
+
buf = []; bufLen = 0; firstTs = null;
|
|
87
|
+
};
|
|
88
|
+
for (const t of turns) {
|
|
89
|
+
const block = `[${t.ts}] ${t.speaker}:\n${t.text.trim()}`;
|
|
90
|
+
if (bufLen + block.length > TARGET && buf.length) flush();
|
|
91
|
+
if (!buf.length) firstTs = t.ts;
|
|
92
|
+
buf.push(block); bufLen += block.length;
|
|
93
|
+
}
|
|
94
|
+
flush();
|
|
95
|
+
|
|
96
|
+
let existing = [];
|
|
97
|
+
if (APPEND && fs.existsSync(OUT_PASSAGES)) {
|
|
98
|
+
existing = fs.readFileSync(OUT_PASSAGES, 'utf8').split('\n').filter(Boolean).map((l) => JSON.parse(l));
|
|
99
|
+
// Re-ingesting the same meeting replaces its old passages instead of duplicating them.
|
|
100
|
+
existing = existing.filter((p) => p.meeting !== slug);
|
|
101
|
+
}
|
|
102
|
+
const all = [...existing, ...passages].map((p, i) => ({ ...p, id: String(i) }));
|
|
103
|
+
fs.writeFileSync(OUT_PASSAGES, all.map((p) => JSON.stringify(p)).join('\n') + '\n');
|
|
104
|
+
fs.writeFileSync(OUT_META, JSON.stringify({
|
|
105
|
+
builder: 'ingest-meeting',
|
|
106
|
+
builtUtc: new Date().toISOString(),
|
|
107
|
+
private: true,
|
|
108
|
+
fence: 'kb/PRIVATE-STORES.json + .gitignore — never bundle, never commit',
|
|
109
|
+
meetings: [...new Set(all.map((p) => `${p.date} ${p.meeting}`))],
|
|
110
|
+
passages: all.length,
|
|
111
|
+
}, null, 2) + '\n');
|
|
112
|
+
|
|
113
|
+
console.log(`ingest-meeting: ${turns.length} turns → ${passages.length} passages for "${title}" (${date})`);
|
|
114
|
+
console.log(`total store: ${all.length} passages → ${path.relative(process.cwd(), OUT_PASSAGES)}`);
|
|
115
|
+
console.log(`next: node kb/forge-big.mjs both --dir kb --name ruv-meetings (embed → ruv-meetings.big.rvf)`);
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ingest-repo.mjs — pull ANY github.com/ruvnet/<name> repo into the brain ON DEMAND.
|
|
3
|
+
//
|
|
4
|
+
// clone (shallow) -> transactional incremental bge-768 refresh -> symbol index
|
|
5
|
+
//
|
|
6
|
+
// After it finishes the new repo is searchable immediately: search_ruvnet / forge-ask-all discover
|
|
7
|
+
// every <name>.rvf in the kb dir at query time, so no server restart is needed. Use this when a
|
|
8
|
+
// project needs a RuvNet repo the brain doesn't cover yet — load it first, don't guess about it.
|
|
9
|
+
//
|
|
10
|
+
// node scripts/ingest-repo.mjs --name rvm
|
|
11
|
+
//
|
|
12
|
+
// For full capability-confidence on the new repo (so it's never wrongly doubted), also build its
|
|
13
|
+
// prose primer afterwards:
|
|
14
|
+
// node scripts/build-primer.mjs --name <name> --variant big
|
|
15
|
+
// node scripts/build-concepts.mjs && node kb/forge-big.mjs both --dir kb --name concepts
|
|
16
|
+
//
|
|
17
|
+
// Portable: paths resolve relative to this file; model cache via KB_MODEL_CACHE (or auto-download).
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
import fs from 'node:fs';
|
|
20
|
+
import { execFileSync } from 'node:child_process';
|
|
21
|
+
import { fileURLToPath } from 'node:url';
|
|
22
|
+
import { FULL_HINTS, KEEP_DIRS } from './full-hints.mjs';
|
|
23
|
+
|
|
24
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
25
|
+
const arg = (f, d) => { const i = process.argv.indexOf(f); return i >= 0 && process.argv[i + 1] ? process.argv[i + 1] : d; };
|
|
26
|
+
const NAME = arg('--name');
|
|
27
|
+
// --org lets us ingest ecosystem repos that live in a rUv COLLABORATOR org (e.g. the QE fleet at
|
|
28
|
+
// proffesor-for-testing/agentic-qe), not just github.com/ruvnet/*. Defaults to ruvnet.
|
|
29
|
+
const ORG = arg('--org', 'ruvnet');
|
|
30
|
+
const SOURCE = arg('--source');
|
|
31
|
+
if (!NAME) {
|
|
32
|
+
console.error('Usage: node scripts/ingest-repo.mjs --name <repo> [--org <github-org>] [--source <local-checkout>]');
|
|
33
|
+
process.exit(2);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const KB = path.join(ROOT, 'kb');
|
|
37
|
+
const CLONES = path.join(ROOT, 'clones');
|
|
38
|
+
const kb = NAME.toLowerCase();
|
|
39
|
+
const dir = SOURCE ? path.resolve(SOURCE) : path.join(CLONES, NAME);
|
|
40
|
+
const env = { ...process.env };
|
|
41
|
+
const run = (cmd, args, opts) => execFileSync(cmd, args, { stdio: 'inherit', ...opts });
|
|
42
|
+
|
|
43
|
+
fs.mkdirSync(CLONES, { recursive: true });
|
|
44
|
+
if (SOURCE) {
|
|
45
|
+
if (!fs.existsSync(path.join(dir, '.git'))) {
|
|
46
|
+
console.error(`[source] ${dir} is not a git checkout`);
|
|
47
|
+
process.exit(2);
|
|
48
|
+
}
|
|
49
|
+
console.log(`[source] local candidate ${dir}`);
|
|
50
|
+
} else if (!fs.existsSync(path.join(dir, '.git'))) {
|
|
51
|
+
console.log(`[clone] ${ORG}/${NAME}`);
|
|
52
|
+
run('git', ['clone', '--depth', '1', `https://github.com/${ORG}/${NAME}`, dir]);
|
|
53
|
+
} else {
|
|
54
|
+
console.log(`[update] ${ORG}/${NAME}`);
|
|
55
|
+
run('git', ['-C', dir, 'fetch', '--depth', '1', 'origin']);
|
|
56
|
+
run('git', ['-C', dir, 'reset', '--hard', 'origin/HEAD']);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const url = process.env.RUVNET_CANONICAL_URL || 'https://raw.githubusercontent.com/stuinfla/ruvnet-brain/main/kb';
|
|
60
|
+
// Depth config (--full / --keep) comes from the SHARED per-repo map, overridable per-invocation.
|
|
61
|
+
// Before this, ingest-repo.mjs never passed --full: any repo rebuilt through it silently lost its
|
|
62
|
+
// full-body source indexing (the 2026-07-10 depth-restore run zeroed ruvector this way).
|
|
63
|
+
const FULL = arg('--full', FULL_HINTS[kb] || '');
|
|
64
|
+
const KEEP = arg('--keep', KEEP_DIRS[kb] || '');
|
|
65
|
+
const buildArgs = ['forge-refresh.mjs', '--repo', dir, '--out', '.', '--name', kb, '--canonical-url', url];
|
|
66
|
+
if (FULL) buildArgs.push('--full', FULL);
|
|
67
|
+
if (KEEP) buildArgs.push('--keep', KEEP);
|
|
68
|
+
console.log(`[refresh bge-768] ${kb}${FULL ? ' (--full: ' + FULL.split(',').length + ' prefixes)' : ''}${KEEP ? ' (--keep: ' + KEEP + ')' : ''}`);
|
|
69
|
+
run('node', buildArgs, { cwd: KB, env });
|
|
70
|
+
console.log(`[symbols] ${kb}`);
|
|
71
|
+
try { run('node', ['scripts/build-symbols.mjs', '--name', kb], { cwd: ROOT, env }); } catch { console.log(' (symbols skipped — sparse repo)'); }
|
|
72
|
+
|
|
73
|
+
const ok = fs.existsSync(path.join(KB, `${kb}.big.rvf`))
|
|
74
|
+
&& fs.existsSync(path.join(KB, `${kb}.passages.jsonl`))
|
|
75
|
+
&& fs.existsSync(path.join(KB, `${kb}.meta.json`));
|
|
76
|
+
console.log(ok
|
|
77
|
+
? `\n[done] ${NAME} ingested → searchable now via search_ruvnet (no restart). For capability-confidence, build its primer next.`
|
|
78
|
+
: `\n[FAIL] ${NAME}: expected stores missing after build.`);
|
|
79
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# install-npx-witness.sh — install the npx witness as a launchd WatchPaths job. Idempotent.
|
|
3
|
+
#
|
|
4
|
+
# The job fires the instant ~/.npm/_npx changes (any creation/deletion, by anything), runs
|
|
5
|
+
# scripts/npx-witness.sh, and is wrapped in job-heartbeat.sh so it PROVES it ran (standing order:
|
|
6
|
+
# launchd reports exit 0 for a job that never ran — silence is not health).
|
|
7
|
+
#
|
|
8
|
+
# Zero sudo. Zero interference: the job only appends to ~/.claude/logs/npx-witness.log.
|
|
9
|
+
# Uninstall: launchctl bootout gui/$(id -u)/com.ruvnet.npx-witness && rm the plist.
|
|
10
|
+
|
|
11
|
+
set -euo pipefail
|
|
12
|
+
|
|
13
|
+
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
|
14
|
+
LABEL="com.ruvnet.npx-witness"
|
|
15
|
+
PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
|
|
16
|
+
HB="$REPO/scripts/job-heartbeat.sh"
|
|
17
|
+
WITNESS="$REPO/scripts/npx-witness.sh"
|
|
18
|
+
|
|
19
|
+
[ -f "$HB" ] || { echo "FAIL: $HB missing"; exit 1; }
|
|
20
|
+
[ -f "$WITNESS" ] || { echo "FAIL: $WITNESS missing"; exit 1; }
|
|
21
|
+
chmod +x "$WITNESS"
|
|
22
|
+
|
|
23
|
+
cat > "$PLIST" <<EOF
|
|
24
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
25
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
26
|
+
<plist version="1.0"><dict>
|
|
27
|
+
<key>Label</key><string>$LABEL</string>
|
|
28
|
+
<key>ProgramArguments</key><array>
|
|
29
|
+
<string>/bin/sh</string>
|
|
30
|
+
<string>$HB</string>
|
|
31
|
+
<string>$LABEL</string>
|
|
32
|
+
<string>--</string>
|
|
33
|
+
<string>/bin/bash</string>
|
|
34
|
+
<string>$WITNESS</string>
|
|
35
|
+
</array>
|
|
36
|
+
<key>WatchPaths</key><array><string>$HOME/.npm/_npx</string></array>
|
|
37
|
+
<key>RunAtLoad</key><false/>
|
|
38
|
+
<key>StandardOutPath</key><string>$HOME/Library/Logs/npx-witness.out</string>
|
|
39
|
+
<key>StandardErrorPath</key><string>$HOME/Library/Logs/npx-witness.err</string>
|
|
40
|
+
</dict></plist>
|
|
41
|
+
EOF
|
|
42
|
+
|
|
43
|
+
launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || true
|
|
44
|
+
launchctl bootstrap "gui/$(id -u)" "$PLIST"
|
|
45
|
+
|
|
46
|
+
echo "installed: $PLIST"
|
|
47
|
+
echo "loaded: $(launchctl list | grep -c "$LABEL") (1 = live)"
|
|
48
|
+
echo "log: ~/.claude/logs/npx-witness.log"
|
|
49
|
+
echo "heartbeat: ~/.cache/ruvnet-brain/heartbeats/$LABEL.json"
|