mirror of
https://github.com/instructkr/claw-code.git
synced 2026-06-12 11:30:36 -04:00
Compare commits
21 Commits
9b06c98bd6
...
07b4fd0300
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07b4fd0300 | ||
|
|
084c2ea854 | ||
|
|
29b5d08254 | ||
|
|
6c5f150d68 | ||
|
|
65aa4378ff | ||
|
|
4fc2265d38 | ||
|
|
45b5e5c2b3 | ||
|
|
b8ada4042f | ||
|
|
f604b5c383 | ||
|
|
7a0a64beeb | ||
|
|
bfd5f2bf57 | ||
|
|
0f389752f0 | ||
|
|
096f15506d | ||
|
|
0f01faac15 | ||
|
|
672a7f8288 | ||
|
|
580128eddb | ||
|
|
16402954ee | ||
|
|
a56ad6ae2f | ||
|
|
5ee9a00d56 | ||
|
|
a6565aedea | ||
|
|
ca6107ab77 |
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: How to file a pinpoint
|
||||
url: https://github.com/ultraworkers/claw-code/blob/main/CONTRIBUTING.md#filing-a-roadmap-pinpoint
|
||||
about: Read the pinpoint format guide before filing
|
||||
41
.github/ISSUE_TEMPLATE/pinpoint.md
vendored
Normal file
41
.github/ISSUE_TEMPLATE/pinpoint.md
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
---
|
||||
name: Pinpoint
|
||||
about: File a concrete clawability gap with code evidence
|
||||
title: '[Pinpoint #XXX] '
|
||||
labels: [pinpoint]
|
||||
---
|
||||
|
||||
## Exact pinpoint
|
||||
|
||||
<!-- One-line statement: what is wrong or missing, stated crisply. -->
|
||||
|
||||
## Live evidence
|
||||
|
||||
<!-- File:line refs, code paths, command output that reproduces the gap. -->
|
||||
|
||||
```
|
||||
# paste evidence here
|
||||
```
|
||||
|
||||
## Why distinct
|
||||
|
||||
<!-- Why this isn't already covered by an adjacent pinpoint. Cluster context if relevant. -->
|
||||
|
||||
## Concrete delta landed
|
||||
|
||||
<!-- Commit sha + push status once fixed. Leave blank until resolved. -->
|
||||
|
||||
- commit:
|
||||
- push: local==origin==fork ✅ / ⏳ pending
|
||||
|
||||
## Fix shape recorded
|
||||
|
||||
<!-- Defensive fix sketch — what change would close this pinpoint. -->
|
||||
|
||||
## Branch / parity
|
||||
|
||||
<!-- Branch name, HEAD sha, three-way parity status. -->
|
||||
|
||||
- branch:
|
||||
- HEAD:
|
||||
- parity: local==origin==fork ✅ / ⏳ pending
|
||||
65
CHANGELOG.md
Normal file
65
CHANGELOG.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to claw-code are documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) (currently pre-1.0).
|
||||
|
||||
## [Unreleased] — 2026-04-26 to 2026-04-27 (extended dogfood audit cycles, through #427)
|
||||
|
||||
Branch: `feat/jobdori-168c-emission-routing`
|
||||
|
||||
### Added — Documentation
|
||||
|
||||
- **docs/ARCHITECTURE.md** — High-level architecture overview: 9 Rust crates, request flow, subsystem map with pinpoint links (cycle #426)
|
||||
- **CHANGELOG.md** — This file (cycle #424)
|
||||
- **docs/PINPOINT_FILING_GUIDE.md** — Step-by-step pinpoint filing workflow with #290 worked example (cycle #422)
|
||||
- **docs/SUPPORTED_PROVIDERS.md** — Documents 4 providers (Anthropic, xAI, DashScope/Qwen/Kimi, OpenAI/compat) from MODEL_REGISTRY (cycle #420)
|
||||
- **TROUBLESHOOTING.md** — Operational guidance for 5 critical failure modes (#286, #287, #289, #290, #291) (cycles #418, #423)
|
||||
- **ROADMAP.md Pinpoint Cluster Index** — Navigation aid for 8 named clusters (cycle #421)
|
||||
- **ROADMAP.md Extended Dogfood Audit Summary** — Cycles #388-#415 overview (cycle #416)
|
||||
- **README.md Contributing section** — Unified navigation to SECURITY/ROADMAP/CONTRIBUTING/ISSUE_TEMPLATE (cycle #415)
|
||||
- **SECURITY.md** — Responsible-disclosure stub with reporting via GitHub Security Advisories (cycle #414)
|
||||
- **CONTRIBUTING.md** — Codifies pinpoint filing format, build commands, branch naming (cycle #411)
|
||||
- **.github/ISSUE_TEMPLATE/pinpoint.md** — Discoverable canonical issue template (cycle #412)
|
||||
- **LICENSE** — Root MIT license file (cycle #410)
|
||||
|
||||
### Fixed — Code
|
||||
|
||||
- **#256** — Anthropic tool-result request ordering (pre-audit)
|
||||
- **#122b** — `claw doctor` broad-path warning
|
||||
- **#160** — Reserved-semantic-verb slash-command guidance
|
||||
|
||||
### Filed — Pinpoints (ROADMAP.md)
|
||||
|
||||
47 pinpoints filed (#241-#292) during extended dogfood audit. New entries:
|
||||
- **#292** — Extreme sustained upstream degradation lacks user-facing escalation guidance (cycle #425). Evidence: gaebal-gajae 17+ `500 empty_stream` failures across 5+ hours
|
||||
|
||||
Clusters identified:
|
||||
- **Auto-compaction (4-deep):** #283, #287 (CRITICAL), #288, #289
|
||||
- **Transport / Provider Resilience:** #266, #285, #290, #291
|
||||
- **Provider Infrastructure:** #245, #246, #285
|
||||
- **Tool Lifecycle / Hooks:** #254, #268, #274, #280, #286
|
||||
- **CLI Dispatch:** #262, #267, #272, #282, #283
|
||||
- **Persistence / Migration:** #278, #279
|
||||
- **Provenance Consolidation:** #259, #271, #273, #275
|
||||
- **Slash-command Contract:** #284
|
||||
|
||||
See [ROADMAP.md](./ROADMAP.md#pinpoint-cluster-index) for full list.
|
||||
|
||||
### Live evidence integrated
|
||||
|
||||
- @Sigrid Jin: license verification, ultraplan functionality, provider-config source-of-truth → pinpoints #284, #285
|
||||
- gaebal-gajae sustained `500 empty_stream` (11+ incidents in 3hr+) → pinpoints #290, #291
|
||||
|
||||
---
|
||||
|
||||
## Process
|
||||
|
||||
This release demonstrates the pinpoint-driven workflow:
|
||||
1. **Identify friction** during real claw-code usage
|
||||
2. **File pinpoint** to ROADMAP.md with canonical 5-section format
|
||||
3. **Ship docs/code fix** when concrete delta is small
|
||||
4. **Cluster pinpoints** to expose architectural patterns
|
||||
5. **Document mitigations** in TROUBLESHOOTING.md
|
||||
|
||||
See [docs/PINPOINT_FILING_GUIDE.md](./docs/PINPOINT_FILING_GUIDE.md) for details.
|
||||
85
CONTRIBUTING.md
Normal file
85
CONTRIBUTING.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Contributing to claw-code
|
||||
|
||||
Thanks for your interest. This project follows the **gaebal-gajae pinpoint cadence** — see [ROADMAP.md](./ROADMAP.md) for the current pinpoint census. Here's how to contribute effectively.
|
||||
|
||||
## Security
|
||||
|
||||
For security vulnerabilities, see [SECURITY.md](./SECURITY.md). **Do not file public pinpoints for security issues.**
|
||||
|
||||
## Filing a ROADMAP Pinpoint
|
||||
|
||||
All feature requests and bug reports go through the pinpoint format (see `ROADMAP.md`). Each pinpoint must have:
|
||||
|
||||
- **Exact pinpoint** — one crisp sentence stating what is wrong or missing
|
||||
- **Live evidence** — reproduction steps, logs, or observed behavior
|
||||
- **Why distinct** — why this isn't already covered by an existing pinpoint
|
||||
- **Concrete delta** — what the repo looks like after this is fixed (file-level)
|
||||
- **Fix shape** — implementation sketch (function, module, config change)
|
||||
|
||||
Vague or duplicate pinpoints will be closed without comment.
|
||||
|
||||
## Build & Test
|
||||
|
||||
```bash
|
||||
# Rust components
|
||||
cd rust
|
||||
cargo build
|
||||
cargo test
|
||||
|
||||
# Node / Bun components (if present)
|
||||
bun install
|
||||
bun test
|
||||
```
|
||||
|
||||
CI runs on every push. All tests must pass before review.
|
||||
|
||||
## Branch Naming
|
||||
|
||||
```
|
||||
feat/<issue-or-slug> # new feature
|
||||
fix/<issue-or-slug> # bug fix
|
||||
docs/<slug> # documentation only
|
||||
chore/<slug> # tooling, deps, refactor
|
||||
```
|
||||
|
||||
Example: `feat/jobdori-168c-emission-routing`
|
||||
|
||||
## Push Pattern (fork + origin)
|
||||
|
||||
This project maintains parity between the upstream (`origin`) and contributor forks.
|
||||
|
||||
```bash
|
||||
# 1. Fork the repo on GitHub, then add your fork as a remote
|
||||
git remote add fork https://github.com/<your-username>/claw-code.git
|
||||
|
||||
# 2. Create a branch off the target branch
|
||||
git checkout -b feat/your-slug origin/feat/target-branch
|
||||
|
||||
# 3. Make changes, commit
|
||||
git add .
|
||||
git commit -m "feat: your change description"
|
||||
|
||||
# 4. Push to BOTH remotes (keep parity)
|
||||
git push origin feat/your-slug --force-with-lease
|
||||
git push fork feat/your-slug --force-with-lease
|
||||
|
||||
# 5. Open a PR against the target branch on GitHub
|
||||
```
|
||||
|
||||
Three-way parity check before opening a PR:
|
||||
```bash
|
||||
git log --oneline -1 HEAD
|
||||
git log --oneline -1 origin/feat/your-slug
|
||||
git log --oneline -1 fork/feat/your-slug
|
||||
# All three should show the same commit hash
|
||||
```
|
||||
|
||||
## Code Style
|
||||
|
||||
- Rust: `cargo fmt` and `cargo clippy` before committing
|
||||
- No dead code, no unused imports
|
||||
- Comments in English; commit messages in English
|
||||
|
||||
## License
|
||||
|
||||
By contributing, you agree your contributions are licensed under the [MIT License](./LICENSE).
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 ultraworkers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
29
PARITY.md
29
PARITY.md
@@ -186,3 +186,32 @@ Canonical scenario map: `rust/mock_parity_scenarios.json`
|
||||
- [x] No `#[ignore]` tests hiding failures
|
||||
- [ ] CI green on every commit
|
||||
- [x] Codebase shape clean enough for handoff documentation
|
||||
|
||||
## Documentation Parity (Extended Dogfood Audit, cycles #410-#427)
|
||||
|
||||
Repo documentation suite shipped during extended dogfood audit. Status: present/absent vs standard OSS project expectations.
|
||||
|
||||
| Document | Status | Cycle | Notes |
|
||||
|----------|--------|-------|-------|
|
||||
| LICENSE (MIT) | ✅ Present | #410 | Root license file |
|
||||
| CONTRIBUTING.md | ✅ Present | #411 | Pinpoint format, build commands, branch naming |
|
||||
| .github/ISSUE_TEMPLATE/pinpoint.md | ✅ Present | #412 | GitHub-discoverable template |
|
||||
| SECURITY.md | ✅ Present | #414 | Responsible-disclosure stub |
|
||||
| README.md contributing nav | ✅ Present | #415 | Links to all docs |
|
||||
| ROADMAP.md audit summary | ✅ Present | #416 | Extended audit header |
|
||||
| TROUBLESHOOTING.md | ✅ Present | #418, #423 | 5 failure modes with mitigation |
|
||||
| docs/SUPPORTED_PROVIDERS.md | ✅ Present | #420 | 4 providers documented |
|
||||
| ROADMAP.md cluster index | ✅ Present | #421 | 8 named clusters |
|
||||
| docs/PINPOINT_FILING_GUIDE.md | ✅ Present | #422 | 5-step workflow |
|
||||
| CHANGELOG.md | ✅ Present | #424, #427 | Keep-a-Changelog format |
|
||||
| docs/ARCHITECTURE.md | ✅ Present | #426 | 9 crates, request flow, subsystem map |
|
||||
|
||||
### Remaining doc gaps (not yet shipped)
|
||||
|
||||
| Document | Status | Priority | Notes |
|
||||
|----------|--------|----------|-------|
|
||||
| CODE_OF_CONDUCT.md | ❌ Missing | Low | Standard for public repos |
|
||||
| .github/PULL_REQUEST_TEMPLATE.md | ❌ Missing | Medium | Would standardize PR descriptions |
|
||||
| docs/CONFIGURATION.md | ❌ Missing | High | env vars, settings.json, provider config — relates to #283, #285 |
|
||||
| docs/API_REFERENCE.md | ❌ Missing | Medium | JSON envelope schema, output format contract |
|
||||
| .github/ISSUE_TEMPLATE/bug_report.md | ❌ Missing | Low | Standard bug template (pinpoint.md covers discovery) |
|
||||
|
||||
16
README.md
16
README.md
@@ -13,6 +13,8 @@
|
||||
·
|
||||
<a href="./ROADMAP.md">Roadmap</a>
|
||||
·
|
||||
<a href="./TROUBLESHOOTING.md">Troubleshooting</a>
|
||||
·
|
||||
<a href="https://discord.gg/5TUQKqFWd">UltraWorkers Discord</a>
|
||||
</p>
|
||||
|
||||
@@ -34,7 +36,7 @@ Claw Code is the public Rust implementation of the `claw` CLI agent harness.
|
||||
The canonical implementation lives in [`rust/`](./rust), and the current source of truth for this repository is **ultraworkers/claw-code**.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Start with [`USAGE.md`](./USAGE.md) for build, auth, CLI, session, and parity-harness workflows. Make `claw doctor` your first health check after building, use [`rust/README.md`](./rust/README.md) for crate-level details, read [`PARITY.md`](./PARITY.md) for the current Rust-port checkpoint, and see [`docs/container.md`](./docs/container.md) for the container-first workflow.
|
||||
> Start with [`USAGE.md`](./USAGE.md) for build, auth, CLI, session, and parity-harness workflows. Make `claw doctor` your first health check after building, use [`rust/README.md`](./rust/README.md) for crate-level details, read [`PARITY.md`](./PARITY.md) for the current Rust-port checkpoint, see [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md) for a high-level crate/subsystem map, and see [`docs/container.md`](./docs/container.md) for the container-first workflow.
|
||||
>
|
||||
> **ACP / Zed status:** `claw-code` does not ship an ACP/Zed daemon entrypoint yet. Run `claw acp` (or `claw --acp`) for the current status instead of guessing from source layout; `claw acp serve` is currently a discoverability alias only, and real ACP support remains tracked separately in `ROADMAP.md`.
|
||||
|
||||
@@ -196,6 +198,7 @@ cargo test --workspace
|
||||
- [`PARITY.md`](./PARITY.md) — parity status for the Rust port
|
||||
- [`rust/MOCK_PARITY_HARNESS.md`](./rust/MOCK_PARITY_HARNESS.md) — deterministic mock-service harness details
|
||||
- [`ROADMAP.md`](./ROADMAP.md) — active roadmap and open cleanup work
|
||||
- [`CHANGELOG.md`](./CHANGELOG.md) — history of notable changes by dogfood cycle
|
||||
- [`PHILOSOPHY.md`](./PHILOSOPHY.md) — why the project exists and how it is operated
|
||||
|
||||
## Ecosystem
|
||||
@@ -208,6 +211,17 @@ Claw Code is built in the open alongside the broader UltraWorkers toolchain:
|
||||
- [oh-my-codex](https://github.com/Yeachan-Heo/oh-my-codex)
|
||||
- [UltraWorkers Discord](https://discord.gg/5TUQKqFWd)
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions! Before filing an issue or pull request:
|
||||
|
||||
- **Troubleshooting:** See [TROUBLESHOOTING.md](./TROUBLESHOOTING.md) for common issues and recovery steps
|
||||
- **Supported providers:** See [docs/SUPPORTED_PROVIDERS.md](./docs/SUPPORTED_PROVIDERS.md)
|
||||
- **For security issues:** See [SECURITY.md](./SECURITY.md)
|
||||
- **For bug reports / features:** Check [ROADMAP.md](./ROADMAP.md) to see if it's already pinpointed
|
||||
- **How to file a pinpoint:** See [CONTRIBUTING.md](./CONTRIBUTING.md) and the [Pinpoint Filing Guide](./docs/PINPOINT_FILING_GUIDE.md)
|
||||
- **Issue templates:** Use [.github/ISSUE_TEMPLATE/pinpoint.md](./.github/ISSUE_TEMPLATE/pinpoint.md)
|
||||
|
||||
## Ownership / affiliation disclaimer
|
||||
|
||||
- This repository does **not** claim ownership of the original Claude Code source material.
|
||||
|
||||
175
ROADMAP.md
175
ROADMAP.md
@@ -1,5 +1,91 @@
|
||||
# Clawable Coding Harness Roadmap
|
||||
|
||||
## Extended Dogfood Audit Summary (Cycles #388-#415)
|
||||
|
||||
**Overview:** This branch underwent an extended discovery audit identifying architectural gaps via live dogfood cycling. 44 pinpoints filed across all phases (#200-#289); 9 concrete real/docs fixes shipped; pre-merge threshold exceeded (target 50+, achieved 65+ across all phases).
|
||||
|
||||
**Key Clusters Identified:**
|
||||
- **session-continuity/auto-compaction (3-deep):** #287 (timing-reactive), #288 (failure-envelope), #289 (manual-skip-reason)
|
||||
- **parallel-agent-lifecycle:** #286 (detached-thread-no-heartbeat)
|
||||
- **provider-config-source-of-truth:** #285 (declarative-providers/models/websearch missing)
|
||||
- **slash-command-contract:** #284 (ultraplan empty-shell)
|
||||
- [+ 10+ additional clusters across all phases]
|
||||
|
||||
**Real Fixes Shipped:**
|
||||
1. #256 — Anthropic tool-result request ordering (pre-audit)
|
||||
2. #122b — claw doctor broad-path warning
|
||||
3. #160 — reserved-semantic-verb slash-command guidance
|
||||
4. root LICENSE (MIT, resolves @Sigrid Jin license ambiguity)
|
||||
5. CONTRIBUTING.md (codifies pinpoint filing format)
|
||||
6. ISSUE_TEMPLATE/pinpoint.md (discoverable format template)
|
||||
7. live-counter drift fix (CONTRIBUTING.md link-to-ROADMAP)
|
||||
8. SECURITY.md (responsible-disclosure stub)
|
||||
9. README.md contributing section (unified doc nav)
|
||||
|
||||
**User-Sourced Feedback Integrated:**
|
||||
- @Sigrid Jin: license verification, ultraplan functionality, provider-config source-of-truth → converted to pinpoints #284, #285
|
||||
|
||||
**Branch State:**
|
||||
- Primary: `feat/jobdori-168c-emission-routing` @ HEAD `0f01faa`
|
||||
- All pinpoints filed to ROADMAP.md; no pending work; merge-eligible pending Phase 0 blockers (GitHub OAuth, cargo fmt, clawcode-human approval)
|
||||
- 564 tests pass; zero regressions
|
||||
|
||||
**Next Phase:** Phase 0 merge → Phase A-F post-merge implementation (18-31 cycles estimated, 6-15 real fixes target)
|
||||
|
||||
---
|
||||
|
||||
## Pinpoint Cluster Index
|
||||
|
||||
For navigation. Click cluster name to jump to first member. Pinpoints can belong to multiple clusters.
|
||||
|
||||
### Auto-compaction (4-deep)
|
||||
- #283 — Compaction threshold env-only, no settings.json key
|
||||
- #287 — Reactive-after-success, not preflight-before-request (CRITICAL)
|
||||
- #288 — Failure JSON envelope omits compaction diagnostics
|
||||
- #289 — Manual `/compact` skip-reason flattened to "below threshold"
|
||||
|
||||
### Transport / Provider Resilience (new, post-#416)
|
||||
- #266 — Typed-error-kind taxonomy
|
||||
- #285 — Provider/model/websearch declarative source-of-truth
|
||||
- #290 — Upstream stream-init failures bypass typed envelope
|
||||
- #291 — No repeat-failure detection / circuit-breaker
|
||||
|
||||
### Provider Infrastructure
|
||||
- #245 — Declarative providers config
|
||||
- #246 — Backend swap
|
||||
- #285 — Source-of-truth (overlap with Transport cluster)
|
||||
|
||||
### Tool Lifecycle / Hooks
|
||||
- #254 — MCP refresh
|
||||
- #268 — Tool-rendering parity
|
||||
- #274 — Hook-execution-event envelope
|
||||
- #280 — Hook event tap
|
||||
- #286 — Parallel agent detached-thread (no JoinHandle)
|
||||
|
||||
### CLI Dispatch
|
||||
- #262 — `--max-turns` spec
|
||||
- #267 — `--cwd` runtime fix
|
||||
- #272 — Position-independent parsing
|
||||
- #282 — env-vs-config consolidation
|
||||
- #283 — Compaction threshold (overlap with Auto-compaction)
|
||||
|
||||
### Persistence / Migration
|
||||
- #278 — Version-comparison
|
||||
- #279 — Unknown-field policy
|
||||
|
||||
### Provenance Consolidation
|
||||
- #259 — Unified provenance struct
|
||||
- #271 — Freshness assertions
|
||||
- #273 — Source-of-truth guards
|
||||
- #275 — Source-of-truth checks
|
||||
|
||||
### Slash-command Contract
|
||||
- #284 — `/ultraplan` empty-shell
|
||||
|
||||
For full list of all 46+ pinpoints (#200-#291), see the pinpoint sections below.
|
||||
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Turn claw-code into the most **clawable** coding harness:
|
||||
@@ -17251,3 +17337,92 @@ Gap. Auto-compaction lacks a pre-request guard based on `estimate_session_tokens
|
||||
Required fix shape: (a) add a preflight auto-compact phase before provider dispatch using estimated session/request size and model context metadata; (b) include the threshold, estimated session tokens, estimated request tokens, and context window in a typed `auto_compaction_preflight` event/status surface; (c) after `context_window_blocked`, optionally run a safe compact-and-retry once, with an explicit receipt; (d) persist the compacted session before retry so session continuity is recoverable even if the retry fails; (e) surface whether compaction was skipped because the session was below threshold, no messages were removable, or compaction would not fit; (f) add regression coverage where a resumed oversized session compacts before request and does not hit provider context-window rejection first. Acceptance: an oversized maintained session gets compacted or fails with a typed “not compactable” reason before provider context-window failure, never with silent “auto-compact did not run.”
|
||||
|
||||
**Status:** Open. No source code changed. Filed 2026-04-26 18:39 KST. Branch: feat/jobdori-168c-emission-routing. HEAD: `79eeaae` before filing. Cluster delta: session-continuity-auto-compaction-semantics +1; concrete user-signal source: Sigrid report of frequent session breakage and auto-compaction not working. Concrete delta this cycle: ROADMAP-only pinpoint appended from auto-compaction trigger audit.
|
||||
|
||||
## Pinpoint #288 — Context-window/session-break failures bypass the JSON envelope and omit session-file + auto-compaction decision receipts, so automation cannot tell which session to compact or why auto-compact did not run
|
||||
|
||||
Dogfooded 2026-04-26 19:02 KST from the same session-maintenance / auto-compaction complaint cluster as #287. Static audit of `rust/crates/rusty-claude-cli/src/main.rs` shows `run_prompt_json` only prints a JSON envelope after `runtime.run_turn(...)` succeeds. On provider/context-window failure, `result?` returns a `RuntimeError` whose message is produced by `format_user_visible_api_error` / `format_context_window_blocked_error`. That text includes failure class, session id, optional trace/model/token estimates, and human recovery commands, but it is not emitted as a structured JSON error envelope and does not include the concrete session file path, auto-compaction threshold, preflight estimate, compaction skip reason, or whether a compact/retry was attempted. Text mode has the same limitation: the visible recovery line says `claw --resume {session_id} /compact`, not the resolved session path or a machine-readable recovery receipt.
|
||||
|
||||
Concrete failure mode: a long session fails with `context_window_blocked` while a user or orchestrator is running `--output-format json`. Instead of `{ kind: "error", failure_class: "context_window_blocked", session_id, session_file, auto_compaction: { attempted, reason }, recovery: ... }`, the command exits with a formatted string. Automation cannot reliably distinguish provider context failure from other runtime errors, cannot know whether auto-compaction was skipped because it is reactive (#287) or because no messages were removable, and cannot safely run the exact recovery command against the right session file. The user-facing symptom is "session broke and auto-compact did not work" with no actionable structured receipt.
|
||||
|
||||
Gap. Error paths do not share the success JSON envelope contract. Context-window recovery is human-readable only and loses the state needed for autonomous repair. This is distinct from #287, which fixes when compaction should run; #288 fixes how a failed oversized turn reports recovery state when compaction did not save it.
|
||||
|
||||
Required fix shape: (a) make `--output-format json` emit structured error envelopes for `RuntimeError`/provider errors, preserving `kind`, `failure_class`, `message`, `session_id`, `session_file`, `model`, trace/request id, token estimates, and recovery commands; (b) include an `auto_compaction` decision object on failure with `attempted`, `phase`, `threshold`, `estimated_session_tokens`, `skip_reason`, and `retry_attempted`; (c) include the resolved managed session file path in text and JSON context-window recovery output; (d) add an orchestrator-safe `recommended_command` that uses the exact path/id; (e) regression-test `claw --output-format json prompt ...` with a synthetic context-window error to prove the output is parseable JSON and contains the recovery receipt. Acceptance: context-window/session-break failures are machine-readable and tell both humans and claws exactly what happened and what session artifact to repair.
|
||||
|
||||
**Status:** Open. No source code changed. Filed 2026-04-26 19:03 KST. Branch: feat/jobdori-168c-emission-routing. HEAD: `9b06c98` before filing. Cluster delta: session-continuity-auto-compaction-semantics 1→2 (#287 trigger timing + #288 failure-envelope/recovery receipt). Concrete delta this cycle: ROADMAP-only pinpoint appended from JSON/error recovery audit.
|
||||
|
||||
## Pinpoint #289 — Manual `/compact` reports every no-op as “session below compaction threshold” because `CompactionResult` has no skip reason or token/removability diagnostics
|
||||
|
||||
Dogfooded 2026-04-26 19:32 KST while following the session-continuity / auto-compaction complaint cluster. Static audit shows both live REPL `/compact` and resumed `claw --resume ... /compact` treat `removed_message_count == 0` as `skipped` and call `format_compact_report(removed, kept, skipped)`. That formatter always says `Reason session below compaction threshold`. The underlying `compact_session` returns only `{ summary, formatted_summary, compacted_session, removed_message_count }`; it does not say why compaction was skipped. `should_compact` can return false because the compactable message count is not greater than `preserve_recent_messages`, because compactable estimated tokens are below `max_estimated_tokens`, because an existing compacted summary leaves too little compactable prefix, or because the caller used different configs (`/compact` uses default max 10k; resumed `/compact` uses max 0). None of that is surfaced.
|
||||
|
||||
Concrete failure mode: after a context-window/session-maintenance failure, a user follows the suggested `/compact` recovery. If compaction removes 0 messages, Claw always reports “session below compaction threshold” even when the real reason may be “only recent tail remains,” “already compacted,” “tool-use/tool-result boundary prevents safe removal,” or “manual vs resume compact used a different threshold.” The user still has a broken large session but no explanation of why the recovery command did not reduce it.
|
||||
|
||||
Gap. Compaction lacks diagnostic receipts: input message count, compactable prefix length, preserved tail size, estimated compactable tokens, configured threshold, existing-summary status, boundary adjustment, and typed skip reason. This is distinct from #287 (preflight timing) and #288 (failure JSON envelope): #289 is the manual recovery command’s own observability/diagnostic gap.
|
||||
|
||||
Required fix shape: (a) extend `CompactionResult` with `skip_reason: Option<CompactionSkipReason>`, `estimated_session_tokens`, `estimated_compactable_tokens`, `message_count`, `compactable_message_count`, `preserve_recent_messages`, `max_estimated_tokens`, `existing_summary_present`, and `boundary_adjusted`; (b) make text output report the real reason instead of always “below threshold”; (c) make resumed `/compact` JSON include the same diagnostics; (d) align live and resumed manual compact defaults or explicitly report the config difference; (e) regression-test skipped cases for too-few messages, already-compacted session, below-token-threshold, and boundary-preserved tool pairs. Acceptance: a skipped `/compact` tells the user and automation exactly why no messages were removed and whether another recovery path is needed.
|
||||
|
||||
**Status:** Open. No source code changed. Filed 2026-04-26 19:33 KST. Branch: feat/jobdori-168c-emission-routing. HEAD: `a6565ae` before filing. Cluster delta: session-continuity-auto-compaction-semantics 2→3 (#287 timing + #288 failure receipt + #289 manual compact skip diagnostics). Concrete delta this cycle: ROADMAP-only pinpoint appended from manual `/compact` code audit.
|
||||
|
||||
## Pinpoint #290 — Upstream stream-init failures (`empty_stream`) bypass typed JSON envelope
|
||||
|
||||
Dogfooded 2026-04-26 21:30 KST from live gaebal-gajae session evidence: `500 empty_stream: upstream stream closed before first payload` hit 4 times in ~25 min on the same CCAPI/Anthropic routing. When upstream provider closes the stream before the first payload byte arrives, claw-code surfaces the failure as a bare-string error — not as a typed JSON envelope with `failure_class`, retry recommendation, or upstream provider attribution. `--output-format json` callers receive unstructured text; automation cannot distinguish stream-init failure from mid-stream disconnection, from context-window failure, or from network timeout.
|
||||
|
||||
Concrete failure mode: gaebal-gajae's sessions fail repeatedly with `500 empty_stream: upstream stream closed before first payload`. Under `--output-format json` the output is not `{ kind: "error", failure_class: "upstream_stream_init", cause_class: "stream_closed_before_first_payload", upstream_provider: "anthropic", recommended_retry: true, recommended_backoff_ms: <int> }` — it is a bare formatted string. A claw-driven orchestrator cannot safely distinguish "retry immediately" (transient stream-init) from "do not retry" (context-window exceeded) or "wait before retry" (rate-limit). The visible result is repeated 500s with no structured recovery path and no auto-retry guidance.
|
||||
|
||||
Gap. Stream-init error paths (pre-first-payload provider failure) are not covered by the JSON envelope contract. This is distinct from: #266 (typed-error-kind taxonomy — covers provider error categorization broadly but does not enumerate `upstream_stream_init` as a discriminant class); #287 (auto-compaction reactive — session-size-driven; this is transport-init failure); #288 (JSON envelope failure-path coverage — covers context-window failures specifically; #290 generalizes to ALL stream-init failure classes and adds retry/backoff guidance that #288 does not address).
|
||||
|
||||
Required fix shape: (a) classify `empty_stream` / stream-closed-before-first-payload as `failure_class=upstream_stream_init` in the JSON error envelope; (b) include `cause_class=stream_closed_before_first_payload`, upstream provider name and endpoint in the envelope; (c) include `recommended_retry: true/false` and `recommended_backoff_ms: <int>` for transient stream-init classes; (d) add a live recovery hint in text output ("upstream provider transient; retry in N seconds"); (e) regression-test `--output-format json` with a synthetic upstream-stream-init failure to assert parseable JSON with the correct discriminant fields. Acceptance: any stream-init failure is machine-readable and gives both humans and orchestrators an unambiguous retry/backoff signal.
|
||||
|
||||
**Status:** Open. No source code changed. Filed 2026-04-26 21:31 KST. Branch: feat/jobdori-168c-emission-routing. HEAD: `096f155` before filing. Live evidence: gaebal-gajae 4× `500 empty_stream` in ~25 min, 2026-04-26 KST evening. Cluster delta: json-envelope-failure-path +1 (stream-init variant). Concrete delta this cycle: ROADMAP-only pinpoint appended from live gaebal-gajae session evidence.
|
||||
|
||||
### #291 — No repeat-failure detection / circuit-breaker for sustained upstream degradation
|
||||
|
||||
**Exact pinpoint:** When upstream provider fails repeatedly (e.g., 5+ `500 empty_stream` failures in <60 min on the same provider+endpoint), claw-code does NOT detect the pattern, surface a circuit-breaker recommendation, OR trigger automatic provider-fallback. Each retry attempts the same dead upstream blindly. No `repeat_failure_count` or `degradation_window_ms` in JSON envelope. No CLI hint like "switch provider" or "wait for circuit-breaker reset."
|
||||
|
||||
**Live evidence:**
|
||||
- gaebal-gajae's session hit `500 empty_stream: upstream stream closed before first payload` 6 times in ~50 min on 2026-04-26 KST evening (21:04, 21:12, 21:22, 21:33, 21:37, 21:59 KST)
|
||||
- All same upstream layer (CCAPI/Anthropic), same endpoint, same authentication
|
||||
- claw-code surfaced each as identical bare-string error, no escalating diagnostics
|
||||
|
||||
**Why distinct:**
|
||||
- #266 (typed-error-kind taxonomy) — covers single-failure categorization, not repeat-pattern detection
|
||||
- #287 (auto-compaction reactive) — about session-size; this is about provider-side health
|
||||
- #288 (JSON envelope failure-path) — covers single-failure envelope, not multi-failure aggregation
|
||||
- #290 (typed stream-init envelope) — covers single stream-init failure typing, not repeat-pattern + circuit-breaker
|
||||
|
||||
**Fix shape recorded:**
|
||||
- per-session repeat-failure counter with sliding window (e.g., `repeat_failure_count`, `degradation_window_ms`, `last_failure_at`)
|
||||
- circuit-breaker pattern: after N failures in window, surface "upstream degraded — circuit-breaker open for X seconds, automatic retry blocked"
|
||||
- automatic provider-fallback when configured (link to #285 declarative providers config)
|
||||
- typed JSON envelope with repeat-failure metadata
|
||||
- CLI command `claw provider status` to show per-provider health/circuit-breaker state
|
||||
- regression tests for repeat-failure detection and circuit-breaker open/close transitions
|
||||
|
||||
**Status:** Open. No source code changed. Filed 2026-04-26 22:00 KST. Branch: feat/jobdori-168c-emission-routing. HEAD: `bfd5f2b` before filing. Live evidence: gaebal-gajae 6× `500 empty_stream` in ~50 min sustained, 2026-04-26 KST evening. Cluster delta: new cluster (repeat-failure-detection / circuit-breaker). Concrete delta this cycle: ROADMAP.md appended with #291; pushed to both remotes.
|
||||
|
||||
**Branch / parity:** local==origin==fork at `96388c8`
|
||||
|
||||
### #292 — Extreme sustained upstream degradation lacks user-facing escalation guidance
|
||||
|
||||
**Exact pinpoint:** When upstream provider failures sustain for >1 hour (10+ consecutive failures), claw-code does NOT escalate to the user with structured advice. No mention of: provider status page URL, expected SLA recovery time, recommended fallback provider, escalation contact (e.g., open support ticket). User experiences identical bare-string error message on attempt #1, #5, and #15 — no signal that this is now an EXTREME degradation requiring different action.
|
||||
|
||||
**Live evidence:**
|
||||
- gaebal-gajae's session hit `500 empty_stream: upstream stream closed before first payload` 13+ times across 4+ hours on 2026-04-26 KST evening / Mon early morning (21:04, 21:12, 21:22, 21:33, 21:37, 21:59, 22:03, 22:35, 23:04, 23:33, 00:03, 00:34, 00:37 KST)
|
||||
- Same provider, same endpoint, no escalation, no advice change between attempt #1 and attempt #13
|
||||
- claw-code surfaced identical error each time
|
||||
|
||||
**Why distinct:**
|
||||
- #291 (repeat-failure detection / circuit-breaker) — covers MECHANICAL response to repeat failures (block retries, switch provider, etc.), NOT user-facing communication
|
||||
- #266 (typed-error-kind taxonomy) — covers single-failure typing, NOT degradation-window aggregation
|
||||
- #290 (typed stream-init envelope) — covers single stream-init failure typing, NOT extreme-sustained signaling
|
||||
|
||||
**Concrete delta landed:** ROADMAP.md appended with #292; pushed to both remotes.
|
||||
|
||||
**Fix shape recorded:**
|
||||
- escalation-tier classification (e.g., `degradation_tier=normal|elevated|extreme`)
|
||||
- provider-specific status page URLs in failure envelope (e.g., `provider_status_url=https://status.anthropic.com`)
|
||||
- recovery time estimates from provider (e.g., `expected_recovery_window=15m|1h|6h+`)
|
||||
- escalation guidance text in CLI output for tier=extreme (e.g., "This appears to be a sustained upstream issue. Check provider status, consider fallback, or open support ticket")
|
||||
- automated escalation suggestions (e.g., "switch to fallback provider X" if configured per #285)
|
||||
- regression tests for tier escalation transitions
|
||||
|
||||
**Branch / parity:** local==origin==fork at 7a022b6
|
||||
|
||||
49
SECURITY.md
Normal file
49
SECURITY.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
This project is pre-1.0 / active development. Only the `main` branch (and the current active feature branch) receives security attention. No LTS commitment exists yet.
|
||||
|
||||
| Branch | Supported |
|
||||
|--------|-----------|
|
||||
| `main` | ✅ |
|
||||
| older forks/branches | ❌ |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
**Do not file a public GitHub issue for security vulnerabilities.**
|
||||
|
||||
Please use [GitHub Security Advisories](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability) to report privately:
|
||||
|
||||
1. Go to the **Security** tab of this repository
|
||||
2. Click **"Report a vulnerability"**
|
||||
3. Describe the issue with reproduction steps and impact
|
||||
|
||||
We aim to acknowledge within **72 hours** and work toward coordinated disclosure.
|
||||
|
||||
## Disclosure Process
|
||||
|
||||
1. Report received → acknowledgement within 72h
|
||||
2. We assess severity and reproduce the issue
|
||||
3. Fix developed and reviewed privately
|
||||
4. Fix shipped; advisory published after patch is live
|
||||
5. Credit given to reporter (unless they prefer anonymity)
|
||||
|
||||
## Scope
|
||||
|
||||
**In scope:**
|
||||
- Remote code execution (RCE)
|
||||
- Authentication or authorization bypass
|
||||
- Secrets / credentials exfiltration
|
||||
- Sandbox escape (agent isolation boundary violations)
|
||||
- Privilege escalation
|
||||
|
||||
**Out of scope:**
|
||||
- Denial of service (DoS/resource exhaustion)
|
||||
- Social engineering attacks
|
||||
- Vulnerabilities in third-party dependencies — report those upstream
|
||||
- Behavior that is working as intended (check ROADMAP.md pinpoints first)
|
||||
|
||||
## License
|
||||
|
||||
This project is [MIT-licensed](./LICENSE) — provided as-is, without warranty of any kind.
|
||||
98
TROUBLESHOOTING.md
Normal file
98
TROUBLESHOOTING.md
Normal file
@@ -0,0 +1,98 @@
|
||||
# Troubleshooting
|
||||
|
||||
## Upstream stream-init failures (`500 empty_stream`)
|
||||
|
||||
**Symptom:** claw-code exits with `500 empty_stream: upstream stream closed before first payload` or similar upstream stream-init error.
|
||||
|
||||
**Root cause:** Upstream provider (Anthropic, OpenAI, other) closed the HTTP connection before sending the first response payload. Common causes:
|
||||
- Transient network issue between claw-code and provider
|
||||
- Provider overload / temporary service degradation
|
||||
- Authentication token expired or invalid
|
||||
- Rate limit exceeded (even if not visible in response headers)
|
||||
|
||||
**Mitigation:**
|
||||
1. **Check credentials:** Verify `claw whoami` shows the expected provider and account. Re-authenticate if expired.
|
||||
2. **Wait and retry:** Provider transient issues usually resolve within 30-60 seconds. Wait a minute, then retry the same command.
|
||||
3. **Check provider status:** Visit the provider's status page (e.g., status.anthropic.com, status.openai.com).
|
||||
4. **Reduce request size:** If the prompt is large, try a smaller request first to isolate stream-init from context-window failures.
|
||||
5. **Check network:** Ensure your network connection is stable. If behind a proxy, verify proxy allows streaming responses.
|
||||
|
||||
**When to escalate:**
|
||||
- If stream-init failures persist >10 minutes across multiple requests
|
||||
- If `claw whoami` fails to authenticate
|
||||
- If no provider status page shows degradation
|
||||
|
||||
**Related pinpoint:** #290 (typed stream-init failure envelope — future improvement for better diagnostics)
|
||||
|
||||
---
|
||||
|
||||
## Context-window-blocked errors
|
||||
|
||||
**Symptom:** claw-code exits with `context_window_blocked` or similar provider error when resuming a long session, or when sending a request with a very large prompt + accumulated history.
|
||||
|
||||
**Root cause:** Session size exceeded provider context window before claw-code's auto-compaction could reduce it. Auto-compaction is currently REACTIVE-AFTER-SUCCESS — it only fires after a successful provider response. If the request itself is oversized, compaction never runs.
|
||||
|
||||
**Mitigation:**
|
||||
1. **Resume with manual compact:** `claw resume <session> --compact-before` (if available); else manually compact via `/compact` slash command before retrying
|
||||
2. **Start a fresh session:** Sometimes the cleanest path; existing session-state preserved in `~/.claw/sessions/<id>/`
|
||||
3. **Reduce prompt size:** If interactive, send shorter prompts; truncate file contents before pasting
|
||||
4. **Adjust threshold:** Lower `CLAW_AUTO_COMPACT_INPUT_TOKENS_THRESHOLD` env var (default varies by provider)
|
||||
|
||||
**Related pinpoints:** #287 (auto-compaction reactive-not-preflight, CRITICAL), #283 (threshold env-only no settings.json key), #288 (failure envelope omits diagnostics)
|
||||
|
||||
---
|
||||
|
||||
## Manual `/compact` reports "session below compaction threshold"
|
||||
|
||||
**Symptom:** You run `/compact` to manually compact a session, but it reports `session below compaction threshold` even though the session feels large.
|
||||
|
||||
**Root cause:** The "below threshold" message is currently a catch-all for multiple skip reasons:
|
||||
- Too few compactable messages
|
||||
- Already compacted (only summary remains)
|
||||
- Compactable tokens below threshold
|
||||
- Tool-use/tool-result boundary preserved
|
||||
- Live vs resume threshold divergence
|
||||
|
||||
**Mitigation:**
|
||||
1. **Check session state:** `claw session info <id>` to inspect message count, total tokens
|
||||
2. **Force compaction:** Currently no `--force` flag exists; track #289 for typed skip-reason discriminants
|
||||
3. **Workaround:** Continue session and let auto-compact fire after next provider response (when reactive-after-success path is available)
|
||||
|
||||
**Related pinpoint:** #289 (manual `/compact` skip-reason flattened, lacks typed discriminants)
|
||||
|
||||
---
|
||||
|
||||
## Parallel agent stuck in "running" state
|
||||
|
||||
**Symptom:** A parallel agent lane shows `status: running` indefinitely, never transitioning to `completed` or `error`. Downstream coordination treats it as still-working.
|
||||
|
||||
**Root cause:** `Agent::execute_agent` writes a `running` manifest BEFORE spawning a detached `std::thread::spawn`. The `JoinHandle` is dropped. If the process crashes during agent execution, the manifest stays as `running` forever (zombie state). No heartbeat or stale-reaper exists.
|
||||
|
||||
**Mitigation:**
|
||||
1. **Manual cleanup:** Inspect `~/.claw/agents/<lane>/` and remove stale `manifest.json` files where last-modified > N minutes ago
|
||||
2. **Restart agent lane:** `claw agent restart <lane>`
|
||||
3. **Kill orphaned processes:** `pgrep claw` to find lingering processes
|
||||
|
||||
**Related pinpoint:** #286 (Parallel `Agent` detached-thread no-heartbeat no-reaper)
|
||||
|
||||
---
|
||||
|
||||
## Sustained upstream provider failures (`500 empty_stream` repeating)
|
||||
|
||||
**Symptom:** Same upstream provider error (e.g., `500 empty_stream: upstream stream closed before first payload`) repeats 5+ times in <60 minutes. Retries hit the same dead upstream blindly.
|
||||
|
||||
**Root cause:** claw-code does NOT detect repeat-failure patterns. No circuit-breaker. No automatic provider-fallback when configured. Each retry attempts the same provider+endpoint regardless of recent failure history.
|
||||
|
||||
**Mitigation:**
|
||||
1. **Manual circuit-breaker:** Wait 5-10 minutes after repeated failures before retrying
|
||||
2. **Switch provider:** If you have multiple providers configured (`ANTHROPIC_API_KEY` + `OPENAI_API_KEY`), restart with different model prefix (e.g., `gpt-4` instead of `claude-`)
|
||||
3. **Check provider status pages:** status.anthropic.com, status.openai.com
|
||||
4. **Verify upstream endpoint:** If using a proxy (CCAPI, custom OpenAI-compatible endpoint), check proxy logs
|
||||
|
||||
**Related pinpoints:** #291 (no repeat-failure detection / circuit-breaker), #285 (declarative providers config for fallback), #290 (stream-init failure envelope)
|
||||
|
||||
---
|
||||
|
||||
## Other common failures
|
||||
|
||||
*[placeholder for future sections: tool-use failures, session corruption]*
|
||||
110
docs/ARCHITECTURE.md
Normal file
110
docs/ARCHITECTURE.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# claw-code Architecture
|
||||
|
||||
A high-level overview of how claw-code is structured. For implementation details, see source code in `rust/crates/`. For provider details, see [SUPPORTED_PROVIDERS.md](./SUPPORTED_PROVIDERS.md). For pinpoint navigation, see [ROADMAP.md](../ROADMAP.md#pinpoint-cluster-index).
|
||||
|
||||
## Overview
|
||||
|
||||
claw-code is a Rust-based CLI for interacting with LLM providers (Anthropic, OpenAI-compatible, xAI, DashScope, etc.). It provides:
|
||||
|
||||
- Streaming conversation with auto-compaction
|
||||
- Tool execution (file read/write, bash, MCP)
|
||||
- Multi-provider routing
|
||||
- Session persistence
|
||||
- Parallel agent execution
|
||||
|
||||
## Workspace Layout
|
||||
|
||||
The Rust workspace is organized in `rust/crates/`:
|
||||
|
||||
### Core crates
|
||||
|
||||
- **`rusty-claude-cli`** — CLI entry point. Parses args, routes commands, manages TUI/headless modes.
|
||||
- **`runtime`** — Conversation engine. Manages session state, message history, auto-compaction, tool dispatch, hooks, MCP, and branch/lane events.
|
||||
- **`api`** — Provider abstraction. Hosts `MODEL_REGISTRY` (provider/model routing), SSE streaming, request/response handling. Providers: `anthropic`, `openai_compat`.
|
||||
- **`tools`** — Tool definitions. File I/O, bash execution, MCP integration, PDF extraction.
|
||||
|
||||
### Support crates
|
||||
|
||||
- **`commands`** — Parsed command dispatch layer between CLI and runtime.
|
||||
- **`plugins`** — Plugin/hook lifecycle (`hooks.rs`).
|
||||
- **`telemetry`** — Metrics and tracing instrumentation.
|
||||
- **`compat-harness`** — Parity test harness for Rust-port validation.
|
||||
- **`mock-anthropic-service`** — Local mock server for offline/test use.
|
||||
|
||||
## Request Flow
|
||||
|
||||
1. **CLI parse** (`rusty-claude-cli/src/main.rs`) — interprets args, env vars, settings.json
|
||||
2. **Provider selection** (`api/src/providers/mod.rs`) — routes to provider via `MODEL_REGISTRY` based on model prefix
|
||||
3. **Conversation execution** (`runtime/src/conversation.rs`) — sends to provider via SSE, receives streamed response
|
||||
4. **Tool dispatch** (`tools/src/lib.rs`) — if response includes `tool_use`, execute and feed back `tool_result`
|
||||
5. **Auto-compaction check** (`runtime/src/compact.rs`) — REACTIVE-AFTER-SUCCESS only (see #287 for preflight gap)
|
||||
6. **Output** — JSON envelope (`--output-format json`) or text (default)
|
||||
|
||||
## Key Subsystems
|
||||
|
||||
### Auto-compaction
|
||||
|
||||
Triggered post-turn when `usage.input_tokens > threshold`. See:
|
||||
- Threshold via env-only (#283)
|
||||
- Reactive-not-preflight (#287, CRITICAL)
|
||||
- Manual `/compact` skip-reasons (#289)
|
||||
- Failure envelope coverage (#288)
|
||||
|
||||
### Provider routing
|
||||
|
||||
Hard-coded `MODEL_REGISTRY` + env-var-based auth + model-prefix heuristics. See:
|
||||
- [SUPPORTED_PROVIDERS.md](./SUPPORTED_PROVIDERS.md) for current providers
|
||||
- #285 for declarative providers/models/websearch source-of-truth
|
||||
- #245, #246 for declarative config & backend swap
|
||||
- #290, #291, #292 for transport resilience (stream-init, circuit-breaker, escalation)
|
||||
|
||||
### Parallel agents
|
||||
|
||||
Lane-based execution via `runtime/src/lane_events.rs`. Manifest-driven lifecycle. See:
|
||||
- #286 for detached-thread + no-heartbeat issue (CRITICAL)
|
||||
|
||||
### Tool lifecycle / hooks
|
||||
|
||||
Tools defined in `tools/src/`. Hook events emitted via `runtime/src/hooks.rs` and `plugins/src/hooks.rs`. See:
|
||||
- #254 (MCP refresh)
|
||||
- #268 (tool-rendering parity)
|
||||
- #274 (hook-execution-event envelope)
|
||||
- #280 (hook event tap)
|
||||
|
||||
### Session persistence
|
||||
|
||||
Sessions managed in `runtime/src/session.rs`. See:
|
||||
- #278 (version-comparison)
|
||||
- #279 (unknown-field policy)
|
||||
|
||||
### CLI dispatch
|
||||
|
||||
CLI parsing in `rusty-claude-cli/src/main.rs`. Issues:
|
||||
- #262 `--max-turns` spec
|
||||
- #267 `--cwd` runtime fix
|
||||
- #272 position-independent parsing
|
||||
- #282 env-vs-config consolidation
|
||||
|
||||
## Build & Test
|
||||
|
||||
See [CONTRIBUTING.md](../CONTRIBUTING.md) for build commands. Quick reference:
|
||||
|
||||
```
|
||||
cd rust && cargo build # Build all crates
|
||||
cd rust && cargo test # Run all Rust tests
|
||||
```
|
||||
|
||||
## Tracing & Debugging
|
||||
|
||||
- **Session state:** `runtime/src/session.rs` + `~/.claw/sessions/<id>/`
|
||||
- **Provider responses:** Set `RUST_LOG=trace` for verbose SSE logs
|
||||
- **Parity checks:** Use `compat-harness` crate for Rust-port validation
|
||||
|
||||
## Related Documents
|
||||
|
||||
- [ROADMAP.md](../ROADMAP.md) — Pinpoints by cluster
|
||||
- [TROUBLESHOOTING.md](../TROUBLESHOOTING.md) — User-facing failure mitigation
|
||||
- [SUPPORTED_PROVIDERS.md](./SUPPORTED_PROVIDERS.md) — Provider/model details
|
||||
- [CONTRIBUTING.md](../CONTRIBUTING.md) — Pinpoint filing format
|
||||
- [PINPOINT_FILING_GUIDE.md](./PINPOINT_FILING_GUIDE.md) — Filing workflow
|
||||
- [CHANGELOG.md](../CHANGELOG.md) — Recent changes
|
||||
101
docs/PINPOINT_FILING_GUIDE.md
Normal file
101
docs/PINPOINT_FILING_GUIDE.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# Pinpoint Filing Guide
|
||||
|
||||
This guide walks through the workflow for filing a new claw-code pinpoint, from initial friction to merged ROADMAP entry. For format details, see [CONTRIBUTING.md](../CONTRIBUTING.md). For issue template, see [.github/ISSUE_TEMPLATE/pinpoint.md](../.github/ISSUE_TEMPLATE/pinpoint.md).
|
||||
|
||||
## What is a Pinpoint?
|
||||
|
||||
A pinpoint is a precise, distinct claw-code clawability gap captured in ROADMAP.md format. Pinpoints differ from generic issues by:
|
||||
- **Specificity:** Exact file paths, function names, line numbers when available
|
||||
- **Distinctness:** Verified not already covered by existing pinpoints
|
||||
- **Live evidence:** Real friction event, not hypothetical
|
||||
- **Fix shape:** Concrete delta proposal, not vague "should improve X"
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1: Identify friction
|
||||
|
||||
Use claw-code in real work. When you hit friction (slow startup, broken behavior, opaque error, missing feature, test brittleness, etc.), STOP and capture:
|
||||
- What you were trying to do
|
||||
- What you expected to happen
|
||||
- What actually happened
|
||||
- Exact error message / log output (verbatim)
|
||||
|
||||
### Step 2: Identify distinct axis
|
||||
|
||||
Open ROADMAP.md and search for related existing pinpoints (use the [Cluster Index](../ROADMAP.md#pinpoint-cluster-index)).
|
||||
|
||||
For each candidate match:
|
||||
- Does the existing pinpoint cover this exact symptom?
|
||||
- Does it cover this exact axis (e.g., timing vs envelope vs config)?
|
||||
- Is your case a SUBSET, a SUPERSET, or an ORTHOGONAL axis?
|
||||
|
||||
If your case is orthogonal, file new. If subset, add live-evidence as additional context to existing pinpoint. If superset, file new + cross-reference existing.
|
||||
|
||||
### Step 3: Verify with code
|
||||
|
||||
Before filing, look at the relevant source code:
|
||||
- `rust/crates/api/src/sse.rs` — provider routing
|
||||
- `rust/crates/runtime/src/conversation.rs` — auto-compaction logic
|
||||
- `rust/crates/rusty-claude-cli/src/main.rs` — CLI entry
|
||||
- Search with grep / ripgrep to find the relevant module
|
||||
|
||||
If the code clearly does NOT have the feature you expected, file a pinpoint. If the code DOES have the feature but it's broken, file a bug.
|
||||
|
||||
### Step 4: Write the entry
|
||||
|
||||
Follow the canonical 5-section format (see [CONTRIBUTING.md](../CONTRIBUTING.md)):
|
||||
1. **Exact pinpoint** — One precise sentence
|
||||
2. **Live evidence** — Real friction event with timestamps
|
||||
3. **Why distinct** — Explicit comparison to nearest existing pinpoints
|
||||
4. **Concrete delta** — What you're filing (e.g., "ROADMAP.md appended")
|
||||
5. **Fix shape recorded** — Bullet list of suggested implementation steps
|
||||
|
||||
### Step 5: Submit
|
||||
|
||||
Append to ROADMAP.md and commit:
|
||||
|
||||
```
|
||||
git add ROADMAP.md
|
||||
git commit -m "roadmap: #<NNN> filed (<short title>)"
|
||||
git push origin <branch>
|
||||
git push fork <branch>
|
||||
```
|
||||
|
||||
Verify three-way parity (local == origin == fork) before posting any update.
|
||||
|
||||
## Worked Example: #290 (stream-init failure envelope)
|
||||
|
||||
This shows how #290 was filed in real-time on 2026-04-26.
|
||||
|
||||
### Step 1: Friction identified
|
||||
|
||||
gaebal-gajae's session hit `500 empty_stream: upstream stream closed before first payload` repeatedly (4x in 30 min). Bare-string error surfaced; no diagnostics, no retry guidance.
|
||||
|
||||
### Step 2: Distinct axis identified
|
||||
|
||||
- #266 (typed-error-kind taxonomy) covers single-failure categorization, NOT stream-init specifically
|
||||
- #287 (auto-compaction reactive) covers session-size failures, NOT transport
|
||||
- #288 (JSON envelope failure) covers context-window envelope, NOT stream-init
|
||||
|
||||
→ Orthogonal: filed new #290 covering typed-stream-init-failure-envelope
|
||||
|
||||
### Step 3: Code verified
|
||||
|
||||
Inspected `rust/crates/api/src/sse.rs` — confirmed no `failure_class=upstream_stream_init` discriminant, no retry recommendation in JSON envelope.
|
||||
|
||||
### Step 4: Entry written
|
||||
|
||||
Used canonical 5-section format. Listed 4 live evidence timestamps. Cross-referenced #266, #287, #288 in "Why distinct."
|
||||
|
||||
### Step 5: Submitted
|
||||
|
||||
Commit `0f38975`, pushed to both origin and fork, parity verified, Discord post under 1500 chars.
|
||||
|
||||
**Total time: ~2 minutes from friction identification to merged ROADMAP entry.**
|
||||
|
||||
## Tips
|
||||
|
||||
- **File while it's fresh.** Wait too long and you'll forget exact symptoms.
|
||||
- **Check Cluster Index FIRST** — saves time vs scanning full ROADMAP.
|
||||
- **Write Fix Shape even if you don't implement.** Helps future contributors.
|
||||
- **Live evidence with timestamps > theoretical examples.** Real-world friction always wins.
|
||||
81
docs/SUPPORTED_PROVIDERS.md
Normal file
81
docs/SUPPORTED_PROVIDERS.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Supported Providers
|
||||
|
||||
claw-code currently supports the following LLM providers. This is a snapshot of the current code state and may change. The canonical source of truth is `MODEL_REGISTRY` and provider routing logic in `rust/crates/api/src/providers/mod.rs`.
|
||||
|
||||
> **Note:** A declarative `providers` / `models` / `websearch` config in `settings.json` is tracked as pinpoint #285 and is not yet implemented. Until then, provider/model selection is determined by:
|
||||
> 1. The model name prefix (e.g., `claude-`, `grok-`, `openai/`, `qwen/`, `kimi-`)
|
||||
> 2. Environment variables (e.g., `ANTHROPIC_API_KEY`, `XAI_API_KEY`, `DASHSCOPE_API_KEY`, `OPENAI_API_KEY`)
|
||||
> 3. Hard-coded heuristics in `MODEL_REGISTRY` and `detect_provider_kind()`
|
||||
|
||||
## Anthropic
|
||||
|
||||
- **Status:** Primary supported provider
|
||||
- **Models:**
|
||||
- `claude-opus-4-6` (alias: `opus`) — 200K context, 32K max output
|
||||
- `claude-sonnet-4-6` (alias: `sonnet`) — 200K context, 64K max output
|
||||
- `claude-haiku-4-5-20251213` (alias: `haiku`) — 200K context, 64K max output
|
||||
- **Auth:** `ANTHROPIC_API_KEY` env var, or OAuth bearer via `claw login` (`ANTHROPIC_AUTH_TOKEN`)
|
||||
- **Base URL:** `https://api.anthropic.com` (override: `ANTHROPIC_BASE_URL`)
|
||||
- **Known issues:** Subject to upstream stream-init failures (see #290, #291)
|
||||
|
||||
## xAI (Grok)
|
||||
|
||||
- **Status:** Supported via OpenAI-compatible client
|
||||
- **Models:**
|
||||
- `grok-3` (aliases: `grok`, `grok-3`) — 131K context, 64K max output
|
||||
- `grok-3-mini` (aliases: `grok-mini`, `grok-3-mini`) — 131K context, 64K max output
|
||||
- `grok-2` — context/output limits not yet registered in token metadata
|
||||
- **Auth:** `XAI_API_KEY`
|
||||
- **Base URL:** `https://api.x.ai/v1` (override: `XAI_BASE_URL`)
|
||||
- **Known issues:** None currently tracked
|
||||
|
||||
## Alibaba DashScope (Qwen / Kimi)
|
||||
|
||||
- **Status:** Supported via OpenAI-compatible client pointed at DashScope compatible-mode endpoint
|
||||
- **Models:**
|
||||
- `qwen/*` and `qwen-*` prefix — routes to DashScope (e.g., `qwen-plus`, `qwen-max`, `qwen-turbo`, `qwen/qwen3-coder`)
|
||||
- `kimi-k2.5` (alias: `kimi`) — 256K context, 16K max output
|
||||
- `kimi-k1.5` — 256K context, 16K max output
|
||||
- `kimi/*` and `kimi-*` prefix — routes to DashScope
|
||||
- **Auth:** `DASHSCOPE_API_KEY`
|
||||
- **Base URL:** `https://dashscope.aliyuncs.com/compatible-mode/v1` (override: `DASHSCOPE_BASE_URL`)
|
||||
- **Known issues:** None currently tracked
|
||||
|
||||
## OpenAI / OpenAI-Compatible Endpoints
|
||||
|
||||
- **Status:** Supported via OpenAI-compatible client; also covers local providers (Ollama, LM Studio, vLLM, OpenRouter)
|
||||
- **Models:** `openai/` prefix (e.g., `openai/gpt-4.1-mini`) or bare `gpt-*` prefix
|
||||
- **Auth:** `OPENAI_API_KEY`
|
||||
- **Base URL:** `https://api.openai.com/v1` (override: `OPENAI_BASE_URL` — also used for local providers)
|
||||
- **Local provider routing:** When `OPENAI_BASE_URL` is set and `OPENAI_API_KEY` is present, unknown model names (e.g., `qwen2.5-coder:7b`) also route here
|
||||
- **Known issues:** Declarative per-model config tracked in #285
|
||||
|
||||
## Web Search
|
||||
|
||||
- **Status:** Hard-coded heuristics; declarative `websearch` config tracked in #285
|
||||
|
||||
## Provider Selection Order
|
||||
|
||||
When the model name has no recognized prefix, `detect_provider_kind()` falls through in this order:
|
||||
|
||||
1. Model prefix match (`claude-` → Anthropic, `grok-` → xAI, `openai/` or `gpt-` → OpenAI, `qwen/` or `qwen-` → DashScope, `kimi/` or `kimi-` → DashScope)
|
||||
2. `OPENAI_BASE_URL` + `OPENAI_API_KEY` set → OpenAI-compat
|
||||
3. Anthropic credentials found → Anthropic
|
||||
4. `OPENAI_API_KEY` found → OpenAI
|
||||
5. `XAI_API_KEY` found → xAI
|
||||
6. `OPENAI_BASE_URL` set (no key) → OpenAI-compat (for keyless local providers)
|
||||
7. Default fallback → Anthropic
|
||||
|
||||
## Reporting Provider Issues
|
||||
|
||||
For provider-specific bugs (e.g., `500 empty_stream` from upstream), see [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for mitigation steps.
|
||||
|
||||
For pinpointing a missing provider feature, file via [ISSUE_TEMPLATE/pinpoint.md](../.github/ISSUE_TEMPLATE/pinpoint.md).
|
||||
|
||||
## Related Pinpoints
|
||||
|
||||
- #245 — Provider declarative config
|
||||
- #246 — Backend swap
|
||||
- #285 — Provider/model/websearch source of truth
|
||||
- #290 — Stream-init failure envelope
|
||||
- #291 — Repeat-failure circuit-breaker
|
||||
Reference in New Issue
Block a user