Skip to content

Commit a049bd2

Browse files
committed
ROADMAP ultraworkers#111: /providers documented as 'List available model providers' but dispatches to Doctor
Dogfooded 2026-04-18 on main HEAD b2366d1 from /tmp/cdHH. Specification mismatch at the command-dispatch layer: commands/src/lib.rs:716-720 SlashCommandSpec registry: name: 'providers', summary: 'List available model providers' commands/src/lib.rs:1386 parser: 'doctor' | 'providers' => SlashCommand::Doctor So /providers dispatches to SlashCommand::Doctor. A claw calling /providers expecting {kind: 'providers', providers: [...]} gets {kind: 'doctor', checks: [auth, config, install_source, workspace, sandbox, system]} instead. Same top-level kind field name, completely different payload. Help text lies twice: --help slash listing: '/providers List available model providers' --help Resume-safe summary: includes /providers Unlike STUB_COMMANDS (ultraworkers#96) which fail noisily, /providers fails QUIETLY — returns wrong subsystem output. Runtime has provider data: ProviderKind::{Anthropic, Xai, OpenAi, ...} at main.rs:1143-1147 resolve_repl_model with provider-prefix routing pricing_for_model with per-provider costs provider_fallbacks config field Scaffolding is present; /providers just doesn't use it. By contrast /tokens → Stats and /cache → Stats are semantically reasonable (Stats has the requested data). /providers → Doctor is genuinely bizarre. Fix shape: A. Implement: SlashCommand::Providers variant + render helper using ProviderKind + provider_fallbacks + env-var check (~60) B. Remove: delete 'providers' from registry + parser (~3 lines) then /providers becomes 'unknown, did you mean /doctor?' Either way: fix --help to match. Parallel to ultraworkers#78 (claw plugins CLI variant never constructed, falls through to prompt). Both are 'declared in spec, not implemented as declared.' ultraworkers#78 fails noisy, ultraworkers#111 fails quiet. Joins silent-flag cluster (ultraworkers#96-ultraworkers#101, ultraworkers#104, ultraworkers#108) — 8th doc-vs-impl mismatch. Joins unplumbed-subsystem (ultraworkers#78, ultraworkers#96, ultraworkers#100, ultraworkers#102, ultraworkers#103, ultraworkers#107, ultraworkers#109) as 8th declared-but-not- delivered surface. Joins truth-audit. Natural bundles: ultraworkers#78 + ultraworkers#96 + ultraworkers#111 — declared-but-not-as-declared triangle ultraworkers#96 + ultraworkers#108 + ultraworkers#111 — full --help/dispatch hygiene quartet (help-filter-leaks + subcommand typo fallthrough + slash mis-dispatch) Filed in response to Clawhip pinpoint nudge 1494872623782301817 in #clawcode-building-in-public.
1 parent b2366d1 commit a049bd2

1 file changed

Lines changed: 77 additions & 0 deletions

File tree

ROADMAP.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3178,3 +3178,80 @@ ear], /color [scheme], /effort [low|medium|high], /fast, /summary, /tag [label],
31783178
**Blocker.** None. `project_root_for` helper trivially reusable from the git-root walker. Discovery list is additive — adding ancestor entries doesn't break existing cwd-anchored configs. Most invasive piece is the architectural decision: walk-to-project-root + cwd-overlay (this proposal), or walk-every-ancestor-like-CLAUDE.md (#85's current over-broad policy), or unify both under a single policy.
31793179
31803180
**Source.** Jobdori dogfood 2026-04-18 against `/tmp/cdGG/nested/deep/dir` on main HEAD `16244ce` in response to Clawhip pinpoint nudge at `1494865079567519834`. Joins **truth-audit / diagnostic-integrity** (#80–#87, #89, #100, #102, #103, #105, #107, #109) — doctor reports "ok, defaults active" when the operator actually has a config. Joins **discovery-overreach / security-shape** (#85, #88) as the opposite-direction sibling: #85 over-discovers instruction files; #110 under-discovers config files. Cross-cluster with **Reporting-surface / config-hygiene** (#90, #91, #92) — this is the canonical config-discovery policy bug. Natural bundle: **#85 + #110** — unify ancestor-discovery policy across CLAUDE.md + config. Also **#85 + #88 + #110** as the three-way "ancestor-walk policy audit" covering skills over-discovery, CLAUDE.md prompt injection via ancestors, and config under-discovery from subdirectories. Session tally: ROADMAP #110.
3181+
3182+
111. **`/providers` slash command is documented as "List available model providers" in both `--help` and the shared command-spec registry, but its parser at `commands/src/lib.rs:1386` maps it to `SlashCommand::Doctor` — so invoking `/providers` runs the six-check health report (auth/config/install_source/workspace/sandbox/system) and returns `{kind: "doctor", checks: [...]}`. A claw expecting a structured list of `{providers: [{name, models, base_url, reachable}]}` gets workspace-health JSON instead** — dogfooded 2026-04-18 on main HEAD `b2366d1` from `/tmp/cdHH`. The command-spec registry at `commands/src/lib.rs:716-718` declares `name: "providers", summary: "List available model providers"`. `--help` echoes that summary in the slash-command listing and in the Resume-safe line. Actual dispatch routes to doctor. Declared contract and implementation diverge completely; this is a specification mismatch rather than a stub — `/providers` has documented semantics claw does not implement and silently delivers the wrong subsystem.
3183+
3184+
**Concrete repro.**
3185+
```
3186+
$ cd /tmp/cdHH && git init -q .
3187+
$ # set up a minimal session
3188+
$ claw --resume s --output-format json /providers | jq '.kind'
3189+
"doctor"
3190+
$ # A /providers call returns kind=doctor with six health checks
3191+
$ claw --resume s --output-format json /providers | jq '.checks[].name'
3192+
"auth"
3193+
"config"
3194+
"install source"
3195+
"workspace"
3196+
"sandbox"
3197+
"system"
3198+
# No `providers` array. No provider list. Auth/config/etc health checks.
3199+
3200+
$ # Compare help documentation:
3201+
$ claw --help | grep '/providers'
3202+
/providers List available model providers [resume]
3203+
# Help advertises provider listing. Implementation delivers doctor.
3204+
3205+
# Also compare: /tokens and /cache alias to SlashCommand::Stats, which IS
3206+
# reasonable — Stats contains token + cache counts. Those aliases are
3207+
# semantically close. /providers → Doctor is not.
3208+
$ claw --resume s --output-format json /tokens | jq '.kind'
3209+
"stats"
3210+
# Reasonable: Stats has token counts.
3211+
$ claw --resume s --output-format json /cache | jq '.kind'
3212+
"stats"
3213+
# Reasonable: Stats has cache counts.
3214+
```
3215+
3216+
**Trace path.**
3217+
- `rust/crates/commands/src/lib.rs:716-720` — command-spec registry:
3218+
```rust
3219+
SlashCommandSpec {
3220+
name: "providers",
3221+
aliases: &[],
3222+
summary: "List available model providers",
3223+
argument_hint: None,
3224+
...
3225+
}
3226+
```
3227+
- `rust/crates/commands/src/lib.rs:1386` — parser:
3228+
```rust
3229+
"doctor" | "providers" => {
3230+
validate_no_args(command, &args)?;
3231+
SlashCommand::Doctor
3232+
}
3233+
```
3234+
Both `/doctor` and `/providers` collapse to `SlashCommand::Doctor`. The registry-declared semantics for `/providers` ("list available model providers") is never honored.
3235+
- `rust/crates/rusty-claude-cli/src/main.rs` — `render_providers_report` / `render_providers_json` / any provider-listing code: **does not exist**. Verified via `grep -rn "fn render_providers\|fn list_providers\|pub fn providers" rust/crates/ | head` — zero matches.
3236+
- Runtime DOES know about providers conceptually — `rust/crates/rusty-claude-cli/src/main.rs:1143-1147` enumerates `ProviderKind::Anthropic`, `Xai`, etc. for prefix-routing model names. `resolve_repl_model` + provider-prefix logic has provider awareness. None of it is surfaced through a command.
3237+
3238+
**Why this is specifically a clawability gap.**
3239+
1. *Declared-but-not-implemented contract mismatch.* Unlike #96's `STUB_COMMANDS` entries (where the infrastructure says "not yet implemented"), `/providers` silently succeeds with the WRONG output. A claw parsing `{kind: "providers", providers: [...]}` from the documented spec gets `{kind: "doctor", checks: [...]}` instead — same top-level `kind` field name, completely different payload shape.
3240+
2. *Help text lies twice.* The standalone slash-command line in `--help` says "List available model providers." The Resume-safe summary also includes `/providers` (passes the #96 filter because it IS implemented — just as the wrong handler). A claw reading either surface cannot know the command is mis-wired without running it.
3241+
3. *Runtime has provider data.* `ProviderKind::{Anthropic,Xai,OpenAi,...}`, `resolve_repl_model`, provider-prefix routing, and `pricing_for_model` all know about providers. A real `/providers` implementation would have input from `ProviderKind` + any configured `providerFallbacks` array + env vars. ~20 lines. The scaffolding is present.
3242+
4. *Parallel to #78 (CLI route never constructed).* #78 says `claw plugins` CLI route is wired as a `CliAction` variant but falls through to Prompt. #111 says `/providers` slash command is wired as a `SlashCommandSpec` entry but dispatches to the wrong handler. Both are "declared in the spec, not actually implemented as declared." #78 fails noisily (prompt-fallthrough error); #111 fails quietly (returns a different subsystem's output).
3243+
5. *Joins the Silent-flag / documented-but-unenforced cluster* on a new axis: documentation-vs-implementation mismatch at the command-dispatch layer.
3244+
6. *Test coverage blind spot.* A unit test that asserts `claw --resume s /providers` returns `kind: "doctor"` would PASS today — which means the current test suite (if any covers /providers) is locking in the bug.
3245+
3246+
**Fix shape — either implement /providers properly or remove it from the spec + help.**
3247+
1. *Option A — implement.* Add a `SlashCommand::Providers` variant. Build a `render_providers_json(runtime_config) -> json!({ kind: "providers", providers: [{name, base_url_env, active, has_credentials, ...}] })` helper from the existing `ProviderKind` enum + `provider_fallbacks` config + env-var inspection. Add to the `run_resume_command` match. ~60 lines.
3248+
2. *Option B — remove.* Delete the `"providers"` name from the command-spec registry. Remove `"providers"` from the parser arm. `/providers` becomes an unknown slash command and gets the "Did you mean /doctor?" suggestion. ~3 lines of deletion.
3249+
3. *Either way, fix `--help`.* If implemented (Option A), the current help text is correct. If removed (Option B), delete the help line.
3250+
4. *Regression test.* Assert `/providers` returns `kind: "providers"` (Option A) or returns "unknown slash command" error (Option B). Either way, prevent the current silent-wrong-subsystem behavior.
3251+
5. *Cross-check.* Audit the rest of the registry for other mismatches. `/tokens → Stats` and `/cache → Stats` are semantically defensible (stats contains what the user asked for). Any other parser arms that collapse disparate commands into a single handler are candidates for the same audit.
3252+
3253+
**Acceptance.** `claw --resume s /providers` returns either `{kind: "providers", providers: [...]}` (Option A) or exits with structured error `unknown slash command: /providers. Did you mean /doctor?` (Option B). The `--help` line for `/providers` matches actual behavior. Test suite locks in the chosen semantic.
3254+
3255+
**Blocker.** None. The choice (implement vs remove) is the only architectural decision. Runtime has enough scaffolding that implementing is ~60 lines. Removing is ~3 lines.
3256+
3257+
**Source.** Jobdori dogfood 2026-04-18 against `/tmp/cdHH` on main HEAD `b2366d1` in response to Clawhip pinpoint nudge at `1494872623782301817`. Joins **silent-flag / documented-but-unenforced** (#96–#101, #104, #108) on the command-dispatch-semantics axis — eighth instance of "documented behavior differs from actual." Joins **unplumbed-subsystem / CLI-advertised-but-unreachable** (#78, #96, #100, #102, #103, #107, #109) as the eighth surface where the spec advertises a capability the implementation doesn't deliver. Joins **truth-audit / diagnostic-integrity** (#80–#87, #89, #100, #102, #103, #105, #107, #109, #110) — `/providers` silently returns doctor output under the wrong kind label; help lies about capability. Natural bundle: **#78 + #96 + #111** — three-way "declared but not implemented as declared" triangle (CLI route never constructed + help resume-safe leaks stubs + slash command dispatches to wrong handler). Also **#96 + #108 + #111** — full `--help`/dispatch surface hygiene quartet covering help-filter-leaks + subcommand typo fallthrough + slash-command mis-dispatch. Session tally: ROADMAP #111.

0 commit comments

Comments
 (0)