From a6ad953710656693ce55459ae5f8964202321315 Mon Sep 17 00:00:00 2001 From: Phil Leggetter Date: Wed, 2 Sep 2026 13:52:57 +0100 Subject: [PATCH 1/6] Codify what a release title names, and the order of the sections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three things about release notes that were either unwritten or written and then not followed. The title names the product finding or fix. A release note is read by someone building on Hookdeck, so the headline is what changed for them or what we learned about the product they use — not the state of our instrument. Two of the three releases so far follow that; v0.3.0 titles itself with our own scenario coverage, which is a fact about the benchmark rather than about Hookdeck. When nothing shipped, the finding is the title. Sections run Shipped, Discovered, Benchmark. What a reader has a stake in first, repairs to our own instrument last. The website does not group by section, so this is the order of the release page — which is where anyone following a link from a blog post arrives. The notes are written with the `hookdeck-voice` skill loaded. They are public, Hookdeck-branded content, and three sets of them were written without it. The classification rule was already here and correct — Discovered is a *product* finding, an open defect in our own instrument goes in neither section — and it was still misapplied while drafting v0.4.0, which put three instrument findings under Discovered. Stating the sections in reading order puts the rule next to the decision rather than four paragraphs below it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01MQzUoMAwEBJWpEGVvVzSjK --- AGENTS.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index c2dc45c..2cad14c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -242,13 +242,32 @@ The parsed format is three sections of one-line items: ## Shipped - · <where> · #<issue> -## Benchmark +## Discovered - <title> · #<issue> -## Discovered +## Benchmark - <title> · #<issue> ``` +**The title names the product finding or fix**, not the state of our instrument. +A release note is read by someone building on Hookdeck: what changed for them, or +what we learned about the product they are using. "The CLI no longer works behind your +back in a guest project" and "Agents can now authenticate the CLI without a terminal" +are the pattern. "Outpost coverage goes from one scenario to five" (v0.3.0) is not — +it titles the release with our own coverage, which is a fact about the benchmark. When +nothing shipped, title it with the finding. + +**Write the notes with the `hookdeck-voice` skill loaded.** They are public, +Hookdeck-branded content that a blog post or changelog entry links to, and they were +written three times without it. American English, no hype vocabulary, specific over +generic, honest about maturity. + +**In that order: Shipped, Discovered, Benchmark.** What a reader has a stake in comes +first — what changed for them, then what we found out about the product — and the +repairs to our own instrument come last. The website does not group by section, so +this is the order of the release page itself, which is where anyone following a link +from a blog post or a changelog entry arrives. + `Shipped` is a change to the product, the docs or the skills. `Benchmark` is a repair to our own instrument, and only ones that have shipped. `Discovered` is a **product** finding — something true of Hookdeck, its docs or its skills that we do not yet From 134b803a3ecb40681fbe4ce20a6df6188af030ef Mon Sep 17 00:00:00 2001 From: Phil Leggetter <phil@leggetter.co.uk> Date: Wed, 2 Sep 2026 13:55:59 +0100 Subject: [PATCH 2/6] Say that a release is a GitHub release, and what it targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The convention said to tag the results commit and that the website reads these releases, and never joined the two: the site resolves the most recent release through the releases API to its tag and reads results/ at that ref, so a bare git tag publishes nothing and the page silently keeps the previous snapshot. Records the command, that lightweight tags are what these are, and that v0.3.0 points at the merge commit of its release PR rather than at a publish commit — the same tree, so it works, but not what the paragraph above it asks for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQzUoMAwEBJWpEGVvVzSjK --- AGENTS.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 2cad14c..0811b17 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -225,6 +225,22 @@ when there is a measured change to report, not on a schedule. commit, so the release points at exactly the data it describes, and `results/runs/<timestamp>.json` is the immutable snapshot behind it. +**It is a GitHub release, not a bare tag.** The website reads the releases API, resolves +the most recent release to its tag, and reads `results/` at that ref — so a tag pushed +without a release publishes nothing, and the page keeps showing the previous snapshot. +Cutting one is a single command against the results commit rather than the branch tip: + +```bash +gh release create v0.4.0 --target <results-commit-sha> \ + --title "<the product finding or fix>" --notes-file <draft> +``` + +Lightweight tags, created by that command; nothing here needs an annotated tag or a +signature. v0.1.0 and v0.2.0 point at their results commits. **v0.3.0 points at the +merge commit of its release PR**, which happens to carry the same tree and so works, +but it is not what this paragraph asks for — check `git log -1 <tag>` names a publish +commit before announcing anything from it. + The notes carry: - the run: id, date, and a link to the workflow run From dfd6a7a8e8ab9609075037d1b2a8cdff6d1ab466 Mon Sep 17 00:00:00 2001 From: Phil Leggetter <phil@leggetter.co.uk> Date: Wed, 2 Sep 2026 14:07:46 +0100 Subject: [PATCH 3/6] Say that the release name and first paragraph are what the page renders The website's changelog card was reading neither: a map of three tags to hand-written titles and blurbs lived in the component, so the release name and notes were ignored and a fourth release would have rendered with no summary. Fixed in hookdeck/website#789, which takes the title from the release name and the summary from the first paragraph. That makes two things about the notes load-bearing rather than stylistic. The name is the card heading, so it has to be short. The first paragraph is the card body, so it has to read as a lede rather than a scene-setter that needs the rest of the paragraph behind it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQzUoMAwEBJWpEGVvVzSjK --- AGENTS.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 0811b17..ac2bbb5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -265,7 +265,10 @@ The parsed format is three sections of one-line items: - <title> · #<issue> ``` -**The title names the product finding or fix**, not the state of our instrument. +**The title names the product finding or fix**, not the state of our instrument, and +it is short — the website renders the release name as the heading of its changelog +card, so eight words is a working ceiling and a wrapped title is the symptom of a +long one. A release note is read by someone building on Hookdeck: what changed for them, or what we learned about the product they are using. "The CLI no longer works behind your back in a guest project" and "Agents can now authenticate the CLI without a terminal" @@ -273,6 +276,12 @@ are the pattern. "Outpost coverage goes from one scenario to five" (v0.3.0) is n it titles the release with our own coverage, which is a fact about the benchmark. When nothing shipped, title it with the finding. +**The first paragraph is the summary the page renders.** The website takes whole +sentences from it up to 120 characters and shows them under the title, so it has to +read as a lede on its own — not a scene-setting sentence that only works with the rest +of the paragraph behind it. Both halves of the card come from the release; nothing +about a release is configured in the website. + **Write the notes with the `hookdeck-voice` skill loaded.** They are public, Hookdeck-branded content that a blog post or changelog entry links to, and they were written three times without it. American English, no hype vocabulary, specific over From 6c713ee067b88efca80454a66636127312d8b006 Mon Sep 17 00:00:00 2001 From: Phil Leggetter <phil@leggetter.co.uk> Date: Wed, 2 Sep 2026 14:16:23 +0100 Subject: [PATCH 4/6] A release title names its subject; it does not make a claim MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The three releases carried sentences — 'The CLI no longer works behind your back in a guest project' — while the website rendered hand-written noun phrases over the top of them. Now that the card reads the release name, the two had to agree, and the noun phrase is the right register: a changelog entry is scanned, so the title names what the release is about and the notes carry the argument. v0.1.0 to v0.3.0 renamed to the copy the page was already showing, which makes hookdeck/website#789 a pure refactor for them: same rendering, one source. Written down because the mistake was mine twice in a row — first a title about our own instrument, then one shaped like a headline. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQzUoMAwEBJWpEGVvVzSjK --- AGENTS.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ac2bbb5..866fc4b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -265,10 +265,17 @@ The parsed format is three sections of one-line items: - <title> · #<issue> ``` -**The title names the product finding or fix**, not the state of our instrument, and -it is short — the website renders the release name as the heading of its changelog -card, so eight words is a working ceiling and a wrapped title is the symptom of a -long one. +**The title is a noun phrase naming the subject, not a sentence making a claim.** +"CLI guest account creation", "No-terminal CLI auth", "More Outpost coverage +scenarios". A title that reads as a headline — "Every number now comes from one run", +"The CLI no longer works behind your back" — is editorial: it argues rather than +names, and it is the wrong register for a changelog entry someone is scanning. +v0.1.0 to v0.3.0 were renamed to this form on 2 September; the sentences they carried +before are what the notes are for. + +**It names the product finding or fix**, not the state of our instrument, and it is +short — the website renders the release name as the heading of its changelog card, so +four or five words is the target and a wrapped title is the symptom of a long one. A release note is read by someone building on Hookdeck: what changed for them, or what we learned about the product they are using. "The CLI no longer works behind your back in a guest project" and "Agents can now authenticate the CLI without a terminal" From 2b096cab24fe6f105a8637f80f546baa9557ea41 Mon Sep 17 00:00:00 2001 From: Phil Leggetter <phil@leggetter.co.uk> Date: Wed, 2 Sep 2026 14:19:23 +0100 Subject: [PATCH 5/6] A release title says what happened to what MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Third attempt at this rule in one afternoon, and the first two are recorded as the counter-examples because I made both. An editorial title argues where a changelog entry should be scanned. A bare noun phrase names the area and drops the verb, so 'No-terminal CLI auth' does not say whether that was fixed, documented or merely found — which is the one thing the line is for. v0.1.0 to v0.3.0 retitled again to carry their verbs. v0.2.0's also corrects what it claims: hookdeck ci already worked, the skill never mentioned it, so the change was documentation rather than a CLI fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQzUoMAwEBJWpEGVvVzSjK --- AGENTS.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 866fc4b..8716a16 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -265,13 +265,16 @@ The parsed format is three sections of one-line items: - <title> · #<issue> ``` -**The title is a noun phrase naming the subject, not a sentence making a claim.** -"CLI guest account creation", "No-terminal CLI auth", "More Outpost coverage -scenarios". A title that reads as a headline — "Every number now comes from one run", -"The CLI no longer works behind your back" — is editorial: it argues rather than -names, and it is the wrong register for a changelog entry someone is scanning. -v0.1.0 to v0.3.0 were renamed to this form on 2 September; the sentences they carried -before are what the notes are for. +**The title says what happened to what.** A verb and its subject: "Fixed CLI guest +account creation", "Documented no-terminal CLI auth", "Expanded Outpost coverage to +five scenarios". Two failure modes, both made here on 2 September before the third +attempt stuck: + +- *Editorial* — "Every number now comes from one run", "The CLI no longer works behind + your back in a guest project". A headline argues; a changelog entry is scanned. +- *Subject with no verb* — "No-terminal CLI auth", "CLI guest account creation". Names + the area and leaves out whether it was fixed, documented or found, which is the only + thing a reader wants from a changelog line. **It names the product finding or fix**, not the state of our instrument, and it is short — the website renders the release name as the heading of its changelog card, so From 84640f7b14c1f5784a16a132f75173355f874bff Mon Sep 17 00:00:00 2001 From: Phil Leggetter <phil@leggetter.co.uk> Date: Wed, 2 Sep 2026 14:21:49 +0100 Subject: [PATCH 6/6] Say what a title does when the release is instrument work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rule contradicted itself within two paragraphs: one named the sentence titles as the editorial failure mode, the next held the same two strings up as the pattern to follow. Both were written today, an hour apart. Replaced with the distinction that actually decides it. A product fix or finding is the headline when there is one. When the release is work on the benchmark, the title says so — promoting a finding to headline a release that fixed nothing sends the reader looking for a fix that is not there, and dressing instrument work as a product change is the same error reversed. Also records that the changelog card is derived from the release rather than configured in the website, which stopped being a hypothetical today. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQzUoMAwEBJWpEGVvVzSjK --- AGENTS.md | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 8716a16..cd17099 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -232,7 +232,7 @@ Cutting one is a single command against the results commit rather than the branc ```bash gh release create v0.4.0 --target <results-commit-sha> \ - --title "<the product finding or fix>" --notes-file <draft> + --title "<verb + subject>" --notes-file <draft> ``` Lightweight tags, created by that command; nothing here needs an annotated tag or a @@ -252,6 +252,13 @@ The notes carry: public copy rather than internal shorthand. Write them for someone who has not read the issues. +**Nothing about a release is configured in the website.** Its changelog card takes the +title from the release name and the summary from the first paragraph of the notes. +That was not true until 2 September: three tags had hand-written titles and blurbs +hardcoded in the component, so the page and the releases it linked to disagreed, and a +fourth release would have rendered with no summary at all — see hookdeck/website#789. +If a card ever looks wrong, the fix belongs in the release, not in the site. + The parsed format is three sections of one-line items: ```markdown @@ -276,15 +283,17 @@ attempt stuck: the area and leaves out whether it was fixed, documented or found, which is the only thing a reader wants from a changelog line. -**It names the product finding or fix**, not the state of our instrument, and it is -short — the website renders the release name as the heading of its changelog card, so -four or five words is the target and a wrapped title is the symptom of a long one. -A release note is read by someone building on Hookdeck: what changed for them, or -what we learned about the product they are using. "The CLI no longer works behind your -back in a guest project" and "Agents can now authenticate the CLI without a terminal" -are the pattern. "Outpost coverage goes from one scenario to five" (v0.3.0) is not — -it titles the release with our own coverage, which is a fact about the benchmark. When -nothing shipped, title it with the finding. +**It is short**, because the website renders the release name as the heading of its +changelog card: four or five words is the target, and a wrapped title is the symptom +of a long one. + +**It says what the release actually did.** A release note is read by someone building +on Hookdeck, so a product fix or a product finding is the headline when there is one. +When the release is work on the instrument — v0.4.0, "Fixed how results are scored and +published" — title it as that. Promoting a finding to the headline of a release that +fixed nothing invites the reader to look for a fix that is not there, and titling +instrument work as though it were a product change is the same mistake pointing the +other way. **The first paragraph is the summary the page renders.** The website takes whole sentences from it up to 120 characters and shows them under the title, so it has to