claude-symphony 0.2.9 → 0.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-symphony",
3
- "version": "0.2.9",
3
+ "version": "0.2.11",
4
4
  "description": "Multi-AI Orchestration Framework - Create new projects with 10-stage development workflow",
5
5
  "type": "module",
6
6
  "bin": {
@@ -124,13 +124,24 @@ for arg in "$@"; do
124
124
  fi
125
125
  done
126
126
 
127
+ # Get configured threshold
128
+ get_threshold() {
129
+ local config_file="${HOME}/.claude/memory-relay/config.json"
130
+ if [[ -f "${config_file}" ]] && command -v jq &> /dev/null; then
131
+ jq -r '.threshold.trigger_percentage // 50' "${config_file}" 2>/dev/null || echo "50"
132
+ else
133
+ echo "50"
134
+ fi
135
+ }
136
+
127
137
  # Display relay status banner
128
138
  show_relay_banner() {
139
+ local threshold=$(get_threshold)
129
140
  echo ""
130
141
  echo -e "${CYAN}+============================================================+${NC}"
131
142
  echo -e "${CYAN}|${NC} ${GREEN}Claude Symphony - Encore Mode${NC} ${CYAN}|${NC}"
132
143
  echo -e "${CYAN}+============================================================+${NC}"
133
- echo -e "${CYAN}|${NC} Automatic session handoff at 50% context ${CYAN}|${NC}"
144
+ printf "${CYAN}|${NC} Automatic session handoff at %s%% context ${CYAN}|${NC}\n" "${threshold}"
134
145
  echo -e "${CYAN}|${NC} Claude never stops - your workflow continues forever ${CYAN}|${NC}"
135
146
  echo -e "${CYAN}+============================================================+${NC}"
136
147
  echo ""
@@ -154,8 +165,9 @@ if [[ -n "${HANDOFF_FILE}" ]] && [[ -f "${HANDOFF_FILE}" ]]; then
154
165
 
155
166
  show_relay_banner
156
167
 
157
- # Start Claude with instruction to read handoff
158
- exec $(get_claude_cmd) --resume "${HANDOFF_FILE}" 2>/dev/null || exec $(get_claude_cmd)
168
+ # Start Claude with system prompt to read handoff file and continue work
169
+ # Using --append-system-prompt to stay in interactive mode (not -p which exits after response)
170
+ exec $(get_claude_cmd) --append-system-prompt "IMPORTANT: A handoff file has been created at ${HANDOFF_FILE}. You MUST read this file immediately using the Read tool and continue the previous work described within it. This is a session continuation - start by reading the handoff file."
159
171
  else
160
172
  log_relay "Starting fresh Claude session with relay support"
161
173
  show_relay_banner
@@ -90,23 +90,59 @@ check_running() {
90
90
  return 1
91
91
  }
92
92
 
93
- # Send ACK back to Claude session
94
- send_ack() {
95
- local source_pane="$1"
96
- local new_pane="$2"
97
- local ack_message="RELAY_ACK:${new_pane}"
93
+ # Wait for /clear to complete
94
+ wait_for_clear_complete() {
95
+ local pane_id="$1"
96
+ local timeout="${2:-15}"
97
+ local elapsed=0
98
+
99
+ log "INFO" "Waiting for /clear to complete in pane ${pane_id} (timeout: ${timeout}s)"
100
+
101
+ while [[ ${elapsed} -lt ${timeout} ]]; do
102
+ # Capture last few lines of pane output
103
+ local output
104
+ output=$(tmux capture-pane -t "${pane_id}" -p -S -5 2>/dev/null || echo "")
105
+
106
+ # Check for Claude prompt ready state (ends with > or is empty/minimal)
107
+ local trimmed
108
+ trimmed=$(echo "${output}" | tr -d '[:space:]')
109
+
110
+ if [[ -z "${trimmed}" ]] || [[ "${output}" =~ \>$ ]]; then
111
+ sleep 0.5 # Small stabilization delay
112
+ log "INFO" "/clear completed, Claude is ready for input"
113
+ return 0
114
+ fi
115
+
116
+ sleep 0.5
117
+ ((elapsed++))
118
+ done
98
119
 
99
- log "INFO" "Sending ACK to pane ${source_pane}: ${ack_message}"
120
+ log "ERROR" "Timeout waiting for /clear to complete after ${timeout}s"
121
+ return 1
122
+ }
100
123
 
101
- if tmux send-keys -t "${source_pane}" "# ${ack_message}" Enter 2>/dev/null; then
102
- log "INFO" "ACK sent successfully"
124
+ # Send prompt to pane
125
+ send_prompt_to_pane() {
126
+ local pane_id="$1"
127
+ local prompt="$2"
128
+
129
+ log "INFO" "Sending handoff prompt to pane ${pane_id}"
130
+
131
+ if tmux send-keys -t "${pane_id}" "${prompt}" Enter 2>/dev/null; then
132
+ log "INFO" "Handoff prompt sent successfully"
103
133
  return 0
104
134
  else
105
- log "WARN" "Failed to send ACK to pane ${source_pane}"
135
+ log "ERROR" "Failed to send prompt to pane ${pane_id}"
106
136
  return 1
107
137
  fi
108
138
  }
109
139
 
140
+ # Build continuation prompt
141
+ build_continuation_prompt() {
142
+ local handoff_path="$1"
143
+ echo "${handoff_path} 파일을 읽고 이어서 작업을 진행해주세요."
144
+ }
145
+
110
146
  # Handle relay signal
111
147
  handle_relay_signal() {
112
148
  local signal="$1"
@@ -115,43 +151,43 @@ handle_relay_signal() {
115
151
  # Parse signal: RELAY_READY:handoff_path:source_pane
116
152
  if [[ "${signal}" =~ ^RELAY_READY:(.+):(.+)$ ]]; then
117
153
  local handoff_path="${BASH_REMATCH[1]}"
118
- local source_pane="${BASH_REMATCH[2]}"
154
+ local pane_id="${BASH_REMATCH[2]}"
119
155
 
120
156
  log "INFO" "Processing relay request"
121
157
  log "INFO" " Handoff path: ${handoff_path}"
122
- log "INFO" " Source pane: ${source_pane}"
158
+ log "INFO" " Pane: ${pane_id}"
123
159
 
124
160
  if [[ ! -f "${handoff_path}" ]]; then
125
161
  log "ERROR" "Handoff file not found: ${handoff_path}"
126
162
  return 1
127
163
  fi
128
164
 
129
- local work_dir=$(dirname "${handoff_path}")
130
-
131
- log "INFO" "Creating new tmux pane for Claude session"
132
-
133
- local new_pane
134
- new_pane=$(tmux split-window -h -P -F "#{pane_id}" \
135
- -c "${work_dir}" \
136
- "${ORCHESTRATOR_DIR}/claude-wrapper.sh '${handoff_path}'" 2>&1)
165
+ # Step 1: Send /clear command to current pane
166
+ log "INFO" "Sending /clear to pane ${pane_id}"
167
+ if ! tmux send-keys -t "${pane_id}" "/clear" Enter 2>/dev/null; then
168
+ log "ERROR" "Failed to send /clear to pane ${pane_id}"
169
+ return 1
170
+ fi
137
171
 
138
- if [[ $? -eq 0 ]] && [[ -n "${new_pane}" ]]; then
139
- log "INFO" "New pane created: ${new_pane}"
140
- sleep 2
172
+ # Step 2: Wait for /clear to complete
173
+ if ! wait_for_clear_complete "${pane_id}" 15; then
174
+ log "ERROR" "Clear did not complete in time"
175
+ return 1
176
+ fi
141
177
 
142
- if tmux list-panes -F "#{pane_id}" | grep -q "${new_pane}"; then
143
- log "INFO" "New Claude session started successfully"
144
- send_ack "${source_pane}" "${new_pane}"
145
- archive_handoff "${handoff_path}"
146
- return 0
147
- else
148
- log "ERROR" "New pane ${new_pane} not found after creation"
149
- return 1
150
- fi
151
- else
152
- log "ERROR" "Failed to create new pane: ${new_pane}"
178
+ # Step 3: Send handoff prompt
179
+ local prompt
180
+ prompt=$(build_continuation_prompt "${handoff_path}")
181
+ if ! send_prompt_to_pane "${pane_id}" "${prompt}"; then
182
+ log "ERROR" "Failed to send handoff prompt"
153
183
  return 1
154
184
  fi
185
+
186
+ log "INFO" "Session handoff complete via /clear injection"
187
+
188
+ # Archive the handoff file
189
+ archive_handoff "${handoff_path}"
190
+ return 0
155
191
  else
156
192
  log "WARN" "Invalid signal format: ${signal}"
157
193
  return 1
@@ -0,0 +1,161 @@
1
+ # /threshold - Context Reset Threshold
2
+
3
+ Set the context percentage threshold for automatic session relay.
4
+
5
+ ## Usage
6
+ ```
7
+ /threshold # Show current threshold
8
+ /threshold <percent> # Set threshold (e.g., /threshold 80)
9
+ /threshold reset # Reset to default (50%)
10
+ ```
11
+
12
+ ## Actions
13
+
14
+ ### Show Current Threshold (`/threshold`)
15
+
16
+ Read the config file and display current threshold settings:
17
+
18
+ ```bash
19
+ CONFIG_FILE="$HOME/.claude/memory-relay/config.json"
20
+ if [ -f "$CONFIG_FILE" ]; then
21
+ TRIGGER=$(jq -r '.threshold.trigger_percentage // 50' "$CONFIG_FILE")
22
+ WARNING=$(jq -r '.threshold.warning_percentage // 60' "$CONFIG_FILE")
23
+ echo ""
24
+ echo "Current Context Threshold Settings:"
25
+ echo " Trigger (relay/compact): ${TRIGGER}%"
26
+ echo " Warning display: ${WARNING}%"
27
+ echo ""
28
+ echo "Session will relay when context drops to ${TRIGGER}% or below."
29
+ else
30
+ echo "Config file not found. Using defaults (trigger: 50%, warning: 60%)"
31
+ fi
32
+ ```
33
+
34
+ ### Set Threshold (`/threshold <percent>`)
35
+
36
+ 1. Validate percent is between 10-90
37
+ 2. Update `~/.claude/memory-relay/config.json`:
38
+ - Set `threshold.trigger_percentage` to the specified value
39
+ - Set `threshold.warning_percentage` to value + 10 (capped at 90)
40
+
41
+ ```bash
42
+ PERCENT=$1 # e.g., 80
43
+ CONFIG_FILE="$HOME/.claude/memory-relay/config.json"
44
+
45
+ # Validate range
46
+ if [ "$PERCENT" -lt 10 ] || [ "$PERCENT" -gt 90 ]; then
47
+ echo "Error: Threshold must be between 10 and 90"
48
+ exit 1
49
+ fi
50
+
51
+ # Calculate warning threshold (trigger + 10, max 90)
52
+ WARNING=$((PERCENT + 10))
53
+ if [ "$WARNING" -gt 90 ]; then
54
+ WARNING=90
55
+ fi
56
+
57
+ # Ensure directory exists
58
+ mkdir -p "$(dirname "$CONFIG_FILE")"
59
+
60
+ # Update config (or create if not exists)
61
+ if [ -f "$CONFIG_FILE" ]; then
62
+ jq --argjson trigger "$PERCENT" --argjson warning "$WARNING" \
63
+ '.threshold.trigger_percentage = $trigger | .threshold.warning_percentage = $warning' \
64
+ "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE"
65
+ else
66
+ cat > "$CONFIG_FILE" << EOF
67
+ {
68
+ "threshold": {
69
+ "trigger_percentage": $PERCENT,
70
+ "warning_percentage": $WARNING,
71
+ "cooldown_seconds": 300
72
+ }
73
+ }
74
+ EOF
75
+ fi
76
+
77
+ echo ""
78
+ echo "Context threshold updated:"
79
+ echo " Trigger: ${PERCENT}%"
80
+ echo " Warning: ${WARNING}%"
81
+ echo ""
82
+ echo "Session will relay when context drops to ${PERCENT}% or below."
83
+ ```
84
+
85
+ ### Reset to Default (`/threshold reset`)
86
+
87
+ Reset trigger_percentage to default value (50%):
88
+
89
+ ```bash
90
+ CONFIG_FILE="$HOME/.claude/memory-relay/config.json"
91
+
92
+ if [ -f "$CONFIG_FILE" ]; then
93
+ jq '.threshold.trigger_percentage = 50 | .threshold.warning_percentage = 60' \
94
+ "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE"
95
+ fi
96
+
97
+ echo ""
98
+ echo "Context threshold reset to defaults:"
99
+ echo " Trigger: 50%"
100
+ echo " Warning: 60%"
101
+ ```
102
+
103
+ ## Output Examples
104
+
105
+ ### Show Current
106
+ ```
107
+ /threshold
108
+
109
+ Current Context Threshold Settings:
110
+ Trigger (relay/compact): 50%
111
+ Warning display: 60%
112
+
113
+ Session will relay when context drops to 50% or below.
114
+ ```
115
+
116
+ ### Set Threshold
117
+ ```
118
+ /threshold 80
119
+
120
+ Context threshold updated:
121
+ Trigger: 80%
122
+ Warning: 90%
123
+
124
+ Session will relay when context drops to 80% or below.
125
+ ```
126
+
127
+ ### Reset
128
+ ```
129
+ /threshold reset
130
+
131
+ Context threshold reset to defaults:
132
+ Trigger: 50%
133
+ Warning: 60%
134
+ ```
135
+
136
+ ## Configuration File
137
+
138
+ Location: `~/.claude/memory-relay/config.json`
139
+
140
+ ```json
141
+ {
142
+ "threshold": {
143
+ "trigger_percentage": 50,
144
+ "warning_percentage": 60,
145
+ "cooldown_seconds": 300
146
+ }
147
+ }
148
+ ```
149
+
150
+ ## Notes
151
+
152
+ - This is a **global setting** (applies to all projects)
153
+ - Valid range: 10-90%
154
+ - Higher threshold = earlier relay (more aggressive context management)
155
+ - Lower threshold = later relay (use more context before handoff)
156
+ - Recommended: 50% (default) for most workflows, 70-80% for complex tasks
157
+
158
+ ## Related Commands
159
+
160
+ - `/context` - Check current context state
161
+ - `/handoff` - Generate handoff document manually
@@ -11,10 +11,25 @@ PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
11
11
  STATE_FILE="$PROJECT_ROOT/state/context/auto-trigger.json"
12
12
  PROGRESS_FILE="$PROJECT_ROOT/state/progress.json"
13
13
  CONTEXT_DIR="$PROJECT_ROOT/state/context"
14
+ CONFIG_FILE="$HOME/.claude/memory-relay/config.json"
14
15
 
15
16
  # Ensure context directory
16
17
  mkdir -p "$CONTEXT_DIR"
17
18
 
19
+ # Read thresholds from config (with defaults)
20
+ if [ -f "$CONFIG_FILE" ] && command -v jq &> /dev/null; then
21
+ THRESHOLD_TRIGGER=$(jq -r '.threshold.trigger_percentage // 50' "$CONFIG_FILE" 2>/dev/null || echo "50")
22
+ THRESHOLD_WARNING=$(jq -r '.threshold.warning_percentage // 60' "$CONFIG_FILE" 2>/dev/null || echo "60")
23
+ else
24
+ THRESHOLD_TRIGGER=50
25
+ THRESHOLD_WARNING=60
26
+ fi
27
+ # Critical is always trigger - 10
28
+ THRESHOLD_CRITICAL=$((THRESHOLD_TRIGGER - 10))
29
+ if [ "$THRESHOLD_CRITICAL" -lt 10 ]; then
30
+ THRESHOLD_CRITICAL=10
31
+ fi
32
+
18
33
  # Read JSON from stdin
19
34
  input=$(cat)
20
35
 
@@ -41,21 +56,21 @@ fi
41
56
  REMAINING_INT=$(printf "%.0f" "$REMAINING" 2>/dev/null || echo "100")
42
57
 
43
58
  # Determine status and color
44
- # Thresholds: 60% warning, 50% auto-save, 40% critical
45
- if [ "$REMAINING_INT" -le 40 ]; then
46
- # 40% or below: Critical - recommend /clear
59
+ # Thresholds from config: warning (display), trigger (auto-save), critical (relay)
60
+ if [ "$REMAINING_INT" -le "$THRESHOLD_CRITICAL" ]; then
61
+ # Critical - recommend /clear or relay
47
62
  STATUS_ICON="🔴"
48
- STATUS_TEXT="CTX≤40%"
63
+ STATUS_TEXT="CTX≤${THRESHOLD_CRITICAL}%"
49
64
  NEEDS_ACTION="critical"
50
- elif [ "$REMAINING_INT" -le 50 ]; then
51
- # 50% or below: Auto snapshot trigger
65
+ elif [ "$REMAINING_INT" -le "$THRESHOLD_TRIGGER" ]; then
66
+ # Trigger level - auto snapshot/relay
52
67
  STATUS_ICON="⚠️"
53
- STATUS_TEXT="CTX≤50%"
68
+ STATUS_TEXT="CTX≤${THRESHOLD_TRIGGER}%"
54
69
  NEEDS_ACTION="warning"
55
- elif [ "$REMAINING_INT" -le 60 ]; then
56
- # 60% or below: Warning display
70
+ elif [ "$REMAINING_INT" -le "$THRESHOLD_WARNING" ]; then
71
+ # Warning display
57
72
  STATUS_ICON="⚡"
58
- STATUS_TEXT="CTX≤60%"
73
+ STATUS_TEXT="CTX≤${THRESHOLD_WARNING}%"
59
74
  NEEDS_ACTION="notice"
60
75
  else
61
76
  # Normal
@@ -12,13 +12,19 @@ TRIGGER_FILE="$PROJECT_ROOT/state/context/auto-trigger.json"
12
12
  COOLDOWN_FILE="$PROJECT_ROOT/state/context/.last-compact"
13
13
  CONTEXT_DIR="$PROJECT_ROOT/state/context"
14
14
  PROGRESS_FILE="$PROJECT_ROOT/state/progress.json"
15
+ CONFIG_FILE="$HOME/.claude/memory-relay/config.json"
15
16
 
16
17
  # Memory Relay FIFO paths
17
18
  MEMORY_RELAY_FIFO_GLOBAL="$HOME/.claude/memory-relay/orchestrator/signals/relay.fifo"
18
19
  MEMORY_RELAY_FIFO_LOCAL="$PROJECT_ROOT/scripts/memory-relay/orchestrator/signals/relay.fifo"
19
20
 
20
- # Cooldown time (seconds) - 5 minutes
21
+ # Read threshold and cooldown from config (with defaults)
22
+ THRESHOLD_TRIGGER=50
21
23
  COOLDOWN_SECONDS=300
24
+ if [ -f "$CONFIG_FILE" ] && command -v jq &> /dev/null; then
25
+ THRESHOLD_TRIGGER=$(jq -r '.threshold.trigger_percentage // 50' "$CONFIG_FILE" 2>/dev/null || echo "50")
26
+ COOLDOWN_SECONDS=$(jq -r '.threshold.cooldown_seconds // 300' "$CONFIG_FILE" 2>/dev/null || echo "300")
27
+ fi
22
28
 
23
29
  # Ensure context directory
24
30
  mkdir -p "$CONTEXT_DIR"
@@ -44,8 +50,8 @@ fi
44
50
  REMAINING=$(jq -r '.remaining // 100' "$TRIGGER_FILE" 2>/dev/null || echo "100")
45
51
  LEVEL=$(jq -r '.level // "warning"' "$TRIGGER_FILE" 2>/dev/null || echo "warning")
46
52
 
47
- # Skip if not 50% or below
48
- if [ "$REMAINING" -gt 50 ]; then
53
+ # Skip if above trigger threshold
54
+ if [ "$REMAINING" -gt "$THRESHOLD_TRIGGER" ]; then
49
55
  exit 0
50
56
  fi
51
57
 
@@ -124,6 +124,10 @@
124
124
  "validate": {
125
125
  "description": "Run output validation",
126
126
  "file": "commands/validate.md"
127
+ },
128
+ "threshold": {
129
+ "description": "Configure context reset threshold for relay",
130
+ "file": "commands/threshold.md"
127
131
  }
128
132
  },
129
133
  "skills": {
@@ -183,6 +183,9 @@ Visualizes context usage, tool activity, and todo progress in the statusline.
183
183
  | `/config sprint disable` | Disable sprint mode (single-pass) |
184
184
  | `/config sprint status` | Show current iteration settings |
185
185
  | `/config sprint count <n>` | Set default sprint count |
186
+ | `/threshold` | Show current context reset threshold |
187
+ | `/threshold <percent>` | Set relay trigger threshold (10-90%) |
188
+ | `/threshold reset` | Reset threshold to default (50%) |
186
189
 
187
190
  ### Stage Shortcut Commands
188
191
  | Command | Stage |