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
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ This notebook is for humans **and** coding agents. Do not invent policy from the

Done when one useful task has a checked result. No routine reflection record is required.

## Reproducible exercise and feedback

Guidance reviewed 15th October 2026. Try the [worked exercise](https://chopwoodcarrywater.uk/worked-example.html) or run `examples/array-limit/test.cjs` as described in its README. [Verify downloads](https://chopwoodcarrywater.uk/downloads.html) with the public manifests/checksums. [Feedback](https://chopwoodcarrywater.uk/feedback.html) should include host/version, exact step, expected/actual and a reference, with private project details removed.

## While you work

- Prefer skills/rules/patterns on disk over chat folklore.
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,9 @@ See [LICENSE](LICENSE) for the split.
---

*AI-assisted (Codex) under Alex’s direction. Use at your own risk.*

## Try one checked result

Guidance reviewed 15th October 2026. [Run the evergreen worked example](https://chopwoodcarrywater.uk/worked-example.html), or use [the local offline guide](examples/array-limit/README.md). It deliberately shows a failed correction before a passing fix, with the same tests throughout.

[Verify starter downloads and file manifests](https://chopwoodcarrywater.uk/downloads.html). [Share feedback](https://chopwoodcarrywater.uk/feedback.html) with host/version, exact step, expected/actual result and a reference; remove secrets and private project details first.
4 changes: 2 additions & 2 deletions content/blog.json
Original file line number Diff line number Diff line change
Expand Up @@ -532,8 +532,8 @@
"url": "https://penelope.uchicago.edu/Thayer/E/Roman/Texts/Quintilian/Institutio_Oratoria/home.html"
},
{
"label": "Leiden University, Ancient Education",
"url": "https://studiegids-archive.leidenuniv.nl/en/courses/43807/tutorial-greek-ancient-education"
"label": "Leiden University, Ancient Education (2014–2015 course archive)",
"url": "https://studiegids-archief.leidenuniv.nl/courses/43807/tutorial-greek-ancient-education"
},
{
"label": "Cambridge University Press, Dialectic after Plato and Aristotle",
Expand Down
6 changes: 4 additions & 2 deletions content/capabilities.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@
"band": "Team knowledge base",
"evidence": {
"url": "notes/the-token-bonfire.html",
"label": "Token Bonfire: failures and limits"
"label": "Token Bonfire: failures and limits",
"limit": "A reported failure and its lessons; no controlled comparison or general productivity result."
}
},
{
Expand All @@ -71,7 +72,8 @@
"band": "Platform engineering",
"evidence": {
"url": "notes/the-cockpit-changed-the-work-did-not.html",
"label": "Host migration account"
"label": "Host migration account",
"limit": "One host migration account; host versions and permissions vary. It does not validate the other capability estimates."
}
},
{
Expand Down
4 changes: 3 additions & 1 deletion docs/agents.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"description": "Short get-going path for coding agents: Codex-first pack, portable Agent Skill, fail-closed boundaries, signed pattern, and a 60-minute checklist.",
"isPartOf": { "@id": "https://chopwoodcarrywater.uk/#website" },
"about": ["Codex", "Agent Skills", "AI coding agents"],
"dateModified": "2026-09-12",
"dateModified": "2026-10-15",
"inLanguage": "en-GB"
}
</script>
Expand Down Expand Up @@ -78,6 +78,7 @@
<div class="wrap">
<p class="agents-kicker">For coding agents</p>
<h1>Get going</h1>
<p class="fineprint">Guidance reviewed <time datetime="2026-10-15">15th October 2026</time>.</p>
<p class="epigraph" data-testid="epigraph-agents">Before enlightenment: chop wood, carry water.</p>
<p class="section-lede">
Do not invent policy from the blog. Install a thin working relationship,
Expand All @@ -90,6 +91,7 @@ <h1>Get going</h1>
<a class="btn ghost" href="./#hour" data-testid="agents-hour">Open the 60-minute path</a>
</p>

<p><a class="text-link" href="worked-example.html">Run a complete small exercise</a> · <a class="text-link" href="downloads.html">Verify pack checksums and file manifests</a> · <a class="text-link" href="feedback.html">Tell us where you got stuck</a></p>
<h2 class="subhead">Six steps</h2>
<ol class="steps" data-testid="agents-steps">
<li class="step-card">
Expand Down
1 change: 1 addition & 0 deletions docs/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ function renderCapabilities(data) {
el("span", {}, [
row.note,
row.evidence ? el("a", { className: "text-link", href: row.evidence.url, text: row.evidence.label }) : null,
row.evidence?.limit ? el("p", { className: "fineprint", text: row.evidence.limit }) : null,
row.band ? el("div", { className: "band", text: row.band }) : null,
]),
]),
Expand Down
4 changes: 2 additions & 2 deletions docs/content/blog.json
Original file line number Diff line number Diff line change
Expand Up @@ -532,8 +532,8 @@
"url": "https://penelope.uchicago.edu/Thayer/E/Roman/Texts/Quintilian/Institutio_Oratoria/home.html"
},
{
"label": "Leiden University, Ancient Education",
"url": "https://studiegids-archive.leidenuniv.nl/en/courses/43807/tutorial-greek-ancient-education"
"label": "Leiden University, Ancient Education (2014–2015 course archive)",
"url": "https://studiegids-archief.leidenuniv.nl/courses/43807/tutorial-greek-ancient-education"
},
{
"label": "Cambridge University Press, Dialectic after Plato and Aristotle",
Expand Down
6 changes: 4 additions & 2 deletions docs/content/capabilities.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@
"band": "Team knowledge base",
"evidence": {
"url": "notes/the-token-bonfire.html",
"label": "Token Bonfire: failures and limits"
"label": "Token Bonfire: failures and limits",
"limit": "A reported failure and its lessons; no controlled comparison or general productivity result."
}
},
{
Expand All @@ -71,7 +72,8 @@
"band": "Platform engineering",
"evidence": {
"url": "notes/the-cockpit-changed-the-work-did-not.html",
"label": "Host migration account"
"label": "Host migration account",
"limit": "One host migration account; host versions and permissions vary. It does not validate the other capability estimates."
}
},
{
Expand Down
93 changes: 93 additions & 0 deletions docs/downloads.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<!DOCTYPE html>
<html lang="en-GB">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Check your starter download · Chop Wood Carry Water</title>
<meta name="description" content="Download the Codex or Cursor starter pack or runnable exercise, inspect file manifests and verify SHA-256 checksums before using the files." />
<meta name="robots" content="index,follow" />
<link rel="canonical" href="https://chopwoodcarrywater.uk/downloads.html" />
<meta property="og:type" content="website" />
<meta property="og:title" content="Check your starter download" />
<meta property="og:description" content="Download the Codex or Cursor starter pack or runnable exercise, inspect file manifests and verify SHA-256 checksums before using the files." />
<meta property="og:url" content="https://chopwoodcarrywater.uk/downloads.html" />
<meta property="og:image" content="https://chopwoodcarrywater.uk/assets/og-cover-v2.png" />
<meta property="og:image:alt" content="Chop Wood Carry Water engineering notebook" />
<link rel="icon" href="assets/chopwood-mark.svg" type="image/svg+xml" />
<link rel="stylesheet" href="styles.css" />
<link rel="stylesheet" href="guides.css" />
<script type="application/ld+json">{"@context": "https://schema.org", "@type": "WebPage", "url": "https://chopwoodcarrywater.uk/downloads.html", "name": "Check your starter download", "dateModified": "2026-10-15", "inLanguage": "en-GB"}</script>
</head>
<body data-ready="true">
<a class="skip" href="#main">Skip to content</a>
<header class="top note-top">
<a class="brand" href="./" aria-label="Chop Wood Carry Water — Durable Agent Harness home">
<img src="assets/chopwood-mark.png" alt="" width="35" height="35" />
<span class="brand-text">
<strong>Chop Wood Carry Water</strong>
<em>Durable Agent Harness</em>
</span>
</a>
<nav class="nav" aria-label="Primary">
<a href="./#hour">60 min</a>
<a href="agents.html">Agents</a>
<a href="./#blog">Insights</a>
<a href="./#privacy">About</a>
</nav>
</header>

<aside class="site-notice" data-testid="site-notice" role="note">
<div class="wrap">
<p>
<strong>Disclaimer.</strong>
AI-assisted notebook — use at your own risk.
Content
<a class="text-link" href="https://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener noreferrer license">CC BY-SA 4.0</a>.
</p>
</div>
</aside>


<main id="main" class="note-article">
<header class="note-header">
<p class="breadcrumb"><a href="./">Home</a> / Evergreen guidance</p>
<p class="kicker">Guide</p>
<h1>Check your starter download</h1>
<p class="note-byline">Reviewed <time datetime="2026-10-15">15th October 2026</time>.</p>
</header>
<div class="note-body">
<p>Each ZIP is built from the source files with a fixed file order, timestamp and permissions. The adjacent manifest lists every file’s relative path, byte size and SHA-256. ZIPs include hidden guidance folders.</p>
<ul>
<li><a class="text-link" href="packs/codex-hour-starter.zip" download>Codex pack ZIP</a> · <a class="text-link" href="packs/codex-hour/README.md">Browse guide</a> · <a class="text-link" href="packs/codex-hour-starter-manifest.json">File manifest</a></li>
<li><a class="text-link" href="packs/cursor-hour-starter.zip" download>Cursor pack ZIP</a> · <a class="text-link" href="packs/cursor-hour/README.md">Browse guide</a> · <a class="text-link" href="packs/cursor-hour-starter-manifest.json">File manifest</a></li>
<li><a class="text-link" href="packs/worked-example.zip" download>Worked exercise ZIP</a> · <a class="text-link" href="examples/array-limit/README.md">Browse guide</a> · <a class="text-link" href="packs/worked-example-manifest.json">File manifest</a></li>
</ul>
<h2 id="verify">Verify a download</h2>
<p>Save <a class="text-link" href="packs/SHA256SUMS" download>SHA256SUMS</a>, the ZIP and its manifest in the same directory. For the Codex pack on Linux, compare these locally computed hashes with the two matching lines in SHA256SUMS:</p>
<pre class="guide-code" tabindex="0" role="region" aria-label="Linux checksum commands"><code>sha256sum codex-hour-starter.zip codex-hour-starter-manifest.json</code></pre>
<p>On macOS use <code>shasum -a 256</code> in place of <code>sha256sum</code>. On Windows PowerShell use:</p>
<pre class="guide-code" tabindex="0" role="region" aria-label="Windows checksum commands"><code>Get-FileHash .\codex-hour-starter.zip -Algorithm SHA256
Get-FileHash .\codex-hour-starter-manifest.json -Algorithm SHA256</code></pre>
<p>Use the corresponding names for Cursor or the exercise. If either hash differs, stop and download again from the intended source. These hashes check that files agree with the published checksum list. They are not signatures: a compromised download source could replace the ZIP, manifest and list together.</p>
<h2>Check individual files</h2>
<p>After extraction, paths in the manifest are relative to the folder named by its <code>root</code> field, such as <code>codex-hour/</code>. Hash any file you want to check and compare its size and SHA-256 with that entry. Include hidden folders when comparing the complete file list; an extra or missing file means it is not the same package.</p>
<h2>Rebuild from the repository</h2>
<p>From a repository checkout with Python 3, run the standard-library builder. It needs no npm package, external service or credentials.</p>
<pre class="guide-code" tabindex="0" role="region" aria-label="Rebuild command"><code>python3 scripts/build_downloads.py</code></pre>
<p>The output goes to <code>docs/packs/</code>. ZIP entries use 1st January 1980, regular-file mode 0644, sorted paths and no compression. Source modification times, permissions and creation order do not affect the bytes. Manifests sit outside the ZIP; SHA256SUMS covers ZIPs and manifests and never hashes itself. No generated timestamp or build counter is added.</p>
<p><code>npm test</code> runs the normal sync and verifies source/browse/archive parity, manifest hashes, extracted execution and reproducibility after changing source times, modes and creation order. Checksums describe the files in this candidate, not the date of a historical site snapshot.</p>
<p><a class="text-link" href="worked-example.html">Run the worked example</a> · <a class="text-link" href="./#hour">First-hour setup</a> · <a class="text-link" href="feedback.html">Report a download problem</a></p>
<p class="fineprint">(Briar helped draft this)</p>
</div>
</main>
<footer class="footer">
<div class="wrap footer-inner">
<div>
<strong>Durable Agent Harness</strong>
<p>Alex Lennon · <a class="text-link" href="https://x.com/embedded_iot" target="_blank" rel="noopener noreferrer me">@embedded_iot</a> · Chop Wood Carry Water</p>
</div>
<p class="tagline-foot">Chop wood. Carry water.</p>
</div>
</footer>
</body>
</html>
34 changes: 34 additions & 0 deletions docs/examples/array-limit/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Worked exercise licence

The README and explanatory prose in this exercise are licensed under Creative
Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0):
https://creativecommons.org/licenses/by-sa/4.0/

Copyright © 2026 Alex Lennon (Chop Wood Carry Water).
Credit the author, indicate changes, link to the licence, and share adaptations
of that prose under the same licence. The linked licence contains the terms.

The JavaScript files (buggy.cjs, attempt.cjs, fixed.cjs and test.cjs) are
licensed under the MIT License reproduced below.

MIT License

Copyright (c) 2026 Dynamic Devices Ltd / Alex Lennon

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
67 changes: 67 additions & 0 deletions docs/examples/array-limit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# When zero is a valid limit

Evergreen exercise. Reviewed 15th October 2026 (Node 24.21.0).

This deliberately small exercise was run for the guide. It is not a historical
project incident or a measurement of an assistant's performance.

## Reproduce it

You need Node.js 24; there are no npm dependencies, accounts or network calls.
After unzipping worked-example.zip, open a terminal in worked-example/.
For a repository clone use examples/array-limit/ instead.

```sh
node --version
node --test-reporter=tap test.cjs buggy
node --test-reporter=tap test.cjs attempt
node --test-reporter=tap test.cjs fixed
```

Run the three stage commands separately. The first two intentionally return exit 1;
this is expected, so do not join them with &&. The fixed stage returns exit 0.

## The problem

`take(items, limit)` returns a new array. Omitted or null limits default to three.
Zero means no items; a positive integer caps the result. In buggy.cjs, `limit || 3`
replaces zero with three. The zero test expects [] but receives oak, ash and elm.

The attempted correction in attempt.cjs moves the default to a variable using
`limit ? limit : 3`. That still treats zero as false. The same test still fails.
In fixed.cjs, `limit ?? 3` defaults only for null or undefined, preserving zero.
All three implementations and the identical six tests are in this folder.

Actual guide run on Node 24.21.0, 15th October 2026:

| Stage | Tests | Pass | Fail | Exit |
| --- | ---: | ---: | ---: | ---: |
| buggy | 6 | 5 | 1 | 1 |
| attempt | 6 | 5 | 1 | 1 |
| fixed | 6 | 6 | 0 | 0 |

The other checks cover omitted/null defaults, positive/large limits, empty input,
and preserving the input. Invalid limits such as strings, negative numbers and
fractions are outside this contract; real APIs need an explicit validation policy.
This does not test model behaviour, host permissions, production integration,
performance or security.

## Try it with an assistant

Ask: "Read test.cjs and buggy.cjs. Explain why zero fails, cite the relevant
lines and suggest a focused check. Do not edit files." Check the answer yourself.
Then, if you want to practise editing, explicitly ask for a local correction and
rerun the tests. A plausible explanation or rewrite is not passing evidence.
You can complete the exercise by hand; an assistant is optional.

## Continue (online)

- Readable guide: https://chopwoodcarrywater.uk/worked-example.html
- Setup: https://chopwoodcarrywater.uk/#hour
- Download checksums and manifests: https://chopwoodcarrywater.uk/downloads.html
- Feedback: https://chopwoodcarrywater.uk/feedback.html

If a step fails, include host/version, exact step, expected/actual result and a
link or file reference. Remove secrets and private project details first.

Content CC BY-SA 4.0; code MIT (see LICENSE.txt). (Briar helped draft this)
5 changes: 5 additions & 0 deletions docs/examples/array-limit/attempt.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Attempt: move the default into a variable. Zero is still treated as false.
module.exports = function take(items, limit) {
const count = limit ? limit : 3;
return items.slice(0, count);
};
4 changes: 4 additions & 0 deletions docs/examples/array-limit/buggy.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Contract: null/undefined use 3; zero returns no items; positive integers cap results.
module.exports = function take(items, limit) {
return items.slice(0, limit || 3);
};
4 changes: 4 additions & 0 deletions docs/examples/array-limit/fixed.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = function take(items, limit) {
const count = limit ?? 3;
return items.slice(0, count);
};
31 changes: 31 additions & 0 deletions docs/examples/array-limit/test.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const { test } = require('node:test');
const assert = require('node:assert/strict');
const stage = process.argv[2] || 'fixed';
if (!['buggy', 'attempt', 'fixed'].includes(stage)) {
throw new Error('Use: node test.cjs buggy|attempt|fixed');
}
const take = require(`./${stage}.cjs`);
const items = ['oak', 'ash', 'elm', 'beech'];

test('omitted limit uses the default of three', () => {
assert.deepEqual(take(items), ['oak', 'ash', 'elm']);
});
test('null limit uses the default of three', () => {
assert.deepEqual(take(items, null), ['oak', 'ash', 'elm']);
});
test('zero requests no items', () => {
assert.deepEqual(take(items, 0), []);
});
test('positive limit returns that many items', () => {
assert.deepEqual(take(items, 2), ['oak', 'ash']);
});
test('large limit and empty input are safe', () => {
assert.deepEqual(take(items, 20), items);
assert.deepEqual(take([], 2), []);
});
test('input remains unchanged and the result is a new array', () => {
const input = Object.freeze(['oak', 'ash', 'elm', 'beech']);
assert.deepEqual(take(input, 2), ['oak', 'ash']);
assert.deepEqual(input, items);
assert.notEqual(take(input, 20), input);
});
Loading
Loading