Work on Hub-to-Runner integration through the canonical SDK request/event/result path.
Hub does not launch executors directly. It creates SDK requests and submits them through
src/runner-client/local-runner-client.ts.
WorkflowService.resolveExecutor().ExecutorSpec, TaskExecutionRequest, TaskExecutionEvent, and TaskExecutionResult.devagent-runner.src/__tests__/baseline-compatibility.test.tssrc/__tests__/baseline-machine-path.test.tssrc/__tests__/workflow-service.test.tslaunch() must return { exitCode, outputPath, eventsPath, output } — never throw.<artifactsDir>/<runId>/<phase>-input.json before executing.<phase>-output.json<phase>-events.jsonl{...} from free text.exitCode: 2 for unsupported phases, not an exception.describe() shells out to <bin> --version with a 5s timeout. Returns null on failure.LauncherFactory (OPENCODE_BINS, CLAUDE_BINS, CODEX_BINS sets) and add detection in isXxxBin(), createAdapter(), createStreamingAdapter(), and describeRunners().createStreamingAdapter().Each phase prompt must instruct the agent to output ONLY valid JSON with the fields expected by the orchestrator. See PHASE_PROMPTS in existing runners for the exact schemas per phase (triage, plan, implement, verify, review, repair, gate).
Add a test in src/__tests__/selection-policy.test.ts confirming factory.getLauncher(phase).id returns the correct runner id for the new bin.