refactor(harness): registry-driven native launch dispatch — scaffolding + uniform arms (PR 1.5b-i) - #3500
Conversation
…ng + uniform arms (PR 1.5b-i) First half of the runner launch seam. Wires the provider's auto_create_terminal field (declared since 1.1, never dispatched) and collapses the 8 uniform create-session launch arms in runner/app.py onto it. Behavior-preserving. - orchestration: add NativeLaunchContext (flat dataclass of the inputs the 11 builders may need, incl. claude's closures), PreLaunchResult (skip / force_recreate / needs_terminal for the special arms in 1.5b-ii), 11 thin _launch_<x>(ctx) adapters that unpack the context and call the unchanged _auto_create_<x>_terminal builder with that harness's exact kwarg subset, and the shared shell _launch_native_terminal(harness, ctx, *, ensure_locks, pre_launch=None, resolve_agent_spec=None). The shell runs the lock / existence-check / pending+error-event mechanics every arm shared and resolves the adapter via resolve_hook(provider, "auto_create_terminal"). - Option A (adapters, builders unchanged) keeps the 21 direct-call builder tests intact. agent_spec is resolved lazily via resolve_agent_spec inside the create block, preserving each arm's error semantics (pi unwrapped; cursor/opencode/ kimi swallow OmnigentError via _resolve_session_agent_spec_or_none; the rest pass no resolver). - harness_plugins: repoint auto_create_terminal to omnigent.runner.native:_launch_<key>. - app.py: the 8 uniform arms (pi, cursor, kiro, opencode, goose, hermes, qwen, kimi) become one _launch_native_terminal call each, picking the per-harness lock dict (kept app-scope so session cleanup can pop by name). Net -256 lines. - qwen's launch-error label is now "Qwen Code" (uniform display_name) vs the former lowercase "qwen" — cosmetic; no test asserted the literal. Deferred to 1.5b-ii: the 3 special arms (claude/codex/antigravity) and the turn-path opencode cold-boot, which still use the direct builders. Tests: unit-cover each adapter's kwarg subset and the shell's branches (create / existing-skip / force-recreate teardown / skip+needs_terminal / start-error event / lazy-spec-only-on-create / non-native None). The workflow- init HTTP suite exercises the real launch path for the uniform arms and stays green. Pre-existing codex gateway-env failures in events_lifecycle are unchanged (verified identical on clean main; codex arm untouched here). Co-authored-by: Isaac Signed-off-by: Pat Sukprasert <pattara.sk127@gmail.com>
|
|
🏷️ Doc impact: Internal refactor consolidating per-harness native terminal launch arms into a shared Auto-classified on merge. Set the label manually before merging to override. · run |
Four conflicts. Three are our copy vs upstream's now-merged copy of the same change (omnigent-ai#3431, merged 2026-07-29) — took upstream wholesale, since the maintainer's version is stricter: the helper is public (harness_owns_its_credential) and gains an early `if canonical in _HARNESS_FAMILY: return False`. The fourth, runner/app.py, needed a real port rather than a side: ours: _build_acp_spawn_env(spec, ..., override_harness=acp_override) upstream: _build_acp_spawn_env(effective_spec, cwd=cwd, workdir=workdir) Upstream introduced `effective_spec`, which bakes in the per-session model override. Taking our side verbatim would have silently dropped that override for every ACP session, so this keeps upstream's spec AND our acp:<slug> threading (omnigent-ai#3057). The openai-agents picker label survives the merge untouched in both sources despite upstream refactoring harness_plugins.py three times (omnigent-ai#3239, omnigent-ai#3495, omnigent-ai#3500) — different regions, no conflict. Signed-off-by: apeltekci <andrew@peltekci.com>
…ch arms (PR 1.5c) (#3543) Collapse the terminal-ensure / attach path in create_session_terminal — 11 hardcoded `if terminal_name == "<x>" and session_key == "main"` arms — behind a single generic `_ensure_native_terminal(...)` shell dispatched through the NativeHarnessProvider seam. The attach-path sibling of the 1.5b launch shell (#3500/#3501); reuses the `_launch_<x>` adapters and NativeLaunchContext. codex/antigravity supply an ownership predicate; codex supplies a `finalize` for its one-shot policy notice — both run under the per-session ensure lock, matching the inline arms. - New shell in runner/native/orchestration.py (view-based existence check, returns JSONResponse: 200 / 500 / 409), exported from runner/native. - app.py: 11 arms (~450 lines) -> one collect-then-dispatch block. - Repoint the HTTP attach-path claude/codex auto_create monkeypatch targets to the orchestration module (the seam resolves the adapter there). - 8 new unit tests for the shell. - Doc: add 1.5c ledger row; flip stale 1.5b-i/ii rows to landed. Behavior-preserving: qwen error label -> "Qwen Code" (display_name, as 1.5b-i); antigravity now wires ensure_comment_relay via the base ctx (the landed _launch_antigravity adapter already passed it). Co-authored-by: Isaac Signed-off-by: Pat Sukprasert <pattara.sk127@gmail.com>
Workstream progress
Modular native-harness registry (
designs/harness-modular-registry-proposal.md). ~14 PRs total — Phase 1 (internal seam): 1.1–1.4, 1.5a/b/c, 1.6, 1.7, 1.8; Phase 2: 2.1–2.4.1.5b is split so the low-risk bulk (this PR) lands separately from the behavior-preservation-critical special arms (1.5b-ii, stacked on this).
Related issue
N/A — Phase 1, PR 1.5b-i of the modular native-harness registry.
Summary
Wires the provider
auto_create_terminalfield (declared since 1.1, never dispatched) and collapses the 8 uniform native launch arms inrunner/app.pyonto it. Behavior-preserving. Net −256 lines inapp.py.orchestration.py— add:NativeLaunchContext: one flat frozen dataclass of the inputs the 11 builders may need (incl. claude's 3 closures), each adapter reads only its subset.PreLaunchResult(skip/force_recreate/needs_terminal) — consumed by the shell; the special arms in 1.5b-ii produce it._launch_<x>(ctx)adapters that unpack the context and call the unchanged_auto_create_<x>_terminalbuilder with that harness's exact kwarg subset (Option A — keeps the 21 direct-call builder tests intact)._launch_native_terminal(harness, ctx, *, ensure_locks, pre_launch=None, resolve_agent_spec=None)— the shared shell: lock → existence-check → pending/error events →resolve_hook(provider, "auto_create_terminal")(ctx).agent_specresolves lazily inside the create block viaresolve_agent_spec, preserving each arm's error semantics (pi unwrapped; cursor/opencode/kimi swallowOmnigentError; the rest none).harness_plugins.py— repointauto_create_terminaltoomnigent.runner.native:_launch_<key>.app.py— the 8 uniform arms (pi, cursor, kiro, opencode, goose, hermes, qwen, kimi) each become one_launch_native_terminal(...)call, picking the per-harness lock dict (kept app-scope so session cleanup can pop by name)."Qwen Code"(uniformdisplay_name) vs the former lowercase"qwen"— cosmetic; no test asserted the literal.Deferred to 1.5b-ii: the 3 special arms (claude/codex/antigravity, which carry pre-call rebuild/transfer/needs-checks) and the turn-path opencode cold-boot — they still call the direct builders here.
Test Plan
force_recreateteardown /skip+needs_terminal→ False / start-error event on failure / lazy-spec-resolved-only-on-create / non-native → None).workflow_initHTTP suite drives the real launch path for the uniform arms and stays green; direct-callterminals_autocreate(21 sites) unaffected.events_lifecycletests pass (9 passed). The 6 failing tests in that file are all codex (app-server/gateway-env artifacts) and fail identically on clean main — codex's arm is untouched in this PR.Demo
N/A — backend refactor, behavior-preserving. Launch path covered by the unchanged
workflow_initHTTP suite.Type of change
Test coverage
Coverage notes
New unit coverage accompanies the scaffolding (adapter kwarg subsets + shell branches). Behavior-preservation across the runner launch path is covered by the existing native workflow-init / terminals-autocreate suites, which stay green.
Changelog
qwen-native's terminal-start error label now reads "Qwen Code" (consistent with the other native harnesses) instead of "qwen".
This pull request and its description were written by Isaac.