Compare commits

..

6 Commits

Author SHA1 Message Date
ffdf5e34c8 Merge pull request 'fix(kugetsu): improve session detection in cmd_start with retry logic and logging' (#107) from fix/start-session-detection into main 2026-04-02 11:41:52 +02:00
shokollm
b3ac73a283 Merge origin/main into fix/start-session-detection
Resolve conflict: use cd approach for worktree, keep retry logic
2026-04-02 09:39:45 +00:00
shokollm
1128b3dfa8 fix(kugetsu): improve session detection in cmd_start with retry logic and logging
- Capture fork output to log file for debugging
- Track fork PID to detect if process exits early
- Retry session detection up to 10 seconds instead of 1 second
- Show fork log output when session creation fails
- Improve error message to indicate timeout
2026-04-02 09:29:30 +00:00
90f46a778a Merge pull request 'fix: use cd + worktree inside parent dir instead of --dir flag (fixes #105)' (#106) from fix/worktree-isolation-via-cd into main 2026-04-02 10:29:32 +02:00
shokollm
ede47439b0 fix: use cd + worktree inside parent dir instead of --dir flag
Issue #105: opencode run --fork/--continue --dir <path> fails to create sessions

Root cause: The --dir flag breaks session creation in opencode. Sessions
fail to be created when --dir is used with --fork or --continue.

Solution: Instead of using --dir flag, create worktrees inside the parent
session's directory and use 'cd $worktree_path && opencode run ...' to
change directory before running opencode.

Key changes:
- Worktrees now created at $PWD/.kugetsu-worktrees/{issue-ref}/ instead
  of $WORKTREES_DIR/{issue-ref}/
- .kugetsu-worktrees is a hidden directory (git ignored by default)
- cmd_start and cmd_continue now use 'cd && opencode run' instead of
  'opencode run --dir'

This approach works because:
1. Worktree is inside parent's directory tree (permission granted)
2. cd properly changes working directory before opencode runs
3. Session gets created with correct directory set
4. No .gitignore entry needed (. prefix makes it hidden from git)
2026-04-02 08:18:17 +00:00
a690788498 Merge pull request 'chore: documentation updates and quick fixes' (#104) from fix/documentation-and-quick-fixes into main 2026-04-02 06:07:13 +02:00

View File

@@ -146,8 +146,9 @@ issue_ref_to_worktree_name() {
issue_ref_to_worktree_path() { issue_ref_to_worktree_path() {
local issue_ref="$1" local issue_ref="$1"
local parent_dir="${2:-$WORKTREES_DIR}"
local worktree_name=$(issue_ref_to_worktree_name "$issue_ref") local worktree_name=$(issue_ref_to_worktree_name "$issue_ref")
echo "$WORKTREES_DIR/$worktree_name" echo "$parent_dir/.kugetsu-worktrees/$worktree_name"
} }
issue_ref_to_branch_name() { issue_ref_to_branch_name() {
@@ -195,13 +196,15 @@ get_repo_url() {
worktree_exists() { worktree_exists() {
local issue_ref="$1" local issue_ref="$1"
local worktree_path=$(issue_ref_to_worktree_path "$issue_ref") local parent_dir="${2:-$PWD}"
local worktree_path=$(issue_ref_to_worktree_path "$issue_ref" "$parent_dir")
[ -d "$worktree_path" ] [ -d "$worktree_path" ]
} }
create_worktree() { create_worktree() {
local issue_ref="$1" local issue_ref="$1"
local worktree_path=$(issue_ref_to_worktree_path "$issue_ref") local parent_dir="${2:-$PWD}"
local worktree_path=$(issue_ref_to_worktree_path "$issue_ref" "$parent_dir")
local branch_name=$(issue_ref_to_branch_name "$issue_ref") local branch_name=$(issue_ref_to_branch_name "$issue_ref")
local repo_url=$(get_repo_url "$issue_ref") local repo_url=$(get_repo_url "$issue_ref")
@@ -211,9 +214,10 @@ create_worktree() {
exit 1 exit 1
fi fi
ensure_worktree_dir local worktree_parent_dir=$(dirname "$worktree_path")
mkdir -p "$worktree_parent_dir"
if worktree_exists "$issue_ref"; then if worktree_exists "$issue_ref" "$parent_dir"; then
echo "Removing existing worktree at '$worktree_path'..." echo "Removing existing worktree at '$worktree_path'..."
git worktree remove "$worktree_path" 2>/dev/null || rm -rf "$worktree_path" git worktree remove "$worktree_path" 2>/dev/null || rm -rf "$worktree_path"
fi fi
@@ -234,9 +238,10 @@ create_worktree() {
remove_worktree_for_issue() { remove_worktree_for_issue() {
local issue_ref="$1" local issue_ref="$1"
local worktree_path=$(issue_ref_to_worktree_path "$issue_ref") local parent_dir="${2:-$PWD}"
local worktree_path=$(issue_ref_to_worktree_path "$issue_ref" "$parent_dir")
if worktree_exists "$issue_ref"; then if worktree_exists "$issue_ref" "$parent_dir"; then
echo "Removing worktree at '$worktree_path'..." echo "Removing worktree at '$worktree_path'..."
git worktree remove "$worktree_path" 2>/dev/null || rm -rf "$worktree_path" git worktree remove "$worktree_path" 2>/dev/null || rm -rf "$worktree_path"
fi fi
@@ -1215,8 +1220,9 @@ cmd_start() {
exit 1 exit 1
fi fi
local worktree_path=$(issue_ref_to_worktree_path "$issue_ref") local parent_dir="$PWD"
create_worktree "$issue_ref" local worktree_path=$(issue_ref_to_worktree_path "$issue_ref" "$parent_dir")
create_worktree "$issue_ref" "$parent_dir"
local session_file="$(issue_ref_to_filename "$issue_ref").json" local session_file="$(issue_ref_to_filename "$issue_ref").json"
@@ -1233,28 +1239,39 @@ cmd_start() {
if [ "$active_count" -ge "$MAX_CONCURRENT_AGENTS" ]; then if [ "$active_count" -ge "$MAX_CONCURRENT_AGENTS" ]; then
echo "Error: Max concurrent agents ($MAX_CONCURRENT_AGENTS) reached" >&2 echo "Error: Max concurrent agents ($MAX_CONCURRENT_AGENTS) reached" >&2
echo "Active sessions: $active_count" >&2 echo "Active sessions: $active_count" >&2
remove_worktree_for_issue "$issue_ref" remove_worktree_for_issue "$issue_ref" "$parent_dir"
exit 1 exit 1
fi fi
local fork_log="$SESSIONS_DIR/$session_file.fork.log"
if [ "$DEBUG_MODE" = true ]; then if [ "$DEBUG_MODE" = true ]; then
opencode run "$message" --fork --session "$base_session_id" --dir "$worktree_path" 2>&1 | tee "$SESSIONS_DIR/$session_file.debug.log" & (cd "$worktree_path" && opencode run "$message" --fork --session "$base_session_id" 2>&1) | tee "$fork_log" &
else else
opencode run "$message" --fork --session "$base_session_id" --dir "$worktree_path" 2>&1 & (cd "$worktree_path" && opencode run "$message" --fork --session "$base_session_id" 2>&1) >> "$fork_log" &
fi fi
# Wait briefly for session to be created local fork_pid=$!
local max_attempts=10
local attempt=1
local new_session_id=""
while [ $attempt -le $max_attempts ]; do
sleep 1 sleep 1
# Find the new session by comparing before/after lists if ! kill -0 $fork_pid 2>/dev/null; then
# Skip any session that existed before the fork and skip base/pm-agent if [ -s "$fork_log" ]; then
local new_session_id="" echo "Fork command exited. Log output:" >&2
tail -20 "$fork_log" >&2
fi
break
fi
while IFS= read -r sess; do while IFS= read -r sess; do
# Skip base and pm-agent
[ "$sess" = "$base_session_id" ] && continue [ "$sess" = "$base_session_id" ] && continue
[ "$sess" = "$pm_agent_session_id" ] && continue [ "$sess" = "$pm_agent_session_id" ] && continue
# Check if this session existed before
local existed_before=false local existed_before=false
for before_sess in "${before_sessions[@]}"; do for before_sess in "${before_sessions[@]}"; do
if [ "$sess" = "$before_sess" ]; then if [ "$sess" = "$before_sess" ]; then
@@ -1269,8 +1286,19 @@ cmd_start() {
fi fi
done < <(opencode session list 2>/dev/null | grep -oP '^ses_\w+') done < <(opencode session list 2>/dev/null | grep -oP '^ses_\w+')
if [ -n "$new_session_id" ]; then
break
fi
attempt=$((attempt + 1))
done
if [ -z "$new_session_id" ]; then if [ -z "$new_session_id" ]; then
echo "Error: Could not find newly created session" >&2 echo "Error: Could not find newly created session after ${max_attempts}s" >&2
if [ -f "$fork_log" ] && [ -s "$fork_log" ]; then
echo "Fork log:" >&2
tail -30 "$fork_log" >&2
fi
remove_worktree_for_issue "$issue_ref" remove_worktree_for_issue "$issue_ref"
exit 1 exit 1
fi fi
@@ -1331,9 +1359,9 @@ cmd_continue() {
if [ -n "$worktree_path" ] && [ -d "$worktree_path" ]; then if [ -n "$worktree_path" ] && [ -d "$worktree_path" ]; then
echo "Using worktree: $worktree_path" echo "Using worktree: $worktree_path"
if [ "$DEBUG_MODE" = true ]; then if [ "$DEBUG_MODE" = true ]; then
opencode run "$message" --continue --session "$opencode_session_id" --dir "$worktree_path" 2>&1 | tee "$session_path.debug.log" & (cd "$worktree_path" && opencode run "$message" --continue --session "$opencode_session_id" 2>&1) | tee "$session_path.debug.log" &
else else
opencode run "$message" --continue --session "$opencode_session_id" --dir "$worktree_path" 2>&1 & (cd "$worktree_path" && opencode run "$message" --continue --session "$opencode_session_id" 2>&1) &
fi fi
else else
if [ "$DEBUG_MODE" = true ]; then if [ "$DEBUG_MODE" = true ]; then