Skip to content

fix: extinction countdown ticks down by 2 seconds instead of 1#107

Merged
nitrocode merged 3 commits into
mainfrom
copilot/fix-countdown-bug
Apr 27, 2026
Merged

fix: extinction countdown ticks down by 2 seconds instead of 1#107
nitrocode merged 3 commits into
mainfrom
copilot/fix-countdown-bug

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 27, 2026

The extinction countdown header decremented by ~2 seconds per tick instead of 1. The bug was a model inconsistency: updateExtinctionCountdown computed secsRemaining = tokensRemaining / currentRate (linear, constant-rate assumption), while getCurrentTokens integrates an exponentially-growing rate (~30%/yr). At ~3.7 years from extinction, this causes the countdown to tick at 1 + secsRemaining × k ≈ 2.17 s/s.

Fix: Replace the linear approximation with the closed-form inverse of the cumulative-token integral:

tExtinction = ln(1 + (target - BASE_TOKENS) × k / R₀) / k
secsRemaining = tExtinction − tNow

tExtinction is a constant; tNow advances 1 s/s → countdown decreases by exactly 1.000000 s/s.

Changes

  • Add computeExtinctionSecsRemaining(targetTokens, nowMs) pure function to death-clock-core.js using the integral inverse formula
  • Export computeExtinctionSecsRemaining from death-clock-core.js and import it in src/js/00-state.js
  • Replace tokensRemaining / currentRate in updateExtinctionCountdown (src/js/02-counter.js) with the new function
  • Add 6 unit tests to tests/death-clock.test.js, including the key 1-second-per-tick invariant that would fail against the old linear approximation
  • Add learning entry A5 and PR log entry to docs/LEARNINGS.md

Agent Checklist

  • npm run test:ci passes (all unit tests green, coverage not decreased)
  • npm run build && npm run test:e2e passes (all E2E tests green)
  • No generated files committed (script.js, styles.css, *-data.js)
  • All dynamic innerHTML values pass through escHtml()
  • No DOM references introduced in death-clock-core.js
  • No new runtime npm packages added
  • GitHub Actions uses: pins use a full commit SHA + inline semver comment
  • PR title follows Conventional Commits (feat:, fix:, docs:, chore:, etc.)
  • project-stats.yaml updated if this session merges one or more PRs
  • Relevant entry added to docs/LEARNINGS.md (new pattern or lesson learned)

Summary by CodeRabbit

  • New Features

    • Exposed a public helper to compute exact time-to-threshold for integrations.
  • Bug Fixes

    • Fixed extinction countdown accuracy to guarantee a 1-second-per-second tick (resolving prior drift).
  • Documentation

    • Updated learning guidelines with the precise countdown calculation specification.
  • Tests

    • Added tests validating timing invariants, boundary cases, and deterministic behavior.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

📝 Walkthrough

Walkthrough

Adds a pure helper computeExtinctionSecsRemaining(targetTokens, nowMs) to DeathClockCore that analytically inverts the exponential cumulative-token model to return seconds-to-threshold; updates client state/counter to use this helper and adds unit tests and docs noting the change.

Changes

Cohort / File(s) Summary
Core Analytics Function
death-clock-core.js
Adds exported DeathClockCore.computeExtinctionSecsRemaining(targetTokens, nowMs) — pure helper that analytically inverts the exponential-integral accumulation to compute seconds remaining; returns 0 for non-progress targets.
Docs / Learnings
docs/LEARNINGS.md
Adds rule A5 describing use of the exponential-integral inverse for extinction countdowns and updates the v1.7.x PR log entry to reference the countdown fix and new helper.
State Integration
src/js/00-state.js
Destructures and exposes computeExtinctionSecsRemaining from window.DeathClockCore for use in UI logic.
Counter Logic
src/js/02-counter.js
Replaces tokensRemaining/currentRate approximation with direct call to computeExtinctionSecsRemaining(...); threshold check now uses secsRemaining <= 0 and downstream time decomposition uses secsRemaining.
Tests
tests/death-clock.test.js
Adds tests for computeExtinctionSecsRemaining: per-second decrement invariant (1s per 1000ms), multi-minute behavior, edge cases at/below BASE_TOKENS, past-target negatives, and robustness when nowMs is non-numeric.

Sequence Diagram(s)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested reviewers

  • nitrocode

I pity the fool who skips the review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main fix: replacing a linear approximation that caused 2-second ticks with the correct exponential integral inverse formula that ensures 1-second-per-second countdown.
Description check ✅ Passed The description comprehensively covers the problem, solution, and all discrete changes made, with complete agent checklist verification (one item unchecked as intended for conditional sections).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch copilot/fix-countdown-bug

Comment @coderabbitai help to get the list of available commands and usage tips.

@nitrocode nitrocode marked this pull request as ready for review April 27, 2026 04:05
@nitrocode nitrocode self-requested a review as a code owner April 27, 2026 04:05
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 27, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (a794491) to head (a1f38cb).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##              main      #107   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            1         1           
  Lines          247       256    +9     
  Branches       110       112    +2     
=========================================
+ Hits           247       256    +9     
Flag Coverage Δ
unit 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
death-clock-core.js 100.00% <100.00%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a794491...a1f38cb. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

github-actions Bot added a commit that referenced this pull request Apr 27, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 27, 2026

👁️ PR Preview

🚀 Open Preview

Deployed from commit a1f38cb · Updates on every push to this PR
(Preview is removed automatically when the PR is closed.)

Screenshots

Desktop Mobile
Desktop Mobile

github-actions Bot added a commit that referenced this pull request Apr 27, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/LEARNINGS.md`:
- Line 105: Update the incorrect PR reference string: replace occurrences of
“#104” in the new learning row and the PR log heading in LEARNINGS.md with the
correct tracked PR number “#107” so the documentation matches the actual change
set; search for the literal “#104” near the A5 learning row (the line containing
the extinction formula tExtinction = ln(1+(target-BASE_TOKENS)*k/R0)/k) and
update those instances to “#107”.

In `@tests/death-clock.test.js`:
- Around line 907-912: The test name claims it supplies a non-numeric nowMs but
the call to computeExtinctionSecsRemaining(TARGET) omits nowMs, so the
non-numeric branch isn't exercised; update the test so it actually passes a
non-numeric nowMs (for example null or 'abc') to
computeExtinctionSecsRemaining(TARGET, nowMs) and assert the result is a finite
number, or alternatively change the test name to reflect that nowMs was omitted
— reference computeExtinctionSecsRemaining and the test block in
death-clock.test.js to locate the code to edit.
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 45e75a97-43da-4362-90a7-a1d598f93dbe

📥 Commits

Reviewing files that changed from the base of the PR and between a794491 and 3fa51b6.

📒 Files selected for processing (5)
  • death-clock-core.js
  • docs/LEARNINGS.md
  • src/js/00-state.js
  • src/js/02-counter.js
  • tests/death-clock.test.js

Comment thread docs/LEARNINGS.md Outdated
Comment thread tests/death-clock.test.js
@nitrocode
Copy link
Copy Markdown
Owner

@coderabbitai apply

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

@nitrocode, I hear ya, fool! I pity the code that ain't reviewed right! I'm gonna review these changes for ya — let's make sure this extinction countdown fix is tight, and no junk code slips through on MY watch! 💪


🧠 Learnings used
Learnt from: CR
Repo: nitrocode/token-deathclock PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-27T00:20:01.920Z
Learning: Applies to death-clock-core.js : Update `BASE_TOKENS`, `TOKENS_PER_SECOND`, and `BASE_DATE_ISO` together as a set with explanatory comments — never change them independently

Learnt from: CR
Repo: nitrocode/token-deathclock PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-27T00:20:01.920Z
Learning: Applies to tests/death-clock.test.js : Maintain unit test coverage at or above 80% for lines and functions, 70% for branches — do not let coverage decrease on any PR

Learnt from: CR
Repo: nitrocode/token-deathclock PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-27T00:20:01.920Z
Learning: Applies to death-clock-core.js : When changing `MILESTONES` array in `death-clock-core.js`, keep it sorted in ascending `tokens` order and include all required fields: `id`, `name`, `icon`, `tokens`, `shortDesc`, `description`, `consequence`, `followingEvent`, `color`, `darkColor`

Learnt from: CR
Repo: nitrocode/token-deathclock PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-27T00:20:01.920Z
Learning: Applies to tests/death-clock.test.js : Add unit tests in `tests/death-clock.test.js` for every new or modified pure function in `death-clock-core.js`

Learnt from: CR
Repo: nitrocode/token-deathclock PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-27T00:20:01.920Z
Learning: Applies to src/js/**/*.js : Use `getCurrentTokens()` from `src/js/00-state.js` which computes elapsed time from `BASE_DATE_ISO`, not from page-load time (which is reserved for session counter only)
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 2 file(s) based on 2 unresolved review comments.

Files modified:

  • docs/LEARNINGS.md
  • tests/death-clock.test.js

Commit: a1f38cb4a6236c45b77d2b254ddc64ee551160cd

The changes have been pushed to the copilot/fix-countdown-bug branch.

Time taken: 5m 31s

Fixed 2 file(s) based on 2 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
github-actions Bot added a commit that referenced this pull request Apr 27, 2026
github-actions Bot added a commit that referenced this pull request Apr 27, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/death-clock.test.js (1)

895-898: Tighten the test name to match the assertion, fool-proof style.

At Line 895, the title says “returns 0 or negative,” but Line 896-897 assert exactly 0 for both cases. Rename for precision.

Suggested rename
-  test('returns 0 or negative when target equals or is below BASE_TOKENS', () => {
+  test('returns 0 when target equals or is below BASE_TOKENS', () => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/death-clock.test.js` around lines 895 - 898, The test description is
inaccurate: it says "returns 0 or negative" but the assertions check for exactly
0; update the test title string in the test block that calls
computeExtinctionSecsRemaining(BASE_TOKENS, baseMs) and
computeExtinctionSecsRemaining(BASE_TOKENS - 1, baseMs) to accurately reflect
the expectation (e.g., "returns 0 when target equals or is below BASE_TOKENS")
so the test name matches the assertions and references BASE_TOKENS and
computeExtinctionSecsRemaining.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/death-clock.test.js`:
- Around line 895-898: The test description is inaccurate: it says "returns 0 or
negative" but the assertions check for exactly 0; update the test title string
in the test block that calls computeExtinctionSecsRemaining(BASE_TOKENS, baseMs)
and computeExtinctionSecsRemaining(BASE_TOKENS - 1, baseMs) to accurately
reflect the expectation (e.g., "returns 0 when target equals or is below
BASE_TOKENS") so the test name matches the assertions and references BASE_TOKENS
and computeExtinctionSecsRemaining.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fe955733-0c90-45d0-9d04-4273df46bdc0

📥 Commits

Reviewing files that changed from the base of the PR and between 3fa51b6 and a1f38cb.

📒 Files selected for processing (2)
  • docs/LEARNINGS.md
  • tests/death-clock.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/LEARNINGS.md

@nitrocode nitrocode merged commit d2d12fa into main Apr 27, 2026
10 checks passed
@nitrocode nitrocode deleted the copilot/fix-countdown-bug branch April 27, 2026 12:56
github-actions Bot added a commit that referenced this pull request Apr 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants