mirror of
https://github.com/ultraworkers/claw-code.git
synced 2026-04-27 06:57:37 +08:00
roadmap: #264 filed
This commit is contained in:
parent
d0aa18e11f
commit
d5568eb7a4
19
ROADMAP.md
19
ROADMAP.md
@ -16902,3 +16902,22 @@ Gap. This is a **help-contract drift / doc-to-runtime divergence** at the CLI su
|
||||
Required fix shape: (a) update `--compact` help text to describe the actual mode matrix: text mode strips tool-call detail into final assistant text; JSON mode emits a compact JSON envelope; (b) document the compact-JSON field contract after #260 is fixed, explicitly naming preserved fields (`iterations`, `auto_compaction`, `prompt_cache_events`, `usage`, `estimated_cost`) and intentionally stripped fields (`tool_uses`, `tool_results`); (c) add a help-output regression that fails if `--compact` still says `text mode only` while `CliOutputFormat::Json if compact` remains supported; (d) optionally add `claw --help --json` / structured flag metadata later so mode compatibility can be generated from the same source as parser dispatch instead of hand-written prose. Acceptance: `claw --help` no longer claims `--compact` is text-only; compact JSON's supported status and field delta are discoverable before running a prompt; help output and dispatch matrix cannot drift silently.
|
||||
|
||||
**Status:** Open. No source code changed. Filed 2026-04-26 13:02 KST. Branch: feat/jobdori-168c-emission-routing. HEAD: `0e4fd38` before filing. Cluster delta: help-contract-drift +1; CLI-contract-observability gap adjacent to #260 but not a duplicate. Concrete delta this cycle: ROADMAP-only pinpoint appended after fresh help-output verification; no implementation landed.
|
||||
|
||||
## Pinpoint #264 — Turn-budget primitive is structurally absent from the runtime: `max_iterations` exists as an untyped builder knob with `usize::MAX` default, the live CLI never calls it, and exhaustion produces a bare string `RuntimeError` with no typed `TurnBudgetExhausted` event, no session-state turn counter, no warning event before the cap, and no zero-turn semantics — sister pinpoint to #262 covering the runtime-side of the same turn-budget concern
|
||||
|
||||
Dogfooded 2026-04-26 13:05 KST on `feat/jobdori-168c-emission-routing` at HEAD `d0aa18e` (post-#263 fast-forward verification onto gaebal-gajae's `--compact` help-text-vs-dispatch-mismatch pinpoint). #262 audited the CLI **parse-side** of the turn-budget gap (no `--max-turns` flag, plus position-sensitive prompt absorption when the unknown flag arrives after `-p`). #264 audits the **runtime-side**: even if the CLI flag existed and were wired through `CliAction::Prompt`, the runtime layer it would have to plumb into has no typed turn-budget primitive at all. The existing `max_iterations: usize` field at `rust/crates/runtime/src/conversation.rs:132` is a flat untyped builder knob, the `with_max_iterations` builder at line 192 takes only a raw `usize` with no validation, the field defaults to `usize::MAX` at line 181, the cap check at lines 343-352 returns a bare string-bodied `RuntimeError::new("conversation loop exceeded the maximum number of iterations")` with no typed discriminant, and `RuntimeError` itself at lines 87-93 is a single-variant struct holding only `message: String` with no `kind` enum / no `RuntimeErrorKind::TurnBudgetExhausted` variant / no machine-readable reason field. The post-completion `TurnSummary` at lines 110-118 carries `iterations: usize` as a passive odometer but has no `budget: Option<u32>` / `budget_remaining: Option<u32>` / `budget_exhausted: bool` companion fields and no in-loop event surface that warns before the cap is reached.
|
||||
|
||||
Verified concrete surface (rg across `rust/crates/`): zero `TurnBudget`, zero `TurnBudgetExhausted`, zero `TurnBudgetWarning`, zero `TurnsExhausted`, zero `TurnLimit`, zero `TurnCap`, zero `turn_budget`, zero `turn_limit`, zero `turn_cap` symbols anywhere in the workspace. Only two `with_max_iterations` callers exist: `conversation.rs:1768` (one unit test setting `1`) and `tools/lib.rs:3589` (subagent runtime with the hardcoded `DEFAULT_AGENT_MAX_ITERATIONS: usize = 32` const at `tools/lib.rs:3475`). The live primary CLI dispatch in `rusty-claude-cli/src/main.rs:7705` constructs `ConversationRuntime::new_with_features(...)` and **never** chains `.with_max_iterations(...)`, so the main interactive and non-interactive CLI always run with `usize::MAX` as the ceiling — the cap check on line 344 is dead code in the primary product surface and only triggers in the subagent dispatch and the one unit test. There is no telemetry/event/log emitted as the iteration count grows; `record_assistant_iteration` at line 593 records each iteration but emits no warning when iteration count crosses (say) 50% / 75% / 90% of the configured budget. There is no zero-turn semantic (a `max_iterations = 0` config would fail-fast on the first iteration with the same generic string error rather than returning a typed `iterations: 0, no_model_call: true` outcome useful for cost-zero parse-validation runs).
|
||||
|
||||
Gap. The runtime treats turn-count as an **untyped odometer plus a single emergency tripwire**, not as a first-class budget primitive. There is no `pub struct TurnBudget { max_turns: u32, warn_at_pct: Option<u8>, on_exhaust: ExhaustionPolicy }` shape, no `pub enum ExhaustionPolicy { Error, ReturnPartial, RequestExtension }`, no `pub enum RuntimeErrorKind { TurnBudgetExhausted { iterations: usize, max: usize }, ApiError, SessionError, HookError, … }`, no in-loop `TurnBudgetEvent::ApproachingLimit { iterations, max }` lane event, no per-session `Session::turn_counter` field that persists across turns (the iteration counter resets to 0 at the top of every `run_turn`, so a long session can run 100 turns with 32 iterations each — 3,200 model calls — without any cumulative budget tripping). The downstream effect: even if #262's CLI parse-side fix lands and a `--max-turns N` flag becomes plumbable, the runtime has no typed surface to plumb it INTO; the only available landing site is the same untyped `with_max_iterations(usize)` builder, which conflates per-turn iteration cap (the existing knob) with cumulative-session turn cap (the upstream Claude Code semantic), gives no typed exhaustion event, and silently disagrees with the subagent-only `DEFAULT_AGENT_MAX_ITERATIONS = 32` ceiling.
|
||||
|
||||
Cluster shape novelty: founds the **NEW Turn-budget-primitive cluster** with #264 as solo founder. The cluster catalogues missing typed primitives at the iteration/turn/session-budget axis: `TurnBudget` config struct, `TurnBudgetExhausted` typed exhaustion event, `TurnBudgetWarning` pre-exhaustion event, `Session::turn_counter` cumulative state, `ExhaustionPolicy` enum, and zero-turn semantics. Distinct from #262 (CLI parse-side; #262 is the request-shape gap, #264 is the type-shape gap underneath it) — together #262+#264 bracket the full turn-budget concern across the CLI parse boundary and the runtime primitive boundary. Distinct from the silent-fallback family (#258/#260/#262): the silent-fallback family is about silent input mutation and silent output stripping at boundaries; #264 is about a **missing typed primitive** layer that prevents typed errors from existing at all, regardless of whether the boundary is silent or loud. Distinct from #239 branch leases / #243 canonical ordering / #253 context-budget compaction (those are coordination/operational primitives at the cycle/branch level; #264 is a runtime-loop primitive at the model-iteration level). Distinct from #229/#238/#244 persistent-WebSocket cluster (those are bidirectional client-driven streams; #264 is a synchronous loop counter). #264 sits in the **runtime-typed-primitive layer**, parallel to #254 (MCP Resources lifecycle, also runtime-protocol layer) — both pinpoints catalogue missing typed primitives the runtime should expose to higher layers.
|
||||
|
||||
Discovery-pattern continuation: #264 is the first member of a **complementary-pinpoint-pair-bundle at the same turn-budget concern across two structural layers**, sister-shaped to #245+#250 (client/server complementary pair at the WebSearch concern). The pair #262 (CLI-parse layer) + #264 (runtime-primitive layer) catalogues both halves of the same operator capability gap and demonstrates that audit-completeness for a single user-facing flag often requires pinpointing TWO distinct internal layers rather than a single dispatch site. Does NOT extend the silent-fallback family (10 members at the close of #262); founds a fresh top-level cluster instead because the missing primitive is the **prerequisite layer** silent-fallback siblings would land typed errors INTO.
|
||||
|
||||
Required fix shape: (a) introduce `pub struct TurnBudget { pub max_turns: u32, pub max_iterations_per_turn: Option<u32>, pub warn_at_pct: Option<u8>, pub on_exhaust: ExhaustionPolicy }` with `Default::default()` returning unbounded; (b) introduce `pub enum ExhaustionPolicy { Error, ReturnPartial }` defaulting to `Error`; (c) replace `RuntimeError { message: String }` with `RuntimeError { kind: RuntimeErrorKind, message: String }` where `RuntimeErrorKind` is a typed enum including `TurnBudgetExhausted { iterations: usize, max: usize }`, `IterationBudgetExhausted { iterations: usize, max: usize }`, `ApiError`, `SessionError`, `HookError`, `HealthProbeFailed`, `Other`; (d) replace `with_max_iterations(usize)` with `with_turn_budget(TurnBudget)` (keep old builder as `#[deprecated]` alias to preserve subagent compatibility), wire the new builder through `ConversationRuntime` and `BuiltRuntime`; (e) add `Session::turn_counter: u64` persisted across turns and increment in `run_turn` before iteration loop; (f) add `pub enum RuntimeEvent { … TurnBudgetWarning { iterations, max, pct }, TurnBudgetExhausted { iterations, max }, IterationBudgetWarning { … } }` lane events emitted from inside the iteration loop at `warn_at_pct` and at exhaustion (so `--output-format json`/`stream-json` consumers can observe the budget approach before the typed error fires); (g) define zero-turn semantics: `TurnBudget { max_turns: 0, … }` returns `Ok(TurnSummary { iterations: 0, assistant_messages: vec![], … })` immediately without an API call, useful for parse-validation/cost-zero runs and matching the upstream Claude Code zero-turn contract that #262's CLI flag would expose; (h) wire `LiveCli::run_turn_with_output` (`main.rs:7705`) to pass a `TurnBudget` derived from the new `--max-turns` flag (#262 fix) plus a default sensible ceiling for the primary CLI surface; (i) add tests for (1) iteration cap typed error, (2) cumulative turn cap typed error across multiple `run_turn` calls on the same runtime, (3) warn-at-pct event firing exactly once per turn, (4) zero-turn fast-return, (5) `RuntimeErrorKind::TurnBudgetExhausted` round-trips through `--output-format json` `error.kind` field instead of being string-only.
|
||||
|
||||
Acceptance: a downstream caller can pattern-match on `RuntimeErrorKind::TurnBudgetExhausted { iterations, max }` instead of substring-matching on a generic string; `--output-format json` emits `{ "error": { "kind": "turn_budget_exhausted", "iterations": 33, "max": 32 }, … }` instead of a bare error message; `TurnBudget { max_turns: 0 }` returns immediately with `iterations: 0`; a 90%-of-budget warning event fires before exhaustion; the subagent runtime keeps its `DEFAULT_AGENT_MAX_ITERATIONS = 32` semantic via the new `TurnBudget` builder; the primary CLI runtime gains a default budget instead of `usize::MAX`; #262's CLI flag fix has a typed runtime surface to land on.
|
||||
|
||||
**Status:** Open. No source code changed. Filed 2026-04-26 13:05 KST. Branch: feat/jobdori-168c-emission-routing. HEAD: `d0aa18e` (post-#263 fast-forward verification onto gaebal-gajae's `--compact` help-text-vs-dispatch-mismatch pinpoint). Cluster delta: Turn-budget-primitive cluster 0→1 (founder, NEW SOLO CLUSTER); complementary-pinpoint-pair-bundle discovery-pattern extended (sister to #245+#250 WebSearch client/server pair, now #262+#264 turn-budget CLI-parse/runtime-primitive pair). Smaller-scope by design (matches #253/#254/#257/#258/#260/#261/#262/#263 context-budget discipline). Sister: #262 (CLI parse-side; #262+#264 bracket the full turn-budget concern across two structural layers). Distinct from silent-fallback family (#258/#260/#262 catalogue silent-mutation at boundaries; #264 catalogues a missing typed primitive layer that those boundaries would land typed errors INTO). Distinct from #254 MCP Resources lifecycle (also runtime-protocol layer but resource-handle axis, not iteration/turn axis). Eleventh-cycle concurrent-dogfood-rebase parity will be confirmed local==origin==fork at HEAD `d0aa18e+#264` after push.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user