comparison · c_97611919bf0b (tommy-mor) vs c_6a02ffb06a41 (tommy-mor)
Side A is a substantial, coherent refactor introducing a structural ItemId enum to replace the stringy CanonicalItemUrl newtype, touching reducer, ranking, RPC, and HTML layers consistently with new modules (item_id.rs, item_wire.rs) and updated tests, representing real architectural progress. Side B is a small, useful bugfix (off-by-one/expect vs unwrap_or for thread_post_index) but is narrow in scope and lower lasting impact compared to A's broader identity-model overhaul.
A lands the structural ItemId type (replacing CanonicalItemUrl), splits wire normalization, and migrates reducer/ranking/RPC/HTML/tests so identity is typed end-to-end—lasting core design. B only drops a 1-based/fallback thread_post_index path to a strict 0-based index with tests/docs, a small correctness polish relative to A.
Side A replaces the pervasive `CanonicalItemUrl` string wrapper with a structural `ItemId` type, introduces dedicated `item_id.rs`/`item_wire.rs` modules, and propagates the new identity model through reducers, ranking, routing, APIs, HTML, and tests. Side B is a focused correctness change that makes `thread_post_index` consistently 0-based and asserts an invariant with `expect`, but its impact is limited compared with the project-wide architectural improvement in Side A.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_859efcb771cb (tommy-mor)
Side A fixes a real off-by-one/index consistency bug (aligning thread_post_index between feed and rank history with 0-based route indices), removes a fragile silent fallback in favor of an explicit invariant check, updates doc comments accordingly, and adds regression tests verifying the fix. Side B is a trivial one-line whitespace/formatting tweak in a view-count span with no functional impact.
A fixes a real indexing inconsistency: rank-history thread_post_index becomes proper 0-based (matching /t/tag/N), drops the silent unwrap_or(0)/1-based map, aligns types/docs/UI, and adds assertions. B only strips a decorative " · " from an embed views span—pure presentation nit with negligible lasting design value.
Side A makes a substantive behavioral fix by treating missing thread post indices as an invariant with `expect` instead of silently defaulting to 0, aligns rank-history indexing with the project's 0-based URL scheme, updates documentation, removes unnecessary conditional rendering, and adds integration tests verifying the new behavior. Side B is a minor UI text tweak that only removes a decorative separator before the view count.
comparison · c_88200cfa5c4d (tommy-mor) vs c_6a02ffb06a41 (tommy-mor)
Side B fixes a real off-by-one indexing bug (thread_post_index was 1-indexed but used as a 0-indexed URL path, causing broken links and an always-true 'index > 0' guard hiding index 0), adds test coverage asserting the corrected values, and updates documentation accordingly. Side A is purely cosmetic clippy cleanup (formatting, lint suppressions, minor idiom changes) with no behavioral impact, aside from trivially enabling one previously-unregistered test.
B fixes real index semantics: thread_post_index becomes required 0-based (aligned with /t/tag/N), drops the silent unwrap_or(0)/optional UI branch, and adds integration assertions plus doc clarity. A is almost entirely clippy/style churn (destructure matches, is_some_and, allow(dead_code), unused binds) plus enabling one already-written test—useful hygiene but little lasting design or bugfix value.
Side B makes a substantive behavioral fix by changing rank history to use a 0-based thread_post_index that matches `/t/tag/N` routes, replacing a silent `unwrap_or(0)` fallback with an `expect(...)` to enforce the data invariant, updating rendering, documentation, and integration tests accordingly. Side A is almost entirely Clippy-driven cleanup and minor test maintenance, with its only functional change being adding a missing `#[test]` attribute; most other edits are stylistic or lint-related.
comparison · c_e4fb43f04791 (tommy-mor) vs c_6a02ffb06a41 (tommy-mor)
Side B fixes a real off-by-one/indexing bug (thread_post_index semantics), removing a fallback that masked an invariant violation with .expect() and documenting the 0-based vs 1-based confusion, plus adds regression tests asserting correct index values. Side A is purely cosmetic: dedenting HTML markup and tweaking CSS counter styling across theme files, which is low-risk but non-functional churn.
B fixes a real indexing bug (1-based/unwrap_or(0) vs 0-based /t/tag/N routes), enforces the invariant with expect, always emits correct post links, and adds integration assertions. A only unwraps a vote-compare shell div and tweaks ranking-number CSS—cosmetic churn with little lasting design impact.
Side B fixes the semantics of `thread_post_index` by making rank history use the actual 0-based thread index consistently, replacing a silent `unwrap_or(0)` fallback with an `expect` that enforces the invariant, updating rendering to always generate the post link, correcting documentation, and adding integration tests for the behavior. Side A is largely a presentation change: it removes a wrapper element from the compare page and adjusts CSS styling for ranked lists across themes, with little impact on core functionality.
comparison · c_7ec67b9cef2c (tommy-mor) vs c_6a02ffb06a41 (tommy-mor)
Side B fixes an actual off-by-one/indexing bug (thread_post_index semantics) with real code, updated docs, and new regression tests, delivering concrete lasting value. Side A is purely a planning markdown file plus an unused RouteContext wrapper that duplicates ThreadNav without migrating any call sites, i.e., speculative scaffolding rather than executed value.
B fixes a real index/contract bug: thread_post_index becomes consistently 0-based like `/t/tag/N`, drops the silent `unwrap_or(0)`/`map(|i| i+1)` fallback, always emits post links, and locks behavior with integration tests. A mostly adds a temporary plan.md plus a thin RouteContext delegating to ThreadNav—useful scaffolding, but little completed behavior versus B’s lasting correctness.
Side B makes concrete behavioral changes: it enforces the invariant that a rank-history post must exist in `ingests_by_scope_thread` with `expect(...)` instead of silently falling back to `0`, aligns `thread_post_index` with the actual 0-based `/t/tag/N` routes, updates rendering to always emit the link, and adds integration tests documenting the behavior. Side A mostly introduces a planning document plus a `RouteContext` wrapper around `ThreadNav` and re-exports it, which is useful scaffolding but does not substantially change project behavior yet.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_9e1ff4fc0186 (tommy-mor)
Side A fixes a real semantic issue (a silent unwrap_or(0) masking a should-never-happen case) and reconciles a 1-vs-0 indexing inconsistency across rpc.rs, garden.rs, and types docs, backed by new integration test assertions verifying the corrected indices. Side B is almost entirely rustfmt/tooling churn (reformatting examples, toolchain pin, .vscode settings) plus a trivial CSS dedupe, which is useful hygiene but contributes no functional or correctness value.
Commit A makes a real semantic fix: switches rank-history thread_post_index to consistent 0-based indexing matching /t/tag/N routes, replaces silent unwrap_or(0) with expect, drops the conditional UI hide, documents the contract, and adds integration assertions. Commit B is almost entirely rustfmt churn across examples and crates plus minor tooling (toolchain components, VS Code settings, one duplicated CSS rule merge), which adds little lasting design or correctness value.
Side A makes a semantic correctness change by treating `thread_post_index` as a guaranteed 0-based index, replacing silent `unwrap_or(0)` fallbacks with `expect(...)`, always rendering the post link, updating API/docs to distinguish 0-based URL indices from 1-based feed ordinals, and adding integration tests to lock in the behavior. Side B is overwhelmingly workspace-wide rustfmt reformatting plus tooling/editor configuration (pinning rustfmt/clippy, VS Code settings, minor CSS cleanup), with little lasting change to project behavior.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_c534b41e8607 (tommy-mor)
Side A fixes a genuine correctness issue (removing an unwrap_or that silently masked a missing-post-id bug with an expect that surfaces invariant violations), aligns the index scheme consistently across template, types docs, and adds regression tests verifying the 0-based indexing behavior. Side B merely deletes a dead/unused test function (missing #[test] attribute) that was never actually run, which is a trivial cleanup with no functional impact.
A fixes real indexing semantics for rank-history thread links (1-based optional/fallback → required 0-based, aligned with /t/tag/N), updates types/docs/UI and adds assertions; B only deletes an unused non-#[test] helper that triggered a warning.
Side A corrects the rank-history thread index semantics by treating the post lookup as required with `expect(...)` instead of silently defaulting to `0`, updates documentation to distinguish 0-based URL indices from 1-based feed display, always renders the corresponding link, and adds integration tests validating the behavior. Side B only removes an unannotated test function that generated a warning, reducing noise but not changing project behavior.
comparison · c_28dfd8015c8a (tommy-mor) vs c_6a02ffb06a41 (tommy-mor)
Side B fixes a real off-by-one bug (thread_post_index was incorrectly 1-indexed with a fallback masking missing entries) with corrected docs and new regression tests covering the exact indices, giving lasting correctness value. Side A is a useful but purely mechanical config simplification (collapsing two hand-listed kaocha suites into a wildcard pattern) with no bugfix and lower risk/benefit.
B fixes real product correctness: thread_post_index is aligned to 0-based /t/tag/N routes, silent unwrap_or(0) fallbacks become hard expects, the garden link is always emitted, and integration assertions lock the contract. A only collapses hand-enumerated kaocha ns-patterns into one ^test\..+ suite—a useful test-ops cleanup, but not a lasting behavioral fix.
Side B fixes a semantic inconsistency by making `thread_post_index` consistently 0-based for rank history, replacing silent `unwrap_or(0)` fallbacks with `expect(...)` to enforce an invariant, updating documentation, rendering, and adding integration tests that verify the behavior. Side A improves maintainability by replacing manually enumerated Kaocha test namespaces with a single auto-discovered `^test\..+` suite, but it is primarily a test configuration simplification rather than a functional correctness change.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_f6d0fed9bf9a (tommy-mor)
Side A is a coherent, real fix: it removes a silently-defaulting `.unwrap_or(0)` fallback for thread_post_index in favor of an explicit `expect` that surfaces bugs, fixes the corresponding UI/link logic, updates doc comments to match 0-based semantics, and adds regression tests verifying the new indexing behavior end-to-end. Side B is a dump of large, mostly unrelated file snapshots (including literal shell-prompt lines like 'tommy@Tommys-Laptop:...⇒ cat ...' pasted into the diff), design notes/tdsl files, and whole modules added wholesale with no clear incremental change being reviewed, making it noisy and hard to attribute as a meaningful single commit of lasting value.
A is a precise correctness fix: thread_post_index becomes consistently 0-based (matching `/t/tag/N`), drops silent `unwrap_or(0)` fallbacks for `expect`, always emits the post link, documents the contract, and extends integration tests. B is mostly seed noise—brainstorm `.tdsl` notes, shell-prompt-corrupted file dumps, and a large unrelated Reddit parser—so line volume does not translate into lasting integrated design.
Side B introduces substantial new project functionality, including core ranking/reducer logic, a URL parser with extensive tests, UI action handling, vote flow, and supporting infrastructure, despite also containing some noisy or accidental content (such as terminal captures and planning files). Side A is a useful correctness change that enforces invariants with `expect`, aligns `thread_post_index` with 0-based URLs, updates documentation, and adds regression tests, but it is a comparatively narrow refinement.
comparison · c_cf0a514b261a (tommy-mor) vs c_6a02ffb06a41 (tommy-mor)
Side B fixes a real off-by-one/indexing bug (0-based vs 1-based thread_post_index mismatch used in URLs), removes a dead conditional in the template, and adds regression tests plus doc clarifications across three files, giving concrete lasting correctness value. Side A merely removes a redundant early-return guard that was already dead code, a smaller and lower-impact cleanup with a single adjusted test.
B fixes real indexing inconsistency by switching rank-history thread_post_index from 1-based-with-silent-0-default to shared 0-based paths (/t/tag/N), replacing unwrap_or(0) with invariant enforcement and updating API/UI/tests/docs accordingly. A only deletes a dead zero-ratio guard already enforced upstream and retunes one unit test, which is sound cleanup but lower lasting impact.
Side B corrects and standardizes the thread post index semantics across RPC, HTML, types, and integration tests: it switches rank history to the intended 0-based `/t/tag/N` indexing, removes the silent `unwrap_or(0)` fallback in favor of asserting the expected invariant with `expect(...)`, and updates rendering and documentation accordingly. Side A is a worthwhile cleanup that removes a redundant zero-ratio guard and updates tests to reflect that zero-weight edges are skipped elsewhere, but it is primarily dead-code removal relying on existing validation.
comparison · c_ebc883667d61 (tommy-mor) vs c_6a02ffb06a41 (tommy-mor)
A resolves a real structural defect (a duplicate forum.rs colliding with the forum/ module tree) and cleanly modularizes ~1400 lines into focused files (feed, nav, ingest, paginator, views, etc.), producing lasting architectural clarity. B is a smaller but well-tested correctness fix — normalizing thread_post_index to 0-based across rpc.rs/garden.rs and adding integration test assertions — valuable but narrower in scope than A's necessary and broad reorganization/bugfix.
Side B fixes a real off-by-one bug: rank-history post indexes were 1-based with a silent unwrap_or(0) fallback, breaking links and disagreeing with 0-based /t/tag/N routes; it aligns RPC, garden HTML, types, and integration tests on the correct contract. Side A only deletes a leftover forum.rs duplicate and wires forum/ as the module root after a split—useful hygiene that removes ambiguity, but it adds no behavioral value beyond cleanup of already-split code.
Side A resolves a structural module issue by deleting the obsolete monolithic `server/src/html/forum.rs`, adding `forum/mod.rs`, and moving the implementation into focused submodules (`feed.rs`, `views.rs`, `page.rs`, `paginator.rs`, `post_single.rs`, `profile.rs`, `thread_morph.rs`), ensuring `mod forum` unambiguously resolves to `forum/mod.rs` and improving maintainability without changing behavior. Side B makes a smaller semantic cleanup by changing rank-history post indexes to the project's 0-based URL convention, replacing silent fallbacks with `expect(...)`, updating links, comments, and tests, but its impact is narrower.
comparison · c_4ed2e2cca39b (tommy-mor) vs c_6a02ffb06a41 (tommy-mor)
Commit A is a tiny one-line config fix that resolves a NameError, useful but narrow in scope. Commit B fixes an off-by-one indexing bug consistently across rpc.rs and garden.rs, updates doc comments to correctly describe 0-based vs 1-based indexing, removes a misleading fallback that masked bugs, and adds regression tests verifying the corrected behavior, giving it broader and more durable impact.
B fixes real indexing semantics (1-based optional fallback → 0-based invariant matching /t/tag/N), drops a silent unwrap_or(0) that could hide missing posts, aligns RPC/HTML/types, and locks behavior with integration asserts. A only introduces a missing GITHUB_API_BASE_URL default—necessary but a one-site config patch with no comparable design or test depth.
Side B corrects the rank-history thread index semantics by making `thread_post_index` consistently 0-based, replacing silent `unwrap_or(0)` fallbacks with `expect(...)` to catch invariant violations, updating UI links, documentation, and adding integration tests that verify the behavior. Side A is a targeted but much smaller fix that defines `GITHUB_API_BASE_URL` to prevent a `NameError` in the GitHub OAuth callback when the API base URL is otherwise missing.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_3ff71f7eaeda (tommy-mor)
Side B fixes a real UX bug (HUD 'pinned item' link navigating away instead of properly unpinning, replaced with a correct POST-based unpin form), adds a genuinely useful vote-count indicator with backing unit test, and includes corresponding CSS and browser-test coverage. Side A is a smaller, more localized change replacing a fallback default with a panic/expect and updating doc comments/tests, which is reasonable but lower-impact and riskier (introducing a potential panic) compared to B's broader, well-tested feature fix.
A permanently reconciles rank-history thread_post_index with the 0-based /t/tag/N routes (types, RPC, garden recv view), replaces silent unwrap_or(0)/1-based offsets with a hard expect, and locks the contract in integration asserts—fixing link bugs class. B adds solid UX (edge vote counts, HUD unpin via set_garden_pin clear) plus tests/CSS, but it is product surface polish rather than a shared data/URL invariant fix.
Side B adds substantive user-facing functionality: it introduces pairwise vote counts in the garden UI with a tested helper (`edge_vote_count_for_pair`), changes the pin HUD to perform an unpin action via `POST /ui`, updates styling, and adds browser and unit tests covering the new behavior. Side A mainly corrects thread post indexing semantics by replacing a fallback with `expect`, always rendering the post link, updating documentation, and extending integration tests, which is valuable but much narrower in scope and lasting impact.
comparison · c_d6d339485601 (tommy-mor) vs c_6a02ffb06a41 (tommy-mor)
Side B fixes a real correctness bug (silently defaulting to 0 instead of failing when an ingested post can't be found, and inconsistent 1-vs-0 indexing across garden.rs, rpc.rs, and types docs), consistently updates all affected call sites, and adds integration tests asserting correct index values. Side A only adds a new CLI display helper for existing stats with unit tests, which is useful but a smaller, purely additive feature rather than a fix to an existing defect.
A adds a complete, tested user-facing feature that surfaces existing ConnectivityStats (density, components, comparisons-to-connect) in pair CLI output, directly aiding voting decisions. B only tightens rank-history indexing (drop unwrap_or(0)/1-based map, always emit 0-based links, assert in tests)—a useful consistency fix, but narrower and less product leverage than A’s topology guidance.
Side A adds a new user-facing capability by exposing graph connectivity statistics in CLI pair output, including density, component count, connection status, and dedicated tests covering connected and disconnected cases. Side B mainly tightens an invariant by replacing fallback values with `expect`, aligns documentation and UI around 0-based thread indices, and adds assertions, but it is largely a consistency/refinement change rather than a substantial new feature.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_16438843de8f (tommy-mor)
Side A is a focused, verified correctness fix: it removes a silent unwrap_or(0) fallback that masked invariant violations, replaces it with an explicit expect, aligns doc comments/URLs to the actual 0-indexed semantics, and adds concrete integration tests validating thread_post_index behavior. Side B mostly dumps unintegrated scaffolding (event_log.rs and views.rs at repo root, not wired into any module tree) plus deployment config and an unrelated Clojure deps.edn, with no tests and unclear integration into the existing Rust crate structure.
A makes a coherent, tested contract fix: rank-history thread_post_index becomes consistently 0-based like /t/tag/N, drops silent unwrap_or(0) fallbacks for expect, updates API docs/HTML links, and asserts behavior in integration tests. B mainly dumps unwired seed files (root event_log.rs/views.rs with no module wiring, plus deps.edn) alongside useful but thinner deploy scaffolding (Dockerfile/fly.toml), so less proven lasting design impact.
Side A fixes a semantic inconsistency by making rank-history thread indices consistently 0-based to match `/t/tag/N` routes, replacing silent fallbacks with `expect(...)` to enforce an invariant, updating documentation, always rendering the post link, and adding integration tests that verify the behavior. Side B adds several new infrastructure and utility files (Dockerfile, Fly config, event log, view store), but they are largely standalone additions without evidence in this patch of integration into the main application, making their demonstrated lasting impact less certain.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_e57094c6229a (tommy-mor)
Side B implements a substantive feature (explicit user-triggered Reddit entity fetch, event-sourced raw payload storage, replay support, config injection for testability, and an integration test with a mock server), representing real architectural and functional progress. Side A is a small correctness cleanup (replacing a silent default with an explicit expect and dropping a conditional link check) plus doc-comment fixes, useful but far more limited in scope and lasting impact.
B redesigns Reddit import around durable EntityImported events (full payload + derived view), explicit user fetch UI, configurable API bases, and a mock end-to-end test—lasting architecture. A only realigns rank-history thread_post_index to strict 0-based paths (expect instead of unwrap_or) with small test/doc tweaks, valuable but narrow.
Side B introduces substantial new functionality and architecture: explicit user-triggered Reddit entity fetching, persistent `EntityImported` events with replay support, storage of raw API payloads plus derived views, configurable API endpoints, dotenv loading, and accompanying UI, tests, and fixtures. Side A is a focused correctness fix that makes `thread_post_index` consistently 0-based by replacing a silent fallback with `expect`, updating documentation, always rendering the link, and adding integration tests, but its scope and lasting impact are much smaller.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_1c1c8e7a2de8 (tommy-mor)
Side B removes real dead/unused complexity (unused ThreadVisibility enum, unused public-room-creation path, simplifies rooms from HashMap to HashSet) and adds a genuinely useful CLI 'room create' command with docs and updated tests across multiple test suites, representing broader functional value. Side A is a smaller, more surgical fix (replacing a silent unwrap_or(0) fallback with an explicit expect and fixing an off-by-one index semantic), which is correct but narrower in scope than B's combination of dead-code removal and new CLI functionality.
B adds a real CLI `room create` path and lasting domain simplification (drop ThreadVisibility/RoomState, rooms as HashSet, simpler RoomCreate RPC) wired through server, types, tests, and docs. A only tightens rank-history indexing (1-based/optional → 0-based/expect, UI always links, tests), a correct but narrower consistency fix.
Side B adds a substantial new CLI capability for creating private rooms (`room create`), wires it through command parsing and RPC, simplifies the room model by removing unused visibility state (replacing a `HashMap` of room metadata with a `HashSet` of room IDs), and updates tests and documentation accordingly. Side A mainly corrects the thread post index semantics by enforcing the invariant with `expect`, always rendering the post link, updating documentation, and adding tests, which is a useful but narrower consistency fix.
comparison · c_bc8c17a00ed7 (tommy-mor) vs c_6a02ffb06a41 (tommy-mor)
Side A fixes a real, self-contained bug (pinned posts polluting ranked imports) with a clear implementation and a targeted regression test. Side B is a fragile fix-up that switches a fallback default to a panic (`.expect(...)`) on missing data, which risks introducing crashes on malformed/edge-case input rather than clearly improving correctness, and mostly consists of doc-comment tweaks and index-off-by-one churn.
A adds lasting import logic: skip stickied/pinned Reddit children with a small helper and a focused unit test, improving data quality at the source. B mainly tightens indexing (drop unwrap_or(0)/1-based optionality for expect + 0-based paths, always render the link, doc/test tweaks)—valuable consistency, but more corrective of local model/UI wiring than a new durable behavior.
Side A fixes a concrete import behavior by skipping Reddit stickied/pinned posts during subreddit listing parsing, adds a dedicated helper checking both `stickied` and `pinned` flags, and includes a focused regression test verifying only normal posts are imported. Side B mainly changes an optional lookup into an asserted invariant, updates indexing semantics/documentation, and adjusts tests and UI links, which is valuable for consistency but is a narrower refactor rather than a user-facing correctness fix.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_f515f8a12d7a (tommy-mor)
Side A fixes a real semantic bug (silently defaulting to index 0 via unwrap_or, masking mismatches) with an explicit invariant-asserting expect, removes an inconsistent conditional link-hiding UI branch, and adds targeted regression tests plus doc corrections across three files. Side B is a reasonable UI simplification/dedup (removing a redundant toolbar action) but is more of a cleanup/refactor with less correctness impact and no new test coverage.
A fixes real indexing semantics: rank-history thread_post_index aligns with 0-based /t/tag/N routes, drops the silent unwrap_or(0)/+1 skew, and locks it with RPC/HTML expect + integration asserts. B is worthwhile UI cleanup (SSR home compose like rooms, delete ExpandNewThreadForm and the extra toolbar), but it is path consolidation rather than a correctness/API fix.
Side B removes the now-redundant `ExpandNewThreadForm` UI action end-to-end, simplifies the home page to server-render the collapsed compose/login state directly, and deletes the associated parsing and tests, reducing maintenance for a unified single-`+` flow. Side A fixes `thread_post_index` semantics by enforcing the invariant with `expect`, switching rank-history links to consistent 0-based URLs, updating documentation, and adding tests, but its scope is narrower than the architectural simplification in Side B.
comparison · c_64faa3bee86f (tommy-mor) vs c_6a02ffb06a41 (tommy-mor)
B fixes an actual off-by-one/inconsistency bug (thread_post_index using different 0/1-based conventions between feed and rank-history/URLs), adds regression tests asserting the correct indices, and updates doc comments accordingly—concrete, verifiable correctness improvement. A is a reasonable UX feature (inline form morphing instead of redirect) but is more speculative UI churn without tests, and its value is harder to verify from the diff alone.
A redesigns auth to return HTML fragments and morph the form via poem JS, removing redirect churn and a parallel auth_layout in favor of the shared layout—lasting UX/architecture. B only aligns thread_post_index to 0-based paths (drop +1/unwrap_or(0), expect, tests), a precise correctness fix but narrower in scope.
Side A implements a substantive authentication UX change: the server returns HTML fragments instead of redirects, the shared Poem JS fetch handler now morphs form innerHTML when a response contains HTML, auth templates are refactored to support fragment rendering, and matching CSS is added. Side B mainly corrects thread post indexing semantics by replacing a fallback with an invariant-enforcing expect, updating links, comments, and tests; while useful, it is a comparatively narrow consistency fix rather than a broader, reusable feature.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_3403e5929da7 (tommy-mor)
Side A fixes a real inconsistency (mixed 0/1-indexing between UI, RPC, and history rows), enforces an invariant with an explicit expect, and adds integration test assertions verifying the corrected index values, giving lasting correctness value. Side B is a smaller UI grouping refinement (splitting unranked siblings into separate groups) with a single unit test, useful but narrower in scope and impact.
A fixes real indexing inconsistency (1-based/unwrap_or(0) → 0-based expect aligned with /t/tag/N), updating RPC, types, HTML links, and integration asserts so rank-history URLs are correct. B only regroups unranked siblings into singleton nav groups plus a unit test—a narrower UI presentation tweak with less cross-cutting impact.
Side A changes the rank-history thread index from a silent fallback (`unwrap_or(0)` after converting to 1-based) to an enforced invariant with `expect`, aligns the value with the project's 0-based `/t/tag/N` URLs, updates documentation, always renders the link, and adds integration tests verifying the behavior. Side B is a localized UI improvement that groups each unranked sibling separately and adds a corresponding unit test, but it affects presentation rather than correcting a broader API/data consistency issue.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_14dd365ffe22 (tommy-mor)
Commit B is a substantive refactor that removes an entire theme-switching subsystem (CSS files, cookie handling, form endpoint) and replaces query-param item addressing with a cleaner path-based `/~/` browse route, backed by new URL parsing logic and tests. Commit A is a smaller, more localized fix (replacing a fallback default with an explicit panic/expect and correcting doc comments/indexing semantics), which is useful but far more limited in scope and lasting architectural impact.
B introduces a lasting routing design (`ItemId::browse_href` / `/~/…`), removes the theme cookie/CSS machinery, and wires real browse handlers with tests—foundational product structure. A is a correct but narrow consistency fix (0-based `thread_post_index`, `expect` instead of silent `unwrap_or(0)`, always-on post links) with supporting asserts, so it matters less overall.
Side B makes a substantial architectural change by replacing query-parameter navigation with canonical `/~/...` browse routes, centralizing URL generation/parsing in `ItemId` (`browse_href`, `from_browse_uri`), updating routing, and adding integration tests for the new behavior. Side A mainly tightens an invariant by replacing a silent fallback with `expect`, aligns documentation/tests around 0-based thread indices, and always renders the post link, which is useful but much narrower in lasting impact.
comparison · c_597d3f736194 (tommy-mor) vs c_6a02ffb06a41 (tommy-mor)
Side B fixes a real off-by-one/index-base bug (1-indexed vs 0-indexed thread_post_index) across server rpc, HTML rendering, and types, and backs it with new integration test assertions verifying correctness, giving lasting correctness value. Side A also fixes real bugs (regex split, request body vs input stream, missing try/catch, null-state handling) improving test infra robustness, which is valuable but more localized to test harness code rather than production logic.
A fixes multiple concrete mock-server bugs (wrong HttpExchange body stream, 302 content-length, fragile query split, null token/state) that had broken real Clojure E2E/Playwright OAuth login, plus makes alias/history reads use reliable selectors. B only tightens thread_post_index to mandatory 0-based indexing with expect and always-on links—a valid consistency fix, but narrower and less unblocking than restoring auth E2E.
Side A fixes multiple concrete failures in the OAuth test infrastructure: it corrects query parsing (`str/split` with regex), reads POST bodies from `getRequestBody`, avoids null crashes when parsing bearer tokens and missing state, fixes redirect response handling, wraps handlers with error reporting, and updates Playwright helpers to use selectors reliably. Side B mainly changes rank-history indexing semantics by replacing a fallback with `expect`, updating documentation/tests, and always rendering a link, which is a narrower behavioral cleanup with less broad impact than restoring broken end-to-end authentication flows.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_f10e7b043e68 (tommy-mor)
Commit B replaces an ad-hoc rule-combinator engine with a more principled semantic graph/DFA architecture for URL canonicalization, a substantive design change with lasting structural impact (even though the diff removes tests, it references new modules graph.rs/parse.rs/registry_tests.rs implying continued coverage). Commit A is a smaller correctness/clarity fix (converting a silent fallback to an explicit panic with better invariants and doc clarifications, plus added test assertions), which is valuable but narrower in scope than B's architectural overhaul.
B replaces ad-hoc URL combinators (engine.rs + per-host normalize paths) with a graph/DFA-based canonicalization API wired through registry, which is core identity infrastructure lasting across the product. A is a correct but narrow fix: rank-history thread_post_index becomes strictly 0-based with expect() and tests, removing optional 1-based/unwrap_or(0) mismatch—valuable polish, not system-level design.
Side A fixes the thread post index semantics by making rank history consistently use the 0-based URL index, replacing silent `unwrap_or(0)` fallbacks with `expect(...)` to catch broken invariants, updating documentation, removing conditional rendering, and adding integration tests that verify the behavior. Side B is primarily a large refactor of the URL canonicalization subsystem (moving logic into new graph/parse modules and deleting the old engine) but the shown patch mostly rewires interfaces and removes in-file tests without exposing the new implementation, making its lasting functional value less evident from the diff.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_ca72f0995396 (tommy-mor)
Commit A fixes a real correctness bug: the previous code silently mapped a missing post lookup to index 0 (which is also a valid index for the first post), making the UI guard `if index > 0` meaningless and the link route (0-based) inconsistent with the displayed 1-based index; A aligns the indexing with the actual /t/tag/N route, replaces the silent fallback with an explicit invariant check, and adds tests asserting correct indices. Commit B is a reasonable UI refactor (grouping CLI hints, hover-to-copy, JS-safety assert) but is mostly cosmetic/feature polish without fixing an underlying correctness issue.
A fixes real contract/indexing bugs: rank-history thread_post_index becomes required 0-based (matching /t/tag/N), drops unwrap_or(0) masking and 1-based off-by-one link logic, and locks that in with type docs plus integration asserts. B is worthwhile CLI UX (grouped panels, row click-to-copy, JS quote asserts, CSS), but it is largely presentation polish versus A’s lasting correctness and API consistency.
Side A fixes the semantics of `thread_post_index` by making rank history consistently use the existing 0-based URL index, replacing silent `unwrap_or(0)` fallbacks with `expect(...)` to enforce the invariant, updating documentation, removing incorrect conditional rendering, and adding integration tests that verify the behavior. Side B is primarily a UI enhancement that refactors the CLI panel to support multiple commands with click-to-copy and adds assertions for JS-safe strings, which is useful but less fundamental than correcting and validating core data behavior.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_939729b4d9a6 (tommy-mor)
Side A is a coherent, self-contained bugfix: it replaces a silently wrong fallback (unwrap_or(0)) with an explicit invariant check, fixes the actual 0-based vs 1-based indexing bug, updates docs, and adds concrete regression tests verifying the fix. Side B's diff references new modules (crate::html::vote, crate::pair) and routes that are never defined in the shown patch, making it appear incomplete/non-compiling as presented, and mixes unrelated dependency additions (rand, urlencoding) and generated Cargo.lock churn with the actual feature work.
B ships a real user-facing vote-compare flow (route, CTA, slider JS/CSS, post-vote `next` navigation) plus reusable form infrastructure (`$form:i32` holes and tests), whereas A only tightens rank-history indexing from optional 1-based `unwrap_or(0)` to required 0-based `expect` with matching docs/tests. B’s design surface and lasting product value outweigh A’s focused correctness cleanup.
Side B adds substantive new infrastructure: typed form-template substitution (`$form:i32`) with tests, a `next` navigation flow after recording votes, new routing/hooks for a vote page, and supporting UI behavior (slider initialization and redirect handling). Side A mainly tightens an invariant by replacing `unwrap_or(0)` with `expect(...)`, updates documentation/tests to enforce 0-based thread indices, and always renders the post link; these are useful correctness and clarity improvements but are narrower in lasting impact.
comparison · c_6a02ffb06a41 (tommy-mor) vs c_59974b9da42a (tommy-mor)
Side B is a substantial, coherent refactor that extracts forum.rs into focused submodules (nav, ingest, room_members, new_thread, access) plus a useful new sampling script/task, improving maintainability without changing behavior. Side A is a small, valid bugfix/clarification (turning silent fallback into an explicit expect and fixing docs/tests for 0-based thread_post_index), which is correct but much narrower in lasting impact.
A fixes a real indexing bug/inconsistency: rank-history `thread_post_index` becomes required 0-based (aligned with `/t/tag/N`), drops silent `unwrap_or(0)`/`+1` and the conditional link UI, and locks behavior with integration asserts. B is mostly a file split/inline of forum helpers plus an unrelated macOS sample script—useful structure/tooling, but little lasting product semantics versus A’s correctness change.