ROCMAI-83: extract cli.rs from apps/rocmd/src/lib.rs - #481
jussielo-amd wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The architecture map incorrectly claims three independently developed modules are already present.
Review effort: Balanced
Findings: 1
What changed in this PR
Extracts rocmd CLI definitions and dispatch into a dedicated module without intended behavior changes.
Changes:
- Adds
cli.rswith CLI types, dispatch, and parsing tests. - Re-exports existing public entry points from
lib.rs. - Updates architecture documentation.
| File | Description |
|---|---|
apps/rocmd/src/cli.rs |
Houses CLI definitions, dispatch, policies, and tests. |
apps/rocmd/src/lib.rs |
Registers the module and updates internal references. |
docs/architecture.md |
Documents modularization progress. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| ### `apps/rocmd` — background daemon | ||
|
|
||
| `lib.rs` is **not yet modularized** — see EAI-7768. | ||
| `lib.rs` modularization is in progress (ROCMAI-83, Phase 5 of EAI-7768's sequencing). Extracted so far: `persistence.rs` (`record_event`/`load_managed_services`, the automation-event/audit-log and managed-service-registry I/O shared across the daemon's sandbox, MCP, service-lifecycle, and watcher code), `common.rs` (helpers shared across ≥2 of those remaining clusters: GPU/amd-smi snapshotting, the bridge-snapshot diagnostic, `CommandCapture`/command-timeout plumbing, and small arg/healthcheck/endpoint-key utilities), `webhook.rs` (the local webhook source: its axum routes, request validation, and watcher-kind allow-list), and `cli.rs` (the `Cli`/`Command` clap definitions, `SandboxToolArg`/`SandboxToolPolicy`, and the top-level dispatch in `run_cli`/`run_bin_cli`/`run_from_args` — the crate's only two externally-consumed entry points are re-exported from here via `lib.rs`'s `pub use`). Still pending: `sandbox.rs`, `mcp.rs`, `service.rs`, and `watchers.rs` — each landing as its own PR. |
There was a problem hiding this comment.
Resolved by stacking rather than editing the doc hunk: this PR is now rebased onto rocmai-83-webhook and its base is set to that branch (merge order 477 → 479 → 480 → 481), so persistence.rs, common.rs, and webhook.rs are genuinely present in this branch's tree — the architecture.md wording now matches the checked-in files. See r0x0r's review for the fuller writeup of why stacking (rather than scoping the doc hunk to cli.rs only) was the chosen fix for the whole Phase-5 batch.
r0x0r
left a comment
There was a problem hiding this comment.
Review: code is clean; holding approval on one doc line
The extraction verified as pure code motion, including every clap attribute — which is where this particular diff could have gone wrong silently. One issue in docs/architecture.md is the only thing between this and an approval, plus one terminology point worth settling before the remaining cluster PRs cite it.
The doc hunk describes a state this branch is not in
The new text claims persistence.rs, common.rs and webhook.rs are extracted alongside cli.rs. None of those three exists in this branch — apps/rocmd/src/ here contains only cli.rs, lib.rs, main.rs.
The reason this is more than a doc nit is only visible across the phase, not from inside this PR:
- All five PRs rewrite the same single line of
docs/architecture.md, each branched independently frommain. Four are guaranteed to conflict on it. - Each text is a cumulative prefix assuming the earlier sequence has merged — true only at merge order 477 → 479 → 480 → 481 → 483.
- The failure is quiet rather than loud: this PR merging first finds nothing to conflict with, applies cleanly, and leaves
mainasserting three files that do not exist. The conflict that would have caught it only exists once something else has touched that line.
Given docs/architecture.md's own framing — updated in the same PR as the code it documents, and "a stale-but-plausible-looking note is worse than an explicit prompt to check" — either fix works:
- Scope the hunk to
cli.rsonly, letting each sibling append as it lands. Correct at any merge order; conflicts become trivial appends. - Keep the cumulative text and gate merge order with
Depends on #477, #479, #480in the body.
Non-blocking: this is the bootstrap.rs pattern, not mechanical relocation
The PR body describes the change as following the mechanical-relocation pattern. docs/architecture.md defines that pattern by the module having no owned types — shared types stay at the crate root and are reached via crate::. This PR moves four type definitions into cli.rs: Cli, Command, SandboxToolArg and SandboxToolPolicy.
The doc also says that for a subsystem with a dedicated clap subcommand the command enum and dispatch usually stay put, and names bootstrap.rs as the further-extracted variant that owns its clap enum and its dispatch function. That is precisely what cli.rs is here.
Nothing about the code is wrong — this is a labelling question, and I'd not hold the PR for it. But it is worth correcting rather than leaving, because sandbox.rs, mcp.rs, service.rs and watchers.rs are still to come and will reach for a precedent in exactly this doc. If "mechanical relocation" is recorded as covering a module that owns four types, the distinction the convention is drawing stops doing any work. Citing the bootstrap.rs precedent instead costs a sentence and keeps the taxonomy meaningful.
Verified clean
- Clap attributes preserved byte-for-byte — I went through
CliandCommandattribute by attribute againstlib.rs:64–215onmain: every#[arg(...)]/#[command(...)], everylong/short/default_value/value_enum/requires/conflicts_with, every help string, the#[command(hide = true)]markers, and the#[cfg(target_os = "linux")]guards onwrites_data/writes_cache. This is the one place in this diff where a silent regression was possible — a dropped attribute changes the CLI's user-facing surface without failing to compile — so it is worth saying explicitly that there is none. Constants inas_cli_valuematch, andSandboxToolPolicy::from_cliis unchanged. - Public API surface is exactly preserved —
mainexported preciselyrun_bin_cliandrun_from_args; this branch exports precisely those two viapub use cli::{...}from a privatemod cli, sorocmd::cli::*stays unreachable from outside. Both external consumers (apps/rocmd/src/main.rs:6,apps/rocm/src/main.rs:2442) are unaffected. - All ~89
SandboxToolArg/SandboxToolPolicysites repointed; thelib.rstests reach them throughuse super::*and can still build struct literals because the fields arepub(crate). - Imports —
clap::{Parser, Subcommand, ValueEnum}correctly dropped fromlib.rsandclap::CommandFactoryfrom its test module, with no clap symbol left referenced there; nothing fails under-D warnings. Everycrate::-qualified call out ofcli.rsresolves to a function still present inlib.rs. - Tests — 130 attributes conserved (126 + 4), matching the claimed 4 exactly.
- Crate-layering (AGENTS.md §6) —
cli.rsimports fromrocm_core, notrocm; therocmd-must-not-depend-on-rocminvariant holds. - Blast radius — the comment at
apps/rocm/src/main.rs:22227referring torocmd::Cli/rocmd::Commandas "crate-private in rocmd" remains accurate after the move, since it describes visibility rather than location. No change needed there. - Leak scan (AGENTS.md §2) — the one hit is the pre-existing phrase "restricted internal tool API" in a help string, moved verbatim. Clean.
🤖 by agent-hub on AMD AgentHub
Fourth PR of Phase 5 (rocmd modularization, ROCMAI-27): pull the Cli/Command clap definitions, SandboxToolArg/SandboxToolPolicy, and the top-level dispatch (run_cli/run_bin_cli/run_from_args) into their own module, following the mechanical-relocation pattern (thin dispatch; call sites into not-yet-extracted clusters stay crate::- qualified until those land). lib.rs re-exports run_bin_cli/ run_from_args via pub use so the crate's only two external call sites are untouched. No behavior change. SandboxToolArg/SandboxToolPolicy are consumed pervasively by the still-inline sandbox.rs cluster (and its test suite), so every one of those ~89 call sites is repointed to cli::SandboxToolArg/cli::SandboxToolPolicy. The 4 tests that exercise Cli/Command parsing directly (not mixed with sandbox/mcp/webhook/service domain logic that happens to share a name prefix or construct these types as a parameter) moved into cli.rs's own #[cfg(test)] mod in this same PR. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
2dc7a94 to
27af1e0
Compare
|
@r0x0r thanks for the thorough verification pass — replying to both points raised in your review: Blocking: architecture.md describing sibling-PR state. Resolved by stacking, not by editing the doc hunk. The whole Phase-5 batch is now stacked per AGENTS.md §11, merge order 477 (persistence.rs) → 479 (common.rs) → 480 (webhook.rs) → 481 (this PR, cli.rs) → 483 → 484 → 487 → 489. This PR's base is now Non-blocking: mechanical-relocation vs. bootstrap.rs-style taxonomy. Fair point, and I agree with the read — |

Summary
Fourth PR of Phase 5 (ROCMAI-83, part of the modularization epic ROCMAI-27). Pulls the
Cli/Commandclap definitions,SandboxToolArg/SandboxToolPolicy, and the top-level dispatch (run_cli/run_bin_cli/run_from_args) into their owncli.rsmodule.This follows the mechanical-relocation pattern (per
docs/architecture.md's convention) rather than full domain extraction:run_cliis thin dispatch, and its match arms call into clusters that haven't been extracted yet (sandbox,mcp,service,watchers) viacrate::-qualified paths, to be updated as each of those lands in a later PR.lib.rsre-exportsrun_bin_cli/run_from_argsviapub use cli::{...};— the crate's only two externally-consumed symbols are untouched.SandboxToolArg/SandboxToolPolicyare consumed pervasively by the still-inlinesandbox.rscluster and its test suite — all ~89 call sites repointed tocli::SandboxToolArg/cli::SandboxToolPolicy.Cli/Commandparsing directly (not mixed with sandbox/mcp/webhook/service domain logic that happens to share a name prefix, or merely use these types as a parameter) moved intocli.rs's own#[cfg(test)] modin this same PR.docs/architecture.mdupdated in this PR.Independent of #477, #479, #480 — branched separately from
main, not stacked, per the one-off PR approach for this phase.Test plan
cargo build(rocmd, androcm+rocmdtogether to confirm the external API surface is untouched)cargo clippy --workspace --all-targets -- -D warningscargo test -p rocmd— 130 tests, same count as before this change (129 passed + 1 pre-existing ignored)cargo xtask manifest --checkcargo fmt/ prek hooks cleantests/e2e-cucumber(CI)