84
Total Votes
65
Upvotes
19
Downvotes
84
Unique PRs
+65-19

Activity

bigintersmindComment#218Once a week the best shall speak - ten votes to earn the merge you seek

This PR didn't change the countdown timer, so it's going to keep ticking down every 24 hours on openchaos.dev.

#220 fixes this.

bigintersmindComment#219The maintainer's last veto stands, putting merge power in the people's hands

What a, dare I say, chaotic sequence of events.

bigintersmindComment#218Once a week the best shall speak - ten votes to earn the merge you seek

I like the idea and agree. I'm in favor of the change.

bigintersmindComment#217A welcome popup springs up to say hey, so new visitors don't wander away

Great idea, @amanbabuhemant! I've updated the PR to make each theme's approach unique.

Screenshots and PR description updated.

bigintersmindComment#213Fix automerge: skip the unmergeable surge, let pending with no count emerge

Suuuuurely it works this time!

bigintersmindComment#208No more lists for the human eye, just a chatbot powered by AI

I love the idea. I don't love that users have to sign up for another service to use the website.

bigintersmindComment#156README is the clear guide, RULES.md steps aside

Why automerge skipped this PR

This PR has 7 net votes, a rhyming title, passing CI, and no merge conflicts — it should have won today's daily merge. However, it was skipped because the combined commit status API returns pending.

Root cause: The branch protection rules for main require a status check named CI (the workflow name), but GitHub Actions only reports status for individual jobs (CI / build, CI / protect-constitution). The CI check is perpetually stuck at "Expected — Waiting for status to be reported" on every PR, which makes the combined status pending, which the automerge workflow treats as a hard skip.

Fix: In the repo's branch protection settings for main, remove the required status check CI and replace it with CI / build. This will unblock automerge for this PR and all others affected (#187, #193, #160, #183, #209).

bigintersmindComment#208No more lists for the human eye, just a chatbot powered by AI

This is fun. Who pays the bill?

bigintersmindComment#189My take on "chaos" in OpenChaos

In that vein, I worked to make adding new themes easier with #204. I didn't do an "internet through time" theme because I thought it might feel quite limiting, but I think it's actually worth re-exploring.

We could do an archive.org-style website where new PRs could add new views in the timeline. We can get creative with themes outside of that framing. For example, newspaper could be even earlier on the timeline.

bigintersmindComment#201Your arrows glow to show the flow of every vote below

Deployment Notes

No configuration changes needed. This feature works with the existing GitHub OAuth app and environment variables (GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET). No new env vars, no scope changes, no permission updates.

How it works

  1. When a logged-in user views the PR list, the useVoteStatus hook calls GET /api/vote-status?prs=1,2,3,... with their session cookie.
  2. The API endpoint authenticates via GET /user, then batch-fetches reactions from GET /repos/.../issues/{n}/reactions for each PR — the same reactions API the existing vote feature already uses.
  3. Each PR card receives its vote status (up, down, or null) and renders a glow on the corresponding arrow.
  4. When a user casts a new vote, the status updates optimistically via onVoted callback — no extra API round-trip needed.

Rate limiting

The endpoint caps at 50 PRs × 10 pages max per request. Failures on individual PRs are caught by Promise.allSettled and logged server-side — the rest of the votes still load. Users see a non-intrusive warning if something goes wrong.

bigintersmindComment#203Send Dickbutt and Doom to the virtual museum room

Can we add Fartscroll to the list? (Maybe a giant turd emoji and Fartscroll is enabled only on the Museum page?)

bigintersmindComment#204Extra! Extra! The Daily Chaos theme is here to stay, read all about it today!

Agreed, I was thinking the same and was on the fence about it.

bigintersmindComment#168Mergeability detection for automerge correction

Gah, I missed it in my last-minute testing; the package is ESM-only, so require() throws an error.

Added the one-line fix to #195.

bigintersmindComment#183Decimate: Alea Iacta Est, put your PRs to the test

I think this problem is sufficiently solved with #185

bigintersmindComment#184Vote integrity inspection for bait-and-switch detection

Closing — reaction has been tepid to mixed, and supporting multiple layouts makes it tough to avoid breaking changes from newly merged PRs.

bigintersmindComment#199Add author quote to earn your vote

This is a super cool idea

bigintersmindComment#168Mergeability detection for automerge correction

No worries! Once I reviewed your PR, I realized that I'd missed the rhyme detection update and forgot to update to daily merges! So it's great that you did it, because I may have merged an incomplete fix otherwise.

bigintersmindComment#143Chaos N: random themes for chaotic dreams

A version of this was included with #163. If you decide to revisit this, please remove the Rust artifacts.

bigintersmindComment#146XP error dialogs are new, and a Start Menu too

Closing — this needs reimagining for the current architecture (ASCII + Web 2.0 dual themes). The XP dialogs concept may return in a different form.

bigintersmindComment#185Add old-age death: PRs take their final breath

You're right, two died. There's no limit in the workflow.

Added this logic to #195, as well.

bigintersmindComment#163Web 2.0 joins the fray, ASCII's here to stay

Buckle up! 🤣

bigintersmindComment#185Add old-age death: PRs take their final breath

Bug: Mergeability detection is broken

The workflow uses pulls.list to fetch all open PRs, then checks pr.mergeable_state and pr.mergeable to detect conflicts. However, the pulls.list endpoint does not return these fields — they are only populated by the individual pulls.get endpoint, which computes mergeability on demand.

As a result, pr.mergeable_state and pr.mergeable are always undefined, and isUnmergeable is always false. The unmergeable penalty (5% base + 5x multiplier) has never applied to any PR.

Example: PR #84 currently has merge conflicts (mergeable: CONFLICTING, mergeable_state: dirty), but the workflow evaluated it with a 13.39% death chance instead of the ~50%+ it should have had.

Fix: Each PR needs an individual pulls.get call to retrieve mergeability info:

const { data: fullPr } = await github.rest.pulls.get({
  owner, repo, pull_number: pr.number
});
const isUnmergeable =
    fullPr.mergeable_state === 'dirty' ||
    fullPr.mergeable === false;

Note that mergeable can be null while GitHub is still computing it, so a brief delay/retry may also be needed on first fetch.

bigintersmindComment#163Web 2.0 joins the fray, ASCII's here to stay

@matthewmayer , this now co-exists with your ASCII view (which I love!). Users would have a 50/50 chance of landing in either view.

Other PRs can build off this foundation by adding additional views.

bigintersmindComment#124feat: Show PR rank, uh, it's dank

Hmm, no ranks after expanding, or in the trending section.

bigintersmindComment#70When the world's in disarray, this banner has something to say!.

Is "Controll" an intended misspelling (to include "troll" perhaps), or a typo?

bigintersmindComment#185Add old-age death: PRs take their final breath

I agree with your suggestions to reduce the dirty multiplier and cap it at 1/day, @matthewmayer.

Regardless of multiplier settings, capping at 1 death/day turns it from mass extinction into a sustainable daily drama. In that vein, maybe it's worth immortalizing the culled PRs on the front page somehow?

Also, a grace period (ignoring dirty status for 24–48h after a daily merge) would help with the timezone fairness issue, but would add implementation complexity.

I really like the idea, but think we should tune it to be more fun than discouraging.

bigintersmindComment#185Add old-age death: PRs take their final breath

Simulation Results: What the Old Age Algorithm Would Do Today

I ran a Monte Carlo simulation (10,000 runs) against the current 64 open PRs to see how this workflow would play out.

Day 1 Impact

The algorithm would kill ~17 PRs on its first run — over a quarter of all open PRs. The unmergeable + old PRs get hit hardest:

PRAgeInteractionsDeath Chance
#8432d579.3%
#4637d2776.8%
#8232d775.6%
#7932d874.1%
#538d6169.5%
#1238d10562.1%

Even #12 with 105 interactions still faces 62% death — the unmergeable 5x multiplier overwhelms the fitness protection.

7-Day Projection

DayAvg DeathsAvg Alive
117.246.8
29.537.3
35.831.5
44.027.5
52.924.6
62.222.4
71.720.7

After 7 days: ~21 survivors out of 64 (min 13, max 29 across simulations). Deaths front-load heavily as the high-risk PRs die first, then taper off.

Key Observations

  • 42 of 64 PRs have <50% chance of surviving a full week
  • The dirty mergeable state is the dominant factor. The 5x unmergeable multiplier means any PR with merge conflicts and more than ~10 days of age is in serious danger, regardless of engagement
  • dirty is the norm, not the exception. Since a PR merges daily, every other open PR touching the same files becomes conflicted. Authors may have less than 24 hours between the daily merge (09:00 UTC) and the old-age sweep (06:00 UTC) to rebase — and that window gets worse since the sweep runs before most people's working hours. In practice, the majority of PRs will carry the dirty state at any given time (39 of 64 currently do)
  • Engagement barely helps unmergeable PRs. PR #12 has 105 interactions but still 62% daily death because the multiplier is applied after fitness reduction
  • Non-dirty PRs are comparatively safe. PR #45 (37 days old, behind) only has 10% daily risk. Same-aged dirty PRs face 60-80%
  • Young mergeable PRs are essentially immune. 6 PRs have >99% weekly survival — all are <13 days old and not dirty

Capped vs Uncapped Culling

There is no per-day cap on deaths. In the worst simulated week, 51 of 64 PRs died. On day 1 alone, up to ~30 deaths are possible in an unlucky run. If the intent is gradual natural selection rather than a mass extinction event, a daily cap might be worth considering.

bigintersmindIssue opened#189

My take on "chaos" in OpenChaos

When I got involved, my read on "OpenChaos" was that the chaos is a byproduct of being open, not the objective. @skridlevsky pitched this as "a repo where the internet votes on PRs and the winner ships." That's compelling because the chaos is emergent. It comes from the lack of ground rules, not from everyone trying to maximize disorder.

Two rallying themes have taken hold: Democracy (because the mechanic is voting) and Chaos (because it's in the name). I think the democracy thread has been genuinely productive, as it's spawned real governance debates, disclosure rules, and updated voting proposals (#176). The chaos thread, on the other hand, seems to be converging on "make the interface as unusable as possible," which I think misreads the project.

100% chaos is /dev/urandom. That's not interesting, and it's not what drew people here. What's interesting is watching what organically emerges when a group of people builds something with no predetermined direction. Which sometimes looks chaotic and sometimes doesn't.

If the group's intent is to make a website that's miserable to use but checks the "chaotic" box, I think the project flames out shortly (as evidenced by the winning vote being lower each day). If we're interested in building something that people actually want to join and participate in over time, we need to move past chaos maximization as a goal and let it be what it always was: a side effect.

bigintersmindComment#130It's been a while, so change to text-only ASCII style

I was working on a time machine feature, but it turned out to be more complicated than I hoped, and I shelved it when #143 showed up. I might revisit it.

bigintersmindComment#153🔥💀 DEMOCRACY UPRISING: THE PEOPLE CAN FINALLY VOTE 💀🔥

Looks great until you refresh the page!

bigintersmindComment#153🔥💀 DEMOCRACY UPRISING: THE PEOPLE CAN FINALLY VOTE 💀🔥

This is a great addition, now that it's working. My only feature request is to be able to see how I already voted on PRs when loading the page.

bigintersmindComment#130It's been a while, so change to text-only ASCII style

Yes, random routing would be a big win! Let's give all of the different designs some time in the sun!

bigintersmindComment#127Shake to stir the storm — break the norm!

For some reason, this one makes me nauseous.

bigintersmindComment#124feat: Show PR rank

That looks nice. I was just looking for a low-lift solution, and those PRs already had a rank of zero in your code. I prefer your new approach, however.

bigintersmindComment#124feat: Show PR rank

One thing to flag: after merging into main, the "Trending This Week" section (added in #69) shows "0" for each PR because it passes rank=0.

Screenshot 2026-02-09 at 5 09 12 PM

A quick fix would be to fall back to the PR number when there's no rank:

<b>{rank > 0 ? rank : `#${pr.number}`}</b>

That way, ranked sections show the position and unranked sections show the PR number like before.

bigintersmindComment#124feat: Show PR rank

I like the way you've handled it, numbering them as they're sorted on the page.

bigintersmindComment#153🔥💀 DEMOCRACY UPRISING: THE PEOPLE CAN FINALLY VOTE 💀🔥

Still a 404 on my end.

bigintersmindComment#153🔥💀 DEMOCRACY UPRISING: THE PEOPLE CAN FINALLY VOTE 💀🔥

Trying to vote or login just sends me to a github 404 page...

bigintersmindComment#143Add Chaos^N: Random theme routing for infinite variants

I'm bummed this doesn't have more votes. I was hoping this would merge before #130 and the other re-styles. Where possible, we should keep the RPs that were voted in rather than overwriting them.

bigintersmindComment#184Vote integrity inspection to prevent bait-and-switch deception

Yeah, that's fair. I don't think that would be a big deal, though. If votes were being reset more often, the totals would be lower, we wouldn't be getting as many super old PRs winning by default, and people would be more actively voting. At least, that's my theory, and a better state for the project, in my view.

That said, this PR may not quite get us there, but I think it's a preferred direction for the project and part of a wider solution, along with #158.

bigintersmindComment#184Add vote integrity system to prevent bait-and-switch PRs

@Nickhoyer, sure, put it in the PR!

bigintersmindComment#173Fix: Move 1.337% randomness check client-side to prevent cached blank pages

Closing this PR. The core bug (server-side Math.random() causing cached blank pages) was already fixed by PR #76, which moved the randomness check to IE6Layout.tsx (a client component). This PR is now only a minor code quality refinement of that fix and isn't worth a separate merge.

bigintersmindComment#171Add a working Windows XP Start Menu

Start Menu merged into #146 (combined XP features PR).

bigintersmindComment#163Web 2.0 Reskin: It's Time to Upgrade from IE6

@Daviey #143 would allow for both to be supported.

bigintersmindComment#177Close inactive PRs

This PR addresses the issue you describe: #158

bigintersmindComment#176Should only contributors be allowed to vote?

I was thinking of a similar solution to the current problem, where we will fail to a white page every day until #174 is fixed.

What if we amend the rules to allow an emergency council to bypass popular vote for bugfixes (however we define that)? The emergency council would comprise anyone who has had a PR merged under the typical voting rules and would require a minimum threshold of votes in favor.

If we can align on a strategy, I can add it to #174 as a comprehensive fix for this type of situation going forward.

bigintersmindComment#143Add Chaos^N: Random theme routing for infinite variants

Aha, I missed that. Thank you for sharing!

bigintersmindComment#129Deprioritize PRs with merge conflicts in ranking

Bug fix: merge status & CI check detection

These bugs exist on main and were not introduced by this PR. This commit fixes them.

1. Wrong API endpoint for CI checks

The code was using the commit status API (/commits/{sha}/status), but this repo's CI uses GitHub Actions, which create check runs — a separate system. The commit status endpoint returned state: "pending" with zero statuses for every PR, since nothing in this repo writes commit statuses. Switched to the check runs API (/commits/{sha}/check-runs), which returns the actual CI results.

2. mergeable: null treated as conflicts

GitHub computes mergeability lazily. The first API request after a change often returns mergeable: null (not yet computed). The code treated null as false, showing false "Merge conflicts" for PRs that are perfectly mergeable. Now defaults to true when null, and the next ISR revalidation cycle (5 min) picks up the real value.

3. Graceful degradation on API errors

Both getPRMergeStatus and getCommitStatus previously returned false on any API error (including rate limiting), which made every PR appear broken. Now defaults to true (optimistic) on errors — better to briefly miss a real conflict than to mark the entire page as broken.

bigintersmindComment#173Fix: Move 1.337% randomness check client-side to prevent cached blank pages

I considered adding this fix to #129, but it doesn't feel like it's in the spirit of the project. Even if it's a "good" trojan horse, it's still a trojan horse.

bigintersmindComment#1741.337% randomness check in server component caches blank page for all visitors

Yes.

bigintersmindComment#173Fix: Move 1.337% randomness check client-side to prevent cached blank pages

Confirmed in local testing.

bigintersmindComment#158feat: add weekly workflow to close oldest open PR

I don't think we need any additional settings for this to work. It should work as written.

Reviewing the changes, the more notable part is the README addition:

Code is Law: Rules are for human guidance. If a GitHub workflow contradicts written rules, the workflow (code) takes precedence. Always inspect the codebase to understand the actual system behavior.

The real question is whether the community wants a "Code is Law" clause.

bigintersmindComment#143Add Chaos^N: Random theme routing for infinite variants

Love the Chaos^N concept!

I'm working on a Web 2.0 era theme and would happily integrate it as a variant if this lands first. My goal is to make it easy for anyone to contribute new themes, so I want to make sure the variant system scales well. A few suggestions with that in mind:

1. Use the standard Next.js middleware location

src/proxy.ts won't be auto-invoked by Next.js. The framework expects middleware.ts (or src/middleware.ts) at the project/src root, exporting a function named middleware. Renaming and re-exporting should be all that's needed:

// src/middleware.ts
export { proxy as middleware, config } from '@/lib/chaos-router';

2. Audit globals.css for theme-specific styles

Moving retro.css into geocities/layout.tsx is the right call. Worth also checking that globals.css (still imported at root) only contains truly shared resets and Tailwind imports. If there are IE6-specific base styles there (body font, link colors, table resets), they'd bleed into other variants. For example, my web2 theme needs Lucida Grande/Trebuchet MS as the base font vs Comic Sans, so shared globals need to be theme-neutral.

3. Scope feature flags per variant

The current FEATURE_FLAGS array is flat and IE6-specific (guestbook, treeGame, midiPlayer). Other themes will have entirely different toggleable components. A per-variant config would scale better:

export const VARIANT_CONFIG = {
	geocities: {
		flags: ['guestbook', 'treeGame', 'midiPlayer', 'clippy'],
	},
	teletext: {
		flags: ['guestbook', 'clippy'],
	},
	// future themes add their own flags here
} as const;

This way each variant only toggles components that actually exist in its layout, and new themes don't need to touch the shared flag list.

4. Document the CSS isolation contract

The teletext variant scopes styles under [data-variant="teletext"] which is a solid pattern. It'd help future theme contributors to document this as an explicit requirement – every variant must scope its styles to avoid bleed (whether via a [data-variant="x"] attribute selector, a class namespace like .web2-*, or a route-group layout wrapper). A short note in a README or code comment would help discoverability.

5. Consider passing the variant name down to pages

If the chosen variant name were available to pages (via a header set by middleware, a search param, or a layout prop), each page could look up its own flag config without hardcoding, and shared components like PRCard could adapt per-variant if needed.


None of these are blockers – the core architecture is sound and I'd be happy to build on it. Just flagging things that would make it smoother for Web 2.0 and anyone else who wants to add a theme down the road.

bigintersmindIssue opened#174

1.337% randomness check in server component caches blank page for all visitors

Bug

The Math.random() <= 0.01337 check in page.tsx (#62) runs server-side at build/render time. When it triggers and returns null, the child components (PRList, HallOfChaos) never render, so their fetch() calls with revalidate: 300 never execute. Without any revalidation hint, Next.js/Vercel treats the blank page as fully static and caches it indefinitely — until the next deployment.

Instead of 1.337% of visitors individually seeing a blank page, one unlucky render poisons the cache and takes the site down for everyone.

Expected behavior

The 1.337% chance should apply per-visitor, not per-cache-rebuild.

Fix

Move the random check from the server component into a client component so it runs in the browser on hydration. The server always renders real content (safe to cache).

bigintersmindComment#621.337% chance to see nothing

I did some digging; I think I understand what happened, and put together a fix:

  • #173

Since page.tsx is a server component, the random check runs at build/render time, not per-visitor. When it returns null, the child components (PRList, HallOfChaos) never render, which means their fetch() calls with revalidate: 300 never execute. Without any revalidation hint, Next.js/Vercel treats the page as fully static and caches the blank result until the next deployment. So instead of 1.337% of visitors seeing nothing, one unlucky render poisoned the cache and took the site down for everyone.

#172 moves the check into IE6Layout.tsx (a client component) using useState + useEffect, so it runs per-visitor in the browser. The server always renders real content now (safe to cache), and each visitor individually rolls the 1.337% dice on hydration. Bonus: the page briefly flashes before going blank, like a crash.

bigintersmindComment#164randomize visitor counter to make it useless/chaotic

I like it; this is a fun idea. 👍

To riff a bit: What if it only counted an individual user's visits? I'm in my 40s, so it would simulate my authentic Geocities experience of seeing the counter increment and later realizing it was because I was repeatedly visiting my own page. ("I hit a thousand! Wait, 998 of those were me, and two were my parents.")

bigintersmindComment#171Add a working Windows XP Start Menu

This is something I've been messing with for a while, and decided I may as well make a PR.

I still prefer the bigger pivot with #163, but if we stay the course, this is a small addition for flavor.

bigintersmindComment#154$100 Bounty: Win the Auto-Merge

To be fair, your idea and approach are funny. It certainly maximizes on chaos.

bigintersmindComment#154$100 Bounty: Win the Auto-Merge

I've submitted PR #168 as a fix for this. Here's a brief rundown of why I think it's the most complete solution currently on the table, and why I'd ask people to evaluate the competing PRs on technical merit.

What #168 fixes:

  • Net votes — The current workflow counts +1 reactions only. The website displays +1 - -1 (net votes), and that's what should determine ranking. #168 fixes this; #159 and #161 do not.
  • Tiebreaker — RULES.md says "Ties go to the more recent PR." #168 implements this; #159 and #161 do not.
  • CI verification — #168 checks both commit statuses and check runs before merging. #159 and #161 skip this entirely.
  • Mergeability retry — GitHub's API can return null for mergeable if it hasn't been computed yet. #168 retries once after a delay; #159 and #161 don't account for this and could incorrectly skip a valid PR.
  • Correct permissions — #168 adds checks: read and statuses: read to the workflow. #159 calls issues.createComment() without the required issues: write permission, which would fail at runtime.

On the bounty:

If #168 wins, I decline the $100. I don't think a cash prize should be a factor in which fix gets merged. It's created a situation where the conversation around #159 and #161 is dominated by arguments about money rather than whether the code is correct. I'd rather people just vote for whichever PR they think is the best fix.

bigintersmindComment#158feat: add weekly workflow to close oldest open PR

Great idea. Let's keep things fresh!

bigintersmindComment#163Web 2.0 Reskin: It's Time to Upgrade from IE6

I spent the last few days on this one. I had a lot of fun, and it brought back quite a few memories.

Open to feedback and ideas, and to making themes swappable.

bigintersmindComment#149allow owner's PRs into the Hall of Chaos

Good call. @skridlevsky can update the explicit list in any future PRs that skip a vote.

Windows XP error dialogs!

Summary

  • Adds random Windows XP-style error dialogs for authentic 2003 nostalgia
  • Includes classic errors: IE illegal operation, ActiveX warnings, MSN Messenger notifications, "You're a Winner!" popups, and more
  • ~20% chance to trigger every 45 seconds, plus 30% chance on initial page load

Screenshots

Screenshot 2026-01-27 at 10 33 49 PM Screenshot 2026-01-27 at 10 39 02 PM
bigintersmindComment#141IE6BrowserChrome.tsx: open skridlevsky/openchaos GitHub repo

This is identical to #104

bigintersmindComment#69Add hot score ranking with trending section

This is also incorporated into #132, along with other views.

bigintersmindComment#66Simplify main page with top 5 PRs and newest section

Closing in favor of #132 which includes multiple PR views (Top, Hot This Week, Controversial, Discussed, Newest) with frames-style navigation.

bigintersmindComment#129Deprioritize PRs with merge conflicts in ranking

I'd also make them gray

Great idea; added!

Screenshot 2026-01-22 at 10 30 23 PM

Add frames with multiple views: Hot This Week, Controversial, Discussed & more

Summary

Adds 5 different ways to explore PRs, each offering a unique perspective:

ViewWhat it shows
🏆 Top By VotesAll-time vote leaders - the community favorites
🔥 Hot This WeekOnly votes from the last 7 days - what's gaining momentum right now
🌶️ ControversialPRs with both upvotes AND downvotes - the divisive ones
💬 DiscussedMost commented PRs - where the conversation is happening
🆕 NewestRecently created PRs - fresh submissions

Why this matters:

  • Hot This Week uses reaction timestamps from GitHub API to count only recent votes - a PR with 10 votes today beats one with 50 stale votes
  • Controversial surfaces PRs that spark debate (both 👍 and 👎)
  • PRs can appear in multiple views (a new PR with lots of votes shows in Top, Hot, and Newest)

Navigation uses a classic IE6 frames layout for a retro aesthetic.

Screenshots

Screenshot 2026-01-22 at 12 20 31 AM Screenshot 2026-01-22 at 12 20 52 AM Screenshot 2026-01-22 at 12 20 59 AM Screenshot 2026-01-22 at 12 21 07 AM Screenshot 2026-01-22 at 12 21 19 AM

Deprioritize PRs with merge conflicts in ranking

Summary

PRs with merge conflicts can't win the daily merge, but they currently appear at the top of the list if they have the most votes. This creates confusion when a high-voted PR doesn't win.

This PR makes the displayed ranking match the actual winner selection methodology. By moving conflict PRs to the bottom, users can follow along and understand why certain PRs were accepted and why others weren't.

Changes:

  • PRs with merge conflicts are moved to the bottom of the ranking list
  • Within each group (mergeable / has conflicts), PRs still sort by votes, then by newest

Attribution

This PR incorporates the auth header fix from #119 by @skridlevsky. The merge conflict indicator was showing false positives because getPRMergeStatus() and getCommitStatus() were missing auth headers.

Screenshots

Screenshot 2026-01-21 at 10 09 14 PM Screenshot 2026-01-21 at 10 09 35 PM
💬
bigintersmindReview comment#60

Good catch. sort=updated returns recently active closed PRs, but doesn't guarantee merge order. Added explicit client-side sorting by merged_at to ensure true chronological merge order.

Add Clippy, the helpful assistant!

Screenshots

clippy_2 clippy_3 clippy_1

Summary

  • Adds the iconic Microsoft Office Clippy to the bottom-right corner
  • Displays randomized helpful tips about voting on PRs and the site
  • Features authentic Windows XP-style speech bubble and buttons
  • Includes gentle idle animation for extra nostalgia

Features

Randomized Tips - Includes classics like:

  • "It looks like you're trying to vote on a PR! Would you like help with that?"
  • "Would you like me to search AltaVista for 'how to vote on GitHub'?"
  • "You look like you could use a break. Want me to open Minesweeper?"

Authentically Annoying - Just like the real Clippy:

  • Can be dismissed with "OK" but comes back in 15 seconds
  • Has a "Don't show tips" button that is politely ignored after 30 seconds
  • Click Clippy anytime to bring back his wisdom

Retro Styling - Uses the classic Clippy image with:

  • Yellow speech bubble with pointer
  • Windows XP gray 3D-style buttons
  • Subtle bouncing idle animation
bigintersmindComment#66Simplify main page with top 5 PRs and newest section

Good point, @sevonj. I've added a "show all" option.

Screenshot 2026-01-20 at 9 02 40 PM
bigintersmindComment#69Add hot score ranking with trending section

Added a "show all" link so all PRs are easily viewed.

Screenshot 2026-01-20 at 9 06 53 PM
bigintersmindComment#60Add Hall of Chaos - Past Winners section

We're now IE6 ready!

Screenshot 2026-01-19 at 7 29 06 PM

edit: removed skridlevsky's PRs from the list, since they are maintenance fixes and not voted in.

bigintersmindComment#65Should have a throwback option

This is a good idea. #60 creates a lighter version of this by implementing a "Hall of Chaos" and noting previous winners. We can extend this by rendering the page with that version of the code when a card is clicked.

bigintersmindComment#6Calculate `+1` and `-1` reaction

Also, with every revision, does everyone who reacted need to react again with every change?

Perhaps we should use a database and implement voting via the frontend, rather than GitHub reactions.

Then we could tie votes to the commit SHA and other methods.

Add hot score ranking with trending section

Summary

  • Implements Reddit-style "hot" ranking that combines votes (logarithmic) with recency (linear)
  • Newer PRs can now compete with older PRs that have more votes
  • PRs displayed in two sections: Top 5 by Votes (merge candidates) and Trending (rising PRs by hot score)
  • Items in Top by Votes show a "TRENDING" badge if they're also in the top 5 by hot score

How it works

hot_score = log10(votes + 1) + (age_seconds / 45000)

The decay constant (45000 seconds ≈ 12.5 hours) means a PR needs ~10x more votes every 12.5 hours to maintain its position against newer PRs.

Screenshot

Screenshot 2026-01-20 at 9 06 53 PM

Simplify main page with top 5 PRs and newest section

Summary

  • Limit main PR list to top 5 by votes to reduce clutter as the number of open PRs grows
  • Add a "Newest" section showing the 5 most recent PRs not already in top voted, giving visibility to new submissions
  • Add consistent section headers ("Top by Votes" and "Newest") for clear visual hierarchy

Screenshot

Screenshot 2026-01-20 at 9 02 40 PM

Add Hall of Chaos - Past Winners section

Summary

  • Adds a Hall of Chaos section that displays previously merged PRs
  • Each winner is immortalized with their PR number, title, author, and merge date
  • Shows the evolution of the site through community votes

What's Added

  • getMergedPRs() function in /src/lib/github.ts - fetches closed+merged PRs from GitHub API
  • HallOfChaos.tsx - async server component that renders the list of past winners
  • HallOfChaosCard.tsx - individual card component with 🏆 trophy and green "MERGED" badge
  • New section on homepage below the open PRs voting section

Why

The site is about its own evolution through community voting. Showing that history:

  • Makes the site self-documenting
  • Motivates contributors (their work gets immortalized)
  • Lets visitors trace how the site got to its current chaotic state

Screenshot

Screenshot 2026-01-19 at 7 29 06 PM