diff --git a/AGENTS.md b/AGENTS.md index 1787c21..ade1578 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,6 +2,8 @@ Guide for coding agents working on `opencode-mission-control` in ULW mode. +> NOTE! Never replace the string opencode with claude or claude code unless explicitly asked to. + ## Mission - Keep changes small, safe, and shippable. diff --git a/MANUAL_TEST_PLAN.md b/MANUAL_TEST_PLAN.md index 87f51cb..f9ec92b 100644 --- a/MANUAL_TEST_PLAN.md +++ b/MANUAL_TEST_PLAN.md @@ -3,6 +3,9 @@ > **Context**: We are dogfooding this plugin from within the plugin's own repo. > All `mc_*` tool calls are made by the AI agent (us) in this session. > This plan covers **all 17 MCP tools**, **all 12 job states**, and **all 8 plan states**. +> +> **v1.5 additions**: Phases 13–18 cover serve-mode launch, enhanced `mc_attach`, structured +> observability, session-aware notifications, permission policies, and dynamic orchestration. > **Dynamic Path Convention**: All paths use `$(basename $(git rev-parse --show-toplevel))` instead of > hardcoded project names. This makes the plan portable across repos and forks. @@ -77,6 +80,16 @@ git worktree prune 2>/dev/null || true echo "Cleaning jobs state..." rm -f "$STATE_DIR/state/jobs.json" 2>/dev/null || true +# 12. Clean port allocation (v1.5 serve mode) +echo "Cleaning port allocation..." +rm -f "$STATE_DIR/port.lock" 2>/dev/null || true + +# 13. Kill leaked serve-mode server processes (ports 14100-14199) +echo "Killing leaked serve processes..." +for p in $(lsof -ti:14100-14199 2>/dev/null); do + kill "$p" 2>/dev/null || true +done + echo "=== Nuclear Cleanup Complete ===" ``` @@ -115,6 +128,9 @@ ls -la dist/index.js 9. **Cancel before completion**: Plans must be cancelled before all jobs reach `merged` state. If all jobs merge, the plan auto-pushes to remote and enters `creating_pr` state. 10. **Dynamic paths only**: Never hardcode project names in paths. Always use `$(basename $(git rev-parse --show-toplevel))` or the `$PROJECT_NAME` variable. 11. **Agent timing**: Simple prompts (echo, file creation) complete in 10-25 seconds. If you need the agent to be in `running` state when you check, either check within 5-10 seconds of launch, use a longer-running prompt like "Read every file in src/ and summarize each one", or kill the agent immediately after launch. +12. **Serve mode default (v1.5)**: `useServeMode` defaults to `true`. Jobs launch via `opencode serve` + SDK. To test TUI-mode behavior, temporarily set `"useServeMode": false` in `config.json` and restore afterwards. +13. **Port range (v1.5)**: Serve mode allocates ports from 14100–14199 using `port.lock`. Cleanup releases ports. If stuck, remove `port.lock` manually from the state directory. +14. **Serve mode startup time**: Serve-mode jobs need 5–10 seconds to start (server boot + SDK session creation), compared to 3–5 seconds for TUI mode. Adjust wait times accordingly. --- @@ -134,9 +150,12 @@ Run these tests for basic validation after a code change. References use test ID | 8 | Phase 9 | 9.4 (overview with jobs) | Dashboard with data | | 9 | Phase 5G | 5.76 (retry + relaunch mutual exclusion) | TouchSet param validation | | 10 | Phase 9 | 9.14 (overview after cleanup) | Dashboard cleanup | -| 11 | Phase 12 | Nuclear Cleanup | Clean exit | +| 11 | Phase 13 | 13.1-13.7 (serve mode launch → status → verify port) | Serve mode basics | +| 12 | Phase 14 | 14.3 (mc_attach opens tmux window for serve job) | Enhanced attach | +| 13 | Phase 15 | 15.5 (mc_capture returns JSON for serve job) | Structured capture | +| 14 | Phase 12 | Nuclear Cleanup | Clean exit | -**Pass criteria**: All 11 steps succeed. If any fail, run the full test plan for that phase. +**Pass criteria**: All 14 steps succeed. If any fail, run the full test plan for that phase. --- @@ -146,23 +165,23 @@ All 17 tools must be exercised during this plan. Check off as tested: | Tool | Phase(s) | Notes | |------|----------|-------| -| `mc_launch` | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 | Core lifecycle | -| `mc_jobs` | 1, 2, 3, 4, 5, 6, 9 | List/filter jobs | -| `mc_status` | 1, 2, 9, 10 | Detailed job info | -| `mc_capture` | 1, 2, 7, 8, 10 | Terminal output | -| `mc_attach` | 1, 2 | Tmux attach command | +| `mc_launch` | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 13 | Core lifecycle + serve mode | +| `mc_jobs` | 1, 2, 3, 4, 5, 6, 9, 13 | List/filter jobs | +| `mc_status` | 1, 2, 9, 10, 13, 15 | Detailed job info + serve telemetry | +| `mc_capture` | 1, 2, 7, 8, 10, 15 | Terminal output + structured events | +| `mc_attach` | 1, 2, 14 | Tmux attach / serve TUI window | | `mc_diff` | 1, 2, 4 | Branch comparison | -| `mc_kill` | 1, 2, 3, 4, 6, 7, 8 | Stop running jobs | -| `mc_cleanup` | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12 | Remove artifacts | +| `mc_kill` | 1, 2, 3, 4, 6, 7, 8, 13 | Stop running jobs | +| `mc_cleanup` | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13 | Remove artifacts + port release | | `mc_sync` | 4 | Rebase/merge sync | | `mc_merge` | 4, 6 | Merge to main | | `mc_pr` | — | **NOT tested** (pushes to remote). Structural mention only. | -| `mc_plan` | 5, 6 | Create orchestrated plans | -| `mc_plan_status` | 5, 6 | Plan progress | -| `mc_plan_cancel` | 5, 6 | Cancel active plan | +| `mc_plan` | 5, 6, 18 | Create orchestrated plans + dynamic features | +| `mc_plan_status` | 5, 6, 18 | Plan progress | +| `mc_plan_cancel` | 5, 6, 18 | Cancel active plan | | `mc_plan_approve` | 5, 5G | Approve copilot/supervisor, accept/relaunch/retry touchSet violations | | `mc_report` | 8 | Agent status reporting (filesystem verification) | -| `mc_overview` | 9 | Dashboard summary | +| `mc_overview` | 9, 15 | Dashboard summary + activity indicators | --- @@ -978,6 +997,8 @@ These cannot be directly invoked but can be observed during testing. ## Phase 12 — Final Verification & Nuclear Cleanup +> **Run this LAST** — after all feature phases (including Phases 13–18). + This ensures we leave the repo in **exactly** the same state we found it. ### 12.1 — Run Nuclear Cleanup @@ -1043,6 +1064,14 @@ rm -f "$STATE_DIR/state/plan.json" 2>/dev/null || true # Clean jobs state rm -f "$STATE_DIR/state/jobs.json" 2>/dev/null || true + +# Clean port allocation (v1.5) +rm -f "$STATE_DIR/port.lock" 2>/dev/null || true + +# Kill leaked serve-mode server processes (v1.5) +for p in $(lsof -ti:14100-14199 2>/dev/null); do + kill "$p" 2>/dev/null || true +done ``` ### 12.7 — Verify against pre-test snapshot @@ -1064,6 +1093,301 @@ rm -f "$STATE_DIR/state/jobs.json" 2>/dev/null || true --- +## Phase 13 — Serve Mode Launch & Port Management (#65) + +> **Context**: v1.5 defaults to `useServeMode: true`. Jobs launch via `opencode serve` on an +> allocated port (range 14100–14199), with prompts delivered via the SDK instead of +> `opencode --prompt`. This phase validates the serve-mode launch path, port allocation, +> and port release on cleanup. +> +> **Prerequisites**: `useServeMode` must be `true` in config (this is the default). If you +> previously overrode it, restore: edit `config.json` or remove the `useServeMode` key. +> +> **Timing Note**: Serve-mode jobs need 5–10 seconds to start (server boot + SDK session +> creation). Adjust wait times vs TUI mode (3–5 seconds). + +### 13A: Basic Serve Mode Launch + +| # | Test | Action | Expected | +|---|------|--------|----------| +| 13.1 | Launch serve mode job | `mc_launch` name=tmc-serve, prompt="Create a file test-serve.txt with 'hello from serve'" | Success message includes Port and Server URL | +| 13.2 | **Wait 5-10 seconds** | Allow server startup + SDK session creation | — | +| 13.3 | Verify port in output | Check launch response | Contains `Port: 14100` (or next available) and `Server: http://127.0.0.1:` | +| 13.4 | Verify status includes serve fields | `mc_status` name=tmc-serve | Shows `Port: ` and `Server URL: http://...` under Metadata | +| 13.5 | Verify tmux session exists | `tmux list-sessions \| grep mc-tmc-serve` | Session present (serves `opencode serve`) | +| 13.6 | Verify port lock file | `cat $STATE_DIR/port.lock` | JSON array containing the allocated port number | +| 13.7 | Verify job state persisted | `mc_jobs` | tmc-serve shown as `running` | +| 13.8 | Verify launchSessionID captured | Read `$STATE_DIR/state/jobs.json` | Job entry has `launchSessionID` field matching your current session | + +### 13B: Port Allocation Uniqueness + +| # | Test | Action | Expected | +|---|------|--------|----------| +| 13.9 | Launch second serve job | `mc_launch` name=tmc-serve-2, prompt="echo hello" | Success, different port | +| 13.10 | **Wait 5-10 seconds** | — | — | +| 13.11 | Verify unique ports | Compare `mc_status` tmc-serve vs `mc_status` tmc-serve-2 | Different port numbers (e.g., 14100 and 14101) | +| 13.12 | Both in port lock | Read port.lock | Contains both allocated ports | + +### 13C: Port Release on Cleanup + +| # | Test | Action | Expected | +|---|------|--------|----------| +| 13.13 | Kill first job | `mc_kill` name=tmc-serve | Stopped | +| 13.14 | Cleanup first job | `mc_cleanup` name=tmc-serve, deleteBranch=true | Cleaned | +| 13.15 | Verify port released | Read port.lock | First job's port no longer listed | +| 13.16 | Kill and cleanup second | `mc_kill` name=tmc-serve-2; `mc_cleanup` name=tmc-serve-2, deleteBranch=true | Cleaned | +| 13.17 | Verify all ports released | Read port.lock | Empty array `[]` or file absent | +| 13.18 | Verify clean state | `mc_jobs` | "No jobs found." | + +### 13D: TUI Mode Fallback + +| # | Test | Action | Expected | +|---|------|--------|----------| +| 13.19 | Set useServeMode=false | Edit `$STATE_DIR/config.json`: set `"useServeMode": false` | Config saved | +| 13.20 | Launch TUI mode job | `mc_launch` name=tmc-tui-fallback, prompt="echo hello" | Success — **no** Port or Server URL in output | +| 13.21 | **Wait 3-5 seconds** | — | — | +| 13.22 | Verify no port allocated | `mc_status` name=tmc-tui-fallback | No Port or Server URL fields | +| 13.23 | Cleanup | `mc_kill` name=tmc-tui-fallback; `mc_cleanup` name=tmc-tui-fallback, deleteBranch=true | Cleaned | +| 13.24 | **Restore useServeMode** | Edit `config.json`: set `"useServeMode": true` or remove the key | Config restored to serve-mode default | + +**Phase 13 Gate**: All ports must be released and config restored before proceeding. + +--- + +## Phase 14 — Enhanced mc_attach (#65) + +> **Context**: In serve mode, `mc_attach` opens an `opencode attach ` TUI in a new +> tmux window (when running inside tmux) instead of returning a `tmux attach -t` command. +> This phase validates both serve-mode and TUI-mode attach behavior. + +### 14A: Serve Mode Attach (Inside tmux) + +| # | Test | Action | Expected | +|---|------|--------|----------| +| 14.1 | Launch serve mode job | `mc_launch` name=tmc-attach-s, prompt="echo attach test" | Success with port | +| 14.2 | **Wait 5-10 seconds** | — | — | +| 14.3 | Attach opens tmux window | `mc_attach` name=tmc-attach-s | Returns "Opened TUI for job 'tmc-attach-s' in new tmux window" | +| 14.4 | Verify tmux window created | `tmux list-windows` (in current session) | Window named `mc-tmc-attach-s` exists | +| 14.5 | Clean up attach window | Kill the window: `tmux kill-window -t :mc-tmc-attach-s` | Window removed | + +### 14B: TUI Mode Attach (Backward Compatibility) + +| # | Test | Action | Expected | +|---|------|--------|----------| +| 14.6 | Kill serve job | `mc_kill` name=tmc-attach-s | Stopped | +| 14.7 | Cleanup serve job | `mc_cleanup` name=tmc-attach-s, deleteBranch=true | Cleaned | +| 14.8 | Set useServeMode=false | Edit config | Done | +| 14.9 | Launch TUI job | `mc_launch` name=tmc-attach-t, prompt="echo tui attach" | Success, no port | +| 14.10 | **Wait 3-5 seconds** | — | — | +| 14.11 | Attach returns tmux command | `mc_attach` name=tmc-attach-t | Returns `tmux attach -t mc-tmc-attach-t` (session mode) | +| 14.12 | Cleanup | `mc_kill` name=tmc-attach-t; `mc_cleanup` name=tmc-attach-t, deleteBranch=true | Cleaned | +| 14.13 | Restore useServeMode | Edit config back to `true` or remove key | Done | + +--- + +## Phase 15 — Serve Mode Observability (#66) + +> **Context**: v1.5 enriches `mc_status`, `mc_capture`, and `mc_overview` with structured +> telemetry for serve-mode jobs. `mc_capture` returns JSON events (with `filter` parameter) +> instead of raw terminal text. `mc_status` adds a "Serve Mode Telemetry" section. +> `mc_overview` shows per-job activity indicators (current tool, last activity time). + +### 15A: Enriched mc_status + +| # | Test | Action | Expected | +|---|------|--------|----------| +| 15.1 | Launch serve job | `mc_launch` name=tmc-obs, prompt="Create file observe.txt with 'testing observability'" | Success with port | +| 15.2 | **Wait 10-15 seconds** | Allow SDK events to accumulate | — | +| 15.3 | Status shows telemetry section | `mc_status` name=tmc-obs | Contains "Serve Mode Telemetry:" with fields: Session State, Current File, Files Edited, Last Activity, Events Accumulated | +| 15.4 | Status shows port and server | `mc_status` name=tmc-obs | Metadata section includes `Port: ` and `Server URL: http://...` | + +### 15B: Structured mc_capture (Serve Mode) + +| # | Test | Action | Expected | +|---|------|--------|----------| +| 15.5 | Capture all events | `mc_capture` name=tmc-obs | Returns **JSON** (not raw text) with fields: `job`, `mode: "serve"`, `status`, `filter: "all"`, `summary`, `events` | +| 15.6 | Verify summary structure | Parse JSON from 15.5 | `summary` has: `totalEvents`, `filesEdited`, `currentTool`, `currentFile`, `lastActivityAt` | +| 15.7 | Capture with file.edited filter | `mc_capture` name=tmc-obs, filter="file.edited" | JSON with `filter: "file.edited"`, events only contain `type: "file.edited"` entries | +| 15.8 | Capture with tool filter | `mc_capture` name=tmc-obs, filter="tool" | JSON with `filter: "tool"`, events only contain `type: "tool"` entries | +| 15.9 | Capture with error filter | `mc_capture` name=tmc-obs, filter="error" | JSON with `filter: "error"`, events array (likely empty for successful work) | + +### 15C: Enriched mc_overview + +| # | Test | Action | Expected | +|---|------|--------|----------| +| 15.10 | Overview with serve job | `mc_overview` | Running Jobs section shows activity indicator format | +| 15.11 | Verify activity format | Check running job line for tmc-obs | Format: `- tmc-obs | |