{"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[d63870bc] fix\n\nSide A — unified diff (full patch):\ndiff --git a/server/src/parser.rs b/server/src/parser.rs\nindex 4bf201008857e3082b70a55e3dcbb2502ab3ed22..ea437c4434045b44cba04a2b3416df850db518e7 100644\n--- a/server/src/parser.rs\n+++ b/server/src/parser.rs\n@@ -1,6 +1,6 @@\n use std::collections::HashMap;\n-use std::rc::Rc;\n-use std::cell::RefCell;\n+use std::sync::OnceLock;\n+\n use crate::parser_action::{GuideOption, ParserAction, ScrollingSuggestion, Suggestion};\n \n // --- Core Abstractions ---\n@@ -98,8 +98,8 @@ pub struct Edge {\n description: Option<&'static str>,\n }\n \n-/// Handler function for generating UI actions\n-type Handler = Box) -> ParserAction>;\n+/// Handler function for generating UI actions (Send + Sync so the graph can live in `OnceLock`).\n+type Handler = Box) -> ParserAction + Send + Sync>;\n \n /// Node in the graph\n pub struct Node {\n@@ -109,16 +109,16 @@ pub struct Node {\n handler: Option,\n }\n \n-/// The composable parser graph\n+/// The composable parser graph (immutable after `build`).\n pub struct Graph {\n- nodes: HashMap>>,\n+ nodes: HashMap,\n root: NodeId,\n }\n \n // --- Graph Builder (Fluent API) ---\n \n pub struct GraphBuilder {\n- nodes: HashMap>>,\n+ nodes: HashMap,\n current_node: Option,\n root: NodeId,\n }\n@@ -126,31 +126,29 @@ pub struct GraphBuilder {\n impl GraphBuilder {\n pub fn new() -> Self {\n let mut nodes = HashMap::new();\n- let root_node = Rc::new(RefCell::new(Node {\n- id: \"root\",\n- edges: Vec::new(),\n- handler: None,\n- }));\n- nodes.insert(\"root\", root_node);\n- \n+ nodes.insert(\n+ \"root\",\n+ Node {\n+ id: \"root\",\n+ edges: Vec::new(),\n+ handler: None,\n+ },\n+ );\n+\n GraphBuilder {\n nodes,\n current_node: Some(\"root\"),\n root: \"root\",\n }\n }\n- \n+\n /// Select a node to add edges to\n pub fn at(mut self, node_id: NodeId) -> Self {\n- // Create node if it doesn't exist\n- if !self.nodes.contains_key(node_id) {\n- let node = Rc::new(RefCell::new(Node {\n- id: node_id,\n- edges: Vec::new(),\n- handler: None,\n- }));\n- self.nodes.insert(node_id, node);\n- }\n+ self.nodes.entry(node_id).or_insert_with(|| Node {\n+ id: node_id,\n+ edges: Vec::new(),\n+ handler: None,\n+ });\n self.current_node = Some(node_id);\n self\n }\n@@ -161,39 +159,39 @@ impl GraphBuilder {\n }\n \n /// Add an edge with description\n- pub fn edge_with_desc(mut self, pattern: EdgePattern, target: NodeId, desc: Option<&'static str>) -> Self {\n+ pub fn edge_with_desc(\n+ mut self,\n+ pattern: EdgePattern,\n+ target: NodeId,\n+ desc: Option<&'static str>,\n+ ) -> Self {\n let current = self.current_node.expect(\"No current node selected\");\n- \n- // Create target node if it doesn't exist\n- if !self.nodes.contains_key(target) {\n- let node = Rc::new(RefCell::new(Node {\n- id: target,\n- edges: Vec::new(),\n- handler: None,\n- }));\n- self.nodes.insert(target, node);\n- }\n- \n- // Add edge to current node\n- if let Some(node) = self.nodes.get(current) {\n- node.borrow_mut().edges.push(Edge {\n+\n+ self.nodes.entry(target).or_insert_with(|| Node {\n+ id: target,\n+ edges: Vec::new(),\n+ handler: None,\n+ });\n+\n+ if let Some(node) = self.nodes.get_mut(current) {\n+ node.edges.push(Edge {\n pattern,\n target,\n description: desc,\n });\n }\n- \n+\n self\n }\n- \n+\n /// Set handler for current node\n- pub fn handler(self, handler: F) -> Self \n- where \n- F: Fn(&str, &str, &HashMap) -> ParserAction + 'static\n+ pub fn handler(mut self, handler: F) -> Self\n+ where\n+ F: Fn(&str, &str, &HashMap) -> ParserAction + Send + Sync + 'static,\n {\n let current = self.current_node.expect(\"No current node selected\");\n- if let Some(node) = self.nodes.get(current) {\n- node.borrow_mut().handler = Some(Box::new(handler));\n+ if let Some(node) = self.nodes.get_mut(current) {\n+ node.handler = Some(Box::new(handler));\n }\n self\n }\n@@ -225,24 +223,25 @@ impl Graph {\n }\n \n fn parse_recursive(&self, state: &mut ParserState) -> ParserAction {\n- let node = self.nodes.get(state.current_node_id)\n+ let node = self\n+ .nodes\n+ .get(state.current_node_id)\n .expect(\"Node not found in graph\");\n- let node_ref = node.borrow();\n- \n+\n // If we've consumed all input, check for handler or suggestions\n if state.cursor >= state.input.len() {\n- if let Some(handler) = &node_ref.handler {\n+ if let Some(handler) = &node.handler {\n return handler(&state.original_query, &state.current_prefix, &state.context);\n }\n- \n+\n // No handler, try to suggest based on available edges\n- return self.suggest_from_edges(&node_ref, state);\n+ return self.suggest_from_edges(node, state);\n }\n- \n+\n let remaining = &state.input[state.cursor..];\n- \n+\n // Try to match each edge\n- for edge in &node_ref.edges {\n+ for edge in &node.edges {\n if let Some((consumed, captured)) = edge.pattern.matches(remaining) {\n // Save state for potential backtracking\n let saved_cursor = state.cursor;\n@@ -297,7 +296,7 @@ impl Graph {\n }\n \n // No edges matched - try to provide suggestions\n- self.suggest_from_edges(&node_ref, state)\n+ self.suggest_from_edges(node, state)\n }\n \n fn suggest_from_edges(&self, node: &Node, state: &ParserState) -> ParserAction {\n@@ -692,10 +691,15 @@ pub fn build_reddit_graph() -> Graph {\n \n // --- Public API ---\n \n+static REDDIT_GRAPH: OnceLock = OnceLock::new();\n+\n+fn reddit_graph() -> &'static Graph {\n+ REDDIT_GRAPH.get_or_init(build_reddit_graph)\n+}\n+\n /// Parse a query string and return a UI action\n pub fn parse_reddit_url(query: &str) -> ParserAction {\n- let graph = build_reddit_graph();\n- graph.parse(query)\n+ reddit_graph().parse(query)\n }\n \n #[cfg(test)]\n\n\nSide B — contributor: tommy-mor\nSide B — commit message:\n[d6b4a41e] Turn /login into an account page with alias switching.\n\nSigned-in users can see trust weight, switch aliases, claim new ones, and re-link OAuth from one place.\n\nCo-authored-by: Cursor \n\nSide B — unified diff (full patch):\ndiff --git a/server/src/auth/mod.rs b/server/src/auth/mod.rs\nindex d4a85ef52c15dc35148e4c743f0d646cbbdb056d..5906f93b13853421e96a3c37bc9d8202a47842bf 100644\n--- a/server/src/auth/mod.rs\n+++ b/server/src/auth/mod.rs\n@@ -94,63 +94,169 @@ fn alias_list(db: &durable::Db, uuid: &str) -> Vec {\n .unwrap_or_default()\n }\n \n-fn login_body(\n- session: Option<&session::SessionActor>,\n+fn alias_claim_forms(return_to: &str, submit_label: &str) -> Result {\n+ let check_rpc = template_json_compact(&serde_json::json!({\n+ \"action\": \"check_pseudonym\",\n+ \"pseudonym\": {\"$form\": \"pseudonym\"},\n+ }))\n+ .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;\n+ let claim_rpc = template_json_compact(&serde_json::json!({\n+ \"action\": \"claim_pseudonym\",\n+ \"pseudonym\": {\"$form\": \"pseudonym\"},\n+ \"return_to\": return_to,\n+ }))\n+ .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;\n+\n+ Ok(html! {\n+ div class=\"alias-claim\" {\n+ form id=\"alias-check-form\" method=\"POST\" action=\"/ui\" {\n+ input type=\"hidden\" name=(UI_RPC_FIELD) value=(check_rpc);\n+ label for=\"alias-input\" { \"alias\" }\n+ input type=\"text\" id=\"alias-input\" name=\"pseudonym\" autocomplete=\"off\"\n+ data-testid=\"alias-input\" maxlength=\"64\" placeholder=\"letters, numbers, _ -\";\n+ p id=\"alias-status\" class=\"muted\" data-testid=\"alias-status\" { \"type to check availability\" }\n+ }\n+ form id=\"alias-claim-form\" method=\"POST\" action=\"/ui\" {\n+ input type=\"hidden\" name=(UI_RPC_FIELD) value=(claim_rpc);\n+ input type=\"hidden\" name=\"pseudonym\" id=\"alias-claim-field\" value=\"\";\n+ button type=\"submit\" class=\"btn-primary\" data-testid=\"alias-claim\" { (submit_label) }\n+ }\n+ }\n+ })\n+}\n+\n+fn signed_out_body(providers: &[(&str, String)]) -> Markup {\n+ html! {\n+ main class=\"panel login-page\" {\n+ section class=\"login-section\" {\n+ h1 { \"sign in\" }\n+ p class=\"muted\" { \"link an account to vote under a lasting alias\" }\n+ @if providers.is_empty() {\n+ p class=\"muted\" {\n+ \"OAuth is not configured. Set GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET.\"\n+ }\n+ } @else {\n+ ul class=\"oauth-provider-list\" {\n+ @for (name, href) in providers {\n+ li {\n+ a href=(href) class=\"btn-primary oauth-provider\"\n+ data-testid=(format!(\"oauth-{}\", name.to_lowercase())) {\n+ (format!(\"Continue with {name}\"))\n+ }\n+ }\n+ }\n+ }\n+ }\n+ }\n+ p class=\"login-back\" { a href=\"/\" { \"← back\" } }\n+ }\n+ }\n+}\n+\n+fn account_body(\n+ actor: &session::SessionActor,\n aliases: &[String],\n providers: &[(&str, String)],\n+ claim_forms: Markup,\n ) -> Markup {\n+ let current = actor.pseudonym.trim();\n html! {\n- main class=\"panel login-page\" {\n- div class=\"login-grid\" {\n- section class=\"login-oauth\" {\n- h1 { \"sign in\" }\n- @if providers.is_empty() {\n- p class=\"muted\" {\n- \"OAuth is not configured. Set GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET.\"\n- }\n- } @else {\n- ul class=\"oauth-provider-list\" {\n- @for (name, href) in providers {\n- li {\n- a href=(href) class=\"button oauth-provider\" data-testid=(format!(\"oauth-{}\", name.to_lowercase())) {\n- (format!(\"Continue with {name}\"))\n+ main class=\"panel login-page account-page\" {\n+ section class=\"login-section\" {\n+ h1 { \"account\" }\n+ @if current.is_empty() {\n+ p class=\"muted\" { \"finish setup by choosing an alias below\" }\n+ } @else {\n+ p class=\"account-current\" {\n+ \"voting as \"\n+ strong data-testid=\"account-current\" { (current) }\n+ }\n+ }\n+ p class=\"muted small\" data-testid=\"account-weight\" {\n+ \"trust weight \" (format!(\"{:.1}\", actor.trust_weight))\n+ \" · rises when you link more OAuth providers\"\n+ }\n+ }\n+\n+ section class=\"login-section\" {\n+ h2 { \"aliases\" }\n+ @if aliases.is_empty() {\n+ p class=\"muted\" data-testid=\"alias-list-empty\" { \"none yet — claim one below\" }\n+ } @else {\n+ ul id=\"alias-list\" class=\"alias-list\" data-testid=\"alias-list\" {\n+ @for alias in aliases {\n+ @let is_current = alias == current;\n+ li class=(if is_current { \"alias-item alias-current\" } else { \"alias-item\" }) {\n+ span class=\"alias-name\" { (alias) }\n+ @if is_current {\n+ span class=\"alias-badge\" data-testid=\"alias-current-badge\" { \"current\" }\n+ } @else {\n+ form class=\"alias-switch\" method=\"post\" action=\"/auth/switch\"\n+ data-navigate=\"full\" {\n+ input type=\"hidden\" name=\"pseudonym\" value=(alias);\n+ button type=\"submit\" class=\"btn-secondary\"\n+ data-testid=(format!(\"alias-switch-{alias}\")) {\n+ \"use\"\n+ }\n }\n }\n }\n }\n }\n- @if let Some(actor) = session {\n- p class=\"muted small\" {\n- \"session active · weight \" (format!(\"{:.1}\", actor.trust_weight))\n- }\n- form method=\"post\" action=\"/auth/logout\" data-navigate=\"full\" {\n- button type=\"submit\" { \"log out\" }\n- }\n- }\n }\n- section class=\"login-aliases\" {\n- h2 { \"your aliases\" }\n- ul id=\"alias-list\" class=\"alias-list\" {\n- @if aliases.is_empty() {\n- li class=\"muted\" data-testid=\"alias-list-empty\" { \"none yet\" }\n- } @else {\n- @for alias in aliases {\n- li { (alias) }\n+ }\n+\n+ section class=\"login-section\" {\n+ h2 { \"add alias\" }\n+ p class=\"muted small\" { \"each alias is unique across sorter2\" }\n+ (claim_forms)\n+ }\n+\n+ @if !providers.is_empty() {\n+ section class=\"login-section\" {\n+ h2 { \"linked sign-in\" }\n+ p class=\"muted small\" { \"sign in again with the same provider to return to this account\" }\n+ ul class=\"oauth-provider-list\" {\n+ @for (name, href) in providers {\n+ li {\n+ a href=(href) class=\"btn-secondary oauth-provider\"\n+ data-testid=(format!(\"oauth-relink-{}\", name.to_lowercase())) {\n+ (format!(\"Re-link {name}\"))\n+ }\n }\n }\n }\n }\n }\n- p { a href=\"/\" { \"← back\" } }\n+\n+ section class=\"login-section login-actions\" {\n+ form method=\"post\" action=\"/auth/logout\" data-navigate=\"full\" {\n+ button type=\"submit\" class=\"btn-secondary\" data-testid=\"account-logout\" { \"log out\" }\n+ }\n+ }\n+\n+ p class=\"login-back\" { a href=\"/\" { \"← back\" } }\n }\n }\n }\n \n+fn login_body(\n+ session: Option<&session::SessionActor>,\n+ aliases: &[String],\n+ providers: &[(&str, String)],\n+ claim_forms: Option,\n+) -> Markup {\n+ match (session, claim_forms) {\n+ (Some(actor), Some(forms)) => account_body(actor, aliases, providers, forms),\n+ _ => signed_out_body(providers),\n+ }\n+}\n+\n pub async fn login_page(\n State(state): State,\n jar: CookieJar,\n Query(query): Query,\n-) -> Response {\n+) -> Result {\n let return_to = return_from_query_or_jar(&jar, query.return_to.as_deref());\n let jar = jar.add(session::auth_return_cookie_value(&return_to));\n \n@@ -164,16 +270,26 @@ pub async fn login_page(\n .unwrap_or_default();\n let providers = oauth_providers(&base_url_from_env(state.cfg.port), &return_to);\n \n+ let claim_forms = if session.is_some() {\n+ Some(alias_claim_forms(\"/login\", \"claim alias\")?)\n+ } else {\n+ None\n+ };\n+\n let markup = layout(\n- \"login · sorter2\",\n- login_body(session.as_ref(), &aliases, &providers),\n+ if session.is_some() {\n+ \"account · sorter2\"\n+ } else {\n+ \"login · sorter2\"\n+ },\n+ login_body(session.as_ref(), &aliases, &providers, claim_forms),\n state.views.get_views(\"/login\"),\n session\n .as_ref()\n .filter(|s| !s.pseudonym.trim().is_empty())\n .map(|s| s.pseudonym.as_str()),\n );\n- (jar, Html(markup.into_string())).into_response()\n+ Ok((jar, Html(markup.into_string())).into_response())\n }\n \n pub async fn alias_page(\n@@ -186,38 +302,17 @@ pub async fn alias_page(\n let db = state.projection_store.db();\n let session = session::load_valid_session(db, &session_id).ok_or(StatusCode::UNAUTHORIZED)?;\n if session::session_has_pseudonym(&session) {\n- return Ok(Redirect::to(&return_to).into_response());\n+ // Already onboarded — manage aliases on the account page.\n+ return Ok(Redirect::to(\"/login\").into_response());\n }\n \n- let check_rpc = template_json_compact(&serde_json::json!({\n- \"action\": \"check_pseudonym\",\n- \"pseudonym\": {\"$form\": \"pseudonym\"},\n- }))\n- .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;\n- let claim_rpc = template_json_compact(&serde_json::json!({\n- \"action\": \"claim_pseudonym\",\n- \"pseudonym\": {\"$form\": \"pseudonym\"},\n- \"return_to\": return_to,\n- }))\n- .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;\n-\n+ let claim_forms = alias_claim_forms(&return_to, \"continue\")?;\n let body = html! {\n main class=\"panel alias-page\" {\n h1 { \"choose alias\" }\n p class=\"muted\" { \"pick a unique display name for your votes\" }\n- form id=\"alias-check-form\" method=\"POST\" action=\"/ui\" {\n- input type=\"hidden\" name=(UI_RPC_FIELD) value=(check_rpc);\n- label { \"alias\" }\n- input type=\"text\" id=\"alias-input\" name=\"pseudonym\" autocomplete=\"off\"\n- data-testid=\"alias-input\" maxlength=\"64\";\n- p id=\"alias-status\" class=\"muted\" data-testid=\"alias-status\" { \"type to check availability\" }\n- }\n- form id=\"alias-claim-form\" method=\"POST\" action=\"/ui\" {\n- input type=\"hidden\" name=(UI_RPC_FIELD) value=(claim_rpc);\n- input type=\"hidden\" name=\"pseudonym\" id=\"alias-claim-field\" value=\"\";\n- button type=\"submit\" class=\"btn-primary\" data-testid=\"alias-claim\" { \"continue\" }\n- }\n- p { a href=\"/login\" { \"← back to login\" } }\n+ (claim_forms)\n+ p class=\"login-back\" { a href=\"/login\" { \"← back to login\" } }\n }\n };\n \ndiff --git a/server/src/html/mod.rs b/server/src/html/mod.rs\nindex 3cc3d7bdf55b5cb5d009600f4ade1fcd201a410b..5b9b73c7ad24499737f0576b3603c3ff5355251e 100644\n--- a/server/src/html/mod.rs\n+++ b/server/src/html/mod.rs\n@@ -149,7 +149,7 @@ pub(crate) fn layout(title: &str, body: Markup, views: u64, nav_user: Option<&st\n nav class=\"top-nav\" {\n @if let Some(name) = nav_user {\n span class=\"top-nav-user\" data-testid=\"nav-user\" { (name) }\n- a href=\"/login\" { \"account\" }\n+ a href=\"/login\" data-testid=\"nav-account\" { \"account\" }\n form class=\"top-nav-logout\" method=\"post\" action=\"/auth/logout\" data-navigate=\"full\" {\n button type=\"submit\" data-testid=\"nav-logout\" { \"log out\" }\n }\ndiff --git a/server/static/sorter.css b/server/static/sorter.css\nindex 257280b6b490c65222e580a325b77351cac6cc6b..e7aca23b426d504938b90b5a25ad06b07843ba02 100644\n--- a/server/static/sorter.css\n+++ b/server/static/sorter.css\n@@ -108,6 +108,152 @@ body {\n cursor: wait;\n }\n \n+.panel {\n+ max-width: 36rem;\n+ margin: 1.5rem auto;\n+ padding: 1.25rem 1.5rem;\n+ background: var(--panel);\n+ border: 1px solid var(--border);\n+}\n+\n+.login-page h1,\n+.alias-page h1 {\n+ margin: 0 0 0.35rem;\n+ font-size: 1.5rem;\n+}\n+\n+.login-page h2,\n+.alias-page h2 {\n+ margin: 0 0 0.5rem;\n+ font-size: 1.05rem;\n+ font-weight: 600;\n+}\n+\n+.login-section {\n+ margin-bottom: 1.5rem;\n+}\n+\n+.login-section:last-of-type {\n+ margin-bottom: 0.75rem;\n+}\n+\n+.account-current {\n+ margin: 0.25rem 0 0.5rem;\n+ font-size: 1.1rem;\n+}\n+\n+.oauth-provider-list {\n+ list-style: none;\n+ margin: 1rem 0 0;\n+ padding: 0;\n+ display: flex;\n+ flex-direction: column;\n+ gap: 0.5rem;\n+}\n+\n+.oauth-provider-list a {\n+ text-align: center;\n+ text-decoration: none;\n+ margin-top: 0;\n+}\n+\n+.alias-list {\n+ list-style: none;\n+ margin: 0.5rem 0 0;\n+ padding: 0;\n+ display: flex;\n+ flex-direction: column;\n+ gap: 0.4rem;\n+}\n+\n+.alias-item {\n+ display: flex;\n+ align-items: center;\n+ justify-content: space-between;\n+ gap: 0.75rem;\n+ padding: 0.55rem 0.75rem;\n+ border: 1px solid var(--border);\n+ background: var(--bg);\n+}\n+\n+.alias-item.alias-current {\n+ border-color: var(--accent);\n+}\n+\n+.alias-name {\n+ font-weight: 600;\n+}\n+\n+.alias-badge {\n+ font-size: 0.75rem;\n+ color: var(--accent);\n+ text-transform: lowercase;\n+}\n+\n+.alias-switch {\n+ margin: 0;\n+}\n+\n+.alias-switch .btn-secondary {\n+ margin-top: 0;\n+}\n+\n+.alias-claim label {\n+ display: block;\n+ margin-bottom: 0.35rem;\n+ color: var(--muted);\n+ font-size: 0.875rem;\n+}\n+\n+.alias-claim input[type=\"text\"] {\n+ width: 100%;\n+ padding: 0.5rem 0.65rem;\n+ background: var(--bg);\n+ border: 1px solid var(--border);\n+ color: var(--fg);\n+ font: inherit;\n+}\n+\n+.alias-claim input[type=\"text\"]:focus {\n+ outline: 1px solid var(--accent);\n+ border-color: var(--accent);\n+}\n+\n+#alias-status {\n+ margin: 0.4rem 0 0.75rem;\n+ min-height: 1.25em;\n+}\n+\n+#alias-status.alias-ok {\n+ color: #8fd19e;\n+}\n+\n+#alias-status.alias-bad {\n+ color: #e8a0a0;\n+}\n+\n+.login-actions {\n+ padding-top: 0.75rem;\n+ border-top: 1px solid var(--border);\n+}\n+\n+.login-actions .btn-secondary {\n+ margin-top: 0;\n+}\n+\n+.login-back {\n+ margin: 1rem 0 0;\n+}\n+\n+.login-back a {\n+ color: var(--muted);\n+ text-decoration: none;\n+}\n+\n+.login-back a:hover {\n+ color: var(--fg);\n+}\n+\n .fetch-entity-form {\n margin-top: 0.5rem;\n }\ndiff --git a/test/auth_login.clj b/test/auth_login.clj\nindex a81e064ebb88fe359c56cf6718880dc1e4c1a7d9..6f2f00d7aa7340e63d1ac465b0a2234cec7a983f 100644\n--- a/test/auth_login.clj\n+++ b/test/auth_login.clj\n@@ -55,7 +55,6 @@\n (move-vote-slider-left pg)\n (loc/click (page/get-by-test-id pg \"vote-post\"))\n (page/wait-for-selector pg \"[data-testid=oauth-github]\" {:timeout 15000})\n- (is (str/includes? (or (element-text pg \"alias-list-empty\") \"\") \"none yet\"))\n (loc/click (page/get-by-test-id pg \"oauth-github\"))\n (page/wait-for-selector pg \"[data-testid=alias-input]\" {:timeout 15000})\n (type-alias! pg \"seeder\")\n","role":"user"}],"model":"openai/gpt-chat-latest"}