Repository navigation
Expand file tree
/
Copy pathbrain
More file actions
executable file
·158 lines (155 loc) · 7.19 KB
/
Copy pathbrain
File metadata and controls
executable file
·158 lines (155 loc) · 7.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/usr/bin/env bash
# brain — the single entry point of GreyMatter.
# Usage : brain <status|doctor|audit|push|metrics|selftest|backup>
set -euo pipefail
# ─── WHERE THIS CLI'S OWN CODE LIVES ─────────────────────────────────────────
# A CLI must run ITS OWN scripts. This one used to `cd` into the trunk and call
# `hooks/brain_status.py` — a path that resolves through the trunk's symlinks to
# whatever engine is CURRENTLY active. Harmless while there was exactly one
# engine; wrong the moment versions live side by side, because
# `versions/v1.29.0/brain` would then execute v1.28.1's hooks and report on a
# mixture of the two. A selftest aimed at a candidate version would go green
# having tested the active one.
#
# `$0` may be a symlink (`~/.local/bin/brain` → `~/.greymatter/engine/brain`, itself
# a symlink into `versions/`), so it is followed to the end before taking the
# directory. The trunk stays the working directory: it is the DATA.
src="$0"
while [ -L "$src" ]; do
dir="$(cd -P "$(dirname "$src")" && pwd)"
src="$(readlink "$src")"
case "$src" in /*) ;; *) src="$dir/$src" ;; esac
done
SELF="$(cd -P "$(dirname "$src")" && pwd)"
export SELF # one inline python block reads it from the environment
BRAIN="$HOME/.greymatter/trunk"
cd "$BRAIN"
cmd="${1:-status}"
case "$cmd" in
status)
python3 "$SELF"/hooks/brain_status.py show 2>/dev/null || cat state/status.json 2>/dev/null || echo "(no status)"
;;
doctor)
python3 "$SELF"/hooks/brain_doctor.py "${@:2}"
;;
audit)
# OPERATIONAL state of the pipeline: what is distilled / queued / uncaptured + health
python3 "$SELF"/hooks/brain_audit.py "${@:2}"
;;
review)
# GLOBAL audit of the trunk (content/topology): aggregates topology + utility +
# challenger + doctor + stale notes + infrastructure paths → state/review.{json,md}
python3 "$SELF"/hooks/brain_review.py "${@:2}"
;;
recall|search)
python3 "$SELF"/hooks/brain_recall.py "${@:2}"
;;
embed)
# (re)build the semantic embeddings index (optional backend)
if [ -x .venv/bin/python ]; then .venv/bin/python "$SELF"/hooks/brain_embed.py build; else echo "embeddings venv missing (BM25 by default)"; fi
;;
next|reprises)
python3 "$SELF"/hooks/brain_anticipate.py
;;
utility|usage)
python3 "$SELF"/hooks/brain_utility.py "${@:2}"
;;
coherence)
# heavily overlapping note pairs awaiting the gardener's arbitration
if [ -f state/coherence.json ]; then python3 -m json.tool state/coherence.json; else echo "✅ no pending pair"; fi
;;
metrics)
# latest trends (last 10 readings)
if [ -f state/metrics.jsonl ]; then tail -10 state/metrics.jsonl; else echo "(no metrics yet)"; fi
;;
credit|quota)
# "can the agents spend RIGHT NOW?" — a one-token probe (~$0.00003) that asks
# the API instead of guessing. `--unblock` clears a block marker that has become
# false (cap topped up, account switched).
if [ "${2:-}" = "--unblock" ]; then
python3 -c "
import json, os, sys, time
sys.path.insert(0, os.environ['SELF'] + '/hooks')
import quota_probe as qp
v = qp.probe()
if not v['ok']:
print('⚠️ the probe says NO —', v['reason']); print(' marker left in place.'); raise SystemExit(7)
json.dump({'blocked_until': 0, 'family': None, 'failures': 0, 'msg': 'ok — unblocked by hand',
'fingerprint': v['fingerprint'], 'last_probe': v['ts'], 'limits': v['limits']},
open('state/quota.json', 'w'))
print('✅ block lifted — the agents can start again (verified by probe, HTTP', str(v['http']) + ')')
"
else
python3 "$SELF"/hooks/quota_probe.py
python3 -c "
import json, time
try: q = json.load(open('state/quota.json'))
except Exception: raise SystemExit
b = q.get('blocked_until', 0)
if b and time.time() < b:
print()
print('⛔ maintenance FROZEN locally until', time.strftime('%d/%m %H:%M', time.localtime(b)))
print(' reason:', str(q.get('msg', ''))[:100])
print(' the probe will retry on its own (≤ 15 min) — or: brain credit --unblock')
"
fi
;;
push|backup)
# ⚠️ THE NAME OVERPROMISES, and the wording below is what corrects it: this
# records a local HISTORY, on this disk. It is not an off-machine backup, and
# calling it one would let someone lose a laptop believing otherwise.
#
# It used to run `git add -A` straight away. On a trunk nobody had `git init`ed
# — the state a default install was left in — that printed
# "fatal: not a git repository" and exited 128: the command whose name promises
# safekeeping answered with a git error and no instruction.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "⚠️ This trunk has no local history: it is not a git repository."
echo " Your notes are safe as files — nothing is lost — but nothing records"
echo " what changed, and the per-session auto-save has nothing to write to."
echo " Turn it on: git -C \"$BRAIN\" init && brain backup"
exit 1
fi
git add -A
# `git commit -q` still prints "On branch main / nothing to commit" on its own
# stdout when there is nothing staged, so the quiet flag is not enough.
git commit -q -m "manual save via brain $(date +%F\ %H:%M)" >/dev/null 2>&1 \
|| echo "(nothing new to record)"
echo "✅ recorded in the local history ($(git rev-list --count HEAD) entries, on this disk)"
# A remote is opt-in and rare: the package never adds one. Staying silent when
# there is none avoids reporting a failed push to someone who never wanted one.
if git remote get-url origin >/dev/null 2>&1; then
git push --quiet origin HEAD && echo "✅ pushed to origin" \
|| echo "⚠️ push to origin failed — the local history is recorded all the same"
fi
;;
selftest)
bash "$SELF"/hooks/selftest.sh "$SELF"
;;
update)
# Updates the ENGINE only. The trunk — your notes — is never touched.
bash "$SELF"/greymatter/update.sh "${@:2}"
;;
demo)
# Three example notes, placed and taken away on demand. An empty trunk on
# first launch shows nothing of what the tool can do.
bash "$SELF"/greymatter/demo.sh "${@:2}"
;;
capsule)
# The one gesture to get the menu bar pill back after a reboot, a stop or a
# crash. Decided 2026-09-20, C bis entry B3: a CLI verb rather than a second
# Desktop bundle, because the capsule's reader is already in a terminal.
bash "$SELF"/greymatter/capsule.sh "${@:2}"
;;
version)
cat "$HOME/.greymatter/VERSION" 2>/dev/null || echo "(unknown version)"
;;
*)
echo "Usage: brain <status|doctor|audit|review|recall|next|coherence|utility|credit|embed|push|metrics|selftest|backup|update|demo|capsule|version>"
echo " (credit: can the agents spend? — --unblock lifts a block that has become false)"
echo ' (capsule: opens the menu bar pill — stop closes it, status says if it is drawing)'
echo " (recall accepts --semantic for embeddings, --lines for passages instead of descriptions)"
echo " (update: session start looks, your agent asks before installing — --auto-on installs without asking)"
exit 1
;;
esac