[Post-v0.1/P2] Split coordination hotspots after contracts freeze #33
Labels
No labels
priority/P0
priority/P1
priority/P2
release/v0.1.0
status/blocked
status/planned
type/bug
type/design
type/test-gap
type/tracker
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
natsukium/felis#33
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follow-up from #12 (P2); start only after the public CLI/IPC choices settle.
Why
cli_bridge.rs,cli_sessions.rs, the connector, and client navigation are coordination hotspots. Refactoring them while contracts are still changing would obscure semantic breaks and make review harder.Scope
felis-client-coreseam.Acceptance criteria
felis-protocol.Triage plan (2026-09-03)
Source-grounded triage against
mainat69076d42, reviewed through seven rounds of an independent reviewer (pisol/luna) until it passed with no findings. The dependency order that supersedes the tracker's is posted on #12.Claim check
Accurate on the diagnosis; imprecise on where the files live.
crates/felis-cli/src/cli_sessions.rsis 2927 lines withrun/plandispatch at:488/:547, onecmd_*per verb (cmd_list :924,cmd_info :968,cmd_send :1048,cmd_kill :1431,cmd_tag :1454,cmd_evict :1511,cmd_switch :1590,cmd_retarget :1675,cmd_capture :2066,cmd_search :2265), and the shared frame driversdrain_frames :1782,drain_rehydrate :1907,drain_region_rows :1965,spawn_on :2211.crates/felis-cli/src/cli_bridge.rsis 2187 lines with admission (parse_request :405,Params :460), the session/stream ownership tables (Core :622,SessionSlot :638,StreamSlot :571,ActiveOp :556), stream registration (Registry :1436,Link :1421,StreamHandle :1499), and the pump (pump :1894,dial :1910,drain_rehydrate :1924) in one file. Note both are in felis-cli, not felis-client-core; the issue's phrasing ("the connector") correctly placescrates/felis-client-core/src/connector.rs(2337 lines: dial/offer inconnect :210,connect_carrier :450,AttachIntent :500, the request methods:903-996, plusDaemonStatus :683). Client navigation is spread acrosscrates/felis-client/src/event_handler.rs(1205),app_methods.rs(1876),switch_intent.rs, andfelis-client-core/src/action.rs+keymap/map.rs.crates/felis-cli/tests/cli_sessions.rs(2498 lines) andcrates/felis-cli/tests/cli_bridge.rs(1048 lines), plus the felis-daemonhead_of_line_rehydrate.rs/real_app_harness.rsconcurrency harnesses.spawn_on, connectorcreate_with/attach), #21 (bridgeOut/Corebounds), #22 (connector/dial reconnect), #23 (cli_output/cli_sessionsmachine contract), #24 (cmd_retarget/run_retarget, connectorretarget_window), #46 (the shared driver throughdrain_frames/pump), #47/#48 (frame taxonomy and correlation, which change what the drivers match on).Verdict
defer (keep post-v0.1.0, P2). Deferral does not get more expensive because of the freeze — the opposite: #12's "Contract freeze boundary" explicitly does not freeze "unpublished Rust APIs, private module structure, or every crate's current
pubvisibility", so this refactor is free after the tag by construction, and every P1 above would have to be re-based over it if it landed first.One scope adjustment: #46 ("extend the shared driver through application phases") is the first slice of this refactor and lands pre-freeze. After #46, re-survey before starting — the driver extraction may have already removed the biggest duplicated block between
cli_sessions.rsandcli_bridge.rs(drain_rehydrateexists in both files today,:1907and:1924).Approach
Pure-move commits first, behavior-preserving, one hotspot per commit so
git diff --color-movedreviews as moves:felis-cli/src/cli_sessions.rs→cli_sessions/:mod.rskeepsrun,plan, theReporterselection (point_out/stream_out :718-724), and id resolution (resolve_roster_id :96);read.rs(cmd_list,cmd_info,cmd_capture,cmd_search,print_*);mutate.rs(cmd_send+wait_for_command_end,cmd_kill,cmd_evict,cmd_tag,spawn_on/spawn_args_for);attachment.rs(cmd_switch,cmd_retarget,run_retarget/staged_retarget, the switch-denial reporting). The frame drivers move to whatever module #46 produced (or adriver.rsshared with the bridge if #46 did not).cli_bridge.rs→cli_bridge/:admission.rs(parse_request,Params,check_scope_minor,is_streaming_op— the last one should become a table shared with the CLI classification per #35),envelope.rs(Envelope,Body,error_object, terminal objects),registry.rs(Registry,Link,StreamHandle,pump),core.rs(Core,SessionSlot,StreamSlot,ActiveOp,settle) — the one serialized session owner the issue's scope keeps.felis-client-core/src/connector.rs: split the dial/offer/handshake (connect,connect_carrier,Offer,Carrier*,RemoteSpawn) from theConnectionrequest methods andDaemonStatus; rehydration already lives inpull.rs/roster.rs/shadow.rs, so the connector should shrink to dial + typed requests.event_handler.rs/app_methods.rsaround the existingswitch_intent.rsseam; anything headless (intent resolution, denial mapping) goes to felis-client-core, anything winit-facing stays.felis-protocol/Cargo.tomlunchanged (no tokio/OS dep — the acceptance criterion is mechanical:cargo tree -p felis-protocolshows no tokio); dependency direction inCLAUDE.md"Project shape" unchanged.docs/reference/workspace.md(layout) anddocs/explanation/implementation.mdif they name the files; skillsextend-ipcstep 4 namescli_sessions/cli_bridgeby file — update paths in the same change (chore(skills):).just snapshot-*must show zero churn; runjust check.Dependencies
Land after #20, #21, #22, #23, #24, #46 (and the #47/#48 shape decisions they build on) — all v0.1.0 P1. #35's classification table is a good thing to introduce in the bridge/CLI split (one shared table instead of
is_streaming_op :387and thecli.mdtable diverging). #12's order still holds; this sits after #31.Risk/effort
M–L (M per hotspot, four hotspots). Main risk: a semantic change hidden inside a large move. Mitigation is procedural — move-only commits, then behavior commits, never mixed — which is precisely why the issue waits for the contracts to stop moving.
Labels
Keep
priority/P2, post-v0.1.0. Consider adding atype/refactorlabel if one exists, and a note that #46 is the first slice.