[v0.1/Proto Review] Decide whether to remove unobservable operation IDs before release #296
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#296
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?
Related: #24, #12
Why
The release-readiness review found that retarget operation IDs are currently exposed as a public protocol and CLI feature without a user-observable completion path.
OpsSwitched.operation_idis returned byswitchand retarget commands, but no CLI verb or bridge operation accepts the token for lookup, waiting, or cancellation. In the daemon,OperationLedger::lookuphas no production caller;OperationLedger::landonly updates bookkeeping whose result is used for a debug log. Carrier retargets cannot be resolved by the origin daemon by design.This leaves the release contract paying for
OperationId,OperationEcho, several minor-version gates, CLI schema fields, and a bounded ledger without providing a capability that a caller can act on. The reference documentation currently describespending,landed, andsupersededstates, but does not expose a way for users to observe them.Decision required before the first release
Choose one of these deliberately:
queuedas the honest result of a switch, remove the operation fields and ledger, and revisit completion tracking only when a real consumer needs it.The current partial implementation should not remain the unexamined final state.
Acceptance criteria
queuedremains the only switch completion claim.Evidence
crates/felis-protocol/proto/felis.proto:OperationId,OperationEcho, andOpsSwitched.operation_idcrates/felis-daemon/src/operations.rs: bounded ledger and test-only lookup coveragecrates/felis-daemon/src/serve.rs: landing result is only logged when it cannot be attributedcrates/felis-cli/src/cli_output.rs: operation ID is exposed in machine outputdocs/reference/ipc.md: documented operation states and minor-8 compatibility behaviorDecision (2026-09-19): remove operation ids from the v0.1 contract (option 1)
Correction to the premise
The current state is not "unexamined". #24's triage plan split the work deliberately: put the id on the wire in v0.1 because "a missing echo field means the verdict can never be attributed" after the tag, and land
--wait/OperationStatuspost-v0.1.docs/reference/ipc.md"Operation ids" says so plainly: "No message reads a record back." What this issue reopens is that deferral decision itself. Two things changed since #24: the follow-up issue its plan called for ("Move--waitandOperationStatusto a post-v0.1 follow-up issue") was never filed, and the consumer evidence #24 leaned on is gone (next section).Why remove rather than keep or complete
sessions info" after a switch) as partial evidence for the revisit trigger; the skill-scope cleanup (5bb91114, 2026-09-05) dropped that workflow, and the shippedskills/felis/SKILL.mdnow listssessions switch/ssh/window retargetunder "Surfaces this skill does not cover" because a headless agent has no window to move. There is no consumer, not even a polling one.OperationId/OperationEcholater is an additive minor. Its degradation for a peer that predates it (a client that echoes nothing leaves its targetpendinguntil eviction) is exactly what the current minor-8 row inipc.mddocuments and accepts. A later addition costs unattributable landings in a mixed-version fleet, and that specific cost is already on the books.operation_idrenders as<incarnation:016x>-<sequence>in CLI and bridge output (docs/reference/cli.md"switch"). Once tagged, that shape is contract. A field whose meaning arrives later cannot change shape when it does.SwitchScopeselects at most one attachment, so the per-target verdict vector and the reordered-landing attribution from #24 round 3 solve a shape that no longer exists.--waitverb) for a consumer that does not exist, on a release still blocked by #12 / #31.Scope of the removal
OperationId,OperationEcho,OpsSwitched.operation_id,PushReattach.operation,PushRetargetHost.operation,SessionAttach.operation. Leave the tags free, not reserved (no release baseline carries them), and add abase:entry tocrates/felis-protocol/proto/BREAKING.mdfollowing the #277 entry's form. The minor-8 row indocs/reference/ipc.mdkeepsSpawn/Createdand theaccepted→queuedrename; only the operation-id clauses go.MINOR_OPERATION_IDSgoes with them: the constant and its ledger text infelis-protocol/src/preface.rs, the re-export inlib.rs, and the four gated-field entries plus their tests inminor.rs.crates/felis-daemon/src/operations.rsand itspub modinlib.rs; dropOperationsfrom the pool (pool.rs); drop the mint at theOpsSwitchhandler inserve.rs(operations().mint()), thelandcall and its debug log at the attach path inserve.rs, and the stamping/recording inserve/session_task.rs; updateserve/tests.rs.lib.rs,messages.rs,messages/{ops,push,session}.rs,convert.rs,convert/ops.rs, regeneratedfelis.v1.rs.felis-client-core(connector.rs,dial.rs) and infelis-client(main.rs,event_handler.rs,app_methods.rs).operation_idfrom theswitch,ssh,window retargetobjects and the bridge results (cli_output.rs,cli_sessions.rs,cli_bridge.rs); regeneratecrates/felis-cli/schemas/felis-cli-v1.schema.jsonandfelis-bridge-v1.schema.json; updatetests/cli_sessions.rs. The bridge goldens hold no successfulsessions.switchresult today, so the removal of the key from the bridge object needs a success-path test added, not a regeneration.grep -rn 'OperationId\|OperationEcho\|MINOR_OPERATION_IDS\|operation_id'overcrates/,docs/,skills/is empty exceptCHANGELOG.mdandBREAKING.md.queuedas the sole completion claim,not_queuedas its error kind.docs/reference/ipc.md(Switch/Switched, Push, the "Operation ids" section, minor-8 row),docs/reference/cli.md(output tables and theoperation_idparagraph),docs/reference/control-surfaces.mdif it names the field,CHANGELOG.md(user-affecting:switch/ssh/window retargetmachine output and the bridge result lose a key).docs/explanation/architecture/ipc.md"What a switch reply can report" is rewritten in the present tense, per doc-cascade §3/§4: a switch reply promises queue admission and nothing else; completion tracking is rejected because no consumer needs it and because the origin daemon cannot observe a carrier landing at all, so any completion contract would either stay partial or make the client a participant in cross-host daemon bookkeeping. The Revisit if stays and names the observable trigger: a consumer that must act on the window's new home. Identifier shape, incarnation keying, and retention bounds are not recorded; they are design for a feature that does not exist, and the consumer that triggers the revisit defines what it needs. The removal itself is recorded inCHANGELOG.mdand git, not in the docs.Acceptance mapping
just check, the schema regeneration, and the identifier sweep.BREAKING.mdentry.queuedremains the only switch completion claim.Effort: S–M, one PR. Labels stay
priority/P1,release/v0.1.0; this is a freeze-list change and goes before the tag.