From 60181afe6a5a2c45be93f4d13ac0e3639d9b4e2c Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Mon, 30 Mar 2026 14:07:43 +0000 Subject: [PATCH 01/14] feat(phase3a): initial Chat Agent infrastructure Phase 3a implementation - Hermes Chat Agent configuration: - kugetsu-chat/SOUL.md - Chat Agent persona and routing logic - kugetsu-chat/SKILL.md - Chat Agent skill documentation - kugetsu-chat/scripts/setup - Configuration setup script - kugetsu-pm/SKILL.md - PM Agent skill documentation - kugetsu-helpers/SKILL.md - Helper tools for Hermes-kugetsu integration - kugetsu-helpers/scripts/kugetsu-helpers - Shell functions for delegation Provides: - Intent classification (small talk, task, status, mode change) - PM Agent delegation via terminal() - kugetsu status checking - Session management helpers --- skills/kugetsu-chat/SKILL.md | 170 ++++++++++++++ skills/kugetsu-chat/SOUL.md | 110 +++++++++ skills/kugetsu-chat/scripts/setup | 194 ++++++++++++++++ skills/kugetsu-helpers/SKILL.md | 166 +++++++++++++ .../kugetsu-helpers/scripts/kugetsu-helpers | 148 ++++++++++++ skills/kugetsu-pm/SKILL.md | 218 ++++++++++++++++++ 6 files changed, 1006 insertions(+) create mode 100644 skills/kugetsu-chat/SKILL.md create mode 100644 skills/kugetsu-chat/SOUL.md create mode 100755 skills/kugetsu-chat/scripts/setup create mode 100644 skills/kugetsu-helpers/SKILL.md create mode 100755 skills/kugetsu-helpers/scripts/kugetsu-helpers create mode 100644 skills/kugetsu-pm/SKILL.md diff --git a/skills/kugetsu-chat/SKILL.md b/skills/kugetsu-chat/SKILL.md new file mode 100644 index 0000000..7a8077f --- /dev/null +++ b/skills/kugetsu-chat/SKILL.md @@ -0,0 +1,170 @@ +--- +name: kugetsu-chat +description: Chat Agent skill for kugetsu Phase 3. Handles Telegram routing, PM delegation, and notification coordination. +license: MIT +compatibility: Requires Hermes agent with Telegram configured, kugetsu CLI, opencode sessions. +metadata: + author: shoko + version: "1.0" +--- + +# kugetsu-chat - Chat Agent for Kugetsu Phase 3 + +Handles natural language routing and PM Agent coordination for Telegram interface. + +## Overview + +The Chat Agent is Hermes configured with a specific SOUL.md and skills that enable: +- Receiving Telegram messages +- Intent classification (small talk, task, status, clarification) +- Routing to PM Agent when needed +- Notification coordination + +## Architecture + +``` +User (Telegram) → Hermes (Chat Agent) + ├── Small talk → Respond directly + ├── Task request → Route to PM Agent + ├── Status query → Route to PM Agent + └── Clarification → Ask via Hermes → User +``` + +## Intent Classification + +### Rules + +| Intent | Examples | Response | +|--------|----------|----------| +| **Small talk** | "hi", "thanks", "how are you" | Respond directly, clear context if unrelated | +| **Task request** | "fix issue #5", "create test for #14" | Route to PM Agent | +| **Status query** | "status?", "what's on #7?" | Route to PM Agent | +| **Mode change** | "pm notify", "pm silent" | Route to PM Agent | +| **Clarification** | "which project?", "what repo?" | Ask user via Hermes | + +### Routing Logic + +``` +1. Receive message +2. Classify intent: + - If small talk → respond directly + - If task/status/mode → delegate to PM Agent +3. If PM response needed → send to PM Agent +4. Return PM response to user +``` + +## PM Agent Delegation + +### How Hermes Delegates to PM Agent + +Hermes uses `terminal()` to interact with the PM Agent opencode session: + +```bash +# Get PM agent session ID +PM_SESSION=$(cat ~/.kugetsu/index.json | python3 -c "import sys,json; print(json.load(sys.stdin).get('pm_agent', ''))") + +# Continue PM agent session with task +opencode run --continue --session "$PM_SESSION" "User request: $MESSAGE" +``` + +### PM Agent Modes + +| Mode | Behavior | Storage | +|------|----------|---------| +| **notify** (default) | PM sends completion notifications | Session context | +| **silent** | PM works quietly, no notifications | Session context | + +Toggle with: "pm notify" / "pm silent" + +## Notification Flow + +``` +PM Agent completes task + → Checks mode + → If notify → Routes via Hermes → Telegram message to user + → If silent → No notification +``` + +## Session Context + +### Chat Agent Context +- Short-term conversation memory +- User preferences +- Last routing decision + +### PM Agent Context +- Managed repositories +- Active tasks +- Notification preferences +- Long-term project memory + +## Skills + +### kugetsu-chat-skill + +Defines Chat Agent behavior: +- Intent classification prompt +- Routing rules +- Response formatting + +### kugetsu-pm-skill (for PM Agent session) + +Defines PM Agent behavior: +- Task coordination +- Gitea integration +- Notification handling + +## Implementation Notes + +### Hermes Gateway + +Hermes gateway must be running: +```bash +hermes gateway start +``` + +Or run interactively: +```bash +hermes gateway run +``` + +### kugetsu init + +Before using chat, ensure kugetsu is initialized: +```bash +kugetsu init +``` + +This creates: +- Base session +- PM agent session + +### PM Agent Session + +The PM agent session ID is stored in: +``` +~/.kugetsu/index.json → "pm_agent" field +``` + +## Troubleshooting + +### Hermes not receiving Telegram messages +1. Check `hermes gateway status` +2. Verify Telegram bot token in config +3. Ensure bot has been started by user + +### PM Agent not responding +1. Check `kugetsu list` shows pm-agent +2. Verify pm-agent session is running: `opencode session list` +3. Check PM agent logs + +### Routing not working +1. Check intent classification in Hermes context +2. Verify kugetsu is initialized +3. Check PM agent session is accessible + +## Related Documentation + +- [kugetsu-architecture.md](../../docs/kugetsu-architecture.md) +- [kugetsu-chat-architecture.md](../../docs/kugetsu-chat.md) +- [telegram-setup.md](../../docs/telegram-setup.md) \ No newline at end of file diff --git a/skills/kugetsu-chat/SOUL.md b/skills/kugetsu-chat/SOUL.md new file mode 100644 index 0000000..3b1a68d --- /dev/null +++ b/skills/kugetsu-chat/SOUL.md @@ -0,0 +1,110 @@ +# Kugetsu Chat Agent SOUL + +You are the Kugetsu Chat Agent - a friendly gateway between users and their agent team via Telegram. + +## Your Role + +You serve as the **first point of contact** for users messaging on Telegram. You: + +1. **Receive** messages from users via Telegram +2. **Classify** the intent of each message +3. **Respond** to small talk directly +4. **Route** task requests and status queries to the PM Agent +5. **Relay** PM Agent responses back to users + +## Intent Classification + +### Message Types + +| Type | Indicators | Your Action | +|------|------------|-------------| +| **Small talk** | greetings, thanks, casual conversation | Respond directly | +| **Task request** | "fix", "create", "implement", issue numbers | Route to PM Agent | +| **Status query** | "status", "progress", "what's on", "done?" | Route to PM Agent | +| **Mode command** | "pm notify", "pm silent" | Route to PM Agent | +| **Clarification** | Questions about which project/repo | Ask user for clarification | + +### Classification Examples + +``` +"hi there" → Small talk (respond directly) +"thanks!" → Small talk (respond directly) +"fix issue #5" → Task request (route to PM) +"what's on #14?" → Status query (route to PM) +"status?" → Status query (route to PM) +"pm silent" → Mode command (route to PM) +"which project?" → Clarification (ask user) +``` + +## Routing to PM Agent + +When you need to route to the PM Agent: + +### Step 1: Get PM Agent Session + +```bash +PM_SESSION=$(cat ~/.kugetsu/index.json | python3 -c "import sys,json; print(json.load(sys.stdin).get('pm_agent', ''))") +``` + +### Step 2: Delegate Task + +Use `terminal()` to continue the PM Agent session: + +``` +terminal(command="opencode run --continue --session $PM_SESSION 'User request: '", timeout=120) +``` + +### Step 3: Relay Response + +Return the PM Agent's response to the user via Telegram. + +## Response Guidelines + +### Small Talk +- Be friendly and conversational +- Keep responses brief +- Use emojis sparingly + +### PM Agent Responses +- Relay exactly what PM Agent says +- Don't add your own commentary unless helpful +- Format for Telegram (short messages preferred) + +### Clarification Requests +- Be specific about what's unclear +- Offer options when possible +- Example: "Which repository? github.com/shoko/kugetsu or gitlab.com/team/project?" + +## Error Handling + +### PM Agent Unavailable +If PM Agent session is not found or unresponsive: +- Check kugetsu is initialized: `kugetsu list` +- Try to restart PM Agent if needed +- Inform user if persistent issues + +### Routing Failures +- Log the error +- Inform user: "I'm having trouble reaching the PM Agent. Please try again." +- Suggest checking `kugetsu list` if persistent + +## Tone and Style + +- **Friendly but professional** +- **Concise** - Telegram users prefer short messages +- **Helpful** - Offer guidance when users seem stuck +- **Patient** - Some users may not be familiar with the system + +## Security Notes + +- Never reveal internal session IDs to users +- Don't expose file paths or system details +- Keep responses user-friendly, not technical + +## Remember + +You are the **face of the system** on Telegram. Users will judge kugetsu based on their interactions with you. Be the best first impression! + +--- + +*Last updated: 2026-03-30 for Phase 3a implementation* \ No newline at end of file diff --git a/skills/kugetsu-chat/scripts/setup b/skills/kugetsu-chat/scripts/setup new file mode 100755 index 0000000..94f6dbb --- /dev/null +++ b/skills/kugetsu-chat/scripts/setup @@ -0,0 +1,194 @@ +#!/bin/bash +# kugetsu-chat setup script +# Configures Hermes as Chat Agent for Phase 3a + +set -euo pipefail + +KUGETSU_CHAT_DIR="$(dirname "$(dirname "$(readlink -f "$0")")")" +HERMES_DIR="${HERMES_DIR:-$HOME/.hermes}" + +usage() { + cat << 'EOF' +kugetsu-chat setup - Configure Hermes as Chat Agent + +Usage: + kugetsu-chat-setup.sh [--apply] [--check] + +Options: + --apply Apply the Chat Agent configuration to Hermes + --check Verify configuration without applying + +Examples: + ./kugetsu-chat-setup.sh --check # Check configuration + ./kugetsu-chat-setup.sh --apply # Apply configuration + +EOF +} + +check_prerequisites() { + echo "=== Checking Prerequisites ===" + + if ! command -v hermes &> /dev/null; then + echo "Error: Hermes is not installed or not in PATH" + exit 1 + fi + echo "✓ Hermes is installed" + + if ! command -v kugetsu &> /dev/null; then + echo "Error: kugetsu is not installed or not in PATH" + exit 1 + fi + echo "✓ kugetsu is installed" + + if [ ! -f "$HERMES_DIR/config.yaml" ]; then + echo "Error: Hermes config not found at $HERMES_DIR/config.yaml" + exit 1 + fi + echo "✓ Hermes config exists" + + echo "" +} + +verify_kugetsu_init() { + echo "=== Verifying kugetsu Initialization ===" + + if [ ! -f "$HOME/.kugetsu/index.json" ]; then + echo "Error: kugetsu not initialized. Run 'kugetsu init' first." + exit 1 + fi + + if ! grep -q '"pm_agent"' "$HOME/.kugetsu/index.json"; then + echo "Error: kugetsu index.json missing pm_agent field" + exit 1 + fi + + PM_AGENT=$(python3 -c "import json; print(json.load(open('$HOME/.kugetsu/index.json')).get('pm_agent', ''))" 2>/dev/null || echo "") + if [ -z "$PM_AGENT" ] || [ "$PM_AGENT" = "null" ]; then + echo "Error: PM agent session not initialized. Run 'kugetsu init' first." + exit 1 + fi + + echo "✓ kugetsu is initialized with PM agent: $PM_AGENT" + echo "" +} + +verify_telegram_config() { + echo "=== Verifying Telegram Configuration ===" + + if ! grep -q "TELEGRAM_HOME_CHANNEL" "$HERMES_DIR/config.yaml"; then + echo "Warning: TELEGRAM_HOME_CHANNEL not found in Hermes config" + echo " Telegram may not be configured. Run 'hermes gateway setup' to configure." + else + echo "✓ Telegram is configured in Hermes" + fi + + echo "" +} + +install_soul() { + echo "=== Installing Chat Agent SOUL ===" + + SOUL_SOURCE="$KUGETSU_CHAT_DIR/SOUL.md" + SOUL_TARGET="$HERMES_DIR/SOUL-chat.md" + + if [ ! -f "$SOUL_SOURCE" ]; then + echo "Error: SOUL.md not found at $SOUL_SOURCE" + exit 1 + fi + + cp "$SOUL_SOURCE" "$SOUL_TARGET" + echo "✓ Copied SOUL.md to $SOUL_TARGET" + + echo "" +} + +install_skill() { + echo "=== Installing kugetsu-chat Skill ===" + + SKILL_SOURCE="$KUGETSU_CHAT_DIR" + SKILL_TARGET="$HERMES_DIR/skills/kugetsu-chat" + + if [ -L "$SKILL_TARGET" ]; then + rm "$SKILL_TARGET" + elif [ -d "$SKILL_TARGET" ]; then + echo "Warning: $SKILL_TARGET already exists (not a symlink)" + fi + + ln -sf "$SKILL_SOURCE" "$SKILL_TARGET" + echo "✓ Linked skill to $SKILL_TARGET" + + echo "" +} + +apply_config() { + echo "=== Applying Chat Agent Configuration ===" + + check_prerequisites + verify_kugetsu_init + verify_telegram_config + install_soul + install_skill + + echo "=== Configuration Complete ===" + echo "" + echo "Next steps:" + echo "1. Run 'hermes gateway' to start the Telegram gateway" + echo "2. Or run 'hermes' to use Chat Agent in CLI mode" + echo "" + echo "The Chat Agent will:" + echo "- Receive Telegram messages" + echo "- Handle small talk directly" + echo "- Route task requests to PM Agent" + echo "- Relay PM Agent responses back" +} + +check_config() { + echo "=== Checking Chat Agent Configuration ===" + echo "" + + check_prerequisites + verify_kugetsu_init + verify_telegram_config + + SOUL_TARGET="$HERMES_DIR/SOUL-chat.md" + if [ -f "$SOUL_TARGET" ]; then + echo "✓ Chat Agent SOUL is installed" + else + echo "○ Chat Agent SOUL not installed (run with --apply)" + fi + + SKILL_TARGET="$HERMES_DIR/skills/kugetsu-chat" + if [ -L "$SKILL_TARGET" ]; then + echo "✓ kugetsu-chat skill is linked" + else + echo "○ kugetsu-chat skill not linked (run with --apply)" + fi + + echo "" +} + +main() { + if [ $# -eq 0 ]; then + usage + exit 1 + fi + + case "$1" in + --apply) + apply_config + ;; + --check) + check_config + ;; + -h|--help) + usage + ;; + *) + echo "Error: Unknown option '$1'" + usage + exit 1 + ;; + esac +} + +main "$@" \ No newline at end of file diff --git a/skills/kugetsu-helpers/SKILL.md b/skills/kugetsu-helpers/SKILL.md new file mode 100644 index 0000000..899f7d1 --- /dev/null +++ b/skills/kugetsu-helpers/SKILL.md @@ -0,0 +1,166 @@ +--- +name: kugetsu-helpers +description: Helper tools for Hermes to interact with kugetsu. Provides routing, delegation, and status functions. +license: MIT +compatibility: Requires Hermes agent, kugetsu CLI, opencode sessions. +metadata: + author: shoko + version: "1.0" +--- + +# kugetsu-helpers - Hermes Tools for Kugetsu + +Provides tools/functions for Hermes to route messages and delegate to the PM Agent. + +## Overview + +This skill enables Hermes (as Chat Agent) to interact with kugetsu-managed opencode sessions. + +## Tools + +### kugetsu_get_pm_session + +Gets the PM Agent session ID from kugetsu index. + +```bash +kugetsu_get_pm_session +``` + +**Returns:** PM agent session ID string, or empty if not initialized + +**Example:** +``` +PM_SESSION=$(kugetsu_get_pm_session) +echo "PM Agent: $PM_SESSION" +``` + +### kugetsu_delegate_to_pm + +Delegates a task to the PM Agent via opencode. + +```bash +kugetsu_delegate_to_pm "" +``` + +**Arguments:** +- `task message`: The task to delegate (e.g., "fix issue #5") + +**Returns:** PM Agent response (may be multi-line) + +**Example:** +``` +kugetsu_delegate_to_pm "User wants to fix issue #5 in github.com/shoko/kugetsu" +``` + +### kugetsu_check_status + +Checks kugetsu initialization status. + +```bash +kugetsu_check_status +``` + +**Returns:** Status string indicating: +- "ok" - kugetsu initialized, PM agent running +- "kugetsu_not_initialized" - Run kugetsu init first +- "pm_agent_missing" - PM agent not found + +### kugetsu_list_sessions + +Lists all kugetsu-managed sessions. + +```bash +kugetsu_list_sessions +``` + +**Returns:** Formatted list of sessions + +### kugetsu_create_dev_session + +Creates a Dev Agent session for an issue. + +```bash +kugetsu_create_dev_session "" "" +``` + +**Arguments:** +- `issue-ref`: Issue reference (e.g., "github.com/shoko/kugetsu#5") +- `task`: Task description for the dev agent + +**Returns:** Session creation status + +## Implementation + +These tools are implemented as shell functions that Hermes can call via `terminal()`. + +### Direct Implementation (Recommended) + +Add to Hermes SOUL.md as custom tools: + +``` +You have access to kugetsu via terminal commands: + +- kugetsu_get_pm_session: Get PM agent session ID +- kugetsu_delegate_to_pm : Delegate to PM agent +- kugetsu_check_status: Check kugetsu status +``` + +### Tool Definition Format + +Hermes tools should call these functions via terminal(): + +```python +{ + "name": "kugetsu_delegate", + "description": "Delegate a task to the PM Agent", + "parameters": { + "type": "object", + "properties": { + "task": { + "type": "string", + "description": "Task to delegate to PM Agent" + } + }, + "required": ["task"] + } +} +``` + +## Usage in Hermes + +### SOUL.md Integration + +Add to your SOUL.md: + +``` +You can interact with kugetsu to route tasks: + +1. Get PM agent session: terminal(command="kugetsu_get_pm_session") +2. Delegate to PM: terminal(command="kugetsu_delegate_to_pm 'fix issue #5'") +3. Check status: terminal(command="kugetsu_check_status") +``` + +### Routing Logic + +``` +User message → Hermes + │ + ├─ Small talk → respond directly + │ + └─ Task request → terminal(kugetsu_delegate_to_pm "") + │ + └─ PM Agent response → relay to user +``` + +## Error Handling + +| Error | Cause | Resolution | +|-------|-------|------------| +| "kugetsu not initialized" | Run `kugetsu init` | Inform user | +| "pm_agent_missing" | PM agent not created | Run `kugetsu init` | +| "session not found" | opencode session expired | May need reinit | + +## Files + +- `scripts/kugetsu-helpers.sh` - Shell implementations +- `SKILL.md` - This documentation \ No newline at end of file diff --git a/skills/kugetsu-helpers/scripts/kugetsu-helpers b/skills/kugetsu-helpers/scripts/kugetsu-helpers new file mode 100755 index 0000000..90c5081 --- /dev/null +++ b/skills/kugetsu-helpers/scripts/kugetsu-helpers @@ -0,0 +1,148 @@ +#!/bin/bash +# kugetsu-helpers - Shell functions for Hermes to interact with kugetsu +# +# These functions provide tools for routing and delegation to PM Agent. + +set -euo pipefail + +KUGETSU_DIR="${KUGETSU_DIR:-$HOME/.kugetsu}" +INDEX_FILE="$KUGETSU_DIR/index.json" + +kugetsu_get_pm_session() { + if [ ! -f "$INDEX_FILE" ]; then + echo "" + return + fi + + python3 -c "import json; print(json.load(open('$INDEX_FILE')).get('pm_agent', ''))" 2>/dev/null || echo "" +} + +kugetsu_check_status() { + if [ ! -f "$INDEX_FILE" ]; then + echo "kugetsu_not_initialized" + return + fi + + if ! grep -q '"pm_agent"' "$INDEX_FILE"; then + echo "pm_agent_missing" + return + fi + + PM_AGENT=$(kugetsu_get_pm_session) + if [ -z "$PM_AGENT" ] || [ "$PM_AGENT" = "null" ]; then + echo "pm_agent_missing" + return + fi + + echo "ok" +} + +kugetsu_delegate_to_pm() { + local task="${1:-}" + + if [ -z "$task" ]; then + echo "Error: task is required" + return 1 + fi + + local pm_session=$(kugetsu_get_pm_session) + if [ -z "$pm_session" ] || [ "$pm_session" = "null" ]; then + echo "Error: PM agent session not found. Run 'kugetsu init' first." + return 1 + fi + + opencode run --continue --session "$pm_session" "$task" 2>&1 +} + +kugetsu_list_sessions() { + if command -v kugetsu &> /dev/null; then + kugetsu list 2>&1 + else + echo "kugetsu command not found" + return 1 + fi +} + +kugetsu_create_dev_session() { + local issue_ref="${1:-}" + local task="${2:-}" + + if [ -z "$issue_ref" ] || [ -z "$task" ]; then + echo "Error: issue_ref and task are required" + return 1 + fi + + if ! command -v kugetsu &> /dev/null; then + echo "Error: kugetsu command not found" + return 1 + fi + + kugetsu start "$issue_ref" "$task" 2>&1 +} + +kugetsu_continue_dev_session() { + local issue_ref="${1:-}" + local update="${2:-}" + + if [ -z "$issue_ref" ] || [ -z "$update" ]; then + echo "Error: issue_ref and update are required" + return 1 + fi + + if ! command -v kugetsu &> /dev/null; then + echo "Error: kugetsu command not found" + return 1 + fi + + kugetsu continue "$issue_ref" "$update" 2>&1 +} + +# Main entry point for CLI usage +main() { + local command="${1:-}" + shift || true + + case "$command" in + get-pm-session) + kugetsu_get_pm_session + ;; + check-status) + kugetsu_check_status + ;; + delegate-to-pm) + kugetsu_delegate_to_pm "$@" + ;; + list-sessions) + kugetsu_list_sessions + ;; + create-dev-session) + kugetsu_create_dev_session "$@" + ;; + continue-dev-session) + kugetsu_continue_dev_session "$@" + ;; + help|--help|-h) + cat << 'EOF' +kugetsu-helpers - Hermes tools for kugetsu + +Commands: + get-pm-session Get PM agent session ID + check-status Check kugetsu initialization status + delegate-to-pm Delegate task to PM agent + list-sessions List all kugetsu sessions + create-dev-session Create dev agent session + continue-dev-session Continue dev agent session + +Usage in Hermes: + terminal(command="kugetsu_delegate_to_pm 'fix issue #5'") +EOF + ;; + *) + echo "Error: Unknown command '$command'" + echo "Run 'kugetsu-helpers help' for usage" + return 1 + ;; + esac +} + +main "$@" \ No newline at end of file diff --git a/skills/kugetsu-pm/SKILL.md b/skills/kugetsu-pm/SKILL.md new file mode 100644 index 0000000..aea1012 --- /dev/null +++ b/skills/kugetsu-pm/SKILL.md @@ -0,0 +1,218 @@ +--- +name: kugetsu-pm +description: PM (Project Manager) Agent skill for kugetsu. Handles task coordination, delegation, and Gitea integration. +license: MIT +compatibility: Requires kugetsu CLI, opencode sessions, Gitea API access. +metadata: + author: shoko + version: "1.0" +--- + +# kugetsu-pm - PM Agent Skill + +Defines the behavior of the PM (Project Manager) Agent in the kugetsu system. + +## Overview + +The PM Agent is a persistent opencode session managed by kugetsu. It: + +1. **Receives** task requests from Chat Agent (via Hermes) +2. **Coordinates** task execution via Dev Agents +3. **Monitors** Gitea for issue updates +4. **Notifies** users of task completion (if in notify mode) +5. **Maintains** context across interactions + +## Architecture + +``` +Chat Agent (Hermes/Telegram) + │ + ├── Routes task requests + │ + ▼ +PM Agent (opencode session via kugetsu) + │ + ├── Creates Dev Agent sessions via kugetsu + │ + ▼ +Dev Agents (opencode sessions via kugetsu) + │ + ├── Work on issues autonomously + │ + ▼ +Gitea (Issues, PRs, Comments) +``` + +## PM Agent Modes + +| Mode | Behavior | Command | +|------|----------|---------| +| **notify** (default) | Send completion notifications | "pm notify" | +| **silent** | Work quietly, no notifications | "pm silent" | + +## Task Flow + +### 1. Receive Task Request + +When Chat Agent routes a task: +``` +"fix issue #5" +``` + +### 2. Parse and Validate + +PM Agent extracts: +- Action (fix, create, test, research, etc.) +- Issue number or identifier +- Repository context + +### 3. Create Task Plan + +PM Agent decides: +- Can it be handled directly? +- Does it need a Dev Agent? +- What context is needed? + +### 4. Execute via Dev Agent + +```bash +kugetsu start "" +``` + +### 5. Monitor and Notify + +- PM monitors Gitea for PR status +- When complete, notifies user (if in notify mode) + +## Gitea Integration + +### Context Fetching + +PM Agent fetches from Gitea when: +- Initial task load (no context) +- Explicit request (agent decides) +- Insufficient context + +### Context Merge Strategy + +- **Default**: Append new context to existing +- **Threshold**: Summarize + replace at 40% of context window + +## Session Context + +PM Agent maintains: + +### Managed Repositories +```json +{ + "repos": [ + "github.com/shoko/kugetsu", + "gitlab.com/team/core" + ] +} +``` + +### Active Tasks +```json +{ + "tasks": { + "issue-5": { + "status": "in_progress", + "dev_agent": "ses_xyz789", + "created_at": "2026-03-30T10:00:00Z" + } + } +} +``` + +### Notification Preferences +```json +{ + "mode": "notify" +} +``` + +## Delegation Commands + +### Create Dev Agent Session + +```bash +kugetsu start "" +``` + +### Continue Dev Agent Session + +```bash +kugetsu continue "" +``` + +### List Active Sessions + +```bash +kugetsu list +``` + +## Response Format + +PM Agent responses should be: +- **Concise** - Telegram-friendly +- **Action-oriented** - What's been done, what's next +- **Clear status** - In progress, done, blocked + +### Example Responses + +``` +"Created task for issue #5. Dev agent started." +"Issue #5 is complete. PR created: [link]" +"Task blocked: Need clarification on requirements." +``` + +## Error Handling + +### Dev Agent Failure +- Analyze failure reason +- Retry or escalate to user +- Log to Gitea issue comment + +### Session Not Found +- Check kugetsu status: `kugetsu list` +- Inform user of issue +- Suggest manual intervention + +### Gitea API Errors +- Retry with backoff +- Cache last known state +- Inform user if persistent + +## Skills + +### kugetsu (for session management) +- Session creation and continuation +- Worktree management + +### github (for Gitea API) +- Issue fetching +- PR creation +- Comment posting + +## Implementation Notes + +### PM Agent Session ID + +The PM Agent session is stored in: +``` +~/.kugetsu/index.json → "pm_agent" field +``` + +### Accessing PM Agent + +```bash +PM_SESSION=$(cat ~/.kugetsu/index.json | python3 -c "import sys,json; print(json.load(sys.stdin).get('pm_agent', ''))") +opencode run --continue --session "$PM_SESSION" "" +``` + +## Related Documentation + +- [kugetsu-architecture.md](../../docs/kugetsu-architecture.md) +- [kugetsu-chat.md](../../docs/kugetsu-chat.md) +- [hermes-setup.md](../../docs/hermes-setup.md) \ No newline at end of file From 7c94a59bb6d19cfb4a864c9caeedda842666ef38 Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Mon, 30 Mar 2026 14:20:21 +0000 Subject: [PATCH 02/14] fix(phase3a): separate SOUL.md personality from SKILL.md routing - SOUL.md: only personality/voice guidance (no routing logic) - SKILL.md: definitive routing behavior + delegation process - Add context passing via temp file for long tasks - Add error handling table with user-friendly messages This aligns with Hermes docs: SOUL.md = identity, SKILL.md = behavior --- skills/kugetsu-chat/SKILL.md | 219 +++++++++++++++-------------------- skills/kugetsu-chat/SOUL.md | 137 ++++++---------------- 2 files changed, 130 insertions(+), 226 deletions(-) diff --git a/skills/kugetsu-chat/SKILL.md b/skills/kugetsu-chat/SKILL.md index 7a8077f..f16875d 100644 --- a/skills/kugetsu-chat/SKILL.md +++ b/skills/kugetsu-chat/SKILL.md @@ -5,166 +5,133 @@ license: MIT compatibility: Requires Hermes agent with Telegram configured, kugetsu CLI, opencode sessions. metadata: author: shoko - version: "1.0" + version: "1.1" --- -# kugetsu-chat - Chat Agent for Kugetsu Phase 3 +# kugetsu-chat - Chat Agent Skill -Handles natural language routing and PM Agent coordination for Telegram interface. +**This skill defines how Hermes routes messages and delegates to the PM Agent.** ## Overview -The Chat Agent is Hermes configured with a specific SOUL.md and skills that enable: -- Receiving Telegram messages -- Intent classification (small talk, task, status, clarification) -- Routing to PM Agent when needed -- Notification coordination - -## Architecture - -``` -User (Telegram) → Hermes (Chat Agent) - ├── Small talk → Respond directly - ├── Task request → Route to PM Agent - ├── Status query → Route to PM Agent - └── Clarification → Ask via Hermes → User -``` +The Chat Agent receives Telegram messages, classifies intent, and routes to the appropriate handler. ## Intent Classification -### Rules +When you receive a message, classify its intent: -| Intent | Examples | Response | -|--------|----------|----------| -| **Small talk** | "hi", "thanks", "how are you" | Respond directly, clear context if unrelated | -| **Task request** | "fix issue #5", "create test for #14" | Route to PM Agent | -| **Status query** | "status?", "what's on #7?" | Route to PM Agent | -| **Mode change** | "pm notify", "pm silent" | Route to PM Agent | -| **Clarification** | "which project?", "what repo?" | Ask user via Hermes | +| Intent | Examples | Action | +|--------|----------|--------| +| **Small talk** | "hi", "thanks", "how are you", "hello" | Respond directly | +| **Task request** | "fix issue #5", "create test for #14", "implement feature" | Route to PM Agent | +| **Status query** | "status?", "what's on #7?", "progress?" | Route to PM Agent | +| **Mode command** | "pm notify", "pm silent", "work silently" | Route to PM Agent | +| **Clarification** | "which project?", "what repo?" | Ask user for clarification | -### Routing Logic +## Delegation Process -``` -1. Receive message -2. Classify intent: - - If small talk → respond directly - - If task/status/mode → delegate to PM Agent -3. If PM response needed → send to PM Agent -4. Return PM response to user -``` +When you need to delegate to the PM Agent: -## PM Agent Delegation - -### How Hermes Delegates to PM Agent - -Hermes uses `terminal()` to interact with the PM Agent opencode session: +### Step 1: Get PM Agent Session ```bash -# Get PM agent session ID -PM_SESSION=$(cat ~/.kugetsu/index.json | python3 -c "import sys,json; print(json.load(sys.stdin).get('pm_agent', ''))") - -# Continue PM agent session with task -opencode run --continue --session "$PM_SESSION" "User request: $MESSAGE" +PM_SESSION=$(cat ~/.kugetsu/index.json | python3 -c "import sys,json; print(json.load(open('$HOME/.kugetsu/index.json')).get('pm_agent', ''))") ``` -### PM Agent Modes +### Step 2: Check if kugetsu is initialized -| Mode | Behavior | Storage | -|------|----------|---------| -| **notify** (default) | PM sends completion notifications | Session context | -| **silent** | PM works quietly, no notifications | Session context | - -Toggle with: "pm notify" / "pm silent" - -## Notification Flow - -``` -PM Agent completes task - → Checks mode - → If notify → Routes via Hermes → Telegram message to user - → If silent → No notification -``` - -## Session Context - -### Chat Agent Context -- Short-term conversation memory -- User preferences -- Last routing decision - -### PM Agent Context -- Managed repositories -- Active tasks -- Notification preferences -- Long-term project memory - -## Skills - -### kugetsu-chat-skill - -Defines Chat Agent behavior: -- Intent classification prompt -- Routing rules -- Response formatting - -### kugetsu-pm-skill (for PM Agent session) - -Defines PM Agent behavior: -- Task coordination -- Gitea integration -- Notification handling - -## Implementation Notes - -### Hermes Gateway - -Hermes gateway must be running: ```bash -hermes gateway start +kugetsu status check ``` -Or run interactively: +If this fails, inform the user: "kugetsu is not initialized. Please run `kugetsu init` first." + +### Step 3: Delegate to PM Agent + +Use `terminal()` to continue the PM Agent session: + +``` +terminal(command="opencode run --continue --session $PM_SESSION 'User request: '", timeout=120) +``` + +### Step 4: Relay Response + +Return the PM Agent's response to the user via Telegram. + +## Delegation via kugetsu-helpers + +Alternatively, use the kugetsu-helpers script: + ```bash -hermes gateway run +terminal(command="kugetsu-delegate ''", timeout=120) ``` -### kugetsu init +Or check status first: -Before using chat, ensure kugetsu is initialized: ```bash -kugetsu init +terminal(command="kugetsu-check-status", timeout=10) ``` -This creates: -- Base session -- PM agent session +## Context Passing -### PM Agent Session +If the task message is too long for terminal parameters, write to a temp file: -The PM agent session ID is stored in: -``` -~/.kugetsu/index.json → "pm_agent" field +```bash +# Write context to file +echo "Task: fix issue #5 +Repo: github.com/shoko/kugetsu +User: Please fix the authentication bug +" > /tmp/task-context.txt + +# Pass file path to PM +terminal(command="opencode run --continue --session $PM_SESSION --workdir /tmp \"Read /tmp/task-context.txt and execute\"", timeout=120) ``` -## Troubleshooting +## Error Handling -### Hermes not receiving Telegram messages -1. Check `hermes gateway status` -2. Verify Telegram bot token in config -3. Ensure bot has been started by user +| Error | User Message | Resolution | +|-------|--------------|------------| +| kugetsu not initialized | "kugetsu is not set up yet. Please run `kugetsu init` first." | User runs kugetsu init | +| PM agent missing | "PM agent not found. Run `kugetsu init` to create it." | User runs kugetsu init | +| Session expired | "The PM agent session may have expired. Please run `kugetsu destroy --pm-agent -y && kugetsu init` to reinitialize." | User reinitializes | -### PM Agent not responding -1. Check `kugetsu list` shows pm-agent -2. Verify pm-agent session is running: `opencode session list` -3. Check PM agent logs +## PM Agent Modes -### Routing not working -1. Check intent classification in Hermes context -2. Verify kugetsu is initialized -3. Check PM agent session is accessible +When routing to PM Agent, you can include mode preferences: -## Related Documentation +- "pm notify" → PM sends notifications on completion (default) +- "pm silent" → PM works quietly, no notifications -- [kugetsu-architecture.md](../../docs/kugetsu-architecture.md) -- [kugetsu-chat-architecture.md](../../docs/kugetsu-chat.md) -- [telegram-setup.md](../../docs/telegram-setup.md) \ No newline at end of file +## Response Formatting + +When relaying PM Agent responses: +- Keep messages concise (Telegram-friendly) +- Don't add your own commentary unless helpful +- Format links and code blocks clearly + +## When NOT to Route + +Do NOT route to PM Agent for: +- Greetings and casual conversation +- Questions about how the system works +- Help with Telegram itself +- Simple questions you can answer directly + +## Quick Reference + +```bash +# Check if kugetsu is ready +cat ~/.kugetsu/index.json | python3 -c "import sys,json; d=json.load(sys.stdin); print('OK' if d.get('pm_agent') else 'NOT INITIALIZED')" + +# Get PM session ID +python3 -c "import json; print(json.load(open('$HOME/.kugetsu/index.json')).get('pm_agent', ''))" +``` + +## Related Skills + +- `kugetsu-pm` - PM Agent behavior and coordination +- `kugetsu-helpers` - Shell functions for kugetsu interaction + +## Files + +- `../kugetsu-helpers/scripts/kugetsu-helpers` - Helper script with delegation functions \ No newline at end of file diff --git a/skills/kugetsu-chat/SOUL.md b/skills/kugetsu-chat/SOUL.md index 3b1a68d..e92d191 100644 --- a/skills/kugetsu-chat/SOUL.md +++ b/skills/kugetsu-chat/SOUL.md @@ -1,110 +1,47 @@ -# Kugetsu Chat Agent SOUL +# Kugetsu Chat Agent -You are the Kugetsu Chat Agent - a friendly gateway between users and their agent team via Telegram. +You are the friendly, professional face of the Kugetsu agent team on Telegram. + +## Your Voice + +- **Friendly but professional** - Warm without being overly casual +- **Concise** - Telegram users prefer short, punchy messages +- **Helpful** - Guide users toward their goals without being pushy +- **Patient** - Some users are new to multi-agent systems +- **Direct** - Get to the point, no fluff + +## Communication Style + +### When responding: +- Keep messages short (Telegram prefers brevity) +- Use emojis sparingly for warmth, not decoration +- Format code or technical terms in backticks if needed +- Be proactive with helpful suggestions + +### When unsure: +- Ask clarifying questions +- Offer options when possible +- Admit what you don't know + +### When things go wrong: +- Be honest about issues +- Don't expose internal technical details to users +- Suggest concrete next steps ## Your Role -You serve as the **first point of contact** for users messaging on Telegram. You: +You are the **first point of contact** for users on Telegram. You: +- Handle casual conversation +- Route task requests to the appropriate agents +- Relay responses back to users +- Maintain a welcoming, professional tone -1. **Receive** messages from users via Telegram -2. **Classify** the intent of each message -3. **Respond** to small talk directly -4. **Route** task requests and status queries to the PM Agent -5. **Relay** PM Agent responses back to users +## Security Posture -## Intent Classification - -### Message Types - -| Type | Indicators | Your Action | -|------|------------|-------------| -| **Small talk** | greetings, thanks, casual conversation | Respond directly | -| **Task request** | "fix", "create", "implement", issue numbers | Route to PM Agent | -| **Status query** | "status", "progress", "what's on", "done?" | Route to PM Agent | -| **Mode command** | "pm notify", "pm silent" | Route to PM Agent | -| **Clarification** | Questions about which project/repo | Ask user for clarification | - -### Classification Examples - -``` -"hi there" → Small talk (respond directly) -"thanks!" → Small talk (respond directly) -"fix issue #5" → Task request (route to PM) -"what's on #14?" → Status query (route to PM) -"status?" → Status query (route to PM) -"pm silent" → Mode command (route to PM) -"which project?" → Clarification (ask user) -``` - -## Routing to PM Agent - -When you need to route to the PM Agent: - -### Step 1: Get PM Agent Session - -```bash -PM_SESSION=$(cat ~/.kugetsu/index.json | python3 -c "import sys,json; print(json.load(sys.stdin).get('pm_agent', ''))") -``` - -### Step 2: Delegate Task - -Use `terminal()` to continue the PM Agent session: - -``` -terminal(command="opencode run --continue --session $PM_SESSION 'User request: '", timeout=120) -``` - -### Step 3: Relay Response - -Return the PM Agent's response to the user via Telegram. - -## Response Guidelines - -### Small Talk -- Be friendly and conversational -- Keep responses brief -- Use emojis sparingly - -### PM Agent Responses -- Relay exactly what PM Agent says -- Don't add your own commentary unless helpful -- Format for Telegram (short messages preferred) - -### Clarification Requests -- Be specific about what's unclear -- Offer options when possible -- Example: "Which repository? github.com/shoko/kugetsu or gitlab.com/team/project?" - -## Error Handling - -### PM Agent Unavailable -If PM Agent session is not found or unresponsive: -- Check kugetsu is initialized: `kugetsu list` -- Try to restart PM Agent if needed -- Inform user if persistent issues - -### Routing Failures -- Log the error -- Inform user: "I'm having trouble reaching the PM Agent. Please try again." -- Suggest checking `kugetsu list` if persistent - -## Tone and Style - -- **Friendly but professional** -- **Concise** - Telegram users prefer short messages -- **Helpful** - Offer guidance when users seem stuck -- **Patient** - Some users may not be familiar with the system - -## Security Notes - -- Never reveal internal session IDs to users -- Don't expose file paths or system details +- Never reveal internal session IDs or file paths - Keep responses user-friendly, not technical - -## Remember - -You are the **face of the system** on Telegram. Users will judge kugetsu based on their interactions with you. Be the best first impression! +- If in doubt, ask the user for clarification --- -*Last updated: 2026-03-30 for Phase 3a implementation* \ No newline at end of file +*Last updated: 2026-03-30* \ No newline at end of file From 227ec3a22e4f3427bc68aad87097a855c937e954 Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Mon, 30 Mar 2026 14:25:22 +0000 Subject: [PATCH 03/14] docs: add Phase 3a installation guide and update install script - docs/phase3a-setup.md - Complete installation guide for Phase 3a - skills/kugetsu/scripts/kugetsu-install.sh - Updated to reflect v2.2 changes --- docs/phase3a-setup.md | 158 ++++++++++++++++++++++ skills/kugetsu/scripts/kugetsu-install.sh | 55 ++++---- 2 files changed, 183 insertions(+), 30 deletions(-) create mode 100644 docs/phase3a-setup.md diff --git a/docs/phase3a-setup.md b/docs/phase3a-setup.md new file mode 100644 index 0000000..a03618f --- /dev/null +++ b/docs/phase3a-setup.md @@ -0,0 +1,158 @@ +# Kugetsu Phase 3a Installation Guide + +Guide for setting up the Kugetsu Chat Agent (Phase 3a) on a new host/container. + +## Prerequisites + +1. **Hermes Agent** installed and configured +2. **Telegram bot** created via @BotFather +3. **kugetsu CLI** installed +4. **opencode** installed + +## Step 1: Verify Hermes Installation + +```bash +hermes version +hermes config show # Check Telegram is configured +``` + +## Step 2: Link Skills to Hermes + +```bash +# Create skill directories +mkdir -p ~/.hermes/skills/kugetsu-chat +mkdir -p ~/.hermes/skills/kugetsu-pm +mkdir -p ~/.hermes/skills/kugetsu-helpers + +# Link skills from kugetsu repo (adjust path as needed) +KUGEETSU_DIR="/path/to/kugetsu" # e.g., ~/repositories/kugetsu + +ln -sf "$KUGEETSU_DIR/skills/kugetsu-chat" ~/.hermes/skills/kugetsu-chat +ln -sf "$KUGEETSU_DIR/skills/kugetsu-pm ~/.hermes/skills/kugetsu-pm +ln -sf "$KUGEETSU_DIR/skills/kugetsu-helpers" ~/.hermes/skills/kugetsu-helpers +``` + +## Step 3: Install Chat Agent SOUL + +```bash +# Copy SOUL.md to Hermes home (this defines the Chat Agent personality) +cp "$KUGEETSU_DIR/skills/kugetsu-chat/SOUL.md" ~/.hermes/SOUL-chat.md +``` + +## Step 4: Install Helper Scripts + +```bash +# Copy helper script to PATH +cp "$KUGEETSU_DIR/skills/kugetsu-helpers/scripts/kugetsu-helpers" ~/.local/bin/kugetsu-helper +chmod +x ~/.local/bin/kugetsu-helper + +# Verify +kugetsu-helper help +``` + +## Step 5: Verify Gateway is Running + +```bash +hermes gateway status +# If stopped: +hermes gateway start +``` + +## Step 6: Initialize kugetsu + +**WARNING:** This requires an interactive terminal (TTY) because it spawns the opencode TUI. + +You must run this in an **interactive shell**, not via `ssh remote "kugetsu init"`: + +```bash +# Option 1: SSH with TTY allocation +ssh -t user@host "kugetsu init" + +# Option 2: Connect to existing session and run +ssh user@host +kugetsu init # Run manually in the SSH session +``` + +This creates: +- **Base session** (for forking dev agents) +- **PM Agent session** (persistent coordinator) + +If you get `Error: init requires a terminal (TTY)`, you're running via non-interactive SSH. Use `-t` flag or connect directly. + +## Step 7: Verify Setup + +```bash +# Check kugetsu status +kugetsu list + +# Check PM agent exists +kugetsu-helper check-status +# Should output: ok +``` + +## Step 8: Test via Telegram + +Start a conversation with your bot (@your_bot_username): + +| Message | Expected | +|---------|----------| +| `hi` | Responds directly (small talk) | +| `status?` | Routes to PM Agent | +| `fix issue #5` | Routes to PM Agent | + +## Troubleshooting + +### kugetsu-helper not found +```bash +export PATH="$HOME/.local/bin:$PATH" +# Or add to ~/.bashrc +echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc +``` + +### Gateway not responding +```bash +hermes gateway restart +``` + +### PM agent missing +```bash +# Reinitialize +kugetsu destroy --pm-agent -y +kugetsu init +``` + +## File Locations + +| File | Location | Purpose | +|------|----------|---------| +| Chat Agent SOUL | `~/.hermes/SOUL-chat.md` | Personality | +| kugetsu-chat skill | `~/.hermes/skills/kugetsu-chat/` | Routing behavior | +| kugetsu-pm skill | `~/.hermes/skills/kugetsu-pm/` | PM Agent docs | +| kugetsu-helpers | `~/.hermes/skills/kugetsu-helpers/` | Helper functions | +| Helper script | `~/.local/bin/kugetsu-helper` | CLI helper | + +## Architecture Summary + +``` +~/.hermes/ +├── SOUL-chat.md # Chat Agent personality +└── skills/ + ├── kugetsu-chat/ # Routing + delegation logic + ├── kugetsu-pm/ # PM Agent documentation + └── kugetsu-helpers/ # Shell helpers for terminal() + +~/.kugetsu/ +├── sessions/ +│ ├── base.json # Base opencode session +│ └── pm-agent.json # PM Agent opencode session +└── index.json # Session registry + +~/.local/bin/ +└── kugetsu-helper # CLI helper script +``` + +## Security Notes + +- Never commit `~/.kugetsu/` or SOUL files to version control +- Bot tokens should be in environment variables, not files +- PM agent session IDs are internal - don't expose to users \ No newline at end of file diff --git a/skills/kugetsu/scripts/kugetsu-install.sh b/skills/kugetsu/scripts/kugetsu-install.sh index 767cc6b..e84c270 100755 --- a/skills/kugetsu/scripts/kugetsu-install.sh +++ b/skills/kugetsu/scripts/kugetsu-install.sh @@ -1,10 +1,13 @@ #!/bin/bash +# kugetsu installation script +# Installs kugetsu CLI and optionally sets up Phase 3a Chat Agent + set -euo pipefail KUGETSU_DIR="${KUGETSU_DIR:-$HOME/.kugetsu}" -BIN_DIR="$KUGETSU_DIR/bin" +BIN_DIR="${BIN_DIR:-$HOME/.local/bin}" -echo "Installing kugetsu to $KUGETSU_DIR..." +echo "Installing kugetsu..." mkdir -p "$BIN_DIR" @@ -13,24 +16,21 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cp "$SCRIPT_DIR/kugetsu" "$BIN_DIR/kugetsu" chmod +x "$BIN_DIR/kugetsu" +echo "kugetsu installed at: $BIN_DIR/kugetsu" + add_to_shell() { local rc_file="$1" - local export_line="export PATH=\"\$HOME/.kugetsu/bin:\$PATH\"" + local export_line="export PATH=\"\$HOME/.local/bin:\$PATH\"" if [ -f "$rc_file" ]; then if grep -q "$export_line" "$rc_file" 2>/dev/null; then - echo "$rc_file already has kugetsu in PATH" + echo "$rc_file already has .local/bin in PATH" else echo "" >> "$rc_file" - echo "# kugetsu - opencode session manager" >> "$rc_file" + echo "# kugetsu and other tools" >> "$rc_file" echo "$export_line" >> "$rc_file" echo "Added to $rc_file" fi - else - echo "" >> "$rc_file" - echo "# kugetsu - opencode session manager" >> "$rc_file" - echo "$export_line" >> "$rc_file" - echo "Created $rc_file with kugetsu PATH" fi } @@ -39,29 +39,24 @@ add_to_shell "$HOME/.zshrc" echo "" echo "=== Verifying installation ===" -if [ ! -f "$BIN_DIR/kugetsu" ]; then - echo "ERROR: kugetsu was not installed correctly." - exit 1 -fi -echo "kugetsu installed at: $BIN_DIR/kugetsu" +"$BIN_DIR/kugetsu" help | head -10 echo "" - echo "Installation complete!" + echo "" -echo "Run this to start using kugetsu immediately:" -echo " export PATH=\"\$HOME/.kugetsu/bin:\$PATH\"" +echo "=== Phase 3a Chat Agent Setup (Optional) ===" +echo "To also install the Chat Agent skills for Phase 3a:" echo "" -echo "Or start a new shell." +echo " 1. Link skills to Hermes:" +echo " mkdir -p ~/.hermes/skills/kugetsu-chat ~/.hermes/skills/kugetsu-pm ~/.hermes/skills/kugetsu-helpers" +echo " ln -sf /path/to/kugetsu/skills/kugetsu-chat ~/.hermes/skills/" +echo " ln -sf /path/to/kugetsu/skills/kugetsu-pm ~/.hermes/skills/" +echo " ln -sf /path/to/kugetsu/skills/kugetsu-helpers ~/.hermes/skills/" echo "" -echo "Usage:" -echo " kugetsu init Initialize base session (requires TTY)" -echo " kugetsu start Start task for issue" -echo " kugetsu continue [msg] Continue existing task" -echo " kugetsu list List all sessions" -echo " kugetsu prune [--force] Remove orphaned sessions" -echo " kugetsu destroy [-y] Delete session for issue" -echo " kugetsu destroy --base [-y] Delete base session" -echo " kugetsu help Show help" +echo " 2. Install Chat Agent SOUL:" +echo " cp /path/to/kugetsu/skills/kugetsu-chat/SOUL.md ~/.hermes/SOUL-chat.md" echo "" -echo "Issue ref format: instance/user/repo#number" -echo "Example: github.com/shoko/kugetsu#14" +echo " 3. Initialize kugetsu (requires TTY):" +echo " kugetsu init" +echo "" +echo "See docs/phase3a-setup.md for full installation guide." \ No newline at end of file From f8070246c82c8a50f943b146cb5818ae2fc49008 Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Mon, 30 Mar 2026 14:56:31 +0000 Subject: [PATCH 04/14] feat(phase3a): add strong routing instructions to SOUL.md - SOUL.md now explicitly instructs Hermes to ALWAYS use kugetsu-helper for delegation - Clear delegation rules with examples - Separation of casual conversation vs delegation This is the first attempt at making Hermes route via kugetsu-helper automatically. --- skills/kugetsu-chat/SOUL.md | 49 ++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/skills/kugetsu-chat/SOUL.md b/skills/kugetsu-chat/SOUL.md index e92d191..fd1f8e5 100644 --- a/skills/kugetsu-chat/SOUL.md +++ b/skills/kugetsu-chat/SOUL.md @@ -36,9 +36,56 @@ You are the **first point of contact** for users on Telegram. You: - Relay responses back to users - Maintain a welcoming, professional tone +## Routing Rules + +**IMPORTANT: You must ALWAYS use the kugetsu-helper for task delegation.** + +When a user sends a message that is NOT casual conversation (not "hi", "hello", "thanks", etc.), you MUST delegate using the kugetsu-helper: + +``` +terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm ''", timeout=120) +``` + +### Delegation Examples + +| User Message | Action | +|--------------|--------| +| "hi" | Respond directly | +| "hello" | Respond directly | +| "thanks" | Respond directly | +| "fix issue #5" | DELEGATE via kugetsu-helper | +| "status?" | DELEGATE via kugetsu-helper | +| "what's on #14?" | DELEGATE via kugetsu-helper | +| "create a test for #7" | DELEGATE via kugetsu-helper | +| "pm notify" | DELEGATE via kugetsu-helper | +| "work on this" | DELEGATE via kugetsu-helper | + +### How to Delegate + +1. Check if kugetsu is initialized: + ``` + terminal(command="~/.local/bin/kugetsu-helper check-status", timeout=10) + ``` + - If output is "kugetsu_not_initialized" or "pm_agent_missing", tell user to run `kugetsu init` + +2. If initialized, delegate: + ``` + terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm ''", timeout=120) + ``` + +3. Relay the output to the user. + +### When NOT to Delegate + +Only respond directly for: +- Greetings: "hi", "hello", "hey" +- Thanks: "thanks", "thank you" +- Casual: "how are you", "what's up" +- Questions about the bot itself + ## Security Posture -- Never reveal internal session IDs or file paths +- Never reveal internal session IDs or file paths to users - Keep responses user-friendly, not technical - If in doubt, ask the user for clarification From a6bbd969b648ca57688efec98c36ad0ed8a5a059 Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Mon, 30 Mar 2026 15:06:04 +0000 Subject: [PATCH 05/14] feat(phase3a): update SKILL.md and SOUL.md with stronger routing instructions - SKILL.md: More explicit about MUST use this skill for delegation - SOUL.md: Explicitly instruct to invoke /kugetsu-chat skill first - Add more explicit delegation rules and error handling --- skills/kugetsu-chat/SKILL.md | 159 +++++++++++++---------------------- skills/kugetsu-chat/SOUL.md | 117 +++++++++----------------- 2 files changed, 97 insertions(+), 179 deletions(-) diff --git a/skills/kugetsu-chat/SKILL.md b/skills/kugetsu-chat/SKILL.md index f16875d..ce31b35 100644 --- a/skills/kugetsu-chat/SKILL.md +++ b/skills/kugetsu-chat/SKILL.md @@ -1,137 +1,92 @@ --- name: kugetsu-chat -description: Chat Agent skill for kugetsu Phase 3. Handles Telegram routing, PM delegation, and notification coordination. +description: Kugetsu Chat Agent - REQUIRED skill for ALL non-casual Telegram messages. This skill MUST be loaded and used for task delegation. license: MIT compatibility: Requires Hermes agent with Telegram configured, kugetsu CLI, opencode sessions. metadata: author: shoko - version: "1.1" + version: "2.0" --- -# kugetsu-chat - Chat Agent Skill +# kugetsu-chat - REQUIRED SKILL FOR KUGETSU ROUTING -**This skill defines how Hermes routes messages and delegates to the PM Agent.** +**THIS SKILL MUST BE USED for any message that is not casual conversation.** -## Overview +## CRITICAL: When to Use This Skill -The Chat Agent receives Telegram messages, classifies intent, and routes to the appropriate handler. +**YOU MUST LOAD AND USE THIS SKILL when:** +- Any message containing "issue", "fix", "create", "test", "implement" +- Any message containing issue numbers like "#5", "#14", "#123" +- Any message that looks like a task request or status query +- Any message containing "pm", "status", "progress", "work on" -## Intent Classification +**DO NOT USE THIS SKILL for:** +- "hi", "hello", "hey" +- "thanks", "thank you" +- "how are you", "what's up" +- Casual greetings -When you receive a message, classify its intent: +## Required Actions -| Intent | Examples | Action | -|--------|----------|--------| -| **Small talk** | "hi", "thanks", "how are you", "hello" | Respond directly | -| **Task request** | "fix issue #5", "create test for #14", "implement feature" | Route to PM Agent | -| **Status query** | "status?", "what's on #7?", "progress?" | Route to PM Agent | -| **Mode command** | "pm notify", "pm silent", "work silently" | Route to PM Agent | -| **Clarification** | "which project?", "what repo?" | Ask user for clarification | +When you MUST use this skill: -## Delegation Process - -When you need to delegate to the PM Agent: - -### Step 1: Get PM Agent Session - -```bash -PM_SESSION=$(cat ~/.kugetsu/index.json | python3 -c "import sys,json; print(json.load(open('$HOME/.kugetsu/index.json')).get('pm_agent', ''))") +### Step 1: Load This Skill +``` +/kugetsu-chat ``` ### Step 2: Check if kugetsu is initialized +``` +terminal(command="~/.local/bin/kugetsu-helper check-status", timeout=10) +``` + +### Step 3: If initialized, DELEGATE immediately +``` +terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm ''", timeout=120) +``` + +### Step 4: Relay the response to the user + +## Delegation Command + +The ONLY command you should use for delegation: ```bash -kugetsu status check +~/.local/bin/kugetsu-helper delegate-to-pm '' ``` -If this fails, inform the user: "kugetsu is not initialized. Please run `kugetsu init` first." - -### Step 3: Delegate to PM Agent - -Use `terminal()` to continue the PM Agent session: - +Example: ``` -terminal(command="opencode run --continue --session $PM_SESSION 'User request: '", timeout=120) -``` - -### Step 4: Relay Response - -Return the PM Agent's response to the user via Telegram. - -## Delegation via kugetsu-helpers - -Alternatively, use the kugetsu-helpers script: - -```bash -terminal(command="kugetsu-delegate ''", timeout=120) -``` - -Or check status first: - -```bash -terminal(command="kugetsu-check-status", timeout=10) -``` - -## Context Passing - -If the task message is too long for terminal parameters, write to a temp file: - -```bash -# Write context to file -echo "Task: fix issue #5 -Repo: github.com/shoko/kugetsu -User: Please fix the authentication bug -" > /tmp/task-context.txt - -# Pass file path to PM -terminal(command="opencode run --continue --session $PM_SESSION --workdir /tmp \"Read /tmp/task-context.txt and execute\"", timeout=120) +terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm 'fix issue #5 in github.com/shoko/kugetsu'", timeout=120) ``` ## Error Handling -| Error | User Message | Resolution | -|-------|--------------|------------| -| kugetsu not initialized | "kugetsu is not set up yet. Please run `kugetsu init` first." | User runs kugetsu init | -| PM agent missing | "PM agent not found. Run `kugetsu init` to create it." | User runs kugetsu init | -| Session expired | "The PM agent session may have expired. Please run `kugetsu destroy --pm-agent -y && kugetsu init` to reinitialize." | User reinitializes | - -## PM Agent Modes - -When routing to PM Agent, you can include mode preferences: - -- "pm notify" → PM sends notifications on completion (default) -- "pm silent" → PM works quietly, no notifications - -## Response Formatting - -When relaying PM Agent responses: -- Keep messages concise (Telegram-friendly) -- Don't add your own commentary unless helpful -- Format links and code blocks clearly - -## When NOT to Route - -Do NOT route to PM Agent for: -- Greetings and casual conversation -- Questions about how the system works -- Help with Telegram itself -- Simple questions you can answer directly +| Status Output | Meaning | Action | +|--------------|---------|--------| +| `ok` | kugetsu is ready | Proceed with delegation | +| `kugetsu_not_initialized` | Not set up | Tell user to run `kugetsu init` | +| `pm_agent_missing` | PM not created | Tell user to run `kugetsu init` | ## Quick Reference -```bash -# Check if kugetsu is ready -cat ~/.kugetsu/index.json | python3 -c "import sys,json; d=json.load(sys.stdin); print('OK' if d.get('pm_agent') else 'NOT INITIALIZED')" - -# Get PM session ID -python3 -c "import json; print(json.load(open('$HOME/.kugetsu/index.json')).get('pm_agent', ''))" +**DELEGATION COMMAND:** +``` +terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm ''", timeout=120) ``` -## Related Skills +**CHECK STATUS:** +``` +terminal(command="~/.local/bin/kugetsu-helper check-status", timeout=10) +``` -- `kugetsu-pm` - PM Agent behavior and coordination -- `kugetsu-helpers` - Shell functions for kugetsu interaction +## Required Files -## Files +- `~/.local/bin/kugetsu-helper` - The delegation helper script -- `../kugetsu-helpers/scripts/kugetsu-helpers` - Helper script with delegation functions \ No newline at end of file +## Notes + +- ALWAYS use the full path `~/.local/bin/kugetsu-helper` +- ALWAYS use `delegate-to-pm` subcommand +- ALWAYS wrap user message in single quotes inside the command +- ALWAYS use timeout of at least 120 seconds for delegation \ No newline at end of file diff --git a/skills/kugetsu-chat/SOUL.md b/skills/kugetsu-chat/SOUL.md index fd1f8e5..c04b9c3 100644 --- a/skills/kugetsu-chat/SOUL.md +++ b/skills/kugetsu-chat/SOUL.md @@ -10,85 +10,48 @@ You are the friendly, professional face of the Kugetsu agent team on Telegram. - **Patient** - Some users are new to multi-agent systems - **Direct** - Get to the point, no fluff +## CRITICAL: Routing Requirement + +**YOU MUST ALWAYS use the kugetsu-chat skill for task delegation.** + +For ANY message that is not casual conversation, you MUST: + +1. First invoke: `/kugetsu-chat` +2. Then use the delegation command from that skill + +## Delegation Rules + +| User Message Type | Example | Action | +|------------------|---------|--------| +| Casual | "hi", "hello", "thanks" | Respond directly | +| Task | "fix issue #5", "create test for #14" | **MUST DELEGATE** | +| Status | "status?", "what's on #7?" | **MUST DELEGATE** | +| Mode | "pm notify", "pm silent" | **MUST DELEGATE** | +| Question | "how does this work?" | May respond directly | + +## Required Delegation Command + +``` +terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm ''", timeout=120) +``` + +## When NOT to Delegate + +Only for: +- Greetings: "hi", "hello", "hey", "howdy" +- Thanks: "thanks", "thank you", "thx" +- Casual: "how are you", "what's up", "nice" +- Simple questions about the bot itself + ## Communication Style -### When responding: - Keep messages short (Telegram prefers brevity) -- Use emojis sparingly for warmth, not decoration -- Format code or technical terms in backticks if needed -- Be proactive with helpful suggestions +- Use emojis sparingly +- Format code/terms in backticks +- Be proactive with suggestions -### When unsure: -- Ask clarifying questions -- Offer options when possible -- Admit what you don't know +## Security -### When things go wrong: -- Be honest about issues -- Don't expose internal technical details to users -- Suggest concrete next steps - -## Your Role - -You are the **first point of contact** for users on Telegram. You: -- Handle casual conversation -- Route task requests to the appropriate agents -- Relay responses back to users -- Maintain a welcoming, professional tone - -## Routing Rules - -**IMPORTANT: You must ALWAYS use the kugetsu-helper for task delegation.** - -When a user sends a message that is NOT casual conversation (not "hi", "hello", "thanks", etc.), you MUST delegate using the kugetsu-helper: - -``` -terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm ''", timeout=120) -``` - -### Delegation Examples - -| User Message | Action | -|--------------|--------| -| "hi" | Respond directly | -| "hello" | Respond directly | -| "thanks" | Respond directly | -| "fix issue #5" | DELEGATE via kugetsu-helper | -| "status?" | DELEGATE via kugetsu-helper | -| "what's on #14?" | DELEGATE via kugetsu-helper | -| "create a test for #7" | DELEGATE via kugetsu-helper | -| "pm notify" | DELEGATE via kugetsu-helper | -| "work on this" | DELEGATE via kugetsu-helper | - -### How to Delegate - -1. Check if kugetsu is initialized: - ``` - terminal(command="~/.local/bin/kugetsu-helper check-status", timeout=10) - ``` - - If output is "kugetsu_not_initialized" or "pm_agent_missing", tell user to run `kugetsu init` - -2. If initialized, delegate: - ``` - terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm ''", timeout=120) - ``` - -3. Relay the output to the user. - -### When NOT to Delegate - -Only respond directly for: -- Greetings: "hi", "hello", "hey" -- Thanks: "thanks", "thank you" -- Casual: "how are you", "what's up" -- Questions about the bot itself - -## Security Posture - -- Never reveal internal session IDs or file paths to users -- Keep responses user-friendly, not technical -- If in doubt, ask the user for clarification - ---- - -*Last updated: 2026-03-30* \ No newline at end of file +- Never reveal session IDs or file paths +- Keep responses user-friendly +- If in doubt, ask for clarification \ No newline at end of file From 6db33ea78610c50d3b36d1e89a13568e74c3c1fb Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Mon, 30 Mar 2026 15:52:29 +0000 Subject: [PATCH 06/14] fix(phase3a): add fix-permissions command to kugetsu-helper Add kugetsu_fix_pm_permissions function to fix opencode session permissions for /tmp/kugetsu directory access. This resolves permission issues when PM agent tries to access worktree directories. Usage: kugetsu-helper fix-permissions --- .../kugetsu-helpers/scripts/kugetsu-helpers | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/skills/kugetsu-helpers/scripts/kugetsu-helpers b/skills/kugetsu-helpers/scripts/kugetsu-helpers index 90c5081..c8ce651 100755 --- a/skills/kugetsu-helpers/scripts/kugetsu-helpers +++ b/skills/kugetsu-helpers/scripts/kugetsu-helpers @@ -97,6 +97,53 @@ kugetsu_continue_dev_session() { kugetsu continue "$issue_ref" "$update" 2>&1 } +kugetsu_fix_pm_permissions() { + local pm_session=$(kugetsu_get_pm_session) + if [ -z "$pm_session" ] || [ "$pm_session" = "null" ]; then + echo "Error: PM agent session not found" + return 1 + fi + + python3 << PYEOF +import sqlite3 +import json +import os + +db_path = os.path.expanduser("~/.local/share/opencode/opencode.db") +conn = sqlite3.connect(db_path) +cursor = conn.cursor() + +# Get current permission for PM session +session_id = "$pm_session" +cursor.execute("SELECT id, permission FROM session WHERE id = ?", (session_id,)) +row = cursor.fetchone() + +if not row: + print(f"Error: Session {session_id} not found") + exit(1) + +perms = json.loads(row[1]) if row[1] else [] +patterns = [p['pattern'] for p in perms] + +# Add missing patterns for /tmp/kugetsu +needed = ['/tmp/kugetsu', '/tmp/kugetsu/*', '/tmp/kugetsu/**'] +added = [] + +for pattern in needed: + if pattern not in patterns: + perms.append({"permission": "external_directory", "pattern": pattern, "action": "allow"}) + added.append(pattern) + +if added: + new_perms = json.dumps(perms) + cursor.execute("UPDATE session SET permission = ? WHERE id = ?", (new_perms, session_id)) + conn.commit() + print(f"Added permissions: {', '.join(added)}") +else: + print("All required permissions already exist") +PYEOF +} + # Main entry point for CLI usage main() { local command="${1:-}" @@ -121,6 +168,9 @@ main() { continue-dev-session) kugetsu_continue_dev_session "$@" ;; + fix-permissions) + kugetsu_fix_pm_permissions + ;; help|--help|-h) cat << 'EOF' kugetsu-helpers - Hermes tools for kugetsu @@ -132,9 +182,13 @@ Commands: list-sessions List all kugetsu sessions create-dev-session Create dev agent session continue-dev-session Continue dev agent session + fix-permissions Fix opencode permission for /tmp/kugetsu access Usage in Hermes: - terminal(command="kugetsu_delegate_to_pm 'fix issue #5'") + terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm 'fix issue #5'", timeout=120) + +Note: If PM agent has permission issues accessing /tmp/kugetsu, run: + kugetsu-helper fix-permissions EOF ;; *) From ef1179839d662f073e4e0195e0f1c63beae94cb2 Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Mon, 30 Mar 2026 23:00:34 +0000 Subject: [PATCH 07/14] docs(phase3): update status and add testing plan --- docs/kugetsu-architecture.md | 4 ++-- docs/kugetsu-chat.md | 2 +- docs/phase3a-setup.md | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/docs/kugetsu-architecture.md b/docs/kugetsu-architecture.md index ddcc21e..027d5d5 100644 --- a/docs/kugetsu-architecture.md +++ b/docs/kugetsu-architecture.md @@ -326,7 +326,7 @@ When a Coding Agent starts, it: | Phase 1 | ✅ Complete | SSH + Tailscale remote access | | Phase 1b | ✅ Complete | Tailscale VPN setup | | Phase 2 | 📋 Planned | API Interface | -| Phase 3 | 📋 Planned | Chat Integration (Telegram) | +| Phase 3 | 🔄 In Progress | Chat Integration (Telegram) | | Phase 4 | 📋 Planned | Web Dashboard | ### 6.2 Current Implementation @@ -344,7 +344,7 @@ When a Coding Agent starts, it: | Parallel capacity | How many Coding Agents can run simultaneously on one machine? | Pending | | Session management | Does kugetsu properly manage opencode sessions? | ✅ Working | | Remote access | Does SSH + Tailscale enable remote work? | ✅ Working | -| Chat interface | Can Hermes bridge Telegram for mobile UX? | Planned (Phase 3) | +| Chat interface | Can Hermes bridge Telegram for mobile UX? | Phase 3a Testing | ### 6.4 Success Criteria diff --git a/docs/kugetsu-chat.md b/docs/kugetsu-chat.md index c6ca50e..40092f5 100644 --- a/docs/kugetsu-chat.md +++ b/docs/kugetsu-chat.md @@ -1,6 +1,6 @@ # Kugetsu Chat Architecture (Phase 3) -**Status:** Planned (Not Yet Implemented) +**Status:** Phase 3a Implemented (Testing in Progress) **Related Issue:** #19 ## Overview diff --git a/docs/phase3a-setup.md b/docs/phase3a-setup.md index a03618f..61013ad 100644 --- a/docs/phase3a-setup.md +++ b/docs/phase3a-setup.md @@ -151,6 +151,47 @@ kugetsu init └── kugetsu-helper # CLI helper script ``` +## Testing Plan (Manual) + +### Test 1: Casual Conversation +**Objective:** Verify Hermes handles small talk directly without delegation + +| Step | Action | Expected Result | +|------|--------|-----------------| +| 1 | Send `hi` to @your_bot_username | Bot responds with greeting | +| 2 | Send `how are you?` | Bot responds naturally | + +### Test 2: Task Delegation +**Objective:** Verify Hermes delegates task to PM Agent via `kugetsu-helper` + +| Step | Action | Expected Result | +|------|--------|-----------------| +| 1 | Send `status?` to bot | Bot routes to PM, PM responds | +| 2 | Send `fix issue #5` to bot | PM agent receives task via opencode | +| 3 | Send `Work on issue #35` to bot | PM agent creates branch, worktree, PR | + +### Test 3: Error Handling +**Objective:** Verify graceful error handling + +| Step | Action | Expected Result | +|------|--------|-----------------| +| 1 | Send `status?` with PM agent stopped | Bot says "PM agent not available" | +| 2 | Send `status?` before `kugetsu init` | Bot says "kugetsu not initialized" | + +### Debugging + +If delegation fails: +```bash +# Check Hermes logs +hermes gateway logs + +# Check PM agent is running +kugetsu-helper check-status + +# Check kugetsu-helper directly +~/.local/bin/kugetsu-helper delegate-to-pm "test" +``` + ## Security Notes - Never commit `~/.kugetsu/` or SOUL files to version control From bc3cc8dd1ec9b2d6a4519741bd7b2502bbb57188 Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Tue, 31 Mar 2026 00:02:24 +0000 Subject: [PATCH 08/14] test(kugetsu-helpers): add unit test suite and fix None/null handling - Add test suite at skills/kugetsu-helpers/tests/test-kugetsu-helpers.sh - 11 unit tests covering check-status, delegate-to-pm, get-pm-session, etc. - Fix bug: Python print(None) outputs literal "None" string, not empty - All tests pass --- .../kugetsu-helpers/scripts/kugetsu-helpers | 6 +- .../tests/test-kugetsu-helpers.sh | 209 ++++++++++++++++++ 2 files changed, 212 insertions(+), 3 deletions(-) create mode 100644 skills/kugetsu-helpers/tests/test-kugetsu-helpers.sh diff --git a/skills/kugetsu-helpers/scripts/kugetsu-helpers b/skills/kugetsu-helpers/scripts/kugetsu-helpers index c8ce651..9d02eb8 100755 --- a/skills/kugetsu-helpers/scripts/kugetsu-helpers +++ b/skills/kugetsu-helpers/scripts/kugetsu-helpers @@ -29,7 +29,7 @@ kugetsu_check_status() { fi PM_AGENT=$(kugetsu_get_pm_session) - if [ -z "$PM_AGENT" ] || [ "$PM_AGENT" = "null" ]; then + if [ -z "$PM_AGENT" ] || [ "$PM_AGENT" = "null" ] || [ "$PM_AGENT" = "None" ]; then echo "pm_agent_missing" return fi @@ -46,7 +46,7 @@ kugetsu_delegate_to_pm() { fi local pm_session=$(kugetsu_get_pm_session) - if [ -z "$pm_session" ] || [ "$pm_session" = "null" ]; then + if [ -z "$pm_session" ] || [ "$pm_session" = "null" ] || [ "$pm_session" = "None" ]; then echo "Error: PM agent session not found. Run 'kugetsu init' first." return 1 fi @@ -99,7 +99,7 @@ kugetsu_continue_dev_session() { kugetsu_fix_pm_permissions() { local pm_session=$(kugetsu_get_pm_session) - if [ -z "$pm_session" ] || [ "$pm_session" = "null" ]; then + if [ -z "$pm_session" ] || [ "$pm_session" = "null" ] || [ "$pm_session" = "None" ]; then echo "Error: PM agent session not found" return 1 fi diff --git a/skills/kugetsu-helpers/tests/test-kugetsu-helpers.sh b/skills/kugetsu-helpers/tests/test-kugetsu-helpers.sh new file mode 100644 index 0000000..d4705a9 --- /dev/null +++ b/skills/kugetsu-helpers/tests/test-kugetsu-helpers.sh @@ -0,0 +1,209 @@ +#!/bin/bash +# kugetsu-helpers test suite +# Tests the shell helper functions for Hermes/Chat Agent integration +# +# Run with: bash skills/kugetsu-helpers/tests/test-kugetsu-helpers.sh + +set -euo pipefail + +KUGETSU_HELPERS="./skills/kugetsu-helpers/scripts/kugetsu-helpers" +TEST_PM_SESSION_ID="ses_test_pm_789" +TEST_ISSUE_REF="github.com/shoko/kugetsu#14" +PASS=0 +FAIL=0 + +cleanup() { + rm -rf ~/.kugetsu/sessions/* ~/.kugetsu/index.json 2>/dev/null || true +} + +setup_mock_index_uninitialized() { + cleanup +} + +setup_mock_index_no_pm_agent() { + mkdir -p ~/.kugetsu/sessions + cat > ~/.kugetsu/index.json << EOF +{ + "base": "ses_base_123", + "pm_agent": null, + "issues": {} +} +EOF +} + +setup_mock_index_with_pm_agent() { + mkdir -p ~/.kugetsu/sessions + cat > ~/.kugetsu/index.json << EOF +{ + "base": "ses_base_123", + "pm_agent": "$TEST_PM_SESSION_ID", + "issues": {} +} +EOF + cat > ~/.kugetsu/sessions/pm-agent.json << EOF +{"type": "pm_agent", "opencode_session_id": "$TEST_PM_SESSION_ID", "created_at": "2026-03-30T18:00:00+02:00", "state": "idle"} +EOF +} + +pass() { + echo "PASS: $1" + PASS=$((PASS + 1)) +} + +fail() { + echo "FAIL: $1" + FAIL=$((FAIL + 1)) +} + +cleanup + +echo "=== kugetsu-helpers Test Suite ===" +echo "" + +# Test 1: check-status when not initialized +echo "--- Test: check-status (not initialized) ---" +setup_mock_index_uninitialized +OUTPUT=$($KUGETSU_HELPERS check-status 2>&1 || true) +if [ "$OUTPUT" = "kugetsu_not_initialized" ]; then + pass "check-status returns kugetsu_not_initialized when no index.json" +else + fail "check-status not initialized: got '$OUTPUT', expected 'kugetsu_not_initialized'" +fi +echo "" + +# Test 2: check-status when pm_agent field is missing +echo "--- Test: check-status (missing pm_agent field) ---" +setup_mock_index_no_pm_agent +OUTPUT=$($KUGETSU_HELPERS check-status 2>&1 || true) +if [ "$OUTPUT" = "pm_agent_missing" ]; then + pass "check-status returns pm_agent_missing when field is null" +else + fail "check-status missing pm_agent: got '$OUTPUT', expected 'pm_agent_missing'" +fi +echo "" + +# Test 3: check-status when PM agent exists +echo "--- Test: check-status (PM agent exists) ---" +setup_mock_index_with_pm_agent +OUTPUT=$($KUGETSU_HELPERS check-status 2>&1 || true) +if [ "$OUTPUT" = "ok" ]; then + pass "check-status returns ok when PM agent exists" +else + fail "check-status ok: got '$OUTPUT', expected 'ok'" +fi +echo "" + +# Test 4: get-pm-session returns session ID when exists +echo "--- Test: get-pm-session (exists) ---" +setup_mock_index_with_pm_agent +OUTPUT=$($KUGETSU_HELPERS get-pm-session 2>&1 || true) +if [ "$OUTPUT" = "$TEST_PM_SESSION_ID" ]; then + pass "get-pm-session returns correct session ID" +else + fail "get-pm-session: got '$OUTPUT', expected '$TEST_PM_SESSION_ID'" +fi +echo "" + +# Test 5: get-pm-session returns empty when not initialized +echo "--- Test: get-pm-session (not initialized) ---" +setup_mock_index_uninitialized +OUTPUT=$($KUGETSU_HELPERS get-pm-session 2>&1 || true) +if [ -z "$OUTPUT" ]; then + pass "get-pm-session returns empty when not initialized" +else + fail "get-pm-session not initialized: got '$OUTPUT', expected ''" +fi +echo "" + +# Test 6: delegate-to-pm fails without task argument +echo "--- Test: delegate-to-pm (no task) ---" +setup_mock_index_with_pm_agent +OUTPUT=$($KUGETSU_HELPERS delegate-to-pm 2>&1 || true) +if echo "$OUTPUT" | grep -q "Error: task is required"; then + pass "delegate-to-pm fails without task" +else + fail "delegate-to-pm no task: got '$OUTPUT', expected error about task required" +fi +echo "" + +# Test 7: delegate-to-pm fails when PM agent missing +echo "--- Test: delegate-to-pm (PM agent missing) ---" +setup_mock_index_uninitialized +OUTPUT=$($KUGETSU_HELPERS delegate-to-pm "test task" 2>&1 || true) +if echo "$OUTPUT" | grep -q "Error: PM agent session not found"; then + pass "delegate-to-pm fails when PM agent not found" +else + fail "delegate-to-pm missing PM: got '$OUTPUT', expected error" +fi +echo "" + +# Test 8: list-sessions when kugetsu not installed +echo "--- Test: list-sessions (kugetsu not installed) ---" +cleanup +TMPDIR=$(mktemp -d) +KUGETSU_BAK="" +if command -v kugetsu &> /dev/null; then + KUGETSU_PATH=$(command -v kugetsu) + KUGETSU_BAK="${TMPDIR}/kugetsu.bak" + mv "$KUGETSU_PATH" "$KUGETSU_BAK" +fi +OUTPUT=$($KUGETSU_HELPERS list-sessions 2>&1 || true) +if [ -n "$KUGETSU_BAK" ]; then + mv "$KUGETSU_BAK" "$KUGETSU_PATH" +fi +rmdir "$TMPDIR" 2>/dev/null || true +if echo "$OUTPUT" | grep -q "kugetsu command not found"; then + pass "list-sessions fails gracefully when kugetsu not found" +else + fail "list-sessions no kugetsu: got '$OUTPUT', expected error" +fi +echo "" + +# Test 9: help command works +echo "--- Test: help command ---" +OUTPUT=$($KUGETSU_HELPERS help 2>&1 || true) +if echo "$OUTPUT" | grep -q "delegate-to-pm"; then + pass "help shows delegate-to-pm command" +else + fail "help: output missing delegate-to-pm" +fi +echo "" + +# Test 10: unknown command fails gracefully +echo "--- Test: unknown command ---" +OUTPUT=$($KUGETSU_HELPERS unknown-cmd 2>&1 || true) +if echo "$OUTPUT" | grep -q "Error: Unknown command"; then + pass "unknown command fails gracefully" +else + fail "unknown command: got '$OUTPUT', expected error" +fi +echo "" + +# Test 11: check-status handles malformed JSON gracefully +echo "--- Test: check-status (malformed JSON) ---" +mkdir -p ~/.kugetsu/sessions +echo "not valid json" > ~/.kugetsu/index.json +OUTPUT=$($KUGETSU_HELPERS check-status 2>&1 || true) +if [ "$OUTPUT" = "pm_agent_missing" ]; then + pass "check-status handles malformed JSON gracefully" +else + fail "check-status malformed JSON: got '$OUTPUT', expected 'pm_agent_missing'" +fi +echo "" + +# Cleanup +cleanup + +echo "" +echo "=== Test Summary ===" +echo "Passed: $PASS" +echo "Failed: $FAIL" +echo "" + +if [ $FAIL -eq 0 ]; then + echo "All tests passed!" + exit 0 +else + echo "Some tests failed." + exit 1 +fi \ No newline at end of file From b3171ed632521d64e36081a42623bdcc2f206d54 Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Tue, 31 Mar 2026 01:09:12 +0000 Subject: [PATCH 09/14] feat(kugetsu): add status, delegate, doctor commands; inject PM context at init This commit implements Phase 3b/3c architectural improvements: ### New kugetsu CLI commands: - `kugetsu status` - Check initialization status (replaces kugetsu-helper check-status) - `kugetsu delegate ` - Send message to PM agent (new command) - `kugetsu doctor [--fix]` - Diagnose and fix kugetsu issues ### PM Context Injection: - kugetsu init now reads ~/.kugetsu/pm-agent.md (if exists) and injects it into the PM agent session at creation time - PM context is loaded ONCE at init, not on every delegation - This improves efficiency - kugetsu-pm content read once, not 10 times ### kugetsu-chat updated: - Now uses `kugetsu delegate` instead of kugetsu-helper - Now uses `kugetsu status` instead of kugetsu-helper check-status - Simplified - no longer depends on kugetsu-helpers ### kugetsu continue: - Removed strict issue-ref format validation - Now accepts any session name that is tracked in index.json["issues"] - Issue-ref format is a guideline, not a hard requirement ### Documentation updated: - phase3a-setup.md - Updated to reflect new kugetsu commands - kugetsu-install.sh - Simplified Phase 3a setup instructions ### Breaking changes: - kugetsu-helpers is no longer required for Phase 3a Chat Agent - kugetsu-chat skill v3.0 now requires kugetsu CLI with new commands --- docs/phase3a-setup.md | 121 ++++------- skills/kugetsu-chat/SKILL.md | 26 +-- skills/kugetsu-chat/SOUL.md | 2 +- skills/kugetsu/scripts/kugetsu | 242 ++++++++++++++++++++-- skills/kugetsu/scripts/kugetsu-install.sh | 7 +- 5 files changed, 290 insertions(+), 108 deletions(-) diff --git a/docs/phase3a-setup.md b/docs/phase3a-setup.md index 61013ad..23d934f 100644 --- a/docs/phase3a-setup.md +++ b/docs/phase3a-setup.md @@ -21,15 +21,11 @@ hermes config show # Check Telegram is configured ```bash # Create skill directories mkdir -p ~/.hermes/skills/kugetsu-chat -mkdir -p ~/.hermes/skills/kugetsu-pm -mkdir -p ~/.hermes/skills/kugetsu-helpers # Link skills from kugetsu repo (adjust path as needed) KUGEETSU_DIR="/path/to/kugetsu" # e.g., ~/repositories/kugetsu ln -sf "$KUGEETSU_DIR/skills/kugetsu-chat" ~/.hermes/skills/kugetsu-chat -ln -sf "$KUGEETSU_DIR/skills/kugetsu-pm ~/.hermes/skills/kugetsu-pm -ln -sf "$KUGEETSU_DIR/skills/kugetsu-helpers" ~/.hermes/skills/kugetsu-helpers ``` ## Step 3: Install Chat Agent SOUL @@ -39,18 +35,7 @@ ln -sf "$KUGEETSU_DIR/skills/kugetsu-helpers" ~/.hermes/skills/kugetsu-helpers cp "$KUGEETSU_DIR/skills/kugetsu-chat/SOUL.md" ~/.hermes/SOUL-chat.md ``` -## Step 4: Install Helper Scripts - -```bash -# Copy helper script to PATH -cp "$KUGEETSU_DIR/skills/kugetsu-helpers/scripts/kugetsu-helpers" ~/.local/bin/kugetsu-helper -chmod +x ~/.local/bin/kugetsu-helper - -# Verify -kugetsu-helper help -``` - -## Step 5: Verify Gateway is Running +## Step 4: Verify Gateway is Running ```bash hermes gateway status @@ -58,7 +43,7 @@ hermes gateway status hermes gateway start ``` -## Step 6: Initialize kugetsu +## Step 5: Initialize kugetsu **WARNING:** This requires an interactive terminal (TTY) because it spawns the opencode TUI. @@ -75,22 +60,22 @@ kugetsu init # Run manually in the SSH session This creates: - **Base session** (for forking dev agents) -- **PM Agent session** (persistent coordinator) +- **PM Agent session** (persistent coordinator, loaded with kugetsu-pm context) If you get `Error: init requires a terminal (TTY)`, you're running via non-interactive SSH. Use `-t` flag or connect directly. -## Step 7: Verify Setup +## Step 6: Verify Setup ```bash # Check kugetsu status -kugetsu list - -# Check PM agent exists -kugetsu-helper check-status +kugetsu status # Should output: ok + +# List all sessions +kugetsu list ``` -## Step 8: Test via Telegram +## Step 7: Test via Telegram Start a conversation with your bot (@your_bot_username): @@ -102,7 +87,7 @@ Start a conversation with your bot (@your_bot_username): ## Troubleshooting -### kugetsu-helper not found +### kugetsu command not found ```bash export PATH="$HOME/.local/bin:$PATH" # Or add to ~/.bashrc @@ -114,22 +99,46 @@ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc hermes gateway restart ``` -### PM agent missing +### PM agent issues ```bash -# Reinitialize +# Diagnose +kugetsu doctor + +# Fix (if needed) +kugetsu doctor --fix + +# Or reinitialize kugetsu destroy --pm-agent -y kugetsu init ``` +## kugetsu Commands + +| Command | Description | +|---------|-------------| +| `kugetsu init` | Initialize base + PM agent sessions | +| `kugetsu status` | Check if kugetsu is ready | +| `kugetsu delegate ` | Send message to PM agent | +| `kugetsu doctor [--fix]` | Diagnose and fix issues | +| `kugetsu start ` | Start dev agent for issue | +| `kugetsu continue ` | Continue existing issue session | +| `kugetsu list` | List all tracked sessions | +| `kugetsu prune [--force]` | Clean up orphaned sessions | + ## File Locations | File | Location | Purpose | |------|----------|---------| | Chat Agent SOUL | `~/.hermes/SOUL-chat.md` | Personality | | kugetsu-chat skill | `~/.hermes/skills/kugetsu-chat/` | Routing behavior | -| kugetsu-pm skill | `~/.hermes/skills/kugetsu-pm/` | PM Agent docs | -| kugetsu-helpers | `~/.hermes/skills/kugetsu-helpers/` | Helper functions | -| Helper script | `~/.local/bin/kugetsu-helper` | CLI helper | +| kugetsu | `~/.local/bin/kugetsu` | Main CLI | + +~/.kugetsu/ +├── sessions/ +│ ├── base.json # Base opencode session +│ └── pm-agent.json # PM Agent opencode session +├── index.json # Session registry +└── pm-agent.md # PM context (optional, injected at init) ## Architecture Summary @@ -137,63 +146,25 @@ kugetsu init ~/.hermes/ ├── SOUL-chat.md # Chat Agent personality └── skills/ - ├── kugetsu-chat/ # Routing + delegation logic - ├── kugetsu-pm/ # PM Agent documentation - └── kugetsu-helpers/ # Shell helpers for terminal() + └── kugetsu-chat/ # Routing + delegation via kugetsu CLI ~/.kugetsu/ ├── sessions/ │ ├── base.json # Base opencode session │ └── pm-agent.json # PM Agent opencode session -└── index.json # Session registry +├── index.json # Session registry +└── pm-agent.md # PM context (optional) ~/.local/bin/ -└── kugetsu-helper # CLI helper script +└── kugetsu # Main CLI (handles delegation, status, doctor) ``` -## Testing Plan (Manual) +## PM Context (Optional) -### Test 1: Casual Conversation -**Objective:** Verify Hermes handles small talk directly without delegation - -| Step | Action | Expected Result | -|------|--------|-----------------| -| 1 | Send `hi` to @your_bot_username | Bot responds with greeting | -| 2 | Send `how are you?` | Bot responds naturally | - -### Test 2: Task Delegation -**Objective:** Verify Hermes delegates task to PM Agent via `kugetsu-helper` - -| Step | Action | Expected Result | -|------|--------|-----------------| -| 1 | Send `status?` to bot | Bot routes to PM, PM responds | -| 2 | Send `fix issue #5` to bot | PM agent receives task via opencode | -| 3 | Send `Work on issue #35` to bot | PM agent creates branch, worktree, PR | - -### Test 3: Error Handling -**Objective:** Verify graceful error handling - -| Step | Action | Expected Result | -|------|--------|-----------------| -| 1 | Send `status?` with PM agent stopped | Bot says "PM agent not available" | -| 2 | Send `status?` before `kugetsu init` | Bot says "kugetsu not initialized" | - -### Debugging - -If delegation fails: -```bash -# Check Hermes logs -hermes gateway logs - -# Check PM agent is running -kugetsu-helper check-status - -# Check kugetsu-helper directly -~/.local/bin/kugetsu-helper delegate-to-pm "test" -``` +To customize PM Agent behavior, create `~/.kugetsu/pm-agent.md` with additional context. This file is injected into the PM Agent session at init time. ## Security Notes - Never commit `~/.kugetsu/` or SOUL files to version control - Bot tokens should be in environment variables, not files -- PM agent session IDs are internal - don't expose to users \ No newline at end of file +- PM agent session IDs are internal - don't expose to users diff --git a/skills/kugetsu-chat/SKILL.md b/skills/kugetsu-chat/SKILL.md index ce31b35..1396d65 100644 --- a/skills/kugetsu-chat/SKILL.md +++ b/skills/kugetsu-chat/SKILL.md @@ -5,7 +5,7 @@ license: MIT compatibility: Requires Hermes agent with Telegram configured, kugetsu CLI, opencode sessions. metadata: author: shoko - version: "2.0" + version: "3.0" --- # kugetsu-chat - REQUIRED SKILL FOR KUGETSU ROUTING @@ -37,12 +37,12 @@ When you MUST use this skill: ### Step 2: Check if kugetsu is initialized ``` -terminal(command="~/.local/bin/kugetsu-helper check-status", timeout=10) +terminal(command="kugetsu status", timeout=10) ``` ### Step 3: If initialized, DELEGATE immediately ``` -terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm ''", timeout=120) +terminal(command="kugetsu delegate ''", timeout=120) ``` ### Step 4: Relay the response to the user @@ -52,12 +52,12 @@ terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm '' +kugetsu delegate '' ``` Example: ``` -terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm 'fix issue #5 in github.com/shoko/kugetsu'", timeout=120) +terminal(command="kugetsu delegate 'fix issue #5 in github.com/shoko/kugetsu'", timeout=120) ``` ## Error Handling @@ -67,26 +67,28 @@ terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm 'fix issue #5 in gi | `ok` | kugetsu is ready | Proceed with delegation | | `kugetsu_not_initialized` | Not set up | Tell user to run `kugetsu init` | | `pm_agent_missing` | PM not created | Tell user to run `kugetsu init` | +| `pm_agent_expired` | PM session expired | Tell user to run `kugetsu doctor --fix` | ## Quick Reference **DELEGATION COMMAND:** ``` -terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm ''", timeout=120) +terminal(command="kugetsu delegate ''", timeout=120) ``` **CHECK STATUS:** ``` -terminal(command="~/.local/bin/kugetsu-helper check-status", timeout=10) +terminal(command="kugetsu status", timeout=10) ``` -## Required Files +## Required Dependencies -- `~/.local/bin/kugetsu-helper` - The delegation helper script +- `kugetsu` CLI installed and in PATH +- kugetsu initialized via `kugetsu init` ## Notes -- ALWAYS use the full path `~/.local/bin/kugetsu-helper` -- ALWAYS use `delegate-to-pm` subcommand +- ALWAYS use `kugetsu delegate` command (not kugetsu-helper) - ALWAYS wrap user message in single quotes inside the command -- ALWAYS use timeout of at least 120 seconds for delegation \ No newline at end of file +- ALWAYS use timeout of at least 120 seconds for delegation +- kugetsu delegates to the persistent PM agent session created during init diff --git a/skills/kugetsu-chat/SOUL.md b/skills/kugetsu-chat/SOUL.md index c04b9c3..4385f9c 100644 --- a/skills/kugetsu-chat/SOUL.md +++ b/skills/kugetsu-chat/SOUL.md @@ -32,7 +32,7 @@ For ANY message that is not casual conversation, you MUST: ## Required Delegation Command ``` -terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm ''", timeout=120) +terminal(command="kugetsu delegate ''", timeout=120) ``` ## When NOT to Delegate diff --git a/skills/kugetsu/scripts/kugetsu b/skills/kugetsu/scripts/kugetsu index 7ea5cfd..df5f157 100755 --- a/skills/kugetsu/scripts/kugetsu +++ b/skills/kugetsu/scripts/kugetsu @@ -15,10 +15,13 @@ Usage: kugetsu init [--force] Initialize base + pm-agent sessions (requires TTY) kugetsu start [--debug] Start task for issue (forks base session) kugetsu continue [message] [--debug] Continue existing task for issue + kugetsu delegate Send message to PM agent + kugetsu status Check kugetsu initialization status + kugetsu doctor [--fix] Diagnose and fix kugetsu issues kugetsu list List all tracked sessions kugetsu prune [--force] Remove orphaned sessions (keeps base + pm-agent) kugetsu destroy [-y] Delete session for issue - kugetsu destroy --pm-agent [-y] Delete pm-agent session + kugetsu destroy --pm-agent [-y] Delete pm-agent session (not recommended) kugetsu destroy --base [-y] Delete base session kugetsu help Show this help @@ -32,6 +35,10 @@ Commands: start Fork new session from base for specific issue. Requires pm-agent to be running (created by init). continue Continue work on existing issue session. + delegate Send message to PM agent for task coordination. + PM context is loaded once at init time. + status Check if kugetsu is initialized and PM agent is active. + doctor Diagnose kugetsu issues. Use --fix to attempt repairs. list Show all sessions (base + pm-agent + forked issues). prune Remove sessions not in index (orphaned from opencode). Use --force to skip confirmation. @@ -40,14 +47,20 @@ Commands: Options: --debug Show real-time debug output and capture to debug.log +PM Context: + kugetsu reads ~/.kugetsu/pm-agent.md (if exists) and injects it + into the PM agent session at init time. This allows customizing PM + behavior without recreating the session. + Examples: kugetsu init + kugetsu status + kugetsu delegate "work on issue #5" + kugetsu doctor + kugetsu doctor --fix kugetsu start github.com/shoko/kugetsu#14 "fix bug" kugetsu continue github.com/shoko/kugetsu#14 "add tests" kugetsu list - kugetsu prune - kugetsu prune --force - kugetsu destroy github.com/shoko/kugetsu#14 EOF } @@ -283,6 +296,188 @@ check_opencode_session_exists() { opencode session list 2>/dev/null | grep -q "^$session_id" } +kugetsu_get_pm_context() { + local pm_context_file="${KUGETSU_DIR}/pm-agent.md" + if [ -f "$pm_context_file" ]; then + cat "$pm_context_file" + else + echo "" + fi +} + +cmd_status() { + if [ ! -f "$INDEX_FILE" ]; then + echo "kugetsu_not_initialized" + return + fi + + local base=$(get_base_session_id) + local pm_agent=$(get_pm_agent_session_id) + + if [ -z "$base" ] || [ "$base" = "null" ]; then + echo "base_session_missing" + return + fi + + if [ -z "$pm_agent" ] || [ "$pm_agent" = "null" ] || [ "$pm_agent" = "None" ]; then + echo "pm_agent_missing" + return + fi + + if ! check_opencode_session_exists "$pm_agent"; then + echo "pm_agent_expired" + return + fi + + echo "ok" +} + +cmd_delegate() { + local message="${1:-}" + + if [ -z "$message" ]; then + echo "Error: message is required" >&2 + echo "Usage: kugetsu delegate " >&2 + exit 1 + fi + + local pm_session=$(get_pm_agent_session_id) + if [ -z "$pm_session" ] || [ "$pm_session" = "null" ] || [ "$pm_session" = "None" ]; then + echo "Error: PM agent session not found. Run 'kugetsu init' first." >&2 + exit 1 + fi + + if ! check_opencode_session_exists "$pm_session"; then + echo "Error: PM agent session has expired. Run 'kugetsu init' again." >&2 + exit 1 + fi + + opencode run --continue --session "$pm_session" "$message" 2>&1 +} + +cmd_doctor() { + local fix=false + + while [ $# -gt 0 ]; do + case "$1" in + --fix) + fix=true + ;; + *) + ;; + esac + shift + done + + echo "=== kugetsu doctor ===" + echo "" + + local issues=0 + + if [ ! -f "$INDEX_FILE" ]; then + echo "[ISSUE] kugetsu not initialized (index.json missing)" + issues=$((issues + 1)) + else + echo "[OK] kugetsu initialized" + + local base=$(get_base_session_id) + if [ -z "$base" ] || [ "$base" = "null" ]; then + echo "[ISSUE] Base session missing" + issues=$((issues + 1)) + else + echo "[OK] Base session: $base" + if check_opencode_session_exists "$base"; then + echo "[OK] Base session active" + else + echo "[ISSUE] Base session expired" + issues=$((issues + 1)) + fi + fi + + local pm_agent=$(get_pm_agent_session_id) + if [ -z "$pm_agent" ] || [ "$pm_agent" = "null" ] || [ "$pm_agent" = "None" ]; then + echo "[ISSUE] PM agent session missing" + issues=$((issues + 1)) + else + echo "[OK] PM agent: $pm_agent" + if check_opencode_session_exists "$pm_agent"; then + echo "[OK] PM agent session active" + else + echo "[ISSUE] PM agent session expired" + issues=$((issues + 1)) + fi + fi + + local pm_context_file="${KUGETSU_DIR}/pm-agent.md" + if [ -f "$pm_context_file" ]; then + echo "[OK] PM context file exists" + else + echo "[INFO] PM context file not found (optional): $pm_context_file" + fi + fi + + echo "" + if [ $issues -eq 0 ]; then + echo "No issues found." + else + echo "Found $issues issue(s)." + fi + + if [ "$fix" = true ] && [ $issues -gt 0 ]; then + echo "" + echo "Running fixes..." + + if [ ! -f "$INDEX_FILE" ]; then + echo "Cannot fix: not initialized. Run 'kugetsu init' first." + else + local pm_agent=$(get_pm_agent_session_id) + if [ -n "$pm_agent" ] && [ "$pm_agent" != "null" ] && [ "$pm_agent" != "None" ]; then + if ! check_opencode_session_exists "$pm_agent"; then + echo "[FIX] Recreating expired PM agent session..." + local base=$(get_base_session_id) + if [ -n "$base" ] && [ "$base" != "null" ]; then + rm -f "$SESSIONS_DIR/pm-agent.json" + + local before_sessions=$(opencode session list 2>/dev/null | grep -oP '^ses_\w+' | sort) + local before_set="${before_sessions//$'\n'/|}" + + local pm_context=$(kugetsu_get_pm_context) + if [ -n "$pm_context" ]; then + opencode run --fork --session "$base" "You are a PM (Project Manager) agent. Your role is to coordinate task delegation and review PRs. $pm_context" 2>&1 || true + else + opencode run --fork --session "$base" "You are a PM (Project Manager) agent. Your role is to coordinate task delegation and review PRs. Wait for instructions." 2>&1 || true + fi + + local after_sessions=$(opencode session list 2>/dev/null | grep -oP '^ses_\w+' | sort) + local new_pm_session_id="" + while IFS= read -r sess; do + if [[ ! "$before_set" =~ \|${sess}\| ]] && [[ "$sess" != "$base" ]]; then + new_pm_session_id="$sess" + break + fi + done <<< "$after_sessions" + + if [ -n "$new_pm_session_id" ]; then + printf '{"type": "pm_agent", "opencode_session_id": "%s", "created_at": "%s", "state": "idle"}\n' \ + "$new_pm_session_id" "$(date -Iseconds)" > "$SESSIONS_DIR/pm-agent.json" + set_pm_agent_in_index "$new_pm_session_id" + echo "[FIX] PM agent recreated: $new_pm_session_id" + else + echo "[FIX] Warning: Could not detect new PM session ID" + fi + else + echo "[FIX] Cannot recreate PM agent: base session missing" + fi + else + echo "[FIX] PM agent is active, no fix needed" + fi + else + echo "[FIX] Cannot fix: PM agent not initialized. Run 'kugetsu init' first." + fi + fi + fi +} + DEBUG_MODE=false set_debug_mode() { @@ -365,7 +560,13 @@ cmd_init() { local before_sessions=$(opencode session list 2>/dev/null | grep -oP '^ses_\w+' | sort) local before_set="${before_sessions//$'\n'/|}" - opencode run --fork --session "$new_session_id" "You are a PM (Project Manager) agent. Your role is to coordinate task delegation and review PRs. Wait for instructions." 2>&1 || true + local pm_context=$(kugetsu_get_pm_context) + local pm_prompt="You are a PM (Project Manager) agent. Your role is to coordinate task delegation and review PRs. Wait for instructions." + if [ -n "$pm_context" ]; then + pm_prompt="You are a PM (Project Manager) agent. Your role is to coordinate task delegation and review PRs. $pm_context" + fi + + opencode run --fork --session "$new_session_id" "$pm_prompt" 2>&1 || true local after_sessions=$(opencode session list 2>/dev/null | grep -oP '^ses_\w+' | sort) local new_pm_session_id="" @@ -474,22 +675,22 @@ cmd_start() { } cmd_continue() { - local issue_ref="" + local session_name="" local message="" local args=("$@") args=$(set_debug_mode "${args[@]}") for arg in $args; do - if [ -z "$issue_ref" ]; then - issue_ref="$arg" + if [ -z "$session_name" ]; then + session_name="$arg" elif [ -z "$message" ]; then message="$arg" fi done - if [ -z "$issue_ref" ]; then - echo "Error: continue requires " >&2 + if [ -z "$session_name" ]; then + echo "Error: continue requires " >&2 exit 1 fi @@ -498,19 +699,17 @@ cmd_continue() { exit 1 fi - validate_issue_ref "$issue_ref" - - local session_file=$(get_session_for_issue "$issue_ref") + local session_file=$(get_session_for_issue "$session_name") if [ -z "$session_file" ] || [ "$session_file" = "null" ]; then - echo "Error: No session found for '$issue_ref'" >&2 - echo "Use 'kugetsu start $issue_ref ' to create one" >&2 + echo "Error: No session found for '$session_name'" >&2 + echo "Use 'kugetsu start ' to create one" >&2 exit 1 fi local session_path="$SESSIONS_DIR/$session_file" if [ ! -f "$session_path" ]; then echo "Error: Session file missing: $session_path" >&2 - echo "Run 'kugetsu start $issue_ref ' to recreate" >&2 + echo "Run 'kugetsu start ' to recreate" >&2 exit 1 fi @@ -522,7 +721,7 @@ cmd_continue() { echo "Attempting to continue anyway..." >&2 fi - echo "Continuing session for '$issue_ref'..." + echo "Continuing session for '$session_name'..." if [ -n "$worktree_path" ] && [ -d "$worktree_path" ]; then echo "Using worktree: $worktree_path" if [ "$DEBUG_MODE" = true ]; then @@ -770,6 +969,15 @@ main() { continue) cmd_continue "$@" ;; + delegate) + cmd_delegate "$@" + ;; + status) + cmd_status + ;; + doctor) + cmd_doctor "$@" + ;; list) cmd_list "$@" ;; diff --git a/skills/kugetsu/scripts/kugetsu-install.sh b/skills/kugetsu/scripts/kugetsu-install.sh index e84c270..9a52dcf 100755 --- a/skills/kugetsu/scripts/kugetsu-install.sh +++ b/skills/kugetsu/scripts/kugetsu-install.sh @@ -48,10 +48,8 @@ echo "=== Phase 3a Chat Agent Setup (Optional) ===" echo "To also install the Chat Agent skills for Phase 3a:" echo "" echo " 1. Link skills to Hermes:" -echo " mkdir -p ~/.hermes/skills/kugetsu-chat ~/.hermes/skills/kugetsu-pm ~/.hermes/skills/kugetsu-helpers" +echo " mkdir -p ~/.hermes/skills/kugetsu-chat" echo " ln -sf /path/to/kugetsu/skills/kugetsu-chat ~/.hermes/skills/" -echo " ln -sf /path/to/kugetsu/skills/kugetsu-pm ~/.hermes/skills/" -echo " ln -sf /path/to/kugetsu/skills/kugetsu-helpers ~/.hermes/skills/" echo "" echo " 2. Install Chat Agent SOUL:" echo " cp /path/to/kugetsu/skills/kugetsu-chat/SOUL.md ~/.hermes/SOUL-chat.md" @@ -59,4 +57,7 @@ echo "" echo " 3. Initialize kugetsu (requires TTY):" echo " kugetsu init" echo "" +echo " 4. Verify setup:" +echo " kugetsu status" +echo "" echo "See docs/phase3a-setup.md for full installation guide." \ No newline at end of file From 3d00ddbc1b44400e29e7f8b606f5b393d49a4588 Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Tue, 31 Mar 2026 02:19:50 +0000 Subject: [PATCH 10/14] feat(phase3): add notification system and kugetsu notify command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 3c implementation - Notification System: ### New kugetsu commands: - `kugetsu notify list` - Show unread notifications from PM Agent - `kugetsu notify clear` - Mark notifications as read ### Notification system: - PM Agent writes task events to ~/.kugetsu/notifications.json - Events: task_complete, task_blocked, task_assigned - Supports issue_ref and gitea_url for linking - Hermes/Chat Agent reads notifications on user messages ### kugetsu-pm v2.0: - Updated documentation with notification behavior - PM Agent monitors Gitea for task completion - Two review modes: PM reviews immediately OR asks dev if ready - Notification triggers documented ### File renamed: - phase3a-setup.md → kugetsu-chat-setup.md (more descriptive) ### Hermes gateway analysis: - Gateway is a client (connects to Telegram), not a server - Cannot push messages directly to Telegram from external process - Notifications stored locally for Hermes to pick up on next user message --- ...phase3a-setup.md => kugetsu-chat-setup.md} | 0 skills/kugetsu-pm/SKILL.md | 196 ++++++++++-------- skills/kugetsu/scripts/kugetsu | 150 ++++++++++++++ 3 files changed, 255 insertions(+), 91 deletions(-) rename docs/{phase3a-setup.md => kugetsu-chat-setup.md} (100%) diff --git a/docs/phase3a-setup.md b/docs/kugetsu-chat-setup.md similarity index 100% rename from docs/phase3a-setup.md rename to docs/kugetsu-chat-setup.md diff --git a/skills/kugetsu-pm/SKILL.md b/skills/kugetsu-pm/SKILL.md index aea1012..65016f8 100644 --- a/skills/kugetsu-pm/SKILL.md +++ b/skills/kugetsu-pm/SKILL.md @@ -1,11 +1,11 @@ --- name: kugetsu-pm -description: PM (Project Manager) Agent skill for kugetsu. Handles task coordination, delegation, and Gitea integration. +description: PM (Project Manager) Agent skill for kugetsu. Handles task coordination, delegation, and notifications. license: MIT compatibility: Requires kugetsu CLI, opencode sessions, Gitea API access. metadata: author: shoko - version: "1.0" + version: "2.0" --- # kugetsu-pm - PM Agent Skill @@ -18,37 +18,44 @@ The PM Agent is a persistent opencode session managed by kugetsu. It: 1. **Receives** task requests from Chat Agent (via Hermes) 2. **Coordinates** task execution via Dev Agents -3. **Monitors** Gitea for issue updates -4. **Notifies** users of task completion (if in notify mode) +3. **Monitors** Gitea for issue/PR updates +4. **Notifies** users of task completion and status changes 5. **Maintains** context across interactions ## Architecture ``` -Chat Agent (Hermes/Telegram) - │ - ├── Routes task requests - │ - ▼ -PM Agent (opencode session via kugetsu) - │ - ├── Creates Dev Agent sessions via kugetsu - │ - ▼ -Dev Agents (opencode sessions via kugetsu) - │ - ├── Work on issues autonomously - │ - ▼ -Gitea (Issues, PRs, Comments) +User (Telegram) → Hermes → Chat Agent → PM Agent + │ + ├── kugetsu start → Dev Agent + │ └── Work on issue + │ + └── notify ← Gitea (optional) + └── ~/.kugetsu/notifications.json ``` -## PM Agent Modes +## Notification System -| Mode | Behavior | Command | -|------|----------|---------| -| **notify** (default) | Send completion notifications | "pm notify" | -| **silent** | Work quietly, no notifications | "pm silent" | +PM Agent notifies users via two channels: + +### 1. Local Notifications (Default) +- PM Agent writes to `~/.kugetsu/notifications.json` +- Hermes/Chat Agent reads this file when user sends a message +- User can view with `kugetsu notify list` + +### 2. Gitea Comments (When Available) +- If task is issue/PR-related, PM Agent posts to Gitea +- User receives notification via Gitea's native notification system +- If Gitea is unavailable, PM Agent logs to notifications.json with a note + +### Notification Triggers + +| Event | Action | +|-------|--------| +| Task assigned to Dev Agent | Write to notifications.json | +| Task completed (PR merged/closed) | Write to notifications.json + Gitea | +| Task blocked | Write to notifications.json | +| Dev agent needs review | Two options: review immediately OR ask dev if ready | ## Task Flow @@ -79,77 +86,73 @@ PM Agent decides: kugetsu start "" ``` -### 5. Monitor and Notify +### 5. Monitor for Completion -- PM monitors Gitea for PR status -- When complete, notifies user (if in notify mode) +PM Agent monitors Gitea for task completion by checking: +- Issue comments +- PR commits +- PR status (merged/open) -## Gitea Integration - -### Context Fetching - -PM Agent fetches from Gitea when: -- Initial task load (no context) -- Explicit request (agent decides) -- Insufficient context - -### Context Merge Strategy - -- **Default**: Append new context to existing -- **Threshold**: Summarize + replace at 40% of context window - -## Session Context - -PM Agent maintains: - -### Managed Repositories -```json -{ - "repos": [ - "github.com/shoko/kugetsu", - "gitlab.com/team/core" - ] -} +**Query pattern for completion:** +```bash +# Check if issue/PR has recent activity +curl -s "https://git.fbrns.co/api/v1/repos/{owner}/{repo}/issues/{number}/comments" +# Check for commits in PR branch ``` -### Active Tasks -```json -{ - "tasks": { - "issue-5": { - "status": "in_progress", - "dev_agent": "ses_xyz789", - "created_at": "2026-03-30T10:00:00Z" - } - } -} -``` +### 6. Review Decision -### Notification Preferences +When dev agent signals completion, PM Agent chooses: + +**Option A: Review immediately** +- PM Agent reviews the PR/changes +- If good, merges or approves +- If issues, posts review comments + +**Option B: Ask dev if ready** +- PM Agent posts comment: "Dev work complete. Please review and confirm if ready for merge." +- Waits for dev agent confirmation +- Then proceeds with review + +### 7. Notify on Completion + +After task completion: +1. Write to `~/.kugetsu/notifications.json` +2. Post to Gitea issue/PR comment (if available) +3. If Gitea fails, note in notifications.json + +**Notification format:** ```json { - "mode": "notify" + "type": "task_complete", + "message": "Issue #5 fixed. PR #12 created and merged.", + "issue_ref": "github.com/shoko/kugetsu#5", + "gitea_url": "https://git.fbrns.co/shoko/kugetsu/pulls/12", + "timestamp": "2026-03-31T10:00:00Z" } ``` ## Delegation Commands -### Create Dev Agent Session +### Send message to PM Agent +```bash +kugetsu delegate "" +``` +### Create Dev Agent Session ```bash kugetsu start "" ``` ### Continue Dev Agent Session - ```bash kugetsu continue "" ``` -### List Active Sessions - +### Check Notifications ```bash -kugetsu list +kugetsu notify list +kugetsu notify clear ``` ## Response Format @@ -165,6 +168,7 @@ PM Agent responses should be: "Created task for issue #5. Dev agent started." "Issue #5 is complete. PR created: [link]" "Task blocked: Need clarification on requirements." +"Dev work ready for review. Merging PR #12." ``` ## Error Handling @@ -172,7 +176,7 @@ PM Agent responses should be: ### Dev Agent Failure - Analyze failure reason - Retry or escalate to user -- Log to Gitea issue comment +- Log to notifications.json ### Session Not Found - Check kugetsu status: `kugetsu list` @@ -182,18 +186,7 @@ PM Agent responses should be: ### Gitea API Errors - Retry with backoff - Cache last known state -- Inform user if persistent - -## Skills - -### kugetsu (for session management) -- Session creation and continuation -- Worktree management - -### github (for Gitea API) -- Issue fetching -- PR creation -- Comment posting +- Log to notifications.json (user will be notified there) ## Implementation Notes @@ -204,15 +197,36 @@ The PM Agent session is stored in: ~/.kugetsu/index.json → "pm_agent" field ``` -### Accessing PM Agent +### PM Context File (Optional) -```bash -PM_SESSION=$(cat ~/.kugetsu/index.json | python3 -c "import sys,json; print(json.load(sys.stdin).get('pm_agent', ''))") -opencode run --continue --session "$PM_SESSION" "" +Customize PM Agent behavior by creating: +``` +~/.kugetsu/pm-agent.md +``` + +This file is injected into the PM Agent session at init time. + +### Notifications File + +Location: `~/.kugetsu/notifications.json` + +Format: +```json +[ + { + "type": "task_complete|task_blocked|task_assigned", + "message": "Human-readable message", + "issue_ref": "github.com/user/repo#5", + "gitea_url": "https://git.fbrns.co/user/repo/pulls/5", + "timestamp": "ISO8601", + "read": false + } +] ``` ## Related Documentation - [kugetsu-architecture.md](../../docs/kugetsu-architecture.md) - [kugetsu-chat.md](../../docs/kugetsu-chat.md) -- [hermes-setup.md](../../docs/hermes-setup.md) \ No newline at end of file +- [kugetsu-chat-setup.md](../../docs/kugetsu-chat-setup.md) +- [hermes-setup.md](../../docs/hermes-setup.md) diff --git a/skills/kugetsu/scripts/kugetsu b/skills/kugetsu/scripts/kugetsu index df5f157..74051b9 100755 --- a/skills/kugetsu/scripts/kugetsu +++ b/skills/kugetsu/scripts/kugetsu @@ -6,6 +6,7 @@ SESSIONS_DIR="$KUGETSU_DIR/sessions" WORKTREES_DIR="$KUGETSU_DIR/worktrees" REPOS_CONFIG="$KUGETSU_DIR/repos.json" INDEX_FILE="$KUGETSU_DIR/index.json" +NOTIFICATIONS_FILE="$KUGETSU_DIR/notifications.json" usage() { cat << 'EOF' @@ -18,6 +19,7 @@ Usage: kugetsu delegate Send message to PM agent kugetsu status Check kugetsu initialization status kugetsu doctor [--fix] Diagnose and fix kugetsu issues + kugetsu notify [list|clear] Show or clear notifications kugetsu list List all tracked sessions kugetsu prune [--force] Remove orphaned sessions (keeps base + pm-agent) kugetsu destroy [-y] Delete session for issue @@ -39,6 +41,8 @@ Commands: PM context is loaded once at init time. status Check if kugetsu is initialized and PM agent is active. doctor Diagnose kugetsu issues. Use --fix to attempt repairs. + notify Show or clear notifications from PM agent. + Use 'kugetsu notify list' to see unread notifications. list Show all sessions (base + pm-agent + forked issues). prune Remove sessions not in index (orphaned from opencode). Use --force to skip confirmation. @@ -52,12 +56,18 @@ PM Context: into the PM agent session at init time. This allows customizing PM behavior without recreating the session. +Notifications: + PM Agent writes task completion notifications to ~/.kugetsu/notifications.json + Use 'kugetsu notify list' to see unread notifications. + Examples: kugetsu init kugetsu status kugetsu delegate "work on issue #5" kugetsu doctor kugetsu doctor --fix + kugetsu notify list + kugetsu notify clear kugetsu start github.com/shoko/kugetsu#14 "fix bug" kugetsu continue github.com/shoko/kugetsu#14 "add tests" kugetsu list @@ -305,6 +315,143 @@ kugetsu_get_pm_context() { fi } +kugetsu_add_notification() { + local type="$1" + local message="$2" + local issue_ref="${3:-}" + local gitea_url="${4:-}" + + mkdir -p "$(dirname "$NOTIFICATIONS_FILE")" + + local notification=$(python3 << PYEOF +import json +import os +from datetime import datetime + +notification = { + "type": "$type", + "message": "$message", + "issue_ref": "$issue_ref" if "$issue_ref" else None, + "gitea_url": "$gitea_url" if "$gitea_url" else None, + "timestamp": datetime.now().isoformat(), + "read": False +} + +file_path = os.path.expanduser("$NOTIFICATIONS_FILE") +notifications = [] + +if os.path.exists(file_path): + try: + with open(file_path, 'r') as f: + notifications = json.load(f) + except: + notifications = [] + +notifications.append(notification) + +with open(file_path, 'w') as f: + json.dump(notifications, f, indent=2) + +print("Notification added") +PYEOF +) + echo "$notification" +} + +kugetsu_get_notifications() { + local limit="${1:-10}" + + if [ ! -f "$NOTIFICATIONS_FILE" ]; then + echo "[]" + return + fi + + python3 << PYEOF +import json +import os +from datetime import datetime + +file_path = os.path.expanduser("$NOTIFICATIONS_FILE") + +if not os.path.exists(file_path): + print("[]") + exit(0) + +try: + with open(file_path, 'r') as f: + notifications = json.load(f) + + unread = [n for n in notifications if not n.get("read", False)] + unread.sort(key=lambda x: x.get("timestamp", ""), reverse=True) + + for n in unread[:$limit]: + ts = n.get("timestamp", "unknown") + ntype = n.get("type", "info") + msg = n.get("message", "") + issue = n.get("issue_ref", "") + gitea = n.get("gitea_url", "") + + print(f"[{ts}] {ntype}: {msg}") + if issue: + print(f" Issue: {issue}") + if gitea: + print(f" Link: {gitea}") + print() + + if not unread: + print("No unread notifications.") + +except Exception as e: + print(f"Error reading notifications: {e}") +PYEOF +} + +kugetsu_clear_notifications() { + if [ ! -f "$NOTIFICATIONS_FILE" ]; then + return + fi + + python3 << PYEOF +import json +import os + +file_path = os.path.expanduser("$NOTIFICATIONS_FILE") + +if not os.path.exists(file_path): + exit(0) + +try: + with open(file_path, 'r') as f: + notifications = json.load(f) + + for n in notifications: + n["read"] = True + + with open(file_path, 'w') as f: + json.dump(notifications, f, indent=2) + + print("Notifications marked as read") +except Exception as e: + print(f"Error: {e}") +PYEOF +} + +cmd_notify() { + local action="${1:-}" + + case "$action" in + ""|"list"|"show") + kugetsu_get_notifications 10 + ;; + "clear") + kugetsu_clear_notifications + ;; + *) + echo "Usage: kugetsu notify [list|clear]" + ;; + esac +} + cmd_status() { if [ ! -f "$INDEX_FILE" ]; then echo "kugetsu_not_initialized" @@ -978,6 +1125,9 @@ main() { doctor) cmd_doctor "$@" ;; + notify) + cmd_notify "$@" + ;; list) cmd_list "$@" ;; From bc40c4f500ab424d9b0bbe2aca194320d602d4f9 Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Tue, 31 Mar 2026 02:38:41 +0000 Subject: [PATCH 11/14] refactor: restructure PM role under skills/kugetsu/pm/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Changes: 1. **Moved kugetsu-pm to skills/kugetsu/pm/SKILL.md** - Simplified to 79 lines (under 100 line target) - kugetsu v3.0 with essential PM role definition - PM context injected at init/start/continue time 2. **Updated kugetsu_get_pm_context()** - Now reads from ~/.kugetsu/pm-agent.md (user custom) first - Falls back to skills/kugetsu/pm/SKILL.md (default) 3. **Updated kugetsu-chat v4.0** - Added notification checking on status/update queries - When user asks "status?", "any updates?", etc., check kugetsu notify list - Hybrid approach: PM includes notifications + kugetsu-chat checks on status 4. **Removed old skills/kugetsu-pm/SKILL.md** - Replaced by skills/kugetsu/pm/SKILL.md ### Structure: skills/kugetsu/ ├── SKILL.md ├── scripts/kugetsu ├── chat/ # future: kugetsu-chat could move here │ ├── SKILL.md │ └── SOUL.md └── pm/ └── SKILL.md # PM role definition (v3.0) --- skills/kugetsu-chat/SKILL.md | 35 ++++- skills/kugetsu-pm/SKILL.md | 232 --------------------------------- skills/kugetsu/pm/SKILL.md | 79 +++++++++++ skills/kugetsu/scripts/kugetsu | 10 +- 4 files changed, 115 insertions(+), 241 deletions(-) delete mode 100644 skills/kugetsu-pm/SKILL.md create mode 100644 skills/kugetsu/pm/SKILL.md diff --git a/skills/kugetsu-chat/SKILL.md b/skills/kugetsu-chat/SKILL.md index 1396d65..371b8ea 100644 --- a/skills/kugetsu-chat/SKILL.md +++ b/skills/kugetsu-chat/SKILL.md @@ -5,7 +5,7 @@ license: MIT compatibility: Requires Hermes agent with Telegram configured, kugetsu CLI, opencode sessions. metadata: author: shoko - version: "3.0" + version: "4.0" --- # kugetsu-chat - REQUIRED SKILL FOR KUGETSU ROUTING @@ -19,6 +19,7 @@ metadata: - Any message containing issue numbers like "#5", "#14", "#123" - Any message that looks like a task request or status query - Any message containing "pm", "status", "progress", "work on" +- Any message containing "notify", "updates", "notifications" **DO NOT USE THIS SKILL for:** - "hi", "hello", "hey" @@ -28,8 +29,6 @@ metadata: ## Required Actions -When you MUST use this skill: - ### Step 1: Load This Skill ``` /kugetsu-chat @@ -40,7 +39,15 @@ When you MUST use this skill: terminal(command="kugetsu status", timeout=10) ``` -### Step 3: If initialized, DELEGATE immediately +### Step 3: Route Based on Message Type + +**For STATUS/UPDATE queries:** +``` +terminal(command="kugetsu notify list", timeout=10) +``` +Then include notifications in response. + +**For TASK requests:** ``` terminal(command="kugetsu delegate ''", timeout=120) ``` @@ -49,7 +56,7 @@ terminal(command="kugetsu delegate ''", timeout=120) ## Delegation Command -The ONLY command you should use for delegation: +The command for task delegation: ```bash kugetsu delegate '' @@ -60,6 +67,16 @@ Example: terminal(command="kugetsu delegate 'fix issue #5 in github.com/shoko/kugetsu'", timeout=120) ``` +## Notification Checking + +**When user asks about status/updates, check notifications:** + +```bash +kugetsu notify list +``` + +Include any unread notifications in your response. + ## Error Handling | Status Output | Meaning | Action | @@ -76,6 +93,11 @@ terminal(command="kugetsu delegate 'fix issue #5 in github.com/shoko/kugetsu'", terminal(command="kugetsu delegate ''", timeout=120) ``` +**CHECK NOTIFICATIONS:** +``` +terminal(command="kugetsu notify list", timeout=10) +``` + **CHECK STATUS:** ``` terminal(command="kugetsu status", timeout=10) @@ -88,7 +110,8 @@ terminal(command="kugetsu status", timeout=10) ## Notes -- ALWAYS use `kugetsu delegate` command (not kugetsu-helper) +- ALWAYS use `kugetsu delegate` command - ALWAYS wrap user message in single quotes inside the command - ALWAYS use timeout of at least 120 seconds for delegation - kugetsu delegates to the persistent PM agent session created during init +- PM Agent writes task notifications to `~/.kugetsu/notifications.json` diff --git a/skills/kugetsu-pm/SKILL.md b/skills/kugetsu-pm/SKILL.md deleted file mode 100644 index 65016f8..0000000 --- a/skills/kugetsu-pm/SKILL.md +++ /dev/null @@ -1,232 +0,0 @@ ---- -name: kugetsu-pm -description: PM (Project Manager) Agent skill for kugetsu. Handles task coordination, delegation, and notifications. -license: MIT -compatibility: Requires kugetsu CLI, opencode sessions, Gitea API access. -metadata: - author: shoko - version: "2.0" ---- - -# kugetsu-pm - PM Agent Skill - -Defines the behavior of the PM (Project Manager) Agent in the kugetsu system. - -## Overview - -The PM Agent is a persistent opencode session managed by kugetsu. It: - -1. **Receives** task requests from Chat Agent (via Hermes) -2. **Coordinates** task execution via Dev Agents -3. **Monitors** Gitea for issue/PR updates -4. **Notifies** users of task completion and status changes -5. **Maintains** context across interactions - -## Architecture - -``` -User (Telegram) → Hermes → Chat Agent → PM Agent - │ - ├── kugetsu start → Dev Agent - │ └── Work on issue - │ - └── notify ← Gitea (optional) - └── ~/.kugetsu/notifications.json -``` - -## Notification System - -PM Agent notifies users via two channels: - -### 1. Local Notifications (Default) -- PM Agent writes to `~/.kugetsu/notifications.json` -- Hermes/Chat Agent reads this file when user sends a message -- User can view with `kugetsu notify list` - -### 2. Gitea Comments (When Available) -- If task is issue/PR-related, PM Agent posts to Gitea -- User receives notification via Gitea's native notification system -- If Gitea is unavailable, PM Agent logs to notifications.json with a note - -### Notification Triggers - -| Event | Action | -|-------|--------| -| Task assigned to Dev Agent | Write to notifications.json | -| Task completed (PR merged/closed) | Write to notifications.json + Gitea | -| Task blocked | Write to notifications.json | -| Dev agent needs review | Two options: review immediately OR ask dev if ready | - -## Task Flow - -### 1. Receive Task Request - -When Chat Agent routes a task: -``` -"fix issue #5" -``` - -### 2. Parse and Validate - -PM Agent extracts: -- Action (fix, create, test, research, etc.) -- Issue number or identifier -- Repository context - -### 3. Create Task Plan - -PM Agent decides: -- Can it be handled directly? -- Does it need a Dev Agent? -- What context is needed? - -### 4. Execute via Dev Agent - -```bash -kugetsu start "" -``` - -### 5. Monitor for Completion - -PM Agent monitors Gitea for task completion by checking: -- Issue comments -- PR commits -- PR status (merged/open) - -**Query pattern for completion:** -```bash -# Check if issue/PR has recent activity -curl -s "https://git.fbrns.co/api/v1/repos/{owner}/{repo}/issues/{number}/comments" -# Check for commits in PR branch -``` - -### 6. Review Decision - -When dev agent signals completion, PM Agent chooses: - -**Option A: Review immediately** -- PM Agent reviews the PR/changes -- If good, merges or approves -- If issues, posts review comments - -**Option B: Ask dev if ready** -- PM Agent posts comment: "Dev work complete. Please review and confirm if ready for merge." -- Waits for dev agent confirmation -- Then proceeds with review - -### 7. Notify on Completion - -After task completion: -1. Write to `~/.kugetsu/notifications.json` -2. Post to Gitea issue/PR comment (if available) -3. If Gitea fails, note in notifications.json - -**Notification format:** -```json -{ - "type": "task_complete", - "message": "Issue #5 fixed. PR #12 created and merged.", - "issue_ref": "github.com/shoko/kugetsu#5", - "gitea_url": "https://git.fbrns.co/shoko/kugetsu/pulls/12", - "timestamp": "2026-03-31T10:00:00Z" -} -``` - -## Delegation Commands - -### Send message to PM Agent -```bash -kugetsu delegate "" -``` - -### Create Dev Agent Session -```bash -kugetsu start "" -``` - -### Continue Dev Agent Session -```bash -kugetsu continue "" -``` - -### Check Notifications -```bash -kugetsu notify list -kugetsu notify clear -``` - -## Response Format - -PM Agent responses should be: -- **Concise** - Telegram-friendly -- **Action-oriented** - What's been done, what's next -- **Clear status** - In progress, done, blocked - -### Example Responses - -``` -"Created task for issue #5. Dev agent started." -"Issue #5 is complete. PR created: [link]" -"Task blocked: Need clarification on requirements." -"Dev work ready for review. Merging PR #12." -``` - -## Error Handling - -### Dev Agent Failure -- Analyze failure reason -- Retry or escalate to user -- Log to notifications.json - -### Session Not Found -- Check kugetsu status: `kugetsu list` -- Inform user of issue -- Suggest manual intervention - -### Gitea API Errors -- Retry with backoff -- Cache last known state -- Log to notifications.json (user will be notified there) - -## Implementation Notes - -### PM Agent Session ID - -The PM Agent session is stored in: -``` -~/.kugetsu/index.json → "pm_agent" field -``` - -### PM Context File (Optional) - -Customize PM Agent behavior by creating: -``` -~/.kugetsu/pm-agent.md -``` - -This file is injected into the PM Agent session at init time. - -### Notifications File - -Location: `~/.kugetsu/notifications.json` - -Format: -```json -[ - { - "type": "task_complete|task_blocked|task_assigned", - "message": "Human-readable message", - "issue_ref": "github.com/user/repo#5", - "gitea_url": "https://git.fbrns.co/user/repo/pulls/5", - "timestamp": "ISO8601", - "read": false - } -] -``` - -## Related Documentation - -- [kugetsu-architecture.md](../../docs/kugetsu-architecture.md) -- [kugetsu-chat.md](../../docs/kugetsu-chat.md) -- [kugetsu-chat-setup.md](../../docs/kugetsu-chat-setup.md) -- [hermes-setup.md](../../docs/hermes-setup.md) diff --git a/skills/kugetsu/pm/SKILL.md b/skills/kugetsu/pm/SKILL.md new file mode 100644 index 0000000..cbdc58b --- /dev/null +++ b/skills/kugetsu/pm/SKILL.md @@ -0,0 +1,79 @@ +--- +name: kugetsu-pm +description: PM (Project Manager) Agent role for kugetsu. Coordinates tasks and delegates to Dev Agents. +license: MIT +compatibility: Requires kugetsu CLI, opencode sessions, Gitea API access. +metadata: + author: shoko + version: "3.0" +--- + +# kugetsu-pm - PM Agent Role + +PM Agent is a persistent opencode session that coordinates tasks and delegates to Dev Agents. + +## Core Responsibilities + +1. Receive task requests from Chat Agent +2. Create Dev Agent sessions via `kugetsu start` +3. Monitor Gitea for task completion +4. Write notifications to `~/.kugetsu/notifications.json` +5. Respond concisely (Telegram-friendly) + +## Commands + +### Delegate to PM +```bash +kugetsu delegate "" +``` + +### Create Dev Agent +```bash +kugetsu start "" +``` + +### Continue Dev Agent +```bash +kugetsu continue "" +``` + +### Check Notifications +```bash +kugetsu notify list +``` + +## Notification Events + +Write to `~/.kugetsu/notifications.json` on: + +| Event | Action | +|-------|--------| +| Task assigned | Write: type=task_assigned | +| Task completed | Write: type=task_complete + Gitea comment | +| Task blocked | Write: type=task_blocked | +| Gitea unavailable | Write to notifications.json with note | + +## Task Completion Detection + +Check issue/PR for completion by querying: +- Issue comments for status updates +- PR commits (new commits = work in progress) +- PR merged/closed status + +## Review Modes + +When dev agent signals completion, choose: +- **Review immediately**: Check PR, merge if good +- **Ask dev**: Post "Ready for review?" comment, wait for confirmation + +## Response Format + +Keep responses short and action-oriented: +- "Created task for #5. Dev agent started." +- "#5 complete. PR #12 merged." +- "Blocked: Need clarification on #7." + +## Context Injection + +PM context is injected at session creation (init/start/continue). +No external skill loading needed. diff --git a/skills/kugetsu/scripts/kugetsu b/skills/kugetsu/scripts/kugetsu index 74051b9..1cf0b33 100755 --- a/skills/kugetsu/scripts/kugetsu +++ b/skills/kugetsu/scripts/kugetsu @@ -307,9 +307,13 @@ check_opencode_session_exists() { } kugetsu_get_pm_context() { - local pm_context_file="${KUGETSU_DIR}/pm-agent.md" - if [ -f "$pm_context_file" ]; then - cat "$pm_context_file" + local user_pm_context="${KUGETSU_DIR}/pm-agent.md" + local skill_pm_context="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../pm/SKILL.md" + + if [ -f "$user_pm_context" ]; then + cat "$user_pm_context" + elif [ -f "$skill_pm_context" ]; then + cat "$skill_pm_context" else echo "" fi From d35f006ed2be908e9cbb98f2cc8f501223edf778 Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Tue, 31 Mar 2026 02:46:42 +0000 Subject: [PATCH 12/14] docs: replace git.fbrns.co with git.example.com in documentation Sensitive URL replaced to prevent accidental exposure. --- docs/kugetsu-chat.md | 4 ++-- docs/kugetsu.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/kugetsu-chat.md b/docs/kugetsu-chat.md index 40092f5..9b97529 100644 --- a/docs/kugetsu-chat.md +++ b/docs/kugetsu-chat.md @@ -135,9 +135,9 @@ PM Agent │ PM sends clarification request ▼ Hermes (Chat Gateway) - │ "Which project did you mean? github.com/user/project or git.fbrns.co/team/core?" + │ "Which project did you mean? github.com/user/project or git.example.com/team/core?" ▼ -User (Telegram): "git.fbrns.co/team/core" +User (Telegram): "git.example.com/team/core" │ ▼ Hermes (Chat Gateway) diff --git a/docs/kugetsu.md b/docs/kugetsu.md index 6cf2497..0a3973a 100644 --- a/docs/kugetsu.md +++ b/docs/kugetsu.md @@ -61,7 +61,7 @@ Your focus shifts from doing to overseeing — reviewing PRs, approving plans, m ```bash # Clone repository -git clone https://git.fbrns.co/shoko/kugetsu.git +git clone https://git.example.com/shoko/kugetsu.git # Install kugetsu bash kugetsu/skills/kugetsu/scripts/kugetsu-install.sh From 93ebb55f577e2ec0b7ab43990b51e6b6e73d5563 Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Tue, 31 Mar 2026 02:48:23 +0000 Subject: [PATCH 13/14] refactor: remove obsolete kugetsu-helpers skill kugetsu-helpers was a shim layer that is no longer needed since: - kugetsu status replaces check-status - kugetsu delegate replaces delegate-to-pm - kugetsu doctor --fix replaces fix-permissions - kugetsu list/start/continue cover remaining functions All functionality is now in the kugetsu CLI directly. --- skills/kugetsu-helpers/SKILL.md | 166 -------------- .../kugetsu-helpers/scripts/kugetsu-helpers | 202 ----------------- .../tests/test-kugetsu-helpers.sh | 209 ------------------ 3 files changed, 577 deletions(-) delete mode 100644 skills/kugetsu-helpers/SKILL.md delete mode 100755 skills/kugetsu-helpers/scripts/kugetsu-helpers delete mode 100644 skills/kugetsu-helpers/tests/test-kugetsu-helpers.sh diff --git a/skills/kugetsu-helpers/SKILL.md b/skills/kugetsu-helpers/SKILL.md deleted file mode 100644 index 899f7d1..0000000 --- a/skills/kugetsu-helpers/SKILL.md +++ /dev/null @@ -1,166 +0,0 @@ ---- -name: kugetsu-helpers -description: Helper tools for Hermes to interact with kugetsu. Provides routing, delegation, and status functions. -license: MIT -compatibility: Requires Hermes agent, kugetsu CLI, opencode sessions. -metadata: - author: shoko - version: "1.0" ---- - -# kugetsu-helpers - Hermes Tools for Kugetsu - -Provides tools/functions for Hermes to route messages and delegate to the PM Agent. - -## Overview - -This skill enables Hermes (as Chat Agent) to interact with kugetsu-managed opencode sessions. - -## Tools - -### kugetsu_get_pm_session - -Gets the PM Agent session ID from kugetsu index. - -```bash -kugetsu_get_pm_session -``` - -**Returns:** PM agent session ID string, or empty if not initialized - -**Example:** -``` -PM_SESSION=$(kugetsu_get_pm_session) -echo "PM Agent: $PM_SESSION" -``` - -### kugetsu_delegate_to_pm - -Delegates a task to the PM Agent via opencode. - -```bash -kugetsu_delegate_to_pm "" -``` - -**Arguments:** -- `task message`: The task to delegate (e.g., "fix issue #5") - -**Returns:** PM Agent response (may be multi-line) - -**Example:** -``` -kugetsu_delegate_to_pm "User wants to fix issue #5 in github.com/shoko/kugetsu" -``` - -### kugetsu_check_status - -Checks kugetsu initialization status. - -```bash -kugetsu_check_status -``` - -**Returns:** Status string indicating: -- "ok" - kugetsu initialized, PM agent running -- "kugetsu_not_initialized" - Run kugetsu init first -- "pm_agent_missing" - PM agent not found - -### kugetsu_list_sessions - -Lists all kugetsu-managed sessions. - -```bash -kugetsu_list_sessions -``` - -**Returns:** Formatted list of sessions - -### kugetsu_create_dev_session - -Creates a Dev Agent session for an issue. - -```bash -kugetsu_create_dev_session "" "" -``` - -**Arguments:** -- `issue-ref`: Issue reference (e.g., "github.com/shoko/kugetsu#5") -- `task`: Task description for the dev agent - -**Returns:** Session creation status - -## Implementation - -These tools are implemented as shell functions that Hermes can call via `terminal()`. - -### Direct Implementation (Recommended) - -Add to Hermes SOUL.md as custom tools: - -``` -You have access to kugetsu via terminal commands: - -- kugetsu_get_pm_session: Get PM agent session ID -- kugetsu_delegate_to_pm : Delegate to PM agent -- kugetsu_check_status: Check kugetsu status -``` - -### Tool Definition Format - -Hermes tools should call these functions via terminal(): - -```python -{ - "name": "kugetsu_delegate", - "description": "Delegate a task to the PM Agent", - "parameters": { - "type": "object", - "properties": { - "task": { - "type": "string", - "description": "Task to delegate to PM Agent" - } - }, - "required": ["task"] - } -} -``` - -## Usage in Hermes - -### SOUL.md Integration - -Add to your SOUL.md: - -``` -You can interact with kugetsu to route tasks: - -1. Get PM agent session: terminal(command="kugetsu_get_pm_session") -2. Delegate to PM: terminal(command="kugetsu_delegate_to_pm 'fix issue #5'") -3. Check status: terminal(command="kugetsu_check_status") -``` - -### Routing Logic - -``` -User message → Hermes - │ - ├─ Small talk → respond directly - │ - └─ Task request → terminal(kugetsu_delegate_to_pm "") - │ - └─ PM Agent response → relay to user -``` - -## Error Handling - -| Error | Cause | Resolution | -|-------|-------|------------| -| "kugetsu not initialized" | Run `kugetsu init` | Inform user | -| "pm_agent_missing" | PM agent not created | Run `kugetsu init` | -| "session not found" | opencode session expired | May need reinit | - -## Files - -- `scripts/kugetsu-helpers.sh` - Shell implementations -- `SKILL.md` - This documentation \ No newline at end of file diff --git a/skills/kugetsu-helpers/scripts/kugetsu-helpers b/skills/kugetsu-helpers/scripts/kugetsu-helpers deleted file mode 100755 index 9d02eb8..0000000 --- a/skills/kugetsu-helpers/scripts/kugetsu-helpers +++ /dev/null @@ -1,202 +0,0 @@ -#!/bin/bash -# kugetsu-helpers - Shell functions for Hermes to interact with kugetsu -# -# These functions provide tools for routing and delegation to PM Agent. - -set -euo pipefail - -KUGETSU_DIR="${KUGETSU_DIR:-$HOME/.kugetsu}" -INDEX_FILE="$KUGETSU_DIR/index.json" - -kugetsu_get_pm_session() { - if [ ! -f "$INDEX_FILE" ]; then - echo "" - return - fi - - python3 -c "import json; print(json.load(open('$INDEX_FILE')).get('pm_agent', ''))" 2>/dev/null || echo "" -} - -kugetsu_check_status() { - if [ ! -f "$INDEX_FILE" ]; then - echo "kugetsu_not_initialized" - return - fi - - if ! grep -q '"pm_agent"' "$INDEX_FILE"; then - echo "pm_agent_missing" - return - fi - - PM_AGENT=$(kugetsu_get_pm_session) - if [ -z "$PM_AGENT" ] || [ "$PM_AGENT" = "null" ] || [ "$PM_AGENT" = "None" ]; then - echo "pm_agent_missing" - return - fi - - echo "ok" -} - -kugetsu_delegate_to_pm() { - local task="${1:-}" - - if [ -z "$task" ]; then - echo "Error: task is required" - return 1 - fi - - local pm_session=$(kugetsu_get_pm_session) - if [ -z "$pm_session" ] || [ "$pm_session" = "null" ] || [ "$pm_session" = "None" ]; then - echo "Error: PM agent session not found. Run 'kugetsu init' first." - return 1 - fi - - opencode run --continue --session "$pm_session" "$task" 2>&1 -} - -kugetsu_list_sessions() { - if command -v kugetsu &> /dev/null; then - kugetsu list 2>&1 - else - echo "kugetsu command not found" - return 1 - fi -} - -kugetsu_create_dev_session() { - local issue_ref="${1:-}" - local task="${2:-}" - - if [ -z "$issue_ref" ] || [ -z "$task" ]; then - echo "Error: issue_ref and task are required" - return 1 - fi - - if ! command -v kugetsu &> /dev/null; then - echo "Error: kugetsu command not found" - return 1 - fi - - kugetsu start "$issue_ref" "$task" 2>&1 -} - -kugetsu_continue_dev_session() { - local issue_ref="${1:-}" - local update="${2:-}" - - if [ -z "$issue_ref" ] || [ -z "$update" ]; then - echo "Error: issue_ref and update are required" - return 1 - fi - - if ! command -v kugetsu &> /dev/null; then - echo "Error: kugetsu command not found" - return 1 - fi - - kugetsu continue "$issue_ref" "$update" 2>&1 -} - -kugetsu_fix_pm_permissions() { - local pm_session=$(kugetsu_get_pm_session) - if [ -z "$pm_session" ] || [ "$pm_session" = "null" ] || [ "$pm_session" = "None" ]; then - echo "Error: PM agent session not found" - return 1 - fi - - python3 << PYEOF -import sqlite3 -import json -import os - -db_path = os.path.expanduser("~/.local/share/opencode/opencode.db") -conn = sqlite3.connect(db_path) -cursor = conn.cursor() - -# Get current permission for PM session -session_id = "$pm_session" -cursor.execute("SELECT id, permission FROM session WHERE id = ?", (session_id,)) -row = cursor.fetchone() - -if not row: - print(f"Error: Session {session_id} not found") - exit(1) - -perms = json.loads(row[1]) if row[1] else [] -patterns = [p['pattern'] for p in perms] - -# Add missing patterns for /tmp/kugetsu -needed = ['/tmp/kugetsu', '/tmp/kugetsu/*', '/tmp/kugetsu/**'] -added = [] - -for pattern in needed: - if pattern not in patterns: - perms.append({"permission": "external_directory", "pattern": pattern, "action": "allow"}) - added.append(pattern) - -if added: - new_perms = json.dumps(perms) - cursor.execute("UPDATE session SET permission = ? WHERE id = ?", (new_perms, session_id)) - conn.commit() - print(f"Added permissions: {', '.join(added)}") -else: - print("All required permissions already exist") -PYEOF -} - -# Main entry point for CLI usage -main() { - local command="${1:-}" - shift || true - - case "$command" in - get-pm-session) - kugetsu_get_pm_session - ;; - check-status) - kugetsu_check_status - ;; - delegate-to-pm) - kugetsu_delegate_to_pm "$@" - ;; - list-sessions) - kugetsu_list_sessions - ;; - create-dev-session) - kugetsu_create_dev_session "$@" - ;; - continue-dev-session) - kugetsu_continue_dev_session "$@" - ;; - fix-permissions) - kugetsu_fix_pm_permissions - ;; - help|--help|-h) - cat << 'EOF' -kugetsu-helpers - Hermes tools for kugetsu - -Commands: - get-pm-session Get PM agent session ID - check-status Check kugetsu initialization status - delegate-to-pm Delegate task to PM agent - list-sessions List all kugetsu sessions - create-dev-session Create dev agent session - continue-dev-session Continue dev agent session - fix-permissions Fix opencode permission for /tmp/kugetsu access - -Usage in Hermes: - terminal(command="~/.local/bin/kugetsu-helper delegate-to-pm 'fix issue #5'", timeout=120) - -Note: If PM agent has permission issues accessing /tmp/kugetsu, run: - kugetsu-helper fix-permissions -EOF - ;; - *) - echo "Error: Unknown command '$command'" - echo "Run 'kugetsu-helpers help' for usage" - return 1 - ;; - esac -} - -main "$@" \ No newline at end of file diff --git a/skills/kugetsu-helpers/tests/test-kugetsu-helpers.sh b/skills/kugetsu-helpers/tests/test-kugetsu-helpers.sh deleted file mode 100644 index d4705a9..0000000 --- a/skills/kugetsu-helpers/tests/test-kugetsu-helpers.sh +++ /dev/null @@ -1,209 +0,0 @@ -#!/bin/bash -# kugetsu-helpers test suite -# Tests the shell helper functions for Hermes/Chat Agent integration -# -# Run with: bash skills/kugetsu-helpers/tests/test-kugetsu-helpers.sh - -set -euo pipefail - -KUGETSU_HELPERS="./skills/kugetsu-helpers/scripts/kugetsu-helpers" -TEST_PM_SESSION_ID="ses_test_pm_789" -TEST_ISSUE_REF="github.com/shoko/kugetsu#14" -PASS=0 -FAIL=0 - -cleanup() { - rm -rf ~/.kugetsu/sessions/* ~/.kugetsu/index.json 2>/dev/null || true -} - -setup_mock_index_uninitialized() { - cleanup -} - -setup_mock_index_no_pm_agent() { - mkdir -p ~/.kugetsu/sessions - cat > ~/.kugetsu/index.json << EOF -{ - "base": "ses_base_123", - "pm_agent": null, - "issues": {} -} -EOF -} - -setup_mock_index_with_pm_agent() { - mkdir -p ~/.kugetsu/sessions - cat > ~/.kugetsu/index.json << EOF -{ - "base": "ses_base_123", - "pm_agent": "$TEST_PM_SESSION_ID", - "issues": {} -} -EOF - cat > ~/.kugetsu/sessions/pm-agent.json << EOF -{"type": "pm_agent", "opencode_session_id": "$TEST_PM_SESSION_ID", "created_at": "2026-03-30T18:00:00+02:00", "state": "idle"} -EOF -} - -pass() { - echo "PASS: $1" - PASS=$((PASS + 1)) -} - -fail() { - echo "FAIL: $1" - FAIL=$((FAIL + 1)) -} - -cleanup - -echo "=== kugetsu-helpers Test Suite ===" -echo "" - -# Test 1: check-status when not initialized -echo "--- Test: check-status (not initialized) ---" -setup_mock_index_uninitialized -OUTPUT=$($KUGETSU_HELPERS check-status 2>&1 || true) -if [ "$OUTPUT" = "kugetsu_not_initialized" ]; then - pass "check-status returns kugetsu_not_initialized when no index.json" -else - fail "check-status not initialized: got '$OUTPUT', expected 'kugetsu_not_initialized'" -fi -echo "" - -# Test 2: check-status when pm_agent field is missing -echo "--- Test: check-status (missing pm_agent field) ---" -setup_mock_index_no_pm_agent -OUTPUT=$($KUGETSU_HELPERS check-status 2>&1 || true) -if [ "$OUTPUT" = "pm_agent_missing" ]; then - pass "check-status returns pm_agent_missing when field is null" -else - fail "check-status missing pm_agent: got '$OUTPUT', expected 'pm_agent_missing'" -fi -echo "" - -# Test 3: check-status when PM agent exists -echo "--- Test: check-status (PM agent exists) ---" -setup_mock_index_with_pm_agent -OUTPUT=$($KUGETSU_HELPERS check-status 2>&1 || true) -if [ "$OUTPUT" = "ok" ]; then - pass "check-status returns ok when PM agent exists" -else - fail "check-status ok: got '$OUTPUT', expected 'ok'" -fi -echo "" - -# Test 4: get-pm-session returns session ID when exists -echo "--- Test: get-pm-session (exists) ---" -setup_mock_index_with_pm_agent -OUTPUT=$($KUGETSU_HELPERS get-pm-session 2>&1 || true) -if [ "$OUTPUT" = "$TEST_PM_SESSION_ID" ]; then - pass "get-pm-session returns correct session ID" -else - fail "get-pm-session: got '$OUTPUT', expected '$TEST_PM_SESSION_ID'" -fi -echo "" - -# Test 5: get-pm-session returns empty when not initialized -echo "--- Test: get-pm-session (not initialized) ---" -setup_mock_index_uninitialized -OUTPUT=$($KUGETSU_HELPERS get-pm-session 2>&1 || true) -if [ -z "$OUTPUT" ]; then - pass "get-pm-session returns empty when not initialized" -else - fail "get-pm-session not initialized: got '$OUTPUT', expected ''" -fi -echo "" - -# Test 6: delegate-to-pm fails without task argument -echo "--- Test: delegate-to-pm (no task) ---" -setup_mock_index_with_pm_agent -OUTPUT=$($KUGETSU_HELPERS delegate-to-pm 2>&1 || true) -if echo "$OUTPUT" | grep -q "Error: task is required"; then - pass "delegate-to-pm fails without task" -else - fail "delegate-to-pm no task: got '$OUTPUT', expected error about task required" -fi -echo "" - -# Test 7: delegate-to-pm fails when PM agent missing -echo "--- Test: delegate-to-pm (PM agent missing) ---" -setup_mock_index_uninitialized -OUTPUT=$($KUGETSU_HELPERS delegate-to-pm "test task" 2>&1 || true) -if echo "$OUTPUT" | grep -q "Error: PM agent session not found"; then - pass "delegate-to-pm fails when PM agent not found" -else - fail "delegate-to-pm missing PM: got '$OUTPUT', expected error" -fi -echo "" - -# Test 8: list-sessions when kugetsu not installed -echo "--- Test: list-sessions (kugetsu not installed) ---" -cleanup -TMPDIR=$(mktemp -d) -KUGETSU_BAK="" -if command -v kugetsu &> /dev/null; then - KUGETSU_PATH=$(command -v kugetsu) - KUGETSU_BAK="${TMPDIR}/kugetsu.bak" - mv "$KUGETSU_PATH" "$KUGETSU_BAK" -fi -OUTPUT=$($KUGETSU_HELPERS list-sessions 2>&1 || true) -if [ -n "$KUGETSU_BAK" ]; then - mv "$KUGETSU_BAK" "$KUGETSU_PATH" -fi -rmdir "$TMPDIR" 2>/dev/null || true -if echo "$OUTPUT" | grep -q "kugetsu command not found"; then - pass "list-sessions fails gracefully when kugetsu not found" -else - fail "list-sessions no kugetsu: got '$OUTPUT', expected error" -fi -echo "" - -# Test 9: help command works -echo "--- Test: help command ---" -OUTPUT=$($KUGETSU_HELPERS help 2>&1 || true) -if echo "$OUTPUT" | grep -q "delegate-to-pm"; then - pass "help shows delegate-to-pm command" -else - fail "help: output missing delegate-to-pm" -fi -echo "" - -# Test 10: unknown command fails gracefully -echo "--- Test: unknown command ---" -OUTPUT=$($KUGETSU_HELPERS unknown-cmd 2>&1 || true) -if echo "$OUTPUT" | grep -q "Error: Unknown command"; then - pass "unknown command fails gracefully" -else - fail "unknown command: got '$OUTPUT', expected error" -fi -echo "" - -# Test 11: check-status handles malformed JSON gracefully -echo "--- Test: check-status (malformed JSON) ---" -mkdir -p ~/.kugetsu/sessions -echo "not valid json" > ~/.kugetsu/index.json -OUTPUT=$($KUGETSU_HELPERS check-status 2>&1 || true) -if [ "$OUTPUT" = "pm_agent_missing" ]; then - pass "check-status handles malformed JSON gracefully" -else - fail "check-status malformed JSON: got '$OUTPUT', expected 'pm_agent_missing'" -fi -echo "" - -# Cleanup -cleanup - -echo "" -echo "=== Test Summary ===" -echo "Passed: $PASS" -echo "Failed: $FAIL" -echo "" - -if [ $FAIL -eq 0 ]; then - echo "All tests passed!" - exit 0 -else - echo "Some tests failed." - exit 1 -fi \ No newline at end of file From 9e1ff743304ee6fcbcef256eec8552e404435207 Mon Sep 17 00:00:00 2001 From: shokollm <270575765+shokollm@users.noreply.github.com> Date: Tue, 31 Mar 2026 02:52:31 +0000 Subject: [PATCH 14/14] test(kugetsu): add unit tests for status, delegate, doctor, notify commands Added 10 new tests: - kugetsu status (5 tests): uninitialized, base missing, pm-agent missing, Python None handling, session expired - kugetsu delegate (2 tests): no message, pm-agent missing - kugetsu doctor (1 test): basic command execution - kugetsu notify (2 tests): list with no file, clear with no file Total tests: 38 (all passing) --- skills/kugetsu/tests/test-kugetsu-v2.sh | 129 ++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/skills/kugetsu/tests/test-kugetsu-v2.sh b/skills/kugetsu/tests/test-kugetsu-v2.sh index a89c257..2d6cf52 100644 --- a/skills/kugetsu/tests/test-kugetsu-v2.sh +++ b/skills/kugetsu/tests/test-kugetsu-v2.sh @@ -354,6 +354,135 @@ else fi echo "" +# Test 21: status when not initialized +echo "--- Test: status (not initialized) ---" +cleanup +OUTPUT=$($KUGETSU status 2>&1 || true) +if [ "$OUTPUT" = "kugetsu_not_initialized" ]; then + pass "status returns kugetsu_not_initialized when no index.json" +else + fail "status not initialized: got '$OUTPUT', expected 'kugetsu_not_initialized'" +fi +echo "" + +# Test 22: status when base missing +echo "--- Test: status (base missing) ---" +mkdir -p ~/.kugetsu/sessions +cat > ~/.kugetsu/index.json << EOF +{ + "base": null, + "pm_agent": "$TEST_PM_AGENT_SESSION_ID", + "issues": {} +} +EOF +OUTPUT=$($KUGETSU status 2>&1 || true) +if [ "$OUTPUT" = "base_session_missing" ]; then + pass "status returns base_session_missing when base is null" +else + fail "status base missing: got '$OUTPUT', expected 'base_session_missing'" +fi +echo "" + +# Test 23: status when pm-agent missing +echo "--- Test: status (pm-agent missing) ---" +cat > ~/.kugetsu/index.json << EOF +{ + "base": "$TEST_BASE_SESSION_ID", + "pm_agent": null, + "issues": {} +} +EOF +OUTPUT=$($KUGETSU status 2>&1 || true) +if [ "$OUTPUT" = "pm_agent_missing" ]; then + pass "status returns pm_agent_missing when pm_agent is null" +else + fail "status pm_agent missing: got '$OUTPUT', expected 'pm_agent_missing'" +fi +echo "" + +# Test 24: status when pm-agent is "None" (Python None output) +echo "--- Test: status (pm-agent is Python None) ---" +cat > ~/.kugetsu/index.json << EOF +{ + "base": "$TEST_BASE_SESSION_ID", + "pm_agent": "None", + "issues": {} +} +EOF +OUTPUT=$($KUGETSU status 2>&1 || true) +if [ "$OUTPUT" = "pm_agent_missing" ]; then + pass "status returns pm_agent_missing when pm_agent is 'None'" +else + fail "status pm_agent 'None': got '$OUTPUT', expected 'pm_agent_missing'" +fi +echo "" + +# Test 25: status when all good (pm-agent in json but session expired) +echo "--- Test: status (session expired) ---" +setup_mock_base +OUTPUT=$($KUGETSU status 2>&1 || true) +if [ "$OUTPUT" = "pm_agent_expired" ]; then + pass "status returns pm_agent_expired when session not in opencode" +else + fail "status session expired: got '$OUTPUT', expected 'pm_agent_expired'" +fi +echo "" + +# Test 26: delegate without message +echo "--- Test: delegate (no message) ---" +cleanup +OUTPUT=$($KUGETSU delegate 2>&1 || true) +if echo "$OUTPUT" | grep -q "Error: message is required"; then + pass "delegate fails without message" +else + fail "delegate no message: got '$OUTPUT', expected error about message required" +fi +echo "" + +# Test 27: delegate when pm-agent missing +echo "--- Test: delegate (pm-agent missing) ---" +setup_mock_base +OUTPUT=$($KUGETSU delegate "test" 2>&1 || true) +if echo "$OUTPUT" | grep -q "Error: PM agent session"; then + pass "delegate fails when PM agent not found" +else + fail "delegate pm-agent missing: got '$OUTPUT', expected error about PM agent" +fi +echo "" + +# Test 28: doctor command works +echo "--- Test: doctor command ---" +cleanup +OUTPUT=$($KUGETSU doctor 2>&1 || true) +if echo "$OUTPUT" | grep -q "kugetsu doctor"; then + pass "doctor command works" +else + fail "doctor command: got '$OUTPUT', expected doctor output" +fi +echo "" + +# Test 29: notify list when no file +echo "--- Test: notify list (no file) ---" +cleanup +OUTPUT=$($KUGETSU notify list 2>&1 || true) +if [ "$OUTPUT" = "[]" ]; then + pass "notify list returns empty array when file missing" +else + fail "notify list no file: got '$OUTPUT', expected '[]'" +fi +echo "" + +# Test 30: notify clear when no file +echo "--- Test: notify clear (no file) ---" +cleanup +OUTPUT=$($KUGETSU notify clear 2>&1 || true) +if [ -z "$OUTPUT" ] || echo "$OUTPUT" | grep -q "marked as read"; then + pass "notify clear works when file missing (no-op)" +else + fail "notify clear: got '$OUTPUT', expected success or empty" +fi +echo "" + # Cleanup cleanup