Skip to content

Commit 5c05945

Browse files
Merge remote-tracking branch 'upstream/main' into dev
2 parents ae1b108 + f1e4ad7 commit 5c05945

4 files changed

Lines changed: 380 additions & 14 deletions

File tree

ROADMAP.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5885,3 +5885,132 @@ pub fn from_cwd(cwd: impl AsRef<Path>) -> Result<Self, SessionControlError> {
58855885
**Blocker.** None.
58865886

58875887
**Source.** Q's ack on #150 surfaced the deeper gap: "#150 closed is real value" but the product function still has the brittleness. Session tally: ROADMAP #151.
5888+
5889+
## Pinpoint #152. Diagnostic verb suffixes allow arbitrary positional args, emit double "error:" prefix
5890+
5891+
**Gap.** Verbs like `claw doctor garbage` and `claw status foo bar` parse successfully instead of failing at parse time. The positional arguments fall through to the prompt-execution path, or in some cases the verb parser doesn't have a flag-only guard. Additionally, the error formatter doubles the "error:" prefix and doesn't hint at `--output-format json` for verbs that don't recognize `--json` as an alias.
5892+
5893+
**Example failures:**
5894+
- `claw doctor garbage` → silently treats "garbage" as a prompt instead of rejecting "doctor" as a verb with unexpected args
5895+
- `claw system-prompt --json` → errors with "error: unknown option" but doesn't suggest `--output-format json`
5896+
- Error messages show `error: error: <message>` (double prefix)
5897+
5898+
**Fix shape (~30 lines).** Three improvements:
5899+
1. Wire parse_verb_suffix to reject positional args after verbs (except multi-word prompts like "help me debug")
5900+
2. Special-case `--json` in the verb-option error path to suggest `--output-format json`
5901+
3. Remove the "error:" prefix from format_unknown_verb_option (already added by top-level handler)
5902+
5903+
**Acceptance:** `claw doctor garbage` exits 1 with "unexpected positional argument"; `claw system-prompt --json` hints at `--output-format json`; error messages have single "error:" prefix.
5904+
5905+
**Blocker.** None. Implementation exists on worktree `jobdori-127-verb-suffix` but needs rebase against main (conflicts with #141 which already shipped).
5906+
5907+
**Source.** Clawhip nudge 2026-04-21 21:17 KST — "no excuses, always find something to ship" directive. Session tally: ROADMAP #152.
5908+
5909+
## Pinpoint #153. README/USAGE missing "add binary to PATH" and "verify install" bridge
5910+
5911+
**Gap.** After `cargo build --workspace`, new users don't know:
5912+
1. Where the binary actually ends up (e.g., `rust/target/debug/claw` vs. expecting it in `/usr/local/bin`)
5913+
2. How to verify the build succeeded (e.g., `claw --help`, `which claw`, `claw doctor`)
5914+
3. How to add it to PATH for shell integration (optional but common follow-up)
5915+
5916+
This creates a confusing gap: users build successfully but then get "command not found: claw" and assume the build failed, or they immediately ask "how do I install this properly?"
5917+
5918+
**Real examples from #claw-code:**
5919+
- "claw not found — did the build fail?"
5920+
- "do I need to `cargo install` this?"
5921+
- "why is the binary at `rust/target/debug/claw` and not just `claw`?"
5922+
5923+
**Fix shape (~50 lines).** Add a new "Post-build verification and PATH" section in README (after Quick start) covering:
5924+
1. **Where the binary lives:** `rust/target/debug/claw` (debug build) or `rust/target/release/claw` (release)
5925+
2. **Verify it works:** Run `./rust/target/debug/claw --help` and `./rust/target/debug/claw doctor`
5926+
3. **Optional: Add to PATH** — three approaches:
5927+
- symlink: `ln -s $(pwd)/rust/target/debug/claw /usr/local/bin/claw`
5928+
- `cargo install --path ./rust` (builds and installs to `~/.cargo/bin/`)
5929+
- update shell profile to export PATH
5930+
4. **Windows equivalent:** Point to `rust\target\debug\claw.exe` and `cargo install --path .\rust`
5931+
5932+
**Acceptance:** New users can find the binary location, run it directly, and know their first verification step is `claw doctor`.
5933+
5934+
**Blocker:** None. Pure documentation.
5935+
5936+
**Source:** Clawhip nudge 2026-04-21 21:27 KST — onboarding gap from #claw-code observations earlier this month.
5937+
5938+
## Pinpoint #154. Model syntax error doesn't hint at env var when multiple credentials present
5939+
5940+
**Gap.** When a user types `claw --model gpt-4` but only has `ANTHROPIC_API_KEY` set (no `OPENAI_API_KEY`), the error is:
5941+
```
5942+
error: invalid model syntax: 'gpt-4'. Expected provider/model (e.g., anthropic/claude-opus-4-6) or known alias (opus, sonnet, haiku)
5943+
```
5944+
5945+
But USAGE.md documents that "The error message now includes a hint that names the detected env var" — **this hint is not actually emitted.** The user gets a generic syntax error and has to re-read USAGE.md to discover they should type `openai/gpt-4` instead.
5946+
5947+
**Expected behavior (from USAGE.md):** When the user has multiple providers' env vars set, or when a model name looks like it belongs to a different provider (e.g., `gpt-4` looks like OpenAI), the error should hint:
5948+
- "Did you mean `openai/gpt-4`? (but `OPENAI_API_KEY` is not set)"
5949+
- or "You have `ANTHROPIC_API_KEY` set but `gpt-4` looks like an OpenAI model. Try `openai/gpt-4` with `OPENAI_API_KEY` exported"
5950+
5951+
**Current behavior:** Generic syntax error, user has to infer the fix from USAGE.md or guess.
5952+
5953+
**Fix shape (~20 lines).** Enhance `FormatError::InvalidModelSyntax` or the model-parsing validation to:
5954+
1. Detect if the model name looks like it belongs to a known provider (prefix `gpt-`, `openai/`, `qwen`, etc.)
5955+
2. If it does, check if that provider's env var is missing
5956+
3. Append a hint: "Did you mean \`{inferred_prefix}/{model}\`? (requires `{PROVIDER_KEY}` env var)"
5957+
5958+
**Acceptance:** `claw --model gpt-4` produces a hint about OpenAI prefix and missing `OPENAI_API_KEY`. Same for `qwen-plus` → hint about `DASHSCOPE_API_KEY`, etc.
5959+
5960+
**Blocker:** None. Pure error-message UX improvement.
5961+
5962+
**Source:** Clawhip nudge 2026-04-21 21:37 KST — discovered during dogfood probing of model validation.
5963+
5964+
## Pinpoint #155. USAGE.md missing docs for `/ultraplan`, `/teleport`, `/bughunter` commands
5965+
5966+
**Gap.** The `claw --help` output lists three interactive slash commands that are not documented in USAGE.md:
5967+
- `/ultraplan [task]` — Run a deep planning prompt with multi-step reasoning
5968+
- `/teleport <symbol-or-path>` — Jump to a file or symbol by searching the workspace
5969+
- `/bughunter [scope]` — Inspect the codebase for likely bugs
5970+
5971+
New users see these commands in the help output but have no explanation of:
5972+
1. What each does
5973+
2. How to use it
5974+
3. What kind of input it expects
5975+
4. When to use it (vs. other commands)
5976+
5. Any limitations or prerequisites
5977+
5978+
**Impact.** Users run `/ultraplan` or `/teleport` out of curiosity, or they skip these commands because they don't understand them. Documentation should lower the barrier to discovery.
5979+
5980+
**Fix shape (~100 lines).** Add a new section to USAGE.md after "Interactive slash commands" covering:
5981+
1. **Planning & Reasoning** — `/ultraplan [task]`
5982+
- Purpose: extended multi-step reasoning over a task
5983+
- Input: a task description or problem statement
5984+
- Output: a structured plan with steps and reasoning
5985+
- Example: `/ultraplan refactor this module to use async/await`
5986+
2. **Navigation** — `/teleport <symbol-or-path>`
5987+
- Purpose: quickly jump to a file or function by name
5988+
- Input: a symbol name (function, class, struct) or file path
5989+
- Output: the file content with that symbol highlighted
5990+
- Example: `/teleport UserService`, `/teleport src/auth.rs`
5991+
3. **Code Analysis** — `/bughunter [scope]`
5992+
- Purpose: scan the codebase for likely bugs or issues
5993+
- Input: optional scope (e.g., "src/handlers", "lib.rs")
5994+
- Output: list of suspicious patterns with explanations
5995+
- Example: `/bughunter src`, `/bughunter` (entire workspace)
5996+
5997+
**Acceptance:** Each command has a one-line description, a practical example, and expected behavior documented.
5998+
5999+
**Blocker:** None. Pure documentation.
6000+
6001+
**Source:** Clawhip nudge 2026-04-21 21:47 KST — discovered discrepancy between `claw --help` and USAGE.md coverage.
6002+
6003+
## Pinpoint #156. Error classification for text-mode output (Phase 2 of #77)
6004+
6005+
**Gap.** #77 Phase 1 added machine-readable `kind` discriminants to JSON error payloads. Text-mode errors still emit prose-only output with no structured classification.
6006+
6007+
**Impact.** Observability tools that parse stderr (e.g., log aggregators, CI error parsers) can't distinguish error classes without regex or substring matching. Phase 1 solves it for JSON consumers; Phase 2 should extend the classification to text mode.
6008+
6009+
**Fix shape (~20 lines).** Option A: Emit a `[error-kind: missing_credentials]` prefix line before the prose error so text parsers can quickly identify the class. Option B: Structured comment format like `# error_class=missing_credentials` at the end. Either way, the `kind` token should appear in text output as well.
6010+
6011+
**Acceptance.** A stderr observer can distinguish `missing_credentials` from `session_not_found` from `cli_parse` without regex-scraping the full error prose.
6012+
6013+
**Blocker.** None. Scope is small and non-breaking (adds a prefix or suffix, doesn't change existing error text).
6014+
6015+
**Source.** Clayhip nudge 2026-04-21 23:18 — dogfood surface clean, Phase 1 proven solid, natural next step is symmetry across output formats.
6016+

USAGE.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,60 @@ error: no worker state file found at .claw/worker-state.json
125125
Then rerun: claw state [--output-format json]
126126
```
127127

128+
## Advanced slash commands (Interactive REPL only)
129+
130+
These commands are available inside the interactive REPL (`claw` with no args). They extend the assistant with workspace analysis, planning, and navigation features.
131+
132+
### `/ultraplan` — Deep planning with multi-step reasoning
133+
134+
**Purpose:** Break down a complex task into steps using extended reasoning.
135+
136+
```bash
137+
# Start the REPL
138+
claw
139+
140+
# Inside the REPL
141+
/ultraplan refactor the auth module to use async/await
142+
/ultraplan design a caching layer for database queries
143+
/ultraplan analyze this module for performance bottlenecks
144+
```
145+
146+
Output: A structured plan with numbered steps, reasoning for each step, and expected outcomes. Use this when you want the assistant to think through a problem in detail before coding.
147+
148+
### `/teleport` — Jump to a file or symbol
149+
150+
**Purpose:** Quickly navigate to a file, function, class, or struct by name.
151+
152+
```bash
153+
# Jump to a symbol
154+
/teleport UserService
155+
/teleport authenticate_user
156+
/teleport RequestHandler
157+
158+
# Jump to a file
159+
/teleport src/auth.rs
160+
/teleport crates/runtime/lib.rs
161+
/teleport ./ARCHITECTURE.md
162+
```
163+
164+
Output: The file content, with the requested symbol highlighted or the file fully loaded. Useful for exploring the codebase without manually navigating directories. If multiple matches exist, the assistant shows the top candidates.
165+
166+
### `/bughunter` — Scan for likely bugs and issues
167+
168+
**Purpose:** Analyze code for common pitfalls, anti-patterns, and potential bugs.
169+
170+
```bash
171+
# Scan the entire workspace
172+
/bughunter
173+
174+
# Scan a specific directory or file
175+
/bughunter src/handlers
176+
/bughunter rust/crates/runtime
177+
/bughunter src/auth.rs
178+
```
179+
180+
Output: A list of suspicious patterns with explanations (e.g., "unchecked unwrap()", "potential race condition", "missing error handling"). Each finding includes the file, line number, and suggested fix. Use this as a first pass before a full code review.
181+
128182
## Model and permission controls
129183

130184
```bash

rust/crates/runtime/src/session_control.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ impl SessionStore {
107107
candidate
108108
} else if looks_like_path {
109109
return Err(SessionControlError::Format(
110-
format_missing_session_reference(reference),
110+
format_missing_session_reference(reference, &self.sessions_root),
111111
));
112112
} else {
113113
self.resolve_managed_path(reference)?
@@ -138,7 +138,7 @@ impl SessionStore {
138138
}
139139
}
140140
Err(SessionControlError::Format(
141-
format_missing_session_reference(session_id),
141+
format_missing_session_reference(session_id, &self.sessions_root),
142142
))
143143
}
144144

@@ -156,7 +156,7 @@ impl SessionStore {
156156
self.list_sessions()?
157157
.into_iter()
158158
.next()
159-
.ok_or_else(|| SessionControlError::Format(format_no_managed_sessions()))
159+
.ok_or_else(|| SessionControlError::Format(format_no_managed_sessions(&self.sessions_root)))
160160
}
161161

162162
pub fn load_session(
@@ -518,13 +518,23 @@ fn session_id_from_path(path: &Path) -> Option<String> {
518518
.map(ToOwned::to_owned)
519519
}
520520

521-
fn format_missing_session_reference(reference: &str) -> String {
521+
fn format_missing_session_reference(reference: &str, sessions_root: &Path) -> String {
522+
// #80: show the actual workspace-fingerprint directory instead of lying about .claw/sessions/
523+
let fingerprint_dir = sessions_root
524+
.file_name()
525+
.and_then(|f| f.to_str())
526+
.unwrap_or("<unknown>");
522527
format!(
523528
"session not found: {reference}\nHint: managed sessions live in .hackcode/sessions/. Try `{LATEST_SESSION_REFERENCE}` for the most recent session or `/session list` in the REPL."
524529
)
525530
}
526531

527-
fn format_no_managed_sessions() -> String {
532+
fn format_no_managed_sessions(sessions_root: &Path) -> String {
533+
// #80: show the actual workspace-fingerprint directory instead of lying about .claw/sessions/
534+
let fingerprint_dir = sessions_root
535+
.file_name()
536+
.and_then(|f| f.to_str())
537+
.unwrap_or("<unknown>");
528538
format!(
529539
"no managed sessions found in .hackcode/sessions/\nStart `claw` to create a session, then rerun with `--resume {LATEST_SESSION_REFERENCE}`."
530540
)

0 commit comments

Comments
 (0)