leopold-driver 0.1.0 → 0.1.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/README.md +19 -5
- package/assets/VERSION +1 -0
- package/assets/extensions/README.md +52 -0
- package/assets/extensions/gstack/extension.json +8 -0
- package/assets/extensions/gstack/manage.sh +68 -0
- package/assets/extensions/leopold/extension.json +8 -0
- package/assets/extensions/leopold/manage.sh +59 -0
- package/assets/extensions/ovmem/README.md +101 -0
- package/assets/extensions/ovmem/extension.json +8 -0
- package/assets/extensions/ovmem/install.sh +330 -0
- package/assets/extensions/ovmem/manage.sh +87 -0
- package/assets/extensions/ovmem/models.json +24 -0
- package/assets/extensions/ovmem/payload/RUNTIME.md +121 -0
- package/assets/extensions/ovmem/payload/ovmem-cleanup.py +148 -0
- package/assets/extensions/ovmem/payload/ovmem.py +421 -0
- package/assets/extensions/serena/README.md +50 -0
- package/assets/extensions/serena/extension.json +8 -0
- package/assets/extensions/serena/manage.sh +119 -0
- package/assets/hooks/guard-irreversible.sh +185 -0
- package/assets/hooks/hooks.json +20 -0
- package/assets/hooks/stop-continuity.sh +132 -0
- package/assets/install.sh +150 -0
- package/assets/scripts/__pycache__/leopold-watch.cpython-312.pyc +0 -0
- package/assets/scripts/leopold-doctor.sh +53 -0
- package/assets/scripts/leopold-menu.sh +132 -0
- package/assets/scripts/leopold-update-check.sh +23 -0
- package/assets/scripts/leopold-update.sh +13 -0
- package/assets/scripts/leopold-watch.py +585 -0
- package/assets/scripts/record-demo.sh +61 -0
- package/assets/scripts/test-guard.sh +76 -0
- package/assets/scripts/test-hooks.sh +121 -0
- package/assets/settings.template.json +23 -0
- package/assets/skills/leopold-brief/SKILL.md +121 -0
- package/assets/skills/leopold-doctor/SKILL.md +23 -0
- package/assets/skills/leopold-run/SKILL.md +171 -0
- package/assets/skills/leopold-status/SKILL.md +34 -0
- package/assets/skills/leopold-stop/SKILL.md +36 -0
- package/assets/skills/leopold-update/SKILL.md +27 -0
- package/assets/skills/leopold-watch/SKILL.md +48 -0
- package/assets/templates/CHARTER.md +32 -0
- package/assets/templates/DECISIONS.md +15 -0
- package/assets/templates/GUARDRAILS.md +38 -0
- package/assets/templates/MISSION.md +22 -0
- package/assets/templates/PLAN.md +9 -0
- package/dist/guard.js +82 -23
- package/dist/harness.js +71 -0
- package/dist/index.js +53 -23
- package/package.json +18 -6
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# leopold doctor — verify the Leopold install: skills, hooks + wiring, gstack,
|
|
3
|
+
# the driver toolchain, and whether an update is available.
|
|
4
|
+
set -u
|
|
5
|
+
CLAUDE="${CLAUDE_HOME:-$HOME/.claude}"
|
|
6
|
+
SRC="${LEOPOLD_SRC:-$HOME/.local/share/leopold}"
|
|
7
|
+
ok=0; warn=0; bad=0
|
|
8
|
+
pass(){ echo " [ok] $1"; ok=$((ok+1)); }
|
|
9
|
+
miss(){ echo " [FAIL] $1"; bad=$((bad+1)); }
|
|
10
|
+
note(){ echo " [warn] $1"; warn=$((warn+1)); }
|
|
11
|
+
|
|
12
|
+
echo "leopold doctor"
|
|
13
|
+
echo
|
|
14
|
+
|
|
15
|
+
command -v jq >/dev/null 2>&1 && pass "jq present" || miss "jq missing (the hooks need it)"
|
|
16
|
+
|
|
17
|
+
n=$(ls -d "$CLAUDE"/skills/leopold-* 2>/dev/null | wc -l | tr -d ' ')
|
|
18
|
+
[ "${n:-0}" -ge 4 ] && pass "skills installed ($n)" || miss "skills not installed ($n found) — run ./install.sh"
|
|
19
|
+
|
|
20
|
+
if [ -x "$CLAUDE/leopold/hooks/stop-continuity.sh" ] && [ -x "$CLAUDE/leopold/hooks/guard-irreversible.sh" ]; then
|
|
21
|
+
pass "hooks installed + executable"
|
|
22
|
+
else
|
|
23
|
+
miss "hooks not installed — run ./install.sh"
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
if [ -f "$CLAUDE/settings.json" ] && grep -q 'leopold/hooks' "$CLAUDE/settings.json" 2>/dev/null; then
|
|
27
|
+
pass "hooks wired in settings.json"
|
|
28
|
+
elif ls -d "$CLAUDE"/plugins/cache/*/leopold* >/dev/null 2>&1; then
|
|
29
|
+
pass "hooks wired via plugin"
|
|
30
|
+
else
|
|
31
|
+
note "hooks not wired (no leopold hook in settings, no plugin) — run ./install.sh or install the plugin"
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
if [ -d "$CLAUDE/skills/gstack" ] || [ -d "$CLAUDE/skills/spec" ]; then
|
|
35
|
+
pass "gstack detected — planning toolchain available"
|
|
36
|
+
else
|
|
37
|
+
note "gstack not installed (optional) — 'make gstack-install' to enable planning"
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
if command -v node >/dev/null 2>&1; then pass "node present ($(node -v 2>/dev/null)) — SDK driver usable"; else note "node missing — the SDK driver (optional) needs Node 18+"; fi
|
|
41
|
+
|
|
42
|
+
if [ -f "$SRC/VERSION" ]; then
|
|
43
|
+
pass "engine source at $SRC (v$(tr -d '[:space:]' < "$SRC/VERSION"))"
|
|
44
|
+
up="$(bash "$SRC/scripts/leopold-update-check.sh" 2>/dev/null || true)"
|
|
45
|
+
[ -n "$up" ] && note "$up — run: make update"
|
|
46
|
+
else
|
|
47
|
+
note "no source clone at $SRC (plugin install? update via 'claude plugin update')"
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
echo
|
|
51
|
+
echo "summary: $ok ok, $warn warnings, $bad problems"
|
|
52
|
+
[ "${bad:-0}" -eq 0 ] && echo "Leopold looks healthy." || echo "Fix the [FAIL] items above."
|
|
53
|
+
exit 0
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Leopold - toolchain manager.
|
|
3
|
+
# A data-driven menu over the extension registry in ../extensions/. Each extension
|
|
4
|
+
# is a self-contained folder with an extension.json (metadata) and a manage.sh that
|
|
5
|
+
# implements: detect | status | install | update | remove | doctor.
|
|
6
|
+
#
|
|
7
|
+
# Works both from a clone (./scripts/leopold-menu.sh) and from an install
|
|
8
|
+
# (~/.claude/leopold/scripts/leopold-menu.sh) - the extensions dir is resolved
|
|
9
|
+
# relative to this script.
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
|
+
EXT_DIR=""
|
|
14
|
+
for cand in "$HERE/../extensions" "${CLAUDE_HOME:-$HOME/.claude}/leopold/extensions"; do
|
|
15
|
+
if [ -d "$cand" ]; then EXT_DIR="$(cd "$cand" && pwd)"; break; fi
|
|
16
|
+
done
|
|
17
|
+
if [ -z "$EXT_DIR" ]; then
|
|
18
|
+
echo "No extensions registry found (looked for ../extensions and ~/.claude/leopold/extensions)." >&2
|
|
19
|
+
exit 1
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# ---- tiny helpers -----------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
if [ -t 1 ]; then
|
|
25
|
+
C_RESET=$'\033[0m'; C_DIM=$'\033[2m'; C_GREEN=$'\033[32m'; C_YELLOW=$'\033[33m'; C_CYAN=$'\033[36m'; C_BOLD=$'\033[1m'
|
|
26
|
+
else
|
|
27
|
+
C_RESET=""; C_DIM=""; C_GREEN=""; C_YELLOW=""; C_CYAN=""; C_BOLD=""
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
_jget() { # file key -> value (jq preferred, python3 fallback)
|
|
31
|
+
if command -v jq >/dev/null 2>&1; then
|
|
32
|
+
jq -r --arg k "$2" '.[$k] // empty' "$1" 2>/dev/null
|
|
33
|
+
elif command -v python3 >/dev/null 2>&1; then
|
|
34
|
+
python3 -c "import json,sys;print(json.load(open(sys.argv[1])).get(sys.argv[2],''))" "$1" "$2" 2>/dev/null
|
|
35
|
+
fi
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
list_exts() { # prints extension dirs, sorted by .order
|
|
39
|
+
for d in "$EXT_DIR"/*/; do
|
|
40
|
+
[ -f "${d}extension.json" ] || continue
|
|
41
|
+
local order; order="$(_jget "${d}extension.json" order)"; [ -n "$order" ] || order=99
|
|
42
|
+
printf "%03d\t%s\n" "$order" "${d%/}"
|
|
43
|
+
done | sort -n | cut -f2
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
ext_installed() { bash "$1/manage.sh" detect >/dev/null 2>&1; }
|
|
47
|
+
ext_status() { bash "$1/manage.sh" status 2>/dev/null || true; }
|
|
48
|
+
ext_run() { bash "$1/manage.sh" "$2"; }
|
|
49
|
+
|
|
50
|
+
pause() { printf "\n%spress Enter to continue%s " "$C_DIM" "$C_RESET"; read -r _ || true; }
|
|
51
|
+
|
|
52
|
+
# ---- screens ----------------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
header() {
|
|
55
|
+
clear 2>/dev/null || true
|
|
56
|
+
printf "%s========================================%s\n" "$C_CYAN" "$C_RESET"
|
|
57
|
+
printf "%s Leopold%s - toolchain manager\n" "$C_BOLD" "$C_RESET"
|
|
58
|
+
printf "%s========================================%s\n\n" "$C_CYAN" "$C_RESET"
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
main_menu() {
|
|
62
|
+
header
|
|
63
|
+
MENU_PATHS=()
|
|
64
|
+
local i=1 d title summary st
|
|
65
|
+
while IFS= read -r d; do
|
|
66
|
+
[ -n "$d" ] || continue
|
|
67
|
+
MENU_PATHS+=("$d")
|
|
68
|
+
title="$(_jget "$d/extension.json" title)"; [ -n "$title" ] || title="$(basename "$d")"
|
|
69
|
+
summary="$(_jget "$d/extension.json" summary)"
|
|
70
|
+
if ext_installed "$d"; then
|
|
71
|
+
st="${C_GREEN}installed${C_RESET}"
|
|
72
|
+
local s; s="$(ext_status "$d")"; [ -n "$s" ] && st="$st ${C_DIM}($s)${C_RESET}"
|
|
73
|
+
else
|
|
74
|
+
st="${C_DIM}not installed${C_RESET}"
|
|
75
|
+
fi
|
|
76
|
+
printf " %s%2d%s) %s%-12s%s %s\n %s%s%s\n\n" \
|
|
77
|
+
"$C_BOLD" "$i" "$C_RESET" "$C_BOLD" "$title" "$C_RESET" "$st" "$C_DIM" "$summary" "$C_RESET"
|
|
78
|
+
i=$((i + 1))
|
|
79
|
+
done < <(list_exts)
|
|
80
|
+
printf " %sd%s) Doctor all %sq%s) Quit\n\n" "$C_BOLD" "$C_RESET" "$C_BOLD" "$C_RESET"
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
component_menu() {
|
|
84
|
+
local d="$1" title
|
|
85
|
+
title="$(_jget "$d/extension.json" title)"; [ -n "$title" ] || title="$(basename "$d")"
|
|
86
|
+
while true; do
|
|
87
|
+
header
|
|
88
|
+
local st="not installed"
|
|
89
|
+
ext_installed "$d" && st="installed${C_RESET} ${C_DIM}($(ext_status "$d"))"
|
|
90
|
+
printf " %s%s%s\n status: %s%s\n\n" "$C_BOLD" "$title" "$C_RESET" "$C_GREEN" "$st"
|
|
91
|
+
printf " %s%s%s\n\n" "$C_DIM" "$(_jget "$d/extension.json" summary)" "$C_RESET"
|
|
92
|
+
printf " 1) Install 2) Update 3) Remove 4) Doctor b) Back\n\n"
|
|
93
|
+
printf "select: "; read -r a || a="b"
|
|
94
|
+
case "$a" in
|
|
95
|
+
1) ext_run "$d" install || echo "${C_YELLOW}install returned non-zero${C_RESET}"; pause ;;
|
|
96
|
+
2) ext_run "$d" update || echo "${C_YELLOW}update returned non-zero${C_RESET}"; pause ;;
|
|
97
|
+
3) ext_run "$d" remove || echo "${C_YELLOW}remove returned non-zero${C_RESET}"; pause ;;
|
|
98
|
+
4) ext_run "$d" doctor || true; pause ;;
|
|
99
|
+
b|B|"") return ;;
|
|
100
|
+
*) ;;
|
|
101
|
+
esac
|
|
102
|
+
done
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
doctor_all() {
|
|
106
|
+
header
|
|
107
|
+
local d
|
|
108
|
+
for d in "${MENU_PATHS[@]}"; do
|
|
109
|
+
printf "%s== %s ==%s\n" "$C_CYAN" "$(basename "$d")" "$C_RESET"
|
|
110
|
+
ext_run "$d" doctor || true
|
|
111
|
+
echo
|
|
112
|
+
done
|
|
113
|
+
pause
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
# ---- main loop --------------------------------------------------------------
|
|
117
|
+
|
|
118
|
+
while true; do
|
|
119
|
+
main_menu
|
|
120
|
+
printf "select a component [number, d, q]: "; read -r choice || choice="q"
|
|
121
|
+
case "$choice" in
|
|
122
|
+
q|Q) echo; exit 0 ;;
|
|
123
|
+
d|D) doctor_all ;;
|
|
124
|
+
''|*[!0-9]*) ;; # ignore non-numeric
|
|
125
|
+
*)
|
|
126
|
+
idx=$((choice - 1))
|
|
127
|
+
if [ "$idx" -ge 0 ] && [ "$idx" -lt "${#MENU_PATHS[@]}" ]; then
|
|
128
|
+
component_menu "${MENU_PATHS[$idx]}"
|
|
129
|
+
fi
|
|
130
|
+
;;
|
|
131
|
+
esac
|
|
132
|
+
done
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Leopold update check. Throttled (once/24h), network-failure-safe, silent unless
|
|
3
|
+
# an update is available. Prints "UPDATE_AVAILABLE <local> <remote>" when the
|
|
4
|
+
# VERSION on main is newer than the installed source clone. No-op for non-clone
|
|
5
|
+
# installs (e.g. the Claude Code plugin, which updates via `claude plugin update`).
|
|
6
|
+
set -u
|
|
7
|
+
SRC="${LEOPOLD_SRC:-$HOME/.local/share/leopold}"
|
|
8
|
+
[ -f "$SRC/VERSION" ] || exit 0
|
|
9
|
+
MARK="$HOME/.leopold/.last-update-check"
|
|
10
|
+
mkdir -p "$HOME/.leopold" 2>/dev/null || true
|
|
11
|
+
now=$(date +%s 2>/dev/null || echo 0)
|
|
12
|
+
if [ -f "$MARK" ]; then
|
|
13
|
+
last=$(cat "$MARK" 2>/dev/null || echo 0)
|
|
14
|
+
[ $((now - last)) -lt 86400 ] 2>/dev/null && exit 0
|
|
15
|
+
fi
|
|
16
|
+
echo "$now" > "$MARK" 2>/dev/null || true
|
|
17
|
+
local_v=$(tr -d '[:space:]' < "$SRC/VERSION" 2>/dev/null)
|
|
18
|
+
remote_v=$(curl -fsSL --max-time 5 https://raw.githubusercontent.com/Jonhvmp/leopold/main/VERSION 2>/dev/null | tr -d '[:space:]')
|
|
19
|
+
[ -z "$remote_v" ] && exit 0
|
|
20
|
+
[ "$remote_v" = "$local_v" ] && exit 0
|
|
21
|
+
newest=$(printf '%s\n%s\n' "$local_v" "$remote_v" | sort -V 2>/dev/null | tail -1)
|
|
22
|
+
[ "$newest" = "$remote_v" ] && echo "UPDATE_AVAILABLE $local_v $remote_v"
|
|
23
|
+
exit 0
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Update the Leopold engine: pull the latest source and re-run the installer.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
SRC="${LEOPOLD_SRC:-$HOME/.local/share/leopold}"
|
|
5
|
+
if [ ! -d "$SRC/.git" ]; then
|
|
6
|
+
echo "No Leopold source clone at $SRC. Reinstall:"
|
|
7
|
+
echo " curl -fsSL https://raw.githubusercontent.com/Jonhvmp/leopold/main/install.sh | bash"
|
|
8
|
+
exit 1
|
|
9
|
+
fi
|
|
10
|
+
echo "-> updating Leopold ($SRC)"
|
|
11
|
+
git -C "$SRC" pull --ff-only
|
|
12
|
+
"$SRC/install.sh"
|
|
13
|
+
echo "Leopold updated to $(tr -d '[:space:]' < "$SRC/VERSION")."
|