airvzxf / airvzxf/moagan

feat(llm): add CLI subcommands moagan probe top_p + moagan probe top_k (D7)

Abierto
#931 0 comentarios 0 reacciones 0 asignados Ver en GitHub
area:llm enhancement priority:P3 size:S
Lenguaje dominante
Rust
Estrellas
0
Forks
1
Merge medio
35 min
PR fusionados (30 d)
238

Descripción

## Goal

Add the CLI verbs `moagan probe top_p` and `moagan probe top_k` per #900 D7. Mirror the existing `moagan probe temperature` and `moagan probe max_tokens` verbs. Both verbs run the auto-probe, persist the result to `/top_p_auto.toml` and `/top_k_auto.toml`, and accept `--persist-min` / `--persist-union` flags (D10: fixed safe set — these are now permanent code, not user-configurable).

## Why now

#12 lands the underlying `TopPTable` / `TopKTable` infrastructure. This issue exposes them via the CLI, completing the two-plane naming contract from #900 D7 (wire field `top_p` / `top_k`; CLI verb `moagan probe top_p` / `moagan probe top_k`; sidecar file `top_p_auto.toml` / `top_k_auto.toml`).

## Scope

**In scope:**
- `src/cli/probe.rs` (already has `ProbeCmd` enum at `:65-84`): add two new variants:
- `ProbeCmd::TopP(ProbeTopPCmd)`
- `ProbeCmd::TopK(ProbeTopKCmd)`
- Each variant mirrors the existing `ProbeMaxTokensCmd` / `ProbeTemperatureCmd` shape (`:87-157`):
- `--provider PROVIDER:MODEL` (required, repeatable).
- `--persist-min` (for `top_p` / `top_k` — pins the operator cap to the minimum accepted value).
- `--batch-size N` (for `top_p` — defaults to the per-verb batch size constant).
- `--dry-run` (don't persist to disk).
- `dispatch(cmd: &ProbeCmd)` at `src/cli/probe.rs:160-166`: add the two new arms.
- `dispatch_top_p` / `dispatch_top_k` functions (mirror `dispatch_temperature` at `:353-502`):
- Build the underlying `LlmClient` via `client::dispatcher::build_client` (issue #4).
- Wrap in `LlmClientProbeTransport` (introduced in #7).
- Run the probe via `TopPTable::probe_and_store(...)` / `TopKTable::probe_and_store(...)`.
- On `--persist-min`, call `TopPTable::set_operator_cap(...)` / `TopKTable::set_operator_cap(...)`.
- Unit tests at `src/cli/probe.rs::tests` that pin the new CLI verbs.
- Update `src/cli/probe.rs::tests::build_provider_for_spec_*` to assert the two new verbs route through the dispatcher.

**Out of scope:**
- The underlying `TopPTable` / `TopKTable` infrastructure — issue #12.
- Cascade absorption (D9) / audit-hash kill (D8) — issue #14.
- Legacy `Provider` deletion — issue #15.

## Approach

### 1. CLI verb shape

```rust
#[derive(Debug, Clone, clap::Args)]
pub struct ProbeTopPCmd {
#[arg(long = "provider", value_name = "PROVIDER:MODEL", required = true, num_args = 1..)]
pub providers: Vec,
#[arg(long, default_value_t = false)]
pub persist_min: bool,
#[arg(long, default_value_t = TOP_P_PROBE_BATCH_SIZE)]
pub batch_size: usize,
#[arg(long, default_value_t = false)]
pub dry_run: bool,
}

#[derive(Debug, Clone, clap::Args)]
pub struct ProbeTopKCmd {
#[arg(long = "provider", value_name = "PROVIDER:MODEL", required = true, num_args = 1..)]
pub providers: Vec,
#[arg(long, default_value_t = false)]
pub persist_min: bool,
#[arg(long, default_value_t = false)]
pub dry_run: bool,
}
```

(`top_k` doesn't take `--batch-size` because the algorithm walks powers of 2 — the batch is fixed.)

### 2. `dispatch_top_p` function

Mirror `dispatch_temperature` at `src/cli/probe.rs:353-502`:

```rust
pub async fn dispatch_top_p(cmd: &ProbeTopPCmd) -> Result {
// 1. Resolve each `provider:model` pair via `cfg.providers_by_section`.
// 2. Build an LlmClient via `client::dispatcher::build_client` (issue #4).
// 3. Wrap in `LlmClientProbeTransport` (issue #7).
// 4. Load `TopPTable::from_home(&home, floor, save)`.
// 5. Run `TopPTable::probe_and_store(transport, ...)` with cmd.batch_size.
// 6. On `--persist-min`, call `TopPTable::set_operator_cap(...)`.
// 7. Print the discovered top_p set + operator cap to stdout.
// 8. Exit 0 on success, 1 on probe failure.
}
```

### 3. Unit tests

- `dispatch_top_p_accepts_provider` — wiremock returns `200` for `top_p=0.5`, `400` for `top_p=0.55`. Probe returns `0.5`.
- `dispatch_top_p_persist_min_writes_cap` — `--persist-min` → sidecar has `operator_caps..auto = false, .top_p = 0.5`.
- `dispatch_top_p_dry_run_does_not_persist` — `--dry-run` → sidecar unchanged.
- `dispatch_top_k_walks_powers_of_2` — wiremock accepts `1, 2, 4, 8, 16`, rejects `32`. Probe returns `16`.
- `dispatch_top_k_persist_min_writes_cap` — same as top_p.

## Acceptance criteria

- [ ] `cargo build --release --all-features` succeeds with **zero warnings**.
- [ ] `make fmt-check guard-deps lint build test-ci` green.
- [ ] `moagan probe top_p --help` and `moagan probe top_k --help` print the new args.
- [ ] `moagan probe top_p --provider mock:mock-model --dry-run` runs without error.
- [ ] `moagan probe top_k --provider mock:mock-model --dry-run` runs without error.
- [ ] `moagan probe top_p --provider mock:mock-model --persist-min` writes `/top_p_auto.toml` with `operator_caps.mock.mock-model.auto = false`.
- [ ] `moagan probe top_k --provider mock:mock-model --persist-min` writes `/top_k_auto.toml` similarly.
- [ ] New unit tests at `src/cli/probe.rs::tests` cover the 5 listed cases and pass.
- [ ] `cli-reference.md` documents the two new verbs.

## Merge order

```
#1-#11 (foundation + migration wave)
#12 (top_p_auto + top_k_auto infrastructure)

#13 (this issue — CLI verbs)

#14-#15 (cleanup wave)
```

## Validation

- `make fmt-check guard-deps lint build test-ci` green after the PR lands.
- 5 new unit tests pass.
- Manual: `moagan probe top_p --provider mock:mock-model --dry-run` and `moagan probe top_k --provider mock:mock-model --dry-run` run successfully.

## Version target

v0.18.0 (or v0.18.x patch — additive feature, no breaking changes). Per the operator's preference in the EPIC body comment, batching into v0.18.0 is the natural target.

## References

- [EPIC #847](https://github.com/airvzxf/moagan/issues/847) — the umbrella.
- [#900 D7, D10](https://github.com/airvzxf/moagan/issues/900) — `_auto` naming (D7), fixed safe set (D10).
- [`src/cli/probe.rs:65-166`](../blob/main/src/cli/probe.rs) — existing `ProbeCmd` enum and `dispatch` function.
- [`src/cli/probe.rs:353-502`](../blob/main/src/cli/probe.rs) — `dispatch_temperature` (mirrored by `dispatch_top_p`).
- [`src/cli/probe.rs:168-320`](../blob/main/src/cli/probe.rs) — `dispatch_max_tokens` (mirrored by `dispatch_top_k`).
- [Issue #4](../issues/921) (when created) — `client::dispatcher::build_client`.
- [Issue #7](../issues/924) (when created) — `LlmClientProbeTransport`.
- [Issue #12](../issues/929) (when created) — `TopPTable` / `TopKTable`.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.