diff --git a/.cursor/skills/continuous-learning-v2/hooks/observe.sh b/.cursor/skills/continuous-learning-v2/hooks/observe.sh index 225c90e..3db1a2c 100755 --- a/.cursor/skills/continuous-learning-v2/hooks/observe.sh +++ b/.cursor/skills/continuous-learning-v2/hooks/observe.sh @@ -56,20 +56,20 @@ if [ -z "$INPUT_JSON" ]; then exit 0 fi -# Parse using python (more reliable than jq for complex JSON) -PARSED=$(python3 << EOF +# Parse using python via stdin pipe (safe for all JSON payloads) +PARSED=$(echo "$INPUT_JSON" | python3 -c ' import json import sys try: - data = json.loads('''$INPUT_JSON''') + data = json.load(sys.stdin) # Extract fields - Claude Code hook format - hook_type = data.get('hook_type', 'unknown') # PreToolUse or PostToolUse - tool_name = data.get('tool_name', data.get('tool', 'unknown')) - tool_input = data.get('tool_input', data.get('input', {})) - tool_output = data.get('tool_output', data.get('output', '')) - session_id = data.get('session_id', 'unknown') + hook_type = data.get("hook_type", "unknown") # PreToolUse or PostToolUse + tool_name = data.get("tool_name", data.get("tool", "unknown")) + tool_input = data.get("tool_input", data.get("input", {})) + tool_output = data.get("tool_output", data.get("output", "")) + session_id = data.get("session_id", "unknown") # Truncate large inputs/outputs if isinstance(tool_input, dict): @@ -83,20 +83,19 @@ try: tool_output_str = str(tool_output)[:5000] # Determine event type - event = 'tool_start' if 'Pre' in hook_type else 'tool_complete' + event = "tool_start" if "Pre" in hook_type else "tool_complete" print(json.dumps({ - 'parsed': True, - 'event': event, - 'tool': tool_name, - 'input': tool_input_str if event == 'tool_start' else None, - 'output': tool_output_str if event == 'tool_complete' else None, - 'session': session_id + "parsed": True, + "event": event, + "tool": tool_name, + "input": tool_input_str if event == "tool_start" else None, + "output": tool_output_str if event == "tool_complete" else None, + "session": session_id })) except Exception as e: - print(json.dumps({'parsed': False, 'error': str(e)})) -EOF -) + print(json.dumps({"parsed": False, "error": str(e)})) +') # Check if parsing succeeded PARSED_OK=$(echo "$PARSED" | python3 -c "import json,sys; print(json.load(sys.stdin).get('parsed', False))") @@ -104,7 +103,11 @@ PARSED_OK=$(echo "$PARSED" | python3 -c "import json,sys; print(json.load(sys.st if [ "$PARSED_OK" != "True" ]; then # Fallback: log raw input for debugging timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ") - echo "{\"timestamp\":\"$timestamp\",\"event\":\"parse_error\",\"raw\":$(echo "$INPUT_JSON" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()[:1000]))')}" >> "$OBSERVATIONS_FILE" + echo "$INPUT_JSON" | python3 -c " +import json, sys +raw = sys.stdin.read()[:2000] +print(json.dumps({'timestamp': '$timestamp', 'event': 'parse_error', 'raw': raw})) +" >> "$OBSERVATIONS_FILE" exit 0 fi @@ -121,10 +124,10 @@ fi # Build and write observation timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ") -python3 << EOF -import json +echo "$PARSED" | python3 -c " +import json, sys -parsed = json.loads('''$PARSED''') +parsed = json.load(sys.stdin) observation = { 'timestamp': '$timestamp', 'event': parsed['event'], @@ -139,7 +142,7 @@ if parsed['output']: with open('$OBSERVATIONS_FILE', 'a') as f: f.write(json.dumps(observation) + '\n') -EOF +" # Signal observer if running OBSERVER_PID_FILE="${CONFIG_DIR}/.observer.pid" diff --git a/skills/strategic-compact/suggest-compact.sh b/skills/strategic-compact/suggest-compact.sh index ea14920..38f5aa9 100755 --- a/skills/strategic-compact/suggest-compact.sh +++ b/skills/strategic-compact/suggest-compact.sh @@ -28,7 +28,9 @@ # - Plan has been finalized # Track tool call count (increment in a temp file) -COUNTER_FILE="/tmp/claude-tool-count-$$" +# Use CLAUDE_SESSION_ID for session-specific counter (not $$ which changes per invocation) +SESSION_ID="${CLAUDE_SESSION_ID:-${PPID:-default}}" +COUNTER_FILE="/tmp/claude-tool-count-${SESSION_ID}" THRESHOLD=${COMPACT_THRESHOLD:-50} # Initialize or increment counter