11#! /bin/bash
22# pre-commit hook — Validate & sync all stack repos before commit
3+ #
4+ # Validates:
5+ # 1. All VERSION files in sync
6+ # 2. lpb.stack.env LPB_PI_REF matches VERSION
7+ # 3. settings.json pins match VERSION
8+ # 4. All repos clean (except VERSION/env)
9+ # 5. Auto-add VERSION + env changes to staging
10+ #
11+ # Exit non-zero to abort commit.
312
13+ # Find devstack dir by searching upward from the git working tree
414DEVSTACK_DIR=" "
5- check_dir=" $PWD "
15+ check_dir=" $( git rev-parse --show-toplevel 2> /dev/null) "
16+ [ -z " $check_dir " ] && check_dir=" $PWD "
617while [ " $check_dir " != " /" ]; do
718 [ -f " $check_dir /VERSION" ] && [ -f " $check_dir /lpb.stack.env" ] && DEVSTACK_DIR=" $check_dir " && break
819 check_dir=$( dirname " $check_dir " )
@@ -23,37 +34,70 @@ declare -a REPOS=(
2334SETTINGS_JSON=" /home/lpb/.pi/agent/settings.json"
2435
2536info () { echo " ✅ $* " ; }
37+ warn () { echo " ⚠️ $* " ; }
2638error () { echo " ❌ $* " ; ERRORS=$(( ERRORS + 1 )) ; }
2739
40+ # 1. Validate VERSION files
2841echo " === Stack Version Sync ==="
2942for repo in " ${REPOS[@]} " ; do
3043 repo_name=$( basename " $repo " )
31- [ ! -f " $repo /VERSION" ] && error " $repo_name : missing VERSION" && continue
44+ if [ ! -f " $repo /VERSION" ]; then
45+ error " $repo_name : missing VERSION file"
46+ continue
47+ fi
3248 repo_version=$( cat " $repo /VERSION" )
33- [ " $repo_version " != " $CURRENT_VERSION " ] && error " $repo_name : $repo_version != $CURRENT_VERSION " || info " $repo_name : $repo_version "
49+ if [ " $repo_version " != " $CURRENT_VERSION " ]; then
50+ error " $repo_name : VERSION=$repo_version (expected $CURRENT_VERSION )"
51+ else
52+ info " $repo_name : $repo_version "
53+ fi
3454done
3555
56+ # 2. Validate lpb.stack.env
3657echo " "
3758echo " === Environment Sync ==="
3859if [ -f " $DEVSTACK_DIR /lpb.stack.env" ]; then
3960 PI_REF=$( grep ' ^LPB_PI_REF=' " $DEVSTACK_DIR /lpb.stack.env" | cut -d= -f2)
40- [ " $PI_REF " != " $CURRENT_VERSION " ] && { error " LPB_PI_REF=$PI_REF != $CURRENT_VERSION " ; sed -i " s/^LPB_PI_REF=.*/LPB_PI_REF=$CURRENT_VERSION /" " $DEVSTACK_DIR /lpb.stack.env" ; } || info " LPB_PI_REF=$PI_REF "
61+ if [ " $PI_REF " != " $CURRENT_VERSION " ]; then
62+ error " lpb.stack.env: LPB_PI_REF=$PI_REF (expected $CURRENT_VERSION )"
63+ sed -i " s/^LPB_PI_REF=.*/LPB_PI_REF=$CURRENT_VERSION /" " $DEVSTACK_DIR /lpb.stack.env"
64+ echo " 🔧 Fixed LPB_PI_REF to $CURRENT_VERSION "
65+ else
66+ info " LPB_PI_REF=$PI_REF "
67+ fi
4168fi
4269
70+ # 3. Validate settings.json pins
4371echo " "
4472echo " === Extension Pins ==="
4573if [ -f " $SETTINGS_JSON " ]; then
4674 for repo in lemonade-pi-plugin lpb-memory pi-subagents; do
47- python3 -c "
48- import json
49- d = json.load(open('$SETTINGS_JSON '))
50- for p in d.get('packages',[]):
51- if isinstance(p,dict) and '$repo ' in p.get('extension',''):
52- assert p.get('version','') == '$CURRENT_VERSION ', f'MISMATCH: {p.get(\" version\" )}'
53- " 2> /dev/null && info " $repo : pinned" || warn " $repo : verification skipped"
75+ if python3 -c "
76+ import json, sys
77+ with open('$SETTINGS_JSON ') as f:
78+ d = json.load(f)
79+ pins = d.get('packages', [])
80+ for p in pins:
81+ if isinstance(p, dict) and '$repo ' in p.get('extension', ''):
82+ ver = p.get('version', '')
83+ if ver and ver != '$CURRENT_VERSION ':
84+ print(f'MISMATCH: {ver}')
85+ sys.exit(1)
86+ elif not ver:
87+ print('NO-PIN')
88+ sys.exit(1)
89+ sys.exit(0)
90+ " 2> /dev/null; then
91+ info " $repo : pinned correctly"
92+ else
93+ warn " $repo : pin verification skipped (format may differ)"
94+ fi
5495 done
96+ else
97+ warn " settings.json not found at $SETTINGS_JSON "
5598fi
5699
100+ # 4. Check repo cleanliness
57101echo " "
58102echo " === Unstaged Changes ==="
59103check_unstaged () {
71115
72116check_unstaged " $DEVSTACK_DIR " " devstack"
73117
74- # Auto-stage VERSION + env
118+ # 5. Auto-add VERSION + env changes
75119if [ $ERRORS -eq 0 ] && [ " $CURRENT_VERSION " != " NOT FOUND" ]; then
76120 echo " "
77121 echo " === Auto-stage VERSION ==="
@@ -82,9 +126,11 @@ if [ $ERRORS -eq 0 ] && [ "$CURRENT_VERSION" != "NOT FOUND" ]; then
82126 info " VERSION files + lpb.stack.env staged"
83127fi
84128
129+ # Result
85130echo " "
86131if [ $ERRORS -gt 0 ]; then
87- echo " ❌ Pre-commit FAILED ($ERRORS error(s))"
132+ echo " ❌ Pre-commit FAILED ($ERRORS error(s)) — commit aborted"
133+ echo " Fix issues above and try again, or use --no-verify to skip"
88134 exit 1
89135else
90136 echo " ✅ All checks passed"
0 commit comments