leopold-driver 0.1.1 → 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.
Files changed (48) hide show
  1. package/README.md +19 -5
  2. package/assets/VERSION +1 -0
  3. package/assets/extensions/README.md +52 -0
  4. package/assets/extensions/gstack/extension.json +8 -0
  5. package/assets/extensions/gstack/manage.sh +68 -0
  6. package/assets/extensions/leopold/extension.json +8 -0
  7. package/assets/extensions/leopold/manage.sh +59 -0
  8. package/assets/extensions/ovmem/README.md +101 -0
  9. package/assets/extensions/ovmem/extension.json +8 -0
  10. package/assets/extensions/ovmem/install.sh +330 -0
  11. package/assets/extensions/ovmem/manage.sh +87 -0
  12. package/assets/extensions/ovmem/models.json +24 -0
  13. package/assets/extensions/ovmem/payload/RUNTIME.md +121 -0
  14. package/assets/extensions/ovmem/payload/ovmem-cleanup.py +148 -0
  15. package/assets/extensions/ovmem/payload/ovmem.py +421 -0
  16. package/assets/extensions/serena/README.md +50 -0
  17. package/assets/extensions/serena/extension.json +8 -0
  18. package/assets/extensions/serena/manage.sh +119 -0
  19. package/assets/hooks/guard-irreversible.sh +185 -0
  20. package/assets/hooks/hooks.json +20 -0
  21. package/assets/hooks/stop-continuity.sh +132 -0
  22. package/assets/install.sh +150 -0
  23. package/assets/scripts/__pycache__/leopold-watch.cpython-312.pyc +0 -0
  24. package/assets/scripts/leopold-doctor.sh +53 -0
  25. package/assets/scripts/leopold-menu.sh +132 -0
  26. package/assets/scripts/leopold-update-check.sh +23 -0
  27. package/assets/scripts/leopold-update.sh +13 -0
  28. package/assets/scripts/leopold-watch.py +585 -0
  29. package/assets/scripts/record-demo.sh +61 -0
  30. package/assets/scripts/test-guard.sh +76 -0
  31. package/assets/scripts/test-hooks.sh +121 -0
  32. package/assets/settings.template.json +23 -0
  33. package/assets/skills/leopold-brief/SKILL.md +121 -0
  34. package/assets/skills/leopold-doctor/SKILL.md +23 -0
  35. package/assets/skills/leopold-run/SKILL.md +171 -0
  36. package/assets/skills/leopold-status/SKILL.md +34 -0
  37. package/assets/skills/leopold-stop/SKILL.md +36 -0
  38. package/assets/skills/leopold-update/SKILL.md +27 -0
  39. package/assets/skills/leopold-watch/SKILL.md +48 -0
  40. package/assets/templates/CHARTER.md +32 -0
  41. package/assets/templates/DECISIONS.md +15 -0
  42. package/assets/templates/GUARDRAILS.md +38 -0
  43. package/assets/templates/MISSION.md +22 -0
  44. package/assets/templates/PLAN.md +9 -0
  45. package/dist/guard.js +82 -23
  46. package/dist/harness.js +71 -0
  47. package/dist/index.js +53 -23
  48. package/package.json +6 -3
@@ -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")."