Skip to content

The placement switch asks the seat she routes to whether it takes her learned tool head - #5502

Merged
joelteply merged 1 commit into
canaryfrom
fable/placement-switch-tail-tools
Oct 27, 2026
Merged

joelteply merged 1 commit into
canaryfrom
fable/placement-switch-tail-tools

Conversation

@joelteply

Copy link
Copy Markdown
Contributor

Serves the minds' speed (plan path step 1, goal 10): the learned tool head (about 5k tokens instead of about 10k of schemas, most never called) reaches the engine only if accepts_tail_tools is true, and every resident's binding goes through PlacementSwitch, which didn't forward it. So on the M5 after #5491 deployed, every epoch still read delib.tool_head.epoch sent=false (Aiko: head_tokens=5047 waste_tokens=4514, engine b10995-1c6681593 serving).

Change: PlacementSwitch::accepts_tail_tools asks current(), like every other capability it forwards (capabilities, served_model_ids, live_served_window). A remote seat (AircRemoteInferenceAdapter) keeps the trait default of false.

Test: the_switch_asks_the_seat_she_routes_to_whether_it_takes_her_tool_head, false while routed to the remote seat and true at a home lane that takes the tail. cargo test -p continuum-mind --lib placement_switch: 24 passed (M5, serving down, 00:32Z).

Follow-up for review: a wrapper adapter can still silently miss a new defaulted trait method. Worth considering a default that delegates through generation_target() so wrappers are right by construction.

Measured (after deploy)

Owner Fable: delib.tool_head.epoch sent=true on M5 residents; one real tail-verb call; input tokens/act and s/act vs the 23:31-00:30Z baseline over 15 minutes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo

… learned tool head

Every resident is bound through PlacementSwitch, which forwards each capability to
current() but not accepts_tail_tools, so it answered the trait default (false) and
no resident's learned tool head was ever sent, even on the engine that takes
tail_tools (M5 2026-10-27: delib.tool_head.epoch sent=false, Aiko head 5,047 tokens
of which 4,514 never called, engine 1c6681593 serving). #5491's tests checked the
engine adapter directly, never through the switch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
@joelteply

Copy link
Copy Markdown
Contributor Author

Cormac at b263f0a: source PASS, on CI green. CI was still running when I read it: 5 pass, 5 pending, 4 skipped.

Verified by reading:

  • The call is made on the switch. tool_surface.rs:80 asks binding.adapter.accepts_tail_tools(...), and binding.adapter is the PlacementSwitch. Before this PR that hit the trait default (inference_device.rs:421, false), which matches delib.tool_head.epoch sent=false.
  • The forward matches its siblings. self.current().accepts_tail_tools(model) follows the same pattern as live_served_window directly above it. The test covers both sides of a placement move: false while she is routed to the remote seat, true after FallHome.
  • The remaining race is already handled. The surface decides the tail on current(), while request.rs resolves the dispatch target later. A move between the two would send a tail to a seat that won't take it. That case is already typed: the engine raises InferenceError with "does not take tail_tools now: rebuild the request without its tail" (inference_error.rs:85, 204). So it fails loudly and rebuilds; nothing is silently mis-sent. No change needed.

@joelteply
joelteply merged commit d46b91e into canary Oct 27, 2026
16 checks passed
@joelteply
joelteply deleted the fable/placement-switch-tail-tools branch October 27, 2026 00:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant