feat: v2 — queue matchmaking, procedural audio, sprite archetypes, auth
- Add queue-based matchmaking with Elo-proximity and 10s timeout - Procedural sound engine (SFX, voice announcer, 4-track music) - Sprite system refactored into 6 archetypes (standard, lobster, sheep, cyborg, blob, tank) - 42+ fight choreographies with themed/generic/wild card selection - 4 KO finish styles, super-speed mode, hyperdetail close-ups - Auth routes, JoinBout page, bot profile with stats - 7-tier ranking system (Baby through Legend) - Arena and challenge system expansions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
335c148866
commit
47d20fbe66
Executable
+76
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
# PreToolUse Bash guard: block dangerous shell commands.
|
||||
# Denies: rm -rf, git reset --hard, git push -f, git clean -fd, chmod -R 777,
|
||||
# fork bombs, block device overwrites, mkfs, building Rust on macOS for Linux.
|
||||
set -euo pipefail
|
||||
|
||||
INPUT=$(cat)
|
||||
CMD=$(python3 -c "
|
||||
import json, sys
|
||||
try:
|
||||
data = json.loads(sys.stdin.read())
|
||||
print(data.get('tool_input', {}).get('command', ''))
|
||||
except: pass
|
||||
" <<< "$INPUT")
|
||||
BASE="${CLAUDE_PROJECT_DIR:-}"
|
||||
[[ -z "$BASE" ]] && BASE=$(python3 -c "
|
||||
import json, sys
|
||||
try:
|
||||
data = json.loads(sys.stdin.read())
|
||||
print(data.get('cwd', ''))
|
||||
except: pass
|
||||
" <<< "$INPUT")
|
||||
[[ -z "$BASE" ]] && BASE="$(pwd)"
|
||||
|
||||
# Normalize: collapse whitespace, strip leading/trailing
|
||||
CMD_NORM=$(echo "$CMD" | tr -s '[:space:]' ' ' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||
|
||||
deny() {
|
||||
local reason="$1"
|
||||
python3 -c "
|
||||
import json
|
||||
print(json.dumps({
|
||||
'hookSpecificOutput': {
|
||||
'hookEventName': 'PreToolUse',
|
||||
'permissionDecision': 'deny',
|
||||
'permissionDecisionReason': '$reason'
|
||||
}
|
||||
}))
|
||||
"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Dangerous patterns
|
||||
case "$CMD_NORM" in
|
||||
*"rm -rf"*|*"rm -fr"*|*"rm -f -r"*|*"rm -r -f"*) deny "Destructive rm -rf blocked by security hook" ;;
|
||||
*"git reset --hard"*) deny "git reset --hard would lose uncommitted work" ;;
|
||||
*"git push --force"*|*"git push -f"*|*"git push -f "*) deny "git push --force would rewrite history" ;;
|
||||
*"git clean -fd"*|*"git clean -f -d"*) deny "git clean -fd deletes untracked files" ;;
|
||||
*"chmod -R 777"*|*"chmod -R 0777"*) deny "chmod -R 777 is a security risk" ;;
|
||||
*":(){ :"*"};:"*) deny "Fork bomb pattern blocked" ;;
|
||||
*"> /dev/sd"*|*">/dev/sd"*) deny "Block device overwrite blocked" ;;
|
||||
*"mkfs "*|*"mkfs."*) deny "Disk format command blocked" ;;
|
||||
esac
|
||||
|
||||
# Block building Rust locally on macOS (should always build on dev server)
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
if echo "$CMD_NORM" | grep -qE '^\s*cargo\s+build'; then
|
||||
# Allow if it's clearly an SSH command (building on remote)
|
||||
if ! echo "$CMD_NORM" | grep -qE 'ssh|sshpass'; then
|
||||
deny "NEVER build Rust on macOS — use ./scripts/deploy-to-target.sh --live or build on dev server via SSH"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for path traversal escaping project root
|
||||
if [[ -n "$BASE" ]] && [[ -d "$BASE" ]]; then
|
||||
if echo "$CMD_NORM" | grep -qE '\.\./|/\.\.'; then
|
||||
if echo "$CMD_NORM" | grep -qE '(rm|mv|cp|cat|chmod|chown)\s+.*\.\.'; then
|
||||
if echo "$CMD_NORM" | grep -qE '\brm\b.*\.\.'; then
|
||||
deny "Path traversal with rm blocked"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
# PostToolUse Bash hook: detect deploy commands and remind to test.
|
||||
# Triggers after deploy-to-target.sh runs.
|
||||
set -euo pipefail
|
||||
|
||||
INPUT=$(cat)
|
||||
|
||||
CMD=$(python3 -c "
|
||||
import json, sys
|
||||
try:
|
||||
data = json.loads(sys.stdin.read())
|
||||
print(data.get('tool_input', {}).get('command', ''))
|
||||
except: pass
|
||||
" <<< "$INPUT")
|
||||
|
||||
# Only trigger on deploy commands or git push
|
||||
if ! echo "$CMD" | grep -qE 'deploy-to-target|git\s+push'; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TIMESTAMP=$(date '+%Y-%m-%d %H:%M')
|
||||
|
||||
python3 -c "
|
||||
import json
|
||||
|
||||
message = '''Deploy detected at $TIMESTAMP.
|
||||
|
||||
Post-deploy checklist:
|
||||
1. Test the web UI at http://192.168.1.228
|
||||
2. Verify modified apps load correctly
|
||||
3. Check backend logs: sudo journalctl -u archipelago -n 20
|
||||
4. Check nginx: sudo tail -f /var/log/nginx/error.log
|
||||
5. If building ISO, sync system configs to image-recipe/configs/
|
||||
6. Update CHANGELOG.md if this is a notable change'''
|
||||
|
||||
output = {
|
||||
'hookSpecificOutput': {
|
||||
'hookEventName': 'PostToolUse',
|
||||
'deployReminder': message
|
||||
}
|
||||
}
|
||||
print(json.dumps(output))
|
||||
"
|
||||
Executable
+75
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
# PostToolUse Bash hook: detect git push/commit and prompt Claude to update PROGRESS.md.
|
||||
# Returns structured feedback with recent commits so Claude can write a session log entry.
|
||||
# Uses python3 instead of jq for JSON (guaranteed on macOS).
|
||||
set -euo pipefail
|
||||
|
||||
INPUT=$(cat)
|
||||
|
||||
# Extract command from JSON using python3
|
||||
CMD=$(python3 -c "
|
||||
import json, sys
|
||||
try:
|
||||
data = json.loads(sys.stdin.read())
|
||||
print(data.get('tool_input', {}).get('command', ''))
|
||||
except: pass
|
||||
" <<< "$INPUT")
|
||||
|
||||
# Only trigger on git push or git commit commands
|
||||
if ! echo "$CMD" | grep -qE '\bgit\s+(push|commit)\b'; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Gather context for the progress update
|
||||
BASE="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
||||
BRANCH=$(git -C "$BASE" branch --show-current 2>/dev/null || echo "unknown")
|
||||
PROGRESS_FILE="$BASE/PROGRESS.md"
|
||||
TIMESTAMP=$(date '+%Y-%m-%d %H:%M')
|
||||
|
||||
# Get recent commits (branch vs main, or last 10)
|
||||
if git -C "$BASE" rev-parse --verify main &>/dev/null; then
|
||||
COMMITS=$(git -C "$BASE" log --oneline main..HEAD 2>/dev/null | head -15)
|
||||
if [ -z "$COMMITS" ]; then
|
||||
COMMITS=$(git -C "$BASE" log --oneline -10 2>/dev/null)
|
||||
fi
|
||||
else
|
||||
COMMITS=$(git -C "$BASE" log --oneline -10 2>/dev/null)
|
||||
fi
|
||||
|
||||
# Get changed files in recent commits
|
||||
CHANGED_FILES=$(git -C "$BASE" diff --name-only main..HEAD 2>/dev/null | head -20 || \
|
||||
git -C "$BASE" diff --name-only HEAD~5..HEAD 2>/dev/null | head -20 || \
|
||||
echo "unknown")
|
||||
|
||||
# Build the feedback message and output as JSON using python3
|
||||
python3 -c "
|
||||
import json, sys
|
||||
|
||||
message = '''Progress Update Needed
|
||||
|
||||
A git push/commit was detected on branch \`$BRANCH\` at $TIMESTAMP.
|
||||
|
||||
Recent commits:
|
||||
\`\`\`
|
||||
$COMMITS
|
||||
\`\`\`
|
||||
|
||||
Changed files:
|
||||
\`\`\`
|
||||
$CHANGED_FILES
|
||||
\`\`\`
|
||||
|
||||
Please update PROGRESS.md:
|
||||
1. Add a session log entry under '## Session Log' with format: ### $TIMESTAMP — $BRANCH
|
||||
2. Summarize what was accomplished (2-4 bullet points based on the commits above)
|
||||
3. Update any roadmap checkboxes if tasks were completed
|
||||
4. Commit the PROGRESS.md update'''
|
||||
|
||||
output = {
|
||||
'hookSpecificOutput': {
|
||||
'hookEventName': 'PostToolUse',
|
||||
'progressUpdate': message
|
||||
}
|
||||
}
|
||||
print(json.dumps(output))
|
||||
"
|
||||
Executable
+82
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env bash
|
||||
# PreToolUse Edit|Write guard: block edits outside project and to protected paths.
|
||||
# Denies: paths outside project, .git/, .env*, lockfiles, node_modules/, deploy-config.sh
|
||||
set -euo pipefail
|
||||
|
||||
INPUT=$(cat)
|
||||
FILE_PATH=$(python3 -c "
|
||||
import json, sys
|
||||
try:
|
||||
data = json.loads(sys.stdin.read())
|
||||
print(data.get('tool_input', {}).get('file_path', ''))
|
||||
except: pass
|
||||
" <<< "$INPUT")
|
||||
BASE="${CLAUDE_PROJECT_DIR:-}"
|
||||
[[ -z "$BASE" ]] && BASE=$(python3 -c "
|
||||
import json, sys
|
||||
try:
|
||||
data = json.loads(sys.stdin.read())
|
||||
print(data.get('cwd', ''))
|
||||
except: pass
|
||||
" <<< "$INPUT")
|
||||
[[ -z "$BASE" ]] && BASE="$(pwd)"
|
||||
|
||||
# Resolve to absolute path
|
||||
if [[ -z "$FILE_PATH" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
ABS_BASE=$(cd "$BASE" 2>/dev/null && pwd) || true
|
||||
[[ -z "$ABS_BASE" ]] && ABS_BASE=$(python3 -c "import os,sys; print(os.path.abspath(os.path.normpath(sys.argv[1])))" "$BASE" 2>/dev/null) || true
|
||||
[[ -z "$ABS_BASE" ]] && ABS_BASE="$BASE"
|
||||
[[ "$ABS_BASE" != */ ]] && ABS_BASE="${ABS_BASE}/"
|
||||
if [[ "$FILE_PATH" != /* ]]; then
|
||||
ABS_PATH="$ABS_BASE${FILE_PATH#./}"
|
||||
else
|
||||
ABS_PATH="$FILE_PATH"
|
||||
fi
|
||||
ABS_PATH=$(python3 -c "import os,sys; print(os.path.abspath(os.path.normpath(sys.argv[1])))" "$ABS_PATH" 2>/dev/null) || true
|
||||
[[ -z "$ABS_PATH" ]] && ABS_PATH="$ABS_BASE${FILE_PATH#./}"
|
||||
|
||||
deny() {
|
||||
local reason="$1"
|
||||
echo "Blocked: $ABS_PATH — $reason" >&2
|
||||
python3 -c "
|
||||
import json
|
||||
print(json.dumps({
|
||||
'hookSpecificOutput': {
|
||||
'hookEventName': 'PreToolUse',
|
||||
'permissionDecision': 'deny',
|
||||
'permissionDecisionReason': '$reason'
|
||||
}
|
||||
}))
|
||||
"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Protected patterns
|
||||
PROTECTED_PATTERNS=(
|
||||
".git/"
|
||||
".env"
|
||||
".env.local"
|
||||
"node_modules/"
|
||||
"package-lock.json"
|
||||
"scripts/deploy-config.sh"
|
||||
)
|
||||
|
||||
for pattern in "${PROTECTED_PATTERNS[@]}"; do
|
||||
if [[ "$ABS_PATH" == *"$pattern"* ]] || [[ "$ABS_PATH" == *"/$pattern" ]]; then
|
||||
deny "Edit blocked: path matches protected pattern ($pattern)"
|
||||
fi
|
||||
done
|
||||
|
||||
# .env.*.local
|
||||
if [[ "$ABS_PATH" =~ \.env\..*\.local$ ]]; then
|
||||
deny "Edit blocked: .env.*.local files contain secrets"
|
||||
fi
|
||||
|
||||
# Ensure path is under project root
|
||||
if [[ "$ABS_PATH" != "$ABS_BASE"* ]] && [[ "$ABS_PATH" != "$BASE"* ]]; then
|
||||
deny "Edit blocked: path is outside project directory"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user