constitution · epochs · watch · epoch 3

comparison

c_257b57c092b1 (tommy-mor) vs c_164969eeea14 (tommy-mor)

download prompt · raw event · cmp_5d5fc673c2ad18

council reasoning

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

Side B delivers a real user-facing feature (account/alias management page, alias switching, re-linking OAuth) with corresponding CSS, template, and test updates, representing lasting functional value. Side A is a solid but narrow internal refactor (Rc<RefCell> -> plain HashMap + OnceLock singleton) that improves code quality and enables Send+Sync but has much smaller scope and impact than B's feature work.

~x-ai/grok-latest · winner B · 2:5 · permalink

B delivers a lasting product surface: /login becomes a real account page (trust weight, alias list/switch, claim forms, OAuth re-link) with shared claim UI, CSS, and test updates. A is a solid parser design fix (drop Rc<RefCell>, Send+Sync handlers, OnceLock-cached graph) but stays an internal efficiency/thread-safety refactor with less user-facing value.

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

Side A refactors the parser graph to be immutable after construction, removes unnecessary Rc<RefCell> indirection, makes handlers Send + Sync, and caches the graph in a OnceLock so it is built once and safely reused. Side B adds a substantial account-management UI (alias switching, claiming, OAuth relinking, styling, and page restructuring), but it is primarily a feature/UI expansion rather than a foundational runtime improvement with broad, lasting performance and thread-safety benefits.

sides

A — c_257b57c092b1 (tommy-mor)

message

[d63870bc] fix

diff preview

diff --git a/server/src/parser.rs b/server/src/parser.rs
index 4bf201008857e3082b70a55e3dcbb2502ab3ed22..ea437c4434045b44cba04a2b3416df850db518e7 100644
--- a/server/src/parser.rs
+++ b/server/src/parser.rs
@@ -1,6 +1,6 @@
 use std::collections::HashMap;
-use std::rc::Rc;
-use std::cell::RefCell;
+use std::sync::OnceLock;
+
 use crate::parser_action::{GuideOption, ParserAction, ScrollingSuggestion, Suggestion};
 
 // --- Core Abstractions ---
@@ -98,8 +98,8 @@ pub struct Edge {
     description: Option<&'static str>,
 }
 
-/// Handler function for generating UI actions
-type Handler = Box<dyn Fn(&str, &str, &HashMap<String, String>) -> ParserAction>;
+/// Handler function for generating UI actions (Send + Sync so the graph can live in `OnceLock`).
+type Handler = Box<dyn Fn(&str, &str, &HashMap<String, String>) -> ParserAction + Send + Sync>;
 
 /// Node in the graph
 pub struct Node {
@@ -109,16 +109,16 @@ pub struct Node {
     handler: Option<Handler>,
 }
 
-/// The composable parser graph
+/// The composable parser graph (immutable after `build`).
 pub struct Graph {
-    nodes: HashMap<NodeId, Rc<RefCell<Node>>>,
+    nodes: HashMap<NodeId, Node>,
     root: NodeId,
 }
 
 // --- Graph Builder (Fluent API) ---
 
 pub struct GraphBuilder {
-    nodes: HashMap<NodeId, Rc<RefCell<Node>>>,
+    nodes: HashMap<NodeId, Node>,
     current_node: Option<NodeId>,
     root: NodeId,
 }
@@ -126,31 +126,29 @@ pub struct GraphBuilder {
 impl GraphBuilder {
     pub fn new() -> Self {
         let mut nodes = HashMap::new();
-        let root_node = Rc::new(RefCell::new(Node {
-            id: "root",
-            edges: Vec::new(),
-            handler: None,
-        }));
-        nodes.insert("root", root_node);
-        
+        nodes.insert(
+            "root",
+            Node {
+                id: "root",
+                edges: Vec::new(),
+                handler: None,
+            },
+        );
+
         GraphBuilder {
             nodes,
             current_node: Some("root"),
             root: "root",
         }
     }
-    
+
     /// Select a node to add edges to
     pub fn at(mut self, node_id: NodeId) -> Self {
-        // Create node if it doesn't exist
-        if !self.nodes.contains_key(node_id) {
-            let node = Rc::new(RefCell::new(Node {
-                id: node_id,
-                edges: Vec::new(),
-                handler: None,
-            }));
-            self.nodes.insert(node_id, node);
-        }
+        self.nodes.entry(node_id).or_insert_with(|| Node {
+            id: node_id,
+            edges: Vec::new(),
+            handler: None,
+        });
         self.current_node = Some(node_id);
         self
     }
@@ -161,39 +159,39 @@ impl GraphBuilder {
     }
     
     /// Add an edge with description
-    pub fn edge_with_desc(mut self, pattern: EdgePattern, target: NodeId, desc: Option<&'static str>) -> Self {
+    pub fn edge_with_desc(
+        mut self,
+        pattern: EdgePattern,
+        target: NodeId,
+        desc: Option<&'static str>,
+    ) -> Self {
         let current = self.current_node.expect("No current node selected");
-        
-        // Create target node if it doesn't exist
-        if !self.nodes.contains_key(target) {
-            let node = Rc::new(RefCell::new(Node {
-                id: target,
-                edges: Vec::new(),
-                handler: None,
-            }));
-            self.nodes.insert(target, node);
-        }
-        
-        // Add edge to current node
-        if let Some(node) = self.nodes.get(current) {
-            node.borrow_mut().edges.push(Edge {
+
+        self.nodes.entry(target).or_insert_with(|| Node {
+            id: target,
+            edges: Vec::new(),
+            handler: None,
+        });
+
+        if let Some(node) = self.nodes.get_mut(current) {
+            node.edges.push(Edge {
                 pattern,
                 target,
                 description: desc,
             });
         }
-        
+
         self
     }
-    
+
     /// Set handler for current node
-    pub fn handler<F>(self, handler: F) -> Self 
-    where 
-        F: Fn(&str, &str, &HashMap<String, String>) -> ParserAction + 'static
+    pub fn handler<F>(mut self, handler: F) -> Self
+    where
+        F: Fn(&str, &str, &HashMap<String, String>) -> ParserAction + Send + Sync + 'static,
     {
         let current = self.current_node.expect("No current node selected");
-        if let Some(node) = self.nodes.get(current) {
-            node.borrow_mut().handler = Some(Box::new(handler));
+        if let Some(node) = self.nodes.get_mut(current) {
+            node.handler = Some(Box::new(handler));
         }
         self
     }
@@ -225,24 +223,25 @@ impl Graph {
     }
     
     fn parse_recursive(&self, state: &mut ParserState) -> ParserAction {
-        let node = self.nodes.get(state.current_node_id)
+        let node = self
+            .nodes
+            .get(state.current_node_id)
             .expect("Node not found in graph");
-        let node_ref = node.borrow();
-        
+
         // If we've consumed all input, check for handler or suggestions
         if state.cursor >= state.input.len() {
-            if let Some(handler) = &node_ref.handler {
+            if let Some(handler) = &node.handler {
                 return handler(&state.original_query, &state.current_prefix, &state.context);
             }
-            
+
             // No handler, try to suggest based on available edges
-            return self.suggest_from_edges(&node_ref, state);
+            return self.suggest_from_edges(node, state);
         }
-        
+
         let remaining = &state.input[state.cursor..];
-        
+
         // Try to match each edge
-        for edge in &node_ref.edges {
+        for edge in &node.edges {
             if let Some((consumed, captured)) = edge.pattern.matches(remaining) {
                 // Save state for potential backtracking
                 let saved_cursor = state.cursor;
@@ -297,7 +296,7 @@ impl Graph {
         }
         
         // No edges matched - try to provide suggestions
-        self.suggest_from_edges(&node_ref, state)
+        self.suggest_from_edges(node, state)
     }
     
     fn suggest_from_edges(&self, node: &Node, state: &ParserState) -> ParserAction {
@@ -692,10 +691,15 @@ pub fn build_reddit_graph() -> Graph {
 
 // --- Public API ---
 
+static REDDIT_GRAPH: OnceLock<Graph> = OnceLock::new();
+
+fn reddit_graph() -> &'static Graph {
+    REDDIT_GRAPH.get_or_init(build_reddit_graph)
+}
+
 /// Parse a query string and return a UI action
 pub fn parse_reddit_url(query: &str) -> ParserAction {
-    let graph = build_reddit_graph();
-    graph.parse(query)
+    reddit_graph().parse(query)
 }
 
 #[cfg(test)]

download full diff A

B — c_164969eeea14 (tommy-mor)

message

[d6b4a41e] Turn /login into an account page with alias switching.

Signed-in users can see trust weight, switch aliases, claim new ones, and re-link OAuth from one place.

Co-authored-by: Cursor <cursoragent@cursor.com>

diff preview

diff --git a/server/src/auth/mod.rs b/server/src/auth/mod.rs
index d4a85ef52c15dc35148e4c743f0d646cbbdb056d..5906f93b13853421e96a3c37bc9d8202a47842bf 100644
--- a/server/src/auth/mod.rs
+++ b/server/src/auth/mod.rs
@@ -94,63 +94,169 @@ fn alias_list(db: &durable::Db, uuid: &str) -> Vec<String> {
         .unwrap_or_default()
 }
 
-fn login_body(
-    session: Option<&session::SessionActor>,
+fn alias_claim_forms(return_to: &str, submit_label: &str) -> Result<Markup, StatusCode> {
+    let check_rpc = template_json_compact(&serde_json::json!({
+        "action": "check_pseudonym",
+        "pseudonym": {"$form": "pseudonym"},
+    }))
+    .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
+    let claim_rpc = template_json_compact(&serde_json::json!({
+        "action": "claim_pseudonym",
+        "pseudonym": {"$form": "pseudonym"},
+        "return_to": return_to,
+    }))
+    .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
+
+    Ok(html! {
+        div class="alias-claim" {
+            form id="alias-check-form" method="POST" action="/ui" {
+                input type="hidden" name=(UI_RPC_FIELD) value=(check_rpc);
+                label for="alias-input" { "alias" }
+                input type="text" id="alias-input" name="pseudonym" autocomplete="off"
+                    data-testid="alias-input" maxlength="64" placeholder="letters, numbers, _ -";
+                p id="alias-status" class="muted" data-testid="alias-status" { "type to check availability" }
+            }
+            form id="alias-claim-form" method="POST" action="/ui" {
+                input type="hidden" name=(UI_RPC_FIELD) value=(claim_rpc);
+                input type="hidden" name="pseudonym" id="alias-claim-field" value="";
+                button type="submit" class="btn-primary" data-testid="alias-claim" { (submit_label) }
+            }
+        }
+    })
+}
+
+fn signed_out_body(providers: &[(&str, String)]) -> Markup {
+    html! {
+        main class="panel login-page" {
+            section class="login-section" {
+                h1 { "sign in" }
+                p class="muted" { "link an account to vote under a lasting alias" }
+                @if providers.is_empty() {
+                    p class="muted" {
+                        "OAuth is not configured. Set GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET."
+                    }
+                } @else {
+                    ul class="oauth-provider-list" {
+                        @for (name, href) in providers {
+                            li {
+                                a href=(href) class="btn-primary oauth-provider"
+                                    data-testid=(format!("oauth-{}", name.to_lowercase())) {
+                                    (format!("Continue with {name}"))
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            p class="login-back" { a href="/" { "← back" } }
+        }
+    }
+}
+
+fn account_body(
+    actor: &session::SessionActor,
     aliases: &[String],
     providers: &[(&str, String)],
+    claim_forms: Markup,
 ) -> Markup {
+    let current = actor.pseudonym.trim();
     html! {
-        main class="panel login-page" {
-            div class="login-grid" {
-                section class="login-oauth" {
-                    h1 { "sign in" }
-                    @if providers.is_empty() {
-                        p class="muted" {
-                            "OAuth is not configured. Set GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET."
-                        }
-                    } @else {
-                        ul class="oauth-provider-list" {
-                            @for (name, href) in providers {
-                                li {
-                                    a href=(href) class="button oauth-provider" data-testid=(format!("oauth-{}", name.to_lowercase())) {
-                                        (format!("Continue with {name}"))
+        main class="panel login-page account-page" {
+            section class="login-section" {
+                h1 { "account" }
+                @if current.is_empty() {
+                    p class="muted" { "finish setup by choosing an alias below" }
+                } @else {
+                    p class="account-current" {
+                        "voting as "
+                        strong data-testid="account-current" { (current) }
+                    }
+                }
+                p class="muted small" data-testid="account-weight" {
+                    "trust weight " (format!("{:.1}", actor.trust_weight))
+                    " · rises when you link more OAuth providers"
+                }
+            }
+
+            section class="login-section" {
+                h2 { "aliases" }
+                @if aliases.is_empty() {
+                    p class="muted" data-testid="alias-list-empty" { "none yet — claim one below" }
+                } @else {
+                    ul id="alias-list" class="alias-list" data-testid="alias-list" {
+                        @for alias in aliases {
+                            @let is_current = alias == current;
+                            li class=(if is_current { "alias-item alias-current" } else { "alias-item" }) {
+                                span class="alias-name" { (alias) }
+                                @if is_current {
+                                    span class="alias-badge" data-testid="alias-current-badge" { "current" }
+                                } @else {
+                                    form class="alias-switch" method="post" action="/auth/switch"
+                                        data-navigate="full" {
+                                        input type="hidden" name="pseudonym" value=(alias);
+                                        button type="submit" class="btn-secondary"
+                                            data-testid=(format!("alias-switch-{alias}")) {
+                                            "use"
+                                        }
                                     }
                                 }
                             }
                         }
                     }
-                    @if let Some(actor) = session {
-                        p class="muted small" {
-                            "session active · weight " (format!("{:.1}", actor.trust_weight))
-                        }
-                        form method="post" action="/auth/logout" data-navigate="full" {
-                            button type="submit" { "log out" }
-                        }
-                    }
                 }
-                section class="login-aliases" {
-                    h2 { "your aliases" }
-                    ul id="alias-list" class="alias-list" {
-                        @if aliases.is_empty() {
-                            li class="muted" data-testid="alias-list-empty" { "none yet" }
-                        } @else {
-                            @for alias in aliases {
-                                li { (alias) }
+            }
+
+            section class="login-section" {
+                h2 { "add alias" }
+                p class="muted small" { "each alias is unique across sorter2" }
+                (claim_forms)
+            }
+
+            @if !providers.is_empty() {
+                section class="login-section" {
+                    h2 { "linked sign-in" }
+                    p class="muted small" { "sign in again with the same provider to return to this account" }
+                    ul class="oauth-provider-list" {
+                        @for (name, href) in providers {
+                            li {
+                                a href=(href) class="btn-secondary oauth-provider"
+                                    data-testid=(format!("oauth-relink-{}", name.to_lowercase())) {
+                                    (format!("Re-link {name}"))
+                                }
                             }
                         }
                     }
                 }
             }
-            p { a href="/" { "← back" } }
+
+            section class="login-section login-actions" {
+                form method="post" action="/auth/logout" data-navigate="full" {
+                    button type="submit" class="btn-secondary" data-testid="account-logout" { "log out" }
+                }
+            }
+
+            p class="login-back" { a href="/" { "← back" } }
         }
     }
 }
 
+fn login_body(
+    session: Option<&session::SessionActor>,
+    aliases: &[String],
+    providers: &[(&str, String)],
+    claim_forms: Option<Markup>,
+) -> Markup {
+    match (session, claim_forms) {
+        (Some(actor), Some(forms)) => account_body(actor, aliases, providers, forms),
+        _ => signed_out_body(providers),
+    }
+}
+
 pub async fn login_page(
     State(state): State<AppState>,
     jar: CookieJar,
     Query(query): Query<LoginQuery>,
-) -> Response {
+) -> Result<Response, StatusCode> {
     let return_to = return_from_query_or_jar(&jar, query.return_to.as_deref());
     let jar = jar.add(session::auth_return_cookie_value(&return_to));
 
@@ -164,16 +270,26 @@ pub async fn login_page(
         .unwrap_or_default();
     let providers = oauth_providers(&base_url_from_env(state.cfg.port), &return_to);
 
+    let claim_forms = if session.is_some() {
+        Some(alias_claim_forms("/login", "claim alias")?)
+    } else {
+        None
+    };
+
     let markup = layout(
-        "login · sorter2",
-        login_body(session.as_ref(), &aliases, &providers),
+        if session.is_some() {
+            "account · sorter2"
+        } else {
+            "login · sorter2"
+        },
+        login_body(session.as_ref(), &aliases, &providers, claim_forms),
         state.views.get_views("/login"),
         session
             .as_ref()
             .filter(|s| !s.pseudonym.trim().is_empty())
             .map(|s| s.pseudonym.as_str()),
     );
-    (jar, Html(markup.into_string())).into_response()
+    Ok((jar, Html(markup.into_string())).into_response())
 }
 
 pub async fn alias_page(
@@ -186,38 +302,17 @@ pub async fn alias_page(
     let db = state.projection_store.db();
     let session = session::load_valid_session(db, &session_id).ok_or(StatusCode::UNAUTHORIZED)?;
     if session::session_has_pseudonym(&session) {
-        return Ok(Redirect::to(&return_to).into_response());
+        // Already onboarded — manage aliases on the account page.
+        return Ok(Redirect::to("/login").into_response());
     }
 
-    let check_rpc = template_json_compact(&serde_json::json!({
-        "action": "check_pseudonym",
-        "pseudonym": {"$form": "pseudonym"},
-    }))
-    .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
-    let claim_rpc = template_json_compact(&serde_json::json!({
-        "action": "claim_pseudonym",
-        "pseudonym": {"$form": "pseudonym"},
-        "return_to": return_to,
-    }))
-    .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
-
+    let claim_forms = alias_claim_forms(&return_to, "continue")?;
     let body = html! {
         main class="panel alias-page" {
             h1 { "choose alias" }
             p class="muted" { "pick a unique display name for your votes" }
-            form id="alias-check-form" method="POST" action="/ui" {
-                input type="hidden" name=(UI_RPC_FIELD) value=(check_rpc);
-                label { "alias" }
-                input type="text" id="alias-input" name="pseudonym" autocomplete="off"
-                    data-testid="alias-input" maxlength="64";
-                p id="alias-status" class="muted" data-testid="alias-status" { "type to check availability" }
-            }
-            form id="alias-claim-form" method="POST" action="/ui" {
-                input type="hidden" name=(UI_RPC_FIELD) value=(claim_rpc);
-                input type="hidden" nam

… preview truncated; 4,534 characters omitted

download full diff B

Hardlinks — judgments / attempts / prompt

prompt download

judgments

attempts

Prompt text is loaded only by the download route.