Expose primary workflow in public CLI help

This commit is contained in:
Michel Paulissen 2026-07-04 00:11:58 +02:00
parent 1c3fdfc38a
commit e6c2a1a981
4 changed files with 56 additions and 4 deletions

View file

@ -1,7 +1,7 @@
{ {
"kind": "disasmer-filtered-public-tree", "kind": "disasmer-filtered-public-tree",
"source_commit": "d0ea56e226f6a5fa409ab5284d5c4e550afe2f35", "source_commit": "133d7b466c2f96c240f559722bc4b557aa94c091",
"release_name": "dryrun-d0ea56e226f6", "release_name": "dryrun-133d7b466c2f",
"filtered_out": [ "filtered_out": [
"private/**", "private/**",
"experiments/**", "experiments/**",

View file

@ -26,7 +26,21 @@ const DOCTOR_COORDINATOR_TIMEOUT: Duration = Duration::from_millis(500);
const DEFAULT_ARTIFACT_EXPORT_MAX_BYTES: u64 = 64 * 1024 * 1024; const DEFAULT_ARTIFACT_EXPORT_MAX_BYTES: u64 = 64 * 1024 * 1024;
#[derive(Clone, Debug, Parser)] #[derive(Clone, Debug, Parser)]
#[command(name = "disasmer", version, arg_required_else_help = true)] #[command(
name = "disasmer",
version,
arg_required_else_help = true,
about = "Disasmer distributed Wasm runtime CLI.",
after_help = "Primary workflow:
1. disasmer login --browser
2. disasmer project init
3. disasmer node enroll; disasmer node attach --worker
4. disasmer run [entry] --project <path>
5. Debug with VS Code \"Disasmer: Launch Virtual Process\" or disasmer dap
6. Inspect with disasmer process status, task list, logs, and artifact list
Use --json on primary commands for scriptable output. Hosted account creation happens in the browser login flow."
)]
struct Cli { struct Cli {
#[command(subcommand)] #[command(subcommand)]
command: Commands, command: Commands,
@ -5887,6 +5901,31 @@ mod tests {
} }
} }
#[test]
fn top_level_help_exposes_primary_workflow_without_auth() {
let mut command = Cli::command();
let help = command.render_help().to_string();
for expected in [
"Primary workflow:",
"disasmer login --browser",
"disasmer project init",
"disasmer node enroll",
"disasmer node attach --worker",
"disasmer run [entry] --project <path>",
"Disasmer: Launch Virtual Process",
"disasmer dap",
"disasmer process status",
"task list",
"logs",
"artifact list",
"--json",
"Hosted account creation happens in the browser login flow.",
] {
assert!(help.contains(expected), "help output missing {expected}");
}
}
#[test] #[test]
fn top_level_logout_alias_removes_only_cli_session_state() { fn top_level_logout_alias_removes_only_cli_session_state() {
let temp = tempfile::tempdir().unwrap(); let temp = tempfile::tempdir().unwrap();

View file

@ -138,7 +138,8 @@ assert.doesNotMatch(
); );
for (const [name, pattern] of [ for (const [name, pattern] of [
["top-level version metadata", /#\[command\(name = "disasmer", version, arg_required_else_help = true\)\]/], ["top-level version metadata", /#\[command\([\s\S]*name = "disasmer"[\s\S]*version[\s\S]*arg_required_else_help = true[\s\S]*\)\]/],
["top-level primary workflow help", /after_help = "Primary workflow:[\s\S]*disasmer login --browser[\s\S]*disasmer node attach --worker[\s\S]*Disasmer: Launch Virtual Process[\s\S]*Hosted account creation happens in the browser login flow\."/],
["top-level logout command", /enum Commands[\s\S]*Logout\(AuthLogoutArgs\)[\s\S]*Auth \{/], ["top-level logout command", /enum Commands[\s\S]*Logout\(AuthLogoutArgs\)[\s\S]*Auth \{/],
["human report renderer", /fn human_report\(value: &Value\) -> String/], ["human report renderer", /fn human_report\(value: &Value\) -> String/],
["shared report emitter", /fn emit_report<T: Serialize>\(report: &T, json_output: bool\) -> Result<\(\)>/], ["shared report emitter", /fn emit_report<T: Serialize>\(report: &T, json_output: bool\) -> Result<\(\)>/],
@ -164,6 +165,7 @@ for (const [name, pattern] of [
for (const [name, pattern] of [ for (const [name, pattern] of [
["CLI parse coverage", /fn cli_first_mvp_command_surface_parses\(\)/], ["CLI parse coverage", /fn cli_first_mvp_command_surface_parses\(\)/],
["CLI primary workflow help coverage", /fn top_level_help_exposes_primary_workflow_without_auth\(\)/],
["CLI version coverage", /fn top_level_version_is_available\(\)/], ["CLI version coverage", /fn top_level_version_is_available\(\)/],
["CLI JSON parse coverage", /fn cli_first_json_mode_parses_for_primary_commands\(\)/], ["CLI JSON parse coverage", /fn cli_first_json_mode_parses_for_primary_commands\(\)/],
["CLI human output coverage", /fn human_report_is_text_not_json\(\)/], ["CLI human output coverage", /fn human_report_is_text_not_json\(\)/],

View file

@ -36,6 +36,17 @@ function assertHuman(name, output, requiredPatterns) {
} }
} }
const helpHuman = disasmer(["help"]);
assertHuman("help", helpHuman, [
/Primary workflow:/,
/disasmer login --browser/,
/disasmer project init/,
/disasmer node attach --worker/,
/Disasmer: Launch Virtual Process/,
/Hosted account creation happens in the browser login flow/,
/--json/,
]);
const loginHuman = disasmer(["login", "--coordinator", "https://coord.example.test"]); const loginHuman = disasmer(["login", "--coordinator", "https://coord.example.test"]);
assertHuman("login", loginHuman, [ assertHuman("login", loginHuman, [
/Disasmer login/, /Disasmer login/,