# session_wait_till_worker_idle — Block Until a Worker Slot Opens in a Pool

**Script name:** `session_wait_till_worker_idle`

**Script location:** [`scripts/session_wait_till_worker_idle.ts`](../../../scripts/session_wait_till_worker_idle.ts)

**Invoke:**
```bash
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/session_wait_till_worker_idle.ts \
  --tag-prefix PREFIX --pool-size N --timeout SECONDS [--server URL]
```

**CRITICAL:** Always invoke the script using bash and the format noted above. **Never** try to use the skill as a task, or invoke it through any other method than by directly calling bash with a command of the form listed above under "Invoke:".

## Synopsis

```
session_wait_till_worker_idle.ts \
  --tag-prefix PREFIX --pool-size N --timeout SECONDS [--server URL]
```

Blocks until the number of busy worker sessions in a specific pool drops below
the desired pool size, or until the timeout is reached.

Worker sessions are identified by tag prefix with strict prefix-dash matching:
the tag must start with `{PREFIX}-` and must **not** end with `-SUP`.

This is a convenience wrapper around
[`session_wait_till_idle`](../session_wait_till_idle/) with `--mode workers`.

## Arguments

| Flag | Type | Required | Description |
|------|------|----------|-------------|
| `--tag-prefix PREFIX` | string | yes | Tag prefix identifying the worker pool (e.g., `AUTO-IMP`). Matches tags starting with `{PREFIX}-`, excludes tags ending in `-SUP`. |
| `--pool-size N` | integer | yes | Positive integer; the maximum number of concurrent workers desired. Blocks while `busy_worker_count >= N`. |
| `--timeout SECONDS` | integer | yes | Positive integer; maximum seconds to block. |
| `--server URL` | string | no | OpenCode Server base URL (default: `http://localhost:4096`) |
| `-h`, `--help` | — | — | Print usage to stderr and exit 0 |

## Matching Rules

A session is counted as a **busy worker** when ALL of these are true:
1. Its status is `busy`
2. Its extracted tag starts with `{PREFIX}-` (strict prefix-dash matching)
3. Its tag does **NOT** end with `-SUP` (excludes supervisor sessions)

Examples with `--tag-prefix AUTO-IMP`:

| Session title | Tag | Matches? | Reason |
|---------------|-----|----------|--------|
| `[AUTO-IMP-ISSUE-42] impl-worker` | `AUTO-IMP-ISSUE-42` | Yes | starts with `AUTO-IMP-`, not `-SUP` |
| `[AUTO-IMP-PR-7] impl-worker` | `AUTO-IMP-PR-7` | Yes | starts with `AUTO-IMP-`, not `-SUP` |
| `[AUTO-IMP-SUP] impl-supervisor` | `AUTO-IMP-SUP` | No | ends in `-SUP` |
| `[AUTO-PRMRG-ISSUE-1] merge-worker` | `AUTO-PRMRG-ISSUE-1` | No | wrong prefix |
| `[AUTO-IMP] some-agent` | `AUTO-IMP` | No | no dash after prefix |

## Output

Written to **stdout** as a JSON object:

| Field | Type | Description |
|-------|------|-------------|
| `waited` | boolean | `true` if the script had to block at least once |
| `timed_out` | boolean | `true` if the timeout was reached before the condition was met |
| `elapsed_seconds` | number | Wall-clock seconds spent waiting (1 decimal precision) |
| `busy_count` | number | Final busy worker count at the moment the script returned |
| `max_pool_size` | number | The pool size threshold that was used |
| `mode` | string | Always `"workers"` |
| `tag_prefix` | string | The tag prefix that was used for matching |

Example:
```json
{
  "waited": true,
  "timed_out": false,
  "elapsed_seconds": 15.2,
  "busy_count": 2,
  "max_pool_size": 3,
  "mode": "workers",
  "tag_prefix": "AUTO-IMP"
}
```

## Diagnostics / stderr

```
Waiting for worker pool "AUTO-IMP" to have fewer than 3 busy worker(s) — timeout: 60s
[0.0s] Busy worker sessions (tag starts with AUTO-IMP-, excludes -SUP): 3 / max 3
[5.1s] Busy worker sessions (tag starts with AUTO-IMP-, excludes -SUP): 3 / max 3
[10.2s] Busy worker sessions (tag starts with AUTO-IMP-, excludes -SUP): 2 / max 3
Condition met after 10.2s — 2 busy worker(s) in pool "AUTO-IMP" < pool size 3
```

## Exit Codes

| Code | Meaning |
|------|---------|
| 0 | Always — check the `timed_out` field in JSON output to distinguish condition-met from timeout |
| 1 | Fatal error (missing args, invalid values, API unreachable after retries) |

## When to Use This Script

- **Supervisor gating new worker dispatch:** a supervisor that manages a worker
  pool calls this before launching a new worker to ensure the pool is not
  over-saturated.
- **Backpressure control:** prevent launching more workers than the system can
  handle by blocking until a slot opens.
- **Sequential dispatch:** in a loop that dispatches workers for multiple tasks,
  call this between dispatches to maintain the pool size invariant.

## Usage Examples

```bash
# Wait for the AUTO-IMP worker pool (max 4 workers) to have an opening, 60s timeout
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/session_wait_till_worker_idle.ts \
  --tag-prefix "AUTO-IMP" --pool-size 4 --timeout 60

# Wait for the AUTO-PRMRG worker pool (max 2) with a longer timeout
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/session_wait_till_worker_idle.ts \
  --tag-prefix "AUTO-PRMRG" --pool-size 2 --timeout 300

# Quick slot check with 1s timeout (effectively: is the pool full right now?)
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/session_wait_till_worker_idle.ts \
  --tag-prefix "AUTO-IMP" --pool-size 4 --timeout 1
```

## Dependencies

- Node.js >= 18 (native `fetch` API)
- `npx tsx` for TypeScript execution
- Zero external npm packages
