cli: reinstate felis ssh and drop the all-mirror switch forms #280

Merged
natsukium merged 4 commits from issue-277-felis-ssh into main 2026-09-14 02:36:43 +09:00
Owner

Closes #277.

felis ssh <dest> is the verb that re-points the window it runs in at the daemon reached over SSH: a subcommand
of its own with a required positional destination, so --ssh-arg is unconditional and the SSH destination has one
spelling. felis window retarget [<socket-path>] is the local-only form; no argument is the default local daemon,
the way back. felis --host <dest> stays the neighboring operation that opens a new window there, and the docs show
the two side by side.

Removed, as pre-release surface with no recorded consumer: sessions switch-all, sessions retarget-all, the
bridge sessions.switch parameter all, --to-host, --to-socket, and the wire arm SwitchScope.all. The
all-mirror forms were the pre-B-9 broadcast kept under a new name; the cross-carrier one did not even keep the
mirrors together on arrival (without --session every window lands on its own fresh session). An OpsSwitch
without a scope is now refused at decode rather than read as that broadcast, so every switch requires minor 2.
Intended pre-release wire break, acknowledged in crates/felis-protocol/proto/BREAKING.md; tag 3 is left free, and
the reservation rule is scoped to numbers a release baseline carries.

Nothing under docs/ or skills/ records the removals or carries a Revisit if for them; the why lives in the
commit bodies and the CHANGELOG.md [Unreleased] entry.

Verification: just check (3522 tests), just proto-compat (acknowledged break), just prose-check "origin/main...HEAD" (0 hits); every commit builds and passes the workspace suite on its own
(git rebase --exec). Three pi sol review rounds (two on the design, one on this diff); the last diff finding, the
fish host completer firing past the destination slot, is fixed with an executable complete -C regression test.

Closes #277. `felis ssh <dest>` is the verb that re-points the window it runs in at the daemon reached over SSH: a subcommand of its own with a required positional destination, so `--ssh-arg` is unconditional and the SSH destination has one spelling. `felis window retarget [<socket-path>]` is the local-only form; no argument is the default local daemon, the way back. `felis --host <dest>` stays the neighboring operation that opens a new window there, and the docs show the two side by side. Removed, as pre-release surface with no recorded consumer: `sessions switch-all`, `sessions retarget-all`, the bridge `sessions.switch` parameter `all`, `--to-host`, `--to-socket`, and the wire arm `SwitchScope.all`. The all-mirror forms were the pre-B-9 broadcast kept under a new name; the cross-carrier one did not even keep the mirrors together on arrival (without `--session` every window lands on its own fresh session). An `OpsSwitch` without a `scope` is now refused at decode rather than read as that broadcast, so every switch requires minor 2. Intended pre-release wire break, acknowledged in `crates/felis-protocol/proto/BREAKING.md`; tag 3 is left free, and the reservation rule is scoped to numbers a release baseline carries. Nothing under `docs/` or `skills/` records the removals or carries a *Revisit if* for them; the why lives in the commit bodies and the `CHANGELOG.md` `[Unreleased]` entry. Verification: `just check` (3522 tests), `just proto-compat` (acknowledged break), `just prose-check "origin/main...HEAD"` (0 hits); every commit builds and passes the workspace suite on its own (`git rebase --exec`). Three pi sol review rounds (two on the design, one on this diff); the last diff finding, the fish host completer firing past the destination slot, is fixed with an executable `complete -C` regression test.
`sessions switch-all`, `sessions retarget-all`, and the bridge's
`sessions.switch` parameter `all` are the same capability under three
spellings: move every window attached to a session at once. No consumer
or scenario was ever recorded for it, and the cross-carrier form does
not preserve what it claims to move — with a `Create` landing, each
window dials independently and lands on its own fresh session, so the
mirrors come apart on arrival. Principle 1, second Test: if no real
consumer needs it yet, the terminal does not implement it. A sweep over
several sessions is a loop over `window retarget --from <id>`.

The `NoInputOwner` diagnostics stop offering the removed forms as the
remedy and name `--attachment` alone.

Refs #277

Assisted-by: Claude Code
`SwitchScope.all` lost its producers with the `-all` verbs and the
bridge's `all` parameter, and a wire variant nothing can reach is not a
capability. The daemon's push path loses the arm that resolved a switch
to every window attachment with it.

Tag 3 is left free rather than reserved: no release baseline carries
it, and the `base:` acknowledgment an intended pre-release break needs
already says both sides are rebuilt together, so no peer survives to
send it. The written rule is scoped the same way, to the numbers a
baseline has carried.

An `OpsSwitch` that carries no scope is now malformed rather than read
as the all-mirror broadcast: absence must never initiate movement, and
reading it as `Default` would silently turn an unversioned request into
a one-window move. Every scope therefore requires minor 2, so the send
gate moves from the field's value to the `OpsSwitch` arm that carries
it.

Refs #277

Assisted-by: Claude Code
`felis ssh <dest>` is the SSH form of the retarget verb: "ssh
somewhere" is the phrase a user reaches for, and its everyday meaning
is "point this terminal at that host", not "open a new window there".
A subcommand of its own with a required positional destination is what
lets `--ssh-arg` be unconditional, which it could not be while the two
forms shared one parser and the destination was a flag.

With the SSH destination positional on its own verb, the local
destination becomes positional on `window retarget` and the `to-`
prefix has nothing left to disambiguate: the prefix existed only to
keep the verb's destination from reading as the root `--host` /
`--socket`. An absent destination still means the default local daemon,
the way home, spelled as the absence of a choice.

The two halves are one change: neither verb carries a destination the
other lost.

Refs #277

Assisted-by: Claude Code
docs: describe the retarget verbs as felis ssh and window retarget
Some checks failed
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
bench / Criterion regression gate (pull_request) Failing after 2m13s
darwin / detect relevant changes (pull_request) Successful in 3s
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m11s
pr / nix flake check (pull_request) Successful in 30s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 54s
pr / publish felis (x86_64-linux) (pull_request) Has been skipped
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 52s
pr / cargo build / clippy / test / deny (pull_request) Successful in 1m55s
pr / wire schema is compatible with the base (pull_request) Successful in 9s
windows / detect relevant changes (pull_request) Successful in 3s
windows / windows docs-only no-op (pull_request) Has been skipped
windows / cargo clippy (Windows cross) (pull_request) Successful in 14s
windows / cargo nextest (Windows) (pull_request) Successful in 3m50s
windows / frontend smoke (Windows) (pull_request) Successful in 1m27s
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been skipped
c692406112
The reference pages, the how-tos, the shipped skill, and the wire
comments that name a CLI spelling follow the surface: one destination
per verb, in its own positional slot, and `felis ssh devbox` beside
`felis --host devbox` wherever either appears, since one re-points this
window and the other opens a new one.

The `window` namespace section keeps its object-and-effect argument and
gains the reason the SSH form is spelled `felis ssh`; the CHANGELOG
carries what moved.

Refs #277

Assisted-by: Claude Code
natsukium deleted branch issue-277-felis-ssh 2026-09-14 02:36:43 +09:00
Sign in to join this conversation.
No description provided.