Skip to content

Choose the Harness, Model and Effort a Command runs on (Claude Code or Codex) - #401

Merged
JacobStephens2 merged 23 commits into
mainfrom
issue-136
Oct 5, 2026
Merged

JacobStephens2 merged 23 commits into
mainfrom
issue-136

Conversation

@JacobStephens2

@JacobStephens2 JacobStephens2 commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

Summary

A Command's sessions run on a Harness (claude or codex), with a Model and an Effort, chosen on the command line, then the User config, then the default (claude, and the Harness's own Model and Effort).

thirdshift <issue-url> harness codex model GPT-6.1-Sol effort Max
  Choice::of(command, User config)          # command > [harness.<name>] > default
  check before work                         # before the Claim, worktree, any log
    CLI on PATH
    codex: match against `codex debug models` (case-insensitive, display name → slug)
    claude: test call, only when a Model is named
  Spec run / Pass: check once, after deciding not to skip
  every session (implement, Repair, Resume, Spec review, Architecture review,
                 Ticket Runs, Base fix) → same Choice via child-Run args
  record: Command log, Activity log, PR body "Built with …", Run notification
[harness]           default = "claude" | "codex"
[harness.claude]    model, effort     # blank: Claude Code's own default
[harness.codex]     model, effort

The Factory skills stop being a Claude plugin (ADR 0012):

-skills/<skill>/            loaded with claude --plugin-dir, as /thirdshift:<skill>
+skills/thirdshift-<skill>/ linked into the worktree, kept out of git by .git/info/exclude
+  claude → .claude/skills/   prompt's first line: /thirdshift-<skill>
+  codex  → .agents/skills/   prompt's first line: $thirdshift-<skill>

A Codex session runs codex exec --json --dangerously-bypass-approvals-and-sandbox with stdin null, -m / model_reasoning_effort, and the CLAUDE.md fallback. Its stream gives the progress lines, Session log, thread id and final message. A Resume runs codex exec resume <thread> with every flag again. A command or sub-agent call left running gets one Resume, turn.failed fails the Run with Codex's error, and an interrupt sends SIGINT before SIGTERM.

Setup asks for the Harness. Both are listed, and one that isn't installed is marked and refused. The default answer is the configured Harness if it's installed, otherwise the installed one, so claude when both are. Setup then asks the Model and Effort for that Harness only. For Codex it lists them from Codex's catalog, and it checks each answer the way a Run does.

Review clean-ups in the last commit:

  • The headless and Resume lines no longer name Claude's Bash timeout or TaskStop tool unconditionally.
  • Re-running Setup keeps a configured codex as the default answer.

Evidence

  • Before: tests/setup.rs on_a_terminal_rerunning_setup_defaults_to_the_harness_already_configured: a config with default = "codex" still offered [claude]. tests/codex_sessions.rs assert_sessions_on_codex failed because a Codex prompt said "raising the Bash timeout".
    After: both pass, and the full cargo test and cargo clippy --all-targets pass.
  • New suites: tests/harness_choice.rs (flags, fallback, checks before work, recording), tests/codex_sessions.rs (Codex sessions end to end), Setup's Harness scenarios in tests/setup.rs, plus additions to the Spec run, Pickup run, Architect run and Base fix suites.

Merge Danger

Door: two-way

The skill rename changes how every session loads its skills. Claude sessions no longer get --plugin-dir and instead find thirdshift-* skills in the worktree's .claude/skills/. The .git/info/exclude entries stay in each target repository.

Blast Radius: every-session

A user with no Harness settings keeps running on Claude Code with no extra calls. A repository with its own .claude/skills/ or .agents/skills/ gains thirdshift-* links beside its own skills. Codex sessions run unsandboxed, as ADR 0012 records.

Unaddressed findings

Standards

  • Possible Data Clumps (Choice repeats ModelAndEffort's fields; --sessions-harness/-model/-effort are three loose options). Skipped: folding them is a wide refactor across the session seam for no change in behaviour. Better as its own clean-up.
  • Possible Repeated Switches (match harness in harness.rs, session.rs, progress.rs, skills.rs, questions.rs). Skipped: with two Harnesses and Harness-specific choices, a per-Harness adapter trait is a larger redesign than this Spec needs.
  • Possible Mysterious Name (harness.harness, the two claude_args/codex_args, Choice::test_call). Skipped: renaming across the seam is churn with no behaviour change, and the doc comments state each one's role.
  • Possible Feature Envy (CLI arguments built partly on Choice, partly in session.rs). Skipped for the same reason as the Repeated Switches finding.
  • Duplicated Harness::named in config.rs. Skipped: it's a match guard, which can't bind the Harness it finds.
  • Duplicated filter in Catalog::model / Catalog::listed. Skipped: they're small and answer different questions.
  • Stream::failed/error defaults that only Codex overrides. Skipped: the reviewer judged them acceptable.

Spec

  • Setup skips the Harness question when neither CLI is installed, or when Codex's catalog can't be read. Skipped: saving a Harness that can't run, or an unchecked Model, would break "Setup never saves a value a Run would reject".
  • - clears a Model or Effort in Setup, and blank keeps the current value (scope creep). Skipped: on re-run, blank keeping the current value is how every Setup question behaves (user story 28). Without -, there would be no way back to the Harness's default.
  • The new thirdshift-resolving-merge-conflicts skill (scope creep). Skipped: the conflict-repair prompt already loaded that skill, which didn't exist, so the rename to thirdshift- names needed it.
  • The longer thirdshift help section on the Harness (scope creep). Skipped: it documents the new flags, which users need.
  • "Built with …" on a Run notification when the check failed. Skipped: the line names the Harness, Model and Effort the Command was given. A failed check reports the setting it rejected, which is what the reader needs.

Closes #136

Tickets

🤖 Generated with Claude Code

JacobStephens2 and others added 23 commits October 5, 2026 00:06
The Factory skills stop being a Claude plugin. Each is renamed
thirdshift-<skill> in skills/, and names the others in plain prose.
thirdshift writes them out once per Command and links each into the
worktree's .claude/skills/, kept out of git by a /.claude/skills/thirdshift-*
entry in .git/info/exclude, added once. No session gets --plugin-dir, and
each prompt's first line is /thirdshift-<skill>.

Restores resolving-merge-conflicts, dropped from skills/ by a skills
update though the conflict Repair prompts still invoke it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ory skills (#391)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Load the Factory skills from the worktree as thirdshift-<skill>, replacing the Claude plugin
…ser config (#392)

harness <name>, model <name> and effort <level> on a Run, an Architect run
(not with --plan-only) and a Pickup run, falling back to the User config's
[harness] section, then to claude with its own Model and Effort. The choice
reaches every session and child Run, is checked before any work (CLI on
PATH, a test call for a named Claude Model, codex not supported yet), and is
recorded in the Command log, the Activity log, the PR body and the Run
notification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Read [harness.<name>] through Harness::named and Settings::of_mut, keep a
User config's Model and Effort as written, move the PR body's Built with line
next to the Delivery that writes it, and rewrap doc comments.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sessions now find the Factory skills linked into the worktree (#391)
instead of loading a plugin, and still run on the Command's Harness
choice (#392): claude_args takes the harness, resume and prompt, with
no --plugin-dir.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Choose the Harness, Model and Effort on the command line and in the User config (#392)
Setup's first questions choose the Harness, listing both and refusing one
sessions can't run on here, then the Model and Effort for it, a Claude
Model checked with the test call a Run makes. The User config gains
[harness], [harness.claude] and [harness.codex] with every key, and
completing an existing one now recurses into subsections.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
harness codex runs every session as codex exec --json, unsandboxed, with
stdin null, the Model and Effort as Codex names them and the CLAUDE.md
fallback. The Factory skills are linked into .agents/skills/, and each
prompt loads its skill as $thirdshift-<skill>. Codex's JSONL stream gives
the progress lines, session id, final message and failures. The Model and
Effort are checked against codex debug models before any work, replacing
the not-supported-yet refusal. The fake gains a codex personality.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Harness question defaults to the first Harness sessions can run on,
claude when both can, as the issue says, rather than the User config's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Setup asks for the Harness, Model and Effort (#393)
Name the Claude stream ClaudeProgress, settle a Codex Model and Effort
into a ModelAndEffort, give the token totals their own type, and cover a
Merge run, a bare non-zero exit and the prompts' sigil on Codex.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Setup's Harness question (#393) refuses Codex as not supported yet
through Harness::unavailable, and its Model check uses test_call. A
Run's check now runs Codex sessions, so it checks only that the CLI is
on PATH, then makes Claude's test call or settles Codex's names from its
catalog. Setup still refuses Codex until #396 turns it on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Run a Command's sessions on Codex
…em with SIGINT first (#395)

A Codex sub-agent call still running at turn end is now killed background
work, as a command is, so its session gets the one Resume. An interrupt
sends a Codex session SIGINT, the only signal Codex stops cleanly on,
before SIGTERM and SIGKILL. Tests cover the Resume on Codex ending the
same way, counting against no Repair cap, and the interrupt order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With codex on PATH, Setup accepts it as the Harness, and it's the default
answer when it's the only one installed. For Codex, Setup lists the Models
codex debug models offers, by slug and display name, then the Efforts the
chosen Model supports. Each answer is matched as a Run matches it and
written as Codex names it; one the catalog doesn't have is asked again,
with the valid choices.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lled-work tracking (#395)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resume and interrupt Codex sessions (#395)
When codex debug models fails, Setup says so and leaves the harness
settings as they are, rather than asking the Harness again, which with
only codex installed could never end. The catalog's errors no longer
speak of checking, as Setup reads it to list the choices, and locals in
ask_harness and Catalog::efforts get names that say what they hold.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tup keeps the configured Harness

The headless and Resume lines no longer name Claude's Bash timeout or
TaskStop tool unconditionally, since Codex sessions get them too. Re-running
Setup offers the Harness already in the User config as the default answer,
when it's installed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JacobStephens2
JacobStephens2 marked this pull request as ready for review October 5, 2026 06:22
@JacobStephens2
JacobStephens2 merged commit 56476cc into main Oct 5, 2026
13 checks passed
@JacobStephens2
JacobStephens2 deleted the issue-136 branch October 5, 2026 06:29
@JacobStephens2 JacobStephens2 mentioned this pull request Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Choose the Harness, Model and Effort a Command runs on (Claude Code or Codex)

1 participant