juno-code 1.0.36 → 1.0.37

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.
@@ -38,6 +38,9 @@ NC='\033[0m' # No Color
38
38
  # Required packages
39
39
  REQUIRED_PACKAGES=("juno-kanban" "roundtable-ai")
40
40
 
41
+ # Slack integration dependencies (optional, only installed when Slack scripts are used)
42
+ SLACK_PACKAGES=("slack_sdk" "python-dotenv")
43
+
41
44
  # Logging functions
42
45
  log_info() {
43
46
  echo -e "${BLUE}[INFO]${NC} $1"
@@ -10,17 +10,34 @@
10
10
  # internal task management systems get a chance to operate even if kanban.sh
11
11
  # doesn't initially detect any tasks.
12
12
  #
13
- # Usage: ./.juno_task/scripts/run_until_completion.sh [juno-code arguments]
13
+ # Usage: ./.juno_task/scripts/run_until_completion.sh [options] [juno-code arguments]
14
14
  # Example: ./.juno_task/scripts/run_until_completion.sh -s claude -i 5 -v
15
15
  # Example: ./.juno_task/scripts/run_until_completion.sh -b shell -s claude -m :opus
16
+ # Example: ./.juno_task/scripts/run_until_completion.sh --pre-run "./slack/sync.sh" -s claude -i 5
17
+ # Example: ./.juno_task/scripts/run_until_completion.sh --pre-run-hook START_ITERATION -s claude -i 5
16
18
  #
17
- # All arguments passed to this script will be forwarded to juno-code.
19
+ # Options (for run_until_completion.sh):
20
+ # --pre-run <cmd> - Execute command before entering the main loop
21
+ # Can be specified multiple times for multiple commands
22
+ # Commands are executed in order before juno-code starts
23
+ # --pre-run-hook <name> - Execute a named hook from .juno_task/config.json
24
+ # --pre-run-hooks <name> (alias for --pre-run-hook)
25
+ # --run-pre-hook <name> (alias for --pre-run-hook)
26
+ # --run-pre-hooks <name> (alias for --pre-run-hook)
27
+ # The hook should be defined in config.json under "hooks"
28
+ # with a "commands" array. All commands in the hook are
29
+ # executed before the main loop.
30
+ # Can be specified multiple times for multiple hooks.
31
+ #
32
+ # All other arguments are forwarded to juno-code.
18
33
  # The script shows all stdout/stderr from juno-code in real-time.
19
34
  #
20
35
  # Environment Variables:
21
- # JUNO_DEBUG=true - Show [DEBUG] diagnostic messages
22
- # JUNO_VERBOSE=true - Show [RUN_UNTIL] informational messages
23
- # (Both default to false for silent operation)
36
+ # JUNO_DEBUG=true - Show [DEBUG] diagnostic messages
37
+ # JUNO_VERBOSE=true - Show [RUN_UNTIL] informational messages
38
+ # JUNO_PRE_RUN - Alternative way to specify pre-run command (env var)
39
+ # JUNO_PRE_RUN_HOOK - Alternative way to specify pre-run hook name (env var)
40
+ # (JUNO_DEBUG and JUNO_VERBOSE default to false for silent operation)
24
41
  #
25
42
  # Created by: juno-code init command
26
43
  # Date: Auto-generated during project initialization
@@ -44,6 +61,191 @@ NC='\033[0m' # No Color
44
61
  SCRIPTS_DIR=".juno_task/scripts"
45
62
  KANBAN_SCRIPT="${SCRIPTS_DIR}/kanban.sh"
46
63
 
64
+ # Arrays to store pre-run commands, hooks, and juno-code arguments
65
+ declare -a PRE_RUN_CMDS=()
66
+ declare -a PRE_RUN_HOOKS=()
67
+ declare -a JUNO_ARGS=()
68
+
69
+ # Configuration file path
70
+ CONFIG_FILE=".juno_task/config.json"
71
+
72
+ # Parse arguments to extract --pre-run and --pre-run-hook commands
73
+ parse_arguments() {
74
+ while [[ $# -gt 0 ]]; do
75
+ case $1 in
76
+ --pre-run)
77
+ if [[ -z "${2:-}" ]]; then
78
+ echo "[ERROR] --pre-run requires a command argument" >&2
79
+ exit 1
80
+ fi
81
+ PRE_RUN_CMDS+=("$2")
82
+ shift 2
83
+ ;;
84
+ --pre-run-hook|--pre-run-hooks|--run-pre-hook|--run-pre-hooks)
85
+ if [[ -z "${2:-}" ]]; then
86
+ echo "[ERROR] $1 requires a hook name argument" >&2
87
+ exit 1
88
+ fi
89
+ PRE_RUN_HOOKS+=("$2")
90
+ shift 2
91
+ ;;
92
+ *)
93
+ JUNO_ARGS+=("$1")
94
+ shift
95
+ ;;
96
+ esac
97
+ done
98
+
99
+ # Also check JUNO_PRE_RUN environment variable
100
+ if [[ -n "${JUNO_PRE_RUN:-}" ]]; then
101
+ # Prepend env var command (runs first)
102
+ PRE_RUN_CMDS=("$JUNO_PRE_RUN" "${PRE_RUN_CMDS[@]}")
103
+ fi
104
+
105
+ # Also check JUNO_PRE_RUN_HOOK environment variable
106
+ if [[ -n "${JUNO_PRE_RUN_HOOK:-}" ]]; then
107
+ # Prepend env var hook (runs first)
108
+ PRE_RUN_HOOKS=("$JUNO_PRE_RUN_HOOK" "${PRE_RUN_HOOKS[@]}")
109
+ fi
110
+ }
111
+
112
+ # Execute commands from a hook defined in config.json
113
+ execute_hook_commands() {
114
+ local hook_name="$1"
115
+
116
+ # Check if config file exists
117
+ if [[ ! -f "$CONFIG_FILE" ]]; then
118
+ log_error "Config file not found: $CONFIG_FILE"
119
+ log_error "Cannot execute hook: $hook_name"
120
+ return 1
121
+ fi
122
+
123
+ # Check if jq is available
124
+ if ! command -v jq &> /dev/null; then
125
+ log_error "jq is required for --pre-run-hook but not installed"
126
+ log_error "Please install jq: brew install jq (macOS) or apt-get install jq (Linux)"
127
+ return 1
128
+ fi
129
+
130
+ # Check if hook exists in config
131
+ local hook_exists
132
+ hook_exists=$(jq -e ".hooks.\"$hook_name\"" "$CONFIG_FILE" 2>/dev/null)
133
+ if [[ $? -ne 0 ]] || [[ "$hook_exists" == "null" ]]; then
134
+ log_error "Hook '$hook_name' not found in $CONFIG_FILE"
135
+ log_error "Available hooks: $(jq -r '.hooks | keys | join(", ")' "$CONFIG_FILE" 2>/dev/null || echo "none")"
136
+ return 1
137
+ fi
138
+
139
+ # Get commands array from hook
140
+ local commands_json
141
+ commands_json=$(jq -r ".hooks.\"$hook_name\".commands // []" "$CONFIG_FILE" 2>/dev/null)
142
+
143
+ # Get number of commands
144
+ local num_commands
145
+ num_commands=$(echo "$commands_json" | jq 'length')
146
+
147
+ if [[ "$num_commands" -eq 0 ]]; then
148
+ log_warning "Hook '$hook_name' has no commands defined"
149
+ return 0
150
+ fi
151
+
152
+ log_status ""
153
+ log_status "Executing hook '$hook_name' ($num_commands command(s))"
154
+ log_status "------------------------------------------"
155
+
156
+ # Execute each command in the hook
157
+ local idx=0
158
+ while [[ $idx -lt $num_commands ]]; do
159
+ local cmd
160
+ cmd=$(echo "$commands_json" | jq -r ".[$idx]")
161
+ idx=$((idx + 1))
162
+
163
+ log_status "Hook command [$idx/$num_commands]: $cmd"
164
+
165
+ if eval "$cmd"; then
166
+ log_success "Hook command [$idx/$num_commands] completed successfully"
167
+ else
168
+ local exit_code=$?
169
+ log_error "Hook command [$idx/$num_commands] failed with exit code $exit_code"
170
+ log_error "Command was: $cmd"
171
+ # Continue with next command even if one fails
172
+ fi
173
+ done
174
+
175
+ return 0
176
+ }
177
+
178
+ # Execute all pre-run hooks
179
+ execute_pre_run_hooks() {
180
+ local hook_count=${#PRE_RUN_HOOKS[@]}
181
+
182
+ if [[ $hook_count -eq 0 ]]; then
183
+ return 0
184
+ fi
185
+
186
+ log_status ""
187
+ log_status "=========================================="
188
+ log_status "Executing $hook_count pre-run hook(s)"
189
+ log_status "=========================================="
190
+
191
+ local idx=0
192
+ for hook_name in "${PRE_RUN_HOOKS[@]}"; do
193
+ idx=$((idx + 1))
194
+ log_status ""
195
+ log_status "Pre-run hook [$idx/$hook_count]: $hook_name"
196
+
197
+ if execute_hook_commands "$hook_name"; then
198
+ log_success "Pre-run hook [$idx/$hook_count] '$hook_name' completed"
199
+ else
200
+ log_error "Pre-run hook [$idx/$hook_count] '$hook_name' had errors"
201
+ # Continue with next hook even if one fails
202
+ fi
203
+ done
204
+
205
+ log_status ""
206
+ log_status "=========================================="
207
+ log_status "Pre-run hooks phase complete"
208
+ log_status "=========================================="
209
+ }
210
+
211
+ # Execute all pre-run commands
212
+ execute_pre_run_commands() {
213
+ local cmd_count=${#PRE_RUN_CMDS[@]}
214
+
215
+ if [[ $cmd_count -eq 0 ]]; then
216
+ return 0
217
+ fi
218
+
219
+ log_status ""
220
+ log_status "=========================================="
221
+ log_status "Executing $cmd_count pre-run command(s)"
222
+ log_status "=========================================="
223
+
224
+ local idx=0
225
+ for cmd in "${PRE_RUN_CMDS[@]}"; do
226
+ idx=$((idx + 1))
227
+ log_status ""
228
+ log_status "Pre-run [$idx/$cmd_count]: $cmd"
229
+ log_status "------------------------------------------"
230
+
231
+ # Execute the command
232
+ if eval "$cmd"; then
233
+ log_success "Pre-run [$idx/$cmd_count] completed successfully"
234
+ else
235
+ local exit_code=$?
236
+ log_error "Pre-run [$idx/$cmd_count] failed with exit code $exit_code"
237
+ log_error "Command was: $cmd"
238
+ # Continue with next pre-run command even if one fails
239
+ # This allows partial execution like Slack sync failing but still running juno-code
240
+ fi
241
+ done
242
+
243
+ log_status ""
244
+ log_status "=========================================="
245
+ log_status "Pre-run phase complete"
246
+ log_status "=========================================="
247
+ }
248
+
47
249
  # Logging functions
48
250
  log_info() {
49
251
  # Only print if JUNO_VERBOSE is set to true
@@ -131,8 +333,17 @@ main() {
131
333
  local iteration=0
132
334
  local max_iterations="${JUNO_RUN_UNTIL_MAX_ITERATIONS:-0}" # 0 = unlimited
133
335
 
336
+ # Parse arguments first to extract --pre-run commands
337
+ parse_arguments "$@"
338
+
134
339
  log_status "=== Run Until Completion ==="
135
- log_status "Arguments to juno-code: $*"
340
+ if [[ ${#PRE_RUN_HOOKS[@]} -gt 0 ]]; then
341
+ log_status "Pre-run hooks: ${PRE_RUN_HOOKS[*]}"
342
+ fi
343
+ if [[ ${#PRE_RUN_CMDS[@]} -gt 0 ]]; then
344
+ log_status "Pre-run commands: ${#PRE_RUN_CMDS[@]}"
345
+ fi
346
+ log_status "Arguments to juno-code: ${JUNO_ARGS[*]:-<none>}"
136
347
 
137
348
  if [ "$max_iterations" -gt 0 ]; then
138
349
  log_status "Maximum iterations: $max_iterations"
@@ -140,11 +351,16 @@ main() {
140
351
  log_status "Maximum iterations: unlimited"
141
352
  fi
142
353
 
143
- # Check if we have any arguments
144
- if [ $# -eq 0 ]; then
354
+ # Check if we have any arguments for juno-code
355
+ if [[ ${#JUNO_ARGS[@]} -eq 0 ]]; then
145
356
  log_warning "No arguments provided. Running juno-code with no arguments."
146
357
  fi
147
358
 
359
+ # Execute pre-run hooks and commands before entering the main loop
360
+ # Hooks run first, then explicit commands
361
+ execute_pre_run_hooks
362
+ execute_pre_run_commands
363
+
148
364
  # Do-while loop pattern: Run juno-code at least once, then continue while tasks remain
149
365
  # This ensures juno-code's internal task management systems get a chance to operate
150
366
  # even if kanban.sh doesn't initially detect any tasks
@@ -165,12 +381,12 @@ main() {
165
381
  exit 0
166
382
  fi
167
383
 
168
- log_status "Running juno-code with args: $*"
384
+ log_status "Running juno-code with args: ${JUNO_ARGS[*]:-<none>}"
169
385
  log_status "------------------------------------------"
170
386
 
171
- # Run juno-code with all provided arguments
387
+ # Run juno-code with parsed arguments (excluding --pre-run which was already processed)
172
388
  # We run juno-code FIRST (do-while pattern), then check for remaining tasks
173
- if juno-code "$@"; then
389
+ if juno-code "${JUNO_ARGS[@]}"; then
174
390
  log_success "juno-code completed successfully"
175
391
  else
176
392
  local exit_code=$?