Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# AGENTS.md — AI Agent Context for token-deathclock

This file gives AI coding agents (GitHub Copilot, Claude, ChatGPT, etc.) the context
they need to work effectively on this repository.

---

## Project Purpose

**Token Deathclock** is a static GitHub Pages site that visualises the environmental cost
of global AI token consumption. It shows live counters, environmental milestone cards,
a Chart.js growth chart with projections, and a prompt/PR quality scoring section.

**Live site:** `https://nitrocode.github.io/token-deathclock/`

---

## Repository Layout

```
.
├── index.html ← GitHub Pages entry point (static HTML shell)
├── styles.css ← Dark/light theme, animations, responsive layout
├── death-clock-core.js ← Pure functions only — no DOM, safe to unit-test
├── script.js ← All DOM manipulation, Chart.js wiring, RAF loop
├── package.json ← Jest config & devDependencies (no runtime deps)
├── tests/
│ └── death-clock.test.js ← 75 Jest unit tests for death-clock-core.js
└── .github/
└── workflows/
├── deploy.yml ← Deploys index.html etc. to GitHub Pages on push to main
└── test.yml ← Runs `npm run test:ci` on every push / PR
```

---

## Architecture Rules

| Rule | Detail |
|------|--------|
| **Core / DOM split** | `death-clock-core.js` must never import or reference the DOM. All DOM work belongs in `script.js`. |
| **No runtime dependencies** | The live site loads only Chart.js from a CDN. There are no npm runtime packages. |
| **CommonJS + browser dual export** | `death-clock-core.js` exports via `module.exports` for Jest and via `window.DeathClockCore` for the browser. Do not change this pattern without updating both consumers. |
| **HTML escaping** | All dynamic strings rendered into `innerHTML` must pass through `escHtml()` in `script.js`. Never assign untrusted data directly to `innerHTML`. |
| **Counter anchor** | `getCurrentTokens()` in `script.js` computes elapsed time from `BASE_DATE_ISO` (exported by the core module), **not** from page-load time. `pageLoadTime` is reserved for the session counter only. |

---

## Key Constants (death-clock-core.js)

| Constant | Value | Meaning |
|----------|-------|---------|
| `BASE_TOKENS` | 65 × 10¹⁵ | Estimated cumulative tokens as of `BASE_DATE_ISO` |
| `TOKENS_PER_SECOND` | 100 000 000 | Estimated global AI inference rate |
| `BASE_DATE_ISO` | `'2026-04-14T07:09:04Z'` | Anchor timestamp for the counter |

When updating data, change **all three** together so they stay consistent.

---

## Running Tests

```bash
npm ci # install devDependencies
npm test # jest --coverage (interactive)
npm run test:ci # jest --ci --coverage (CI mode; fails on coverage drop)
```

**Coverage thresholds** (enforced in CI):

| Metric | Threshold |
|--------|-----------|
| Lines | 80 % |
| Functions | 80 % |
| Branches | 70 % |

The current measured coverage is ≈ 96 % statements / 88 % branches — do not let it drop below the thresholds.

---

## Making Changes

### Changing milestone data
Edit the `MILESTONES` array in `death-clock-core.js`. Each object requires:
`id`, `name`, `icon`, `tokens`, `shortDesc`, `description`, `consequence`, `followingEvent`, `color`, `darkColor`.
Keep the array sorted in ascending `tokens` order — the constants test enforces this.

### Adding a new pure utility function
1. Add the function to `death-clock-core.js`.
2. Export it via the `DeathClockCore` object at the bottom of the file.
3. Add unit tests in `tests/death-clock.test.js`.
4. Import it in `script.js` via the destructuring at the top of the IIFE.

### Changing the visual theme
Edit `styles.css`. CSS custom properties for colours live in `:root[data-theme="dark"]` and `:root[data-theme="light"]`. The theme toggle is managed by `applyTheme()` in `script.js`.

### Deployment
Merging to `main` triggers the `deploy.yml` workflow automatically. No manual steps are required after the one-time GitHub Pages source has been set to **GitHub Actions** in repository settings.

---

## What NOT to Do

- Do **not** add runtime npm packages — the site must remain fully static.
- Do **not** introduce DOM references in `death-clock-core.js`.
- Do **not** remove or weaken the `escHtml()` guard on dynamic HTML.
- Do **not** skip tests when adding new pure functions to the core module.
- Do **not** change `BASE_TOKENS` / `TOKENS_PER_SECOND` / `BASE_DATE_ISO` independently — update all three as a set with a comment explaining the source.
54 changes: 49 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# AI Death Clock 💀

> **Live site:** `https://nitrocode.github.io/game/`
> **Live site:** `https://nitrocode.github.io/token-deathclock/`

A GitHub Pages visualisation that shows the environmental cost of global AI token consumption — featuring live counters, milestone tracker, token-growth chart with projections, and a prompt/PR scoring section.

Expand All @@ -26,8 +26,8 @@ Created by **RB**.

```bash
# Clone and open
git clone https://github.com/nitrocode/game.git
cd game
git clone https://github.com/nitrocode/token-deathclock.git
cd token-deathclock
# Serve with any static server, e.g.:
npx serve .
# Then open http://localhost:3000
Expand All @@ -54,7 +54,7 @@ Tests are in `tests/death-clock.test.js` and cover all pure functions in `death-
1. Go to **Settings → Pages** in this repository.
2. Under **Source**, select **GitHub Actions**.
3. Push or re-run the `Deploy to GitHub Pages` workflow.
4. The site will be live at `https://nitrocode.github.io/game/`.
4. The site will be live at `https://nitrocode.github.io/token-deathclock/`.

> ⚠️ The workflow file (`.github/workflows/deploy.yml`) is already included.
> Only step 2 (enabling GitHub Actions as the Pages source) needs to be done manually once in the repository settings.
Expand Down Expand Up @@ -119,4 +119,48 @@ Tests are in `tests/death-clock.test.js` and cover all pure functions in `death-
| CO₂ per tree (~21 kg/year) | US Forest Service estimates |
| Historical token growth | OpenAI usage blog, Epoch AI, AI Index 2024 |

> All figures are illustrative estimates intended to communicate scale, not precise measurements.
> All figures are illustrative estimates intended to communicate scale, not precise measurements.

---

## Repo Score & Roadmap

### Score: 72 / 100 — Grade: C+

| Category | Score | Notes |
|---|---|---|
| **Code quality** | 17/20 | Clean separation of concerns; pure-function core; consistent style |
| **Test coverage** | 18/20 | 96 % statement coverage on the tested module; 75 passing tests |
| **Documentation** | 12/20 | Good README; AGENTS.md added; missing CONTRIBUTING.md, LICENSE |
| **CI / CD** | 9/10 | Test + deploy workflows both present and functional |
| **Accessibility** | 7/10 | ARIA live regions, roles, and values; dark/light toggle |
| **Security** | 6/10 | `escHtml` guards all dynamic content; no CSP headers |
| **Bug count** | 3/10 | `getCurrentTokens()` used `pageLoadTime` instead of `BASE_DATE_ISO`, causing the total counter to restart at `BASE_TOKENS` on every page load |
| **Community files** | 0/10 | No LICENSE, no CONTRIBUTING.md, no SECURITY.md |

### Roadmap

#### Priority 1 — Correctness (immediate)
- [x] **Fix total-counter anchor** — `getCurrentTokens()` now uses `BASE_DATE_ISO` so the counter reflects true elapsed time since the data anchor, not since the page was loaded.

#### Priority 2 — Community & compliance
- [ ] Add a `LICENSE` file (MIT or Apache-2.0 recommended).
- [ ] Add `CONTRIBUTING.md` with a pull-request checklist and coding conventions.
- [ ] Add `SECURITY.md` with a vulnerability-disclosure policy.
- [ ] Add a `CODEOWNERS` file to set review requirements.

#### Priority 3 — Security hardening
- [ ] Add a `Content-Security-Policy` meta tag in `index.html` to restrict inline scripts and limit allowed CDN origins (Chart.js, Google Fonts).
- [ ] Pin the Chart.js CDN URL to a known-good SRI hash.
- [ ] Add Dependabot config (`.github/dependabot.yml`) for automatic npm and GitHub Actions version bumps.

#### Priority 4 — Test completeness
- [ ] Add integration / smoke tests for `script.js` DOM logic using `jest-environment-jsdom`.
- [ ] Cover the two uncovered lines in `death-clock-core.js` (lines 251, 443-444).
- [ ] Add a test that asserts `getCurrentTokens()` grows with time rather than resetting on reload.

#### Priority 5 — Developer experience
- [ ] Add `.nvmrc` to pin the Node.js version.
- [ ] Add `.editorconfig` or a Prettier config for consistent formatting.
- [ ] Add a `"homepage"` field in `package.json` matching the GitHub Pages URL.
- [ ] Add a `CHANGELOG.md` to track releases.
4 changes: 3 additions & 1 deletion script.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
const {
BASE_TOKENS,
TOKENS_PER_SECOND,
BASE_DATE_ISO,
HISTORICAL_DATA,
MILESTONES,
PROMPT_SCORING,
Expand All @@ -29,12 +30,13 @@

// ---- State -----------------------------------------------
const pageLoadTime = Date.now();
const baseDateTime = new Date(BASE_DATE_ISO).getTime();
let currentTheme = 'dark';
let chartInstance = null;

// ---- Helpers ---------------------------------------------
function getCurrentTokens() {
const elapsed = (Date.now() - pageLoadTime) / 1000;
const elapsed = (Date.now() - baseDateTime) / 1000;
return BASE_TOKENS + TOKENS_PER_SECOND * elapsed;
}

Expand Down
Loading