diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 10c64eb..eb5612b 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -22,28 +22,28 @@ struct Args { #[command(subcommand)] command: Option, - #[arg(long, default_value_t = 0)] + #[arg(short, long, default_value_t = 0)] port: u16, - #[arg(long, help = SETTINGS_PATH_HELP.as_str())] + #[arg(short, long, help = SETTINGS_PATH_HELP.as_str())] settings_path: Option, - #[arg(long)] + #[arg(short, long)] file: Option, - #[arg(long)] + #[arg(short, long)] metrics_url: Option, - #[arg(long)] + #[arg(short, long)] name: Option, } #[derive(Subcommand, Debug)] enum Command { Mcp { - #[arg(long)] + #[arg(short, long)] session: Option, - #[arg(long)] + #[arg(short, long)] port: Option, }, Sessions, diff --git a/src/engine/handle.rs b/src/engine/handle.rs index 0469c4d..0ea552e 100644 --- a/src/engine/handle.rs +++ b/src/engine/handle.rs @@ -100,31 +100,31 @@ impl EngineHandle { } } -pub fn spawn(settings: SettingsHandle, channel_capacity: usize) -> EngineHandle { +/// Builds the handle/receiver/writer triple shared by `spawn` and, in tests, by callers that +/// want the raw receiver without an actor loop draining it. +fn new_channel_and_handle( + channel_capacity: usize, +) -> (EngineHandle, mpsc::Receiver, IndexWriter) { let (tx, rx) = mpsc::channel(channel_capacity); let (write, read) = left_right::new::(); let reader = IndexReader { factory: read.factory(), }; - tokio::spawn(run(rx, settings, IndexWriter { handle: write })); - EngineHandle { tx, reader } + (EngineHandle { tx, reader }, rx, IndexWriter { handle: write }) +} + +pub fn spawn(settings: SettingsHandle, channel_capacity: usize) -> EngineHandle { + let (handle, rx, write) = new_channel_and_handle(channel_capacity); + tokio::spawn(run(rx, settings, write)); + handle } #[cfg(test)] pub(crate) fn test_handle( channel_capacity: usize, ) -> (EngineHandle, mpsc::Receiver) { - let (tx, rx) = mpsc::channel(channel_capacity); - let (_write, read) = left_right::new::(); - ( - EngineHandle { - tx, - reader: IndexReader { - factory: read.factory(), - }, - }, - rx, - ) + let (handle, rx, _write) = new_channel_and_handle(channel_capacity); + (handle, rx) } async fn run( diff --git a/tickets/093-json-viewer-collapsed-by-default.md b/tickets/093-json-viewer-collapsed-by-default.md deleted file mode 100644 index dcc5091..0000000 --- a/tickets/093-json-viewer-collapsed-by-default.md +++ /dev/null @@ -1,35 +0,0 @@ -# 093 — Log-line JSON viewer should default to collapsed, not expanded - -## Summary - -When a log line's text parses as a JSON object, the frontend renders it -via a collapsible tree view — but every node starts expanded, so a -line with a large JSON payload dumps its entire structure into the -timeline by default instead of showing a collapsed summary the user -opts into expanding. - -## Where - -- `webapp/src/components/LogPreview.tsx:97-107` — `JsonValueView` - recursively renders JSON values, delegating objects/arrays to - `JsonNode`. -- `webapp/src/components/LogPreview.tsx:109-156` — `JsonNode` renders - a collapsible subtree with a ▾/▸ disclosure toggle. Default state is - set at line 116: `useState(true)`, i.e. expanded. Each nested - object/array has its own independent `expanded` state. -- `webapp/src/components/LogPreview.tsx:160-164` — `LogMessage` is the - per-row entry point: parses the line via `tryParseJsonObject` - (`:82-94`) and renders through `JsonValueView` when it succeeds. -- Empty objects/arrays already short-circuit to plain `{}`/`[]` with - no toggle (`:118-125`) — unaffected by this change. - -## Scope - -- Flip the default in `JsonNode` (`LogPreview.tsx:116`) from - `useState(true)` to `useState(false)` so JSON subtrees render - collapsed until the user clicks to expand. -- Since expand state is per-node (not shared across the tree), this - changes every node in a JSON log line's tree independently — confirm - that's the intended look (top-level object collapsed with `{...}` - rather than only nested children collapsing) rather than needing a - "expand root, collapse children" split default. diff --git a/tickets/096-clap-short-flags.md b/tickets/096-clap-short-flags.md deleted file mode 100644 index 4fbb6a1..0000000 --- a/tickets/096-clap-short-flags.md +++ /dev/null @@ -1,34 +0,0 @@ -# 096 — Add single-character short flags to clap CLI args - -## Summary - -None of the CLI's clap-defined flags have a `short` form — every -option is long-only, including ones that are typed often -(`--file`, `--metrics-url`). - -## Where - -- `src/cli/mod.rs:20-39` — top-level `Args` struct, all fields - `#[arg(long, ...)]` with no `short`: - - `port: u16` — `:25-26`, `default_value_t = 0` - - `settings_path: Option` — `:28-29` - - `file: Option` — `:31-32` - - `metrics_url: Option` — `:34-35` - - `name: Option` — `:37-38` -- `src/cli/mod.rs:41-50` — `Command::Mcp` subcommand, also long-only: - - `session: Option` — `:44-45` - - `port: Option` — `:46-47` - -## Scope - -- Add `short` to each flag where the initial letter is unambiguous - within its own `Args`/subcommand struct: `-p` (port), `-f` (file), - `-m` (metrics-url), `-n` (name), `-s` (settings-path or session, - whichever reads more naturally per subcommand — they're in separate - structs so both can use `-s` without conflict). -- `Mcp`'s `port` can reuse `-p` since it's a distinct struct from the - top-level `Args`. -- Verify with `cargo run -- --help` (and the `mcp` subcommand's - `--help`) that clap doesn't reject any of these for collision, and - update `README.md`'s CLI usage section if it documents flags - explicitly. diff --git a/tickets/099-remove-test-handle-stub.md b/tickets/099-remove-test-handle-stub.md deleted file mode 100644 index cdda94e..0000000 --- a/tickets/099-remove-test-handle-stub.md +++ /dev/null @@ -1,45 +0,0 @@ -# 099 — Remove `test_handle`'s duplicate-of-`spawn` test stub - -## Summary - -`test_handle` is a `#[cfg(test)]` production-file function that exists -only to give tests access to the engine's internal `mpsc::Receiver` — -it duplicates `spawn()` almost line-for-line rather than exposing that -receiver through `spawn()`/`EngineHandle` itself. Per this repo's -`IDEAS.md` guidance: prefer changing a function's scope/visibility (or -the tests) over maintaining a parallel stub. - -## Where - -- `src/engine/handle.rs:113-128` — `#[cfg(test)] pub(crate) fn - test_handle(channel_capacity: usize) -> (EngineHandle, - mpsc::Receiver)`, duplicating `spawn()` - (`src/engine/handle.rs:103-111`) except that `spawn()` discards the - receiver after wiring the actor loop, while `test_handle` returns it - raw. -- Re-exported at `src/engine/mod.rs:21`: `pub(crate) use - handle::test_handle;`. -- Consumed only by tests in `src/engine/ingest.rs:228` (`use - crate::engine::test_handle;`) and called at lines 248, 264, 281, 302 - inside `#[cfg(test)] mod tests`. - -## Scope - -- Remove `test_handle` and instead give tests access via `spawn()` - itself — e.g. have `spawn()` take an optional channel-capacity - override and always hand back the receiver alongside the handle (or - the actor join handle), with production call sites (`main.rs`) - simply ignoring what they don't need, rather than keeping a second - constructor whose only difference is what it returns. -- Update the four call sites in `src/engine/ingest.rs`'s test module - to use the adjusted `spawn()` signature. -- Out of scope: the other test-fixture helpers in `src/engine/tests.rs` - (`metric_request`, `declare_test_param`, `ingest_log`, `logs_query`, - `logs_query_sorted`, etc.) are ordinary test-data builders, not - visibility workarounds — leave those alone. Also leave the - `#[allow(dead_code)]` items (`src/engine/message.rs:11,29`, - `src/api/mcp_server.rs:254`, `src/config/mod.rs:27`, and similar in - `metric_primitive.rs`/`data_value.rs`/`timestamp.rs`/`index_key.rs`) - untouched — they weren't confirmed to be test-visibility stubs and - need individual inspection before deciding whether they're even - related to this ticket's pattern. diff --git a/webapp/src/components/LogPreview.tsx b/webapp/src/components/LogPreview.tsx index 1015034..d2f1a3e 100644 --- a/webapp/src/components/LogPreview.tsx +++ b/webapp/src/components/LogPreview.tsx @@ -113,7 +113,7 @@ function JsonNode({ entries: ReadonlyArray bracket: [string, string] }) { - const [expanded, setExpanded] = useState(true) + const [expanded, setExpanded] = useState(false) if (entries.length === 0) { return (