constitution · epochs · watch · epoch 3

comparison

c_11d6a0ec9839 (tommy-mor) vs c_6f04dcb2e38c (tommy-mor)

download prompt · raw event · cmp_66ae10373aecdb

council reasoning

~anthropic/claude-sonnet-latest · winner A · 6:4 · permalink

Side A fixes a real, user-facing bug (attribution text leaking into DSL body, silent fallback to entire item pool producing nonsensical pairs, dead swap button) and cleanly renames a route across code and tests, all verified by adjusted integration tests. Side B is a substantial internal refactor removing legacy projection code for an evidence/ledger system, which is reasonable cleanup but is narrower in scope (affects one internal admin/evidence UI) and mostly deletes now-unneeded fallback logic rather than fixing an active correctness bug affecting end users.

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

B removes an entire dual-path legacy projection layer (_legacy_commit_row/_legacy_observation and GitDiscovery/Emission fallbacks on epoch/commit pages), making Evidence envelopes the sole source of truth and tightening Emission required fields—durable architectural cleanup. A’s real wins are the out-of-band delegate attribution fix and stopping the bad all-items fallback, but they sit beside lower-impact renames and UI chrome removal, so less structural lasting value.

openai/gpt-chat-latest · winner B · 4:1 · permalink

Side B removes the legacy GitDiscovery projection path and makes the evidence model authoritative by requiring emission metadata fields, deleting fallback lookup code, simplifying epoch/commit pages to use Evidence events only, and returning not-found instead of synthesizing historical views. In contrast, Side A mixes one real behavior fix (avoiding fallback to all items when the sibling pool is too small and passing delegate attribution out-of-band) with lower-impact UI and routing changes such as removing the swap button and renaming `/vote/compare` to `/vote`.

sides

A — c_11d6a0ec9839 (tommy-mor)

message

[36e92cf2] Fix /vote/compare page: attribution, fallback, swap button, and route rename.

- Pass WEB_BROWSER_AGENT as delegate_opt out-of-band (not in DSL body text)
- Error instead of falling back to all items when sibling pool < 2
- Remove pointless "swap sides" button
- Rename route /vote/compare → /vote

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

diff preview

diff --git a/server/src/api/rpc.rs b/server/src/api/rpc.rs
index 0b7070a2b7289e5c40778c8d062bd4150285a8df..8e3d8e34922ddaaa89ea699edd99402bd40fdb1b 100644
--- a/server/src/api/rpc.rs
+++ b/server/src/api/rpc.rs
@@ -281,6 +281,7 @@ pub async fn rpc_post_with_bearer(
     bearer_token: &str,
     room: String,
     thread_tag: String,
+    delegate_opt: Option<String>,
     text: String,
 ) -> Result<RpcResult, RpcErr> {
     use axum::http::{header, HeaderMap, HeaderValue};
@@ -288,7 +289,7 @@ pub async fn rpc_post_with_bearer(
     let hv = HeaderValue::from_str(&format!("Bearer {bearer_token}"))
         .map_err(|_| ("invalid session token".into(), None))?;
     headers.insert(header::AUTHORIZATION, hv);
-    rpc_post(state, &headers, room, thread_tag, None, text, false).await
+    rpc_post(state, &headers, room, thread_tag, delegate_opt, text, false).await
 }
 
 async fn rpc_check(
diff --git a/server/src/api/ui_html.rs b/server/src/api/ui_html.rs
index a13a94767d8905adc09e31effff838e166781b6c..5faa642451d69555cb391974beb0ad22c9355c8c 100644
--- a/server/src/api/ui_html.rs
+++ b/server/src/api/ui_html.rs
@@ -118,6 +118,7 @@ async fn dispatch_ui_action(
                 &session.bearer,
                 room.clone(),
                 thread_tag.clone(),
+                None,
                 text,
             )
             .await
@@ -246,8 +247,7 @@ async fn dispatch_ui_action(
             }
 
             let text = format!(
-                "@{}\n{{\n{}\n}}\n{} {}:{} {}\n",
-                crate::api::auth::WEB_BROWSER_AGENT,
+                "{{\n{}\n}}\n{} {}:{} {}\n",
                 exp,
                 left_id.as_str(),
                 rl,
@@ -260,6 +260,7 @@ async fn dispatch_ui_action(
                 &session.bearer,
                 room.clone(),
                 thread_tag.clone(),
+                Some(crate::api::auth::WEB_BROWSER_AGENT.to_string()),
                 text,
             )
             .await
diff --git a/server/src/html/forum/nav.rs b/server/src/html/forum/nav.rs
index d33dc50f0b89a5ed7730c3bca204a67f6309388f..ae67f550a4bdf0bbeff58384c29a715015b64bd5 100644
--- a/server/src/html/forum/nav.rs
+++ b/server/src/html/forum/nav.rs
@@ -85,7 +85,7 @@ impl ThreadNav {
         format!("{}/{}/{}", self.thread_path_prefix, tag, idx)
     }
 
-    /// Empty for public; `/r/:seg` for room — prefix for routes like `/vote/compare`.
+    /// Empty for public; `/r/:seg` for room — prefix for routes like `/vote`.
     pub(crate) fn room_path_prefix_for_vote_compare(&self) -> String {
         match &self.scope {
             ScopeId::Public => String::new(),
diff --git a/server/src/html/garden/vote.rs b/server/src/html/garden/vote.rs
index bdb4008c29ba49d7dc97b1cd2c32d9cdfce1ca04..1d7fc8aa7436bfa9c1186dfd940a8d751ab7e088 100644
--- a/server/src/html/garden/vote.rs
+++ b/server/src/html/garden/vote.rs
@@ -208,7 +208,7 @@ pub(crate) async fn vote_compare_post_success_js(
     state: &AppState,
     nav: &ThreadNav,
     _room_wire: &str,
-    thread_tag: &str,
+    _thread_tag: &str,
     left: &ItemId,
     right: &ItemId,
     _post_id: &str,
@@ -218,8 +218,7 @@ pub(crate) async fn vote_compare_post_success_js(
     let content = content_for_garden_view(&reduced, &nav.scope());
     let edge_history = vote_edge_history_markup(content, left, right);
     let next_pair = suggest_next_vote_pair(content, left, right);
-    let nav_markup =
-        vote_compare_nav_markup(nav, next_pair.as_ref(), left, right, Some(thread_tag));
+    let nav_markup = vote_compare_nav_markup(nav, next_pair.as_ref());
     drop(reduced);
     JsBuilder::new()
         .morph_inner_selector("#vote-edge-history-region", edge_history)
@@ -236,7 +235,7 @@ pub(super) fn vote_compare_href(
     let left_q = urlencoding::encode(left.as_str());
     let right_q = urlencoding::encode(right.as_str());
     let base = format!(
-        "{}/vote/compare?left={}&right={}",
+        "{}/vote?left={}&right={}",
         nav.room_path_prefix_for_vote_compare(),
         left_q,
         right_q
@@ -251,12 +250,8 @@ pub(super) fn vote_compare_href(
 fn vote_compare_nav_markup(
     nav: &ThreadNav,
     next_pair: Option<&(ItemId, ItemId)>,
-    left: &ItemId,
-    right: &ItemId,
-    thread_override: Option<&str>,
 ) -> maud::Markup {
     let next_pair_href = next_pair.map(|(nl, nr)| vote_compare_href(nav, nl, nr, None));
-    let swap_pair_href = vote_compare_href(nav, right, left, thread_override);
     html! {
         div class="vote-compare-nav" {
             @if let Some(href) = &next_pair_href {
@@ -264,7 +259,6 @@ fn vote_compare_nav_markup(
             } @else {
                 span class="vote-compare-next is-disabled" { "no next pair" }
             }
-            a class="vote-compare-next" href=(swap_pair_href) { "swap sides" }
         }
     }
 }
@@ -274,7 +268,7 @@ pub(super) fn suggest_next_vote_pair(
     current_left: &ItemId,
     current_right: &ItemId,
 ) -> Option<(ItemId, ItemId)> {
-    let mut pool: Vec<ItemId> = if current_left.parent().as_ref().map(|p| p.as_str())
+    let pool: Vec<ItemId> = if current_left.parent().as_ref().map(|p| p.as_str())
         == current_right.parent().as_ref().map(|p| p.as_str())
     {
         current_left
@@ -291,7 +285,7 @@ pub(super) fn suggest_next_vote_pair(
         Vec::new()
     };
     if pool.len() < 2 {
-        pool = content.items.iter().cloned().collect();
+        return None;
     }
     suggest_next_pair_in_pool(
         &content.ranking_group,
@@ -334,7 +328,7 @@ pub struct VoteCompareQuery {
     pub thread: Option<String>,
 }
 
-/// Public pairwise vote UI — `/vote/compare?left=&right=&thread=`.
+/// Public pairwise vote UI — `/vote?left=&right=&thread=`.
 pub async fn vote_compare_page(
     State(state): State<AppState>,
     Query(q): Query<VoteCompareQuery>,
@@ -426,7 +420,7 @@ async fn vote_compare_inner(
     let next_path = uri
         .path_and_query()
         .map(|pq| pq.as_str().to_string())
-        .unwrap_or_else(|| "/vote/compare".into());
+        .unwrap_or_else(|| "/vote".into());
 
     let rpc_json = template_json_compact(&json!({
         "action": "vote_compare_post",
@@ -462,7 +456,7 @@ async fn vote_compare_inner(
                 Some(&item_bodies_for_cards),
             ))
         }
-        (vote_compare_nav_markup(&nav, next_pair.as_ref(), &left, &right, q.thread.as_deref()))
+        (vote_compare_nav_markup(&nav, next_pair.as_ref()))
         div id="vote-edge-history-region" {
             (edge_history)
         }
diff --git a/server/src/html/ui_action.rs b/server/src/html/ui_action.rs
index c7b643c8dde37dd1e3001f5ff716fe4f79d24c5e..dd5294202569454acf9f41b458718700bbf96f39 100644
--- a/server/src/html/ui_action.rs
+++ b/server/src/html/ui_action.rs
@@ -38,7 +38,7 @@ pub enum HtmlUiAction {
         #[serde(default)]
         form_id: Option<String>,
     },
-    /// Post a pairwise vote from `/vote/compare` (browser compose).
+    /// Post a pairwise vote from `/vote` (browser compose).
     VoteComparePost {
         room: String,
         thread_tag: String,
diff --git a/server/src/lib.rs b/server/src/lib.rs
index ad8e31099c807fb5844acb16cd5086a2f19327a7..e102e73ec167fa35dcc22d4ec8c6f40202982429 100644
--- a/server/src/lib.rs
+++ b/server/src/lib.rs
@@ -82,9 +82,9 @@ pub fn create_app(state: AppState) -> Router {
         .route("/u/:username", get(crate::html::user_profile_page))
         .route("/try", get(crate::html::editor_page))
         .route("/try/check", post(crate::html::editor_check))
-        .route("/vote/compare", get(crate::html::vote_compare_page))
+        .route("/vote", get(crate::html::vote_compare_page))
         .route(
-            "/r/:room_key/vote/compare",
+            "/r/:room_key/vote",
             get(crate::html::room_vote_compare_page),
         )
         .route("/~", get(crate::html::garden_index))
diff --git a/server/tests/integration_html.rs b/server/tests/integration_html.rs
index a25a456c7cafd74a69e65e0c2e8ed2bfb2e27498..b3e31376737b2d5aabb739f408984a1f5ae0c974 100644
--- a/server/tests/integration_html.rs
+++ b/server/tests/integration_html.rs
@@ -52,12 +52,12 @@ async fn test_view_counts_increment_and_display() {
         .normalized_storage()
         .to_storage_string();
     let vote_q_right_first = format!(
-        "/vote/compare?right={}&left={}",
+        "/vote?right={}&left={}",
         urlencoding::encode(&right),
         urlencoding::encode(&left)
     );
     let vote_q_left_first = format!(
-        "/vote/compare?left={}&right={}",
+        "/vote?left={}&right={}",
         urlencoding::encode(&left),
         urlencoding::encode(&right)
     );
@@ -148,7 +148,7 @@ https://github.com/ghvotehi/a/issues/10 {\n\
         .normalized_storage()
         .to_storage_string();
     let q = format!(
-        "/vote/compare?left={}&right={}",
+        "/vote?left={}&right={}",
         urlencoding::encode(&left),
         urlencoding::encode(&right)
     );
diff --git a/server/tests/integration_ui.rs b/server/tests/integration_ui.rs
index 091afd922d28f48ab36aa9b9084aa825036d1f74..23db7b5672418d5bb0ab7529e05ef1f89e59062a 100644
--- a/server/tests/integration_ui.rs
+++ b/server/tests/integration_ui.rs
@@ -110,7 +110,7 @@ async fn test_choose_username_carries_redirect_next() {
             .expect("pending session must exist");
         pending.provider = Some("google".to_string());
         pending.provider_id = Some("google-user-redirect".to_string());
-        pending.redirect_next = Some("/vote/compare?left=%7E%2Fa&right=%7E%2Fb".to_string());
+        pending.redirect_next = Some("/vote?left=%7E%2Fa&right=%7E%2Fb".to_string());
     }
 
     let choose = client
@@ -122,7 +122,7 @@ async fn test_choose_username_carries_redirect_next() {
 
     assert_eq!(choose.status(), reqwest::StatusCode::OK);
     let body = choose.text().await.unwrap();
-    assert!(body.contains("window.location = \"/vote/compare?left=%7E%2Fa&right=%7E%2Fb\""));
+    assert!(body.contains("window.location = \"/vote?left=%7E%2Fa&right=%7E%2Fb\""));
 }
 
 #[tokio::test]
diff --git a/test/browser_vote_compare.clj b/test/browser_vote_compare.clj
index 7cd1e467fdd8a4480df1be2afd78adb45b9cdc6d..a98e144756421e1fa5064db6a9fc0dd8b08471c7 100644
--- a/test/browser_vote_compare.clj
+++ b/test/browser_vote_compare.clj
@@ -66,7 +66,7 @@
                       :headers {"Authorization" (str "Bearer " alice-token)})
            post-json (json/parse-string (:body post-resp) false)
            _ (is (true? (get-in post-json ["results" 0 "ok"])) "seed items + edge vote via rpc")
-           cmp-url (str base-url "/vote/compare?left=" (enc left-url) "&right=" (enc third-url))]
+           cmp-url (str base-url "/vote?left=" (enc left-url) "&right=" (enc third-url))]
        (core/with-playwright [pw]
          (core/with-browser [browser (core/launch-chromium pw {:headless true :channel "chrome"})]
            (core/with-context [ctx (core/new-context browser)]

download full diff A

B — c_6f04dcb2e38c (tommy-mor)

message

[bda5f8aa] Remove legacy evidence projection; Evidence envelopes only.

Epoch and commit pages no longer invent history from bare GitDiscovery rows. Production ledger will be wiped to re-emit under the current schema.

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

diff preview

diff --git a/constitution.py b/constitution.py
index 4dd5b9dfbba231d46289c490f91b1dd5b1018bcf..26ba130e885e0e69fb7874ca5c3f07f42100a150 100644
--- a/constitution.py
+++ b/constitution.py
@@ -210,10 +210,10 @@ class Emission:
     distributions: dict   # author -> amount str
     ranking: dict         # author -> score str
     models_used: list
-    discovery_snapshot_id: str = ""  # empty only for pre-discovery ledger history
-    evidence_schema_version: int = 1
-    ranking_run_id: str = ""
-    ranking_event_id: str = ""
+    discovery_snapshot_id: str
+    evidence_schema_version: int
+    ranking_run_id: str
+    ranking_event_id: str
 
 
 @event
@@ -502,26 +502,6 @@ def _epochs_in_ledger() -> list[int]:
     return sorted(epochs)
 
 
-def _legacy_commit_row(commit_id: str) -> tuple[GitDiscovery | None, dict | None]:
-    for discovery in store.read():
-        if not isinstance(discovery, GitDiscovery):
-            continue
-        for commit in discovery.commits:
-            if commit_id_for_oid(commit["oid"]) == commit_id:
-                return discovery, commit
-    return None, None
-
-
-def _legacy_observation(commit_id: str) -> tuple[GitDiscovery | None, dict | None]:
-    for discovery in store.read():
-        if not isinstance(discovery, GitDiscovery):
-            continue
-        for obs in discovery.observations:
-            if commit_id_for_oid(obs["oid"]) == commit_id:
-                return discovery, obs
-    return None, None
-
-
 def build_pairwise_prompt(side_a: dict, side_b: dict) -> str:
     return f"""You are ranking contributions to an open source project.
 Compare these two sides (each may be one or more commits). Decide which side contributed more.
@@ -2040,7 +2020,7 @@ def _strip_heavy_fields(obj: dict) -> dict:
 
 @app.get("/api/ledger")
 async def get_ledger(offset: int = 0, limit: int = 100, full: int = 0):
-    """List of ledger dicts (backward-compatible). Heavy blobs stripped unless full=1."""
+    """List of ledger dicts. Heavy blobs stripped unless full=1."""
     limit = max(1, min(limit, 500))
     rows = []
     for e in store.read()[offset:offset + limit]:
@@ -2274,23 +2254,25 @@ async def epochs_index():
     epochs = _epochs_in_ledger()
     rows = []
     for epoch in epochs:
-        discovery = _discovery_for_epoch(epoch)
         emission = _emission_for_epoch(epoch)
-        evidence_n = sum(
-            1 for e in evidence_by_kind() if e.epoch == epoch
+        evidence_n = sum(1 for e in evidence_by_kind() if e.epoch == epoch)
+        disc = next(
+            (
+                e for e in evidence_by_kind("git.discovery_completed")
+                if e.epoch == epoch
+            ),
+            None,
         )
         detail = []
-        if discovery:
+        if disc:
             detail.append(
-                f"{len(discovery.commits)} eligible / "
-                f"{len(discovery.observations)} observed"
+                f"{disc.payload.get('eligible_count', 0)} eligible / "
+                f"{disc.payload.get('observation_count', 0)} observed"
             )
         if emission:
             detail.append(f"emitted {emission.total_emitted}")
         if evidence_n:
             detail.append(f"{evidence_n} evidence events")
-        elif discovery or emission:
-            detail.append("legacy (no Evidence envelopes)")
         rows.append(["li",
             _a(_evidence_path("epoch", str(epoch)), f"epoch {epoch}"),
             " — ",
@@ -2307,37 +2289,37 @@ async def epochs_index():
 
 @app.get("/epochs/{epoch}")
 async def epoch_detail(epoch: int):
-    discovery = _discovery_for_epoch(epoch)
     emission = _emission_for_epoch(epoch)
     evidence_rows = [e for e in evidence_by_kind() if e.epoch == epoch]
+    if not evidence_rows and emission is None:
+        return _evidence_page(f"epoch {epoch}", [
+            _evidence_nav(),
+            ["h1", f"epoch {epoch}"],
+            ["p.note", "No evidence for this epoch."],
+        ])
+
     commit_evs = [e for e in evidence_rows if e.kind == "git.commit"]
     comparison_evs = [e for e in evidence_rows if e.kind == "comparison.input"]
     judgment_evs = [e for e in evidence_rows if e.kind == "llm.judgment"]
+    discovery_ev = next(
+        (e for e in evidence_rows if e.kind == "git.discovery_completed"), None
+    )
     ranking_started = next(
         (e for e in evidence_rows if e.kind == "ranking.started"), None
     )
     ranking_completed = next(
         (e for e in evidence_rows if e.kind == "ranking.completed"), None
     )
-    legacy = not evidence_rows and (discovery is not None or emission is not None)
-
-    commit_links: list[tuple[str, str]] = []
-    if commit_evs:
-        for e in commit_evs:
-            cid = e.payload.get("commit_id") or ""
-            label = (
-                f"{e.payload.get('oid', cid)[:24]} "
-                f"({e.payload.get('contributor', '?')})"
-            )
-            commit_links.append((label, _evidence_path("commit", cid)))
-    elif discovery:
-        for c in discovery.commits:
-            cid = commit_id_for_oid(c["oid"])
-            commit_links.append((
-                f"{c['oid'][:24]} ({c.get('contributor', '?')})",
-                _evidence_path("commit", cid),
-            ))
 
+    commit_links = [
+        (
+            f"{e.payload.get('oid', e.payload.get('commit_id', ''))[:24]} "
+            f"({e.payload.get('contributor', '?')})",
+            _evidence_path("commit", e.payload["commit_id"]),
+        )
+        for e in commit_evs
+        if e.payload.get("commit_id")
+    ]
     comparison_links = [
         (
             e.payload.get("summary") or e.payload.get("comparison_id", e.event_id),
@@ -2360,16 +2342,13 @@ async def epoch_detail(epoch: int):
     ]
 
     excluded = []
-    if discovery:
-        for obs in discovery.observations:
+    if discovery_ev:
+        for obs in discovery_ev.payload.get("observations") or []:
             if obs.get("eligible"):
                 continue
             oid = obs.get("oid", "?")
             reason = obs.get("exclusion_reason") or "excluded"
-            excluded.append(["li",
-                f"{oid[:28]} — {reason} — ",
-                ["span.note", "legacy evidence unavailable"],
-            ])
+            excluded.append(["li", f"{oid[:28]} — {reason}"])
 
     ranking_nodes: list = []
     if ranking_completed:
@@ -2388,21 +2367,10 @@ async def epoch_detail(epoch: int):
                 indent=2, sort_keys=True,
             )],
         ]
-    elif emission:
-        if legacy and len(emission.ranking or {}) <= 1:
-            ranking_nodes.append(["p.note",
-                "Single-contributor epoch — no LLM judgments."
-            ])
-        ranking_nodes.extend([
-            ["p", "Projected from Emission (no ranking Evidence event)."],
-            ["pre.blob", json.dumps(emission.ranking, indent=2, sort_keys=True)],
-        ])
+    elif ranking_started:
+        ranking_nodes = [["p.note", f"Ranking started: {ranking_started.event_id}"]]
     else:
-        ranking_nodes = [["p.note", "No ranking recorded."]]
-    if ranking_started and not ranking_completed:
-        ranking_nodes.insert(0, ["p.note",
-            f"Ranking started: {ranking_started.event_id}"
-        ])
+        ranking_nodes = [["p.note", "No ranking evidence."]]
 
     if emission:
         emission_node = _dl_rows([
@@ -2411,44 +2379,41 @@ async def epoch_detail(epoch: int):
             ("pool_after", emission.pool_after),
             ("discovery_snapshot_id", emission.discovery_snapshot_id),
             ("ranking_run_id", emission.ranking_run_id or None),
+            ("ranking_event_id", emission.ranking_event_id or None),
             ("models_used", ", ".join(emission.models_used or [])),
             ("distributions", json.dumps(emission.distributions, sort_keys=True)),
         ])
     else:
         emission_node = ["p.note", "No emission for this epoch."]
 
-    single_contributor = False
-    if discovery:
-        single_contributor = len({c.get("contributor") for c in discovery.commits}) <= 1
-    elif emission:
-        single_contributor = len(emission.ranking or {}) <= 1
+    contributors = {
+        e.payload.get("contributor")
+        for e in commit_evs
+        if e.payload.get("contributor")
+    }
+    no_comparisons_note = "No comparisons."
+    if len(contributors) <= 1:
+        no_comparisons_note += " Single-contributor — no LLM judgments."
 
     body = [
         _evidence_nav(),
         ["div.eyebrow", f"epoch {epoch}"],
         ["h1", f"epoch {epoch}"],
     ]
-    if legacy:
-        body.append(["p.note",
-            "Legacy epoch: projected from GitDiscovery/Emission without Evidence "
-            "envelopes. Eligible commits use discovery patches; discarded observation "
-            "metadata is marked legacy evidence unavailable. Single-contributor "
-            "epochs have no LLM judgments."
-        ])
-    if discovery:
+    if discovery_ev:
         body.extend([
             ["h2", "discovery"],
             _dl_rows([
-                ("snapshot_id", discovery.snapshot_id),
-                ("config_digest", discovery.config_digest),
-                ("initial_snapshot", discovery.initial_snapshot),
-                ("observations", len(discovery.observations)),
-                ("eligible", len(discovery.commits)),
+                ("snapshot_id", discovery_ev.payload.get("snapshot_id")),
+                ("config_digest", discovery_ev.payload.get("config_digest")),
+                ("observations", discovery_ev.payload.get("observation_count")),
+                ("eligible", discovery_ev.payload.get("eligible_count")),
+                ("event", _a(
+                    _evidence_path("event", discovery_ev.event_id),
+                    discovery_ev.event_id,
+                )),
             ]),
         ])
-    no_comparisons_note = "No comparisons."
-    if single_contributor:
-        no_comparisons_note += " Single-contributor — no LLM judgments."
     body.extend([
         ["h2", "commits"],
         _link_list(commit_links),
@@ -2471,92 +2436,42 @@ async def epoch_detail(epoch: int):
 @app.get("/commits/{commit_id}")
 async def commit_detail(commit_id: str):
     ev = find_evidence_payload("git.commit", "commit_id", commit_id)
-    discovery, legacy_row = (None, None)
     if not ev:
-        discovery, legacy_row = _legacy_commit_row(commit_id)
-    if not ev and not legacy_row:
-        discovery, obs = _legacy_observation(commit_id)
-        if obs is not None:
-            epoch = discovery.epoch if discovery else "?"
-            return _evidence_page(f"commit {commit_id[:24]}", [
-                _evidence_nav(
-                    _a(_evidence_path("epoch", str(epoch)), f"epoch {epoch}")
-                ),
-                ["div.eyebrow", "commit"],
-                ["h1", commit_id],
-                ["p.note", "legacy evidence unavailable"],
-                _dl_rows([
-                    ("oid", obs.get("oid")),
-                    ("eligible", obs.get("eligible")),
-                    ("exclusion_reason", obs.get("exclusion_reason")),
-                    ("epoch", str(epoch)),
-                ]),
-            ])
         return _evidence_page("commit not found", [
             _evidence_nav(),
             ["h1", "commit not found"],
             ["p", commit_id],
         ])
-    if ev:
-        p = ev.payload
-        epoch = ev.epoch
-        oid = p.get("oid", "")
-        contributor = p.get("contributor", "")
-        message = _blob_text(p.get("message"))
-        patch = _blob_text(p.get("patch"))
-        meta = _dl_rows([
+    p = ev.payload
+    epoch = ev.epoch
+    return _evidence_page(f"commit {commit_id[:24]}", [
+        _evidence_nav(_a(_evidence_path("epoch", str(epoch)), f"epoch {epoch}")),
+        ["div.eyebrow", "commit"],
+        ["h1", commit_id],
+        _dl_rows([
             ("commit_id", commit

… preview truncated; 7,279 characters omitted

download full diff B

Hardlinks — judgments / attempts / prompt

prompt download

judgments

attempts

Prompt text is loaded only by the download route.