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
5 changes: 4 additions & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ jobs:
- name: Regenerate changelog-data.js from CHANGELOG.md
run: npm run build:changelog

- name: Regenerate project-stats-data.js from YAML
run: npm run build:project-stats

- name: Deploy to GitHub Pages (gh-pages branch)
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
with:
Expand All @@ -46,4 +49,4 @@ jobs:
# Preserve any existing PR preview directories across production deploys
keep_files: true
# Exclude non-site files from the deployment
exclude_assets: '.github,node_modules,tests,scripts,package-lock.json,package.json,milestones.yaml'
exclude_assets: '.github,node_modules,tests,scripts,package-lock.json,package.json,milestones.yaml,project-stats.yaml'
17 changes: 16 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ a Chart.js growth chart with projections, and a prompt/PR quality scoring sectio
├── script.js ← All DOM manipulation, Chart.js wiring, RAF loop
├── changelog-data.js ← AUTO-GENERATED from CHANGELOG.md — do not edit
├── milestones-data.js ← AUTO-GENERATED from milestones.yaml — do not edit
├── project-stats-data.js ← AUTO-GENERATED from project-stats.yaml — do not edit
├── project-stats.yaml ← Edit this to update footer PR count + token total
├── package.json ← version, Jest config & devDependencies (no runtime deps)
├── release-please-config.json ← release-please release automation config
├── .release-please-manifest.json ← release-please version manifest
Expand Down Expand Up @@ -108,6 +110,19 @@ 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.

### Updating project token consumption stats (footer)
The footer shows how many tokens this project has consumed building itself.
After each agent session that merges one or more PRs, **update `project-stats.yaml`**:

```yaml
pr_count: 47 # ← increment by the number of PRs merged this session
total_tokens: 7000000 # ← add the tokens consumed this session
```

Then run `npm run build:project-stats` to regenerate `project-stats-data.js`.
The deploy workflow runs this automatically on every push to `main`, so the
generated file will always reflect the latest YAML values.

### 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.
Expand Down Expand Up @@ -225,6 +240,6 @@ feat!: redesign anchor hash scheme (removes legacy ?tab= param)
- Do **not** use mutable tags (e.g. `@v6`) in `uses:` — always pin to a commit SHA with a full semver comment (e.g. `@abc1234... # v6.0.2`).
- Do **not** finish a session without running `npm run test:ci` and `npm run test:e2e` to confirm both suites pass.
- Do **not** let coverage decrease — a negative coverage delta on any PR fails the Codecov status check.
- Do **not** edit `changelog-data.js` or `milestones-data.js` directly — they are auto-generated; edit `CHANGELOG.md` / `milestones.yaml` and run the corresponding build script.
- Do **not** edit `changelog-data.js`, `milestones-data.js`, or `project-stats-data.js` directly — they are auto-generated; edit `CHANGELOG.md` / `milestones.yaml` / `project-stats.yaml` and run the corresponding build script.
- Do **not** bump the version in `package.json` manually — let release-please handle it via Conventional Commits.
- Do **not** use free-form commit or PR title messages — always follow the Conventional Commits format described above.
7 changes: 4 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1541,9 +1541,8 @@ <h2>Changelog</h2>
not official measurements. Sources: Google/DeepMind energy reports, Microsoft sustainability
disclosures, Epoch AI compute trends, AI Index 2024.
</p>
<p class="footer-disclaimer footer-meta-irony">
🔥 This site was built using AI coding agents across 27 pull requests,
consuming an estimated <strong>~4,000,000 tokens</strong> in the process —
<p class="footer-disclaimer footer-meta-irony" id="footerMetaIrony">
🔥 This site was built using AI coding agents — consuming tokens in the process —
adding to the very problem it tracks.
</p>
<div class="footer-share-row" aria-label="Share this page">
Expand Down Expand Up @@ -1688,6 +1687,8 @@ <h2 id="receipt-heading" class="sr-only">Session Receipt</h2>
<script src="changelog-data.js"></script>
<!-- Milestone data (auto-generated from milestones.yaml) -->
<script src="milestones-data.js"></script>
<!-- Project build stats (auto-generated from project-stats.yaml) -->
<script src="project-stats-data.js"></script>
<!-- Core logic (no DOM deps — loaded first so script.js can use it) -->
<script src="death-clock-core.js"></script>
<!-- Minimal Chart.js date adapter (required for time-scale x-axis) -->
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui",
"build:milestones": "node scripts/build-milestones.js",
"build:changelog": "node scripts/build-changelog.js"
"build:changelog": "node scripts/build-changelog.js",
"build:project-stats": "node scripts/build-project-stats.js"
},
"devDependencies": {
"@playwright/test": "^1.59.1",
Expand Down
13 changes: 13 additions & 0 deletions project-stats-data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';
// AUTO-GENERATED from project-stats.yaml — do not edit directly.
// Run `npm run build:project-stats` to regenerate from project-stats.yaml.

const PROJECT_PR_COUNT = 47;
const PROJECT_TOTAL_TOKENS = 7000000;

/* istanbul ignore next */
if (typeof module !== 'undefined' && module.exports) {
module.exports = { PROJECT_PR_COUNT, PROJECT_TOTAL_TOKENS };
} else if (typeof window !== 'undefined') {
window.ProjectStatsData = { PROJECT_PR_COUNT, PROJECT_TOTAL_TOKENS };
}
12 changes: 12 additions & 0 deletions project-stats.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Project statistics — updated by AI coding agents after each session.
#
# HOW TO UPDATE:
# After each agent session, update the values below:
# - pr_count: increment by the number of PRs merged in this session
# - total_tokens: add the number of tokens consumed in this session
#
# Run `npm run build:project-stats` (or let the deploy workflow do it) to
# regenerate project-stats-data.js from this file.

pr_count: 47
total_tokens: 7000000
21 changes: 20 additions & 1 deletion script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* global Chart, DeathClockCore, ChangelogData */
/* global Chart, DeathClockCore, ChangelogData, ProjectStatsData */
'use strict';

// ============================================================
Expand Down Expand Up @@ -49,6 +49,12 @@
CHANGELOG_RELEASES = [],
} = (typeof window !== 'undefined' && window.ChangelogData) || {};

// ---- Unpack project stats -----------------------------------
const {
PROJECT_PR_COUNT = 0,
PROJECT_TOTAL_TOKENS = 0,
} = (typeof window !== 'undefined' && window.ProjectStatsData) || {};

// ---- State -----------------------------------------------
const BASE_DATE_MS = new Date(BASE_DATE_ISO).getTime();
const pageLoadTime = Date.now();
Expand Down Expand Up @@ -1184,6 +1190,18 @@
list.innerHTML = html;
}

// ---- Render footer meta-irony stats -------------------------
function renderFooterStats() {
const el = document.getElementById('footerMetaIrony');
if (!el || PROJECT_PR_COUNT == null || PROJECT_TOTAL_TOKENS == null) return;
const formattedTokens = '~' + PROJECT_TOTAL_TOKENS.toLocaleString('en-US');
el.innerHTML =
'🔥 This site was built using AI coding agents across ' +
escHtml(String(PROJECT_PR_COUNT)) + ' pull requests, consuming an estimated ' +
'<strong>' + escHtml(formattedTokens) + ' tokens</strong> in the process \u2014 ' +
'adding to the very problem it tracks.';
}

// ============================================================
// FUN FEATURES
// ============================================================
Expand Down Expand Up @@ -3453,6 +3471,7 @@
renderPredictionsTable();
renderTips();
renderChangelog();
renderFooterStats();

// Chart init is isolated so a missing date-adapter or other chart error
// cannot prevent the counters and life-blocks from running.
Expand Down
63 changes: 63 additions & 0 deletions scripts/build-project-stats.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env node
'use strict';

/**
* Build script: project-stats.yaml → project-stats-data.js
*
* Usage: node scripts/build-project-stats.js
* (also callable via `npm run build:project-stats`)
*
* Reads project-stats.yaml from the repo root, validates the data, and writes
* project-stats-data.js — a dual-export module consumed by both Node.js (tests)
* and the browser (loaded via <script> before script.js).
*/

const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');

const ROOT = path.join(__dirname, '..');
const SRC = path.join(ROOT, 'project-stats.yaml');
const DEST = path.join(ROOT, 'project-stats-data.js');

// ── Load & parse ─────────────────────────────────────────────────────────────
const raw = fs.readFileSync(SRC, 'utf8');
const doc = yaml.load(raw);

if (!doc || typeof doc !== 'object') {
console.error('ERROR: project-stats.yaml must be a valid YAML mapping.');
process.exit(1);
}

// ── Validate ──────────────────────────────────────────────────────────────────
const prCount = doc.pr_count;
const totalTokens = doc.total_tokens;

if (typeof prCount !== 'number' || !Number.isInteger(prCount) || prCount < 0) {
console.error(`ERROR: project-stats.yaml — pr_count must be a non-negative integer, got: ${prCount}`);
process.exit(1);
}

if (typeof totalTokens !== 'number' || !Number.isInteger(totalTokens) || totalTokens < 0) {
console.error(`ERROR: project-stats.yaml — total_tokens must be a non-negative integer, got: ${totalTokens}`);
process.exit(1);
}

// ── Generate JS ───────────────────────────────────────────────────────────────
const output = `'use strict';
// AUTO-GENERATED from project-stats.yaml — do not edit directly.
// Run \`npm run build:project-stats\` to regenerate from project-stats.yaml.

const PROJECT_PR_COUNT = ${prCount};
const PROJECT_TOTAL_TOKENS = ${totalTokens};

/* istanbul ignore next */
if (typeof module !== 'undefined' && module.exports) {
module.exports = { PROJECT_PR_COUNT, PROJECT_TOTAL_TOKENS };
} else if (typeof window !== 'undefined') {
window.ProjectStatsData = { PROJECT_PR_COUNT, PROJECT_TOTAL_TOKENS };
}
`;

fs.writeFileSync(DEST, output, 'utf8');
console.log(`✅ Written project stats to ${path.relative(ROOT, DEST)} (pr_count=${prCount}, total_tokens=${totalTokens})`);
Loading