Skip to content

Commit 3bd70aa

Browse files
lapc506claude
andcommitted
merge: resolve conflicts — combine main's error handling with PR's subagent delegation
- session-stop.sh: keep check_jq guard + add pending-lessons archive - track-code-change.sh: keep rate limiting + error handling, add pending-lessons queue + delegation output to sensei subagent - track-command.sh: same pattern — pending-lessons + delegation output Both sides rewrote the same logic differently: main improved error handling (check_jq, log_error, json_escape), PR restructured output for subagent pipeline (DOJ-2436). This merge keeps both improvements. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2 parents 84be95d + 47295c1 commit 3bd70aa

9 files changed

Lines changed: 2244 additions & 399 deletions

data/concept-tree.json

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,8 +358,36 @@
358358
"triggers": ["cache", "redis", "CDN", "load balancer"]
359359
}
360360
}
361+
},
362+
"debugging": {
363+
"name": "Debugging",
364+
"icon": "🐛",
365+
"belt_requirement": "white",
366+
"concepts": {
367+
"error-reading": {
368+
"name": "Error Reading",
369+
"xp_to_master": 15,
370+
"prerequisites": [],
371+
"description": "Understanding error messages and stack traces",
372+
"triggers": ["error", "Error:", "Traceback", "ENOENT", "stack trace"]
373+
},
374+
"debugging-mindset": {
375+
"name": "Debugging Mindset",
376+
"xp_to_master": 20,
377+
"prerequisites": ["error-reading"],
378+
"description": "Systematic approach to finding and fixing bugs",
379+
"triggers": ["debug", "breakpoint", "console.log", "print("]
380+
},
381+
"common-errors": {
382+
"name": "Common Errors",
383+
"xp_to_master": 25,
384+
"prerequisites": ["error-reading", "debugging-mindset"],
385+
"description": "Recognizing and fixing common programming errors",
386+
"triggers": ["TypeError", "ReferenceError", "SyntaxError", "undefined", "null"]
387+
}
388+
}
361389
}
362390
},
363-
"total_concepts": 42,
391+
"total_concepts": 45,
364392
"mastery_quiz_threshold": 3
365393
}

data/quiz-bank.json

Lines changed: 1349 additions & 67 deletions
Large diffs are not rendered by default.

scripts/lib/date-compat.sh

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env bash
2+
# Cross-platform date utilities for CodeSensei
3+
# Supports: GNU date (Linux), BSD date (macOS), python3 fallback
4+
5+
# Get today's date in YYYY-MM-DD format (UTC)
6+
date_today() {
7+
date -u '+%Y-%m-%d' 2>/dev/null || python3 -c "from datetime import datetime; print(datetime.utcnow().strftime('%Y-%m-%d'))"
8+
}
9+
10+
# Get yesterday's date in YYYY-MM-DD format (UTC)
11+
date_yesterday() {
12+
# Try GNU date first
13+
date -u -d 'yesterday' '+%Y-%m-%d' 2>/dev/null && return
14+
# Try BSD date (macOS)
15+
date -u -v-1d '+%Y-%m-%d' 2>/dev/null && return
16+
# Python fallback
17+
python3 -c "from datetime import datetime, timedelta; print((datetime.utcnow() - timedelta(days=1)).strftime('%Y-%m-%d'))" 2>/dev/null && return
18+
# Last resort: empty string
19+
echo ""
20+
}
21+
22+
# Convert date string (YYYY-MM-DD) to epoch seconds
23+
date_to_epoch() {
24+
local date_str="$1"
25+
# Try GNU date
26+
date -u -d "$date_str" '+%s' 2>/dev/null && return
27+
# Try BSD date (macOS)
28+
date -u -j -f '%Y-%m-%d %H:%M:%S' "${date_str} 00:00:00" '+%s' 2>/dev/null && return
29+
# Python fallback
30+
python3 -c "from datetime import datetime, timezone; print(int(datetime.strptime('$date_str', '%Y-%m-%d').replace(tzinfo=timezone.utc).timestamp()))" 2>/dev/null && return
31+
echo "0"
32+
}
33+
34+
# Get date N days ago in YYYY-MM-DD format (UTC)
35+
date_days_ago() {
36+
local days="$1"
37+
# Try GNU date
38+
date -u -d "${days} days ago" '+%Y-%m-%d' 2>/dev/null && return
39+
# Try BSD date (macOS)
40+
date -u -v-${days}d '+%Y-%m-%d' 2>/dev/null && return
41+
# Python fallback
42+
python3 -c "from datetime import datetime, timedelta; print((datetime.utcnow() - timedelta(days=${days})).strftime('%Y-%m-%d'))" 2>/dev/null && return
43+
echo ""
44+
}
45+
46+
# Get current UTC timestamp in ISO format
47+
date_now_iso() {
48+
date -u '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || python3 -c "from datetime import datetime; print(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'))"
49+
}

scripts/lib/error-handling.sh

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/bin/bash
2+
# CodeSensei — Shared Error Handling Library
3+
# Source this file in hook scripts for consistent error logging and JSON safety.
4+
#
5+
# Usage:
6+
# source "$(dirname "$0")/lib/error-handling.sh"
7+
8+
LOG_FILE="${HOME}/.code-sensei/error.log"
9+
MAX_LOG_LINES=1000
10+
11+
# Log an error with timestamp and script name.
12+
# Usage: log_error "script-name" "message"
13+
log_error() {
14+
local script_name="${1:-unknown}"
15+
local message="$2"
16+
local timestamp
17+
timestamp=$(date -u '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || date '+%Y-%m-%d')
18+
mkdir -p "$(dirname "$LOG_FILE")"
19+
printf '[%s] [%s] %s\n' "$timestamp" "$script_name" "$message" >> "$LOG_FILE"
20+
# Cap log file to MAX_LOG_LINES
21+
if [ -f "$LOG_FILE" ]; then
22+
local line_count
23+
line_count=$(wc -l < "$LOG_FILE" 2>/dev/null || echo 0)
24+
if [ "$line_count" -gt "$MAX_LOG_LINES" ]; then
25+
tail -n "$MAX_LOG_LINES" "$LOG_FILE" > "${LOG_FILE}.tmp" && mv "${LOG_FILE}.tmp" "$LOG_FILE"
26+
fi
27+
fi
28+
}
29+
30+
# Safely escape a string for JSON interpolation.
31+
# Returns a JSON-encoded string including surrounding double quotes.
32+
# Usage: escaped=$(json_escape "$var")
33+
json_escape() {
34+
local str="$1"
35+
if command -v jq &>/dev/null; then
36+
printf '%s' "$str" | jq -Rs '.'
37+
else
38+
# Basic fallback: escape backslashes, double quotes, and common control chars
39+
printf '"%s"' "$(printf '%s' "$str" | sed 's/\\/\\\\/g; s/"/\\"/g')"
40+
fi
41+
}
42+
43+
# Check that jq is installed. Logs a one-time warning per session if missing.
44+
# Usage: check_jq "script-name" || exit 0
45+
check_jq() {
46+
if ! command -v jq &>/dev/null; then
47+
local warn_file="${HOME}/.code-sensei/.jq-warned"
48+
if [ ! -f "$warn_file" ]; then
49+
log_error "${1:-unknown}" "jq not installed — CodeSensei features limited. Install with: brew install jq"
50+
touch "$warn_file"
51+
fi
52+
return 1
53+
fi
54+
return 0
55+
}

0 commit comments

Comments
 (0)