ruvnet-brain 3.9.133-dev → 4.0.1
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 +13 -0
- package/README.md +3 -3
- package/bin/install.mjs +284 -33
- package/kb/zip-extract.mjs +53 -14
- package/package.json +7 -1
- package/plugin/.claude-plugin/marketplace.json +13 -0
- package/plugin/.claude-plugin/plugin.json +23 -0
- package/plugin/.codex-plugin/plugin.json +21 -0
- package/plugin/.mcp.json +8 -0
- package/plugin/commands/brain-console.md +16 -0
- package/plugin/commands/configure.md +32 -0
- package/plugin/commands/rvbc.md +78 -0
- package/plugin/commands/rvcb.md +16 -0
- package/plugin/commands/whats-new.md +57 -0
- package/plugin/hooks/codex-hooks.json +160 -0
- package/plugin/hooks/hook-contracts.json +77 -0
- package/plugin/hooks/hooks.json +203 -0
- package/plugin/mcp/server.mjs +35 -6
- package/plugin/scripts/anticipate.sh +534 -0
- package/plugin/scripts/codex-hook-adapter.mjs +96 -0
- package/plugin/scripts/continuation-gate.mjs +267 -0
- package/plugin/scripts/design-wall.sh +137 -0
- package/plugin/scripts/detach.mjs +168 -0
- package/plugin/scripts/finalize-token-meter.mjs +25 -0
- package/plugin/scripts/gate-receipt.sh +35 -0
- package/plugin/scripts/ground-before-write.sh +199 -0
- package/plugin/scripts/ground-ruvnet.sh +507 -0
- package/plugin/scripts/grounding-stamp.sh +113 -0
- package/plugin/scripts/grounding-substance.mjs +595 -0
- package/plugin/scripts/hijack-ruvnet.sh +81 -0
- package/plugin/scripts/hook-input.mjs +558 -0
- package/plugin/scripts/hook-shim-bash.mjs +55 -0
- package/plugin/scripts/hook-shim.mjs +303 -0
- package/plugin/scripts/host-update.mjs +58 -0
- package/plugin/scripts/kling-preflight.sh +146 -0
- package/plugin/scripts/learn-capture.sh +154 -0
- package/plugin/scripts/learn-flush.mjs +138 -0
- package/plugin/scripts/lesson-hooks.sh +213 -0
- package/plugin/scripts/md-stamp.mjs +219 -0
- package/plugin/scripts/protect-brain-state.sh +84 -0
- package/plugin/scripts/route-dispatch.sh +147 -0
- package/plugin/scripts/routing-outcome-capture.mjs +89 -0
- package/plugin/scripts/session-start.sh +868 -0
- package/plugin/scripts/signal-watch.mjs +193 -0
- package/plugin/scripts/unprompted-runtime.mjs +377 -0
- package/plugin/scripts/update-apply.mjs +419 -0
- package/plugin/scripts/verify-interface.sh +53 -0
- package/plugin/scripts/version-bump-gate.sh +112 -0
- package/plugin/skills/brain-build/SKILL.md +123 -0
- package/plugin/skills/brain-console/SKILL.md +20 -0
- package/plugin/skills/brain-prompt/SKILL.md +83 -0
- package/plugin/skills/brain-score/SKILL.md +101 -0
- package/plugin/skills/ruvnet-brain/PLAYBOOK.md +117 -0
- package/plugin/skills/ruvnet-brain/SKILL.md +234 -0
- package/plugin/skills/rvbc/SKILL.md +20 -0
- package/plugin/skills/savings/SKILL.md +46 -0
- package/plugin/skills/whats-new/SKILL.md +22 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ground-before-write.sh — PreToolUse gate on Write|Edit.
|
|
3
|
+
# YOU MAY NOT WRITE RUV-DOMAIN CODE THE BRAIN HAS NOT SEEN FIRST.
|
|
4
|
+
#
|
|
5
|
+
# ─────────────────────────────────────────────────────────────────────────────────────────────
|
|
6
|
+
# WHY (2026-07-13). Stuart, after losing a full day: "The 100% entire reason we built RuvNet
|
|
7
|
+
# Brain was to prevent exactly this scenario... come up with a way to keep Claude Code from
|
|
8
|
+
# stepping in and overriding RuvNet-Brain."
|
|
9
|
+
#
|
|
10
|
+
# What happened, twice in one week: Claude hand-wrote agentdb-autocapture.mjs (prompt-echo
|
|
11
|
+
# snapshots) while rUv's ADR-174 `memory distill` pipeline shipped the real design; Claude
|
|
12
|
+
# hand-wrote a 216-line "MetaHarness router" while @metaharness/router sat on npm. Both times
|
|
13
|
+
# the brain HELD the answer and was never asked. The write path had no wall.
|
|
14
|
+
#
|
|
15
|
+
# rUv names the disease and the cure himself (@claude-flow/guidance, ADR-G007):
|
|
16
|
+
# "prompts are advisory. Agents can and do ignore them, especially in long sessions."
|
|
17
|
+
# "The model can forget a rule; the gate does not."
|
|
18
|
+
# And his own hooks doc wires exactly this shape: PreToolUse on ^(Write|Edit|MultiEdit)$
|
|
19
|
+
# (ruflo/.claude/commands/hooks/overview.md).
|
|
20
|
+
#
|
|
21
|
+
# THE RULE: writing/editing a CODE file that touches a RuvNet ecosystem product requires a
|
|
22
|
+
# fresh (<24h) grounding stamp for that product — written only by grounding-stamp.sh when
|
|
23
|
+
# search_ruvnet is genuinely called with that product in the query.
|
|
24
|
+
#
|
|
25
|
+
# Deliberate scope choices (so this never becomes a tax that gets switched off):
|
|
26
|
+
# • CODE files only (.mjs/.js/.ts/.sh/...). Docs/README claims are enforced by the CI gates
|
|
27
|
+
# (claims-verify, no-silent-substitution), not per-keystroke.
|
|
28
|
+
# • Product terms only (agentdb, metaharness, ...). Generic words like "memory"/"hook"
|
|
29
|
+
# would fire on half of all software.
|
|
30
|
+
# • Block only the UNGROUNDED terms — grounding agentdb unlocks agentdb, not metaharness.
|
|
31
|
+
# Granularity matches the mistake, same as verify-interface.sh's per-subcommand stamps.
|
|
32
|
+
#
|
|
33
|
+
# CONTRACT: exit 0 = allow · exit 2 + stderr = BLOCK (stderr returns to the model as reason).
|
|
34
|
+
# FAILS OPEN on anything unparseable. Opt-in (router profile), like every gate here.
|
|
35
|
+
# ─────────────────────────────────────────────────────────────────────────────────────────────
|
|
36
|
+
|
|
37
|
+
set -uo pipefail
|
|
38
|
+
|
|
39
|
+
INPUT=""
|
|
40
|
+
# BOUNDED READ (2026-07-27, ADR-055 F20): an unqualified `read` never returns on a stdin that is
|
|
41
|
+
# opened and never closed — measured across the mesh, 18 of 37 registered commands sat until the
|
|
42
|
+
# harness killed them. Real Claude Code writes and closes, so this costs no normal turn; that is
|
|
43
|
+
# exactly why a hook that CAN hang forever survives unnoticed. -t bounds the wait, and the string
|
|
44
|
+
# is truncated AFTER the loop because a hook payload is one line with no newline, so `read` hands
|
|
45
|
+
# the whole thing back at once and a per-iteration cap never fires.
|
|
46
|
+
while IFS= read -r -t 2 _l; do
|
|
47
|
+
INPUT+="$_l"
|
|
48
|
+
[ ${#INPUT} -ge 65536 ] && break
|
|
49
|
+
done
|
|
50
|
+
[ -n "$_l" ] && INPUT+="$_l"
|
|
51
|
+
INPUT="${INPUT:0:65536}"
|
|
52
|
+
[ -n "$INPUT" ] || exit 0
|
|
53
|
+
|
|
54
|
+
# ── BRAIN OFF — THE FIRST CHECK IN THE FILE (ADR-054 §3). ───────────────────────────────────────
|
|
55
|
+
# This gate demands a fresh grounding stamp, and a stamp can only be minted by a successful
|
|
56
|
+
# search_ruvnet. With the brain switched off there IS no search_ruvnet, so an unmodified gate would
|
|
57
|
+
# block every rUv-domain write forever with an instruction the user has deliberately made
|
|
58
|
+
# impossible to follow. That is the "something bad happened because it can be turned off" failure
|
|
59
|
+
# the owner's build mandate rules out, and it is why this check comes before the opt-in check,
|
|
60
|
+
# before the tool check and before the file-type check: nothing this gate does downstream is
|
|
61
|
+
# meaningful while its evidence source is switched off.
|
|
62
|
+
#
|
|
63
|
+
# It degrades to ONE advisory line on stdout and exit 0 — never a block. PreToolUse stdout on exit 0
|
|
64
|
+
# is transcript-only (it does not enter the model's context), so this is legibility for the person
|
|
65
|
+
# reading their own session, not another channel of unsolicited speech.
|
|
66
|
+
#
|
|
67
|
+
# Both duel reviewers independently caught that this hook is wired in the USER's settings.json,
|
|
68
|
+
# OUTSIDE plugin/hooks/hooks.json and therefore outside the shim's dispatch table — so the shim's
|
|
69
|
+
# per-hook offBehavior cannot reach it and the check has to live here, in the body. It is a pure
|
|
70
|
+
# `[ -f ]` on a path built from bash parameter expansion only: this gate's standing contract
|
|
71
|
+
# (ADR-0021, enforced by ground-before-write.test.mjs) is that it depends on no node, no jq, no
|
|
72
|
+
# python, so it can never fail-open because a tool went missing.
|
|
73
|
+
#
|
|
74
|
+
# The `! -r` clause is the bash half of a polarity bug gate test 5 found in the node half: an
|
|
75
|
+
# unreadable state directory makes `[ -f ]` (like fs.existsSync) answer "no sentinel", which would
|
|
76
|
+
# re-arm this gate for a user who had switched the brain off — the two readers disagreeing about the
|
|
77
|
+
# same machine. "The directory is there and we cannot read it" is not evidence of ON.
|
|
78
|
+
BRAIN_STATE_DIR="${RUVNET_BRAIN_STATE_DIR:-$HOME/.config/ruvnet-brain}"
|
|
79
|
+
BRAIN_OFF_FILE="$BRAIN_STATE_DIR/brain-off"
|
|
80
|
+
if [ -f "$BRAIN_OFF_FILE" ] || { [ -d "$BRAIN_STATE_DIR" ] && [ ! -r "$BRAIN_STATE_DIR" ]; }; then
|
|
81
|
+
echo "[RuvNet Brain is off by your setting — the grounding gate is advisory only, nothing is blocked.]"
|
|
82
|
+
exit 0
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
PROFILE="${MODEL_ROUTER_PROFILE:-$HOME/.claude/model-router/profile.json}"
|
|
86
|
+
[ -f "$PROFILE" ] || exit 0
|
|
87
|
+
|
|
88
|
+
# The blanket override, NARROWED (ADR-055 §3.5, verbatim: "the blanket RUVNET_SKIP_GROUNDING_CHECK=1
|
|
89
|
+
# regime is retired for the fourth wall"). It still disarms the RECENCY wall below, exactly as
|
|
90
|
+
# documented since ADR-0012 — but it no longer disarms the SUBSTANCE stage, which has its own
|
|
91
|
+
# in-band, reasoned, receipted token. The reason is the whole point of issue #46: recency is a
|
|
92
|
+
# ceremony you can reasonably choose to skip, while "you are writing the opposite of the source you
|
|
93
|
+
# were just shown" is not a ceremony, and a variable exported once at the top of a session must not
|
|
94
|
+
# buy a day of contradicting writes. Note the substance stage never blocks on ABSENCE of evidence,
|
|
95
|
+
# so with the recency wall skipped and nothing stamped, it permits — as it should.
|
|
96
|
+
SKIP_RECENCY=0
|
|
97
|
+
[ "${RUVNET_SKIP_GROUNDING_CHECK:-0}" = "1" ] && SKIP_RECENCY=1
|
|
98
|
+
|
|
99
|
+
# This gate is a BLOCKING wall (the #1-failure preventer), so by deliberate design (ADR-0021, and
|
|
100
|
+
# enforced by ground-before-write.test.mjs) it depends on NOTHING fragile — pure bash builtins, no
|
|
101
|
+
# node/jq/python — and therefore cannot fail-open because a tool went missing. The #13 quote-truncation
|
|
102
|
+
# that justified hook-input.mjs for design-wall does NOT bite here: the product-term scan below runs
|
|
103
|
+
# over the RAW payload (untouched by field()), and the only parsed values are tool_name (Write/Edit —
|
|
104
|
+
# no quotes) and file_path (a truncated path merely fails the extension check → exit 0, harmless).
|
|
105
|
+
field() { local re="\"$1\"[[:space:]]*:[[:space:]]*\"([^\"]*)\""; [[ $INPUT =~ $re ]] && printf '%s' "${BASH_REMATCH[1]}"; }
|
|
106
|
+
|
|
107
|
+
case "$(field tool_name)" in Write|Edit|MultiEdit) ;; *) exit 0 ;; esac
|
|
108
|
+
|
|
109
|
+
FILE_PATH=$(field file_path)
|
|
110
|
+
[ -n "$FILE_PATH" ] || exit 0
|
|
111
|
+
case "$FILE_PATH" in
|
|
112
|
+
*.mjs|*.cjs|*.js|*.ts|*.tsx|*.jsx|*.sh|*.bash|*.zsh|*.rs|*.py|*.go) ;;
|
|
113
|
+
*) exit 0 ;;
|
|
114
|
+
esac
|
|
115
|
+
# The grounding-guidance hooks ENUMERATE every rUv product by design — that IS their job: telling the
|
|
116
|
+
# model which rUv primitive replaces which classical default. They don't hand-roll or call any rUv
|
|
117
|
+
# tool, so demanding a fresh stamp per listed term just to EDIT the guidance is a false positive — the
|
|
118
|
+
# gate firing on its own source material (it blocked a trim of ground-ruvnet.sh on 2026-07-18). Exempt
|
|
119
|
+
# these two by basename; the repo-wide CI gates (claims-verify, no-silent-substitution) still cover them.
|
|
120
|
+
case "$FILE_PATH" in
|
|
121
|
+
*/ground-ruvnet.sh|*/session-start.sh) exit 0 ;;
|
|
122
|
+
esac
|
|
123
|
+
|
|
124
|
+
shopt -s nocasematch 2>/dev/null || true
|
|
125
|
+
|
|
126
|
+
STAMP_DIR="$HOME/.cache/ruvnet-brain/grounded"
|
|
127
|
+
NOW=$(date +%s 2>/dev/null) || exit 0
|
|
128
|
+
|
|
129
|
+
# Scan the WHOLE tool input (path + content + new_string) — where the code mentions the
|
|
130
|
+
# product is where the hand-roll hides.
|
|
131
|
+
MISSING=""
|
|
132
|
+
SEEN=""
|
|
133
|
+
for t in agentdb metaharness ruvector aidefence agentic-flow agentic-qe ruv-swarm rvf ruflo; do
|
|
134
|
+
[[ $INPUT == *"$t"* ]] || continue
|
|
135
|
+
SEEN="$SEEN$t "
|
|
136
|
+
STAMP="$STAMP_DIR/$t"
|
|
137
|
+
if [ -f "$STAMP" ]; then
|
|
138
|
+
# GNU date reads a file's mtime with -r; BSD/macOS needs stat -f %m. Either failing → allow
|
|
139
|
+
# (fail open — a gate that bricks a session is worse than the bug it prevents).
|
|
140
|
+
THEN=$(date -r "$STAMP" +%s 2>/dev/null) || THEN=$(stat -f %m "$STAMP" 2>/dev/null) || exit 0
|
|
141
|
+
[ $((NOW - THEN)) -lt 86400 ] && continue
|
|
142
|
+
fi
|
|
143
|
+
MISSING="$MISSING$t "
|
|
144
|
+
done
|
|
145
|
+
|
|
146
|
+
# ═══════════════════════════════════════════════════════════════════════════════════════════════
|
|
147
|
+
# STAGE 2 — THE SUBSTANCE WALL (ADR-055 §3, issue #46). Runs only once the recency wall above has
|
|
148
|
+
# PASSED: a term the model has never grounded is stopped by stage 1 and never reaches here.
|
|
149
|
+
#
|
|
150
|
+
# ── THE DEPENDENCY CONTRACT, AND WHY THIS DOES NOT BREAK IT ────────────────────────────────────
|
|
151
|
+
# Everything above this line is pure bash builtins, by standing contract (ADR-0021, enforced by
|
|
152
|
+
# ground-before-write.test.mjs): the recency wall is THE blocking wall, so it can never fail open
|
|
153
|
+
# because a tool went missing. That contract is unchanged and still tested — the assertion now
|
|
154
|
+
# reads the file UP TO THIS MARKER.
|
|
155
|
+
#
|
|
156
|
+
# The substance stage is different in kind and is allowed one dependency, node, because deciding
|
|
157
|
+
# "does this write contradict the source the brain returned?" requires a real JSON parse of the
|
|
158
|
+
# payload (this repo has paid twice for pretending otherwise — issue #13's quote truncation) plus a
|
|
159
|
+
# read of the evidence ledger. It is therefore built to FAIL OPEN, loudly and by construction: no
|
|
160
|
+
# node, no checker file, no ledger, any non-2 exit → the write proceeds. The only thing that can
|
|
161
|
+
# produce a refusal here is a detector that found a contradiction, which is ADR-055 §1.2's
|
|
162
|
+
# "malfunction ≠ decision" applied to the one stage that has something to malfunction.
|
|
163
|
+
# ═══════════════════════════════════════════════════════════════════════════════════════════════
|
|
164
|
+
if [ -z "$MISSING" ] || [ "$SKIP_RECENCY" = "1" ]; then
|
|
165
|
+
[ -n "$SEEN" ] || exit 0
|
|
166
|
+
SUBSTANCE="$(dirname "${BASH_SOURCE[0]}")/grounding-substance.mjs"
|
|
167
|
+
[ -f "$SUBSTANCE" ] || exit 0
|
|
168
|
+
command -v node >/dev/null 2>&1 || exit 0
|
|
169
|
+
SUB_OUT=$(printf '%s' "$INPUT" | node "$SUBSTANCE" 2>&1)
|
|
170
|
+
SUB_RC=$?
|
|
171
|
+
if [ "$SUB_RC" = "2" ]; then
|
|
172
|
+
printf '%s\n' "$SUB_OUT" >&2
|
|
173
|
+
exit 2
|
|
174
|
+
fi
|
|
175
|
+
# Anything else — clean pass, a crash, a timeout, an unknown code — permits the write. An override
|
|
176
|
+
# acceptance line (exit 0 with stderr) is surfaced so the record is visible in the transcript.
|
|
177
|
+
[ -n "$SUB_OUT" ] && printf '%s\n' "$SUB_OUT" >&2
|
|
178
|
+
exit 0
|
|
179
|
+
fi
|
|
180
|
+
|
|
181
|
+
read -r -d '' MSG <<EOF || true
|
|
182
|
+
⛔ BLOCKED — you are writing rUv-domain code the brain has not seen: ${MISSING% }
|
|
183
|
+
|
|
184
|
+
This exact move has already cost a full day TWICE: a hand-rolled agentdb capture hook while
|
|
185
|
+
rUv's ADR-174 distill pipeline shipped the real design, and a fake "MetaHarness router" while
|
|
186
|
+
@metaharness/router sat on npm. Both times the brain held the answer and was never asked.
|
|
187
|
+
|
|
188
|
+
Before writing this file, ground each blocked term in the RuvNet Brain — call the
|
|
189
|
+
search_ruvnet MCP tool with the product in the query, e.g.:
|
|
190
|
+
|
|
191
|
+
search_ruvnet({ query: "${MISSING%% *}: how does rUv implement / recommend this?" })
|
|
192
|
+
|
|
193
|
+
Reading real source stamps the term for 24h and this gate opens. rUv's own rule (ADR-G007):
|
|
194
|
+
prompts are advisory; the gate is not. EFFECTIVE BEATS EFFICIENT.
|
|
195
|
+
(Deliberate override, say why out loud: RUVNET_SKIP_GROUNDING_CHECK=1)
|
|
196
|
+
EOF
|
|
197
|
+
bash "$(dirname "${BASH_SOURCE[0]}")/gate-receipt.sh" ground-before-write "${MISSING%% *}" "rUv-product code without a fresh search_ruvnet stamp" 2>/dev/null || true
|
|
198
|
+
printf '%s\n' "$MSG" >&2
|
|
199
|
+
exit 2
|