juno-code 1.0.44 → 1.0.46
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/README.md +1 -1
- package/dist/bin/cli.js +658 -50
- package/dist/bin/cli.js.map +1 -1
- package/dist/bin/cli.mjs +658 -50
- package/dist/bin/cli.mjs.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -4
- package/dist/index.mjs.map +1 -1
- package/dist/templates/scripts/__pycache__/attachment_downloader.cpython-38.pyc +0 -0
- package/dist/templates/scripts/__pycache__/github.cpython-38.pyc +0 -0
- package/dist/templates/scripts/__pycache__/slack_fetch.cpython-38.pyc +0 -0
- package/dist/templates/scripts/__pycache__/slack_state.cpython-38.pyc +0 -0
- package/dist/templates/scripts/attachment_downloader.py +405 -0
- package/dist/templates/scripts/github.py +282 -7
- package/dist/templates/scripts/hooks/session_counter.sh +328 -0
- package/dist/templates/scripts/kanban.sh +22 -4
- package/dist/templates/scripts/log_scanner.sh +790 -0
- package/dist/templates/scripts/slack_fetch.py +232 -20
- package/dist/templates/services/claude.py +50 -1
- package/dist/templates/services/codex.py +5 -4
- package/dist/templates/skills/claude/.gitkeep +0 -0
- package/dist/templates/skills/claude/plan-kanban-tasks/SKILL.md +25 -0
- package/dist/templates/skills/claude/ralph-loop/SKILL.md +43 -0
- package/dist/templates/skills/claude/ralph-loop/references/first_check.md +20 -0
- package/dist/templates/skills/claude/ralph-loop/references/implement.md +99 -0
- package/dist/templates/skills/claude/ralph-loop/scripts/kanban.sh +293 -0
- package/dist/templates/skills/claude/understand-project/SKILL.md +39 -0
- package/dist/templates/skills/codex/.gitkeep +0 -0
- package/dist/templates/skills/codex/ralph-loop/SKILL.md +43 -0
- package/dist/templates/skills/codex/ralph-loop/references/first_check.md +20 -0
- package/dist/templates/skills/codex/ralph-loop/references/implement.md +99 -0
- package/dist/templates/skills/codex/ralph-loop/scripts/kanban.sh +293 -0
- package/package.json +3 -2
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# kanban.sh
|
|
4
|
+
#
|
|
5
|
+
# Purpose: Kanban wrapper with Python environment setup
|
|
6
|
+
#
|
|
7
|
+
# This script ensures juno-kanban always executes from the project root directory
|
|
8
|
+
# with the proper Python virtual environment activated.
|
|
9
|
+
#
|
|
10
|
+
# Usage: ./.juno_task/scripts/kanban.sh [juno-kanban arguments]
|
|
11
|
+
# Example: ./.juno_task/scripts/kanban.sh list --limit 5
|
|
12
|
+
# Example: ./.juno_task/scripts/kanban.sh list -f json --raw # (flag order normalized)
|
|
13
|
+
# Example: ./.juno_task/scripts/kanban.sh -f json --raw list # (also works)
|
|
14
|
+
#
|
|
15
|
+
# Note: Global flags (-f/--format, -p/--pretty, --raw, -v/--verbose, -c/--config)
|
|
16
|
+
# can be placed anywhere in the command line. This wrapper normalizes them
|
|
17
|
+
# to appear before the command for juno-kanban compatibility.
|
|
18
|
+
#
|
|
19
|
+
# Environment Variables:
|
|
20
|
+
# JUNO_DEBUG=true - Show [DEBUG] diagnostic messages
|
|
21
|
+
# JUNO_VERBOSE=true - Show [KANBAN] informational messages
|
|
22
|
+
# (Both default to false for silent operation)
|
|
23
|
+
#
|
|
24
|
+
# Created by: juno-code init command
|
|
25
|
+
# Date: Auto-generated during project initialization
|
|
26
|
+
|
|
27
|
+
set -euo pipefail # Exit on error, undefined variable, or pipe failure
|
|
28
|
+
|
|
29
|
+
# DEBUG OUTPUT: Show that kanban.sh is being executed (only if JUNO_DEBUG=true)
|
|
30
|
+
# Note: JUNO_DEBUG is separate from JUNO_VERBOSE for fine-grained control
|
|
31
|
+
if [ "${JUNO_DEBUG:-false}" = "true" ]; then
|
|
32
|
+
echo "[DEBUG] kanban.sh is being executed from: $(pwd)" >&2
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Color output for better readability
|
|
36
|
+
RED='\033[0;31m'
|
|
37
|
+
GREEN='\033[0;32m'
|
|
38
|
+
YELLOW='\033[1;33m'
|
|
39
|
+
BLUE='\033[0;34m'
|
|
40
|
+
NC='\033[0m' # No Color
|
|
41
|
+
|
|
42
|
+
# Configuration
|
|
43
|
+
VENV_DIR=".venv_juno"
|
|
44
|
+
SCRIPTS_DIR=".juno_task/scripts"
|
|
45
|
+
INSTALL_SCRIPT="${SCRIPTS_DIR}/install_requirements.sh"
|
|
46
|
+
|
|
47
|
+
# Logging functions
|
|
48
|
+
log_info() {
|
|
49
|
+
# Only print if JUNO_VERBOSE is set to true
|
|
50
|
+
if [ "${JUNO_VERBOSE:-false}" = "true" ]; then
|
|
51
|
+
echo -e "${BLUE}[KANBAN]${NC} $1"
|
|
52
|
+
fi
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
log_success() {
|
|
56
|
+
# Only print if JUNO_VERBOSE is set to true
|
|
57
|
+
if [ "${JUNO_VERBOSE:-false}" = "true" ]; then
|
|
58
|
+
echo -e "${GREEN}[KANBAN]${NC} $1"
|
|
59
|
+
fi
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
log_warning() {
|
|
63
|
+
# Only print if JUNO_VERBOSE is set to true
|
|
64
|
+
if [ "${JUNO_VERBOSE:-false}" = "true" ]; then
|
|
65
|
+
echo -e "${YELLOW}[KANBAN]${NC} $1"
|
|
66
|
+
fi
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
log_error() {
|
|
70
|
+
# Always print errors regardless of JUNO_VERBOSE
|
|
71
|
+
echo -e "${RED}[KANBAN]${NC} $1"
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
# Function to check if we're inside .venv_juno specifically
|
|
75
|
+
# CRITICAL: Don't just check for ANY venv - check if we're in .venv_juno
|
|
76
|
+
is_in_venv_juno() {
|
|
77
|
+
# Check if VIRTUAL_ENV is set and points to .venv_juno
|
|
78
|
+
if [ -n "${VIRTUAL_ENV:-}" ]; then
|
|
79
|
+
# Check if VIRTUAL_ENV path contains .venv_juno
|
|
80
|
+
if [[ "${VIRTUAL_ENV:-}" == *"/.venv_juno" ]] || [[ "${VIRTUAL_ENV:-}" == *".venv_juno"* ]]; then
|
|
81
|
+
return 0 # Inside .venv_juno
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
# Check if the basename is .venv_juno
|
|
85
|
+
if [ "$(basename "${VIRTUAL_ENV:-}")" = ".venv_juno" ]; then
|
|
86
|
+
return 0 # Inside .venv_juno
|
|
87
|
+
fi
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
return 1 # Not inside .venv_juno (or not in any venv)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# Function to activate virtual environment
|
|
94
|
+
activate_venv() {
|
|
95
|
+
local venv_path="$1"
|
|
96
|
+
|
|
97
|
+
if [ ! -d "$venv_path" ]; then
|
|
98
|
+
log_error "Virtual environment not found: $venv_path"
|
|
99
|
+
return 1
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
# Activate the venv
|
|
103
|
+
# shellcheck disable=SC1091
|
|
104
|
+
if [ -f "$venv_path/bin/activate" ]; then
|
|
105
|
+
source "$venv_path/bin/activate"
|
|
106
|
+
log_success "Activated virtual environment: $venv_path"
|
|
107
|
+
return 0
|
|
108
|
+
else
|
|
109
|
+
log_error "Activation script not found: $venv_path/bin/activate"
|
|
110
|
+
return 1
|
|
111
|
+
fi
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
# Function to ensure Python environment is ready
|
|
115
|
+
ensure_python_environment() {
|
|
116
|
+
log_info "Checking Python environment..."
|
|
117
|
+
|
|
118
|
+
# Step 1: Check if we're already in .venv_juno specifically
|
|
119
|
+
if is_in_venv_juno; then
|
|
120
|
+
log_success "Already inside .venv_juno virtual environment"
|
|
121
|
+
return 0
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# Step 2: Not in .venv_juno - check if .venv_juno exists in project root
|
|
125
|
+
if [ -d "$VENV_DIR" ]; then
|
|
126
|
+
log_info "Found existing virtual environment: $VENV_DIR"
|
|
127
|
+
|
|
128
|
+
# Activate the venv
|
|
129
|
+
if activate_venv "$VENV_DIR"; then
|
|
130
|
+
return 0
|
|
131
|
+
else
|
|
132
|
+
log_error "Failed to activate virtual environment"
|
|
133
|
+
return 1
|
|
134
|
+
fi
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
# Step 3: .venv_juno doesn't exist - need to create it
|
|
138
|
+
log_warning "Virtual environment not found: $VENV_DIR"
|
|
139
|
+
log_info "Running install_requirements.sh to create virtual environment..."
|
|
140
|
+
|
|
141
|
+
# Check if install_requirements.sh exists
|
|
142
|
+
if [ ! -f "$INSTALL_SCRIPT" ]; then
|
|
143
|
+
log_error "Install script not found: $INSTALL_SCRIPT"
|
|
144
|
+
log_error "Please run 'juno-code init' to initialize the project"
|
|
145
|
+
return 1
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
# Make sure the script is executable
|
|
149
|
+
chmod +x "$INSTALL_SCRIPT"
|
|
150
|
+
|
|
151
|
+
# Run the install script
|
|
152
|
+
if bash "$INSTALL_SCRIPT"; then
|
|
153
|
+
log_success "Python environment setup completed successfully"
|
|
154
|
+
|
|
155
|
+
# After install, activate the venv if it was created
|
|
156
|
+
if [ -d "$VENV_DIR" ]; then
|
|
157
|
+
if activate_venv "$VENV_DIR"; then
|
|
158
|
+
return 0
|
|
159
|
+
fi
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
return 0
|
|
163
|
+
else
|
|
164
|
+
log_error "Failed to run install_requirements.sh"
|
|
165
|
+
log_error "Please check the error messages above"
|
|
166
|
+
return 1
|
|
167
|
+
fi
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
# Get the directory where this script is located
|
|
171
|
+
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
172
|
+
|
|
173
|
+
# Navigate to project root (parent of scripts directory)
|
|
174
|
+
PROJECT_ROOT="$( cd "$SCRIPT_DIR/../../../.." && pwd )"
|
|
175
|
+
|
|
176
|
+
# Change to project root
|
|
177
|
+
cd "$PROJECT_ROOT"
|
|
178
|
+
|
|
179
|
+
# Arrays to store normalized arguments (declared at script level for proper handling)
|
|
180
|
+
declare -a NORMALIZED_GLOBAL_FLAGS=()
|
|
181
|
+
declare -a NORMALIZED_COMMAND_ARGS=()
|
|
182
|
+
|
|
183
|
+
# Normalize argument order for juno-kanban
|
|
184
|
+
# juno-kanban requires global flags BEFORE the command, but users often
|
|
185
|
+
# write them after (e.g., "list -f json --raw" instead of "-f json --raw list")
|
|
186
|
+
# This function reorders arguments so global flags come first.
|
|
187
|
+
# Results are stored in NORMALIZED_GLOBAL_FLAGS and NORMALIZED_COMMAND_ARGS arrays.
|
|
188
|
+
normalize_arguments() {
|
|
189
|
+
# Reset arrays
|
|
190
|
+
NORMALIZED_GLOBAL_FLAGS=()
|
|
191
|
+
NORMALIZED_COMMAND_ARGS=()
|
|
192
|
+
local found_command=false
|
|
193
|
+
|
|
194
|
+
# Known subcommands
|
|
195
|
+
local commands="create search get show update archive mark list merge"
|
|
196
|
+
|
|
197
|
+
while [[ $# -gt 0 ]]; do
|
|
198
|
+
case $1 in
|
|
199
|
+
# Global flags that take a value
|
|
200
|
+
-f|--format|-c|--config)
|
|
201
|
+
if [[ -n "${2:-}" ]]; then
|
|
202
|
+
NORMALIZED_GLOBAL_FLAGS+=("$1" "$2")
|
|
203
|
+
shift 2
|
|
204
|
+
else
|
|
205
|
+
NORMALIZED_GLOBAL_FLAGS+=("$1")
|
|
206
|
+
shift
|
|
207
|
+
fi
|
|
208
|
+
;;
|
|
209
|
+
# Global flags that don't take a value
|
|
210
|
+
-p|--pretty|--raw|-v|--verbose|-h|--help|--version)
|
|
211
|
+
NORMALIZED_GLOBAL_FLAGS+=("$1")
|
|
212
|
+
shift
|
|
213
|
+
;;
|
|
214
|
+
# Check if this is a known command
|
|
215
|
+
*)
|
|
216
|
+
# Check if this argument is a known command
|
|
217
|
+
local is_command=false
|
|
218
|
+
for cmd in $commands; do
|
|
219
|
+
if [[ "$1" == "$cmd" ]]; then
|
|
220
|
+
is_command=true
|
|
221
|
+
found_command=true
|
|
222
|
+
break
|
|
223
|
+
fi
|
|
224
|
+
done
|
|
225
|
+
|
|
226
|
+
# If we found a command, everything from here goes to command_args
|
|
227
|
+
if $is_command || $found_command; then
|
|
228
|
+
NORMALIZED_COMMAND_ARGS+=("$1")
|
|
229
|
+
found_command=true
|
|
230
|
+
else
|
|
231
|
+
# Before finding a command, treat as command arg
|
|
232
|
+
NORMALIZED_COMMAND_ARGS+=("$1")
|
|
233
|
+
fi
|
|
234
|
+
shift
|
|
235
|
+
;;
|
|
236
|
+
esac
|
|
237
|
+
done
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
# Main kanban logic
|
|
241
|
+
main() {
|
|
242
|
+
log_info "=== juno-kanban Wrapper ==="
|
|
243
|
+
|
|
244
|
+
# Ensure Python environment is ready
|
|
245
|
+
if ! ensure_python_environment; then
|
|
246
|
+
log_error "Failed to setup Python environment"
|
|
247
|
+
exit 1
|
|
248
|
+
fi
|
|
249
|
+
|
|
250
|
+
log_success "Python environment ready!"
|
|
251
|
+
|
|
252
|
+
# Normalize argument order (global flags before command)
|
|
253
|
+
# This allows users to write "list -f json --raw" which gets reordered to "-f json --raw list"
|
|
254
|
+
normalize_arguments "$@"
|
|
255
|
+
|
|
256
|
+
if [ "${JUNO_DEBUG:-false}" = "true" ]; then
|
|
257
|
+
echo "[DEBUG] Original args: $*" >&2
|
|
258
|
+
echo "[DEBUG] Normalized global flags: ${NORMALIZED_GLOBAL_FLAGS[*]:-<none>}" >&2
|
|
259
|
+
echo "[DEBUG] Normalized command args: ${NORMALIZED_COMMAND_ARGS[*]:-<none>}" >&2
|
|
260
|
+
fi
|
|
261
|
+
|
|
262
|
+
# Execute juno-kanban with normalized arguments from project root
|
|
263
|
+
# Build the command properly preserving argument quoting
|
|
264
|
+
log_info "Executing juno-kanban with normalized arguments"
|
|
265
|
+
|
|
266
|
+
# Execute with proper array expansion to preserve quoting
|
|
267
|
+
# Use ${arr[@]+"${arr[@]}"} pattern to handle empty arrays with set -u
|
|
268
|
+
#
|
|
269
|
+
# Stdin handling:
|
|
270
|
+
# Detect the type of stdin to determine whether to pass it through or redirect from /dev/null:
|
|
271
|
+
# - 'p' (pipe): Pass through - user is piping data (e.g., echo "..." | kanban.sh create)
|
|
272
|
+
# - '-' (regular file): Pass through - user is using heredoc (kanban.sh create << 'EOF')
|
|
273
|
+
# - 'c' (character device) or other: Redirect from /dev/null to prevent hanging
|
|
274
|
+
# when called from tools that don't provide stdin (Issue #42, #60)
|
|
275
|
+
#
|
|
276
|
+
# The first character of `ls -la /dev/fd/0` indicates the file type:
|
|
277
|
+
# p = pipe, - = regular file, c = character device, l = symlink, etc.
|
|
278
|
+
local stdin_type
|
|
279
|
+
stdin_type=$(ls -la /dev/fd/0 2>/dev/null | cut -c1)
|
|
280
|
+
|
|
281
|
+
if [[ "$stdin_type" == "p" || "$stdin_type" == "-" ]]; then
|
|
282
|
+
# stdin is a pipe or regular file (heredoc) - pass it through
|
|
283
|
+
juno-kanban ${NORMALIZED_GLOBAL_FLAGS[@]+"${NORMALIZED_GLOBAL_FLAGS[@]}"} \
|
|
284
|
+
${NORMALIZED_COMMAND_ARGS[@]+"${NORMALIZED_COMMAND_ARGS[@]}"}
|
|
285
|
+
else
|
|
286
|
+
# stdin is a character device or unknown - redirect from /dev/null to prevent hanging
|
|
287
|
+
juno-kanban ${NORMALIZED_GLOBAL_FLAGS[@]+"${NORMALIZED_GLOBAL_FLAGS[@]}"} \
|
|
288
|
+
${NORMALIZED_COMMAND_ARGS[@]+"${NORMALIZED_COMMAND_ARGS[@]}"} < /dev/null
|
|
289
|
+
fi
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
# Run main function with all arguments
|
|
293
|
+
main "$@"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "juno-code",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.46",
|
|
4
4
|
"description": "Ralph Wiggum meet Kanban! Ralph style execution for [Claude Code, Codex, Gemini, Cursor]. One task per iteration, automatic progress tracking, and git commits. Set it and let it run.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ralph",
|
|
@@ -40,9 +40,10 @@
|
|
|
40
40
|
],
|
|
41
41
|
"scripts": {
|
|
42
42
|
"dev": "tsx src/bin/cli.ts",
|
|
43
|
-
"build": "tsup && npm run build:copy-templates && npm run build:copy-services && npm run build:copy-wrapper",
|
|
43
|
+
"build": "tsup && npm run build:copy-templates && npm run build:copy-services && npm run build:copy-skills && npm run build:copy-wrapper",
|
|
44
44
|
"build:copy-templates": "node -e \"const fs = require('fs-extra'); const path = require('path'); fs.copySync('src/templates/scripts', 'dist/templates/scripts', { recursive: true }); fs.readdirSync('dist/templates/scripts').filter(f => f.endsWith('.sh')).forEach(f => fs.chmodSync(path.join('dist/templates/scripts', f), 0o755));\"",
|
|
45
45
|
"build:copy-services": "node -e \"const fs = require('fs-extra'); const path = require('path'); const src = 'src/templates/services'; const dest = 'dist/templates/services'; fs.copySync(src, dest, { recursive: true }); const required = ['codex.py','claude.py','gemini.py']; const missing = required.filter(file => !fs.existsSync(path.join(dest, file))); if (missing.length) { throw new Error('Missing required service scripts in dist: ' + missing.join(', ')); } required.forEach(file => fs.chmodSync(path.join(dest, file), 0o755));\"",
|
|
46
|
+
"build:copy-skills": "node -e \"const fs = require('fs-extra'); const src = 'src/templates/skills'; const dest = 'dist/templates/skills'; fs.copySync(src, dest, { recursive: true });\"",
|
|
46
47
|
"build:copy-wrapper": "node -e \"const fs = require('fs-extra'); fs.copySync('src/bin/juno-code.sh', 'dist/bin/juno-code.sh'); fs.chmodSync('dist/bin/juno-code.sh', 0o755);\"",
|
|
47
48
|
"build:watch": "tsup --watch",
|
|
48
49
|
"test": "vitest",
|