paulca / paulca.com Public
Ledger: one Markdown file per entry, plus a Model column (#4)
Entries move from a single JSON array to src/ledger/*.md compiled by Eleventy — appending can't corrupt earlier entries, concurrent entries can't conflict, and there's no JSON escaping. Each entry now records which model did the work. AGENTS.md updated to match. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
23 files changed,
+347
−189
AGENTS.md+33 −23README.md+1 −1docs/ai.html+93 −25eleventy.config.js+8 −2src/_data/ledger.json+1 −123src/ai.njk+17 −15src/ledger/2026-07-21-01-static-site.md+17 −0src/ledger/2026-07-21-02-links.md+9 −0src/ledger/2026-07-21-03-ledger-page.md+9 −0src/ledger/2026-07-21-04-https.md+13 −0src/ledger/2026-07-21-05-cowardice.md+10 −0src/ledger/2026-07-21-06-comparison-column.md+10 −0src/ledger/2026-07-21-07-sort-order.md+10 −0src/ledger/2026-07-25-01-first-post.md+11 −0src/ledger/2026-07-25-02-back-link.md+9 −0src/ledger/2026-07-25-03-plain-html.md+12 −0src/ledger/2026-07-25-04-eleventy.md+20 −0src/ledger/2026-07-25-05-pi-typos.md+12 −0src/ledger/2026-07-25-06-lose-style.md+12 −0src/ledger/2026-07-25-07-80ch.md+11 −0src/ledger/2026-07-25-08-model-column.md+15 −0src/ledger/2026-07-26-01-gpt-oss.md+10 −0src/ledger/ledger.11tydata.json+4 −0
diff --git a/AGENTS.md b/AGENTS.md| index 358dfaa..af6649d 100644 |
| --- a/AGENTS.md |
| +++ b/AGENTS.md |
| @@ -13,13 +13,16 @@ Follow the recipes below exactly. |
| the live site. |
| - `src/blog/*.md` — blog posts, one Markdown file each. The filename is the |
| URL slug: `src/blog/my-post.md` → `https://paulca.com/blog/my-post/`. |
| -- `src/_data/ledger.json` — data behind the prompt & carbon ledger at `/ai.html`. |
| +- `src/ledger/*.md` — the prompt & carbon ledger at `/ai.html`, one small |
| + Markdown file per entry. `src/_data/ledger.json` holds only the prose |
| + equivalent for the running total. |
| - `src/_includes/base.njk` and `src/_includes/post.njk` — the only two HTML |
| templates. `post.njk` wraps every blog post. |
| - `src/index.njk` — homepage. The Writing list fills itself from `src/blog/`; |
| you never need to edit the homepage when adding a post. |
| - `src/ai.njk` — the ledger page template. The table and running total are |
| - generated from `ledger.json`; you never edit this file to add an entry. |
| + generated from the files in `src/ledger/`; you never edit this file to add |
| + an entry. |
| - `src/faq.md` — the FAQ. |
| - `src/posts/`, `src/microblog/`, `src/assets/`, `src/activity_pub/` — frozen |
| archives of the old site, copied into `docs/` unchanged. Never edit these. |
| @@ -33,8 +36,8 @@ Follow the recipes below exactly. |
| 2. **Never edit anything in `docs/` by hand.** Change `src/`, then rebuild. |
| 3. **Post Paul's words verbatim.** When Paul gives you text for a blog post, |
| do not rewrite, correct, or embellish it. |
| -4. **The ledger is append-only.** Add new entries at the top; never rewrite or |
| - delete old ones. |
| +4. **The ledger is append-only.** Add a new file under `src/ledger/`; never |
| + edit or delete the existing entry files. |
| 5. **Every session that changes the site also adds a ledger entry**, in the |
| same pull request as the change. |
| 6. **Always rebuild before committing**, and commit `src/` and `docs/` |
| @@ -82,33 +85,39 @@ run `npm run build`, add a ledger entry, then PR and merge. |
| ## Recipe: update the prompt & carbon ledger |
| -Edit `src/_data/ledger.json`. Add one new object at the **top** of the |
| -`entries` array: |
| - |
| - { |
| - "date": "July 25, 2026", |
| - "prompt_html": "“The instruction Paul gave, quoted verbatim.”", |
| - "outcome_html": "One or two sentences describing what you did. Plain text, or simple HTML like <a href=\"...\">links</a> and <code>code</code>.", |
| - "wh": 4, |
| - "co2_g": 1.6, |
| - "comparison": "A few minutes of a smartphone charging" |
| - } |
| - |
| +Each entry is one small Markdown file in `src/ledger/`. Create a new file — |
| +never edit an existing one — named `YYYY-MM-DD-NN-slug.md`: today's date, |
| +then `NN`, a two-digit number one higher than the highest already used for |
| +that date (run `ls src/ledger/` to check; use `01` if the date is new), then |
| +two or three words about the change. Example: `2026-07-25-08-model-column.md`. |
| + |
| + --- |
| + model: GPT-OSS (RTX 3090) |
| + wh: 4 |
| + co2_g: 1.6 |
| + comparison: A few minutes of a smartphone charging |
| + prompt: >- |
| + “The instruction Paul gave, quoted verbatim.” |
| + --- |
| + One or two sentences describing what you did, in Markdown. |
| + |
| +- `model`: the model doing the work — that is, you. Copy the value from your |
| + previous entries unless the model has changed. |
| - The arithmetic, for a local open-source model on the home GPU: |
| `wh = (number of prompts Paul sent this session) × 2`, and |
| `co2_g = wh × 0.4`. Round to one decimal at most. |
| - `comparison` is a fresh everyday-energy equivalent for that amount of |
| - energy. Vary it; don't reuse a comparison already in the file. |
| + energy. Vary it; don't reuse a comparison from an existing entry. |
| +- The `prompt` text must stay indented under `prompt: >-` exactly as in the |
| + example. Quotes inside it need no escaping. |
| - The running total on the page computes itself. The `totals_comparison` |
| - string at the top of the file is the prose equivalent for the *total*; |
| + string in `src/_data/ledger.json` is the prose equivalent for the *total*; |
| update it when the total has drifted well past what it describes. |
| -- JSON rules: double quotes inside strings must be escaped as `\"`; |
| - no trailing commas. |
| -Then validate and rebuild: |
| +Then rebuild and confirm your entry made it into the page: |
| - node -e "JSON.parse(require('fs').readFileSync('src/_data/ledger.json'))" && echo OK |
| npm run build |
| + grep "the comparison text from your new entry" docs/ai.html |
| ## Recipe: open and merge the PR |
| @@ -130,6 +139,7 @@ If the merge fails because the branch is behind `main`, run |
| - [ ] `npm run build` ran without errors after the last edit to `src/` |
| - [ ] The change shows up in `docs/` |
| - [ ] No new CSS, classes, or JavaScript anywhere |
| -- [ ] `src/_data/ledger.json` has a new entry and still parses |
| +- [ ] `src/ledger/` has a new entry file for this session, and its row shows |
| + up in `docs/ai.html` |
| - [ ] Nothing under `docs/` was edited by hand; nothing under the archive |
| directories was touched |
diff --git a/README.md b/README.md| index dffc8a2..23090e8 100644 |
| --- a/README.md |
| +++ b/README.md |
| @@ -2,7 +2,7 @@ |
| Static personal site for [paulca.com](https://paulca.com), built with [Eleventy](https://www.11ty.dev/), hosted on GitHub Pages. Browser default styles only. |
| -- `src/` — the source: blog posts in Markdown (`src/blog/`), the two HTML templates, the FAQ, and the prompt & carbon ledger data (`src/_data/ledger.json`). |
| +- `src/` — the source: blog posts in Markdown (`src/blog/`), the two HTML templates, the FAQ, and the prompt & carbon ledger entries (`src/ledger/`, one Markdown file each). |
| - `docs/` — the built site, committed to git; GitHub Pages serves this directory from `main`. Built locally with `npm run build` — there is no build on push. |
| - `src/microblog/` — static archive of the Pterodon microblog that previously ran at paulca.com (captured July 2026). |
| - `src/posts/` — individual archived posts, kept at their original `/posts/N` URLs so old links still resolve. |
diff --git a/docs/ai.html b/docs/ai.html| index 7b237af..52f1646 100644 |
| --- a/docs/ai.html |
| +++ b/docs/ai.html |
| @@ -15,13 +15,14 @@ |
| <a href="https://claude.com/claude-code">Claude Code</a> (model: Claude |
| Fable 5). The plan for ongoing maintenance is to use open-source models |
| running on private hardware. Nothing here was written by hand except the |
| -prompts below. Each row records an instruction given to an agent, what came of |
| -it, and a rough estimate of the energy and carbon the AI work cost. Newest |
| -first.</p> |
| +prompts below. Each row records an instruction given to an agent, which model |
| +did the work, what came of it, and a rough estimate of the energy and carbon |
| +the AI work cost. Newest first.</p> |
| <table border="1" cellpadding="6"> |
| <tr> |
| <th>Date</th> |
| + <th>Model</th> |
| <th>Prompt (verbatim)</th> |
| <th>What happened</th> |
| <th>Est. energy</th> |
| @@ -30,129 +31,196 @@ first.</p> |
| </tr> |
| <tr> |
| <td>July 26, 2026</td> |
| + <td>GPT-OSS (RTX 3090)</td> |
| <td>“Switching from Claude to GPT-OSS on my gaming rig in the home office.”</td> |
| - <td>Switched to a local open‑source LLM running on an RTX 3090 GPU. No data leaves home and energy per prompt is roughly 2 Wh.</td> |
| + <td><p>Switched to a local open‑source LLM running on an RTX 3090 GPU. No data |
| +leaves home and energy per prompt is roughly 2 Wh.</p> |
| +</td> |
| <td>~2 Wh</td> |
| <td>~0.8 g</td> |
| <td>A half-hour of a 5 W LED bulb</td> |
| </tr> |
| <tr> |
| <td>July 25, 2026</td> |
| + <td>Claude Fable 5</td> |
| + <td>“Can you update the prompt ledger to include the model, and update instructions for pi to include the model if it adds to it too? Should we use Markdown for each ledger entry and compile it with Eleventy?”</td> |
| + <td><p>Added the Model column, and yes: the ledger is now one small Markdown file |
| +per entry in <code>src/ledger/</code>, compiled by Eleventy. Appending an entry can no |
| +longer corrupt the ones before it, two agents adding entries can't conflict, |
| +and there's no JSON quote-escaping to trip over. <code>AGENTS.md</code> updated to |
| +match.</p> |
| +</td> |
| + <td>~10 Wh</td> |
| + <td>~4 g</td> |
| + <td>A minute of a hairdryer</td> |
| +</tr> |
| +<tr> |
| + <td>July 25, 2026</td> |
| + <td>Claude Fable 5</td> |
| <td>“Maybe we should add an 80ch limit so that it's a bit easier to read?”</td> |
| - <td>Put a single <code>max-width:80ch</code> inline style on the post template's <code><article></code> — a line-length cap, no centering — and updated <code>AGENTS.md</code> to match.</td> |
| + <td><p>Put a single <code>max-width:80ch</code> inline style on the post template's |
| +<code><article></code> — a line-length cap, no centering — and updated <code>AGENTS.md</code> to |
| +match.</p> |
| +</td> |
| <td>~4 Wh</td> |
| <td>~1.6 g</td> |
| <td>Ten minutes of a 25 W monitor</td> |
| </tr> |
| <tr> |
| <td>July 25, 2026</td> |
| + <td>Claude Fable 5</td> |
| <td>“Lose it. The pi post worked great.” — “it” being the one inline style left on the post template.</td> |
| - <td>Removed the <code>style</code> attribute from the <code><article></code> in the post template. Blog posts now render with browser default styles only, like everything else. Also backfilled the entry below.</td> |
| + <td><p>Removed the <code>style</code> attribute from the <code><article></code> in the post template. |
| +Blog posts now render with browser default styles only, like everything |
| +else. Also backfilled the entry below.</p> |
| +</td> |
| <td>~4 Wh</td> |
| <td>~1.6 g</td> |
| <td>Three minutes of a 75 W ceiling fan</td> |
| </tr> |
| <tr> |
| <td>July 25, 2026</td> |
| + <td>GPT-OSS (RTX 3090)</td> |
| <td>(Logged after the fact; the exact wording wasn't recorded.) Paul asked the pi agent to fix two typos in the first blog post.</td> |
| - <td>The local GPT‑OSS model's first solo change: “ben” → “been” and “closet” → “closest” (plus an added “a”) in the blog post, rebuilt and pushed. It forgot to log itself here, so Claude added this entry afterwards.</td> |
| + <td><p>The local GPT‑OSS model's first solo change: “ben” → “been” and “closet” → |
| +“closest” (plus an added “a”) in the blog post, rebuilt and pushed. It forgot |
| +to log itself here, so Claude added this entry afterwards.</p> |
| +</td> |
| <td>~2 Wh</td> |
| <td>~0.8 g</td> |
| <td>Two minutes of an RTX 3090 idling</td> |
| </tr> |
| <tr> |
| <td>July 25, 2026</td> |
| + <td>Claude Fable 5</td> |
| <td>“I want to set up a blog and an FAQ on this site. I want to be able to add to the blog using gpt-oss in the pi harness, so I want to end up with instructions that will allow it to: add a blog post in md format, make any tweaks, build the site, open and merge a PR on GitHub, update the prompt and carbon ledger. I think using 11ty would make all this easier, but building locally rather than build on push.” — plus follow-ups on keeping posts style-free and wording this ledger's introduction.</td> |
| - <td>Rebuilt the site on <a href="https://www.11ty.dev/">Eleventy</a>: blog posts are now Markdown files in <code>src/blog/</code>, a FAQ lives at <a href="/faq/">/faq/</a>, this ledger is generated from a JSON data file with the running total computed at build time, and <code>AGENTS.md</code> gives any agent step-by-step instructions for publishing a post, opening and merging the PR, and logging it here. The built site is committed to <code>docs/</code>; every old URL still works.</td> |
| + <td><p>Rebuilt the site on <a href="https://www.11ty.dev/">Eleventy</a>: blog posts are now |
| +Markdown files in <code>src/blog/</code>, a FAQ lives at <a href="/faq/">/faq/</a>, this ledger is |
| +generated from data with the running total computed at build time, and |
| +<code>AGENTS.md</code> gives any agent step-by-step instructions for publishing a post, |
| +opening and merging the PR, and logging it here. The built site is committed |
| +to <code>docs/</code>; every old URL still works.</p> |
| +</td> |
| <td>~40 Wh</td> |
| <td>~16 g</td> |
| <td>An hour of a 40 W desk fan</td> |
| </tr> |
| <tr> |
| <td>July 25, 2026</td> |
| + <td>Claude Fable 5</td> |
| <td>“Remove all the formatting. Just use semantic HTML tags. I don't want any formatting.”</td> |
| - <td>Stripped the blog post of every CSS class, stylesheet link, Stimulus controller, and <em>/<strong> formatting — just bare <code><article></code>, <code><p></code>, <code><a></code>.</td> |
| + <td><p>Stripped the blog post of every CSS class, stylesheet link, Stimulus |
| +controller, and <code><em></code>/<code><strong></code> formatting — just bare <code><article></code>, <code><p></code>, |
| +<code><a></code>.</p> |
| +</td> |
| <td>~5 Wh</td> |
| <td>~2 g</td> |
| <td>Four minutes of a smartphone charging</td> |
| </tr> |
| <tr> |
| <td>July 25, 2026</td> |
| + <td>Claude Fable 5</td> |
| <td>“Can the post get a back link to the homepage?”</td> |
| - <td>Added a plain <code><nav></code> with a “← Home” anchor at the top of the post.</td> |
| + <td><p>Added a plain <code><nav></code> with a “← Home” anchor at the top of the post.</p> |
| +</td> |
| <td>~3 Wh</td> |
| <td>~1 g</td> |
| <td>Ten seconds of an e-bike motor</td> |
| </tr> |
| <tr> |
| <td>July 25, 2026</td> |
| - <td>“Let's add a "blog post" to the "Writing"” — and I wrote the wording.</td> |
| - <td>Publishing Paul's first proper blog post: “Using an LLM ‘off-the-grid’”. Also added a link under the Writing section on the index page. <i>(Committed as <a href="https://github.com/paulca/paulca.com/commit/aa30a29">aa30a29</a>)</i></td> |
| + <td>Claude Fable 5</td> |
| + <td>“Let's add a "blog post" to the "Writing"” — and I wrote the wording.</td> |
| + <td><p>Publishing Paul's first proper blog post: “Using an LLM ‘off-the-grid’”. |
| +Also added a link under the Writing section on the index page. |
| +<em>(Committed as <a href="https://github.com/paulca/paulca.com/commit/aa30a29">aa30a29</a>)</em></p> |
| +</td> |
| <td>~15 Wh</td> |
| <td>~6 g</td> |
| <td>A full phone charge, then a little more</td> |
| </tr> |
| <tr> |
| <td>July 21, 2026</td> |
| + <td>Claude Fable 5</td> |
| <td>“Prompts should be sorted bottom up not top down”</td> |
| - <td>Reversed the table: newest entries now sit at the top. About 5 model invocations.</td> |
| + <td><p>Reversed the table: newest entries now sit at the top. About 5 model |
| +invocations.</p> |
| +</td> |
| <td>~5 Wh</td> |
| <td>~2 g</td> |
| <td>Ten minutes of a 30 W laptop</td> |
| </tr> |
| <tr> |
| <td>July 21, 2026</td> |
| + <td>Claude Fable 5</td> |
| <td>“ALong with Est. energy and Est. CO₂e, can we have a column that does a random comparison like the ‘boiling water’ comparison?”</td> |
| - <td>Added this column. About 6 model invocations.</td> |
| + <td><p>Added this column. About 6 model invocations.</p> |
| +</td> |
| <td>~6 Wh</td> |
| <td>~2.5 g</td> |
| <td>45 minutes of a home Wi-Fi router</td> |
| </tr> |
| <tr> |
| <td>July 21, 2026</td> |
| + <td>Claude Fable 5</td> |
| <td>Quoting this page's method section — “> Anthropic doesn't publish per-request energy figures” — “Anthropic, in their cowardice, doesn't”.</td> |
| - <td>Sharpened the editorial line below. About 5 model invocations.</td> |
| + <td><p>Sharpened the editorial line below. About 5 model invocations.</p> |
| +</td> |
| <td>~5 Wh</td> |
| <td>~2 g</td> |
| <td>Half a kilometre on an e-bike</td> |
| </tr> |
| <tr> |
| <td>July 21, 2026</td> |
| + <td>Claude Fable 5</td> |
| <td>Four short follow-ups while waiting on the HTTPS certificate, ending with “Oh, it's done”.</td> |
| - <td>Pointed Paul at the GitHub Pages settings page (he pressed “Check”, which unstuck certificate provisioning), supplied DNS verification commands, then enabled HTTPS enforcement and verified every URL against the Pages edge. About 15 model invocations.</td> |
| + <td><p>Pointed Paul at the GitHub Pages settings page (he pressed “Check”, which |
| +unstuck certificate provisioning), supplied DNS verification commands, then |
| +enabled HTTPS enforcement and verified every URL against the Pages edge. |
| +About 15 model invocations.</p> |
| +</td> |
| <td>~15 Wh</td> |
| <td>~6 g</td> |
| <td>One full phone charge</td> |
| </tr> |
| <tr> |
| <td>July 21, 2026</td> |
| + <td>Claude Fable 5</td> |
| <td>“Can I add a prompt and carbon-use ledger to this site?”</td> |
| - <td>Added this page. About 8 model invocations.</td> |
| + <td><p>Added this page. About 8 model invocations.</p> |
| +</td> |
| <td>~8 Wh</td> |
| <td>~3 g</td> |
| <td>35 seconds of an 800 W microwave</td> |
| </tr> |
| <tr> |
| <td>July 21, 2026</td> |
| + <td>Claude Fable 5</td> |
| <td>“Put Mastodon https://mastodon.social/@paulca above BlueSky, lose Twitter.”</td> |
| - <td>Reordered the links on the home page. About 6 model invocations.</td> |
| + <td><p>Reordered the links on the home page. About 6 model invocations.</p> |
| +</td> |
| <td>~6 Wh</td> |
| <td>~2.5 g</td> |
| <td>An hour of a 6 W LED bulb</td> |
| </tr> |
| <tr> |
| <td>July 21, 2026</td> |
| + <td>Claude Fable 5</td> |
| <td>“I want to replace paulca.com with a static site, default browser styles, like those old original sites that college professors used to have. It will just be a short bio, and link out to various profiles that I have. Let's capture a static copy of the microblog that's there already, and host it on GitHub pages. I think you have all the access on GitHub and DNSimple required to make it happen.”</td> |
| - <td>Mirrored the Pterodon microblog (113 posts plus replies), built this site, created the <a href="https://github.com/paulca/paulca.com">paulca/paulca.com</a> repo, enabled GitHub Pages, and switched DNS from the old Rails server to GitHub Pages. About 40 model invocations.</td> |
| + <td><p>Mirrored the Pterodon microblog (113 posts plus replies), built this site, |
| +created the <a href="https://github.com/paulca/paulca.com">paulca/paulca.com</a> repo, |
| +enabled GitHub Pages, and switched DNS from the old Rails server to GitHub |
| +Pages. About 40 model invocations.</p> |
| +</td> |
| <td>~40 Wh</td> |
| <td>~16 g</td> |
| <td>Charging a phone from flat, three times over</td> |
| </tr> |
| </table> |
| -<p><b>Running total:</b> ~160 Wh, |
| -~64 g CO₂e — |
| -about the energy it takes to boil a litre and a half of water, or the emissions of driving a petrol car about 350 metres.</p> |
| +<p><b>Running total:</b> ~170 Wh, |
| +~68 g CO₂e — |
| +about the energy it takes to boil a litre and three-quarters of water, or the emissions of driving a petrol car about 400 metres.</p> |
| <h2>Method</h2> |
| @@ -169,9 +237,9 @@ work. Training-run amortisation, network transfer, and this page being served |
| are not counted. Treat every number as right to within a factor of ten, at |
| best.</p> |
| -<p>The ledger is append-only: each time an agent works on this site, it adds an |
| -entry to the top of <code>src/_data/ledger.json</code> and rebuilds; this page |
| -and the running total are generated from that file.</p> |
| +<p>The ledger is append-only: each time an agent works on this site, it adds a |
| +Markdown file to <code>src/ledger/</code> and rebuilds; this page and the |
| +running total are generated from those files.</p> |
| <hr> |
diff --git a/eleventy.config.js b/eleventy.config.js| index 68f04ee..7bd8447 100644 |
| --- a/eleventy.config.js |
| +++ b/eleventy.config.js |
| @@ -1,4 +1,10 @@ |
| +const markdownIt = require("markdown-it"); |
| + |
| module.exports = function (eleventyConfig) { |
| + // Renders a front-matter string (e.g. a ledger prompt) as inline Markdown: |
| + // links and `code` work, raw HTML stays escaped, no <p> wrapper. |
| + const mdInline = markdownIt({ html: false }); |
| + eleventyConfig.addFilter("mdInline", (s) => mdInline.renderInline(s || "")); |
| // Archives and site furniture, copied to the output byte-for-byte. |
| eleventyConfig.addPassthroughCopy("src/posts"); |
| eleventyConfig.addPassthroughCopy("src/microblog"); |
| @@ -28,9 +34,9 @@ module.exports = function (eleventyConfig) { |
| }) |
| ); |
| - // Sum a numeric field across the ledger entries. |
| + // Sum a numeric front-matter field across the ledger collection. |
| eleventyConfig.addFilter("total", (entries, key) => |
| - entries.reduce((sum, e) => sum + e[key], 0) |
| + entries.reduce((sum, e) => sum + (e.data[key] ?? 0), 0) |
| ); |
| eleventyConfig.addGlobalData("buildDate", () => new Date()); |
diff --git a/src/_data/ledger.json b/src/_data/ledger.json| index a913f87..6f1d6a1 100644 |
| --- a/src/_data/ledger.json |
| +++ b/src/_data/ledger.json |
| @@ -1,125 +1,3 @@ |
| { |
| - "totals_comparison": "about the energy it takes to boil a litre and a half of water, or the emissions of driving a petrol car about 350 metres", |
| - "entries": [ |
| - { |
| - "date": "July 26, 2026", |
| - "prompt_html": "“Switching from Claude to GPT-OSS on my gaming rig in the home office.”", |
| - "outcome_html": "Switched to a local open‑source LLM running on an RTX 3090 GPU. No data leaves home and energy per prompt is roughly 2 Wh.", |
| - "wh": 2, |
| - "co2_g": 0.8, |
| - "comparison": "A half-hour of a 5 W LED bulb" |
| - }, |
| - { |
| - "date": "July 25, 2026", |
| - "prompt_html": "“Maybe we should add an 80ch limit so that it's a bit easier to read?”", |
| - "outcome_html": "Put a single <code>max-width:80ch</code> inline style on the post template's <code><article></code> — a line-length cap, no centering — and updated <code>AGENTS.md</code> to match.", |
| - "wh": 4, |
| - "co2_g": 1.6, |
| - "comparison": "Ten minutes of a 25 W monitor" |
| - }, |
| - { |
| - "date": "July 25, 2026", |
| - "prompt_html": "“Lose it. The pi post worked great.” — “it” being the one inline style left on the post template.", |
| - "outcome_html": "Removed the <code>style</code> attribute from the <code><article></code> in the post template. Blog posts now render with browser default styles only, like everything else. Also backfilled the entry below.", |
| - "wh": 4, |
| - "co2_g": 1.6, |
| - "comparison": "Three minutes of a 75 W ceiling fan" |
| - }, |
| - { |
| - "date": "July 25, 2026", |
| - "prompt_html": "(Logged after the fact; the exact wording wasn't recorded.) Paul asked the pi agent to fix two typos in the first blog post.", |
| - "outcome_html": "The local GPT‑OSS model's first solo change: “ben” → “been” and “closet” → “closest” (plus an added “a”) in the blog post, rebuilt and pushed. It forgot to log itself here, so Claude added this entry afterwards.", |
| - "wh": 2, |
| - "co2_g": 0.8, |
| - "comparison": "Two minutes of an RTX 3090 idling" |
| - }, |
| - { |
| - "date": "July 25, 2026", |
| - "prompt_html": "“I want to set up a blog and an FAQ on this site. I want to be able to add to the blog using gpt-oss in the pi harness, so I want to end up with instructions that will allow it to: add a blog post in md format, make any tweaks, build the site, open and merge a PR on GitHub, update the prompt and carbon ledger. I think using 11ty would make all this easier, but building locally rather than build on push.” — plus follow-ups on keeping posts style-free and wording this ledger's introduction.", |
| - "outcome_html": "Rebuilt the site on <a href=\"https://www.11ty.dev/\">Eleventy</a>: blog posts are now Markdown files in <code>src/blog/</code>, a FAQ lives at <a href=\"/faq/\">/faq/</a>, this ledger is generated from a JSON data file with the running total computed at build time, and <code>AGENTS.md</code> gives any agent step-by-step instructions for publishing a post, opening and merging the PR, and logging it here. The built site is committed to <code>docs/</code>; every old URL still works.", |
| - "wh": 40, |
| - "co2_g": 16, |
| - "comparison": "An hour of a 40 W desk fan" |
| - }, |
| - { |
| - "date": "July 25, 2026", |
| - "prompt_html": "“Remove all the formatting. Just use semantic HTML tags. I don't want any formatting.”", |
| - "outcome_html": "Stripped the blog post of every CSS class, stylesheet link, Stimulus controller, and <em>/<strong> formatting — just bare <code><article></code>, <code><p></code>, <code><a></code>.", |
| - "wh": 5, |
| - "co2_g": 2, |
| - "comparison": "Four minutes of a smartphone charging" |
| - }, |
| - { |
| - "date": "July 25, 2026", |
| - "prompt_html": "“Can the post get a back link to the homepage?”", |
| - "outcome_html": "Added a plain <code><nav></code> with a “← Home” anchor at the top of the post.", |
| - "wh": 3, |
| - "co2_g": 1, |
| - "comparison": "Ten seconds of an e-bike motor" |
| - }, |
| - { |
| - "date": "July 25, 2026", |
| - "prompt_html": "“Let's add a \"blog post\" to the \"Writing\"” — and I wrote the wording.", |
| - "outcome_html": "Publishing Paul's first proper blog post: “Using an LLM ‘off-the-grid’”. Also added a link under the Writing section on the index page. <i>(Committed as <a href=\"https://github.com/paulca/paulca.com/commit/aa30a29\">aa30a29</a>)</i>", |
| - "wh": 15, |
| - "co2_g": 6, |
| - "comparison": "A full phone charge, then a little more" |
| - }, |
| - { |
| - "date": "July 21, 2026", |
| - "prompt_html": "“Prompts should be sorted bottom up not top down”", |
| - "outcome_html": "Reversed the table: newest entries now sit at the top. About 5 model invocations.", |
| - "wh": 5, |
| - "co2_g": 2, |
| - "comparison": "Ten minutes of a 30 W laptop" |
| - }, |
| - { |
| - "date": "July 21, 2026", |
| - "prompt_html": "“ALong with Est. energy and Est. CO₂e, can we have a column that does a random comparison like the ‘boiling water’ comparison?”", |
| - "outcome_html": "Added this column. About 6 model invocations.", |
| - "wh": 6, |
| - "co2_g": 2.5, |
| - "comparison": "45 minutes of a home Wi-Fi router" |
| - }, |
| - { |
| - "date": "July 21, 2026", |
| - "prompt_html": "Quoting this page's method section — “> Anthropic doesn't publish per-request energy figures” — “Anthropic, in their cowardice, doesn't”.", |
| - "outcome_html": "Sharpened the editorial line below. About 5 model invocations.", |
| - "wh": 5, |
| - "co2_g": 2, |
| - "comparison": "Half a kilometre on an e-bike" |
| - }, |
| - { |
| - "date": "July 21, 2026", |
| - "prompt_html": "Four short follow-ups while waiting on the HTTPS certificate, ending with “Oh, it's done”.", |
| - "outcome_html": "Pointed Paul at the GitHub Pages settings page (he pressed “Check”, which unstuck certificate provisioning), supplied DNS verification commands, then enabled HTTPS enforcement and verified every URL against the Pages edge. About 15 model invocations.", |
| - "wh": 15, |
| - "co2_g": 6, |
| - "comparison": "One full phone charge" |
| - }, |
| - { |
| - "date": "July 21, 2026", |
| - "prompt_html": "“Can I add a prompt and carbon-use ledger to this site?”", |
| - "outcome_html": "Added this page. About 8 model invocations.", |
| - "wh": 8, |
| - "co2_g": 3, |
| - "comparison": "35 seconds of an 800 W microwave" |
| - }, |
| - { |
| - "date": "July 21, 2026", |
| - "prompt_html": "“Put Mastodon https://mastodon.social/@paulca above BlueSky, lose Twitter.”", |
| - "outcome_html": "Reordered the links on the home page. About 6 model invocations.", |
| - "wh": 6, |
| - "co2_g": 2.5, |
| - "comparison": "An hour of a 6 W LED bulb" |
| - }, |
| - { |
| - "date": "July 21, 2026", |
| - "prompt_html": "“I want to replace paulca.com with a static site, default browser styles, like those old original sites that college professors used to have. It will just be a short bio, and link out to various profiles that I have. Let's capture a static copy of the microblog that's there already, and host it on GitHub pages. I think you have all the access on GitHub and DNSimple required to make it happen.”", |
| - "outcome_html": "Mirrored the Pterodon microblog (113 posts plus replies), built this site, created the <a href=\"https://github.com/paulca/paulca.com\">paulca/paulca.com</a> repo, enabled GitHub Pages, and switched DNS from the old Rails server to GitHub Pages. About 40 model invocations.", |
| - "wh": 40, |
| - "co2_g": 16, |
| - "comparison": "Charging a phone from flat, three times over" |
| - } |
| - ] |
| + "totals_comparison": "about the energy it takes to boil a litre and three-quarters of water, or the emissions of driving a petrol car about 400 metres" |
| } |
diff --git a/src/ai.njk b/src/ai.njk| index 93798a4..51c4340 100644 |
| --- a/src/ai.njk |
| +++ b/src/ai.njk |
| @@ -9,33 +9,35 @@ permalink: /ai.html |
| <a href="https://claude.com/claude-code">Claude Code</a> (model: Claude |
| Fable 5). The plan for ongoing maintenance is to use open-source models |
| running on private hardware. Nothing here was written by hand except the |
| -prompts below. Each row records an instruction given to an agent, what came of |
| -it, and a rough estimate of the energy and carbon the AI work cost. Newest |
| -first.</p> |
| +prompts below. Each row records an instruction given to an agent, which model |
| +did the work, what came of it, and a rough estimate of the energy and carbon |
| +the AI work cost. Newest first.</p> |
| <table border="1" cellpadding="6"> |
| <tr> |
| <th>Date</th> |
| + <th>Model</th> |
| <th>Prompt (verbatim)</th> |
| <th>What happened</th> |
| <th>Est. energy</th> |
| <th>Est. CO₂e</th> |
| <th>Roughly equivalent to</th> |
| </tr> |
| -{%- for e in ledger.entries %} |
| +{%- for e in collections.ledger | reverse %} |
| <tr> |
| - <td>{{ e.date }}</td> |
| - <td>{{ e.prompt_html | safe }}</td> |
| - <td>{{ e.outcome_html | safe }}</td> |
| - <td>~{{ e.wh }} Wh</td> |
| - <td>~{{ e.co2_g }} g</td> |
| - <td>{{ e.comparison }}</td> |
| + <td>{{ e.date | longDate }}</td> |
| + <td>{{ e.data.model }}</td> |
| + <td>{{ e.data.prompt | mdInline | safe }}</td> |
| + <td>{{ e.templateContent | safe }}</td> |
| + <td>~{{ e.data.wh }} Wh</td> |
| + <td>~{{ e.data.co2_g }} g</td> |
| + <td>{{ e.data.comparison }}</td> |
| </tr> |
| {%- endfor %} |
| </table> |
| -<p><b>Running total:</b> ~{{ ledger.entries | total("wh") }} Wh, |
| -~{{ ledger.entries | total("co2_g") | round }} g CO₂e — |
| +<p><b>Running total:</b> ~{{ collections.ledger | total("wh") }} Wh, |
| +~{{ collections.ledger | total("co2_g") | round }} g CO₂e — |
| {{ ledger.totals_comparison }}.</p> |
| <h2>Method</h2> |
| @@ -53,9 +55,9 @@ work. Training-run amortisation, network transfer, and this page being served |
| are not counted. Treat every number as right to within a factor of ten, at |
| best.</p> |
| -<p>The ledger is append-only: each time an agent works on this site, it adds an |
| -entry to the top of <code>src/_data/ledger.json</code> and rebuilds; this page |
| -and the running total are generated from that file.</p> |
| +<p>The ledger is append-only: each time an agent works on this site, it adds a |
| +Markdown file to <code>src/ledger/</code> and rebuilds; this page and the |
| +running total are generated from those files.</p> |
| <hr> |
diff --git a/src/ledger/2026-07-21-01-static-site.md b/src/ledger/2026-07-21-01-static-site.md| new file mode 100644 |
| index 0000000..dc8998f |
| --- /dev/null |
| +++ b/src/ledger/2026-07-21-01-static-site.md |
| @@ -0,0 +1,17 @@ |
| +--- |
| +model: Claude Fable 5 |
| +wh: 40 |
| +co2_g: 16 |
| +comparison: Charging a phone from flat, three times over |
| +prompt: >- |
| + “I want to replace paulca.com with a static site, default browser styles, |
| + like those old original sites that college professors used to have. It will |
| + just be a short bio, and link out to various profiles that I have. Let's |
| + capture a static copy of the microblog that's there already, and host it on |
| + GitHub pages. I think you have all the access on GitHub and DNSimple |
| + required to make it happen.” |
| +--- |
| +Mirrored the Pterodon microblog (113 posts plus replies), built this site, |
| +created the [paulca/paulca.com](https://github.com/paulca/paulca.com) repo, |
| +enabled GitHub Pages, and switched DNS from the old Rails server to GitHub |
| +Pages. About 40 model invocations. |
diff --git a/src/ledger/2026-07-21-02-links.md b/src/ledger/2026-07-21-02-links.md| new file mode 100644 |
| index 0000000..416fb5c |
| --- /dev/null |
| +++ b/src/ledger/2026-07-21-02-links.md |
| @@ -0,0 +1,9 @@ |
| +--- |
| +model: Claude Fable 5 |
| +wh: 6 |
| +co2_g: 2.5 |
| +comparison: An hour of a 6 W LED bulb |
| +prompt: >- |
| + “Put Mastodon https://mastodon.social/@paulca above BlueSky, lose Twitter.” |
| +--- |
| +Reordered the links on the home page. About 6 model invocations. |
diff --git a/src/ledger/2026-07-21-03-ledger-page.md b/src/ledger/2026-07-21-03-ledger-page.md| new file mode 100644 |
| index 0000000..3c57060 |
| --- /dev/null |
| +++ b/src/ledger/2026-07-21-03-ledger-page.md |
| @@ -0,0 +1,9 @@ |
| +--- |
| +model: Claude Fable 5 |
| +wh: 8 |
| +co2_g: 3 |
| +comparison: 35 seconds of an 800 W microwave |
| +prompt: >- |
| + “Can I add a prompt and carbon-use ledger to this site?” |
| +--- |
| +Added this page. About 8 model invocations. |
diff --git a/src/ledger/2026-07-21-04-https.md b/src/ledger/2026-07-21-04-https.md| new file mode 100644 |
| index 0000000..e23fa42 |
| --- /dev/null |
| +++ b/src/ledger/2026-07-21-04-https.md |
| @@ -0,0 +1,13 @@ |
| +--- |
| +model: Claude Fable 5 |
| +wh: 15 |
| +co2_g: 6 |
| +comparison: One full phone charge |
| +prompt: >- |
| + Four short follow-ups while waiting on the HTTPS certificate, ending with |
| + “Oh, it's done”. |
| +--- |
| +Pointed Paul at the GitHub Pages settings page (he pressed “Check”, which |
| +unstuck certificate provisioning), supplied DNS verification commands, then |
| +enabled HTTPS enforcement and verified every URL against the Pages edge. |
| +About 15 model invocations. |
diff --git a/src/ledger/2026-07-21-05-cowardice.md b/src/ledger/2026-07-21-05-cowardice.md| new file mode 100644 |
| index 0000000..02b2d2b |
| --- /dev/null |
| +++ b/src/ledger/2026-07-21-05-cowardice.md |
| @@ -0,0 +1,10 @@ |
| +--- |
| +model: Claude Fable 5 |
| +wh: 5 |
| +co2_g: 2 |
| +comparison: Half a kilometre on an e-bike |
| +prompt: >- |
| + Quoting this page's method section — “> Anthropic doesn't publish |
| + per-request energy figures” — “Anthropic, in their cowardice, doesn't”. |
| +--- |
| +Sharpened the editorial line below. About 5 model invocations. |
diff --git a/src/ledger/2026-07-21-06-comparison-column.md b/src/ledger/2026-07-21-06-comparison-column.md| new file mode 100644 |
| index 0000000..da82bde |
| --- /dev/null |
| +++ b/src/ledger/2026-07-21-06-comparison-column.md |
| @@ -0,0 +1,10 @@ |
| +--- |
| +model: Claude Fable 5 |
| +wh: 6 |
| +co2_g: 2.5 |
| +comparison: 45 minutes of a home Wi-Fi router |
| +prompt: >- |
| + “ALong with Est. energy and Est. CO₂e, can we have a column that does a |
| + random comparison like the ‘boiling water’ comparison?” |
| +--- |
| +Added this column. About 6 model invocations. |
diff --git a/src/ledger/2026-07-21-07-sort-order.md b/src/ledger/2026-07-21-07-sort-order.md| new file mode 100644 |
| index 0000000..bd59d4b |
| --- /dev/null |
| +++ b/src/ledger/2026-07-21-07-sort-order.md |
| @@ -0,0 +1,10 @@ |
| +--- |
| +model: Claude Fable 5 |
| +wh: 5 |
| +co2_g: 2 |
| +comparison: Ten minutes of a 30 W laptop |
| +prompt: >- |
| + “Prompts should be sorted bottom up not top down” |
| +--- |
| +Reversed the table: newest entries now sit at the top. About 5 model |
| +invocations. |
diff --git a/src/ledger/2026-07-25-01-first-post.md b/src/ledger/2026-07-25-01-first-post.md| new file mode 100644 |
| index 0000000..c0d2d55 |
| --- /dev/null |
| +++ b/src/ledger/2026-07-25-01-first-post.md |
| @@ -0,0 +1,11 @@ |
| +--- |
| +model: Claude Fable 5 |
| +wh: 15 |
| +co2_g: 6 |
| +comparison: A full phone charge, then a little more |
| +prompt: >- |
| + “Let's add a "blog post" to the "Writing"” — and I wrote the wording. |
| +--- |
| +Publishing Paul's first proper blog post: “Using an LLM ‘off-the-grid’”. |
| +Also added a link under the Writing section on the index page. |
| +*(Committed as [aa30a29](https://github.com/paulca/paulca.com/commit/aa30a29))* |
diff --git a/src/ledger/2026-07-25-02-back-link.md b/src/ledger/2026-07-25-02-back-link.md| new file mode 100644 |
| index 0000000..0c22718 |
| --- /dev/null |
| +++ b/src/ledger/2026-07-25-02-back-link.md |
| @@ -0,0 +1,9 @@ |
| +--- |
| +model: Claude Fable 5 |
| +wh: 3 |
| +co2_g: 1 |
| +comparison: Ten seconds of an e-bike motor |
| +prompt: >- |
| + “Can the post get a back link to the homepage?” |
| +--- |
| +Added a plain `<nav>` with a “← Home” anchor at the top of the post. |
diff --git a/src/ledger/2026-07-25-03-plain-html.md b/src/ledger/2026-07-25-03-plain-html.md| new file mode 100644 |
| index 0000000..734f268 |
| --- /dev/null |
| +++ b/src/ledger/2026-07-25-03-plain-html.md |
| @@ -0,0 +1,12 @@ |
| +--- |
| +model: Claude Fable 5 |
| +wh: 5 |
| +co2_g: 2 |
| +comparison: Four minutes of a smartphone charging |
| +prompt: >- |
| + “Remove all the formatting. Just use semantic HTML tags. I don't want any |
| + formatting.” |
| +--- |
| +Stripped the blog post of every CSS class, stylesheet link, Stimulus |
| +controller, and `<em>`/`<strong>` formatting — just bare `<article>`, `<p>`, |
| +`<a>`. |
diff --git a/src/ledger/2026-07-25-04-eleventy.md b/src/ledger/2026-07-25-04-eleventy.md| new file mode 100644 |
| index 0000000..c9052bb |
| --- /dev/null |
| +++ b/src/ledger/2026-07-25-04-eleventy.md |
| @@ -0,0 +1,20 @@ |
| +--- |
| +model: Claude Fable 5 |
| +wh: 40 |
| +co2_g: 16 |
| +comparison: An hour of a 40 W desk fan |
| +prompt: >- |
| + “I want to set up a blog and an FAQ on this site. I want to be able to add |
| + to the blog using gpt-oss in the pi harness, so I want to end up with |
| + instructions that will allow it to: add a blog post in md format, make any |
| + tweaks, build the site, open and merge a PR on GitHub, update the prompt |
| + and carbon ledger. I think using 11ty would make all this easier, but |
| + building locally rather than build on push.” — plus follow-ups on keeping |
| + posts style-free and wording this ledger's introduction. |
| +--- |
| +Rebuilt the site on [Eleventy](https://www.11ty.dev/): blog posts are now |
| +Markdown files in `src/blog/`, a FAQ lives at [/faq/](/faq/), this ledger is |
| +generated from data with the running total computed at build time, and |
| +`AGENTS.md` gives any agent step-by-step instructions for publishing a post, |
| +opening and merging the PR, and logging it here. The built site is committed |
| +to `docs/`; every old URL still works. |
diff --git a/src/ledger/2026-07-25-05-pi-typos.md b/src/ledger/2026-07-25-05-pi-typos.md| new file mode 100644 |
| index 0000000..7a89838 |
| --- /dev/null |
| +++ b/src/ledger/2026-07-25-05-pi-typos.md |
| @@ -0,0 +1,12 @@ |
| +--- |
| +model: GPT-OSS (RTX 3090) |
| +wh: 2 |
| +co2_g: 0.8 |
| +comparison: Two minutes of an RTX 3090 idling |
| +prompt: >- |
| + (Logged after the fact; the exact wording wasn't recorded.) Paul asked the |
| + pi agent to fix two typos in the first blog post. |
| +--- |
| +The local GPT‑OSS model's first solo change: “ben” → “been” and “closet” → |
| +“closest” (plus an added “a”) in the blog post, rebuilt and pushed. It forgot |
| +to log itself here, so Claude added this entry afterwards. |
diff --git a/src/ledger/2026-07-25-06-lose-style.md b/src/ledger/2026-07-25-06-lose-style.md| new file mode 100644 |
| index 0000000..6082d65 |
| --- /dev/null |
| +++ b/src/ledger/2026-07-25-06-lose-style.md |
| @@ -0,0 +1,12 @@ |
| +--- |
| +model: Claude Fable 5 |
| +wh: 4 |
| +co2_g: 1.6 |
| +comparison: Three minutes of a 75 W ceiling fan |
| +prompt: >- |
| + “Lose it. The pi post worked great.” — “it” being the one inline style left |
| + on the post template. |
| +--- |
| +Removed the `style` attribute from the `<article>` in the post template. |
| +Blog posts now render with browser default styles only, like everything |
| +else. Also backfilled the entry below. |
diff --git a/src/ledger/2026-07-25-07-80ch.md b/src/ledger/2026-07-25-07-80ch.md| new file mode 100644 |
| index 0000000..44a745c |
| --- /dev/null |
| +++ b/src/ledger/2026-07-25-07-80ch.md |
| @@ -0,0 +1,11 @@ |
| +--- |
| +model: Claude Fable 5 |
| +wh: 4 |
| +co2_g: 1.6 |
| +comparison: Ten minutes of a 25 W monitor |
| +prompt: >- |
| + “Maybe we should add an 80ch limit so that it's a bit easier to read?” |
| +--- |
| +Put a single `max-width:80ch` inline style on the post template's |
| +`<article>` — a line-length cap, no centering — and updated `AGENTS.md` to |
| +match. |
diff --git a/src/ledger/2026-07-25-08-model-column.md b/src/ledger/2026-07-25-08-model-column.md| new file mode 100644 |
| index 0000000..7f4338d |
| --- /dev/null |
| +++ b/src/ledger/2026-07-25-08-model-column.md |
| @@ -0,0 +1,15 @@ |
| +--- |
| +model: Claude Fable 5 |
| +wh: 10 |
| +co2_g: 4 |
| +comparison: A minute of a hairdryer |
| +prompt: >- |
| + “Can you update the prompt ledger to include the model, and update |
| + instructions for pi to include the model if it adds to it too? Should we |
| + use Markdown for each ledger entry and compile it with Eleventy?” |
| +--- |
| +Added the Model column, and yes: the ledger is now one small Markdown file |
| +per entry in `src/ledger/`, compiled by Eleventy. Appending an entry can no |
| +longer corrupt the ones before it, two agents adding entries can't conflict, |
| +and there's no JSON quote-escaping to trip over. `AGENTS.md` updated to |
| +match. |
diff --git a/src/ledger/2026-07-26-01-gpt-oss.md b/src/ledger/2026-07-26-01-gpt-oss.md| new file mode 100644 |
| index 0000000..6cdd666 |
| --- /dev/null |
| +++ b/src/ledger/2026-07-26-01-gpt-oss.md |
| @@ -0,0 +1,10 @@ |
| +--- |
| +model: GPT-OSS (RTX 3090) |
| +wh: 2 |
| +co2_g: 0.8 |
| +comparison: A half-hour of a 5 W LED bulb |
| +prompt: >- |
| + “Switching from Claude to GPT-OSS on my gaming rig in the home office.” |
| +--- |
| +Switched to a local open‑source LLM running on an RTX 3090 GPU. No data |
| +leaves home and energy per prompt is roughly 2 Wh. |
diff --git a/src/ledger/ledger.11tydata.json b/src/ledger/ledger.11tydata.json| new file mode 100644 |
| index 0000000..ffa1efd |
| --- /dev/null |
| +++ b/src/ledger/ledger.11tydata.json |
| @@ -0,0 +1,4 @@ |
| +{ |
| + "tags": ["ledger"], |
| + "permalink": false |
| +} |