Compare commits
3 Commits
v0.2.0
...
990bc46477
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
990bc46477 | ||
| e1050cb70a | |||
|
|
0f66de2929 |
@@ -326,7 +326,7 @@ When a Coding Agent starts, it:
|
|||||||
| Phase 1 | ✅ Complete | SSH + Tailscale remote access |
|
| Phase 1 | ✅ Complete | SSH + Tailscale remote access |
|
||||||
| Phase 1b | ✅ Complete | Tailscale VPN setup |
|
| Phase 1b | ✅ Complete | Tailscale VPN setup |
|
||||||
| Phase 2 | 📋 Planned | API Interface |
|
| Phase 2 | 📋 Planned | API Interface |
|
||||||
| Phase 3 | ✅ Implemented | Chat Integration (Telegram) |
|
| Phase 3 | 🔄 In Progress | Chat Integration (Telegram) |
|
||||||
| Phase 4 | 📋 Planned | Web Dashboard |
|
| Phase 4 | 📋 Planned | Web Dashboard |
|
||||||
|
|
||||||
### 6.2 Current Implementation
|
### 6.2 Current Implementation
|
||||||
|
|||||||
@@ -48,10 +48,6 @@ A default config file is created during `kugetsu init` with commented examples:
|
|||||||
|----------|---------|-------------|
|
|----------|---------|-------------|
|
||||||
| `MAX_CONCURRENT_AGENTS` | 3 | Maximum number of concurrent dev agents |
|
| `MAX_CONCURRENT_AGENTS` | 3 | Maximum number of concurrent dev agents |
|
||||||
| `KUGETSU_TEMP_DIR` | `~/.local/share/opencode/tool-output` | Temp directory for subagent tool output (useful in headless environments where /tmp is restricted) |
|
| `KUGETSU_TEMP_DIR` | `~/.local/share/opencode/tool-output` | Temp directory for subagent tool output (useful in headless environments where /tmp is restricted) |
|
||||||
| `KUGETSU_VERBOSITY` | `default` | PM agent verbosity level: `verbose`, `default`, or `quiet` |
|
|
||||||
| `QUEUE_DAEMON_INTERVAL_MINUTES` | 5 | How often daemon polls queue (in minutes) |
|
|
||||||
| `QUEUE_DAEMON_BATCH_SIZE` | 2 | How many tasks daemon picks per poll |
|
|
||||||
| `QUEUE_CLEANUP_AGE_DAYS` | 7 | Auto-cleanup completed/error items older than N days |
|
|
||||||
|
|
||||||
### Environment Variables for Agents
|
### Environment Variables for Agents
|
||||||
|
|
||||||
@@ -114,10 +110,6 @@ Each issue session gets its own git worktree to prevent conflicts:
|
|||||||
├── worktrees/
|
├── worktrees/
|
||||||
│ ├── github.com-shoko-kugetsu-14/ # Isolated workdir for issue #14
|
│ ├── github.com-shoko-kugetsu-14/ # Isolated workdir for issue #14
|
||||||
│ └── github.com-shoko-kugetsu-15/ # Isolated workdir for issue #15
|
│ └── github.com-shoko-kugetsu-15/ # Isolated workdir for issue #15
|
||||||
├── queue/
|
|
||||||
│ ├── items/ # Queue item JSON files
|
|
||||||
│ ├── daemon.pid # Daemon process ID
|
|
||||||
│ └── daemon.log # Daemon log output
|
|
||||||
└── index.json # Maps session IDs and issue refs to session files
|
└── index.json # Maps session IDs and issue refs to session files
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -263,152 +255,23 @@ kugetsu destroy --base -y
|
|||||||
|
|
||||||
**Note**: Destroying base also destroys PM agent since PM depends on base.
|
**Note**: Destroying base also destroys PM agent since PM depends on base.
|
||||||
|
|
||||||
### kugetsu delegate `<message>`
|
|
||||||
|
|
||||||
Send a message to the PM agent for task coordination via queue:
|
|
||||||
```bash
|
|
||||||
kugetsu delegate "work on issue #14"
|
|
||||||
kugetsu delegate "review PR #92"
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Always enqueues** (fire-and-forget): returns immediately
|
|
||||||
- Queue daemon polls queue and invokes PM when slots available
|
|
||||||
- Tasks are processed FIFO (first-in-first-out)
|
|
||||||
- Use `kugetsu queue list` to see pending tasks
|
|
||||||
- Use `kugetsu queue-daemon logs` to debug queue processing
|
|
||||||
|
|
||||||
### kugetsu logs [n]
|
|
||||||
|
|
||||||
Show recent delegation logs:
|
|
||||||
```bash
|
|
||||||
kugetsu logs # Show last 10 logs
|
|
||||||
kugetsu logs 20 # Show last 20 logs
|
|
||||||
```
|
|
||||||
|
|
||||||
- Logs are stored in `~/.kugetsu/logs/`
|
|
||||||
- Automatically deletes logs older than 7 days
|
|
||||||
|
|
||||||
### kugetsu status
|
|
||||||
|
|
||||||
Check if kugetsu is properly initialized:
|
|
||||||
```bash
|
|
||||||
kugetsu status
|
|
||||||
```
|
|
||||||
|
|
||||||
Output:
|
|
||||||
- `kugetsu_not_initialized` - No index file
|
|
||||||
- `base_session_missing` - Base session not found
|
|
||||||
- `pm_agent_missing` - PM agent not found
|
|
||||||
- `ok` - Everything is initialized
|
|
||||||
|
|
||||||
### kugetsu doctor [--fix]
|
|
||||||
|
|
||||||
Diagnose and fix kugetsu issues:
|
|
||||||
```bash
|
|
||||||
kugetsu doctor # Show diagnostic info
|
|
||||||
kugetsu doctor --fix # Attempt automatic repairs
|
|
||||||
```
|
|
||||||
|
|
||||||
- Checks index file existence
|
|
||||||
- Validates base and PM agent sessions
|
|
||||||
- With `--fix`: recreates PM agent if missing
|
|
||||||
- With `--fix-permissions`: fixes session permissions in opencode database
|
|
||||||
|
|
||||||
### kugetsu notify [list|clear]
|
|
||||||
|
|
||||||
Show or clear notifications from PM agent:
|
|
||||||
```bash
|
|
||||||
kugetsu notify list # Show unread notifications (default)
|
|
||||||
kugetsu notify clear # Mark all as read
|
|
||||||
```
|
|
||||||
|
|
||||||
- PM agent writes task completion notifications to `~/.kugetsu/notifications.json`
|
|
||||||
- Shows timestamp, type, message, and issue ref for each notification
|
|
||||||
|
|
||||||
### kugetsu server <list|add|remove|default|get>
|
|
||||||
|
|
||||||
Manage git server configurations:
|
|
||||||
```bash
|
|
||||||
kugetsu server list # List all configured servers
|
|
||||||
kugetsu server add github https://github.com # Add a server
|
|
||||||
kugetsu server remove gitlab # Remove a server
|
|
||||||
kugetsu server default github # Set default server
|
|
||||||
kugetsu server get github # Get server URL
|
|
||||||
```
|
|
||||||
|
|
||||||
### kugetsu queue <list|stats|clear>
|
|
||||||
|
|
||||||
Manage task queue for autonomous PM operation:
|
|
||||||
```bash
|
|
||||||
kugetsu queue list # Show queued tasks with status
|
|
||||||
kugetsu queue stats # Show queue statistics (total, pending, notified, completed, error)
|
|
||||||
kugetsu queue clear # Clean up old completed/error items
|
|
||||||
kugetsu queue enqueue <issue-ref> <message> # Manually enqueue a task
|
|
||||||
```
|
|
||||||
|
|
||||||
**Queue Item States:**
|
|
||||||
- `pending` - Waiting in queue, daemon can pick up
|
|
||||||
- `notified` - PM agent has picked up the task
|
|
||||||
- `completed` - Dev agent finished, PR created
|
|
||||||
- `error` - Timeout or failure
|
|
||||||
|
|
||||||
### kugetsu queue-daemon <start|stop|restart|status|logs>
|
|
||||||
|
|
||||||
Manage the queue daemon background process:
|
|
||||||
```bash
|
|
||||||
kugetsu queue-daemon start # Start daemon in background
|
|
||||||
kugetsu queue-daemon stop # Stop daemon
|
|
||||||
kugetsu queue-daemon restart # Restart daemon
|
|
||||||
kugetsu queue-daemon status # Check if daemon is running
|
|
||||||
kugetsu queue-daemon logs # Show recent daemon logs
|
|
||||||
```
|
|
||||||
|
|
||||||
**Daemon Behavior:**
|
|
||||||
1. Runs at configurable interval (default: 5 minutes)
|
|
||||||
2. Checks if active agents < MAX_CONCURRENT_AGENTS
|
|
||||||
3. Picks 1-N pending items (configurable batch size)
|
|
||||||
4. Forks PM session for each picked item
|
|
||||||
5. PM decides whether to use `start` or `continue`
|
|
||||||
|
|
||||||
**Queue Directory:**
|
|
||||||
```
|
|
||||||
~/.kugetsu/queue/
|
|
||||||
├── items/ # Queue item JSON files
|
|
||||||
│ ├── q_1234567890.json # One file per queued task
|
|
||||||
│ └── q_1234567891.json
|
|
||||||
├── daemon.pid # Daemon process ID
|
|
||||||
├── daemon.lock # Daemon lock file
|
|
||||||
└── daemon.log # Daemon log output
|
|
||||||
```
|
|
||||||
|
|
||||||
## Workflow Example
|
## Workflow Example
|
||||||
|
|
||||||
### First-time Setup
|
|
||||||
```bash
|
```bash
|
||||||
# Initialize kugetsu (requires TTY)
|
# First-time setup (requires TTY)
|
||||||
kugetsu init
|
kugetsu init
|
||||||
|
# Creates: base session + pm-agent session
|
||||||
|
|
||||||
# Start the queue daemon (for autonomous operation)
|
# Start work on issue
|
||||||
kugetsu queue-daemon start
|
kugetsu start github.com/shoko/kugetsu#14 "implement feature X"
|
||||||
```
|
# Creates: worktree at ~/.kugetsu/worktrees/github.com-shoko-kugetsu-14/
|
||||||
|
|
||||||
### Normal Workflow
|
# Continue later
|
||||||
```bash
|
|
||||||
# Enqueue tasks via delegate - agents will process them automatically
|
|
||||||
kugetsu delegate "work on issue #14"
|
|
||||||
kugetsu delegate "review PR #92"
|
|
||||||
|
|
||||||
# Check queue status
|
|
||||||
kugetsu queue list # See pending tasks
|
|
||||||
kugetsu queue stats # See statistics
|
|
||||||
|
|
||||||
# Debug queue daemon
|
|
||||||
kugetsu queue-daemon status # Is daemon running?
|
|
||||||
kugetsu queue-daemon logs # See daemon logs
|
|
||||||
|
|
||||||
# Continue work on existing issue
|
|
||||||
kugetsu continue github.com/shoko/kugetsu#14 "add tests"
|
kugetsu continue github.com/shoko/kugetsu#14 "add tests"
|
||||||
|
|
||||||
|
# Continue again
|
||||||
|
kugetsu continue github.com/shoko/kugetsu#14 "fix failing test"
|
||||||
|
|
||||||
# List all sessions
|
# List all sessions
|
||||||
kugetsu list
|
kugetsu list
|
||||||
|
|
||||||
@@ -419,21 +282,6 @@ kugetsu prune --force
|
|||||||
kugetsu destroy github.com/shoko/kugetsu#14
|
kugetsu destroy github.com/shoko/kugetsu#14
|
||||||
```
|
```
|
||||||
|
|
||||||
### Queue Daemon Management
|
|
||||||
```bash
|
|
||||||
# Check if daemon is running
|
|
||||||
kugetsu queue-daemon status
|
|
||||||
|
|
||||||
# View daemon logs for debugging
|
|
||||||
kugetsu queue-daemon logs
|
|
||||||
|
|
||||||
# Restart daemon if needed
|
|
||||||
kugetsu queue-daemon restart
|
|
||||||
|
|
||||||
# Stop daemon
|
|
||||||
kugetsu queue-daemon stop
|
|
||||||
```
|
|
||||||
|
|
||||||
## Headless Operation
|
## Headless Operation
|
||||||
|
|
||||||
This design solves the headless CLI limitation discovered in Issue #14:
|
This design solves the headless CLI limitation discovered in Issue #14:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
277
skills/kugetsu/tests/test-kugetsu.sh
Executable file
277
skills/kugetsu/tests/test-kugetsu.sh
Executable file
@@ -0,0 +1,277 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# kugetsu test suite
|
||||||
|
# Run with: bash skills/kugetsu/tests/test-kugetsu.sh
|
||||||
|
#
|
||||||
|
# Memory management approach:
|
||||||
|
# - Sequential test execution (no parallel)
|
||||||
|
# - Cleanup between tests that spawn opencode
|
||||||
|
# - No hard memory cap (ulimit -v breaks Bun/opencode)
|
||||||
|
# - If OOM occurs, it is a known failure mode
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
KUGETSU="./skills/kugetsu/scripts/kugetsu"
|
||||||
|
TEST_SESSION_PREFIX="kugetsu-test-"
|
||||||
|
PASS=0
|
||||||
|
FAIL=0
|
||||||
|
|
||||||
|
cleanup_sessions() {
|
||||||
|
for dir in ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}*; do
|
||||||
|
[ -d "$dir" ] && rm -rf "$dir" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup_opencode() {
|
||||||
|
pkill -f "opencode.*${TEST_SESSION_PREFIX}" 2>/dev/null || true
|
||||||
|
pkill -f "kugetsu.*${TEST_SESSION_PREFIX}" 2>/dev/null || true
|
||||||
|
sleep 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
cleanup_sessions
|
||||||
|
cleanup_opencode
|
||||||
|
}
|
||||||
|
|
||||||
|
pass() {
|
||||||
|
echo "✅ PASS: $1"
|
||||||
|
PASS=$((PASS + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
echo "❌ FAIL: $1"
|
||||||
|
FAIL=$((FAIL + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
|
||||||
|
echo "=== kugetsu Test Suite ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 1: Help
|
||||||
|
echo "--- Test: help ---"
|
||||||
|
if $KUGETSU help 2>&1 | grep -q "kugetsu - OpenCode Session Manager"; then
|
||||||
|
pass "help displays usage"
|
||||||
|
else
|
||||||
|
fail "help displays usage"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 2: List empty
|
||||||
|
echo "--- Test: list (empty) ---"
|
||||||
|
if $KUGETSU list 2>&1 | grep -q "SESSION_ID"; then
|
||||||
|
pass "list shows header even when empty"
|
||||||
|
else
|
||||||
|
fail "list shows header even when empty"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 3: List --all empty
|
||||||
|
echo "--- Test: list --all (empty) ---"
|
||||||
|
if $KUGETSU list --all 2>&1 | grep -q "SESSION_ID"; then
|
||||||
|
pass "list --all shows header even when empty"
|
||||||
|
else
|
||||||
|
fail "list --all shows header even when empty"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 4: Start session (quick exit)
|
||||||
|
echo "--- Test: start session ---"
|
||||||
|
if timeout 15 bash -c "$KUGETSU start ${TEST_SESSION_PREFIX}start-test 'echo hello'" 2>&1; then
|
||||||
|
if [ -d ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}start-test ]; then
|
||||||
|
pass "start creates session directory"
|
||||||
|
else
|
||||||
|
fail "start creates session directory"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
fail "start runs successfully"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 5: List shows only left by default
|
||||||
|
echo "--- Test: list default filters non-left ---"
|
||||||
|
if ! $KUGETSU list 2>&1 | grep -q "${TEST_SESSION_PREFIX}start-test"; then
|
||||||
|
pass "list default hides idle sessions"
|
||||||
|
else
|
||||||
|
fail "list default hides idle sessions"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 6: List --all shows all
|
||||||
|
echo "--- Test: list --all shows all states ---"
|
||||||
|
if $KUGETSU list --all 2>&1 | grep -q "${TEST_SESSION_PREFIX}start-test"; then
|
||||||
|
pass "list --all shows all sessions"
|
||||||
|
else
|
||||||
|
fail "list --all shows all sessions"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 7: Resume with auto-fill
|
||||||
|
echo "--- Test: resume auto-fill ---"
|
||||||
|
mkdir -p ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}resume-test
|
||||||
|
echo "left" > ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}resume-test/state
|
||||||
|
echo "continue this task" > ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}resume-test/message
|
||||||
|
|
||||||
|
OUTPUT=$(timeout 10 bash -c "$KUGETSU resume ${TEST_SESSION_PREFIX}resume-test" 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "Auto-filled message: continue this task"; then
|
||||||
|
pass "resume auto-fills stored message"
|
||||||
|
else
|
||||||
|
fail "resume auto-fills stored message"
|
||||||
|
fi
|
||||||
|
cleanup
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 8: Resume with provided message overrides
|
||||||
|
echo "--- Test: resume with message overrides ---"
|
||||||
|
mkdir -p ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}resume-override
|
||||||
|
echo "left" > ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}resume-override/state
|
||||||
|
echo "original message" > ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}resume-override/message
|
||||||
|
|
||||||
|
OUTPUT=$(timeout 30 bash -c "$KUGETSU resume ${TEST_SESSION_PREFIX}resume-override 'new message'" 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "new message" && ! echo "$OUTPUT" | grep -q "Auto-filled message"; then
|
||||||
|
pass "resume uses provided message over auto-fill"
|
||||||
|
else
|
||||||
|
fail "resume uses provided message over auto-fill: $OUTPUT"
|
||||||
|
fi
|
||||||
|
cleanup
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 9: Resume idle session fails
|
||||||
|
echo "--- Test: resume idle session fails ---"
|
||||||
|
rm -rf ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}idle-test 2>/dev/null
|
||||||
|
mkdir -p ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}idle-test
|
||||||
|
echo "idle" > ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}idle-test/state
|
||||||
|
|
||||||
|
OUTPUT=$(timeout 5 bash -c "$KUGETSU resume ${TEST_SESSION_PREFIX}idle-test" 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "cannot be resumed"; then
|
||||||
|
pass "resume idle session fails with message"
|
||||||
|
else
|
||||||
|
echo "DEBUG: $OUTPUT"
|
||||||
|
fail "resume idle session fails with message"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 10: Resume non-existent session fails
|
||||||
|
echo "--- Test: resume non-existent session fails ---"
|
||||||
|
rm -rf ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}nonexistent 2>/dev/null
|
||||||
|
OUTPUT=$(timeout 5 bash -c "$KUGETSU resume ${TEST_SESSION_PREFIX}nonexistent" 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "not found"; then
|
||||||
|
pass "resume non-existent session fails"
|
||||||
|
else
|
||||||
|
echo "DEBUG: $OUTPUT"
|
||||||
|
fail "resume non-existent session fails"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 11: Stop non-used session fails
|
||||||
|
echo "--- Test: stop non-used session fails ---"
|
||||||
|
rm -rf ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}notused 2>/dev/null
|
||||||
|
mkdir -p ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}notused
|
||||||
|
echo "idle" > ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}notused/state
|
||||||
|
|
||||||
|
OUTPUT=$(timeout 5 bash -c "$KUGETSU stop ${TEST_SESSION_PREFIX}notused" 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "not in use"; then
|
||||||
|
pass "stop non-used session fails"
|
||||||
|
else
|
||||||
|
echo "DEBUG: $OUTPUT"
|
||||||
|
fail "stop non-used session fails"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test 12: Start existing left session resumes instead
|
||||||
|
echo "--- Test: start on left session resumes ---"
|
||||||
|
mkdir -p ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}left-start
|
||||||
|
echo "left" > ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}left-start/state
|
||||||
|
echo "original task" > ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}left-start/message
|
||||||
|
|
||||||
|
OUTPUT=$(timeout 10 bash -c "$KUGETSU start ${TEST_SESSION_PREFIX}left-start 'new task'" 2>&1 || true)
|
||||||
|
if echo "$OUTPUT" | grep -q "Resuming instead"; then
|
||||||
|
pass "start on left session resumes"
|
||||||
|
else
|
||||||
|
fail "start on left session resumes"
|
||||||
|
fi
|
||||||
|
cleanup
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# FLAKY TESTS - Commented out due to timing/process behavior issues
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# Test: Stop active session (FLAKY - timing dependent)
|
||||||
|
# echo "--- Test: stop active session (FLAKY) ---"
|
||||||
|
# (
|
||||||
|
# timeout 20 bash -c "$KUGETSU start ${TEST_SESSION_PREFIX}stop-test 'sleep 30'" 2>&1 &
|
||||||
|
# KUGETSU_PID=$!
|
||||||
|
# sleep 3
|
||||||
|
#
|
||||||
|
# # Check session is in use
|
||||||
|
# if ! $KUGETSU list --all 2>&1 | grep -q "${TEST_SESSION_PREFIX}stop-test.*used"; then
|
||||||
|
# echo "⚠️ SKIP (FLAKY): Could not verify session was used"
|
||||||
|
# elif timeout 5 bash -c "$KUGETSU stop ${TEST_SESSION_PREFIX}stop-test" 2>&1; then
|
||||||
|
# if [ "$(cat ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}stop-test/state 2>/dev/null)" = "idle" ]; then
|
||||||
|
# echo "✅ PASS (FLAKY): stop transitions to idle"
|
||||||
|
# else
|
||||||
|
# echo "❌ FAIL (FLAKY): stop does not transition to idle"
|
||||||
|
# fi
|
||||||
|
# else
|
||||||
|
# echo "❌ FAIL (FLAKY): stop command failed"
|
||||||
|
# fi
|
||||||
|
#
|
||||||
|
# wait $KUGETSU_PID 2>/dev/null || true
|
||||||
|
# ) 2>&1 || true
|
||||||
|
|
||||||
|
# Test: Interrupt session leaves state as left (FLAKY - opencode signal handling)
|
||||||
|
# echo "--- Test: interrupt session leaves left (FLAKY) ---"
|
||||||
|
# (
|
||||||
|
# bash -c "$KUGETSU start ${TEST_SESSION_PREFIX}interrupt-test 'sleep 30'" 2>&1 &
|
||||||
|
# KUGETSU_PID=$!
|
||||||
|
# sleep 3
|
||||||
|
#
|
||||||
|
# # Find and kill opencode process
|
||||||
|
# OPENCODE_PID=$(pgrep -f "opencode.*${TEST_SESSION_PREFIX}interrupt-test" | head -1 || true)
|
||||||
|
# if [ -n "$OPENCODE_PID" ]; then
|
||||||
|
# kill -9 $OPENCODE_PID 2>/dev/null || true
|
||||||
|
# fi
|
||||||
|
#
|
||||||
|
# wait $KUGETSU_PID 2>/dev/null || true
|
||||||
|
# sleep 1
|
||||||
|
#
|
||||||
|
# STATE=$(cat ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}interrupt-test/state 2>/dev/null || echo "unknown")
|
||||||
|
# if [ "$STATE" = "left" ]; then
|
||||||
|
# echo "✅ PASS (FLAKY): interrupt leaves state as left"
|
||||||
|
# else
|
||||||
|
# echo "❌ FAIL (FLAKY): interrupt left state=$STATE (expected left)"
|
||||||
|
# fi
|
||||||
|
# ) 2>&1 || true
|
||||||
|
|
||||||
|
# Test: Concurrent resume attempts (FLAKY - race condition)
|
||||||
|
# echo "--- Test: concurrent resume (FLAKY) ---"
|
||||||
|
# mkdir -p ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}concurrent
|
||||||
|
# echo "left" > ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}concurrent/state
|
||||||
|
# echo "test task" > ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}concurrent/message
|
||||||
|
#
|
||||||
|
# (
|
||||||
|
# timeout 10 bash -c "$KUGETSU resume ${TEST_SESSION_PREFIX}concurrent" 2>&1 &
|
||||||
|
# timeout 10 bash -c "$KUGETSU resume ${TEST_SESSION_PREFIX}concurrent" 2>&1
|
||||||
|
# ) 2>&1 || true
|
||||||
|
#
|
||||||
|
# echo "⚠️ NOTE (FLAKY): This test is informational only - no assertion"
|
||||||
|
# rm -rf ~/.kugetsu/sessions/${TEST_SESSION_PREFIX}concurrent
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# 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
|
||||||
Reference in New Issue
Block a user