constitution · epochs · watch · epoch 3

comparison

c_3403e5929da7 (tommy-mor) vs c_cf0a514b261a (tommy-mor)

download prompt · raw event · cmp_95d09145142468

council reasoning

~anthropic/claude-sonnet-latest · winner B · 3:2 · permalink

Side B removes genuinely dead/redundant code with a clear rationale (guard is now unreachable given upstream validation) and updates the corresponding test to reflect the correct invariant, tightening the reducer's logic. Side A refactors sibling grouping in a UI-only helper (splitting unranked items into separate groups) with a matching test, which is a smaller, more cosmetic behavioral tweak with less systemic value than removing incorrect/dead logic in core reducer code.

~x-ai/grok-latest · winner A · 3:1 · permalink

A changes real sibling-nav behavior (each unranked item becomes its own group) with an updated contract and a dedicated regression test, which shapes lasting UI structure. B only deletes a redundant zero-ratio early-return already enforced upstream and retunes an existing test—useful hygiene, but no meaningful product or design effect.

openai/gpt-chat-latest · winner A · 3:2 · permalink

Side A makes a functional change to sibling navigation by placing each unranked sibling into its own navigation group instead of one combined group, and adds a targeted regression test verifying the new grouping behavior. Side B mainly removes a redundant zero-ratio early return and updates the test to reflect that items are still registered while zero-weight edges are skipped, which is a worthwhile cleanup but has a narrower long-term impact.

sides

A — c_3403e5929da7 (tommy-mor)

message

[65bce99f] sibling groups #130

diff preview

diff --git a/server/src/html/garden.rs b/server/src/html/garden.rs
index 82c1b4b4f36ea13a906035a1789ba893222b3695..e3c56d124ab7b0fa08c7f9ae736103e6b7cf5862 100644
--- a/server/src/html/garden.rs
+++ b/server/src/html/garden.rs
@@ -837,7 +837,8 @@ struct SiblingNavGroup {
     links: Vec<SiblingNavLink>,
 }
 
-/// Siblings under the same parent, grouped like child rankings (components then isolates).
+/// Siblings under the same parent: one group per ranking component (ordered list), then one
+/// group per isolated unranked sibling (each shows rank `1`, separated like components).
 #[derive(Debug, Clone)]
 struct SiblingNavBar {
     groups: Vec<SiblingNavGroup>,
@@ -890,15 +891,12 @@ fn build_sibling_nav(
             groups.push(SiblingNavGroup { links });
         }
     }
-    if !rankings.unranked_items.is_empty() {
-        let links: Vec<SiblingNavLink> = rankings
-            .unranked_items
-            .iter()
-            .map(|u| SiblingNavLink {
+    for u in &rankings.unranked_items {
+        groups.push(SiblingNavGroup {
+            links: vec![SiblingNavLink {
                 path: u.clone().normalized_storage().to_storage_string(),
-            })
-            .collect();
-        groups.push(SiblingNavGroup { links });
+            }],
+        });
     }
     let sibling_total: usize = groups.iter().map(|g| g.links.len()).sum();
     if sibling_total <= 1 {
@@ -1541,6 +1539,29 @@ mod tests {
         assert_eq!(nav.groups[1].links.len(), 1);
     }
 
+    #[test]
+    fn sibling_nav_splits_each_unranked_into_its_own_group() {
+        let mut reduced = ReducerState::default();
+        apply_ingest(
+            &mut reduced,
+            1,
+            "@00000000-0000-0000-0000-000000000000:test:local/test\n\
+             ~/topic {topic body}\n\
+             ~/topic/a {alpha}\n\
+             ~/topic/b {beta}\n\
+             ~/topic/c {gamma}\n\
+             ~/topic/d {delta}\n\
+             {a beats b}\n             ~/topic/a 2:1 ~/topic/b\n",
+        );
+
+        let model = build_item_page_view_model(&reduced, &ScopeId::Public, "~/topic/a");
+        let nav = model.sibling_nav.expect("expected sibling nav");
+        assert_eq!(nav.groups.len(), 3);
+        assert_eq!(nav.groups[0].links.len(), 2);
+        assert_eq!(nav.groups[1].links.len(), 1);
+        assert_eq!(nav.groups[2].links.len(), 1);
+    }
+
     #[test]
     fn item_page_model_builds_ranked_child_components() {
         let mut reduced = ReducerState::default();

download full diff A

B — c_cf0a514b261a (tommy-mor)

message

[047b82bd] Remove redundant zero-ratio guard from reducer.

Zeros are already rejected at the DSL parser and browser handler;
the guard in apply_vote was dead code. The negative clamping stays
since add_edge_weight already skips weight-0 edges correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

diff preview

diff --git a/server/src/reducer.rs b/server/src/reducer.rs
index 0e36979abe0f051493038ff7e652efc7f7a0ac80..efbf7f67ff24c7a2989102fe62879b2794a27c5f 100644
--- a/server/src/reducer.rs
+++ b/server/src/reducer.rs
@@ -112,11 +112,6 @@ impl GroupState {
         if vote.ratio_right < 0 {
             vote.ratio_right = 0;
         }
-        if vote.ratio_left == 0 || vote.ratio_right == 0 {
-            // Zero on either side produces no valid edge; drop before registering items or pair.
-            return;
-        }
-
         let a_idx = self.ensure_item(&vote.a);
         let b_idx = self.ensure_item(&vote.b);
 
diff --git a/server/tests/basic.rs b/server/tests/basic.rs
index 08159f4a7f0850fd165817a4a1af4f31ced2ad76..1748769ccf7196b2d81cf556d5368c7e723f6a4e 100644
--- a/server/tests/basic.rs
+++ b/server/tests/basic.rs
@@ -533,7 +533,7 @@ fn dsl_parse_rejects_zero_zero_vote_ratio() {
 #[test]
 fn reducer_negative_ratio_clamped_to_zero() {
     let _state = ReducerState::default();
-    // GroupState::apply_vote clamps negatives to 0; when either side is 0 the vote is dropped.
+    // apply_vote clamps negatives to 0; add_edge_weight skips zero-weight edges.
     let mut group = GroupState::new();
     group.apply_vote(slugsocial_server::reducer::VoteData {
         ts: 1,
@@ -546,10 +546,9 @@ fn reducer_negative_ratio_clamped_to_zero() {
         delegate: Some("00000000-0000-0000-0000-000000000000:test:local/test".to_string()),
         thread_tag: "t".to_string(),
     });
-    // Nothing registered: zero-clamped vote is dropped before ensure_item.
-    assert!(group.idx_to_item.is_empty());
+    // Items and pair are registered; edges are absent because weight 0 is skipped.
+    assert_eq!(group.idx_to_item.len(), 2);
     assert!(group.edges.is_empty());
-    assert!(group.voted_pairs.is_empty());
 }
 
 

download full diff B

Hardlinks — judgments / attempts / prompt

prompt download

judgments

attempts

Prompt text is loaded only by the download route.