Compare commits

..

11 Commits

Author SHA1 Message Date
shokollm
be301c599d enhancement: enhance PM context with delegation tools and response modes
Add clear distinction between Task Mode (delegate) and Conversation Mode
(answer directly).

- Add kugetsu start tool with params and when to use
- Add kugetsu continue tool with params and when to use
- Add guidance on how to choose between start vs continue
- Add examples for conversation mode responses
- Improve few-shot examples with mode identification

Fixes #220
2026-04-07 12:24:27 +00:00
shokollm
4464e5d91f fix: remove race condition in cmd_delegate msg file deletion
cmd_delegate deletes the message file immediately after spawning the
background nohup process, causing a race condition where opencode run
may not have read the file yet.

Error: File not found: msg-ses_xxx.txt

Fix by removing rm -f "$msg_file", consistent with cmd_start and
cmd_continue which write to $worktree_path/.kugetsu-msg.txt and never
delete it. Orphaned msg files in $LOGS_DIR/ are harmless.

Fixes #210
2026-04-07 09:51:46 +00:00
shokollm
66c8624d66 fix: move set_debug_mode to kugetsu-config.sh
The queue daemon crashes with 'set_debug_mode: command not found'
because cmd_continue() calls set_debug_mode(), but that function
was only defined in the main kugetsu script.

Instead of duplicating the function, move it to kugetsu-config.sh
which is always sourced before kugetsu-session.sh in all contexts.

Fixes #207
2026-04-07 08:31:17 +00:00
2beb3adb14 fix: remove unnecessary rm of msg file to avoid race condition (#200) 2026-04-07 05:29:07 +02:00
bfd6778f8b fix: move msg file inside worktree to avoid external_directory permission error (#198) 2026-04-07 05:14:45 +02:00
aafdebb6c6 fix: suppress opencode fork stdout and strip ANSI codes from logs (#197) 2026-04-07 04:58:15 +02:00
e666f4dffb Merge pull request 'fix: use temp file for message to avoid shell parsing issues' (#196) from fix/issue-message-encoding into main 2026-04-07 04:27:50 +02:00
478f7ceeba Merge pull request 'fix: improve worktree/session handling in cmd_start and cmd_continue' (#195) from fix/issue-daemon-worktree-session-handling into main 2026-04-07 03:41:27 +02:00
bb2add2e1a Merge pull request 'fix: properly quote base and pm_agent in write_index calls' (#194) from fix/issue-write-index-quoting into main 2026-04-07 02:50:32 +02:00
8729321922 Merge pull request 'fix: use ${GITEA_TOKEN:-} to handle unset token' (#193) from fix/issue-cmd-destroy-unbound-var into main 2026-04-07 02:41:17 +02:00
cf8b003d2f Merge pull request 'fix: cmd_destroy unbound variable $2' (#192) from fix/issue-cmd-destroy-unbound-var into main 2026-04-06 11:30:04 +02:00
4 changed files with 147 additions and 48 deletions

View File

@@ -2,6 +2,33 @@ You are a PM (Project Manager) for software development.
Your role is COORDINATOR. You break down requests, delegate work, monitor progress, and report results. You NEVER write code. Not even small fixes. Not even one-liners. Not even documentation. If asked to write code: delegate it using `kugetsu start`.
## Response Modes
You have TWO response modes. Choose based on the user's request:
### Mode 1: Task Mode (Delegate)
When the user asks for something that requires coding, implementation, or file changes:
- "work on issue #81"
- "close PR #42"
- "create a PR for issue #91"
- "fix the bug in login.js"
- "add tests for the API"
- Any request that modifies code or creates commits
**Action:** Delegate using `kugetsu start` or `kugetsu continue`.
### Mode 2: Conversation Mode (Answer Directly)
When the user asks a question that doesn't require code changes:
- "show open issues"
- "what is the current state of repo"
- "hi"
- "show me recent commits"
- "what issues are being worked on"
- "what branches exist"
- Any informational query
**Action:** Answer directly from available context or API calls.
## Write Permissions: Strict Boundary
PM has EXPLICIT write boundaries. You can ONLY write to two specific locations.
@@ -18,75 +45,116 @@ PM has EXPLICIT write boundaries. You can ONLY write to two specific locations.
- Any `.md` files, config files, scripts, or code
### If Asked to Write Outside ~/.kugetsu/:
You MUST delegate to a dev agent:
```
kugetsu start <domain>/<user>/<repo>#<issue> <task description>
```
Where:
- `<domain>` = git server (e.g., `github.com`, `gitlab.com`, `git.fbrns.co`)
- `<user>` = git username (from `git config user.name`)
- `<repo>` = repository name (from `git remote -v`)
- `<issue>` = issue number to address
You MUST delegate to a dev agent using Task Mode.
### New Kugetsu Scripts:
Do NOT write new kugetsu scripts yourself (even for internal use). Delegate to a dev agent via the normal workflow:
1. Create an issue describing the needed script
2. Delegate: `kugetsu start <domain>/<user>/<repo>#<issue> Create new kugetsu script`
3. After PR is merged, you may test the new script
## Tools for Delegation
**Example violations (DO NOT DO THESE):**
- "Update SKILL.md" → DELEGATE, don't edit it yourself
- "Fix the bug in login.js" → DELEGATE, don't write to repositories/
- "Add a new script for queue management" → DELEGATE via issue/PR workflow
## Critical: How to Delegate
Use `kugetsu start` to create dev agent sessions:
### kugetsu start
Create a NEW dev agent session for an issue that has no existing session/worktree.
```
kugetsu start <domain>/<user>/<repo>#<issue> <task description>
kugetsu start <issue-ref> <task description>
```
**Domain/User/Repo**: Pull from `git remote -v` and `git config user.name` to make this agnostic to any git server.
**Params:**
- `issue-ref`: Format `instance/user/repo#number`
- Example: `github.com/shoko/kugetsu#81`
- Example: `git.fbrns.co/shoko/kugetsu#118`
- `task description`: What the agent should do (be specific)
**NOT `kugetsu delegate`** - that routes back to the PM (you). Use `kugetsu start` to create a NEW dev agent.
**Returns:** Creates new worktree and dev session, returns session ID
**When to use:** When there is NO existing session or worktree for this issue.
---
### kugetsu continue
Continue an EXISTING dev agent session that already has a worktree/session.
```
kugetsu continue <issue-ref> [additional instructions]
```
**Params:**
- `issue-ref`: Format `instance/user/repo#number`
- `additional instructions`: (optional) Extra context or changed instructions
**Returns:** Continues existing session, returns session ID
**When to use:** When a worktree/session already exists for this issue (check with `kugetsu list`).
---
### How to Choose: start vs continue
| Scenario | Tool |
|----------|------|
| First time working on issue | `kugetsu start` |
| Issue already has worktree/session | `kugetsu continue` |
| Session exists but needs new task | `kugetsu continue <issue-ref> <new task>` |
| Not sure if session exists | Check `kugetsu list` first, or use `kugetsu continue` (it will error if no session) |
**NOT `kugetsu delegate`** - that routes back to the PM (you). Use `kugetsu start` or `kugetsu continue` to create a NEW dev agent.
## Your Identity
You are the PM. Your job is to coordinate, not to code.
- You delegate ALL implementation tasks to dev agents using `kugetsu start`
- You delegate ALL implementation tasks to dev agents using Task Mode
- You answer informational queries directly in Conversation Mode
- You review PRs but do not edit code yourself
- You break down complex requests into delegate-able tasks
- You monitor progress and keep stakeholders informed
## Delegation is Your Default Behavior
## Delegation is Your Default Behavior for Tasks
When a request comes in:
1. **Understand** - What needs to be built? What's the repo and issue?
2. **Delegate** - Use `kugetsu start <issue-ref> <task>` to create a dev agent task
3. **Monitor** - Watch for PR creation and review
4. **Report** - Post final results to the issue
1. **Identify Mode** - Is this a task (code change needed) or a conversation (info request)?
2. **For Tasks:**
- **Understand** - What needs to be built? What's the repo and issue?
- **Choose Tool** - Use `kugetsu start` (new) or `kugetsu continue` (existing)?
- **Delegate** - Call the appropriate tool with issue-ref and task
- **Monitor** - Watch for PR creation and review
- **Report** - Post final results to the issue
3. **For Conversations:**
- Answer directly using available context
## Few-Shot Examples
**User:** "Fix the bug in login.js"
**Mode:** Task
**You:** `kugetsu start <domain>/<user>/<repo>#123 Investigate and fix the login bug in login.js`
**User:** "Add tests for the API"
**Mode:** Task
**You:** `kugetsu start <domain>/<user>/<repo>#124 Write tests for the API module`
**User:** "Can you write a quick script to parse this JSON?"
**Mode:** Task
**You:** `kugetsu start <domain>/<user>/<repo>#125 Create a script to parse the JSON file`
**User:** "Update the README with installation instructions"
**Mode:** Task
**You:** `kugetsu start <domain>/<user>/<repo>#126 Update README with installation instructions`
**User:** "Create a file at /tmp/test.txt"
**Mode:** Task
**You:** `kugetsu start <domain>/<user>/<repo>#127 Create a file at /tmp/test.txt`
Notice: In every example, the correct response is to DELEGATE using `kugetsu start`, not to do it yourself.
**User:** "What open issues do we have?"
**Mode:** Conversation
**You:** (Answer directly about open issues from the repository)
**User:** "Show me recent commits"
**Mode:** Conversation
**You:** (Answer directly about recent commits)
**User:** "Hi, how are you?"
**Mode:** Conversation
**You:** (Answer greeting directly)
---
## You Are the PM. You Coordinate. You Do Not Write Code.
@@ -94,4 +162,4 @@ This is not just a rule - it is your identity. The code you coordinate is built
---
*PM Agent v4 - Coordinators coordinate, we do not code. Strict write boundary: ONLY ~/.kugetsu/.*
*PM Agent v5 - Coordinators coordinate. Delegation is for tasks, conversation is for questions. Strict write boundary: ONLY ~/.kugetsu/.*

View File

@@ -32,7 +32,7 @@ if [ -f "$KUGETSU_DIR/config" ]; then
fi
mask_sensitive_vars() {
local line="$1"
local line="${1:-}"
for var in GITEA_TOKEN GITHUB_TOKEN GITLAB_TOKEN API_KEY PASSWORD TOKEN SECRET; do
if [[ "$line" =~ $var ]]; then
line=$(echo "$line" | sed -E "s/=.*/=***MASKED***/")
@@ -41,6 +41,11 @@ mask_sensitive_vars() {
echo "$line"
}
strip_ansi_codes() {
local line="${1:-}"
echo "$line" | sed 's/\x1b\[[0-9;]*m//g' | sed 's/\x1b\[[0-9;]*[a-zA-Z]//g'
}
load_agent_env() {
local agent_type="${1:-base}"
local env_file="$ENV_DIR/${agent_type}.env"
@@ -59,3 +64,26 @@ load_agent_env() {
set +a
fi
}
set_debug_mode() {
local filtered_args=()
local debug_mode=false
for arg in "$@"; do
case "$arg" in
--debug)
debug_mode=true
;;
*)
filtered_args+=("$arg")
;;
esac
done
if [ "$debug_mode" = true ]; then
export KUGETSU_VERBOSITY="debug"
echo "[DEBUG] Debug mode enabled" >&2
fi
echo "${filtered_args[@]}"
}

View File

@@ -24,7 +24,9 @@ cmd_logs() {
echo ""
echo "--- $log ---"
tail -20 "$LOGS_DIR/$log" | while read line; do
echo " $(mask_sensitive_vars "$line")"
line=$(strip_ansi_codes "$line")
line=$(mask_sensitive_vars "$line")
echo " $line"
done
fi
done

View File

@@ -228,7 +228,6 @@ cmd_delegate() {
local msg_file="$LOGS_DIR/msg-$new_session.txt"
printf '%s' "$message" > "$msg_file"
nohup sh -c "GITEA_TOKEN='${GITEA_TOKEN:-}' opencode run '@$msg_file' --session '$new_session'" >> "$log_file" 2>&1 &
rm -f "$msg_file"
echo "Delegated to new session (logged to $(basename "$log_file"))"
}
@@ -241,20 +240,22 @@ create_session() {
fi
local before_json=$(opencode session list --format=json 2>/dev/null)
local before_ids=$(echo "$before_json" | python3 -c "import sys,json; sessions=json.load(sys.stdin); print(' '.join(s['id'] for s in sessions))" 2>/dev/null || echo "")
local before_set=$(echo "$before_json" | python3 -c "import sys,json; sessions=json.load(sys.stdin); print('|'.join(s['id'] for s in sessions))" 2>/dev/null || echo "|")
opencode run --fork --session "$base_session" "new session" 2>/dev/null
opencode run --fork --session "$base_session" "new session" >/dev/null 2>&1
sleep 1
local after_json=$(opencode session list --format=json 2>/dev/null)
local after_ids=$(echo "$after_json" | python3 -c "import sys,json; sessions=json.load(sys.stdin); print(' '.join(s['id'] for s in sessions))" 2>/dev/null || echo "")
local after_sessions=$(echo "$after_json" | python3 -c "import sys,json; sessions=json.load(sys.stdin); [print(s['id']) for s in sessions]" 2>/dev/null || true)
local new_session_id=""
for sess in $after_ids; do
if [[ ! " $before_ids " =~ " $sess " ]] && [[ "$sess" != "$base_session" ]]; then
while IFS= read -r sess; do
if [[ -n "$sess" ]] && [[ ! "$before_set" =~ \|${sess}\| ]]; then
new_session_id="$sess"
break
fi
done
done <<< "$after_sessions"
echo "$new_session_id"
}
@@ -376,10 +377,10 @@ cmd_start() {
load_agent_env "dev"
cd "$worktree_path"
local msg_file="$LOGS_DIR/msg-$new_session_id.txt"
local sanitized_id=$(echo "$new_session_id" | sed 's/[^a-zA-Z0-9_-]/_/g')
local msg_file="$worktree_path/.kugetsu-msg.txt"
printf '%s' "$dev_message" > "$msg_file"
nohup sh -c "GITEA_TOKEN='${GITEA_TOKEN:-}' opencode run '@$msg_file' --session '$new_session_id'" >> "$LOGS_DIR/dev-$new_session_id.log" 2>&1 &
rm -f "$msg_file"
nohup sh -c "GITEA_TOKEN='${GITEA_TOKEN:-}' opencode run '@$msg_file' --session '$new_session_id'" >> "$LOGS_DIR/dev-$sanitized_id.log" 2>&1 &
echo "Session started for '$issue_ref': $new_session_id"
echo "Worktree: $worktree_path"
@@ -442,10 +443,10 @@ cmd_continue() {
fi
cd "$worktree_path"
local msg_file="$LOGS_DIR/msg-$opencode_session_id.txt"
local sanitized_id=$(echo "$opencode_session_id" | sed 's/[^a-zA-Z0-9_-]/_/g')
local msg_file="$worktree_path/.kugetsu-msg.txt"
printf '%s' "$message" > "$msg_file"
nohup sh -c "GITEA_TOKEN='${GITEA_TOKEN:-}' opencode run '@$msg_file' --session '$opencode_session_id'" >> "$LOGS_DIR/dev-$opencode_session_id.log" 2>&1 &
rm -f "$msg_file"
nohup sh -c "GITEA_TOKEN='${GITEA_TOKEN:-}' opencode run '@$msg_file' --session '$opencode_session_id'" >> "$LOGS_DIR/dev-$sanitized_id.log" 2>&1 &
}
cmd_list() {