# 05. Scheduler, retry, and command-target parsing meta: id: pygienium-05 feature: pygienium priority: P1 depends_on: [pygienium-01] tags: [infrastructure, utilities, no-model] objective: - Build three small infra modules the check runner needs: a concurrency-bounding scheduler, a retry-with-backoff helper, and a command argument parser. deliverables: - `src/scheduler.ts`: `Scheduler` with `enqueue({id, run})`, burst cap from env `PYGIENIUM_MAX_AGENTS` (default 3), `dispose()` - `src/retry.ts`: `runWithRetry`, `readPositiveIntEnv`, `readNonNegativeIntEnv`, `errorMessage`, `yieldToEventLoop` - `src/command-target.ts`: `parseCommandArgs(args, cwd, opts)` → `{ cwd, tokens, args, error? }` supporting `[path]`, `--fresh`, `--fix`, `--check=`, `--scope=` steps: - Port piolium's `Scheduler` (Promise.allSettled under a semaphore-like cap) and `retry.ts` env helpers - Implement `runWithRetry(fn, { maxRetries, backoffBaseMs, backoffMaxMs, onRetry, signal })` - Implement `parseCommandArgs`: first non-flag token = optional target path (default cwd); collect `--flag` and `--opt=val` tokens into a tokens array + option lookup; return error string for malformed input tests: - Unit: scheduler caps concurrent runs at the configured value (spawn N no-op tasks, assert max in-flight) - Unit: retry exhausting throws the last error; onRetry invoked with backoff between attempts - Unit: parser handles `--fresh /repo --check=comments` → cwd=/repo, tokens=[--fresh, --check=comments], check=comments acceptance_criteria: - Scheduler never exceeds the burst cap - retry respects maxRetries and aborts on signal - parser returns structured tokens with no ambiguity for the supported flags validation: - `grep -n "PYGIENIUM_MAX_AGENTS" src/scheduler.ts` present - Unit test suite for the three modules passes (if a test runner is configured) notes: - These are pure utilities; keep them dependency-free beyond node builtins - Grouped into one task because each is small and they're mutually independent