comparison · c_c534b41e8607 (tommy-mor) vs c_af08bd851e49 (tommy-mor)
Commit B introduces substantial new functionality and infrastructure: a complete pairwise voting UI, pair selection algorithms, dynamic UI morphing, item ID normalization improvements, integration and browser tests, reusable mock Reddit test support, CSS/JS updates, and related API changes. It spans many files and adds significant user-facing behavior and core logic. Commit A only removes a single test that produced a warning, with negligible impact on project functionality.
Commit B introduces a substantial new feature set: pairwise voting UI, backend logic for pair selection, DOM morphing updates, new modules, refactors to ID parsing, integration tests, and supporting utilities. It meaningfully expands functionality across multiple layers. Commit A merely removes a single test, providing negligible impact in comparison.
Commit B introduces a substantial new feature (pairwise vote compare UI), adds multiple new modules (pair.rs, vote.rs), extends existing core types (ItemId normalization), updates reducers, API handlers, JS/CSS, and includes both unit and integration tests. It meaningfully expands functionality and refactors behavior across the stack. Commit A only removes a single test function, a minimal change with negligible impact. Therefore, B contributes far more overall.
comparison · c_af08bd851e49 (tommy-mor) vs c_995cbd9de96d (tommy-mor)
Commit A introduces substantial new functionality and infrastructure. It adds a new vote comparison page, pair-selection algorithms, dynamic UI morphing after votes, item ID normalization improvements, integration and unit tests, CSS/JS updates, and refactors related request handling. These changes materially expand the project's capabilities and improve correctness. Commit B is a formatting/refactoring pass that reorganizes imports, wraps lines, and adjusts code layout without changing behavior. While useful for readability and consistency, it contributes far less to the project's functionality.
Side A introduces a substantial new feature set: a full vote-compare UI flow, pair selection algorithm, dynamic DOM morphing, new modules (vote.rs, pair.rs), API changes, normalization improvements, CSS/JS updates, and integration tests. Side B is purely formatting and minor code reorganization with no functional changes. The impact difference is large.
Side A introduces a substantial new feature: a full pairwise vote compare UI (/vote), new HTML rendering module, pair selection algorithm with prioritization and tests, integration tests, storage normalization improvements, JS/CSS updates, and backend changes to support morphing edge history. It spans many new files and meaningful logic (~1000+ lines). Side B is purely formatting and import reordering with no behavioral changes. Therefore, Side A contributes overwhelmingly more.
comparison · c_c534b41e8607 (tommy-mor) vs c_af08bd851e49 (tommy-mor)
Side A merely deletes a single dead/broken test (a trivial cleanup with no functional effect), while Side B implements a substantial, coherent feature: a pairwise vote-compare page with morphing UI, pair-selection logic (pair.rs with bridge/component-aware pairing), ItemId normalization via from_storage, refactored ui_action fields, plus new integration and Clojure e2e tests and refactored test support. Side B represents real, lasting functional and architectural value versus Side A's negligible housekeeping.
A only deletes one dead, non-#[test] helper that triggered a warning—pure cleanup with no behavior change. B adds lasting product value: pairwise vote UI with in-place morphs, a bridge-preferring pair-selection module, ItemId::from_storage normalization, shared mock-Reddit test support, and solid integration coverage.
Side B adds substantial new functionality and infrastructure: a dedicated pair-selection module with bridge-aware voting logic and tests, a full `/vote` compare UI with in-place morph updates after voting, ID normalization via `ItemId::from_storage` to fix canonicalization bugs, and accompanying integration/end-to-end tests. Side A only removes a single test function, reducing test coverage without introducing lasting behavior or design improvements.
Side A only deletes a single test, removing coverage without improving behavior. Side B adds substantial functionality (pair selection algorithm in pair.rs, full vote compare UI, and integration tests) and fixes data consistency by introducing ItemId::from_storage and using it across parsing and voting paths.
Side A merely deletes a single test (`parse_full_keeps_quoted_thread_title_statement_as_prose`), reducing coverage without improving functionality. Side B introduces a full pairwise vote compare feature (new `vote.rs`, `pair.rs` with bridge-prioritized selection logic, UI morphing via `vote_recorded_morph`), improves ID normalization with `ItemId::from_storage` integrated into reducer/state, and adds integration and unit tests—substantial, lasting functionality and correctness improvements.
comparison · c_af08bd851e49 (tommy-mor) vs c_995cbd9de96d (tommy-mor)
Side A implements a real feature: a working vote-compare morph flow, a new pair-selection module with bridge-priority algorithm and tests, storage-id normalization (from_storage), and integration tests plus test infra refactor (mock-reddit extraction). Side B is purely cosmetic rustfmt-style reformatting (import ordering, wrapping, if/else collapsing) with zero behavioral change, providing negligible lasting value beyond style consistency.
Side A ships real product value: new pair-selection logic (bridge-preferring suggest_next_pair_in_pool), a full /vote compare UI with in-place morph after record_vote, ItemId::from_storage normalization, and integration/e2e coverage. Side B only reformats garden.rs (import order, line breaks, wrapping) with no behavioral change.
Side A introduces substantial new functionality: a complete pairwise voting page, pair-selection logic that prioritizes bridge comparisons across connected components, in-place UI morphing after votes, ID normalization via `ItemId::from_storage`, and accompanying unit/integration tests. Side B is purely formatting and import reordering with no behavioral changes, so it adds essentially no lasting project functionality.
Side A introduces substantial new functionality (pair selection algorithm in `pair.rs`, full vote-compare UI, morphing updates, and `ItemId::from_storage` normalization fixing parsing inconsistencies) plus tests, whereas Side B is purely formatting and reordering with no behavioral changes.
Side A introduces substantial new functionality: a full pairwise vote compare UI (`html/vote.rs`), a bridge-aware pair selection engine (`pair.rs`), storage normalization via `ItemId::from_storage`, JS morph helpers, and integration tests validating vote morph behavior. Side B is purely formatting and import reordering in `garden.rs` with no behavioral changes, so it adds no lasting functional value.
comparison · c_3f420a1f5aa1 (tommy-mor) vs c_af08bd851e49 (tommy-mor)
B introduces a genuine algorithmic improvement (bridge-preferring pair selection in pair.rs) and fixes a real correctness bug where Reddit permalinks with title slugs created duplicate ItemIds (ItemId::from_storage), backed by new unit and integration tests plus a Clojure e2e test. A is a solid but more mechanical feature (server-persisted theme cookie threaded through ~20 handlers) plus useful but secondary private-room URL prefixing fixes; it's broader in diff size but less deep in core logic than B's ranking/pair-selection and id-normalization fixes.
B adds lasting core product logic: bridge-first pair selection in pair.rs (with unit tests), a full /vote compare UI with post-vote edge-history morphing, and ItemId::from_storage normalization plus integration coverage. A mostly plumbs cookie-based theme through layout/handlers and secondary private-room wire URL helpers in RPC—useful polish and API consistency, but less foundational than the ranking/vote path work.
Side A delivers two substantial, project-wide improvements: persistent theme support via cookies integrated across authentication and HTML rendering (including preserving the theme through login redirects), and correct room-aware URL generation throughout the RPC/API layer with dedicated helper functions and tests. Side B adds a useful vote-comparison UI flow with in-place morph updates and improves item normalization for Reddit imports, but much of the patch is feature-specific, whereas Side A fixes cross-cutting behavior affecting navigation, rendering, and API correctness across the application.
comparison · c_af08bd851e49 (tommy-mor) vs c_11d6a0ec9839 (tommy-mor)
Side A introduces the core pairwise-voting infrastructure (pair.rs bridge-selection algorithm with tests, vote.rs compare page, morph-based vote recording) plus a real correctness fix (ItemId::from_storage normalizing reddit permalink slugs) and adds test coverage/refactors test support code. Side B is a narrower, later fix-up (attribution placement, removing a fallback bug, dropping a UI button, route rename) that is useful but smaller in scope and builds on infrastructure like A's rather than creating it.
A lands core lasting surface area: pair selection with bridge/component priority (pair.rs), the full /vote compare UI + in-place morph after record, ItemId::from_storage normalization across import/reducer paths, and real integration/e2e coverage. B is smaller corrective polish on an existing flow—delegate attribution plumbing, stop falling back when the sibling pool is <2, drop swap, and rename /vote/compare→/vote—valuable but incremental versus A’s design and feature weight.
Side A adds substantial new functionality: a complete `/vote` comparison page, pair-selection logic that prioritizes bridge comparisons across connected components, in-place UI morphing after votes, improved item ID normalization (`from_storage`) to avoid inconsistent Reddit paths, and accompanying integration/unit tests. Side B mainly refines an existing feature by renaming `/vote/compare` to `/vote`, removing the swap button, fixing delegate attribution handling, and preventing an undesirable fallback when too few sibling items exist; these are useful polish and correctness fixes but have much narrower long-term impact.
comparison · c_af08bd851e49 (tommy-mor) vs c_597d3f736194 (tommy-mor)
Side A adds substantial lasting functionality: a new pair.rs module with a principled bridge-based pair-suggestion algorithm (with unit tests), a new vote.rs compare-page module, a genuine bugfix in ItemId normalization (from_storage) that fixes ID mismatches across form/event/reddit-import boundaries, and extraction of a reusable mock-reddit test helper. Side B is a narrower but real bugfix to mock OAuth test harness (fixing a str/split regex bug and body-read/redirect issues) that only restores broken E2E test infrastructure without adding new capability.
A ships lasting product design: a full /vote compare flow with in-place morph updates, bridge-preferring pair selection in pair.rs, ItemId::from_storage normalization, and related integration coverage. B only repairs OAuth/Reddit test mocks (split regex, getRequestBody, redirect length, null guards) so E2E auth works again—valuable but narrow infrastructure, not core behavior.
Side A adds substantial new functionality and infrastructure: a full pairwise voting UI, pair-selection logic that prioritizes bridge comparisons across ranking components, incremental DOM morph updates after voting, improved ItemId normalization via `from_storage`, and accompanying integration/tests. Side B fixes test infrastructure for OAuth/Reddit mocks (correct request-body handling, redirect behavior, query parsing, null checks, and Playwright helpers), which is valuable for test reliability but is confined to the test harness rather than the project's core behavior.
comparison · c_97611919bf0b (tommy-mor) vs c_af08bd851e49 (tommy-mor)
Side A completes a substantial, well-documented type-safety refactor (CanonicalItemUrl -> ItemId) across the whole codebase with consistent updates to reducer, ranking, RPC, HTML, and tests, removing a stringly-typed newtype in favor of a structured enum with proper serde/Ord semantics. Side B adds a real feature (vote comparison UI with morph updates, pair-selection logic, and tests) which is valuable but narrower in scope and more localized to one UI flow, making it a good but less foundational contribution than A's systemic identity-model overhaul.
Side A delivers the structural ItemId enum (with item_wire split), fully migrating reducer maps, ranking, RPC, HTML routing, and tests off CanonicalItemUrl—core lasting identity design. Side B adds a valuable /vote compare UX, bridge-aware pair picker, and morph path, but is a feature layer on top rather than foundational type/architecture work.
Side A performs a project-wide architectural migration from `CanonicalItemUrl` string keys to a structured `ItemId`, adding the new `item_id`/`item_wire` modules and propagating the type through reducers, ranking, routing, APIs, HTML, and tests while preserving normalization and serialization behavior. Side B adds a useful vote comparison UI, pair-selection logic, and related tests, but its scope is primarily a feature layer, whereas Side A changes the project's core identity model in a way that is likely to support many future features and reduce string-based errors.
comparison · c_afa638171cf7 (tommy-mor) vs c_af08bd851e49 (tommy-mor)
Side A implements a coherent, security-relevant feature (Reddit OAuth linking, UUID-canonical identity, conflict handling, private linked-providers UI) with corresponding storage/schema changes, tests, and mock server updates. Side B is a mixed 'refactor' that adds a new vote-compare page/pair-selection logic (useful) but is labeled generically and bundles unrelated changes (ItemId normalization, JS behavior tweaks) with less architectural clarity than A's identity model overhaul.
A lands a lasting identity redesign: UUID as sole principal, multi-provider OAuth *linking* (GitHub + Reddit) with logged-in attach/conflict handling, private linked-provider UI, and a real projection fix (pending_weights so multi-link trust updates in one batch). B adds useful vote-compare morph UX, bridge-aware pair selection, and ItemId::from_storage normalization, but much of the diff is module extraction/refactor and UI wiring rather than comparable foundational design.
Side A introduces a substantial identity model change by making UUIDs the canonical account identity, adding Reddit OAuth support, implementing provider linking with conflict handling, exposing linked providers privately, updating routing, storage, and projection logic, and fixing trust-weight batching with tests. Side B adds a useful pairwise voting UI flow and item ID normalization, but much of it is feature/UI work and refactoring, whereas Side A establishes a broader, lasting authentication and identity architecture affecting core account behavior.
comparison · c_af08bd851e49 (tommy-mor) vs c_c6f5afec1d36 (tommy-mor)
Side A introduces a genuinely new, well-tested module (pair.rs) implementing bridge-aware pair selection via connected components, adds a more robust ItemId::from_storage normalization used consistently across reducer/state/reddit import, and refactors the Clojure test harness into a reusable mock-reddit module with new integration/e2e tests. Side B's pool-scoped voting is a reasonable but narrower feature addition that mostly threads an optional pool id through existing vote-compare code with less algorithmic depth and lighter test coverage.
A lands foundational pairwise-voting design—new pair selection (bridge-preferring components), a full /vote compare UI with in-place morph after record_vote, ItemId::from_storage normalization, and solid integration/e2e coverage—whereas B only threads an optional pool param and a 'vote on children' link through existing garden vote helpers. A’s changes are larger in lasting product surface and algorithm quality, not merely line count; B is a useful but incremental constraint on already-present compare flow.
Side A delivers substantial new functionality and infrastructure: it adds a dedicated pairwise voting page, pair-selection logic that prioritizes bridge comparisons across ranking components, in-place UI morphing after votes, identifier normalization via `ItemId::from_storage`, and accompanying tests. Side B is a focused extension that threads an optional `pool` parameter through the existing vote flow and adds a 'vote on children' entry point, but it primarily builds on mechanisms that Side A introduces rather than providing comparable foundational value.
comparison · c_af08bd851e49 (tommy-mor) vs c_8dc1a8119370 (tommy-mor)
Side B removes ~1800 lines of a fragile, over-engineered keystroke-transition parser graph (with its brittle race-condition test) and replaces it with a small, testable, deterministic paste-and-go URL parser plus a simpler UI, net reducing complexity and fixing a stated reliability problem. Side A adds real functionality (a pairwise vote-compare page, bridge-pair selection logic, id normalization) but is more feature-churn/addition without removing prior debt, and 'refactor' as commit message undersells substantial new surface area added without corresponding cleanup elsewhere.
A lands core product surface: a full /vote compare page, bridge-first pair selection in pair.rs, in-place morph of edge history after record_vote, ItemId::from_storage normalization, and integration/browser coverage. B’s paste-and-go rewrite correctly deletes an unreliable ~1.8k-line keystroke graph and race workarounds, but that is a navigation UX simplification, not new ranking/voting capability of comparable lasting depth.
Side A adds substantial new functionality: a dedicated pairwise voting page, pair-selection logic that prioritizes bridging disconnected ranking components, in-place UI morphing after votes, canonicalized item ID parsing to fix Reddit URL inconsistencies, and extensive unit/integration tests. Side B mainly removes a large autocomplete/parser system in favor of a simpler paste-and-go flow and redirect, simplifying the UI but largely replacing existing behavior rather than adding lasting project capabilities.
comparison · c_af08bd851e49 (tommy-mor) vs c_e57094c6229a (tommy-mor)
Side A adds a genuinely new, well-tested ranking algorithm (pair.rs's bridge-aware next-pair selection with component detection) plus a real bugfix in ItemId normalization (from_storage) that fixes vote/id mismatches from Reddit title slugs, along with an in-place morph-based vote-compare UI backed by integration tests. Side B's changes (explicit fetch button, raw-payload event storage, dotenv, configurable Reddit API base) are solid plumbing/UX improvements but are more incremental infrastructure rather than a core algorithmic/product feature.
A lands the project’s core ranking product: a full /vote compare UI plus pair.rs with bridge/within-component pair prioritization, in-place vote morphing, and targeted integration/E2E coverage. B is still lasting (EntityImported + raw payload persistence, explicit fetch, configurable Reddit API), but it is mostly import/plumbing versus A’s domain algorithm and primary UX.
Side A delivers a substantial new pairwise voting workflow: it adds a dedicated `/vote` page, bridge-aware pair selection (`suggest_next_pair_in_pool`), in-place UI morphing after votes, ID normalization via `ItemId::from_storage`, and accompanying unit/integration tests. Side B introduces useful infrastructure for explicit Reddit fetching and persistent raw entity imports, but much of the patch is architectural refactoring around fetch/storage; A's changes more directly add enduring application behavior and fix identifier consistency across voting and imports.
comparison · c_af08bd851e49 (tommy-mor) vs c_48edc893c5b0 (tommy-mor)
Side A ships a complete, tested feature (pairwise vote-compare page with a principled next-pair/bridge-selection algorithm in pair.rs), fixes a real correctness bug in ItemId normalization (from_storage) that ripples through reducer/reddit import, and improves test infra (extracted mock-reddit support, new Clojure e2e test) — all backed by unit and integration tests. Side B mainly stands up generic plumbing (form_template holes, ui_action enum, /ui route) for existing forum actions, which is useful scaffolding but smaller in scope and lower-stakes than A's working feature plus bugfix.
A ships lasting product design: bridge-aware pair selection in pair.rs with tests, the /vote compare page and post-vote morph path, plus ItemId::from_storage canonicalization used in Reddit import and votes. B is valuable plumbing (form_template holes, HtmlUiAction, POST /ui wrappers and expand-form morphs) but mostly routing/refactor of existing ingest/redact flows rather than new core behavior.
Side A delivers substantial end-user functionality and infrastructure: it adds a full pairwise voting page, intelligent pair selection based on connected components, in-place UI morphing after votes, ID normalization via `ItemId::from_storage`, and corresponding integration/tests. Side B mainly introduces a generic `/ui` endpoint and form-template mechanism, refactors existing web-post handlers for reuse, and adds lazy expansion of new-thread forms; while useful architectural work, it is less directly impactful than the new voting workflow and correctness improvements in Side A.
comparison · c_4772ee88dbe3 (tommy-mor) vs c_af08bd851e49 (tommy-mor)
Side B adds substantive, tested functionality: a pair-selection algorithm (bridge/within component prioritization in pair.rs), a real vote-compare UI with edge history morphing, ItemId normalization fixes for storage/import correctness, and new integration/e2e tests plus refactored mock-reddit test support. Side A mostly removes dead demo-counter code (fine cleanup) and adds a settlement worker/caching layer for ranking, which is useful but narrower and less validated by new tests than B's changes.
B delivers core product domain work: intelligent bridge/unvoted pair selection (`pair.rs`), a full `/vote` compare UI with in-place edge-history morphing, and lasting ID normalization via `ItemId::from_storage`. A is valuable (demo removal + settlement worker/ranking cache) but is narrower infrastructure cleanup relative to B’s ranking-UX and pair-graph design.
Side A introduces a substantial architectural improvement by moving vote recording into a dedicated settlement worker that batches event-log writes, recomputes cached rankings asynchronously, adds cached ranking reads, and switches UI paths from write locks to read locks. It also removes the temporary demo counter feature and simplifies the main UI, whereas Side B mainly adds a new vote-comparison UI flow, pair-selection logic, and ID normalization, which are valuable features but less foundational than the concurrency and caching changes in Side A.
comparison · c_af08bd851e49 (tommy-mor) vs c_2722a3195825 (tommy-mor)
Side B is a focused, well-tested algorithmic refinement to pair selection (established-component merging, isolate attachment, and rank-zip refinement) that improves a core ranking heuristic with clear new unit tests. Side A is a broader but more diffuse refactor mixing UI morphing, a new vote-compare page, ItemId normalization changes, and test infra shuffling, which adds real functionality but is riskier/noisier and less singularly focused than B's targeted improvement to existing logic.
A introduces the full vote-compare feature surface (new vote.rs UI, morph-after-vote path replacing next-URL redirects, ItemId::from_storage normalization used in votes/Reddit import, JsBuilder morph helper, CSS, and integration/e2e tests) plus the initial pair.rs bridge-aware selector. B only refines suggest_next_pair_in_pool with bridge sub-priorities and adjacent-rank zip ordering on that existing module—valuable ranking logic, but incremental on A’s foundation.
Side A delivers multiple lasting functional improvements across the project: it adds a dedicated pairwise voting UI with incremental DOM morphing after votes, introduces robust pair resolution and bridge-aware pair selection, and fixes identifier normalization by adding ItemId::from_storage and using it throughout vote processing and Reddit import to avoid inconsistent IDs. Side B is a focused refinement of the existing pair-selection heuristic—adding better tie-breaking for attaching isolates and adjacent-rank refinement with tests—but it builds on infrastructure introduced by Side A rather than providing comparable new functionality or cross-cutting bug fixes.
comparison · c_7a129e904906 (tommy-mor) vs c_af08bd851e49 (tommy-mor)
Commit A ships a complete, coherent production deployment path (Dockerfile, fly.toml, CI/CD workflow, GitHub App auth for git mirroring, expanded repo/contributor config, a real live audit/status dashboard with SSE) plus corresponding tests, closing a previously flagged TODO. Commit B, despite its 'refactor' label, is a substantial feature addition (pairwise vote comparison page, bridge-pair selection algorithm, ItemId normalization) with decent test coverage, but is narrower in scope and less clearly load-bearing for overall project operability than A's deployment infrastructure and observability work.
A ships production authority (Fly/Docker/CI), multi-repo contributor roots, epoch retry safety, and a tested live /watch audit SSE surface that makes the constitution operable and auditable. B’s bridge-first pair selection, ItemId::from_storage normalization, and in-place vote morphs are solid core design, but they refine an existing sorter vote path rather than standing up the deployed economic process.
Side A delivers a substantial production capability: it adds deployment infrastructure (Dockerfile, Fly.io config, GitHub Actions), a live audit dashboard with SSE-backed progress/status APIs, startup/retry improvements, authenticated GitHub access, and fixes repository discovery by deduplicating commit object verification, all backed by new integration and unit tests. Side B contains useful UI and architecture work for pairwise voting (new vote page, pair-selection logic, ID normalization, and incremental morph updates), but its impact is narrower and primarily focused on one feature area rather than end-to-end operational capability.
comparison · c_2595b6007624 (tommy-mor) vs c_af08bd851e49 (tommy-mor)
Side A is a substantial, coherent architectural change (RPC batch endpoint replacing dozens of REST routes, room/thread scoping refactor across CLI, server, reducer, events, and tests) that establishes a lasting new API design with broad test coverage updated to match. Side B is a smaller, more localized refactor (vote-compare UI morph behavior, ItemId normalization for Reddit imports, test helper extraction) that is useful but narrower in scope and impact than A's system-wide restructuring.
Side A is a foundational architectural rewrite: it unifies the HTTP surface into a batched RPC API, separates room permission boundaries from forum thread tags in events/reducer state, and rewires the CLI plus integrations accordingly—lasting multi-tenant design rather than surface churn. Side B only improves the HTML pair-vote UX (in-place morph instead of redirect), extracts pair-selection helpers, and normalizes Reddit item IDs, which is useful but narrower and more UI-local.
Side A introduces a substantial architectural change by consolidating many REST endpoints into a batched RPC API, adding room-scoped commands (`Public`/`Private`), separating room and thread concepts (`room_id` vs `thread_tag`), and refactoring validation and reducer logic to support scoped content while updating tests and CLI accordingly. Side B mainly adds a new vote comparison UI flow, in-place DOM morphing, pair-selection helpers, and storage normalization improvements, which are useful features but have a narrower, presentation-focused impact than A's core API and data model redesign.
comparison · c_2dc96aace098 (tommy-mor) vs c_af08bd851e49 (tommy-mor)
Commit A delivers a substantive architectural change—offloading large Reddit JSON payloads to RocksDB via a new durable crate and switching event replay to a streaming line-by-line model, both of which reduce startup RAM and are backed by tests—representing real, lasting infrastructure value despite the vendored crate bloat. Commit B is a solid but comparatively smaller refactor (vote-compare morphing via Idiomorph, pair-selection bridging logic, ItemId normalization) that improves UX and correctness but is narrower in scope and less foundational than A's storage/replay overhaul.
A’s lasting impact is architectural: it moves full Reddit entity JSON out of GlobalTree into a RocksDB-backed EntityStore and replaces load-all event startup with line-at-a-time replay, directly cutting RAM and decoupling derived views from raw payloads. B adds real product value (vote-compare morph UX, bridge-preferring pair selection, ItemId::from_storage), but it is incremental UI/ranking polish versus A’s foundational storage and startup design.
Side A introduces substantial infrastructure: a new RocksDB-backed `durable` workspace crate, an `EntityStore` that moves raw Reddit JSON off-heap, updates the reducer to keep only derived entity data, and replaces startup `load_all` with streaming event-log replay to reduce memory usage. Side B mainly refactors the vote UI by adding compare-page morphing, pair-selection helpers, and ID normalization improvements, which are useful but much narrower in long-term architectural impact.
comparison · c_af08bd851e49 (tommy-mor) vs c_ca9169f732b8 (tommy-mor)
Side B fixes a real production bug (public Reddit API blocking cloud IPs) with a robust retry-on-401/403 mechanism, error surfacing via truncated messages, and a deployment config fix, all backed by a targeted unit test. Side A is a large refactor adding a new vote-compare feature and pair-selection logic, which is substantial but more speculative UI/UX work with less proven necessity and higher risk of churn compared to B's focused, correctness-driven fix.
A lands core product machinery: bridge-aware pair selection in pair.rs, the full /vote compare UI and in-place morph path (vote_recorded_morph, vote_compare flag), plus ItemId::from_storage normalization with tests—lasting design for ranking. B is a precise, necessary production fix (force OAuth when creds exist, AuthRejected + refresh on 401/403, fly.toml base URL) but narrower in scope than the vote/pair subsystem.
Side A delivers substantial new functionality and infrastructure: it adds a dedicated pairwise voting page, pair-selection logic that prioritizes bridging disconnected ranking components, in-place UI morphing after votes, ID normalization via `ItemId::from_storage`, and accompanying integration/tests. Side B fixes an important operational issue by requiring OAuth when configured, refreshing tokens after 401/403 responses, and improving error handling, but it is a narrower reliability improvement compared with the broader, lasting feature and architectural additions in Side A.
comparison · c_94135a1c4c58 (tommy-mor) vs c_af08bd851e49 (tommy-mor)
Side A fixes a real security bug (fail-open voting fallback to anon) with a fail-closed rewrite, adds Secure cookie support, gates mock OAuth behind an env flag, hardens open-redirect sanitization, and adds unit tests plus nav UI improvements—concrete, security-relevant lasting value. Side B is a larger refactor (new pair.rs module, vote.rs rewrite, ItemId::from_storage normalization) that is useful but is mostly internal restructuring/feature polish without addressing a correctness or security defect, and is labeled just 'refactor' with less durable architectural necessity than A's fixes.
B adds the core /vote compare surface, bridge-aware pair selection in pair.rs, ItemId::from_storage canonicalization, and in-place morph after votes—foundational product/ranking design with tests. A is real lasting security (fail-closed resolve_vote_actor, mock-OAuth gate, Secure cookies, open-redirect hardening) plus nav alias polish, but it hardens an existing path rather than delivering the main voting/ranking capability.
Side A introduces substantive security and correctness improvements: voting now fails closed instead of silently falling back to an anonymous actor, OAuth mocking is gated behind an explicit environment flag, Secure cookie handling is centralized, open-redirect sanitization is strengthened, and these behaviors are covered with new tests. Side B adds useful functionality around a pairwise voting UI, pair selection logic, and ID normalization, but much of the patch is feature work and refactoring rather than the broad, lasting hardening of core authentication and session handling delivered by Side A.
comparison · c_abd68b5e771a (tommy-mor) vs c_af08bd851e49 (tommy-mor)
Side A is a small, correct bugfix that closes a real ghost-item/voted-pair bug with a matching test update — solid but narrow value. Side B, despite the misleading 'refactor' message, adds substantial lasting functionality (new pair-selection module with bridge-priority logic, a new vote-compare page with morph-based UI, storage-id normalization fixing Reddit slug/id mismatches) plus integration and Clojure test coverage and refactored test support, representing significantly more durable feature/architecture value despite being noisier.
A is a small but real correctness fix: moving the zero-ratio early-return before ensure_item/voted_pairs so invalid votes no longer leave ghost index entries. B delivers far more lasting product value—an entire /vote compare flow, bridge-preferring pair selection (pair.rs + components), in-place morph UX, ItemId::from_storage normalization, and substantial tests—not mere churn despite the vague message.
Side B adds substantial new functionality: a dedicated pairwise voting UI, pair-selection logic that prioritizes bridging disconnected ranking components, in-place UI morphing after votes, canonical ItemId normalization via from_storage, and accompanying integration/unit tests. Side A fixes a real reducer bug by moving the zero-ratio guard before ensure_item/voted_pairs side effects and strengthens the regression test, but it is a narrowly scoped correctness fix compared with the broader lasting capabilities introduced in Side B.
comparison · c_25ece8f92dc8 (tommy-mor) vs c_af08bd851e49 (tommy-mor)
B delivers substantial new functionality (pairwise vote UI with bridge-based pair selection algorithm, edge-history morphing, ItemId normalization for reddit URLs) plus real test infra reuse (extracted mock-reddit helper) and new integration/e2e tests. A is a smaller but genuinely important bugfix (removing a shared sentinel delegate that blocked concurrent human votes) with good targeted tests, but is narrower in scope and lasting impact compared to B's broader feature and architecture contribution.
B adds lasting core product design: bridge-preferring pair selection in pair.rs, a dedicated vote compare UI with in-place morphs (vote_recorded_morph), and durable ItemId::from_storage normalization with tests—not mere churn. A is a high-value correctness fix (optional agent, drop shared WEB_BROWSER_AGENT so multi-user browser votes no longer hit AgentBound), but narrower in scope than B’s voting infrastructure.
Side B adds substantial new functionality and architecture: a dedicated pair-selection module with bridge-aware ranking logic, a new vote comparison UI that updates edge history in place, canonical item normalization via `ItemId::from_storage`, and supporting tests and utilities. Side A delivers an important targeted bug fix by replacing browser sentinel delegates with `None` to prevent shared delegate collisions for human votes, but its scope is narrower despite being well-tested and impactful.
comparison · c_25172cf8caa0 (tommy-mor) vs c_af08bd851e49 (tommy-mor)
Side A fixes a real, well-documented multi-user bug (shared browser sentinel delegate blocking concurrent human votes) with a minimal, coherent diff, clear tests validating the fix, and cleanup of now-dead sentinel logic. Side B, despite being labeled 'refactor,' is a much larger, unrelated feature bundle (new pair-suggestion algorithm, new vote.rs page, ItemId::from_storage normalization, Clojure test harness refactor) that is broader and less focused, making it harder to verify as a clean, necessary unit of ownership even though it adds substantial functionality.
B lands lasting product surface: a full /vote compare page, idiomorph edge-history refresh, and a bridge-preferring pair-selection algorithm in new pair.rs/vote.rs with normalization via ItemId::from_storage—core ranking UX, not churn. A is a precise, well-tested fix (drop shared WEB_BROWSER_AGENT sentinels so multi-user browser votes no longer hit AgentBound), but it is narrower correctness surgery around Optional agents rather than new ranking capability.
Side A fixes a substantive correctness bug by removing shared browser sentinel delegates, changing pending sessions to use an optional delegate, updating attribution logic, and adding integration tests proving multiple browser users can vote independently without erroneous AgentBound conflicts. Side B introduces a substantial new vote-compare UI flow and related refactoring, but much of it is feature work and infrastructure rather than resolving an existing correctness issue, making A's bugfix more durable and fundamental.
comparison · c_c0df72aee6da (tommy-mor) vs c_af08bd851e49 (tommy-mor)
Side A fixes a real, security-relevant bug (XSS via untrusted Reddit HTML) with a small, focused, well-tested change (new sanitize module + call sites + tests), delivering clear lasting value. Side B is a large, diffuse refactor touching voting UI, pair selection, ID normalization, and test infra with mixed concerns and no security or correctness fix of comparable importance, making its net contribution harder to justify as cleanly as A's targeted fix; notably it also reintroduces the unsanitized `PreEscaped(body)` pattern for entity bodies in vote_compare_item_card, potentially regressing the exact issue A addresses.
B lands lasting product design: bridge-aware pair selection in pair.rs, the /vote compare page with in-place morph after record_vote, ItemId::from_storage slug normalization (used in reddit/reducer/parse paths), plus integration coverage—far more than module reshuffling. A is a correct, necessary XSS fix (ammonia at PreEscaped render sites with tests) but a narrow hardening change versus B’s core ranking/vote behavior.
Side A fixes a concrete security issue by introducing HTML sanitization with the `ammonia` library before rendering untrusted Reddit `body_html`, replacing direct `PreEscaped(body)` output with `entity_body_html(body)` and adding tests that verify scripts and event handlers are stripped while benign markup is preserved. Side B adds a substantial new voting UI, pair-selection logic, and refactoring, but it is largely feature work and even continues rendering `body_html` with `PreEscaped` in the new vote comparison page, whereas Side A provides a focused, lasting security improvement that protects all affected rendering paths.
comparison · c_c124c217f89c (tommy-mor) vs c_af08bd851e49 (tommy-mor)
Side A turns the previously stubbed-out Reddit import into a real, working feature: a background worker with OAuth token management, rate-limit handling/backoff, dedup, JSON parsing for both subreddits and post listings, wired into the UI, plus solid unit tests for URL mapping and parsing. Side B is a valuable refactor (bridge-based pair suggestion algorithm, ID-normalization fix, morph-based vote UI, test infra cleanup), but it builds on and refines functionality that side A actually introduced, making A's contribution more foundational and self-contained.
B delivers the core pairwise-vote product surface (vote.rs UI, in-place morph after record instead of navigation churn) plus lasting algorithmic design in pair.rs (bridge-first unvoted pair selection with tests) and real ID correctness via ItemId::from_storage. A is substantial Reddit ingestion plumbing (worker, OAuth, rate limits, parsers) that replaces a stub, but it is more peripheral integration than B’s ranking-loop and path-normalization work.
Side A implements a substantial new Reddit integration: it adds an asynchronous background fetch broker with request deduplication, OAuth support, rate-limit/backoff handling, JSON parsing into project entities, automatic fetch triggering from browsing and item creation, and supporting tests. Side B contains useful refactoring and new pairwise voting UI logic (including pair selection, morph updates, and item ID normalization), but much of it reorganizes or extends existing UI behavior, whereas Side A introduces a major new subsystem with lasting functionality.