cli: record the frozen CLI and bridge surfaces, and close the gaps the audit found #346
No reviewers
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
Due date
No due date set.
Dependencies
No dependencies set
Reference
natsukium/felis!346
Loading…
Reference in a new issue
No description provided.
Delete branch "issue-326-a"
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?
Part of #326: items 3, 4 and 5 of the final interface-freeze audit. Item 6 (the
AttachFailuresplit, plus item 4'sConnectErrorgolden and exhaustive match) is PR B, which rebases on this branch.Item 3 — the bridge is an explicitly smaller session-automation surface
The op set is closed to
sessions.*,notifications.subscribeandcancel. That is surface policy, not a limit of thewire, and it is now recorded as such; two things that were defects rather than policy are fixed.
docs/reference/cli.md"felis bridge": the closed op set, the three CLI-only verb groups (operator verbs, windowlaunches, shell plumbing) and how a bridge client reaches them, and the three ops that take less than their CLI verb
with their reasons —
sessions.send's requiredtextand absentkeys/wait(additive withinv:1, filed as#344),
notifications.subscribewithoutonce/timeout, andsessions.switch's requiredfromand itsqueued == 0result.docs/explanation/architecture/control-surfaces.md: the rationale and the rejected complete mirror (process-lifecycleverbs behind a correlated stream, and a bridge twin for every operator verb).
skills/felis/SKILL.md: the CLI-only groups in the bridge bullet.crates/felis-cli/src/cli_bridge.rsop_send: the comment claiming a chord needs client-side keyboard modes isfalse (the daemon encodes
InputMsg::Keyagainst the modes it owns) and is replaced by the policy.op_spawnnow fillsSpawnArgs.env_basefor a local carrier (env_base::fill_for_carrier), ascli_sessions.rsdoes; a bridge-created child inherited the daemon's environment, against REQ-912a. Unit test: alocal spawn carries a captured base, a relay spawn none.
rows/colsparse at the wire'su32width instead ofu16, so a geometry past the REQ-605a bounds is thedaemon's
invalid_requeston both surfaces rather thanmalformed_requeston the bridge alone. The staleu16_optcomment (a terminal anchor failure
OpsMsg::Spawnno longer has) is gone,felis-bridge-v1.schema.jsonisregenerated, the live-bridge test covers a value above
u16::MAX, and the schema fixture moves toreq-rows-above-u32.Item 4 — one vocabulary, one error object, two transports: frozen
docs/reference/cli.md"Machine output": what is frozen for the epoch (the two format words and their class binding,the error object shape, the
kindspellings with their exit codes, the two transports) and the boundaries — framingbegins after a successful parse, a clap rejection stays human on stderr at exit
2, bridge shape failures arecorrelated whenever a valid
idwas recovered. The exit-code table'sfelis bridgerow gains the initialat_capacitydial refusal beside its own pipe failure.docs/explanation/architecture/control-surfaces.md"Frozen forv:1": why the transports follow from the processmodel, the rejected unification in both directions, and #23 / #29 / #145 cited once.
?whose error reachedmainon a machine-formatted verb now goes through the verb'sReporter—resolve_config_source(usage), the dial (daemon_unreachable),build_runtime(internal), theverb bodies (
internal), andsessions send ID -'s stdin read (input_failed). Oneverb_reporternow decidesclass and format for the whole invocation, which is also what makes
Cli::machine_output()coverCmd::Version.cli_sessions::planno longer returnsResultbecause nothing in it can escape unframed.crates/felis-cli/tests/cli_sessions.rs): one JSON error object on stderr, no stdout, exit2, foran unresolvable
--configunder--format jsonand forsessions send ID - --format jsonwith an unreadable stdin.Item 5 —
sessions sendstays one typed operationdocs/explanation/architecture/control-surfaces.md: the decision, the wait race that rejects a separatewaitverb,why a separate
keyverb has no race (and what keeps--keyonsend), and the rule that no new flag may depend onanother — anything else is a new verb.
docs/reference/cli.md"Verb details": the three constraints stated as the whole grammar, "at least one of TEXT /--key/--wait" included.crates/felis-cli/src/tests.rs: one parser table over all three constraints both ways (rejected baresend ID,--timeoutwithout--wait,--rawwithout TEXT; accepted key-only, wait-only,--wait --timeout N, TEXT with--raw).CHANGELOG.mdcarries the two bridge fixes and the framing fix.Gates
Run on this branch (macOS, worktree under
.claude/worktrees/):just fmt-check,just lint,just check-portable,just prose-check,just skill-check,just docs-links,just deny,just proto-compat,just proto-compat-test,just release-check-test: pass.just schema: no diff remains.cargo nextest run --workspace --all-features --no-fail-fast: 3407 passed, 5 failures, all pre-existing localenvironment failures from the socket path length in a deep worktree (verified against a clean tree):
cli_bridge a_lost_daemon_answers_pending_point_requests_with_error_replies,cli_bridge a_relative_spawn_cwd_is_resolved_from_the_bridge_process,cli_bridge::tests::a_daemon_write_failure_fails_and_clears_the_link(timeout),felis-daemon agent::tests::a_racing_teardown_never_strands_a_live_registration,felis-daemon serve::tests::a_peer_that_hangs_up_while_parked_gives_its_connection_back.just goldenwas not run (bridge fixtures pick up environment noise on this machine); no golden file needed a change.a53badd5ff81f5f613dc81f5f613dccbb992d4eacbb992d4eac037424102c03742410299be731feb99be731feb94b31a1e808d249a73f275a9cfc5bb75a9cfc5bb94b31a1e80