- tui-model.lisp: defpackage, *state*, st/init-state, add-msg, event queue - tui-view.lisp: view-status, view-chat, view-input, redraw (pure renders) - tui-main.lisp: on-key, on-daemon-msg, daemon I/O, connect, tui-main - ASDF updated to serial 3-file dependency - Removed monolithic org/gateway-tui.org and lisp/gateway-tui.lisp - Pre-commit hook: added 3 split files to croatoan exclusion - core-skills: added 3 split files to skill loader exclusion - Verified: LLM response arrives, /eval works, colors render [no-verify: pre-commit hook SKIPped for TUI files]
103 lines
3.5 KiB
Bash
Executable File
103 lines
3.5 KiB
Bash
Executable File
#!/bin/bash
|
|
# Pre-commit hook: verify all defuns in staged .org files compile in the daemon.
|
|
# For each changed .org file, it tangles to .lisp then sends the entire file
|
|
# to the daemon for compilation. This catches undefined symbol references,
|
|
# syntax errors, and broken function bodies.
|
|
#
|
|
# Install:
|
|
# ln -sf ../../scripts/pre-commit-repl-check .git/hooks/pre-commit
|
|
#
|
|
# Requires: running daemon on port 9105, repl script, emacs with ob-tangle.
|
|
#
|
|
# Returns 0 (pass) or 1 (fail).
|
|
|
|
set -euo pipefail
|
|
IFS=$'\n\t'
|
|
|
|
REPL=$(command -v repl 2>/dev/null || echo "/home/user/.opencode/bin/repl")
|
|
PORT=9105
|
|
PROJECT_DIR=$(git rev-parse --show-toplevel 2>/dev/null || echo "/home/user/memex/projects/passepartout")
|
|
|
|
# Check daemon connectivity
|
|
if ! timeout 2 bash -c "echo >/dev/tcp/127.0.0.1/$PORT" 2>/dev/null; then
|
|
echo "ERROR: Daemon not reachable on 127.0.0.1:$PORT. Start it first." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Collect changed .org files from the index
|
|
CHANGED=$(git diff --cached --name-only --diff-filter=ACM | grep '\.org$' || true)
|
|
if [ -z "$CHANGED" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
FAILED=0
|
|
for orgfile in $CHANGED; do
|
|
[ -f "$orgfile" ] || continue
|
|
|
|
# Determine the tangle target from the org file's PROPERTY line
|
|
TANGLE=$(grep 'header-args.*:tangle' "$orgfile" | sed "s/.*:tangle //" | head -1 || true)
|
|
if [ -z "$TANGLE" ]; then
|
|
echo "SKIP: $orgfile — no :tangle header" >&2
|
|
continue
|
|
fi
|
|
|
|
# Skip files that depend on external libraries not loaded in the daemon
|
|
BASENAME=$(basename "$orgfile")
|
|
case "$BASENAME" in
|
|
gateway-tui.org|gateway-tui-model.org|gateway-tui-view.org|gateway-tui-main.org)
|
|
echo "SKIP: $orgfile — external dependency (croatoan)" >&2
|
|
continue
|
|
;;
|
|
esac
|
|
|
|
# Resolve relative tangle path
|
|
ORG_DIR=$(dirname "$orgfile")
|
|
LISP_FILE=$(cd "$ORG_DIR" && realpath -m "$TANGLE" 2>/dev/null || echo "$ORG_DIR/$TANGLE")
|
|
|
|
# Tangle the org file to lisp
|
|
if ! emacs --batch -L "$PROJECT_DIR" --eval "(require 'ob-tangle)" \
|
|
--eval "(org-babel-tangle-file \"$ORG_DIR/$(basename "$orgfile")\")" \
|
|
</dev/null 2>/dev/null; then
|
|
echo "FAIL: $orgfile — tangling failed" >&2
|
|
FAILED=1
|
|
continue
|
|
fi
|
|
|
|
if [ ! -f "$LISP_FILE" ]; then
|
|
echo "SKIP: $orgfile — tangle target $LISP_FILE not found" >&2
|
|
continue
|
|
fi
|
|
|
|
# Compile the lisp file in the daemon.
|
|
# We send a Lisp form that compiles the file and returns T or an error string.
|
|
# Using format to avoid backquote/comma issues.
|
|
LISP_ABS=$(realpath "$LISP_FILE" 2>/dev/null || echo "$LISP_FILE")
|
|
CODE=$(cat <<-LISPEOF
|
|
(let ((*standard-output* (make-broadcast-stream))
|
|
(*error-output* (make-broadcast-stream)))
|
|
(handler-case
|
|
(progn
|
|
(compile-file "$LISP_ABS")
|
|
(load (compile-file-pathname "$LISP_ABS"))
|
|
(format nil "OK"))
|
|
(error (c)
|
|
(format nil "COMPILE-ERROR: ~a" c))))
|
|
LISPEOF
|
|
)
|
|
RESULT=$(printf '%s' "$CODE" | timeout 10 "$REPL" 2>/dev/null || echo "DAEMON-UNREACHABLE")
|
|
|
|
if echo "$RESULT" | grep -q '^COMPILE-ERROR:\|^DAEMON-UNREACHABLE\|^$'; then
|
|
echo "REJECT: $(basename "$orgfile") — compilation failed: $RESULT" >&2
|
|
FAILED=1
|
|
else
|
|
echo "OK: $(basename "$orgfile")" >&2
|
|
fi
|
|
done
|
|
|
|
if [ "$FAILED" -eq 1 ]; then
|
|
echo "" >&2
|
|
echo "COMMIT REJECTED: REPL compilation check failed." >&2
|
|
echo "Fix errors, or bypass with: git commit --no-verify" >&2
|
|
exit 1
|
|
fi
|