refactor(harness): registry-driven server seeding loop (PR 1.7) - #3599
Conversation
|
/review |
|
|
Thanks Polly — no blocking issues, and the byte-identical verification across all 11 agents matches what I checked locally. On the three non-blocking notes:
|
On the Coverage status (
|
Collapse the server's built-in native-agent seeding onto the NativeHarnessProvider seam. The 11 hand-written _ensure_default_<x>_agent helpers + their 11 _build_<x>_native_bundle partners become two registry-driven functions in omnigent/server/app.py: - _build_native_bundle(provider): resolves provider.materialize_agent_spec via the seam and runs the shared materialize -> bundle -> tar dance. The per-harness `model` arg variance (codex required kw / kiro,opencode default / the rest none) is bridged by one inspect.signature check. - _ensure_default_native_agents(...): loops NATIVE_CODING_AGENTS, resolving the provider by key and seeding each content-aware via _ensure_builtin_agent. debby / polly / _ensure_extra_builtin_agents stay hand-written. Removed the now -dead _<X>_NATIVE_AGENT_NAME constants and the *_NATIVE_CODING_AGENT imports. Net server/app.py -455/+146. Redeploy safety: builtin_agent_id(name) is a pure hash of the agent name, and the names (NativeCodingAgent.agent_name) and bundle bytes are unchanged, so seeded ids and bundles stay byte-identical (verified: sha256 of _build_native_bundle output matches the pre-loop named builders across all model-arg variants). New tests freeze the 11 expected ids and assert the loop covers every native agent. Updated test_builtin_bundles / test_app to the generic builder; fixed stale symbol refs in two e2e tests and a scheduled-tasks integration test. Co-authored-by: Isaac Signed-off-by: Pat Sukprasert <pattara.sk127@gmail.com>
The seeding-loop collapse removed ~330 lines that were only exercised transitively by e2e suites; add direct unit coverage so the new generic path is fully covered and the coverage gate recovers: - Parametrize the native bundle-builder tests over EVERY native agent (was a 4-agent sample), so each harness's _materialize_* + bundle path is covered directly, across both model-arg shapes. - Cover the two defensive guards in _build_native_bundle / _ensure_default_native_agents (missing materialize hook, missing provider row). - Add an end-to-end seed test asserting all 11 native agents register under their stable builtin_agent_id with a retrievable bundle. Co-authored-by: Isaac Signed-off-by: Pat Sukprasert <pattara.sk127@gmail.com>
…bridge Address Polly non-blocking note: the inspect.signature bridge in _build_native_bundle understands only the `model` kwarg; a future harness whose materializer needs a different required kwarg fails loud at seed time rather than routing. Comment so the next author knows. Co-authored-by: Isaac Signed-off-by: Pat Sukprasert <pattara.sk127@gmail.com>
315d895 to
ac3b8c4
Compare
|
/review |
|
… 1.7)
The seeding-loop collapse deleted the 11 private _<X>_NATIVE_AGENT_NAME
constants from server/app.py (the loop uses agent.agent_name directly), which
pushed callers that need one specific built-in onto magic-string literals
("claude-native-ui", "qwen-native-ui", ...) in the tests.
Restore them as PUBLIC constants in omnigent/native_coding_agents.py — the
module that already indexes the registry rows — so seeding and tests share one
named, registry-derived source of truth instead of re-deriving the literal:
- Add CLAUDE_NATIVE_AGENT_NAME ... KIMI_NATIVE_AGENT_NAME (each = the row's
agent_name) to native_coding_agents.
- Point the server + scheduled-tasks tests at the shared constants (drop the
bare "qwen-native-ui" / "antigravity-native-ui" / "claude-native-ui" strings).
- Fold the two host e2e tests' own local _CLAUDE/_CODEX_NATIVE_AGENT_NAME
literals onto the shared constants too.
Co-authored-by: Isaac
Signed-off-by: Pat Sukprasert <pattara.sk127@gmail.com>
|
Follow-up pushed ( An earlier revision of this PR deleted the 11 Now restored as a shared, public block in
The seeding loop stays registry-driven; the constants exist for callers that need a specific built-in by name. 112 server tests pass, e2e files import the new symbol, ruff/pre-commit clean. |
|
/review |
|
|
Thanks Polly — approve confirmed, and good catch on the incomplete sweep. Fixed in The behavior-preservation verification (byte-identical bundles across the three signature shapes, byte-stable name-derived ids, raise-on-missing) matches what I checked locally — appreciate the independent confirmation. |
|
🏷️ Doc impact: This is an internal refactor collapsing 11 hand-written native-agent seed helpers into one registry-driven loop (plus symbol/test renames); the set of built-in native agents and their behavior is unchanged, so no user-facing surface changed. Auto-classified on merge. Set the label manually before merging to override. · run |
|
Correction: my note above said the opencode e2e cleanup landed in |
) Follow-up to #3599 (PR 1.7). That PR moved the built-in native agent-name constants into a shared public block in omnigent/native_coding_agents.py and migrated the claude/codex host e2e tests onto them, but missed the opencode sibling: test_host_opencode_native_e2e.py still defined a local _OPENCODE_NATIVE_AGENT_NAME = "opencode-native-ui" literal and asserted a stale '_ensure_default_opencode_agent did not run' message (that per-harness seeder was collapsed into _ensure_default_native_agents). Import the shared OPENCODE_NATIVE_AGENT_NAME constant and update the message so all three host e2e tests are consistent. Test-only; opt-in e2e (skipped without OMNIGENT_E2E_OPENCODE_NATIVE=1). Co-authored-by: Isaac Signed-off-by: Pat Sukprasert <pattara.sk127@gmail.com>
Related issue
N/A — part of the modular native-harness registry workstream (
designs/harness-modular-registry-proposal.md).Summary
PR 1.7 of the modular native-harness registry refactor: collapses the server's built-in
native-agent seeding loop onto the
NativeHarnessProviderseam. It's a disjoint hub(depends on 1.1, not the runner PRs).
omnigent/server/app.py: the 11 hand-written_ensure_default_<x>_agenthelpers + their11
_build_<x>_native_bundlepartners collapse into two registry-driven functions —_build_native_bundle(provider)(resolvesprovider.materialize_agent_specvia the seam)and
_ensure_default_native_agents(...)(loopsNATIVE_CODING_AGENTS). Net −455/+146.modelarg variance (codex requires a keyword-onlymodel; kiro/opencodedefault it; the rest take just
tmpdir) is bridged by oneinspect.signaturecheck, so theproduced bundles are byte-identical to the pre-loop builders.
_ensure_extra_builtin_agentsstay hand-written (shipped-example andenv-driven paths — not
_materialize_*).server/app.py(where thecollapsed loop no longer needs them) into a shared, public block in
omnigent/native_coding_agents.py—CLAUDE_NATIVE_AGENT_NAME…KIMI_NATIVE_AGENT_NAME,each
= <registry row>.agent_name. Seeding and tests reference a single namedsource of truth instead of magic-string literals. (See the follow-up commit note below.)
Redeploy safety (the core invariant)
builtin_agent_id(name)issha256("builtin:<name>")[:32]— a pure hash of the agent name.Persisted
conversation.agent_idrows point at these ids, so both the seeded ids and thebundle bytes must stay byte-identical or a redeploy orphans live sessions. Verified
empirically:
_build_native_bundle(provider)produces byte-identical tarballs (sha256 match)to today's named builders for claude/codex/pi/kiro/opencode/qwen — across all three model-arg
variants — and the seeded ids are frozen in a new test.
ELI5
Eleven copy-pasted "build this agent's starter bundle and register it" pairs in the server
startup became one loop over the harness registry. The agent ids are hashes of their names, and
the names didn't change, so every existing session still points at the right agent after a
redeploy — pinned by a test that freezes the expected ids.
Test Plan
test_builtin_bundles.py: the native_BUILDERScases now drive the generic_build_native_bundle(provider)(claude/codex/pi/kiro — a spread of the model-arg variants),keeping the valid-tarball + reproducibility assertions; debby/polly keep their named-builder
cases.
test_native_seed_ids_are_byte_stablefreezes the 11 expected 32-char ids;test_native_seed_loop_covers_every_native_agentasserts the loop resolves a provider forevery
NATIVE_CODING_AGENTSentry (a dropped harness raises instead of silently unseeding).Demo
N/A — internal server-startup refactor, no user-facing or UI change.
Type of change
Test coverage
Coverage notes
Behavior-preserving refactor. Beyond the updated/added unit tests, I verified byte-stability
directly: captured sha256 of every named builder's output on
main, then confirmed_build_native_bundle(provider)reproduces each hash exactly on this branch (claude, codex,pi, kiro, opencode, qwen — covering bare-
tmpdir, required-model, and defaulted-modelsignatures). The two stale references to deleted function names in e2e comments/messages
(
test_host_codex_native_e2e.py,e2e_ui/conftest.py) were updated; both were text-only, notcalls.
Follow-up (
ef98b092) — shared agent-name constants. An earlier revision of this PR deletedthe 11
_<X>_NATIVE_AGENT_NAMEconstants outright (the seeding loop usesagent.agent_name),which pushed callers that need one specific built-in onto magic-string literals
(
"claude-native-ui","qwen-native-ui", …) in the tests. That was an overcorrection; they'renow restored as public constants in
omnigent/native_coding_agents.py(the module thatalready indexes the registry rows), and every caller —
test_app.py,test_scheduled_tasks_routes.py, and the two host e2e tests (which previously each redefinedtheir own local literal) — imports the shared symbol. Net: one registry-derived source of truth,
no magic strings.
Workstream progress (
designs/harness-modular-registry-proposal.md, ~14 PRs):Phase 1 — 1.1 (#3239), 1.2 (#3244), 1.3 (#3314), 1.5a (#3495), 1.5b-i (#3500), 1.5b-ii
(#3501), 1.5c (#3543) landed; 1.6 (#3568) in review; 1.7 is this PR. Remaining: 1.8
(enumerations); Phase 2 — 2.1–2.4. 1.7 is a disjoint hub — independent of the 1.6 review.
(Also flips the stale 1.5c ledger row to
landed.)