Repository navigation
Conversation
|
Product question (not addressed in this PR): Codex strips an admin's managed On an unmanaged launch with no model chosen, Codex's Two things look inconsistent:
This PR's Codex cases deliberately seed only keys outside ug's owned paths, so they neither lock in nor contradict the current behavior. If the intended behavior is to preserve admin-set |
11fbb2b to
3a1440d
Compare
58a6c8b to
d0c996e
Compare
read_jsonl used Path.read_text() with the platform default encoding. On the Windows integration lane that is cp1252, which cannot decode UTF-8 model text such as a closing curly quote (0xE2 0x80 0x9D), so every Codex headless case that reads its session transcript through assert_completed_task_model failed with UnicodeDecodeError. Read transcripts as UTF-8 and add a reader regression test with non-ASCII content; it fails under a non-UTF-8 default without the fix. Co-authored-by: Isaac <no-reply@databricks.com>
`codex exec` cannot prompt for a Windows sandbox on first run and rejects
every shell command until one is configured, so on the Windows lane the
fresh-workspace task could not read its file ("file-system access is
blocked by the current sandbox/policy"). Call
choose_codex_windows_sandbox() as the other Codex headless journeys do;
it is a no-op elsewhere.
Co-authored-by: Isaac <no-reply@databricks.com>
d844ef6 to
1fbc5d7
Compare
Headless launches have no TTY, so ug leaves Claude's OS-managed settings untouched unless they conflict; only an interactive launch rewrites that file. Add a CUJ7 TUI case that seeds OS-managed family defaults, selects Sonnet in the real Claude TUI, and asserts that ug rewrote the file (its ANTHROPIC_BASE_URL is present) while keeping every seeded default, that the TUI task reached the Sonnet service through the recorder, and that `ug revert` restores the seeded file. Co-authored-by: Isaac <no-reply@databricks.com>
Keep CUJ7 at Claude/Codex parity: add Codex's headless preservation case (before ug's separator and in exec) and its interactive rewrite case, each over a seeded /etc/codex/managed_config.toml holding inert admin settings outside ug's owned keys (a sibling AdminProvider model provider and file_opener). Both agents now share one seeded-file fixture and the same assertions: every seeded leaf unchanged, task-correlated inference through the recorder (Codex also with the parent-schema header), and for the interactive cases ug's gateway base URL in the rewritten file plus `ug revert` restoring the seeded document. CUJ7 now collects twelve cases, six per agent. Co-authored-by: Isaac <no-reply@databricks.com>
d0c996e to
53000c6
Compare
Summary
Stacked on #930. Adds the CUJ7 coverage #930's headless cases cannot reach, and keeps CUJ7 at Claude/Codex parity. Tracks AIGTWY-4882.
ug only rewrites an agent's OS-managed file when it has a TTY:
managed_writes_allowed()issys.stdin.isatty()(src/ucode/managed_files.py). Both_reconcile_managed_settings(Claude) and_reconcile_managed_config(Codex) return early unless ug's desired settings conflict with the file, and a missing owned path is not a conflict.UserSession.runstarts children with stdinDEVNULLor a pipe, so every headless case covers only the no-write path. No test asserted that the interactive rewrite keeps pre-existing admin input.CUJ7 now collects twelve cases, six per agent:
--model-locationtask ×2test_ug_claude_preserves_preexisting_managed_family_defaults(#930)test_ug_codex_preserves_preexisting_managed_config(new)test_ug_claude_tui_rewrites_managed_settings_preserving_family_defaults(new)test_ug_codex_tui_rewrites_managed_config_preserving_admin_settings(new)Shared fixture and assertions. #930's
family_defaultsfixture is now an agent-keyedmanaged_inputfixture. It seeds/etc/claude-code/managed-settings.jsonwith distinct family defaults, or/etc/codex/managed_config.tomlwith inert admin settings outside ug's owned keys: a siblingAdminProvidermodel provider andfile_opener. Teardown is unchanged: recording stops, then the guarded revert, file removal and parent-directory cleanup (only if the fixture created the directory) run. Every preservation case requires:_assert_contains;assert_inference_evidence(Codex also withdatabricks-model-service-parent-schema = ug_e2e.models, plus a completed turn reporting the scoped Luna service; Claude headless also checksmodelUsage);env.ANTHROPIC_BASE_URL/model_providers.Databricks.base_url=<recorder>/ai-gateway/{anthropic,codex/v1}). This proves the interactive write happened.ug revertmust restore the parsed seeded document. Revert may reserialize the file, so the comparison is on parsed JSON/TOML, not bytes.Both READMEs now describe CUJ7 as eight journeys and twelve cases, and the scenario table has rows for the three new cases.
Not asserted, intentionally. Codex strips a pre-existing
model/model_reasoning_effortfrom the managed file when no model is chosen. That is the opposite of Claude's family-default preservation, and the CUJ seed avoids those keys. See the comment below; it's a product question, not something to lock in here.Validation
e2e_cujcases collect (90), including 12 CUJ7 cases, with--confcutdir=tests/e2e_cujand pexpect/pyte, matching CI._assert_containsaccepts ug's additions and rejects a changed or missing seeded leaf, and_assert_rewrittenrejects a file ug did not write.ruff checkandruff format --checkpass ontests.tests/test_e2e_user_agent.py::TestClaudeUserAgent::{test_user_agent_arrives_at_gateway,test_managed_http_header_arrives_at_gateway}, which also fail onorigin/mainon the authoring host: it has its own/etc/claude-code/managed-settings.json. They pass in CI.ci.ymlonly triggers on PRs targetingmain, so this stacked PR gets no automatic CUJ run. It will run once [AIGTWY-4882] Add fresh-launch journeys and dedicated CUJ7 coverage #930 merges and this PR retargetsmain, or via a manualintegration.ymldispatch on this branch.This pull request and its description were written by Isaac.