Skip to content

Choose the Harness, Model and Effort on the command line and in the User config (#392) - #402

Merged
JacobStephens2 merged 3 commits into
issue-136from
issue-392
Oct 5, 2026
Merged

JacobStephens2 merged 3 commits into
issue-136from
issue-392

Conversation

@JacobStephens2

Copy link
Copy Markdown
Owner

Summary

Each of the three is chosen by the command first, then the User config, then the default:

Choice::of(flags, [harness] section)
  harness = flag ?? harness.default ?? claude
  model   = flag ?? [harness.<chosen>].model   ?? none (Harness's own)
  effort  = flag ?? [harness.<chosen>].effort  ?? none
 main
   command::start            # User config loaded
+  Flags::harness(config)    # one Choice per Command
   run / architect / pickup
     LaunchDirectory::open_for_run      # Origin match
+    Choice::check                      # CLI on PATH, codex "not supported yet",
+                                       # test call `claude -p --model M [--effort E]` if a Model is named
     logs::started
+      "sessions run on claude · opus · high"   (Command log + Activity log start line)
     Delivery
-      Sessions::within(logs, worktree)
+      Sessions::within(logs, worktree, harness)   # --model/--effort on every session, Repair and Resume
+      write "Built with claude · opus · high" in the PR body (Spec PR too), warning on failure
       child_run::start(issue, kind, base_fix
+                       , harness)                # --sessions-harness/-model/-effort hidden args
  • harness <name>, model <name>, effort <level> (with or without dashes) on a Run, an Architect run and a Pickup run. They are rejected with --plan-only, when repeated, or when given without a value.
  • [harness], [harness.claude] and [harness.codex] are parsed into harness::Settings. Unknown keys and wrong types are User config errors.
  • Checks run only for a Run started by hand, or in a Pass once it has decided not to skip. A Spec run's Tickets, a Base fix and a dispatched run never repeat them.
  • The Run notification gains the same Built with … line.
  • Setup is untouched; that's Setup asks for the Harness, Model and Effort #393.

Evidence

  • Before: thirdshift <url> model opus → not a GitHub issue URL: model; every session runs claude -p --permission-mode auto … with no --model.
  • After: the new tests/harness_choice.rs and new tests in spec_run, pickup_run, architect_run and base_fix pass. They cover:
    no flag, no config         → sessions have no --model/--effort, no test call
    model X effort Y           → one test call ["-p","--model",X,"--effort",Y] "Reply with OK.", every session gets them
    harness claude, codex default → [harness.claude] used
    model Claude refuses       → exit 1, no Claim, no worktree, no Command log
    claude not on PATH         → "claude is not on PATH … chosen by …"
    harness codex              → "harness codex, chosen by …, is not supported yet"
    Spec run                   → one test call; #21, #22 and the Spec review on the Model
    skipped Pickup/Architect   → no claude call at all
    Base fix                   → its session on the Run's Model and Effort
    Command log, Activity log, PR body, notification → name claude · X · Y
    
  • The full suite passes except two failures already on issue-136. The Factory skills were updated in a2afa36 without regenerating them: prompts_page_shows_what_the_binary_sends (stale site/prompts) and loads_every_factory_skill_as_the_thirdshift_plugin (missing resolving-merge-conflicts). Neither involves this change.

Merge Danger

Door: two-way

With no flag and no [harness], sessions run exactly as before. The new visible output is:

  • a sessions run on … line in the Command log;
  • , on claude · default model · default effort at the end of the Activity log start line;
  • one Built with … line, with a hidden marker, appended to each pull request body.

Blast Radius: moderate

Anything that parses the Activity log start line, or a PR body exactly, sees the new text. A Run with a named Model makes one extra small Claude call before work.

Unaddressed findings

Standards

  • Choice::check does I/O inside a value type (testability). It is covered end to end by the fake claude on PATH, which is the seam the spec names. Injecting a runner adds a seam no test needs.
  • Flags::harness and Started::built_with are middle men. They mirror the existing Flags::notification and Started::took, keeping one way to resolve and record an ask.
  • The same model/effort shape is duplicated in the retry command, hidden args and Claude args. Each produces a different syntax (public flags, hidden flags, claude flags), so a shared helper would need its own mapping table.
  • Choice flattens model/effort instead of holding ModelAndEffort; Reader keeps them separate. Flat fields read more simply at every use (choice.model). It is cosmetic.
  • Naming. The harness: Choice parameters lead to self.harness.harness, and built_with is both a getter and a setter. The parameter name matches the domain term (the Harness choice). Renaming every site is churn without clearer meaning. I renamed the unclear local sessions_on.
  • Shotgun surgery from threading &Choice through ~12 signatures. This is explicit by design. The alternative is process-wide state, and the spec requires the choice to reach every session and child Run.
  • The --plan-only flag list is repeated in the message, docs and tests. That matches how the existing list was already spelled out.
  • The round-trip test pairs kinds with harnesses through zip/cycle. It is a test idiom only.

Spec

  • The test call has no timeout. The spec asks for none. A hung claude would equally hang the session that follows.
  • A child Run records ChosenBy::Command even when the User config chose. It is never shown, because child Runs make no checks. It is documented at the field.
  • Scope creep: the Base fix retry command repeats harness/model/effort. Kept, so the retried Run asks for what the original asked.

Closes #392

🤖 Generated with Claude Code

JacobStephens2 and others added 3 commits October 5, 2026 00:19
…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>
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.

1 participant