docs: anchor telemetry counters by symbol; fix locale counts and crate paths

- TELEMETRY.md: every counters-table row and the turn_wall source now
  name the function that bumps it (run_event_loop,
  execute_tool_with_lock, create_queued_run_with_descriptor,
  snapshot_from_config, tool_ask_rule_decision_for_context, ...) instead
  of line numbers that had drifted by hundreds of lines; the
  has_hooks_for_event check lives in ui/observer_hooks.rs, not ui.rs.
  First columns are unchanged, so the doc-match tests still read them.
- LOCALIZATION.md: every pack is at parity with en.json (2248 keys at
  HEAD, not 1299); say "all" and let check-tui-locale-parity.py own the
  number. The Devanagari spike note left the repo in 7242381022.
- ARCHITECTURE.md: the TUI crate has no models.rs or skills.rs (models
  live in crates/models; skills/ is a directory); the subagent tools now
  include the agents/* coordination tools alongside agent.

Checks: cargo test -p codewhale-telemetry (includes TELEMETRY.md):
51 passed, 0 failed; python3 scripts/check-provider-registry.py passed.
Docs only.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01TvKGZz4LrKfrQiAXip48JS
This commit is contained in:
CodeWhale BotandClaude Opus 5.5 committed 2026-09-22 20:06:28 -07:00
1 parent 89c60adf39
commit b0a9f9b8d6
3 files changed
+35 -31

No files matched your search

+9 -5
View File
@@ -153,7 +153,8 @@ boundary has held since v0.9.1):
- **`llm_client/`** - LLM client trait, retry logic, and error classification
(`LlmClient`, `RetryConfig`, `with_retry`) consumed by `client.rs`; `mock.rs`
is test-only (`#[cfg(test)]`).
- **`models.rs`** - Data structures for API requests/responses
- **`crates/models`** (`codewhale_models`) - Data structures for API
requests/responses; the TUI crate has no local `models.rs`.
#### DeepSeek API Endpoints
@@ -183,16 +184,19 @@ drives turns through Chat Completions.
discoverable through `tool_search`
- `automation.rs` - Model-visible scheduling tools over `AutomationManager`
- `plan.rs` - Planning tools
- `subagent/` - Sub-agent launch and supervision. The one model-facing tool
is `agent`; the `agent_open`/`agent_eval`/`agent_close` lifecycle surface
was retired (see `subagent/coord.rs:5`)
- `subagent/` - Sub-agent launch and supervision. `agent` is the one
creation surface; `subagent/coord.rs` adds narrow coordination tools
(`agents/list`, `agents/message`, `agents/followup`, `agents/interrupt`,
`agents/wait`, `agents/coordinate`) over the existing manager. The
`agent_open`/`agent_eval`/`agent_close` lifecycle surface was retired
(see the `subagent/coord.rs` module doc)
- `spec.rs` - Tool specifications
- `rlm.rs` - Persistent Recursive Language Model (RLM) sessions — sandboxed Python REPLs with semantic helper calls and `var_handle` output support
### Extension Systems
- **`mcp.rs`** - Model Context Protocol client for external tool servers
- **`skills.rs`** - Plugin/skill loading and execution
- **`skills/`** - Skill discovery and registry for local `SKILL.md` files, plus install and audit
- **`hooks.rs`** - Pre/post execution hooks with conditions
### User Interface
+16 -16
View File
@@ -43,23 +43,23 @@ only at exact raw key parity with it, enforced by
`crates/localization/src/lib.rs`. See `crates/localization/locales/AGENTS.md` for the
authoring contract.
| Locale | File | Keys vs `en.json` (1299) | Status | Notes |
| Locale | File | Keys vs `en.json` | Status | Notes |
|--------|------|--------------------------|--------|-------|
| English | `en.json` | 1299/1299 | **shipped** | Reference pack. |
| Japanese | `ja.json` | 1299/1299 | **shipped** | Complete. |
| Simplified Chinese | `zh-Hans.json` | 1299/1299 | **shipped** | Complete. |
| Traditional Chinese | `zh-Hant.json` | 1299/1299 | **shipped** | Complete (#5143). Awaiting native-speaker review. |
| Brazilian Portuguese | `pt-BR.json` | 1299/1299 | **shipped** | Complete. |
| Latin American Spanish | `es-419.json` | 1299/1299 | **shipped** | Complete. Note the website tracks `es` — the shipped TUI pack is Latin American Spanish, not `es-ES`. |
| Vietnamese | `vi.json` | 1299/1299 | **shipped** | Complete. |
| Korean | `ko.json` | 1299/1299 | **shipped** | Complete. |
| Catalan | `ca.json` | 1299/1299 | **shipped** | Complete (#4749/#4788). Awaiting native-speaker review. |
| German | `de.json` | 1299/1299 | **shipped** | Complete (#4788). Awaiting native-speaker review. |
| French | `fr.json` | 1299/1299 | **shipped** | Complete (#4788). Awaiting native-speaker review. |
| Indonesian | `id.json` | 1299/1299 | **shipped** | Complete (#4789). Awaiting native-speaker review. |
| Hindi | `hi.json` | 1299/1299 | **shipped** | Complete (#4790). Devanagari shaping spike: `docs/evidence/v092-devanagari-terminal-shaping.md` — code-level guarantees only; terminal visual QA and native review still open. |
| Russian | `ru.json` | 1299/1299 | **shipped** | Complete (#3092). Cyrillic script fixtures guard against mixed-language copy. Awaiting native-speaker review. |
| Ukrainian | `uk.json` | 1299/1299 | **shipped** | Complete (#4791). Cyrillic script fixtures keep it distinct from Russian (no ы/э/ъ; і/ї/є/ґ present). Awaiting native-speaker review. |
| English | `en.json` | all | **shipped** | Reference pack. |
| Japanese | `ja.json` | all | **shipped** | Complete. |
| Simplified Chinese | `zh-Hans.json` | all | **shipped** | Complete. |
| Traditional Chinese | `zh-Hant.json` | all | **shipped** | Complete (#5143). Awaiting native-speaker review. |
| Brazilian Portuguese | `pt-BR.json` | all | **shipped** | Complete. |
| Latin American Spanish | `es-419.json` | all | **shipped** | Complete. Note the website tracks `es` — the shipped TUI pack is Latin American Spanish, not `es-ES`. |
| Vietnamese | `vi.json` | all | **shipped** | Complete. |
| Korean | `ko.json` | all | **shipped** | Complete. |
| Catalan | `ca.json` | all | **shipped** | Complete (#4749/#4788). Awaiting native-speaker review. |
| German | `de.json` | all | **shipped** | Complete (#4788). Awaiting native-speaker review. |
| French | `fr.json` | all | **shipped** | Complete (#4788). Awaiting native-speaker review. |
| Indonesian | `id.json` | all | **shipped** | Complete (#4789). Awaiting native-speaker review. |
| Hindi | `hi.json` | all | **shipped** | Complete (#4790). The Devanagari shaping spike (moved out of this repository in `7242381022`) gave code-level guarantees only; terminal visual QA and native review still open. |
| Russian | `ru.json` | all | **shipped** | Complete (#3092). Cyrillic script fixtures guard against mixed-language copy. Awaiting native-speaker review. |
| Ukrainian | `uk.json` | all | **shipped** | Complete (#4791). Cyrillic script fixtures keep it distinct from Russian (no ы/э/ъ; і/ї/є/ґ present). Awaiting native-speaker review. |
## Website locales
+10 -10
View File
@@ -280,16 +280,16 @@ The workhorse. Everything a session accumulated ships here, once.
| field | source anchor |
|---|---|
| `turns` | `crates/tui/src/tui/ui/event_loop.rs:1856` — the *caller* of `execute_turn_end_observer_hook`. Never inside it: that function's first statement is `if !app.hooks.has_hooks_for_event(HookEvent::TurnEnd) { return Ok(()); }` (`crates/tui/src/tui/ui.rs:1035`), and the natural future optimization hoists that check to the call site, silently zeroing the counter for every user without hooks. |
| `tool_calls` | `crates/tui/src/core/engine/tool_execution.rs:495` — surface-agnostic, fires for exec and CLI too |
| `fleet_dispatch` | `crates/tui/src/fleet/manager.rs:374` — the single funnel (`create_queued_run_with_descriptor`) that `create_run` and `create_queued_run` both land in; counting at either caller would double-count a plain `fleet run`. |
| `turns` | `run_event_loop` in `crates/tui/src/tui/ui/event_loop.rs`, immediately before it calls `execute_turn_end_observer_hook`. Never inside that hook: its first statement is `if !app.hooks.has_hooks_for_event(HookEvent::TurnEnd) { return Ok(()); }` (`crates/tui/src/tui/ui/observer_hooks.rs`), and the natural future optimization hoists that check to the call site, silently zeroing the counter for every user without hooks. |
| `tool_calls` | `execute_tool_with_lock` in `crates/tui/src/core/engine/tool_execution.rs` — surface-agnostic, fires for exec and CLI too |
| `fleet_dispatch` | `create_queued_run_with_descriptor` in `crates/tui/src/fleet/manager.rs` — the single funnel that `create_run` and `create_queued_run` both land in; counting at either caller would double-count a plain `fleet run`. |
| `workflow_run` | bumped in `WorkflowTool::execute` (`crates/tui/src/tools/workflow/mod.rs`) only after `parse_workflow_action` returns an `Ok(WorkflowAction)`, never from `input["action"]`. The JSON Schema `enum` in `WorkflowTool::input_schema` is what is published *to the model* — a declaration, not a guard; the real parse also accepts `spawn\|wait\|list\|inspect\|stop\|abort`, and its reject arm (`Invalid workflow action '…'`) embeds the model string verbatim, so a rejected action is never counted. |
| `subagent_spawn` | `crates/tui/src/tui/ui/apply.rs:32` |
| `mcp_server_connected` | count of `.connected` in the snapshot at `crates/tui/src/mcp.rs:4254-4261`; never `name`, `command_or_url`, or `error` — server names are user-chosen and routinely internal infra |
| `memory_search` | tool name at `crates/tui/src/tools/native_memory.rs:60-61`, counted at the tool_execution choke point |
| `approval_modal_shown` | `crates/tui/src/tui/ui/event_loop.rs:2372` (consumer of `Event::ApprovalRequired`, `crates/tui/src/core/events.rs:444`) |
| `approval_auto_allowed` | `crates/tui/src/core/engine.rs:5714`. Count only. Never `matched_rule`, `reason()`, the command, or argv — `auto_allow` patterns are user-authored command strings (`crates/execpolicy/src/command_safety.rs:35/309`) |
| `command_palette_open` | `crates/tui/src/tui/ui/event_loop.rs:3941` and `crates/tui/src/tui/mouse_ui.rs:1346` |
| `subagent_spawn` | `apply_agent_spawned_status_and_observer` in `crates/tui/src/tui/ui/apply.rs` |
| `mcp_server_connected` | bumped when a server snapshot's `.connected` is true, in `snapshot_from_config` (`crates/tui/src/mcp.rs`); never `name`, `command_or_url`, or `error` — server names are user-chosen and routinely internal infra |
| `memory_search` | `tool_name == "memory_search"` (the tool registered in `crates/tui/src/tools/native_memory.rs`), counted at the same `execute_tool_with_lock` choke point |
| `approval_modal_shown` | the `Event::ApprovalRequired` arm of `run_event_loop` (`crates/tui/src/tui/ui/event_loop.rs`; the event is defined in `crates/tui/src/core/events.rs`) |
| `approval_auto_allowed` | `tool_ask_rule_decision_for_context` in `crates/tui/src/core/engine.rs`. Count only. Never `matched_rule`, `reason()`, the command, or argv — `auto_allow` patterns are user-authored command strings (`crates/execpolicy/src/command_safety.rs:35/309`) |
| `command_palette_open` | the palette key path in `run_event_loop` (`crates/tui/src/tui/ui/event_loop.rs`) and `handle_context_menu_action` in `crates/tui/src/tui/mouse_ui.rs` |
**`errors`** — closed field set. Every value is a **variant discriminant**, never `err.to_string()`:
@@ -304,7 +304,7 @@ The workhorse. Everything a session accumulated ships here, once.
Why discriminants and nothing else: `ToolError::PathEscape`'s `Display` *is* an absolute path (`crates/tools/src/lib.rs:61`); `fim.rs:48-50`'s `Display` *is* a literal source fragment the model emitted; `secrets/src/lib.rs:50`'s `Display` carries the secret store's absolute path; every `LlmError` variant carries the raw provider HTTP body verbatim (`crates/tui/src/llm_client/mod.rs:327`), and a 400 from a content filter routinely echoes the prompt.
**`turn_wall`** — a per-session histogram of counts, never per-turn events. `lt_5s`, `5_30s`, `30_120s`, `gte_120s`. Source `crates/tui/src/tui/ui/event_loop.rs:1857`, which already has `duration` in hand.
**`turn_wall`** — a per-session histogram of counts, never per-turn events. `lt_5s`, `5_30s`, `30_120s`, `gte_120s`. Recorded by `observe_turn_secs` next to the `turns` bump in `run_event_loop`, which already has the turn duration in hand.
### Event: `panic`