{"messages":[{"content":"You are a constitutional council ranking individual git commits for ownership allocation.\n\nCompare these two commits. Decide which contributed more lasting value to the project.\n\nJudge substance, not spectacle:\n- Prefer correct, lasting design and real bugfixes over churn, formatting, renames, or generated noise.\n- Prefer clarity and necessity over sheer line count. A small precise change can beat a large diffuse one.\n- Do not favor a side merely because its patch is longer or noisier.\n- Weight what the change does for the project, not the contributor's name.\n\nReturn ONLY a JSON object: {\"winner\": \"A\" or \"B\", \"ratio\": \"N:M\", \"explanation\": \"...\"}\nThe explanation must cite concrete differences in the patches (1-3 sentences).\n\nSide A — contributor: tommy-mor\nSide A — commit message:\n[09842c93] remove shell\n\nSide A — unified diff (full patch):\ndiff --git a/server/src/html/garden.rs b/server/src/html/garden.rs\nindex 8fc6be1de8dd975f9547de615809222236be4b70..76ba96e45c9e16291a6ccd8096fdd01b274c1560 100644\n--- a/server/src/html/garden.rs\n+++ b/server/src/html/garden.rs\n@@ -1321,55 +1321,53 @@ async fn vote_compare_inner(\n .expect(\"vote compare rpc json\");\n \n let body = html! {\n- section class=\"vote-compare-shell\" {\n- h2 { \"compare\" }\n- div class=\"vote-compare-pair\" {\n- a class=\"vote-compare-item\" href=(nav.garden_item_href(&left)) {\n- code { (item_display_path(left.as_str())) }\n- }\n- span class=\"vote-compare-vs\" { \"vs\" }\n- a class=\"vote-compare-item\" href=(nav.garden_item_href(&right)) {\n- code { (item_display_path(right.as_str())) }\n- }\n- }\n- div id=\"vote-edge-history-region\" {\n- (edge_history)\n- }\n- @if can_post {\n- form id=\"vote-compare-form\" method=\"POST\" action=\"/ui\" {\n- input type=\"hidden\" name=(UI_RPC_FIELD) value=(rpc_json);\n- div class=\"vote-thread-picker\" {\n- label class=\"vote-thread-picker-label\" { \"thread\" }\n- select id=\"vote-thread-select\" name=\"thread_tag\" aria-label=\"Thread to post vote into\" {\n- @if thread_tags.is_empty() {\n- option value=\"vote\" selected { \"#vote\" }\n- }\n- @for t in &thread_tags {\n- @if *t == auto_thread {\n- option value=(t) selected { \"#\" (t) }\n- } @else {\n- option value=(t) { \"#\" (t) }\n- }\n- }\n- }\n+ h2 { \"compare\" }\n+ div class=\"vote-compare-pair\" {\n+ a class=\"vote-compare-item\" href=(nav.garden_item_href(&left)) {\n+ code { (item_display_path(left.as_str())) }\n+ }\n+ span class=\"vote-compare-vs\" { \"vs\" }\n+ a class=\"vote-compare-item\" href=(nav.garden_item_href(&right)) {\n+ code { (item_display_path(right.as_str())) }\n+ }\n+ }\n+ div id=\"vote-edge-history-region\" {\n+ (edge_history)\n+ }\n+ @if can_post {\n+ form id=\"vote-compare-form\" method=\"POST\" action=\"/ui\" {\n+ input type=\"hidden\" name=(UI_RPC_FIELD) value=(rpc_json);\n+ div class=\"vote-thread-picker\" {\n+ label class=\"vote-thread-picker-label\" { \"thread\" }\n+ select id=\"vote-thread-select\" name=\"thread_tag\" aria-label=\"Thread to post vote into\" {\n+ @if thread_tags.is_empty() {\n+ option value=\"vote\" selected { \"#vote\" }\n }\n- input type=\"hidden\" name=\"ratio_left\" id=\"vote-ratio-left\" value=\"50\";\n- input type=\"hidden\" name=\"ratio_right\" id=\"vote-ratio-right\" value=\"50\";\n- label class=\"vote-compare-slider-label\" {\n- span id=\"vote-slider-left-label\" { (item_display_path(left.as_str())) }\n- input type=\"range\" id=\"vote-preference-slider\" min=\"0\" max=\"100\" value=\"50\"\n- aria-valuemin=\"0\" aria-valuemax=\"100\";\n- span id=\"vote-slider-right-label\" { (item_display_path(right.as_str())) }\n+ @for t in &thread_tags {\n+ @if *t == auto_thread {\n+ option value=(t) selected { \"#\" (t) }\n+ } @else {\n+ option value=(t) { \"#\" (t) }\n+ }\n }\n- label class=\"vote-explain-label\" { \"reason (required)\" }\n- textarea name=\"explanation\" id=\"vote-explain\" rows=\"5\" placeholder=\"why this split?\" required {}\n- div id=\"vote-compare-errors\" {}\n- p { button type=\"submit\" { \"post vote\" } }\n }\n- } @else {\n- p class=\"muted\" { a href=\"/login\" { \"log in\" } \" to post this vote.\" }\n }\n+ input type=\"hidden\" name=\"ratio_left\" id=\"vote-ratio-left\" value=\"50\";\n+ input type=\"hidden\" name=\"ratio_right\" id=\"vote-ratio-right\" value=\"50\";\n+ label class=\"vote-compare-slider-label\" {\n+ span id=\"vote-slider-left-label\" { (item_display_path(left.as_str())) }\n+ input type=\"range\" id=\"vote-preference-slider\" min=\"0\" max=\"100\" value=\"50\"\n+ aria-valuemin=\"0\" aria-valuemax=\"100\";\n+ span id=\"vote-slider-right-label\" { (item_display_path(right.as_str())) }\n+ }\n+ label class=\"vote-explain-label\" { \"reason (required)\" }\n+ textarea name=\"explanation\" id=\"vote-explain\" rows=\"5\" placeholder=\"why this split?\" required {}\n+ div id=\"vote-compare-errors\" {}\n+ p { button type=\"submit\" { \"post vote\" } }\n }\n+ } @else {\n+ p class=\"muted\" { a href=\"/login\" { \"log in\" } \" to post this vote.\" }\n+ }\n };\n \n let page = layout_full_bleed_chromeless(\ndiff --git a/server/static/theme_default.css b/server/static/theme_default.css\nindex a441c4f79d8cf88f5a8240f9992f47dbbd1ab46b..fdcde86c718eb53cce8273e45a9844c2d8041f88 100644\n--- a/server/static/theme_default.css\n+++ b/server/static/theme_default.css\n@@ -1270,8 +1270,12 @@ body.view-ontology-dark .ont-ranking-list li {\n body.view-ontology-dark .ont-ranking-list li::before {\n color: var(--meta);\n content: counter(ont-rank) \".\";\n- font-size: 11px;\n- min-width: 18px;\n+ flex-shrink: 0;\n+ font-size: 1.35rem;\n+ font-weight: 700;\n+ font-variant-numeric: tabular-nums;\n+ line-height: 1;\n+ min-width: 2.25ch;\n text-align: right;\n }\n body.view-ontology-dark .ont-rank-score {\n@@ -1424,8 +1428,12 @@ body.view-ontology-light .ont-ranking-list li {\n body.view-ontology-light .ont-ranking-list li::before {\n color: var(--meta);\n content: counter(ont-rank) \".\";\n- font-size: 11px;\n- min-width: 18px;\n+ flex-shrink: 0;\n+ font-size: 1.35rem;\n+ font-weight: 700;\n+ font-variant-numeric: tabular-nums;\n+ line-height: 1;\n+ min-width: 2.25ch;\n text-align: right;\n }\n body.view-ontology-light .ont-rank-score {\ndiff --git a/server/static/theme_retro.css b/server/static/theme_retro.css\nindex 373f15bbd75b62604cdd14b9f0fadda2d6176991..61e1448b2f66a075c0e33325d6980448712fc927 100644\n--- a/server/static/theme_retro.css\n+++ b/server/static/theme_retro.css\n@@ -135,6 +135,30 @@ body.view-ontology nav.breadcrumb a:hover {\n body.view-ontology nav.breadcrumb a.bc-current { color: #111; font-weight: 600; }\n body.view-ontology nav.breadcrumb .bc-sep { color: #888; padding: 0 2px; }\n \n+body.view-ontology ol.ont-ranking-list {\n+ counter-reset: ont-rank;\n+ list-style: none;\n+ margin: 0.5rem 0;\n+ padding: 0;\n+}\n+body.view-ontology ol.ont-ranking-list li {\n+ align-items: baseline;\n+ counter-increment: ont-rank;\n+ display: flex;\n+ gap: 0.35rem;\n+}\n+body.view-ontology ol.ont-ranking-list li::before {\n+ flex-shrink: 0;\n+ color: #666;\n+ content: counter(ont-rank) \".\";\n+ font-size: 1.35rem;\n+ font-weight: 700;\n+ font-variant-numeric: tabular-nums;\n+ line-height: 1;\n+ min-width: 2.25ch;\n+ text-align: right;\n+}\n+\n nav.breadcrumb.ont-sibling-nav {\n margin-top: 0;\n width: 100%;\ndiff --git a/server/static/theme_retro_craft.css b/server/static/theme_retro_craft.css\nindex 6eb9222184a8795d67a5d09d41de08c8ac1b148f..7da102040484c887833158a37c307d078205c701 100644\n--- a/server/static/theme_retro_craft.css\n+++ b/server/static/theme_retro_craft.css\n@@ -742,12 +742,32 @@ body.view-ontology button.ont-garden-pin-ico:focus-visible {\n outline-offset: 2px;\n }\n \n+body.view-ontology ol.ont-ranking-list {\n+ counter-reset: ont-rank;\n+ list-style: none;\n+ margin: 0;\n+ padding: 0;\n+}\n body.view-ontology ol.ont-ranking-list li,\n body.view-ontology ul.ont-group-list li {\n display: flex;\n align-items: baseline;\n gap: 0.35rem;\n }\n+body.view-ontology ol.ont-ranking-list li {\n+ counter-increment: ont-rank;\n+}\n+body.view-ontology ol.ont-ranking-list li::before {\n+ flex-shrink: 0;\n+ color: #5c574e;\n+ content: counter(ont-rank) \".\";\n+ font-size: 1.35rem;\n+ font-weight: 700;\n+ font-variant-numeric: tabular-nums;\n+ line-height: 1;\n+ min-width: 2.25ch;\n+ text-align: right;\n+}\n body.view-ontology ol.ont-ranking-list li .item-link,\n body.view-ontology ul.ont-group-list li .item-link {\n flex: 1;\n\n\nSide B — contributor: tommy-mor\nSide B — commit message:\n[2e4be477] format\n\nSide B — unified diff (full patch):\ndiff --git a/server/src/html/garden.rs b/server/src/html/garden.rs\nindex 76ba96e45c9e16291a6ccd8096fdd01b274c1560..2d5fcd903fe8f56800ad2c5564b704bd25f9b18d 100644\n--- a/server/src/html/garden.rs\n+++ b/server/src/html/garden.rs\n@@ -9,30 +9,28 @@ use serde::Deserialize;\n use serde_json::json;\n use std::collections::HashSet;\n \n-use base64::{engine::general_purpose::URL_SAFE_NO_PAD as B64_ENGINE, Engine as _};\n+use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD as B64_ENGINE};\n \n use crate::{\n api::optional_principal,\n canonical_path::{canonicalize_item, canonicalize_tag},\n- form_template::template_json_compact,\n- html::{\n- ui_action::UI_RPC_FIELD,\n- user_can_post_room,\n- JsBuilder,\n- },\n events::ThreadCapability,\n+ form_template::template_json_compact,\n+ html::{JsBuilder, ui_action::UI_RPC_FIELD, user_can_post_room},\n path_types::ItemId,\n- reducer::{scope_from_room_wire, ContentState, ReducerState, ScopeId},\n- scope_rank::{build_children_rankings, ChildrenRankings},\n+ reducer::{ContentState, ReducerState, ScopeId, scope_from_room_wire},\n+ scope_rank::{ChildrenRankings, build_children_rankings},\n state::AppState,\n timeago,\n };\n \n use super::{\n- bc_path, bc_path_external, bc_segment, cli_panel, layout, layout_full_bleed_chromeless, now_ms,\n- ratio_pct, render_linkified_with_embeds_in_scope, theme_from_jar, theme_next_from_uri,\n+ bc_path, bc_path_external, bc_segment,\n breadcrumb_path::{ExternalOntologyPath, OntologyPath},\n- forum::{ingest_entry_markup, ThreadNav},\n+ cli_panel,\n+ forum::{ThreadNav, ingest_entry_markup},\n+ layout, layout_full_bleed_chromeless, now_ms, ratio_pct, render_linkified_with_embeds_in_scope,\n+ theme_from_jar, theme_next_from_uri,\n };\n \n /// `GET /vote/compare` — pairs `left` / `right` query params with optional `thread`.\n@@ -90,7 +88,11 @@ fn canonical_edge_items(a: &ItemId, b: &ItemId) -> (ItemId, ItemId) {\n }\n \n /// All votes whose endpoints are exactly this unordered pair (unsorted).\n-fn edge_vote_entries_for_pair(content: &ContentState, a: &ItemId, b: &ItemId) -> Vec {\n+fn edge_vote_entries_for_pair(\n+ content: &ContentState,\n+ a: &ItemId,\n+ b: &ItemId,\n+) -> Vec {\n let (lo, hi) = canonical_edge_items(a, b);\n let lo_s = lo.as_str();\n let hi_s = hi.as_str();\n@@ -107,7 +109,11 @@ fn edge_vote_entries_for_pair(content: &ContentState, a: &ItemId, b: &ItemId) ->\n .collect()\n }\n \n-fn ratios_for_compare_page(v: &crate::reducer::VoteData, page_left: &ItemId, page_right: &ItemId) -> (i32, i32) {\n+fn ratios_for_compare_page(\n+ v: &crate::reducer::VoteData,\n+ page_left: &ItemId,\n+ page_right: &ItemId,\n+) -> (i32, i32) {\n let pl = page_left.as_str();\n let pr = page_right.as_str();\n match (v.a.as_str(), v.b.as_str()) {\n@@ -121,11 +127,7 @@ fn left_share_normalized(ratio_left: i32, ratio_right: i32) -> f64 {\n let l = ratio_left.max(0) as f64;\n let r = ratio_right.max(0) as f64;\n let sum = l + r;\n- if sum <= 0.0 {\n- 0.5\n- } else {\n- l / sum\n- }\n+ if sum <= 0.0 { 0.5 } else { l / sum }\n }\n \n /// Stronger preference for **`page_left` first**; ties **newer first**.\n@@ -177,11 +179,7 @@ fn vote_thread_tags_for_pair(content: &ContentState, a: &ItemId, b: &ItemId) ->\n v.into_iter().map(|t| canonicalize_tag(&t)).collect()\n }\n \n-fn vote_edge_history_markup(\n- content: &ContentState,\n- left: &ItemId,\n- right: &ItemId,\n-) -> maud::Markup {\n+fn vote_edge_history_markup(content: &ContentState, left: &ItemId, right: &ItemId) -> maud::Markup {\n let votes = edge_vote_entries_for_pair(content, left, right);\n let votes = sort_votes_for_compare_display(votes, left, right);\n let legend_left = item_display_path(left.as_str());\n@@ -276,7 +274,12 @@ fn item_code_label(item: &str) -> String {\n item_display_path(item)\n }\n \n-fn vote_compare_href(nav: &ThreadNav, left: &ItemId, right: &ItemId, thread_override: Option<&str>) -> String {\n+fn vote_compare_href(\n+ nav: &ThreadNav,\n+ left: &ItemId,\n+ right: &ItemId,\n+ thread_override: Option<&str>,\n+) -> String {\n let left_q = urlencoding::encode(left.as_str());\n let right_q = urlencoding::encode(right.as_str());\n let base = format!(\n@@ -299,7 +302,8 @@ fn ont_pin_vote_controls(\n next_path: &str,\n ) -> maud::Markup {\n let room_wire = nav.room_wire.clone();\n- let current = ItemId::parse(current_storage).unwrap_or_else(|| ItemId::opaque(current_storage.to_string()));\n+ let current = ItemId::parse(current_storage)\n+ .unwrap_or_else(|| ItemId::opaque(current_storage.to_string()));\n let pin_matches_scope = pinned_room_and_item\n .map(|(r, _)| r == nav.room_wire.as_str())\n .unwrap_or(false);\n@@ -307,26 +311,22 @@ fn ont_pin_vote_controls(\n .filter(|_| pin_matches_scope)\n .map(|(_, i)| i);\n \n- let pin_rpc = template_json_compact(\n- &json!({\n- \"action\": \"set_garden_pin\",\n- \"clear\": false,\n- \"room_wire\": room_wire,\n- \"item_storage\": current.as_str(),\n- \"next\": next_path,\n- \"form_action\": \"/ui\",\n- }),\n- )\n+ let pin_rpc = template_json_compact(&json!({\n+ \"action\": \"set_garden_pin\",\n+ \"clear\": false,\n+ \"room_wire\": room_wire,\n+ \"item_storage\": current.as_str(),\n+ \"next\": next_path,\n+ \"form_action\": \"/ui\",\n+ }))\n .expect(\"pin rpc json\");\n- let unpin_rpc = template_json_compact(\n- &json!({\n- \"action\": \"set_garden_pin\",\n- \"clear\": true,\n- \"room_wire\": \"\",\n- \"next\": next_path,\n- \"form_action\": \"/ui\",\n- }),\n- )\n+ let unpin_rpc = template_json_compact(&json!({\n+ \"action\": \"set_garden_pin\",\n+ \"clear\": true,\n+ \"room_wire\": \"\",\n+ \"next\": next_path,\n+ \"form_action\": \"/ui\",\n+ }))\n .expect(\"unpin rpc json\");\n \n html! {\n@@ -497,9 +497,9 @@ fn room_scope_has_garden_content(reduced: &ReducerState, nav: &ThreadNav) -> boo\n fn content_for_garden_view<'a>(reduced: &'a ReducerState, scope: &ScopeId) -> &'a ContentState {\n match scope {\n ScopeId::Public => reduced.public(),\n- ScopeId::Room(_) => reduced.content_for_scope(scope).expect(\n- \"room garden only renders after room_scope_has_garden_content returned true\",\n- ),\n+ ScopeId::Room(_) => reduced\n+ .content_for_scope(scope)\n+ .expect(\"room garden only renders after room_scope_has_garden_content returned true\"),\n }\n }\n \n@@ -723,10 +723,8 @@ pub async fn room_external_garden_index(\n }\n let ext_path = ExternalOntologyPath::from_input(\"\");\n let parent = ItemId::parse(\"https://.\").unwrap();\n- let child_rankings = build_children_rankings(\n- content_for_garden_view(&reduced, &nav.scope()),\n- &parent,\n- );\n+ let child_rankings =\n+ build_children_rankings(content_for_garden_view(&reduced, &nav.scope()), &parent);\n drop(reduced);\n \n let page = layout(\n@@ -953,48 +951,74 @@ fn build_rank_history(\n None => return vec![],\n Some(e) => e,\n };\n- entries.iter().map(|e| {\n- // Resolve caused_by: votes from this ingest that directly touched this item.\n- let caused_by: Vec = reduced.ingests_by_id\n- .get(&e.post_id)\n- .and_then(|ing| crate::dsl::parse_full(&ing.raw).ok())\n- .map(|doc| {\n- doc.statements.into_iter().filter_map(|s| {\n- if let crate::dsl::Stmt::Vote { item1, item2, ratio_left, ratio_right, explanation } = s {\n- let a_str = crate::canonical_path::canonicalize_item(&item1);\n- let b_str = crate::canonical_path::canonicalize_item(&item2);\n- if a_str == item || b_str == item {\n- Some(crate::reducer::VoteData {\n- ts: e.ts,\n- a: ItemId::parse(&a_str).unwrap_or_else(|| ItemId::opaque(a_str)),\n- b: ItemId::parse(&b_str).unwrap_or_else(|| ItemId::opaque(b_str)),\n- ratio_left, ratio_right,\n- body: explanation,\n- principal: reduced.ingests_by_id.get(&e.post_id)\n- .map(|ing| ing.principal.clone())\n- .unwrap_or_default(),\n- delegate: reduced.ingests_by_id.get(&e.post_id).and_then(|ing| ing.delegate.clone()),\n- thread_tag: e.thread.clone(),\n- })\n- } else { None }\n- } else { None }\n- }).collect()\n- })\n- .unwrap_or_default();\n-\n- let thread_post_index =\n- reduced.thread_post_index_chronological(scope, &e.thread, &e.post_id);\n-\n- RankHistoryEntryView {\n- ts: e.ts,\n- scope_rank: e.scope_rank,\n- scope_total: e.scope_total,\n- scope_rank_delta: e.scope_rank_delta,\n- thread: e.thread.clone(),\n- thread_post_index,\n- caused_by,\n- }\n- }).collect()\n+ entries\n+ .iter()\n+ .map(|e| {\n+ // Resolve caused_by: votes from this ingest that directly touched this item.\n+ let caused_by: Vec = reduced\n+ .ingests_by_id\n+ .get(&e.post_id)\n+ .and_then(|ing| crate::dsl::parse_full(&ing.raw).ok())\n+ .map(|doc| {\n+ doc.statements\n+ .into_iter()\n+ .filter_map(|s| {\n+ if let crate::dsl::Stmt::Vote {\n+ item1,\n+ item2,\n+ ratio_left,\n+ ratio_right,\n+ explanation,\n+ } = s\n+ {\n+ let a_str = crate::canonical_path::canonicalize_item(&item1);\n+ let b_str = crate::canonical_path::canonicalize_item(&item2);\n+ if a_str == item || b_str == item {\n+ Some(crate::reducer::VoteData {\n+ ts: e.ts,\n+ a: ItemId::parse(&a_str)\n+ .unwrap_or_else(|| ItemId::opaque(a_str)),\n+ b: ItemId::parse(&b_str)\n+ .unwrap_or_else(|| ItemId::opaque(b_str)),\n+ ratio_left,\n+ ratio_right,\n+ body: explanation,\n+ principal: reduced\n+ .ingests_by_id\n+ .get(&e.post_id)\n+ .map(|ing| ing.principal.clone())\n+ .unwrap_or_default(),\n+ delegate: reduced\n+ .ingests_by_id\n+ .get(&e.post_id)\n+ .and_then(|ing| ing.delegate.clone()),\n+ thread_tag: e.thread.clone(),\n+ })\n+ } else {\n+ None\n+ }\n+ } else {\n+ None\n+ }\n+ })\n+ .collect()\n+ })\n+ .unwrap_or_default();\n+\n+ let thread_post_index =\n+ reduced.thread_post_index_chronological(scope, &e.thread, &e.post_id);\n+\n+ RankHistoryEntryView {\n+ ts: e.ts,\n+ scope_rank: e.scope_rank,\n+ scope_total: e.scope_total,\n+ scope_rank_delta: e.scope_rank_delta,\n+ thread: e.thread.clone(),\n+ thread_post_index,\n+ caused_by,\n+ }\n+ })\n+ .collect()\n }\n \n fn build_item_page_view_model(\n@@ -1301,23 +1325,28 @@ async fn vote_compare_inner(\n let edge_history = vote_edge_history_markup(content, &left, &right);\n drop(reduced);\n \n- let title = format!(\"vote — {} vs {}\", item_display_path(left.as_str()), item_display_path(right.as_str()));\n- let next_path = uri.path_and_query().map(|pq| pq.as_str().to_string()).unwrap_or_else(|| \"/vote/compare\".into());\n-\n- let rpc_json = template_json_compact(\n- &json!({\n- \"action\": \"vote_compare_post\",\n- \"room\": nav.room_wire,\n- \"thread_tag\": {\"$form\": \"thread_tag\"},\n- \"left_item\": left.as_str(),\n- \"right_item\": right.as_str(),\n- \"ratio_left\": {\"$form\": \"ratio_left\"},\n- \"ratio_right\": {\"$form\": \"ratio_right\"},\n- \"explanation\": {\"$form\": \"explanation\"},\n- \"next\": next_path,\n- \"form_action\": \"/ui\",\n- }),\n- )\n+ let title = format!(\n+ \"vote — {} vs {}\",\n+ item_display_path(left.as_str()),\n+ item_display_path(right.as_str())\n+ );\n+ let next_path = uri\n+ .path_and_query()\n+ .map(|pq| pq.as_str().to_string())\n+ .unwrap_or_else(|| \"/vote/compare\".into());\n+\n+ let rpc_json = template_json_compact(&json!({\n+ \"action\": \"vote_compare_post\",\n+ \"room\": nav.room_wire,\n+ \"thread_tag\": {\"$form\": \"thread_tag\"},\n+ \"left_item\": left.as_str(),\n+ \"right_item\": right.as_str(),\n+ \"ratio_left\": {\"$form\": \"ratio_left\"},\n+ \"ratio_right\": {\"$form\": \"ratio_right\"},\n+ \"explanation\": {\"$form\": \"explanation\"},\n+ \"next\": next_path,\n+ \"form_action\": \"/ui\",\n+ }))\n .expect(\"vote compare rpc json\");\n \n let body = html! {\n@@ -1532,11 +1561,23 @@ mod tests {\n .iter()\n .map(|r| r.item.as_str())\n .collect();\n- assert_eq!(names, vec![\"https://slug.social/~/topic/a\", \"https://slug.social/~/topic/b\"]);\n+ assert_eq!(\n+ names,\n+ vec![\n+ \"https://slug.social/~/topic/a\",\n+ \"https://slug.social/~/topic/b\"\n+ ]\n+ );\n use crate::path_types::ItemId;\n assert!(\n- model.child_rankings.unranked_items.contains(&ItemId::parse(\"https://slug.social/~/topic/kid1\").unwrap())\n- || model.child_rankings.unranked_items.contains(&ItemId::parse(\"https://slug.social/~/topic/kid2\").unwrap())\n+ model\n+ .child_rankings\n+ .unranked_items\n+ .contains(&ItemId::parse(\"https://slug.social/~/topic/kid1\").unwrap())\n+ || model\n+ .child_rankings\n+ .unranked_items\n+ .contains(&ItemId::parse(\"https://slug.social/~/topic/kid2\").unwrap())\n );\n }\n \n@@ -1609,11 +1650,8 @@ mod tests {\n 1,\n \"@00000000-0000-0000-0000-000000000000:test:local/test\\n~/x {x}\\n\",\n );\n- let model = build_item_page_view_model(\n- &reduced,\n- &ScopeId::Public,\n- \"https://slug.social/~/\",\n- );\n+ let model =\n+ build_item_page_view_model(&reduced, &ScopeId::Public, \"https://slug.social/~/\");\n assert_eq!(model.child_rankings.unranked_items.len(), 1);\n assert_eq!(\n model.child_rankings.unranked_items[0].as_str(),\n","role":"user"}],"model":"~anthropic/claude-sonnet-latest"}