[v0.1/CLI Args Review] CLI 引数のリリース前設計レビュー #55
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#55
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?
概要
v0.1.0 の public contract freeze 前提で、CLI argument grammar を
2645b986+ review working tree (5077d74b) に対して重点レビューした。互換性は考慮せず、以下を実施した。felis/ 全 visible subcommand /felis-client/felis-daemonの実 help を生成して比較docs/reference/cli.md、reference/control-surfaces.md、explanation/architecture/control-surfaces.md、IPC/requirements/backlog と照合設計の主軸(window launch と headless verbs の分離、typed argv、session prefix、Point/Stream/Exempt の分類)は維持できる。一方、凍結前に直すべき新規2件と、既存 P0/P1 issue に追加して確認すべき argument-level gap が見つかった。
新規 issue
sessions spawnだけ--を要求せず、option typo (spawn --json) を program 実行要求として受理する。bare launch/retarget と-- <CMD>...に統一する。--trace-perfは headless/config/doctor/bridge で受理後 silent ignore。RUST_LOGと process-local 診断面があるため public global に置く根拠が弱い。既存 issue に統合する確認事項
#17 — version grammar
felis --version sessions listとfelis --version -- htopが parse に成功し、後続 command を無視して version report を exit 0 で返す。#17 の offline/self-only 化に加え、標準--versionと同様に exclusive であることを acceptance に含めるべき。#23 — machine/usage contract
#23 の方針は妥当だが、実装時に次を golden test へ含める必要がある。
sessions spawn --format json --jsonの daemon-autospawn failure では、stderr に tracing の INFO 行が先行し、現在の「point failure は exactly one JSON object」という契約を破る。machine channel と logs を分離または machine mode で console logs を抑止する。--formatとcapture --sourceは customvalue_parser = fnのため、help/completion metadata に possible values が載らない。completionsを public surface とするなら finite vocabulary を clap に公開する。window retarget --session 1a -- htop、SSH carrier なしの--ssh-arg、payload なしのsendは clap 後の usage error。#23 の「valid machine format 認識後の usage error は同 format」をこの全経路で揃える。send --raw --wait/send --raw --key enterは--rawの対象 payload がないのに受理される。無効 option を拒否するか、効果がある意味を定義する。#27 — config path
--config PATHは argument review でも必要性を再確認した。Windows test だけでなく、実 profile を置換せずconfig check/show-effectiveを試す唯一の再現可能な入口になる。既存 #27 の scope で十分。#23 / #37 / #38 / #39 — carrier spelling and placement
同じ
--hostが root では「この invocation が dial する daemon」、window retarget配下では「window の destination」を意味し、flag の位置だけで役割が変わる。#23 の--to-host+felis sshremoval が最も単純で、#37–#39 の問いをまとめて閉じられる。root carrier を真の global option として subcommand 後にも許すか、常に root-before-command と凍結するかも同時に決める。#39 / #42 — dynamic completion の network side effect
fish/zsh completion は
<TAB>ごとに hidden__complete-sessionsを実行し、in-flight--hostを転送して SSH 接続する。connect_stdio_commandは SSH stderr/TTY を継承し felis-side timeout を持たないため、remote session-id completion が password/host-key prompt や不達 host で対話シェルを停止し得る。completion は local-only に戻す、短い hard timeout + noninteractive SSH + cache を設ける、または remote dynamic completion を削る、のどれかを #39/#42 の carrier/timeout 決定に含めるべき。
explanation/architecture/control-surfaces.mdは helper を local-only と記述する一方、実装とreference/cli.mdは remote forwarding を normative としており、現状は docs も不整合。今回は変更不要と判断した点
felis attachを top-level launcher、sessions switchを headless IPC verb とする分離: process boundary を正しく表しており、closed #3 の再オープン理由なし。frontend <name> [ARGS]...のみ opaque pass-through: namespace が明示されており、unknown built-in typo を exec しない。send <id> -の stdin convention、repeatable--key、--env KEY=VAL: shell string evaluator を導入せず typed data のまま。推奨順序
--versionの standard/exclusive contract を確定。Principle verdict
提案はいずれも capability を増やさず、曖昧・重複・silent no-op を削る。principles 1–4 はすべて Pass。特に command separator と ignored option の除去は principle 4 の explicitness を強める。
完了条件
<TAB>から無期限/対話的 network operation を起動しない。docs/reference/cli.md、reference/explanation twins、tutorials、man、completion、skills/felis、CHANGELOG.mdが同じ grammar を示す。レビュー対象
crates/felis-cli/src/{main,cli_sessions,cli_output,cli_completions,cli_notifications,cli_config,cli_daemon}.rscrates/felis-client/src/main.rscrates/felis-daemon/src/main.rscrates/felis-client-core/src/{dial,connector,local_socket}.rsdocs/reference/{cli,control-surfaces,spec}.mddocs/explanation/{design,principles,non-goals,architecture/control-surfaces,architecture/ipc}.mddocs/backlog.mdParent release tracker: #12
Triage (2026-09-05): the 2026-09-05 CLI review adds #136, #141, #145 as P1 children of this tracker. #53 and #54 are merged. Closure now waits on those three plus #29's goldens.
残っていた完了条件のうち子 issue がなかった2件を分割した:
他 (version 排他、machine/log 分離、completion local-only、send --raw requires) は実装済みを確認。
Closed (2026-09-08)
Every child issue this tracker raised is closed and every prose completion criterion has landed evidence on
main.Children
5a1a49a2(fix(cli): require -- before spawn argv and drop ignored --trace-perf)5a1a49a2(fix(cli): require -- before spawn argv and drop ignored --trace-perf)The pre-existing issues named in this tracker's recommended order are closed too:
--ssh-argstays one verbatim argv token and multiplexing stays OpenSSH's, recorded indocs/explanation/architecture/ipc.mdCompletion criteria
state: closedvia the API; no open issue carriesrelease/v0.1.0besides #12, #31, and this tracker.crates/felis-cli/src/tests.rs:fn every_visible_help_page_is_snapshotted()walks the whole non-hidden subcommand tree intocrates/felis-cli/src/snapshots/felis__tests__every_visible_help_page_is_snapshotted.snap, andmod argv_matrixpins the parser layer: "The frozen argv grammar as a table: one row per line whose outcome the surface has committed to, so a refactor that loosens a rule fails here instead of shipping."crates/felis-cli/src/main.rs: "A machine format silences the console: a point verb's stderr is one typed error object, and an autospawn INFO line beside it would make that two lines.RUST_LOGstill wins", implemented aslet fallback = if cli.machine_output() { "off" } else { "info,felis=debug" };.crates/felis-cli/src/tests.rsassertshelp.contains("[possible values: human, jsonl]"),help.contains("[possible values: visible, scrollback, command-output, last-command]"), and for a point verbpoint.contains("[possible values: human, json]"); the vocabularies became clapValueEnums in PR #198.<TAB>から無期限/対話的 network operation を起動しない —crates/felis-cli/src/cli_completions.rs: "Completion is local-only: the helper never dials SSH." (and the same rule again for the retarget helpers), landed by PR #58.docs/reference/cli.md、reference/explanation twins、tutorials、man、completion、skills/felis、CHANGELOG.mdが同じ grammar を示す — the separator grammar reads the same everywhere:docs/reference/cli.md"detached command without a window, usefelis sessions spawn -- <cmd>",skills/felis/SKILL.mdfelis sessions spawn -- /bin/zshandfelis sessions spawn --tag agent -- …, with the matchingCHANGELOG.mdentries; the generated help, man, and completion surfaces are frozen by the snapshot test above and the schemas by #29.Follow-ups
None. No follow-up issue from this review moved to a post-v0.1 backlog; #178, raised from the #29 schema work, was itself closed on
main.