Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 <session-id>`, using the id printed on quit. |
| Model flag | `--model <model>`. |
| Effort flag | `-c 'model_reasoning_effort="<low\|medium\|high\|xhigh>"'`, 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. |

Expand Down
14 changes: 11 additions & 3 deletions bin/fm-spawn.sh
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,15 @@
# 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).
# Launch templates live in launch_template() below; placeholders replaced before launch:
# 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.
# 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/<task-id>/brief.md
# __CLAUDEPERMFLAG__ the claude permission flag selected by config/claude-permission-mode
# __PIBIN__ quoted concrete Pi-family executable path resolved from PATH
Expand Down Expand Up @@ -1603,9 +1611,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__)"' ;;
Expand Down
2 changes: 2 additions & 0 deletions tests/fm-control-relaunch.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion tests/fm-secondmate-harness.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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" \
Expand Down
32 changes: 26 additions & 6 deletions tests/fm-spawn-dispatch-profile.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Expand Down Expand Up @@ -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"
}
Expand All @@ -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() {
Expand All @@ -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"
Expand Down Expand Up @@ -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"
Expand All @@ -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"
}

Expand Down Expand Up @@ -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
Expand Down
Loading