You are a constitutional council ranking individual git commits for ownership allocation. Compare these two commits. Decide which contributed more lasting value to the project. Judge substance, not spectacle: - Prefer correct, lasting design and real bugfixes over churn, formatting, renames, or generated noise. - Prefer clarity and necessity over sheer line count. A small precise change can beat a large diffuse one. - Do not favor a side merely because its patch is longer or noisier. - Weight what the change does for the project, not the contributor's name. Return ONLY a JSON object: {"winner": "A" or "B", "ratio": "N:M", "explanation": "..."} The explanation must cite concrete differences in the patches (1-3 sentences). Side A — contributor: tommy-mor Side A — commit message: [e999c571] nit Side A — unified diff (full patch): diff --git a/server/src/html/forum.rs b/server/src/html/forum.rs index 815fc6529062b103553644fc15e516334aec2b88..9d9eae409e9df24d6946a6f8782da9b1d536fe3c 100644 --- a/server/src/html/forum.rs +++ b/server/src/html/forum.rs @@ -980,12 +980,6 @@ pub async fn room_page( h3 { "threads" } (render_thread_feed(Some(&nav), "room-thread-feed", &rows, now)) @if show_new { - div class="thread-feed-toolbar" { - form method="POST" action="/ui" { - input type="hidden" name=(UI_RPC_FIELD) value=(expand_room_new_thread_rpc_value(&nav)); - button type="submit" class="section-add-btn" { "+" } - } - } div id="room-new-thread-ui-slot" { (new_thread_form_for_room(&nav, true, false)) } @@ -1015,11 +1009,10 @@ fn new_thread_form_for_room(nav: &ThreadNav, show: bool, compose_expanded: bool) form method="POST" action="/ui" { input type="hidden" name=(UI_RPC_FIELD) value=(rpc_close); button type="submit" class="form-toggle" aria-expanded="true" { - "hide new thread form" + "-" } } section class="compose" id="room-new-thread-compose" { - h3 { "new thread in this room" } div id="room-new-thread-errors" {} form id="room-new-thread-form" method="POST" action="/ui" data-check-action="/ui" data-check-rpc=(template_json_compact(&json!({ "action": "check_ingest", @@ -1037,8 +1030,7 @@ fn new_thread_form_for_room(nav: &ThreadNav, show: bool, compose_expanded: bool) "error_target": "room-new-thread-errors", "form_id": "room-new-thread-form", })).unwrap()); - label for="room-new-tag" { "thread tag" } - input type="text" id="room-new-tag" name="thread_tag" pattern="[a-z0-9_\\-]{1,64}" required; + input type="text" id="room-new-tag" name="thread_tag" pattern="[a-z0-9_\\-]{1,64}" required placeholder="thread-topic-slug-here"; textarea name="text" rows="4" placeholder="First post body…" required {} p { button type="submit" { "post" } } } @@ -1047,7 +1039,7 @@ fn new_thread_form_for_room(nav: &ThreadNav, show: bool, compose_expanded: bool) form method="POST" action="/ui" { input type="hidden" name=(UI_RPC_FIELD) value=(rpc_open); button type="submit" class="form-toggle" aria-expanded="false" { - "new thread in this room" + "+" } } } Side B — contributor: tommy-mor Side B — commit message: [ed042dc3] fixes Side B — unified diff (full patch): diff --git a/bb.edn b/bb.edn new file mode 100644 index 0000000000000000000000000000000000000000..1e8ec120921761a9a4f28f36578efb1567407cb3 --- /dev/null +++ b/bb.edn @@ -0,0 +1,19 @@ +{:paths ["."] + :deps {} + :tasks + {:requires ([babashka.process :as p] + [clojure.string :as str]) + + watch + {:doc "Hot-reload the server on source changes (requires cargo-watch)" + :task (do + (deref (p/process ["mkdir" "-p" "dev-data"] {:inherit true})) + (deref (p/process ["cargo" "watch" + "-x" "run -p server" + "-w" "server/"] + {:inherit true + :env (merge (into {} (System/getenv)) + {"SLUG_DATA_DIR" "dev-data" + "SLUG_KEYS" "dev:dev" + "PORT" "8080" + "RUST_LOG" "info"})})))}}} diff --git a/server/src/api/ui_html.rs b/server/src/api/ui_html.rs index e74e42e0f0ffc4224f5ef5421b486a5f35434999..d2024bd4582bcc8482b461b2ba4fedbd8bff7c66 100644 --- a/server/src/api/ui_html.rs +++ b/server/src/api/ui_html.rs @@ -6,9 +6,8 @@ use axum::{ use std::collections::HashMap; use crate::{ - html::{js_string_literal, ranking_panel, JsBuilder}, + html::{input_panel, js_string_literal, ranking_panel, JsBuilder}, parser::parse_reddit_url, - parser_render::navigate_panel, path_types::ItemId, reddit::ensure_partial_tree, state::{parse_item_param, AppState}, @@ -82,7 +81,7 @@ pub async fn post_ui_html( .into_response() } Err(message) => { - let panel = navigate_panel(&query, Some(&message)); + let panel = input_panel(&query, Some(&message)); JsBuilder::new() .morph_selector("#parser-panel", panel) .into_response() diff --git a/server/src/html/mod.rs b/server/src/html/mod.rs index a8353c6de0cd6d268219e552b7ca1ba4e3000585..322dffefeaa3b8560c1c2b2f70ba8e5a8c555022 100644 --- a/server/src/html/mod.rs +++ b/server/src/html/mod.rs @@ -8,7 +8,6 @@ use maud::{html, Markup, DOCTYPE}; use crate::{ form_template::template_json_compact, - parser_render::navigate_panel, path_types::ItemId, ranking::{top_bottom, RankedItem}, reducer::{GroupState, NodeState}, @@ -224,49 +223,34 @@ pub fn ranking_panel(item: &ItemId, group: &GroupState) -> Markup { } } -pub fn vote_panel(parent: &ItemId) -> Markup { - let parent_str = parent.as_str(); +pub fn input_panel(query: &str, error: Option<&str>) -> Markup { let rpc = template_json_compact(&serde_json::json!({ - "action": "record_vote", - "a": {"$form": "item_a"}, - "b": {"$form": "item_b"}, - "ratio_left": 2, - "ratio_right": 1, - "scope": {"$form": "scope"} + "action": "parse_query", + "query": {"$form": "query"}, })) - .expect("vote rpc json"); + .expect("parse_query rpc template"); html! { - section id="vote-panel" class="demo-panel" { - h2 { "Compare" } - p class="muted small" { - @if parent.is_root() { - "Left item wins at 2:1. Votes append to the JSONL log and update rank centrality." - } @else { - "Ranking children of " - span class="scope-name" { (parent_str) } - ". Left item wins at 2:1; each vote updates this ranking." + section id="parser-panel" class="demo-panel" { + form method="post" action="/ui" id="parser-form" { + textarea + name="query" + id="parser-input" + rows="3" + placeholder="https://reddit.com/r/rust or r/rust" + autocomplete="off" + spellcheck="false" { + (query) } - } - form method="post" action="/ui" id="vote-form" { input type="hidden" name=(UI_RPC_FIELD) value=(rpc); - input type="hidden" name="scope" value=(parent_str); - div class="vote-fields" { - label { - "Left (wins) " - input type="text" name="item_a" required placeholder="alpha" autocomplete="off"; - } - label { - "Right " - input type="text" name="item_b" required placeholder="beta" autocomplete="off"; - } - } - button type="submit" class="btn-primary" { "Vote" } + button type="submit" class="btn-primary" { "Go" } + } + @if let Some(msg) = error { + p class="parser-error muted" { (msg) } } } } } - async fn item_page(state: AppState, uri: Uri, item: ItemId) -> Markup { let path = uri.path().to_string(); state.views.increment(path.clone()); @@ -278,11 +262,10 @@ async fn item_page(state: AppState, uri: Uri, item: ItemId) -> Markup { let group = &node.local_ranking; let body = html! { - h1 { "sorter2" } + h1 { "sorter" } + (input_panel("", None)) (breadcrumb_path(&item)) - (navigate_panel("", None)) (entity_panel(node)) - (vote_panel(&item)) (ranking_panel(&item, group)) }; layout("sorter2", body, views) diff --git a/server/src/lib.rs b/server/src/lib.rs index cd56743192919cf4dcea539b3d8873a21fb7e72b..79b173f391a96ae5d0d96fd656e1e8d2dd070d09 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -4,7 +4,6 @@ pub mod events; pub mod form_template; pub mod html; pub mod parser; -pub mod parser_render; pub mod path_types; pub mod ranking; pub mod reddit; diff --git a/server/src/parser_render.rs b/server/src/parser_render.rs deleted file mode 100644 index acf2e7403f4238291677ef0c79d5766302ea78cf..0000000000000000000000000000000000000000 --- a/server/src/parser_render.rs +++ /dev/null @@ -1,44 +0,0 @@ -use maud::{html, Markup}; - -use crate::{ - form_template::template_json_compact, - ui_action::UI_RPC_FIELD, -}; - -fn parse_query_rpc_template() -> String { - template_json_compact(&serde_json::json!({ - "action": "parse_query", - "query": {"$form": "query"}, - })) - .expect("parse_query rpc template") -} - -/// Navigate panel: paste a Reddit URL and click Go. -pub fn navigate_panel(query: &str, error: Option<&str>) -> Markup { - html! { - section id="parser-panel" class="demo-panel" { - h2 { "Navigate" } - p class="muted small" { - "Paste a Reddit URL or " - code { "r/subreddit" } - " path. Breadcrumb links drill down the tree; rankings apply to each node's children." - } - form method="post" action="/ui" id="parser-form" { - textarea - name="query" - id="parser-input" - rows="3" - placeholder="https://reddit.com/r/rust or r/rust" - autocomplete="off" - spellcheck="false" { - (query) - } - input type="hidden" name=(UI_RPC_FIELD) value=(parse_query_rpc_template()); - button type="submit" class="btn-primary" { "Go" } - } - @if let Some(msg) = error { - p class="parser-error muted" { (msg) } - } - } - } -} diff --git a/server/static/sorter.css b/server/static/sorter.css index f5fb317a2c2a86d3dd00a639fff017fa3b8cc354..04f4fabdea3de7c3bc54805d0d3d9e0cea6eeefd 100644 --- a/server/static/sorter.css +++ b/server/static/sorter.css @@ -29,7 +29,7 @@ body { .view-meta { position: fixed; - top: 0.5rem; + top: 0.1rem; right: 0.5rem; font-size: 0.75rem; } @@ -166,3 +166,7 @@ code { text-align: center; margin: 0.25rem 0; } + +h1 { + margin: 0; +} \ No newline at end of file diff --git a/server/tests/integration_health.rs b/server/tests/integration_health.rs index 1d816e008b9bf629967e3b3c786c41afefc284e3..244bdb69d680569b0074b31a9d7b98315b8ecaab 100644 --- a/server/tests/integration_health.rs +++ b/server/tests/integration_health.rs @@ -49,7 +49,6 @@ async fn home_has_main_panels() { .text() .await .unwrap(); - assert!(html.contains("vote-panel")); assert!(html.contains("ranking-panel")); assert!(html.contains("parser-panel")); assert!(html.contains("__rpc__"));