From 8755b0cf6ac6eff8b4127f20ba3bed160cb941a8 Mon Sep 17 00:00:00 2001 From: rub-a-dub-dub Date: Sat, 26 Sep 2026 15:56:48 -0700 Subject: [PATCH 1/2] fix(bin): keep Codex workers on standard tier --- .../references/harness/codex.md | 1 + bin/fm-spawn.sh | 8 +++-- tests/fm-control-relaunch.test.sh | 2 ++ tests/fm-secondmate-harness.test.sh | 2 +- tests/fm-spawn-dispatch-profile.test.sh | 32 +++++++++++++++---- 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/.agents/skills/harness-adapters/references/harness/codex.md b/.agents/skills/harness-adapters/references/harness/codex.md index 368afadddf9..ae9eb077799 100644 --- a/.agents/skills/harness-adapters/references/harness/codex.md +++ b/.agents/skills/harness-adapters/references/harness/codex.md @@ -13,6 +13,7 @@ Verified on 2026-06-11 with codex-cli 0.139.0 unless a fact gives a newer versio | Resume | `codex resume `, using the id printed on quit. | | Model flag | `--model `. | | Effort flag | `-c 'model_reasoning_effort=""'`, verified on codex-cli 0.142.1 whose installed schema contains `model_reasoning_effort`, active config uses it, and bundled catalog advertises only these four values while omitting `max`. | +| Service tier | `-c 'service_tier="default"'`, verified on codex-cli 0.154.0 whose strict config read resolves it from session flags over a user-level `priority` value, while the bundled catalog names `priority` as `Fast` and leaves the default service tier unset. | | Model discovery | Open the current interactive session's `/model` picker. | | Marker | None; identity comes from ancestry, and `../../../bin/fm-harness.sh` is what keeps a retained foreign `CLAUDECODE` from renaming it. Verified on 2026-09-01 with codex-cli 0.152.0: the pane process is the `node` npm shim and the native `codex` binary runs as its foreground child, so a tool subprocess reaches the native name directly while the shim itself is identified from its script path. | diff --git a/bin/fm-spawn.sh b/bin/fm-spawn.sh index c24d72591c5..3f7a6d0b693 100755 --- a/bin/fm-spawn.sh +++ b/bin/fm-spawn.sh @@ -268,6 +268,10 @@ # worktree, or record exists and names the accepted values. The file is read # on every spawn and relaunch, so a change reaches the next launch without a # restart, and it is inherited into secondmate homes (bin/fm-config-inherit-lib.sh). +# Codex worker service tier: +# Every codex launch (ship, scout, secondmate, and relaunch) carries +# `-c 'service_tier="default"'`, which overrides a user's priority tier for +# this process only and leaves user-level Codex configuration unchanged. # Launch templates live in launch_template() below; placeholders replaced before launch: # __BRIEF__ absolute path to data//brief.md # __CLAUDEPERMFLAG__ the claude permission flag selected by config/claude-permission-mode @@ -1603,9 +1607,9 @@ launch_template() { claude) printf '%s' 'CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false CLAUDE_CODE_SEND_FEEDBACK=0 claude __CLAUDEPERMFLAG__ --settings '\''{"feedbackDrafts":"off","attribution":{"commit":"","pr":"","sessionUrl":false}}'\'' __MODELFLAG____EFFORTFLAG__"$(__OPINPUT__ encode launch-brief < __BRIEF__)"' ;; codex) if [ "$kind" = secondmate ]; then - printf '%s' 'codex __MODELFLAG____EFFORTFLAG__--dangerously-bypass-approvals-and-sandbox "$(__OPINPUT__ encode launch-brief < __BRIEF__)"' + printf '%s' 'codex __MODELFLAG____EFFORTFLAG__-c '\''service_tier="default"'\'' --dangerously-bypass-approvals-and-sandbox "$(__OPINPUT__ encode launch-brief < __BRIEF__)"' else - printf '%s' 'codex __MODELFLAG____EFFORTFLAG__--dangerously-bypass-approvals-and-sandbox -c "notify=[\"bash\",\"-c\",\"touch __TURNEND__\"]" "$(__OPINPUT__ encode launch-brief < __BRIEF__)"' + printf '%s' 'codex __MODELFLAG____EFFORTFLAG__-c '\''service_tier="default"'\'' --dangerously-bypass-approvals-and-sandbox -c "notify=[\"bash\",\"-c\",\"touch __TURNEND__\"]" "$(__OPINPUT__ encode launch-brief < __BRIEF__)"' fi ;; opencode) printf '%s' 'OPENCODE_CONFIG_CONTENT='\''{"permission":{"*":"allow"}}'\'' opencode __MODELFLAG__--prompt "$(__OPINPUT__ encode launch-brief < __BRIEF__)"' ;; diff --git a/tests/fm-control-relaunch.test.sh b/tests/fm-control-relaunch.test.sh index 08ef8ade65a..e324102809e 100755 --- a/tests/fm-control-relaunch.test.sh +++ b/tests/fm-control-relaunch.test.sh @@ -927,6 +927,8 @@ test_harness_switch_moves_the_record_and_clears_prior_wiring() { [ ! -e "$dir/wt/.claude/settings.local.json" ] \ || fail "the previous harness's per-task wiring must be cleared on a switch" assert_grep "codex" "$dir/fake/literal" "the replacement launch should be the new harness" + assert_grep "-c 'service_tier=\"default\"'" "$dir/fake/literal" \ + "a relaunch onto codex should carry the standard service-tier override" [ "$(journal_field "$dir" rl4 from_harness)" = claude ] || fail "the journal should record the origin harness" [ "$(journal_field "$dir" rl4 to_harness)" = codex ] || fail "the journal should record the target harness" pass "fm-control relaunch: switching harness is one ordinary relaunch, and the old wiring goes with the old agent" diff --git a/tests/fm-secondmate-harness.test.sh b/tests/fm-secondmate-harness.test.sh index f4d9546e0b4..80d89589e46 100755 --- a/tests/fm-secondmate-harness.test.sh +++ b/tests/fm-secondmate-harness.test.sh @@ -877,7 +877,7 @@ test_spawn_explicit_harness_does_not_inherit_secondmate_harness_tokens() { [ "$(meta_field "$meta" model)" = default ] || fail "explicit-harness-no-tokens: meta model should stay default" [ "$(meta_field "$meta" effort)" = default ] || fail "explicit-harness-no-tokens: meta effort should stay default" launch=$(cat "$launchlog") - assert_contains "$launch" "codex --dangerously-bypass-approvals-and-sandbox" \ + assert_contains "$launch" "codex -c 'service_tier=\"default\"' --dangerously-bypass-approvals-and-sandbox" \ "explicit-harness-no-tokens: launch did not use codex" assert_not_contains "$launch" "--model" "explicit-harness-no-tokens: launch must not carry a --model flag" assert_not_contains "$launch" "model_reasoning_effort" \ diff --git a/tests/fm-spawn-dispatch-profile.test.sh b/tests/fm-spawn-dispatch-profile.test.sh index 188e6890bf3..026fe4e9308 100755 --- a/tests/fm-spawn-dispatch-profile.test.sh +++ b/tests/fm-spawn-dispatch-profile.test.sh @@ -345,7 +345,7 @@ test_active_dispatch_profile_allows_explicit_harness() { assert_contains "$out" "spawned $id harness=codex" "spawn did not report explicit codex harness" assert_meta_profile "$HOME_DIR/state/$id.meta" codex gpt-5 high launch=$(cat "$LAUNCH_LOG") - assert_contains "$launch" "codex --model 'gpt-5' -c 'model_reasoning_effort=\"high\"' --dangerously-bypass-approvals-and-sandbox" \ + assert_contains "$launch" "codex --model 'gpt-5' -c 'model_reasoning_effort=\"high\"' -c 'service_tier=\"default\"' --dangerously-bypass-approvals-and-sandbox" \ "explicit harness launch did not thread model and effort" pass "active crew-dispatch profile allows an explicit resolved harness" } @@ -397,6 +397,7 @@ test_claude_threads_model_and_effort() { launch=$(cat "$LAUNCH_LOG") assert_contains "$launch" "claude --dangerously-skip-permissions --settings '{\"feedbackDrafts\":\"off\",\"attribution\":{\"commit\":\"\",\"pr\":\"\",\"sessionUrl\":false}}' --model 'sonnet' --effort 'high'" \ "claude launch did not thread model and effort flags" + assert_not_contains "$launch" "service_tier" "claude launch must not receive the codex service-tier override" assert_not_contains "$launch" "--tui-mode" "non-Pi launches must not receive Pi's TUI mode override" pass "claude receives --model and --effort profile flags" } @@ -412,9 +413,24 @@ test_codex_threads_model_and_effort() { expect_code 0 "$status" "codex spawn with profile flags should succeed" assert_meta_profile "$HOME_DIR/state/$id.meta" codex gpt-5 high launch=$(cat "$LAUNCH_LOG") - assert_contains "$launch" "codex --model 'gpt-5' -c 'model_reasoning_effort=\"high\"' --dangerously-bypass-approvals-and-sandbox" \ - "codex launch did not thread model and reasoning effort config" - pass "codex receives --model and model_reasoning_effort profile flags" + assert_contains "$launch" "codex --model 'gpt-5' -c 'model_reasoning_effort=\"high\"' -c 'service_tier=\"default\"' --dangerously-bypass-approvals-and-sandbox" \ + "codex launch did not thread model, reasoning effort, and standard service-tier config" + pass "codex receives model, reasoning-effort, and standard service-tier flags" +} + +test_codex_scout_uses_standard_service_tier() { + local rec id out status launch + id=profile-codex-scout-z24 + rec=$(make_spawn_case profile-codex-scout codex "$id") + read_case_record "$rec" + + out=$(run_spawn "$HOME_DIR" "$WT_DIR" "$FAKEBIN_DIR" "$LAUNCH_LOG" "$id" "$PROJ_DIR" --scout) + status=$? + expect_code 0 "$status" "codex scout spawn should succeed" + launch=$(cat "$LAUNCH_LOG") + assert_contains "$launch" "codex -c 'service_tier=\"default\"' --dangerously-bypass-approvals-and-sandbox" \ + "codex scout launch did not carry the standard service-tier override" + pass "codex scouts use the standard service tier" } test_codex_omits_invalid_max_effort() { @@ -428,7 +444,7 @@ test_codex_omits_invalid_max_effort() { expect_code 0 "$status" "codex spawn with unsupported max effort should omit the effort flag" assert_meta_profile "$HOME_DIR/state/$id.meta" codex gpt-5 max launch=$(cat "$LAUNCH_LOG") - assert_contains "$launch" "codex --model 'gpt-5' --dangerously-bypass-approvals-and-sandbox" \ + assert_contains "$launch" "codex --model 'gpt-5' -c 'service_tier=\"default\"' --dangerously-bypass-approvals-and-sandbox" \ "codex launch did not preserve the model flag when max effort was omitted" assert_not_contains "$launch" "model_reasoning_effort" "codex launch must omit unsupported max reasoning effort" pass "codex omits unsupported max effort instead of passing a bad config value" @@ -901,7 +917,7 @@ test_claude_secondmate_launch_carries_the_attribution_policy() { } test_active_dispatch_profile_does_not_block_secondmate_launch() { - local rec id sm out status + local rec id sm out status launch id=profile-secondmate-z16 rec=$(make_spawn_case profile-secondmate codex "$id") read_case_record "$rec" @@ -915,6 +931,9 @@ test_active_dispatch_profile_does_not_block_secondmate_launch() { assert_contains "$out" "spawned $id harness=codex kind=secondmate" "secondmate launch did not use secondmate harness resolution" assert_grep "kind=secondmate" "$HOME_DIR/state/$id.meta" "secondmate meta missing kind=secondmate" assert_meta_profile "$HOME_DIR/state/$id.meta" codex default default + launch=$(cat "$LAUNCH_LOG") + assert_contains "$launch" "codex -c 'service_tier=\"default\"' --dangerously-bypass-approvals-and-sandbox" \ + "codex secondmate launch did not carry the standard service-tier override" pass "active crew-dispatch profile does not block secondmate launches" } @@ -1310,6 +1329,7 @@ test_active_dispatch_profile_allows_positional_harness test_active_dispatch_profile_allows_raw_launch_command test_claude_threads_model_and_effort test_codex_threads_model_and_effort +test_codex_scout_uses_standard_service_tier test_codex_omits_invalid_max_effort test_grok_threads_model_and_reasoning_effort test_grok_omits_invalid_max_reasoning_effort From 128d2cdce4204ad026cb3118a3ace8eb8fa624a2 Mon Sep 17 00:00:00 2001 From: rub-a-dub-dub Date: Sat, 26 Sep 2026 16:31:40 -0700 Subject: [PATCH 2/2] no-mistakes(document): document Codex worker standard-tier rationale in spawn launch contract --- bin/fm-spawn.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/fm-spawn.sh b/bin/fm-spawn.sh index 3f7a6d0b693..09ea9162e5b 100755 --- a/bin/fm-spawn.sh +++ b/bin/fm-spawn.sh @@ -272,7 +272,11 @@ # Every codex launch (ship, scout, secondmate, and relaunch) carries # `-c 'service_tier="default"'`, which overrides a user's priority tier for # this process only and leaves user-level Codex configuration unchanged. -# Launch templates live in launch_template() below; placeholders replaced before launch: +# A worker runs unattended with nobody waiting on its tokens, so priority +# speed buys nothing while spending the captain's allowance faster; the +# captain's own interactive Codex sessions keep whichever tier their config +# selects. Model and effort remain the profile's axes and are untouched here. +# Launch templates live in launch_template() below; placeholders replaced before launch: # __BRIEF__ absolute path to data//brief.md # __CLAUDEPERMFLAG__ the claude permission flag selected by config/claude-permission-mode # __PIBIN__ quoted concrete Pi-family executable path resolved from PATH