tool updates
This commit is contained in:
parent
0a295350cd
commit
f20ecbc699
|
|
@ -5,48 +5,80 @@ Agent-assisted task execution for the Wayland port, driven by `ACTION_PLAN.md` a
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Add to PATH (or use full paths)
|
|
||||||
export PATH="$PWD/tools/wm-port:$PATH"
|
export PATH="$PWD/tools/wm-port:$PATH"
|
||||||
|
|
||||||
# See what's available
|
# See what's available
|
||||||
wm-tasks
|
wm-tasks
|
||||||
|
|
||||||
# Dispatch a single task (foreground — waits for completion)
|
# Dispatch a task from the action plan
|
||||||
wm-dispatch B.1
|
wm-dispatch B.1
|
||||||
|
|
||||||
# Dispatch and return immediately (background)
|
# Generate an ad-hoc task from a template
|
||||||
wm-dispatch --bg B.1 B.2 B.3
|
wm-gen 3 "Replace XClearArea at wrlib/context.c:730 with wm_backend->window_clear_area"
|
||||||
|
|
||||||
# Monitor running agents
|
# Monitor
|
||||||
wm-status --watch
|
wm-status --watch
|
||||||
|
|
||||||
# Follow a specific agent's work live
|
# Collect results from background tasks
|
||||||
wm-status --follow B.1
|
wm-collect
|
||||||
|
|
||||||
# Review completed work
|
# Review diffs
|
||||||
wm-review --pending
|
|
||||||
wm-review B.1
|
wm-review B.1
|
||||||
|
|
||||||
# Dispatch all unblocked Wave 1 tasks in parallel
|
|
||||||
wm-dispatch --wave 1 --bg
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Scripts
|
## Scripts
|
||||||
|
|
||||||
| Script | Purpose |
|
| Script | Purpose | Default model |
|
||||||
|---|---|
|
|---|---|---|
|
||||||
| `wm-dispatch` | Dispatch tasks to agent sessions |
|
| `wm-dispatch` | Execute action plan tasks | `qwen/qwen3-coder` |
|
||||||
| `wm-tasks` | Show task board (status, waves, blockers) |
|
| `wm-gen` | Generate ad-hoc tasks from templates | `anthropic/claude-sonnet-4` |
|
||||||
| `wm-status` | Monitor active agent sessions |
|
| `wm-tasks` | Show task board (status, waves, blockers) | — |
|
||||||
| `wm-review` | Interactive diff review, approve/reject |
|
| `wm-status` | Monitor active agent sessions | — |
|
||||||
| `wm-done` | Manually mark tasks done/undone |
|
| `wm-collect` | Harvest results from background sessions | — |
|
||||||
| `wm-kill` | Kill running agent sessions |
|
| `wm-review` | Interactive diff review, approve/reject | — |
|
||||||
|
| `wm-done` | Manually mark tasks done/undone | — |
|
||||||
|
| `wm-kill` | Kill running agent sessions | — |
|
||||||
|
|
||||||
|
## Two ways to dispatch
|
||||||
|
|
||||||
|
### `wm-dispatch` — action plan tasks
|
||||||
|
|
||||||
|
Executes pre-defined tasks from `ACTION_PLAN.md`. Each task is mapped to a template, and the prompt is assembled automatically.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wm-dispatch B.1 # single task, foreground
|
||||||
|
wm-dispatch --bg A5.1 B.1 B.3 C.1 # batch, background
|
||||||
|
wm-dispatch --wave 1 --bg # entire wave in parallel
|
||||||
|
wm-dispatch --next 5 --bg # next 5 unblocked tasks
|
||||||
|
wm-dispatch --dry-run A5.1 # preview prompt without dispatching
|
||||||
|
```
|
||||||
|
|
||||||
|
### `wm-gen` — ad-hoc tasks from templates
|
||||||
|
|
||||||
|
Generates a task from a template number + plain English description. Use this for follow-ups, fixes from verification findings, or anything not in the action plan.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List templates
|
||||||
|
wm-gen --list
|
||||||
|
|
||||||
|
# Template + description
|
||||||
|
wm-gen 3 "Replace XClearArea at wrlib/context.c:730 with wm_backend->window_clear_area"
|
||||||
|
wm-gen 4 "Guard X11 init block at WINGs/widgets.c:637-739"
|
||||||
|
wm-gen 2 "Eliminate _x11_raw at src/framewin.c:1165" --name fix-framewin
|
||||||
|
|
||||||
|
# Pipe findings from a verification log
|
||||||
|
grep 'STOP\|issue' tools/wm-port/logs/F.2.log | wm-gen 3 --name fix-F2
|
||||||
|
|
||||||
|
# Preview
|
||||||
|
wm-gen --dry-run 4 "Guard the X11 block at wrlib/context.c:725-740"
|
||||||
|
```
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
### 1. Pick tasks
|
### 1. Pick tasks
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
wm-tasks # full board
|
||||||
wm-tasks --ready # what can be dispatched now?
|
wm-tasks --ready # what can be dispatched now?
|
||||||
wm-tasks --wave 1 # what's in wave 1?
|
wm-tasks --wave 1 # what's in wave 1?
|
||||||
wm-tasks B.1 # details on a specific task
|
wm-tasks B.1 # details on a specific task
|
||||||
|
|
@ -55,49 +87,37 @@ wm-tasks B.1 # details on a specific task
|
||||||
### 2. Dispatch
|
### 2. Dispatch
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Single task, wait for result
|
# From the action plan
|
||||||
wm-dispatch A5.1
|
wm-dispatch B.1
|
||||||
|
|
||||||
# Preview the prompt without dispatching
|
|
||||||
wm-dispatch --dry-run A5.1
|
|
||||||
|
|
||||||
# Multiple tasks in parallel (background)
|
|
||||||
wm-dispatch --bg A5.1 B.1 B.3 C.1
|
|
||||||
|
|
||||||
# All ready tasks in a wave
|
|
||||||
wm-dispatch --wave 1 --bg
|
wm-dispatch --wave 1 --bg
|
||||||
|
|
||||||
# Next 5 unblocked tasks regardless of wave
|
# Ad-hoc from template
|
||||||
wm-dispatch --next 5 --bg
|
wm-gen 3 "Replace XFoo at src/bar.c:42 with wm_backend->baz"
|
||||||
|
|
||||||
# Use a different model
|
|
||||||
wm-dispatch --model anthropic/claude-opus-4 D.1
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Monitor
|
### 3. Monitor
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Dashboard (refreshes every 2s)
|
wm-status --watch # dashboard (refreshes every 2s)
|
||||||
wm-status --watch
|
wm-status --follow A5.1 # tail one agent's chat live
|
||||||
|
wm-kill A5.1 # kill a stuck agent
|
||||||
# Follow one agent's chat live
|
wm-kill --all # kill all
|
||||||
wm-status --follow A5.1
|
|
||||||
|
|
||||||
# Kill a stuck agent
|
|
||||||
wm-kill A5.1
|
|
||||||
|
|
||||||
# Kill all
|
|
||||||
wm-kill --all
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Review
|
### 4. Collect (background tasks)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# List branches ready for review
|
wm-collect # harvest all finished sessions
|
||||||
wm-review --pending
|
wm-collect --dry-run # preview without acting
|
||||||
|
```
|
||||||
|
|
||||||
# Interactive review (shows diff, offers approve/reject/edit)
|
Scans idle `wm-port-*` sessions, reads results, updates `done.txt`, saves logs, kills successful sessions. Failed/unclear sessions are kept for inspection.
|
||||||
wm-review A5.1
|
|
||||||
|
### 5. Review (code change tasks)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wm-review --pending # list branches ready for review
|
||||||
|
wm-review B.1 # interactive review
|
||||||
```
|
```
|
||||||
|
|
||||||
The review flow:
|
The review flow:
|
||||||
|
|
@ -111,26 +131,40 @@ The review flow:
|
||||||
- **edit** — opens changed files in `$EDITOR`
|
- **edit** — opens changed files in `$EDITOR`
|
||||||
- **skip** — come back later
|
- **skip** — come back later
|
||||||
|
|
||||||
### 5. Track
|
### 6. Track
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Mark a task done manually (e.g., verified by hand)
|
wm-done G.1 # manually mark done
|
||||||
wm-done G.1
|
wm-done --undo G.1 # re-open
|
||||||
|
wm-tasks # updated board
|
||||||
# Re-open a task
|
|
||||||
wm-done --undo G.1
|
|
||||||
|
|
||||||
# Full board
|
|
||||||
wm-tasks
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## How It Works
|
## What updates `done.txt`
|
||||||
|
|
||||||
|
| Path | When |
|
||||||
|
|---|---|
|
||||||
|
| `wm-dispatch` (foreground) | Agent reports DONE → auto-marked |
|
||||||
|
| `wm-collect` | Harvests background sessions → marks DONE ones |
|
||||||
|
| `wm-review --approve` | Human approves diff → marked |
|
||||||
|
| `wm-done` | Manual mark/unmark |
|
||||||
|
|
||||||
|
## Session lifecycle
|
||||||
|
|
||||||
|
Sessions are always created with `-keep`. Cleanup is handled by the scripts:
|
||||||
|
|
||||||
|
- **DONE** → session killed (unless `--keep`)
|
||||||
|
- **STOP / FAIL / unclear** → session kept for inspection, path printed
|
||||||
|
- `wm-collect` kills DONE sessions, keeps everything else
|
||||||
|
- `wm-kill` for manual cleanup
|
||||||
|
|
||||||
|
## How it works
|
||||||
|
|
||||||
1. `wm-dispatch` extracts the task block from `ACTION_PLAN.md` and the matching template from `ACTION_PLAN_PROMPTS.md`
|
1. `wm-dispatch` extracts the task block from `ACTION_PLAN.md` and the matching template from `ACTION_PLAN_PROMPTS.md`
|
||||||
2. It composes a prompt: task description + template procedure + reference tables
|
2. `wm-gen` takes a template number + description directly
|
||||||
3. It spawns an ollie agent session (`coding` agent config) via `$OLLIE/s/b`
|
3. Both compose a prompt: task description + template procedure + reference tables
|
||||||
4. The agent creates a `port/<id>` git branch, makes the changes, verifies, and reports status
|
4. An ollie agent session is spawned via `$OLLIE/s/b`
|
||||||
5. You review the branch with `wm-review`
|
5. The agent creates a `port/<id>` git branch, makes changes, verifies, reports status
|
||||||
|
6. You review with `wm-review` or results are harvested by `wm-collect`
|
||||||
|
|
||||||
## Files
|
## Files
|
||||||
|
|
||||||
|
|
@ -138,10 +172,12 @@ wm-tasks
|
||||||
tools/wm-port/
|
tools/wm-port/
|
||||||
task-map.sh # Task database: ID→template, ID→wave, ID→blockers
|
task-map.sh # Task database: ID→template, ID→wave, ID→blockers
|
||||||
done.txt # Completed task IDs (one per line)
|
done.txt # Completed task IDs (one per line)
|
||||||
logs/ # Agent output logs (one per task)
|
logs/ # Agent output logs (one per task/name)
|
||||||
wm-dispatch # Dispatcher
|
wm-dispatch # Action plan task dispatcher
|
||||||
|
wm-gen # Ad-hoc task generator from templates
|
||||||
wm-tasks # Task board
|
wm-tasks # Task board
|
||||||
wm-status # Session monitor
|
wm-status # Session monitor
|
||||||
|
wm-collect # Background session harvester
|
||||||
wm-review # Diff reviewer
|
wm-review # Diff reviewer
|
||||||
wm-done # Manual done/undo
|
wm-done # Manual done/undo
|
||||||
wm-kill # Session killer
|
wm-kill # Session killer
|
||||||
|
|
@ -149,9 +185,10 @@ tools/wm-port/
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
| Variable | Default | Description |
|
Defaults can be overridden per-call with flags:
|
||||||
|
|
||||||
|
| Flag | `wm-dispatch` default | `wm-gen` default |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `OLLIE` | `~/mnt/ollie` | Ollie mount path |
|
| `--backend` | `openrouter` | `openrouter` |
|
||||||
| `--backend` | `openrouter` | LLM backend |
|
| `--model` | `qwen/qwen3-coder` | `anthropic/claude-sonnet-4` |
|
||||||
| `--model` | `anthropic/claude-sonnet-4` | LLM model |
|
| `--agent` | `coding` | `coding` |
|
||||||
| `--agent` | `coding` | Ollie agent config |
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
user: You are executing a mechanical Wayland porting task for WindowMaker.
|
||||||
|
|
||||||
|
# Task: F.2 (Verification only)
|
||||||
|
|
||||||
|
## Task Description (from ACTION_PLAN.md)
|
||||||
|
|
||||||
|
### F.2 Verify `RCreateContextWayland()` completeness
|
||||||
|
- **File**: `wrlib/context.c:725-775`
|
||||||
|
- **Operation**: Read `RCreateContextWayland()`. Verify it sets all fields that `RConvertImage` and image loaders need: `depth`, `vclass`, `red_offset`, `green_offset`, `blue_offset`, `black`, `white`, `convert_image`, `convert_image_mask`. Verify `dpy`, `cmap`, `copy_gc`, `visual`, `drawable` are NULL/0.
|
||||||
|
- **Test**: Call `RCreateContextWayland(1920, 1080, NULL)`, then `RLoadImage(ctx, "test.png", 0)`, then `RConvertImage(ctx, img, &pixmap)`. Confirm the pixmap is a `pixman_image_t*` cast to `Pixmap`.
|
||||||
|
- **Blocked by**: nothing
|
||||||
|
|
||||||
|
## Procedure (Template 9)
|
||||||
|
|
||||||
|
|
||||||
|
**Use for**: F.2, F.3, F.4, G.1, I.1, I.2, C.3, H.5, and any verification task
|
||||||
|
|
||||||
|
```
|
||||||
|
TASK: Verify that {{FILE}} has no X11 dependencies that would break on the
|
||||||
|
Wayland backend.
|
||||||
|
|
||||||
|
STEPS:
|
||||||
|
|
||||||
|
1. Run: `grep -nE '\bX[A-Z][a-z]' {{FILE}}`
|
||||||
|
This finds direct Xlib function calls.
|
||||||
|
EXPECTED: {{EXPECTED_XLIB_COUNT}} matches.
|
||||||
|
|
||||||
|
2. Run: `grep -nE '\bDisplay\b|\bXEvent\b|\bXImage\b|\bXColor\b' {{FILE}}`
|
||||||
|
This finds X11 type usage.
|
||||||
|
EXPECTED: {{EXPECTED_TYPE_COUNT}} matches.
|
||||||
|
|
||||||
|
3. Run: `grep -n '_x11_raw' {{FILE}}`
|
||||||
|
This finds raw event escape hatches.
|
||||||
|
EXPECTED: 0 matches.
|
||||||
|
|
||||||
|
4. Run: `grep -n '#ifdef.*USE_X\|#ifdef.*HAVE_X\|#ifdef.*XINERAMA\|#ifdef.*XSHAPE\|#ifdef.*XDND' {{FILE}}`
|
||||||
|
This finds X11 feature guards.
|
||||||
|
EXPECTED: {{EXPECTED_IFDEF_COUNT}} matches.
|
||||||
|
|
||||||
|
5. If any count exceeds expected:
|
||||||
|
- For each unexpected match, report the line number and the X11 reference.
|
||||||
|
- Classify as: (a) actual dependency, (b) comment/string, (c) type used
|
||||||
|
but never passed to Xlib.
|
||||||
|
|
||||||
|
REPORT FORMAT:
|
||||||
|
```
|
||||||
|
FILE: {{FILE}}
|
||||||
|
Xlib calls: N (expected {{EXPECTED_XLIB_COUNT}})
|
||||||
|
X11 types: N (expected {{EXPECTED_TYPE_COUNT}})
|
||||||
|
_x11_raw: N (expected 0)
|
||||||
|
#ifdef guards: N (expected {{EXPECTED_IFDEF_COUNT}})
|
||||||
|
STATUS: CLEAN / NEEDS WORK
|
||||||
|
ISSUES: (list any unexpected findings)
|
||||||
|
```
|
||||||
|
|
||||||
|
CONSTRAINTS:
|
||||||
|
- Do NOT modify the file. This is a read-only verification task.
|
||||||
|
- Report findings exactly. Do not interpret or fix.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Reference Tables (embed in every prompt)
|
||||||
|
|
||||||
|
### X11 Event Type → WMEvent Type
|
||||||
|
|
||||||
|
```
|
||||||
|
KeyPress/KeyRelease → WME_KEY_PRESS/WME_KEY_RELEASE → event->u.key.*
|
||||||
|
ButtonPress/ButtonRelease → WME_BUTTON_PRESS/WME_BUTTON_RELEASE → event->u.button.*
|
||||||
|
MotionNotify → WME_MOTION → event->u.motion.*
|
||||||
|
EnterNotify/LeaveNotify → WME_ENTER/WME_LEAVE → event->u.crossing.*
|
||||||
|
Expose → WME_EXPOSE → event->u.expose.*
|
||||||
|
ConfigureNotify → WME_CONFIGURE → event->u.configure.*
|
||||||
|
ConfigureRequest → WME_CONFIGURE_REQUEST → event->u.configureRequest.*
|
||||||
|
MapNotify → WME_MAP → event->u.lifecycle.*
|
||||||
|
MapRequest → WME_MAP_REQUEST → event->u.mapRequest.*
|
||||||
|
UnmapNotify → WME_UNMAP → event->u.lifecycle.*
|
||||||
|
DestroyNotify → WME_DESTROY → event->u.lifecycle.*
|
||||||
|
FocusIn/FocusOut → WME_FOCUS_IN/WME_FOCUS_OUT → event->u.focus.*
|
||||||
|
PropertyNotify → WME_PROPERTY → event->u.property.*
|
||||||
|
ClientMessage → WME_CLIENT_MESSAGE → event->u.clientMessage.*
|
||||||
|
SelectionNotify → WME_SELECTION → event->u.selection.*
|
||||||
|
SelectionRequest → WME_SELECTION_REQUEST → event->u.selection.* (check)
|
||||||
|
SelectionClear → WME_SELECTION_CLEAR → event->u.selection.* (check)
|
||||||
|
VisibilityNotify → WME_VISIBILITY → event->u.visibility.*
|
||||||
|
ColormapNotify → WME_COLORMAP → event->u.colormap.*
|
||||||
|
MappingNotify → WME_MAPPING → event->u.mapping.*
|
||||||
|
ReparentNotify → WME_REPARENT → event->u.reparent.*
|
||||||
|
```
|
||||||
|
|
||||||
|
### X11 Event Field → WMEvent Field
|
||||||
|
|
||||||
|
```
|
||||||
|
event->xkey.keycode → event->u.key.keycode
|
||||||
|
event->xkey.state → event->u.key.state
|
||||||
|
event->xkey.time → event->u.key.time
|
||||||
|
event->xkey.window → event->u.key.window
|
||||||
|
event->xkey.x, y → event->u.key.x, y
|
||||||
|
event->xkey.x_root → event->u.key.x_root
|
||||||
|
|
||||||
|
event->xbutton.button → event->u.button.button
|
||||||
|
event->xbutton.state → event->u.button.state
|
||||||
|
event->xbutton.time → event->u.button.time
|
||||||
|
event->xbutton.window → event->u.button.window
|
||||||
|
event->xbutton.x, y → event->u.button.x, y
|
||||||
|
event->xbutton.x_root → event->u.button.x_root
|
||||||
|
|
||||||
|
event->xmotion.state → event->u.motion.state
|
||||||
|
event->xmotion.time → event->u.motion.time
|
||||||
|
event->xmotion.window → event->u.motion.window
|
||||||
|
event->xmotion.x, y → event->u.motion.x, y
|
||||||
|
event->xmotion.x_root → event->u.motion.x_root
|
||||||
|
|
||||||
|
event->xcrossing.window → event->u.crossing.window
|
||||||
|
event->xcrossing.state → event->u.crossing.state
|
||||||
|
event->xcrossing.time → event->u.crossing.time
|
||||||
|
event->xcrossing.mode → event->u.crossing.mode
|
||||||
|
event->xcrossing.detail → event->u.crossing.detail
|
||||||
|
|
||||||
|
event->xconfigure.window → event->u.configure.window
|
||||||
|
event->xconfigure.x, y → event->u.configure.x, y
|
||||||
|
event->xconfigure.width → event->u.configure.width
|
||||||
|
event->xconfigure.height → event->u.configure.height
|
||||||
|
|
||||||
|
event->xclient.data.l[N] → event->u.clientMessage.data.l[N]
|
||||||
|
event->xclient.message_type → event->u.clientMessage.atom
|
||||||
|
event->xclient.window → event->u.clientMessage.window
|
||||||
|
|
||||||
|
event->xproperty.atom → event->u.property.atom
|
||||||
|
event->xproperty.time → event->u.property.time
|
||||||
|
event->xproperty.window → event->u.property.window
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Important Rules
|
||||||
|
|
||||||
|
1. Work in the git repository at /home/lkn/src/WindowMaker-0.96.0. Create a git branch named "port/F.2" before making changes.
|
||||||
|
2. Make exactly the changes described. No more, no less.
|
||||||
|
3. After making changes, verify with the grep commands in the template.
|
||||||
|
4. Attempt to compile with: cd /home/lkn/src/WindowMaker-0.96.0 && make -j$(nproc) 2>&1 | tail -30
|
||||||
|
5. If compilation fails, fix the errors. If you cannot fix them, revert and report.
|
||||||
|
6. If you hit a STOP condition (missing vtable slot, missing API), revert changes and report exactly what is missing.
|
||||||
|
7. When done, run: git add -A && git diff --cached --stat
|
||||||
|
8. Report the final status as one of:
|
||||||
|
- DONE: task completed, compiles clean
|
||||||
|
- STOP: blocked on <reason>
|
||||||
|
- FAIL: could not complete because <reason>
|
||||||
|
|
||||||
|
Line numbers in ACTION_PLAN.md may have drifted. Use grep to find current line numbers before editing.
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# wm-collect: Harvest results from completed wm-port agent sessions.
|
||||||
|
#
|
||||||
|
# Scans all wm-port-* sessions. For each idle session, reads the result,
|
||||||
|
# updates done.txt, saves the log, and kills the session.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# wm-collect # collect all finished sessions
|
||||||
|
# wm-collect --dry-run # show what would be collected, don't act
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||||
|
TOOLS="$ROOT/tools/wm-port"
|
||||||
|
MOUNT="${OLLIE:-$HOME/mnt/ollie}"
|
||||||
|
DONE_FILE="$TOOLS/done.txt"
|
||||||
|
LOG_DIR="$TOOLS/logs"
|
||||||
|
|
||||||
|
source "$TOOLS/task-map.sh"
|
||||||
|
mkdir -p "$LOG_DIR"
|
||||||
|
touch "$DONE_FILE"
|
||||||
|
|
||||||
|
dry_run=0
|
||||||
|
[ "${1:-}" = "--dry-run" ] && dry_run=1
|
||||||
|
[ "${1:-}" = "--help" ] || [ "${1:-}" = "-h" ] && {
|
||||||
|
sed -n '2,/^$/{ s/^# //; s/^#//; p; }' "$0"; exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
collected=0
|
||||||
|
skipped=0
|
||||||
|
|
||||||
|
while IFS=$'\t' read -r sid state cwd backend model; do
|
||||||
|
[[ "$sid" == wm-port-* ]] || continue
|
||||||
|
tid="${sid#wm-port-}"
|
||||||
|
session_path="$MOUNT/s/$sid"
|
||||||
|
|
||||||
|
# Skip sessions still running
|
||||||
|
if [ "$state" != "idle" ]; then
|
||||||
|
(( ++skipped ))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Skip already-collected tasks
|
||||||
|
task_is_done "$tid" "$DONE_FILE" 2>/dev/null && {
|
||||||
|
if [ "$dry_run" -eq 0 ]; then
|
||||||
|
echo kill > "$session_path/ctl" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read the result
|
||||||
|
local_offset=$(cat "$session_path/offset" 2>/dev/null || echo 0)
|
||||||
|
result=$(tail -c +$((local_offset + 1)) "$session_path/chat" 2>/dev/null || true)
|
||||||
|
|
||||||
|
# Determine status
|
||||||
|
status="UNKNOWN"
|
||||||
|
if [ -z "$result" ] || echo "$result" | head -1 | grep -q '^user:'; then
|
||||||
|
status="FAIL"
|
||||||
|
elif echo "$result" | grep -qiE '\*\*DONE\*\*|^DONE:|^DONE\b|Status:.*DONE|DONE: task completed|DONE: verified'; then
|
||||||
|
status="DONE"
|
||||||
|
elif echo "$result" | grep -qiE '\*\*STOP\*\*|^STOP:|^STOP\b|Status:.*STOP|STOP: blocked'; then
|
||||||
|
status="STOP"
|
||||||
|
elif echo "$result" | grep -qiE '\*\*FAIL\*\*|^FAIL:|^FAIL\b|Status:.*FAIL|FAIL: could not'; then
|
||||||
|
status="FAIL"
|
||||||
|
elif echo "$result" | grep -qiE 'compiles clean|no action needed'; then
|
||||||
|
status="DONE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Report
|
||||||
|
case "$status" in
|
||||||
|
DONE)
|
||||||
|
printf '\033[1;32m\u2713 %s: %s\033[0m\n' "$tid" "$status"
|
||||||
|
;;
|
||||||
|
STOP)
|
||||||
|
printf '\033[1;33m\u26a0 %s: %s\033[0m\n' "$tid" "$status"
|
||||||
|
;;
|
||||||
|
FAIL)
|
||||||
|
printf '\033[1;31m\u2717 %s: %s\033[0m\n' "$tid" "$status"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
printf '\033[1;35m? %s: %s\033[0m\n' "$tid" "$status"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$dry_run" -eq 1 ]; then
|
||||||
|
(( ++collected ))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Save log
|
||||||
|
printf '%s\n' "$result" > "$LOG_DIR/${tid}.log"
|
||||||
|
|
||||||
|
# Update done.txt for successful tasks
|
||||||
|
case "$status" in
|
||||||
|
DONE)
|
||||||
|
echo "$tid" >> "$DONE_FILE"
|
||||||
|
echo kill > "$session_path/ctl" 2>/dev/null || true
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Keep session alive for inspection
|
||||||
|
printf ' Session: %s\n' "$session_path"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
(( ++collected ))
|
||||||
|
done < <(cat "$MOUNT/s/idx" 2>/dev/null)
|
||||||
|
|
||||||
|
if [ "$collected" -eq 0 ] && [ "$skipped" -eq 0 ]; then
|
||||||
|
echo "No wm-port sessions found."
|
||||||
|
elif [ "$collected" -eq 0 ]; then
|
||||||
|
printf '%d session(s) still running.\n' "$skipped"
|
||||||
|
else
|
||||||
|
printf '\nCollected %d result(s)' "$collected"
|
||||||
|
[ "$skipped" -gt 0 ] && printf ', %d still running' "$skipped"
|
||||||
|
printf '.\n'
|
||||||
|
fi
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# wm-dispatch: Dispatch a WindowMaker Wayland port task to an agent.
|
# wm-dispatch: Execute action plan tasks via agent sessions.
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# wm-dispatch <task-id> # dispatch one task
|
# wm-dispatch <task-id> # dispatch one task (foreground)
|
||||||
# wm-dispatch <task-id> <task-id>... # dispatch multiple in parallel
|
# wm-dispatch <task-id> <task-id>... # dispatch multiple in parallel
|
||||||
# wm-dispatch --wave <N> # dispatch all unblocked tasks in wave N
|
# wm-dispatch --wave <N> # dispatch all unblocked tasks in wave N
|
||||||
# wm-dispatch --next [N] # dispatch next N unblocked tasks (default 1)
|
# wm-dispatch --next [N] # dispatch next N unblocked tasks (default 1)
|
||||||
|
|
@ -10,9 +10,11 @@
|
||||||
# Options:
|
# Options:
|
||||||
# --dry-run Print the prompt instead of dispatching
|
# --dry-run Print the prompt instead of dispatching
|
||||||
# --backend B Override backend (default: openrouter)
|
# --backend B Override backend (default: openrouter)
|
||||||
# --model M Override model (default: anthropic/claude-sonnet-4)
|
# --model M Override model (default: qwen/qwen3-coder)
|
||||||
# --keep Don't auto-kill session on completion
|
# --keep Keep session on success (failures always kept)
|
||||||
# --bg Submit and return immediately (print session paths)
|
# --bg Submit and return immediately (use wm-collect to harvest)
|
||||||
|
#
|
||||||
|
# See also: wm-gen (ad-hoc tasks from templates)
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
|
@ -26,7 +28,7 @@ source "$TOOLS/task-map.sh"
|
||||||
|
|
||||||
# Defaults
|
# Defaults
|
||||||
backend="openrouter"
|
backend="openrouter"
|
||||||
model="anthropic/claude-sonnet-4"
|
model="qwen/qwen3-coder"
|
||||||
dry_run=0
|
dry_run=0
|
||||||
keep=0
|
keep=0
|
||||||
bg=0
|
bg=0
|
||||||
|
|
@ -163,7 +165,34 @@ build_prompt() {
|
||||||
local ref_tables
|
local ref_tables
|
||||||
ref_tables=$(extract_reference_tables)
|
ref_tables=$(extract_reference_tables)
|
||||||
|
|
||||||
cat <<PROMPT
|
if [ "$tnum" -eq 9 ]; then
|
||||||
|
# Verification tasks: read-only audit, report findings
|
||||||
|
cat <<PROMPT
|
||||||
|
You are executing a verification task for the WindowMaker Wayland port.
|
||||||
|
This is a READ-ONLY audit. Do NOT modify any files. Do NOT create branches.
|
||||||
|
|
||||||
|
# Task: $tid
|
||||||
|
|
||||||
|
## Task Description (from ACTION_PLAN.md)
|
||||||
|
|
||||||
|
$task_block
|
||||||
|
|
||||||
|
## Procedure (Template $tnum)
|
||||||
|
|
||||||
|
$template
|
||||||
|
|
||||||
|
## Important Rules
|
||||||
|
|
||||||
|
1. Work in the git repository at $ROOT.
|
||||||
|
2. Run the verification checks described in the procedure.
|
||||||
|
3. Report findings using the REPORT FORMAT from the procedure.
|
||||||
|
4. End with exactly one of:
|
||||||
|
- DONE: verified clean, no issues found.
|
||||||
|
- STOP: found issues that need human decision. List each issue with file:line and a one-line description.
|
||||||
|
PROMPT
|
||||||
|
else
|
||||||
|
# Code modification tasks: branch, edit, compile
|
||||||
|
cat <<PROMPT
|
||||||
You are executing a mechanical Wayland porting task for WindowMaker.
|
You are executing a mechanical Wayland porting task for WindowMaker.
|
||||||
|
|
||||||
# Task: $tid ($tname)
|
# Task: $tid ($tname)
|
||||||
|
|
@ -194,6 +223,7 @@ $ref_tables
|
||||||
|
|
||||||
Line numbers in ACTION_PLAN.md may have drifted. Use grep to find current line numbers before editing.
|
Line numbers in ACTION_PLAN.md may have drifted. Use grep to find current line numbers before editing.
|
||||||
PROMPT
|
PROMPT
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Dispatch a single task ──
|
# ── Dispatch a single task ──
|
||||||
|
|
@ -212,48 +242,74 @@ dispatch_one() {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local session_name="wm-port-${tid}"
|
local session_name="wm-port-${tid}"
|
||||||
|
local session_path="$MOUNT/s/$session_name"
|
||||||
local flags=(
|
local flags=(
|
||||||
-name "$session_name"
|
-name "$session_name"
|
||||||
-cwd "$ROOT"
|
-cwd "$ROOT"
|
||||||
-agent coding
|
-agent coding
|
||||||
-backend "$backend"
|
-backend "$backend"
|
||||||
-model "$model"
|
-model "$model"
|
||||||
|
-keep
|
||||||
)
|
)
|
||||||
[ "$keep" -eq 1 ] && flags+=(-keep)
|
|
||||||
[ "$bg" -eq 1 ] && flags+=(-bg)
|
[ "$bg" -eq 1 ] && flags+=(-bg)
|
||||||
|
|
||||||
printf '\033[1;36m▶ Dispatching %s\033[0m (%s)\n' \
|
printf '\033[1;36m▶ Dispatching %s\033[0m (%s)\n' \
|
||||||
"$tid" "${TEMPLATE_NAME[${TASK_TEMPLATE[$tid]}]}" >&2
|
"$tid" "${TEMPLATE_NAME[${TASK_TEMPLATE[$tid]}]}" >&2
|
||||||
|
|
||||||
if [ "$bg" -eq 1 ]; then
|
if [ "$bg" -eq 1 ]; then
|
||||||
local session_path
|
local sp
|
||||||
session_path=$(printf '%s' "$prompt" | "$MOUNT/s/b" "${flags[@]}")
|
sp=$(printf '%s' "$prompt" | "$MOUNT/s/b" "${flags[@]}")
|
||||||
printf '%s\t%s\n' "$tid" "$session_path"
|
printf '%s\t%s\n' "$tid" "$sp"
|
||||||
printf '\033[1;33m → %s\033[0m\n' "$session_path" >&2
|
printf '\033[1;33m → %s\033[0m\n' "$sp" >&2
|
||||||
else
|
else
|
||||||
local result
|
local result
|
||||||
result=$(printf '%s' "$prompt" | "$MOUNT/s/b" "${flags[@]}" 2>&1) || true
|
result=$(printf '%s' "$prompt" | "$MOUNT/s/b" "${flags[@]}" 2>/dev/null) || true
|
||||||
|
|
||||||
# Save log
|
# Save log
|
||||||
printf '%s\n' "$result" > "$LOG_DIR/${tid}.log"
|
printf '%s\n' "$result" > "$LOG_DIR/${tid}.log"
|
||||||
|
|
||||||
# Parse result status
|
# Parse result status — search broadly since agents format varies
|
||||||
local status="UNKNOWN"
|
local status="UNKNOWN"
|
||||||
if echo "$result" | grep -q '^DONE\b\|^\*\*DONE\*\*\|Status:.*DONE'; then
|
local should_keep="$keep"
|
||||||
|
if [ -z "$result" ] || echo "$result" | head -1 | grep -q '^user:'; then
|
||||||
|
status="FAIL"
|
||||||
|
should_keep=1
|
||||||
|
printf '\033[1;31m✗ %s: FAIL (agent produced no response)\033[0m\n' "$tid" >&2
|
||||||
|
elif echo "$result" | grep -qiE '\*\*DONE\*\*|^DONE:|^DONE\b|Status:.*DONE|DONE: task completed|DONE: verified'; then
|
||||||
status="DONE"
|
status="DONE"
|
||||||
echo "$tid" >> "$DONE_FILE"
|
echo "$tid" >> "$DONE_FILE"
|
||||||
printf '\033[1;32m✓ %s: DONE\033[0m\n' "$tid" >&2
|
printf '\033[1;32m✓ %s: DONE\033[0m\n' "$tid" >&2
|
||||||
elif echo "$result" | grep -q '^STOP\b\|^\*\*STOP\*\*\|Status:.*STOP'; then
|
elif echo "$result" | grep -qiE '\*\*STOP\*\*|^STOP:|^STOP\b|Status:.*STOP|STOP: blocked'; then
|
||||||
status="STOP"
|
status="STOP"
|
||||||
|
should_keep=1
|
||||||
printf '\033[1;33m⚠ %s: STOP\033[0m\n' "$tid" >&2
|
printf '\033[1;33m⚠ %s: STOP\033[0m\n' "$tid" >&2
|
||||||
elif echo "$result" | grep -q '^FAIL\b\|^\*\*FAIL\*\*\|Status:.*FAIL'; then
|
echo "$result" | grep -iE 'STOP' | head -3 | sed 's/^/ /' >&2
|
||||||
|
elif echo "$result" | grep -qiE '\*\*FAIL\*\*|^FAIL:|^FAIL\b|Status:.*FAIL|FAIL: could not'; then
|
||||||
status="FAIL"
|
status="FAIL"
|
||||||
|
should_keep=1
|
||||||
printf '\033[1;31m✗ %s: FAIL\033[0m\n' "$tid" >&2
|
printf '\033[1;31m✗ %s: FAIL\033[0m\n' "$tid" >&2
|
||||||
|
echo "$result" | grep -iE 'FAIL' | head -3 | sed 's/^/ /' >&2
|
||||||
else
|
else
|
||||||
printf '\033[1;35m? %s: status unclear — check log\033[0m\n' "$tid" >&2
|
if echo "$result" | grep -qiE 'compiles clean|no action needed'; then
|
||||||
|
status="DONE"
|
||||||
|
echo "$tid" >> "$DONE_FILE"
|
||||||
|
printf '\033[1;32m✓ %s: DONE (inferred from output)\033[0m\n' "$tid" >&2
|
||||||
|
else
|
||||||
|
status="UNKNOWN"
|
||||||
|
should_keep=1
|
||||||
|
printf '\033[1;35m? %s: status unclear — review log\033[0m\n' "$tid" >&2
|
||||||
|
echo "$result" | grep -v '^$' | tail -5 | sed 's/^/ /' >&2
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf ' Log: %s\n' "$LOG_DIR/${tid}.log" >&2
|
printf ' Log: %s\n' "$LOG_DIR/${tid}.log" >&2
|
||||||
|
|
||||||
|
# Clean up session: keep on failure/unclear for inspection, kill on success
|
||||||
|
if [ "$should_keep" -eq 1 ]; then
|
||||||
|
printf ' Session: %s\n' "$session_path" >&2
|
||||||
|
elif [ -d "$session_path" ]; then
|
||||||
|
echo kill > "$session_path/ctl" 2>/dev/null || true
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,222 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# wm-gen: Generate and dispatch a task from a template + description.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# wm-gen <template> <description> # dispatch immediately
|
||||||
|
# wm-gen <template> <description> --name ID # dispatch with tracking ID
|
||||||
|
# wm-gen --list # list available templates
|
||||||
|
# echo "description" | wm-gen <template> # description from stdin
|
||||||
|
#
|
||||||
|
# Templates:
|
||||||
|
# 1 Signature XEvent*→WMEvent*
|
||||||
|
# 2 Eliminate _x11_raw
|
||||||
|
# 3 Xlib→wm_backend vtable
|
||||||
|
# 4 Guard X11 block (if scr->display)
|
||||||
|
# 5 Split into _x11/_wl pair
|
||||||
|
# 6 Xlib drawing→render backend
|
||||||
|
# 7 Remove #ifdef guard
|
||||||
|
# 8 WPrefs Xlib→WINGs API
|
||||||
|
# 9 Verification
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# --name ID Tracking name (default: gen-<timestamp>)
|
||||||
|
# --dry-run Print the prompt, don't dispatch
|
||||||
|
# --backend B Override backend
|
||||||
|
# --model M Override model
|
||||||
|
# --bg Background dispatch
|
||||||
|
# --keep Keep session after completion
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# wm-gen 3 "Replace XClearArea at wrlib/context.c:730 with wm_backend->window_clear_area"
|
||||||
|
# wm-gen 4 "Guard X11 init block at WINGs/widgets.c:637-739"
|
||||||
|
# wm-gen 2 "Eliminate _x11_raw at src/framewin.c:1165" --name fix-framewin
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||||
|
TOOLS="$ROOT/tools/wm-port"
|
||||||
|
MOUNT="${OLLIE:-$HOME/mnt/ollie}"
|
||||||
|
LOG_DIR="$TOOLS/logs"
|
||||||
|
|
||||||
|
source "$TOOLS/task-map.sh"
|
||||||
|
mkdir -p "$LOG_DIR"
|
||||||
|
|
||||||
|
die() { printf 'wm-gen: %s\n' "$*" >&2; exit 1; }
|
||||||
|
|
||||||
|
if [ "${1:-}" = "--list" ]; then
|
||||||
|
for t in 1 2 3 4 5 6 7 8 9; do
|
||||||
|
printf ' %s %s\n' "$t" "${TEMPLATE_NAME[$t]}"
|
||||||
|
done
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Defaults
|
||||||
|
backend="openrouter"
|
||||||
|
model="anthropic/claude-sonnet-4"
|
||||||
|
dry_run=0
|
||||||
|
keep=0
|
||||||
|
bg=0
|
||||||
|
name=""
|
||||||
|
tnum=""
|
||||||
|
desc_args=()
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
--name) name="$2"; shift ;;
|
||||||
|
--dry-run) dry_run=1 ;;
|
||||||
|
--backend) backend="$2"; shift ;;
|
||||||
|
--model) model="$2"; shift ;;
|
||||||
|
--bg) bg=1 ;;
|
||||||
|
--keep) keep=1 ;;
|
||||||
|
--help|-h) sed -n '2,/^$/{ s/^# //; s/^#//; p; }' "$0"; exit 0 ;;
|
||||||
|
-*) die "unknown flag: $1" ;;
|
||||||
|
*) if [ -z "$tnum" ] && [[ "$1" =~ ^[1-9]$ ]]; then
|
||||||
|
tnum="$1"
|
||||||
|
else
|
||||||
|
desc_args+=("$1")
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
[ -n "$tnum" ] || die "template number required (1-9). Use --list to see templates."
|
||||||
|
[ -n "${TEMPLATE_NAME[$tnum]:-}" ] || die "invalid template number: $tnum"
|
||||||
|
|
||||||
|
# Read description from args or stdin
|
||||||
|
if [ ${#desc_args[@]} -gt 0 ] && ! [ -t 0 ]; then
|
||||||
|
description="${desc_args[*]}"$'\n'"$(cat)"
|
||||||
|
elif [ ${#desc_args[@]} -gt 0 ]; then
|
||||||
|
description="${desc_args[*]}"
|
||||||
|
elif ! [ -t 0 ]; then
|
||||||
|
description=$(cat)
|
||||||
|
else
|
||||||
|
die "description required: pass as arguments or pipe via stdin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -n "$description" ] || die "empty description"
|
||||||
|
|
||||||
|
name="${name:-gen-$(date +%s)}"
|
||||||
|
|
||||||
|
# Extract the template procedure
|
||||||
|
extract_template() {
|
||||||
|
local t="$1"
|
||||||
|
local prompts="$ROOT/ACTION_PLAN_PROMPTS.md"
|
||||||
|
awk -v tnum="$t" '
|
||||||
|
BEGIN { found=0; in_code=0 }
|
||||||
|
/^## Template / {
|
||||||
|
if (found && !in_code) exit
|
||||||
|
if ($0 ~ "Template " tnum ":" || $0 ~ "Template " tnum " ") {
|
||||||
|
found=1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/^## Template [0-9]/ { if (found) exit }
|
||||||
|
/^---$/ { if (found && !in_code) exit }
|
||||||
|
found { print }
|
||||||
|
' "$prompts"
|
||||||
|
}
|
||||||
|
|
||||||
|
extract_reference_tables() {
|
||||||
|
local prompts="$ROOT/ACTION_PLAN_PROMPTS.md"
|
||||||
|
awk '
|
||||||
|
/^## Reference Tables/,/^## Template 1/ {
|
||||||
|
if (/^## Template 1/) exit
|
||||||
|
print
|
||||||
|
}
|
||||||
|
' "$prompts"
|
||||||
|
}
|
||||||
|
|
||||||
|
template=$(extract_template "$tnum")
|
||||||
|
ref_tables=$(extract_reference_tables)
|
||||||
|
tname="${TEMPLATE_NAME[$tnum]}"
|
||||||
|
|
||||||
|
prompt=$(cat <<PROMPT
|
||||||
|
You are executing a mechanical Wayland porting task for WindowMaker.
|
||||||
|
|
||||||
|
# Task: $name ($tname)
|
||||||
|
|
||||||
|
## What to do
|
||||||
|
|
||||||
|
$description
|
||||||
|
|
||||||
|
## Procedure (Template $tnum: $tname)
|
||||||
|
|
||||||
|
$template
|
||||||
|
|
||||||
|
$ref_tables
|
||||||
|
|
||||||
|
## Important Rules
|
||||||
|
|
||||||
|
1. Work in the git repository at $ROOT. Create a git branch named "port/$name" before making changes.
|
||||||
|
2. Make exactly the changes described. No more, no less.
|
||||||
|
3. After making changes, verify with the grep commands in the template.
|
||||||
|
4. Attempt to compile with: cd $ROOT && make -j\$(nproc) 2>&1 | tail -30
|
||||||
|
5. If compilation fails, fix the errors. If you cannot fix them, revert and report.
|
||||||
|
6. If you hit a STOP condition (missing vtable slot, missing API), revert changes and report exactly what is missing.
|
||||||
|
7. When done, run: git add -A && git diff --cached --stat
|
||||||
|
8. Report the final status as one of:
|
||||||
|
- DONE: task completed, compiles clean
|
||||||
|
- STOP: blocked on <reason>
|
||||||
|
- FAIL: could not complete because <reason>
|
||||||
|
|
||||||
|
Line numbers may have drifted. Use grep to find current line numbers before editing.
|
||||||
|
PROMPT
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ "$dry_run" -eq 1 ]; then
|
||||||
|
echo "════════════════════════════════════════"
|
||||||
|
echo "TASK: $name (Template $tnum: $tname)"
|
||||||
|
echo "════════════════════════════════════════"
|
||||||
|
echo "$prompt"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
session_name="wm-port-${name}"
|
||||||
|
session_path="$MOUNT/s/$session_name"
|
||||||
|
flags=(
|
||||||
|
-name "$session_name"
|
||||||
|
-cwd "$ROOT"
|
||||||
|
-agent coding
|
||||||
|
-backend "$backend"
|
||||||
|
-model "$model"
|
||||||
|
-keep
|
||||||
|
)
|
||||||
|
[ "$bg" -eq 1 ] && flags+=(-bg)
|
||||||
|
|
||||||
|
printf '\033[1;36m▶ Dispatching %s\033[0m (T%s: %s)\n' "$name" "$tnum" "$tname" >&2
|
||||||
|
|
||||||
|
if [ "$bg" -eq 1 ]; then
|
||||||
|
sp=$(printf '%s' "$prompt" | "$MOUNT/s/b" "${flags[@]}")
|
||||||
|
printf '%s\t%s\n' "$name" "$sp"
|
||||||
|
printf '\033[1;33m → %s\033[0m\n' "$sp" >&2
|
||||||
|
else
|
||||||
|
result=$(printf '%s' "$prompt" | "$MOUNT/s/b" "${flags[@]}" 2>/dev/null) || true
|
||||||
|
printf '%s\n' "$result" > "$LOG_DIR/${name}.log"
|
||||||
|
|
||||||
|
if [ -z "$result" ] || echo "$result" | head -1 | grep -q '^user:'; then
|
||||||
|
printf '\033[1;31m✗ %s: FAIL (agent produced no response)\033[0m\n' "$name" >&2
|
||||||
|
printf ' Session: %s\n' "$session_path" >&2
|
||||||
|
elif echo "$result" | grep -qiE '\*\*DONE\*\*|^DONE:|^DONE\b|DONE: task completed'; then
|
||||||
|
printf '\033[1;32m✓ %s: DONE\033[0m\n' "$name" >&2
|
||||||
|
if [ "$keep" -eq 0 ]; then
|
||||||
|
echo kill > "$session_path/ctl" 2>/dev/null || true
|
||||||
|
else
|
||||||
|
printf ' Session: %s\n' "$session_path" >&2
|
||||||
|
fi
|
||||||
|
elif echo "$result" | grep -qiE '\*\*STOP\*\*|^STOP:|^STOP\b'; then
|
||||||
|
printf '\033[1;33m⚠ %s: STOP\033[0m\n' "$name" >&2
|
||||||
|
echo "$result" | grep -iE 'STOP' | head -3 | sed 's/^/ /' >&2
|
||||||
|
printf ' Session: %s\n' "$session_path" >&2
|
||||||
|
elif echo "$result" | grep -qiE '\*\*FAIL\*\*|^FAIL:|^FAIL\b'; then
|
||||||
|
printf '\033[1;31m✗ %s: FAIL\033[0m\n' "$name" >&2
|
||||||
|
echo "$result" | grep -iE 'FAIL' | head -3 | sed 's/^/ /' >&2
|
||||||
|
printf ' Session: %s\n' "$session_path" >&2
|
||||||
|
else
|
||||||
|
printf '\033[1;35m? %s: status unclear\033[0m\n' "$name" >&2
|
||||||
|
echo "$result" | grep -v '^$' | tail -5 | sed 's/^/ /' >&2
|
||||||
|
printf ' Session: %s\n' "$session_path" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf ' Log: %s\n' "$LOG_DIR/${name}.log" >&2
|
||||||
|
fi
|
||||||
Loading…
Reference in New Issue