Compare commits

...

7 Commits

Author SHA1 Message Date
shokollm
416e8e5757 fix(kugetsu): destroy --base now also deletes PM agent session
When destroying base session, we now also delete the PM agent session
and all issue session files. This ensures clean slate on re-init.
2026-04-02 14:47:40 +00:00
1c1d18b9ae Merge pull request 'fix(kugetsu): init creates base session in ~/.kugetsu-worktrees and adds context to forked sessions' (#114) from fix/session-context-and-init-worktree into main 2026-04-02 16:35:12 +02:00
shokollm
8c639e2928 fix(kugetsu): init creates base session in ~/.kugetsu-worktrees, adds context to forked sessions, and clears logs
1. Init: cd to ~/.kugetsu-worktrees before creating base session
   This keeps all worktrees inside a predictable directory structure
   and avoids external_directory permission issues

2. Init: Clear old logs but keep repos.json, config, and env files

3. Fork context: Add kugetsu_get_fork_context() that provides:
   - Important working rules (stop on error, don't pivot)
   - Repository configuration from repos.json
   - Environment file location info

4. Fork message: Prepend context to user message when forking session
2026-04-02 14:32:07 +00:00
c4c3556247 Merge pull request 'fix(kugetsu): destroy --base and --pm-agent actually delete opencode sessions' (#113) from fix/destroy-removes-opencode-session into main 2026-04-02 15:30:48 +02:00
shokollm
4342347ac6 fix(kugetsu): destroy --base and --pm-agent actually delete opencode sessions
Previously destroy only removed local session files but didn't delete
the sessions from opencode's database. This caused init to reuse the
same session with old context.

Now destroy calls 'opencode session delete <id>' to properly remove
the session from opencode.
2026-04-02 13:28:47 +00:00
7888a34bd9 Merge pull request 'fix(kugetsu): warn if init run from non-empty directory' (#112) from fix/init-directory-warning into main 2026-04-02 15:21:30 +02:00
shokollm
e2a37cdbb9 fix(kugetsu): warn if init run from non-empty directory
Warn users if running kugetsu init from a directory with files or
git repository. This prevents project context from contaminating the
base session, which causes forked sessions to have unwanted context.
2026-04-02 13:19:49 +00:00

View File

@@ -394,6 +394,41 @@ kugetsu_get_pm_context() {
fi fi
} }
kugetsu_get_fork_context() {
local issue_ref="$1"
local context=""
context="## IMPORTANT WORKING RULES
1. You are working on issue: $issue_ref
2. If you encounter ANY error, blocker, or cannot complete the task:
- STOP immediately
- Log what happened and why you cannot proceed
- Do NOT switch to other work or try alternative approaches
3. Do NOT work on other issues or PRs unless explicitly asked
4. Environment variables are available in ~/.kugetsu/env/
"
if [ -f "$REPOS_CONFIG" ]; then
context="${context}
## REPOSITORIES CONFIG
$(cat "$REPOS_CONFIG")
"
fi
if [ -f "$ENV_DIR/default.env" ]; then
context="${context}
## ENVIRONMENT (available at ~/.kugetsu/env/)
Environment file exists at: $ENV_DIR/default.env
Source it with: source ~/.kugetsu/env/default.env
"
fi
echo "$context"
}
kugetsu_add_notification() { kugetsu_add_notification() {
local type="$1" local type="$1"
local message="$2" local message="$2"
@@ -1088,6 +1123,11 @@ EOF
echo "Created pm-agent env file: $ENV_DIR/pm-agent.env" echo "Created pm-agent env file: $ENV_DIR/pm-agent.env"
fi fi
if [ -d "$LOGS_DIR" ]; then
echo "Cleaning up old logs..."
rm -rf "$LOGS_DIR"/*.log 2>/dev/null || true
fi
local existing_base=$(get_base_session_id) local existing_base=$(get_base_session_id)
local existing_pm=$(get_pm_agent_session_id) local existing_pm=$(get_pm_agent_session_id)
@@ -1107,6 +1147,29 @@ EOF
exit 1 exit 1
fi fi
local init_worktree_dir="$HOME/.kugetsu-worktrees"
mkdir -p "$init_worktree_dir"
cd "$init_worktree_dir"
echo "Initialized kugetsu worktrees directory: $init_worktree_dir"
echo "Base session will be created in this directory."
echo ""
local cwd_files=$(ls -A "$PWD" 2>/dev/null | wc -l)
local cwd_git=$(git rev-parse --is-inside-work-tree 2>/dev/null || echo "false")
if [ "$cwd_files" -gt 0 ] || [ "$cwd_git" = "true" ]; then
echo "Warning: Worktrees directory is not empty: $PWD" >&2
echo "This may cause project context to contaminate the base session." >&2
echo "Consider running kugetsu destroy --base -y and reinitializing." >&2
echo "" >&2
echo "Files in current directory: $cwd_files" >&2
if [ "$cwd_git" = "true" ]; then
echo "Git repository detected: $(git rev-parse --show-toplevel 2>/dev/null || echo 'unknown')" >&2
fi
echo "" >&2
echo "Press Ctrl+C to cancel or wait 5 seconds to continue anyway..." >&2
sleep 5
fi
echo "Starting TUI to create base session..." echo "Starting TUI to create base session..."
echo "Press Ctrl+C to cancel or wait for session to be created" echo "Press Ctrl+C to cancel or wait for session to be created"
sleep 2 sleep 2
@@ -1240,12 +1303,20 @@ cmd_start() {
local fork_log="$SESSIONS_DIR/$session_file.fork.log" local fork_log="$SESSIONS_DIR/$session_file.fork.log"
local opencode_db="${OPENCODE_DB:-$HOME/.local/share/opencode/opencode.db}" local opencode_db="${OPENCODE_DB:-$HOME/.local/share/opencode/opencode.db}"
> "$fork_log"
local fork_context=$(kugetsu_get_fork_context "$issue_ref")
local full_message="${fork_context}
## YOUR TASK
$message"
fix_session_permissions fix_session_permissions
if [ "$DEBUG_MODE" = true ]; then if [ "$DEBUG_MODE" = true ]; then
(cd "$worktree_path" && opencode run "$message" --fork --session "$base_session_id" 2>&1) | tee "$fork_log" & (cd "$worktree_path" && opencode run "$full_message" --fork --session "$base_session_id" --dir "$worktree_path" 2>&1) | tee "$fork_log" &
else else
(cd "$worktree_path" && opencode run "$message" --fork --session "$base_session_id" 2>&1) >> "$fork_log" & (cd "$worktree_path" && opencode run "$full_message" --fork --session "$base_session_id" --dir "$worktree_path" 2>&1) >> "$fork_log" &
fi fi
local fork_pid=$! local fork_pid=$!
@@ -1371,9 +1442,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
(cd "$worktree_path" && opencode run "$message" --continue --session "$opencode_session_id" 2>&1) | tee "$session_path.debug.log" & opencode run "$message" --continue --session "$opencode_session_id" --dir "$worktree_path" 2>&1 | tee "$session_path.debug.log" &
else else
(cd "$worktree_path" && opencode run "$message" --continue --session "$opencode_session_id" 2>&1) & opencode run "$message" --continue --session "$opencode_session_id" --dir "$worktree_path" 2>&1 &
fi fi
else else
if [ "$DEBUG_MODE" = true ]; then if [ "$DEBUG_MODE" = true ]; then
@@ -1530,15 +1601,22 @@ cmd_destroy() {
if [ "$target" = "base" ]; then if [ "$target" = "base" ]; then
if [ "$force" = true ]; then if [ "$force" = true ]; then
local base_session_id=$(get_base_session_id)
local pm_agent_session_id=$(get_pm_agent_session_id)
rm -f "$SESSIONS_DIR/base.json" rm -f "$SESSIONS_DIR/base.json"
local pm_agent=$(get_pm_agent_session_id)
if [ -n "$pm_agent" ] && [ "$pm_agent" != "null" ]; then
rm -f "$SESSIONS_DIR/pm-agent.json" rm -f "$SESSIONS_DIR/pm-agent.json"
rm -f "$SESSIONS_DIR/issue-"*.json 2>/dev/null || true
echo '{"base": null, "pm_agent": null, "issues": {}}' > "$INDEX_FILE" echo '{"base": null, "pm_agent": null, "issues": {}}' > "$INDEX_FILE"
else
echo '{"base": null, "pm_agent": null, "issues": {}}' > "$INDEX_FILE" if [ -n "$base_session_id" ] && [ "$base_session_id" != "null" ]; then
echo "Deleting base session: $base_session_id"
opencode session delete "$base_session_id" 2>/dev/null || echo "Warning: Could not delete base session"
fi fi
echo "Base session destroyed" if [ -n "$pm_agent_session_id" ] && [ "$pm_agent_session_id" != "null" ]; then
echo "Deleting PM agent session: $pm_agent_session_id"
opencode session delete "$pm_agent_session_id" 2>/dev/null || echo "Warning: Could not delete PM agent session"
fi
echo "Base and PM agent sessions destroyed"
else else
echo "Error: destroying base session requires --base -y" >&2 echo "Error: destroying base session requires --base -y" >&2
exit 1 exit 1
@@ -1548,6 +1626,7 @@ cmd_destroy() {
if [ "$target" = "pm-agent" ]; then if [ "$target" = "pm-agent" ]; then
if [ "$force" = true ]; then if [ "$force" = true ]; then
local pm_session_id=$(get_pm_agent_session_id)
rm -f "$SESSIONS_DIR/pm-agent.json" rm -f "$SESSIONS_DIR/pm-agent.json"
local base=$(get_base_session_id) local base=$(get_base_session_id)
if [ -n "$base" ] && [ "$base" != "null" ]; then if [ -n "$base" ] && [ "$base" != "null" ]; then
@@ -1555,6 +1634,10 @@ cmd_destroy() {
else else
write_index "null" "null" "{}" write_index "null" "null" "{}"
fi fi
if [ -n "$pm_session_id" ] && [ "$pm_session_id" != "null" ]; then
echo "Deleting opencode session: $pm_session_id"
opencode session delete "$pm_session_id" 2>/dev/null || echo "Warning: Could not delete session from opencode (may already be deleted)"
fi
echo "PM agent session destroyed" echo "PM agent session destroyed"
else else
echo "Error: destroying pm-agent session requires --pm-agent -y" >&2 echo "Error: destroying pm-agent session requires --pm-agent -y" >&2