## Related issue N/A ## Summary The published `dev` extra mixed repository workflows with installable Omnigent capabilities. Move contributor-only dependencies to PEP 735 groups so package extras describe product functionality and CI installs only the workflow dependencies it executes. - Replace the `dev` extra with local-only `lint`, `test`, and aggregate `dev` groups; configure no default groups so plain `uv sync` matches the published base package. - Remove the retired mypy dependency/configuration, `types-PyYAML`, the orphaned `pathspec` declaration, and the duplicate `filelock` declaration. - Migrate workflows, actions, contributor commands, tests, and development skills from `--extra dev` to the smallest required group, or no group for application/benchmark jobs. - Compose Pyrefly's lint environment from the `lint` group plus the existing `hindsight`, `nimble`, `s3`, and `tracing` capability extras. Remove the OpenTelemetry missing-import configuration and Nimble's inline missing-import suppression so real package types remain checked. - Update OpenShell, e2e, browser-test, Slack, and implementation-plan commands to compose capability extras with repository groups explicitly. Document why read-only/tools-less agent workflows intentionally keep runtime-only environments. - Avoid `--all-extras`: it resolves but selects 240 product packages, including unrelated large/native integrations. Keep capability ownership explicit instead. ELI5: product features remain extras users can install; lint and test toolboxes become private repository groups that never appear in the wheel. ```text published wheel: base + capability extras repository: lint group | test group | dev = lint + test CI lint: lint + explicitly type-checked capability extras ``` ## Test Plan - `uv lock && just normalize-locks` - Built the wheel and verified its metadata contains no `dev` extra or lint/test dependencies. - Verified a fresh base environment imports Omnigent, excludes lint/test/pathspec packages, and imports each release benchmark script. - `uv run --isolated --frozen --group lint --extra hindsight --extra nimble --extra s3 --extra tracing pre-commit run pyrefly --all-files` - `uv run --isolated --frozen --group lint python scripts/gen_routing_pb2.py --check` - Verified isolated `test` and aggregate `dev` group membership independently. - `uv run --isolated --frozen --group test pytest tests/tools/builtins/test_hindsight.py tests/tools/builtins/test_nimble_research.py tests/stores/test_s3_artifact_store.py tests/db/test_d1_fts_dialect.py -q` (172 passed) - `uv run --isolated --frozen --group test --extra tracing pytest tests/runtime/test_telemetry.py tests/inner/test_tracing_genai_semconv.py -q` (69 passed) - `uv run --isolated --frozen --extra openshell --group test pytest tests/onboarding/sandboxes/test_openshell.py tests/server/test_managed_hosts.py -q` (259 passed) - Verified load-test modules import with only `loadtest` and `agents-sdk` extras. - Ran the exact locked lint sync against PyPI and Pyrefly passed. - Rebased onto current `origin/main`; migrated the newly added compatibility-smoke test actions and host benchmark workflow. - Surveyed all tracked uv install/run commands and removed every remaining published-`dev`/implicit-tooling command. Verified the documented e2e and Slack environments and collected the Kimi/live-DDG tests in fresh group-selected environments. - `uv run --frozen pre-commit run --all-files` ## Demo N/A — dependency metadata and CI configuration only. ## Type of change - [ ] Bug fix - [ ] Feature - [ ] UI / frontend change - [x] Refactor / chore - [ ] Docs - [ ] Test / CI - [ ] Breaking change ## Test coverage - [ ] Unit tests added / updated - [ ] Integration tests added / updated - [ ] E2E tests added / updated - [x] Manual verification completed - [x] Existing tests cover this change - [ ] Not applicable ## Coverage notes Fresh isolated environments validated the base, lint, test, aggregate dev, tracing-test, and load-test dependency boundaries. Focused tests prove retained optional clients are genuine test runtimes, while wheel inspection proves repository groups are not published. Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
Codex Parity Tests
This suite verifies Omnigent's Codex integration by running the real boundary we care about:
Omnigent CodexExecutor
-> real codex app-server process
-> mock OpenAI Responses API
The important choice is that the tests do not mock the Omnigent-to-Codex API. They start a real Codex CLI and only replace the upstream model endpoint. That means the test covers Codex app-server JSON-RPC behavior, Codex request serialization, retry notifications, streaming notifications, and dynamic tool round trips.
Architecture
pytest
|
| starts
v
Rust sidecar: tests/codex_parity/sidecar
|
| uses upstream Codex test helper crate
v
core_test_support::responses / WireMock
^
| /v1/responses
|
real codex app-server
^
| JSON-RPC app-server protocol
|
Omnigent CodexExecutor
The Rust sidecar exists because Codex's mock Responses API helpers are Rust test-support code in the public Codex repository. Rather than reimplementing that mock in Python, the sidecar pulls the upstream test-support crate directly through Cargo:
core_test_support = { git = "https://github.com/openai/codex.git", rev = "..." }
That keeps the fake Responses wire format aligned with Codex upstream. Pytest still owns the test scenarios and assertions; the sidecar only starts WireMock, serves queued SSE fixtures, and reports captured requests.
The revision is pinned in tests/codex_parity/sidecar/Cargo.toml so the parity
harness is reproducible without requiring a checked-in Codex submodule. Updating
the upstream fixture implementation is a normal Cargo dependency bump: change the
Codex rev, refresh Cargo.lock, and run the parity tests.
Fixture Flow
Each test passes a list of model responses to the sidecar:
sidecar = codex_responses_sidecar(
[
[
ev_response_created("resp-1"),
ev_assistant_message("msg-1", "hello"),
ev_completed("resp-1"),
]
]
)
Each inner list becomes one SSE response body. Codex consumes one body per
POST /v1/responses request. Multi-turn scenarios enqueue multiple inner
lists, for example a dynamic tool call followed by the assistant's final
answer after Omnigent returns the tool result.
The sidecar prints one JSON ready line with a base_url. The pytest fixture
passes that URL into CodexExecutor using the existing gateway override path,
so Codex sends model traffic to the sidecar instead of OpenAI.
After a turn, pytest asks the sidecar for captured requests over a small JSONL stdin/stdout protocol:
{"op": "requests", "min": 1, "timeout_ms": 5000}
The response includes stable fields that are useful for parity assertions: request path, selected headers, and JSON body.
Coverage
test_codex_executor_parity.py covers executor-observable turn behavior:
sdk/python/tests/test_app_server_run.py- mock Responses request path/model/input
- explicit token usage crossing the app-server boundary
- last unknown-phase message selection
- final-answer phase preference
- commentary-only output not becoming the final response
- failed Responses events surfacing as turn errors
sdk/python/tests/test_app_server_streaming.py- text delta routing and completed-turn response
- selected request-routing behavior from
codex-rs/core/tests/suite/*- dynamic tool call/result round trip through real Codex app-server
test_codex_goal.py covers the Codex goal contract Omnigent relies on:
- upstream app-server goal operations
thread/goal/set+thread/goal/get+thread/goal/clearround trip- pause/resume through
thread/goal/setstatus-only updates - explicit
tokenBudget: nullpreservation - idempotent
thread/goal/clear budgetLimitedpreservation when setting the same objective- persisted
blockedandusageLimitedgoal statuses
- Omnigent AP goal routes
PUT /v1/sessions/{id}/codex_goalforwards objective, budget, and modePATCH /v1/sessions/{id}/codex_goal/statusforwards pause/resume- Codex-owned terminal statuses are rejected as user-writeable inputs
- Codex-owned terminal statuses returned by the runner are preserved
- API-shaped misses return JSON 404s instead of the SPA shell
That is comprehensive for the goal surface Omnigent owns because it exercises both sides of the integration: real Codex app-server JSON-RPC for every goal state transition we depend on, and Omnigent's public HTTP route mapping for every browser control we expose. It intentionally does not copy Codex TUI slash-menu/status rendering tests; Omnigent does not embed that TUI path. It also does not duplicate Codex's internal goal-extension accounting tests except where the app-server result is part of Omnigent's public contract.
Not yet represented here: upstream SDK-only app-server tests for lifecycle,
login, approvals, steer/interrupt, local/remote image input, and skill input.
Those APIs do not have a direct Omnigent CodexExecutor surface yet, so they
need either executor-facing analogs or a separate SDK compatibility harness
before they can be one-for-one parity tests.
Updating From Codex Upstream
The upstream Codex fixture dependency is pinned in
tests/codex_parity/sidecar/Cargo.toml:
core_test_support = { git = "https://github.com/openai/codex.git", rev = "..." }
To refresh the harness:
- Update that
revto the Codex commit you want to validate against. - Refresh
tests/codex_parity/sidecar/Cargo.lockby building or testing the sidecar. - Inspect the pinned Codex checkout under Cargo's git cache, usually
~/.cargo/git/checkouts/codex-*/<rev>/. - Compare these upstream files against the local parity files:
sdk/python/tests/test_app_server_run.pysdk/python/tests/test_app_server_streaming.pysdk/python/tests/test_app_server_goal_operations.pysdk/python/tests/test_client_rpc_methods.pycodex-rs/app-server/tests/suite/v2/thread_resume.rscodex-rs/ext/goal/tests/goal_extension_backend.rscodex-rs/prompts/src/goals_tests.rs
- Port new app-server public-contract goal cases into
tests/codex_parity/test_codex_goal.py. Keep TUI-only cases classified as intentionally excluded unless Omnigent starts exposing that path. - Run the focused goal file, then the full parity suite:
pytest tests/codex_parity/test_codex_goal.py \
--codex-parity \
--codex-bin "$(which codex)" \
-q
pytest tests/codex_parity \
--codex-parity \
--codex-bin "$(which codex)" \
-q
Running
Run against the Codex CLI on PATH:
pytest tests/codex_parity --codex-parity -v
Run against one explicit binary:
pytest tests/codex_parity --codex-parity --codex-bin "$(which codex)" -v
Compare multiple Codex versions:
pytest tests/codex_parity \
--codex-parity \
--codex-bin /path/to/codex-old \
--codex-bin /path/to/codex-new \
-v
You can also set CODEX_TEST_BINS to an os.pathsep-separated list.
At Databricks, use the internal PyPI proxy when syncing the Python test environment:
uv --no-config run --frozen \
--default-index https://pypi-proxy.cloud.databricks.com/simple/ \
--group test \
pytest tests/codex_parity --codex-parity --codex-bin "$(which codex)" -q
Why This Shape
Mocking the Omnigent-to-Codex API would test our assumptions about Codex's app-server protocol. This suite instead lets Codex define that contract by running the actual CLI/app-server implementation. Only the final network hop is mocked, which gives us stable, deterministic tests while still catching protocol drift between Omnigent and Codex.