skilldrop-cli 0.16.14 → 0.16.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skilldrop-cli",
3
- "version": "0.16.14",
3
+ "version": "0.16.16",
4
4
  "description": "Portable AI-agent skills, measured against the agent without them. ADRs, PRDs, runbooks, decks and reviews, installable into Claude Code, Cursor, Kiro, and any IDE that takes custom instructions. One command per skill or per role-based pack.",
5
5
  "author": {
6
6
  "name": "Sanjay Ananthanarayan",
@@ -29,8 +29,8 @@ being folded into either neighbour.
29
29
  checks rollback, detection, response, measured targets, data and privacy, comms and
30
30
  exposure, each with evidence. `REVISE` returns to `plan`, and the report names which gap to
31
31
  close and which skill closes it. A missing rollback is `BLOCKED` on its own.
32
- 3. **Announce only once it is ready.** `release-notes` drafts the customer-facing and
33
- internal notes from the git range. Writing them before G3 risks announcing a launch that
32
+ 3. **Announce only once it is ready.** `release-notes` drafts the notes for each audience
33
+ you name from the git range, with nothing the log doesn't say. Writing them before G3 risks announcing a launch that
34
34
  then does not happen.
35
35
  4. **A human decides at G3.1.** The release owner decides whether to ship *now*, given
36
36
  timing, freeze windows and on-call coverage. When that decision is contested, use
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$comment": "RFC-0031. Covers the step between build (ends at merge, G2.1) and operate (starts at instrument). Its gates are G3 and G3.1: the whole number places the loop in the lifecycle (discover G0 through operate G4), and a decimal is a second gate inside the same loop (RFC-0044).",
3
3
  "name": "release",
4
- "version": "0.3.0",
4
+ "version": "0.3.1",
5
5
  "description": "Take merged code to live users through a planned, reversible rollout — plan the phases and the rollback, judge readiness on evidence, draft the release notes, then a human makes the go/no-go call. Use when the user has merged a change and asks how to roll it out, whether they are ready to launch, or for a go/no-go decision.",
6
6
  "entrypoint": "LOOP.md",
7
7
  "kind": "loop",
@@ -1,69 +1,96 @@
1
1
  ---
2
2
  name: release-notes
3
- description: Turn git history between two refs into release notes — a customer-facing version written in reader benefits and an internal Keep-a-Changelog version with commit traceability, breaking changes always first. Use when the user wants release notes, a changelog, "what's in this release", a deploy announcement, or to summarize changes since the last tag.
3
+ description: Write release notes from a git log, a list of merged PRs or rough notes about what changed — for the audience and in the format the user names (a customer changelog page, an email, an in-app "what's new", store text, a CHANGELOG.md entry). Says nothing the input doesn't, writes a vague change only as far as it was described, puts breaking changes and anything the reader must do first, and keeps internal noise and working notes out of the text. Use when the user wants release notes, a changelog entry, "what's in this release", a deploy announcement, or to summarise changes since the last tag.
4
4
  ---
5
5
 
6
6
  # release-notes
7
7
 
8
- Converts commit history into two artifacts with different readers: **customer-facing release notes** (benefits, no commit-speak) and an **internal changelog** (Keep a Changelog format, every line traceable to a commit). The rule that drives everything: write for the reader who didn't make the change.
8
+ **The rule: nothing goes in the notes that the log or the user didn't say.** A release note is
9
+ read as a promise. The agent's habit is to make a vague commit sound finished: "tweaked onboarding"
10
+ becomes "onboarding is now simpler", a half-remembered fix gets a symptom, a reverted feature
11
+ gets announced because its commit is in the range. Each of those reads exactly like a real
12
+ change, and a customer will hold you to it. This skill's job is to write only what the input
13
+ supports, as far as it supports it.
9
14
 
10
15
  ## How to respond
11
16
 
12
- **Four rules come before the steps and outrank them:**
13
-
14
- - **Answer what was asked, first.** Open with the answer, the decision or the artifact, in plain words. Scores, matrices, frameworks and tags come after it, and anything that doesn't change the answer is cut.
15
- - **Use only what you were given.** Don't add facts, names, numbers, incidents, history, steps or sections the input doesn't contain. What you need and don't have is left out of the artifact and listed once at the end under "To confirm".
16
- - **Deliver from what you have.** When the request gives you something to work on, state your assumptions in a line and produce the result. When it gives you nothing to work on, ask for it in one or two plain sentences and say what you will do once you have it.
17
- - **Write for someone who has never heard of this skill.** No skill names, no paths or scripts from this folder, no internal terms, and nothing about how the run was set up. A next step is one plain sentence at the end that describes the work.
18
- - **For this skill:** Write one set of notes for the audience the user named. Add the second, internal version only when they ask for both. Use the product's name only if they gave it, and count commits and pull requests from the list in front of you.
19
-
20
- 1. **Resolve the range.** Default: last tag to HEAD (`git describe --tags --abbrev=0`). If no tags exist, ask for a start ref or take the user's two refs. State the resolved range at the top of the output: "`v1.4.0..HEAD`, 37 commits, 2026-05-02 → 2026-06-10".
21
-
22
- 2. **Gather the raw material.** `git log <range> --no-merges --pretty='%h|%s|%an|%ad' --date=short` for the commit list; `git log <range> --stat` only when a subject line is too vague to classify. Where the `gh` CLI is available and the repo uses PRs, prefer PR titles over commit subjects (`gh pr list --state merged --search "merged:>={date}"`) — they're written closer to reader language. Don't require `gh`; commits alone are enough.
23
-
24
- 3. **Classify every change** into Keep-a-Changelog categories plus one local bucket:
25
- - **Added / Changed / Fixed / Deprecated / Removed / Security** — reader-visible
26
- - **Internal** — refactors, CI, deps, tests; appears in the internal changelog, never in customer notes
27
- - **Needs review** — can't tell what it does from the commit; goes in a list for the user, never guessed into customer notes
28
-
29
- 4. **Hoist breaking changes and migrations to the top** of both artifacts, each with an **Action required** line. A breaking change buried under "Changed" is the cardinal failure of release notes. Detect via `BREAKING`, `!:` conventional-commit markers, migration files, major dependency bumps, and removed public API — and say which signal triggered the flag.
30
-
31
- 5. **Rewrite, don't transcribe.** Each customer-facing line states what the reader can now do or no longer suffers. ✅ *"Fixed a crash when exporting reports with more than 10,000 rows"* — ❌ *"fix NPE in ReportExporter.flush()"*. Drop ticket numbers and author names from customer notes; keep both in the internal changelog with the short hash on every line.
32
-
33
- 6. **Emit both artifacts** with [`templates/release-notes.md`](templates/release-notes.md): customer notes first, internal changelog second, then the **Needs review** list. If the user wants only one artifact, emit that one — but the needs-review list is never optional.
34
-
35
- ## Useful references in this skill
36
-
37
- - [`templates/release-notes.md`](templates/release-notes.md) — both artifact skeletons plus the classification cheat-sheet
17
+ 1. **Find out what actually shipped.** Read the whole range or list before writing a line.
18
+ - A change that was reverted later in the same range did not ship. Leave it out.
19
+ - A later commit can narrow or contradict an earlier one ("partial fix", a figure revised,
20
+ a date moved). Write the final state, not the first claim.
21
+ - Where you have a repo and no list, take the range from the last tag to HEAD
22
+ (`git describe --tags --abbrev=0`, then `git log <tag>..HEAD --no-merges`). Read a commit's
23
+ body or diff only when its subject is too vague to tell what it does.
24
+
25
+ 2. **Find what breaks or needs action, wherever it is said.** A breaking change is often not
26
+ marked: a removed option in a PR description, a renamed setting in a commit body, an old
27
+ endpoint "no longer accepted". Each one goes first, with the step the reader has to take,
28
+ written for how this audience gets the release. Customers of a hosted service upgrade
29
+ nothing; they need to know what stops working and what to do instead. A library's users
30
+ need the version and the migration.
31
+
32
+ 3. **Write only as far as each change was described.** "Fixed a bug in exports" stays that
33
+ vague if that's all the input says. Don't add a symptom, a cause, a number, a date, a
34
+ version, a PR number or a count the input doesn't give. A change you can't tell the meaning
35
+ of stays out of the notes and goes in the short list in step 6.
36
+
37
+ 4. **Write for this reader, in this format.** Use the channel, length and tone the user asked
38
+ for: a customer changelog page, an email, a pop-up of a few lines, store text with a
39
+ character limit, or the repo's own CHANGELOG style if there is one. Say what the reader can
40
+ now do or no longer suffers ✅ *"Exports with more than 10,000 rows no longer fail"*, not
41
+ what the code does ❌ *"fix NPE in ReportExporter.flush()"*. Use the product name only if
42
+ you were given it.
43
+
44
+ 5. **Leave internal work out of anything a customer reads.** CI, refactors, tests, dependency
45
+ bumps, typo fixes and tooling are not news, not even as "various improvements". In an
46
+ internal changelog they may appear if the repo's existing style includes them.
47
+
48
+ 6. **Hand back the notes, then at most a few lines for the user.** The notes are clean: no
49
+ commit range, commit count, hashes, "flagged by" notes, or review lists inside them unless
50
+ the user's format asks for hashes (an internal CHANGELOG often does). After the notes, list
51
+ once, briefly, what you left out and why: changes too vague to describe, claims the log
52
+ contradicts, anything the user should confirm before publishing.
53
+
54
+ 7. **Deliver from what you have.** With a log, a list or notes, write the notes and state any
55
+ assumption about audience or format in one line. Ask first only when there is nothing to
56
+ work from.
38
57
 
39
58
  ## Quality bar
40
59
 
41
- - **Breaking changes are first, with an action.** Every breaking entry has "Action required: …" a reader can execute. No action identifiable → it goes to Needs review, not to the top section unverified.
42
- - **No commit-speak in customer notes.** Class names, function names, internal service names, and ticket IDs are all signals the line wasn't rewritten.
43
- - **Every internal-changelog line ends in a short hash** (and PR number when available). A claim nobody can trace is a claim nobody can verify.
44
- - **Internal noise stays internal.** Dependency bumps, refactors, CI, and test-only changes never appear in customer notes — not even as "various improvements".
45
- - **Nothing is guessed.** A vague commit ("fix stuff", "wip") lands in Needs review with its hash; the skill never invents a user-facing meaning for it.
46
- - **The range is stated.** Refs, commit count, and date span at the top — so a reader knows exactly what window the notes cover.
60
+ - **Nothing in the notes goes beyond the input.** No invented feature, behaviour, symptom,
61
+ figure, date, version, PR number or count.
62
+ - **Reverted and superseded changes don't appear;** the final state does.
63
+ - **Breaking changes and required actions come first,** found from the text as well as the
64
+ markers, with an action that fits how the audience gets the release.
65
+ - **Internal noise is absent from customer text.**
66
+ - **The format, length and tone are the ones the user asked for,** and the notes carry no
67
+ working notes.
68
+ - **Vague items are left out or kept vague, and named once to the user.**
47
69
 
48
70
  ## When to use this skill
49
71
 
50
72
  - ✅ Cutting a release and writing "what's new" for users or customers
51
- - ✅ Maintaining `CHANGELOG.md` between versions
52
- - ✅ A deploy/release announcement for internal stakeholders
53
- - ✅ "Summarize everything merged since the last tag"
73
+ - ✅ A `CHANGELOG.md` entry between versions
74
+ - ✅ A deploy or release announcement for internal stakeholders
75
+ - ✅ "Summarise everything merged since the last tag"
54
76
 
55
77
  ## When NOT to use this skill
56
78
 
57
79
  - ❌ A single PR description — that's one change; use `pr-description-writer`
58
80
  - ❌ Reviewing the changes for quality or risk — that's `devils-advocate` / `sonar-review`
59
- - ❌ Stakeholder narrative about *why* the release matters strategically — feed the notes to `exec-summary`
60
- - ❌ Generating commit messages going forward — this skill reads history, it doesn't write it
81
+ - ❌ A narrative about *why* the release matters strategically — feed the notes to `exec-summary`
82
+ - ❌ Writing commit messages going forward — this skill reads history, it doesn't write it
61
83
 
62
84
  ## Anti-patterns to avoid
63
85
 
64
- - ❌ **Transcribing commit subjects with bullets in front.** That's `git log` with extra steps — the rewrite into reader language is the entire job.
65
- - ❌ **"Various bug fixes and improvements."** Either the fix is worth a line or it's internal; the vague catch-all is neither.
66
- - ❌ **Burying a breaking change** in the middle of "Changed" because the commit didn't shout about it. The detection signals exist precisely for quiet breaks.
67
- - ❌ **Padding a thin release.** Two real changes get two lines. Inflating with internal noise to look substantial erodes trust in every future release note.
68
- - ❌ **Marketing adjectives.** "Blazing-fast", "completely redesigned", "supercharged" — state the measurable change ("export is ~3× faster on large reports") or state nothing.
69
- - ❌ **Silently skipping unparseable commits.** They go to Needs review; the count of skipped commits is part of the output.
86
+ - ❌ **Finishing a vague change.** "Looked at the search thing" becomes "search is faster".
87
+ Keep it as vague as it was, or leave it out and say so.
88
+ - ❌ **Announcing reverted work.** A commit in the range is not a change that shipped.
89
+ - ❌ **Burying a quiet break.** No `!:` marker doesn't mean nothing broke; read the bodies.
90
+ - ❌ **"Various bug fixes and improvements."** Either a fix is worth a line or it's internal.
91
+ - ❌ **The working notes in the text.** Ranges, counts, hashes, "flagged by", a "Needs review"
92
+ table in a customer email.
93
+ - ❌ **A changelog where an email was asked for.** Headings and bullets in a two-paragraph
94
+ member update.
95
+ - ❌ **Marketing adjectives.** "Blazing-fast", "completely redesigned": state the measured
96
+ change the input gives, or nothing.
@@ -5,12 +5,12 @@
5
5
  "id": 1,
6
6
  "prompt": "Write release notes for v2.4.0 from this log (range v2.3.0..HEAD, 2026-08-12 to 2026-09-28):\n\na1b2c3d|feat: bulk CSV import for contacts (#412)\ne4f5a6b|fix: NPE in ReportExporter.flush() when >10k rows (#418)\nc7d8e9f|feat!: remove legacy /v1/contacts endpoint (#420)\n0a1b2c3|chore(deps): bump lodash 4.17.20 -> 4.17.21\n4d5e6f7|refactor: extract ExportService\n8a9b0c1|fix stuff\n2d3e4f5|perf: cache tenant settings, report export ~3x faster (#425)",
7
7
  "assertions": [
8
- "States the range, commit count (7), and date span at the top",
9
- "The removal of /v1/contacts is hoisted to the top of both artifacts with an 'Action required' line and names the !: marker that flagged it",
8
+ "Delivers the notes from the log without stopping to ask who they are for, stating any assumption about the audience in a line",
9
+ "The removal of /v1/contacts comes first, with the step API users must take",
10
10
  "Customer notes contain no commit-speak — no ReportExporter.flush(), class names, ticket numbers, or author names",
11
- "The lodash bump and the ExportService refactor appear only in the internal changelog, never in customer notes, not even as 'various improvements'",
12
- "Every internal changelog line ends with its short hash, plus PR number where present",
13
- "The vague 'fix stuff' commit (8a9b0c1) goes in the Needs review list with its hash, not guessed into customer notes",
11
+ "The lodash bump and the ExportService refactor do not appear in customer-facing notes, not even as 'various improvements'",
12
+ "The notes carry no working notes: no commit range, commit count, hashes or review lists in customer-facing text",
13
+ "The vague 'fix stuff' commit is not given an invented meaning in the notes, and is named to the user outside them",
14
14
  "No marketing adjectives; the performance line states the measured change (~3x faster export) rather than 'blazing fast'",
15
15
  "Does not invent features or fixes not present in the log"
16
16
  ]
@@ -72,6 +72,34 @@
72
72
  "It does not invent crash counts, percentages, a release date for Android, or features that are not in the list",
73
73
  "The store text itself is short: about 100 words or fewer per store"
74
74
  ]
75
+ },
76
+ {
77
+ "id": 6,
78
+ "held_out": "2026-10-17",
79
+ "prompt": "Our next Quillmoor release goes out tomorrow. Quillmoor is our invoicing app for freelancers and small studios, and some of our customers use our API. The git log since the last release is in `git-log.txt`. Write the customer-facing release notes for our public changelog page: Markdown, 200 words max. I want them ready to paste.",
80
+ "assertions": [
81
+ "The webhook payload change (`amount` now an integer in minor units, `client_name` renamed to `client.display_name`) is in the notes and comes before every other change, worded so a customer with a webhook integration can tell they must update their handler",
82
+ "The Swiss QR-bill feature is not presented as part of the release, since it was reverted in the same range",
83
+ "No internal-only work appears in the notes: no CI changes, dependency bumps, test fixtures, the auth/session refactor, feature-flag removal, release checklist, or typo fixes in comments or CONTRIBUTING",
84
+ "The 'misc fixes from Henrike's QA pass' and 'sync stuff' commits are either left out or mentioned no more specifically than general small fixes; no particular behaviour, such as a sync feature, is attributed to them",
85
+ "Does not invent anything absent from the log or request: no version number, release date, PR or ticket number, count of changes, or figure such as how much faster the invoice list is",
86
+ "Covers at least six of these seven customer-visible changes: duplicating an invoice, receipt photos from a phone's browser, the client-portal ZIP download, no more reminders for invoices marked paid offline, the VAT rounding fix, the due date column in CSV export, and the faster invoice list",
87
+ "The pasteable notes are 200 words or fewer and in Markdown, are delivered without first stopping to ask questions, and contain no working notes about what was left out or why"
88
+ ]
89
+ },
90
+ {
91
+ "id": 7,
92
+ "held_out": "2026-10-17",
93
+ "prompt": "I run the Bramblegate Tool Library, it's a volunteer thing where members borrow tools through our little app. My nephew does the app and he did a bunch of stuff this month. From memory:\n\n- you can reserve tools a week ahead now instead of 3 days? I think a week\n- the login code by text message, he fixed that, people were complaining it didn't arrive\n- something about late fees, he changed how they work, I need to check with him but basically you get a reminder before it's late now\n- everyone has to re-accept the borrowing agreement next time they log in because the committee updated it\n- new photos on the tool pages\n- also a lot of backend stuff I don't understand\n\nCan you write the text for the \"What's new\" pop-up members see when they open the app? It's a small box, so 75 words max.",
94
+ "assertions": [
95
+ "Re-accepting the updated borrowing agreement at next log-in comes first in the pop-up text and is stated as something the member will have to do",
96
+ "Does not invent details: no late-fee amounts, no number of days before the due date that the reminder arrives, no reservation window other than a week, no cause for the login problem, no date, and no change that is not in the notes",
97
+ "The late-fee item goes only as far as described, a reminder before an item is late, and does not claim fees were raised, lowered or removed",
98
+ "The 'backend stuff' is not in the pop-up text, and nothing specific is claimed about it",
99
+ "Mentions reserving further ahead, the fixed text-message login code, and the new tool photos",
100
+ "The pop-up text is 75 words or fewer and in plain language for library members, with no developer jargon such as 'backend', 'OTP' or 'SMS verification flow'",
101
+ "Delivers the pop-up text without first stopping to ask for confirmation; any suggestion to check details with the developer sits outside the pop-up text"
102
+ ]
75
103
  }
76
104
  ]
77
105
  }
@@ -0,0 +1,136 @@
1
+ commit 0d1f6b8
2
+ Author: Jun Okafor
3
+
4
+ chore(release): scaffold release checklist
5
+
6
+ commit a4c91e0
7
+ Author: Odile Brandt
8
+
9
+ chore(ci): cache node_modules between workflow runs
10
+
11
+ commit 7d2b33f
12
+ Author: Tomasz Wereszka
13
+
14
+ Revert "feat(invoices): Swiss QR-bill block on PDF invoices"
15
+
16
+ This reverts commit 3e8f10b. The bank validator rejects our reference
17
+ field. Pulling it until we can test against real QR scanners.
18
+
19
+ commit e01f5c9
20
+ Author: Marisol Quintero
21
+
22
+ fix(reminders): stop sending payment reminders for invoices marked paid offline
23
+
24
+ Invoices marked "paid by bank transfer" by hand were still getting the
25
+ automatic reminder email sent to the client.
26
+
27
+ commit 5bb7a20
28
+ Author: Tomasz Wereszka
29
+
30
+ misc fixes from Henrike's QA pass
31
+
32
+ commit c33d9e4
33
+ Author: Jun Okafor
34
+
35
+ chore(deps): bump pdfkit from 0.13.0 to 0.15.1
36
+
37
+ commit 2f6a811
38
+ Author: Marisol Quintero
39
+
40
+ feat(expenses): attach receipt photos to expenses from your phone's browser
41
+
42
+ Camera upload on mobile web. JPG, PNG and HEIC, up to 10 MB each.
43
+
44
+ commit 88e0b4c
45
+ Author: Jun Okafor
46
+
47
+ refactor(webhooks): normalise payload serializer
48
+
49
+ Moves all webhook payloads onto the shared serializer. Side effect:
50
+ `amount` on invoice.created and invoice.paid is now an integer in minor
51
+ units (cents) instead of a decimal string, to match the REST API, and
52
+ `client_name` is renamed to `client.display_name`. Anyone parsing our
53
+ webhooks has to update their handler. There is no compatibility flag.
54
+
55
+ commit 41d7f02
56
+ Author: Tomasz Wereszka
57
+
58
+ test: add fixtures for multi-currency invoices
59
+
60
+ commit 3e8f10b
61
+ Author: Tomasz Wereszka
62
+
63
+ feat(invoices): Swiss QR-bill block on PDF invoices
64
+
65
+ Adds the QR payment slip to the bottom of PDF invoices for clients
66
+ with a Swiss address.
67
+
68
+ commit b9a2e6c
69
+ Author: Odile Brandt
70
+
71
+ sync stuff
72
+
73
+ commit 6c1d8a5
74
+ Author: Marisol Quintero
75
+
76
+ feat(invoices): duplicate an invoice from the invoice menu
77
+
78
+ Copies line items, client and tax settings. The new invoice gets the
79
+ next invoice number and today's date.
80
+
81
+ commit d57e3b1
82
+ Author: Jun Okafor
83
+
84
+ perf(dashboard): faster invoice list for accounts with lots of invoices
85
+
86
+ Paginate server-side instead of fetching every invoice up front.
87
+
88
+ commit 0ae4f9c
89
+ Author: Odile Brandt
90
+
91
+ docs: fix typo in CONTRIBUTING
92
+
93
+ commit f62c0d8
94
+ Author: Marisol Quintero
95
+
96
+ fix(tax): VAT total off by a cent on long invoices
97
+
98
+ Totals on invoices with many line items could be off by 0.01 because
99
+ we rounded each line instead of the total.
100
+
101
+ commit 19b7e44
102
+ Author: Jun Okafor
103
+
104
+ chore: remove unused feature flag new_sidebar_v1
105
+
106
+ commit ab30c6e
107
+ Author: Tomasz Wereszka
108
+
109
+ fix(export): CSV export now includes the due date column
110
+
111
+ commit 7e5d1f2
112
+ Author: Odile Brandt
113
+
114
+ ci: run e2e suite on Node 22
115
+
116
+ commit 2c94b8d
117
+ Author: Jun Okafor
118
+
119
+ refactor(auth): extract session middleware
120
+
121
+ commit 95f0a3c
122
+ Author: Marisol Quintero
123
+
124
+ feat(portal): clients can download all their paid invoices as one ZIP
125
+
126
+ New "Download all" button on the client portal's invoice page.
127
+
128
+ commit 4b6e7d9
129
+ Author: Odile Brandt
130
+
131
+ chore(deps-dev): bump eslint to 9.12
132
+
133
+ commit e8c2a05
134
+ Author: Tomasz Wereszka
135
+
136
+ chore: fix typos in code comments
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "release-notes",
3
- "version": "0.1.2",
4
- "description": "Turn git history between two refs into release notes — a customer-facing version written in reader benefits and an internal Keep-a-Changelog version with commit traceability, breaking changes always first. Use when the user wants release notes, a changelog, \"what's in this release\", a deploy announcement, or to summarize changes since the last tag.",
3
+ "version": "0.2.0",
4
+ "description": "Write release notes from a git log, a list of merged PRs or rough notes about what changed — for the audience and in the format the user names (a customer changelog page, an email, an in-app \"what's new\", store text, a CHANGELOG.md entry). Says nothing the input doesn't, writes a vague change only as far as it was described, puts breaking changes and anything the reader must do first, and keeps internal noise and working notes out of the text. Use when the user wants release notes, a changelog entry, \"what's in this release\", a deploy announcement, or to summarise changes since the last tag.",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
8
  "related": ["devils-advocate", "exec-summary", "pr-description-writer", "sonar-review"],
9
9
  "tags": ["release-notes", "changelog", "git", "release", "deploy", "communication"],
10
- "model": { "tier": "standard", "rationale": "Classifies commits and rewrites them for a reader. The audience translation needs judgment; escalate via large-input on very long ranges." }
10
+ "model": { "tier": "standard", "rationale": "Reads a range for what really shipped and rewrites it for one reader. The audience translation needs judgment; escalate via large-input on very long ranges." }
11
11
  }
@@ -45,7 +45,7 @@
45
45
  {
46
46
  "skill": "postmortem-generator",
47
47
  "you_do": "Paste the incident thread, pager timeline and notes once it is over.",
48
- "you_get": "A blameless postmortem with quantified impact, a UTC timeline showing detection and mitigation gaps, contributing factors, up to eight action items, and runbook deltas phrased as edits.",
48
+ "you_get": "A blameless postmortem at the length you ask for: the cause as the change and the missing check, never a person; who or what noticed first and how late; checkable follow-ups; and the runbook edits the incident showed were needed.",
49
49
  "decide": "Gate G4, a human call: PROCEED closes it, PROCEED WITH CONDITIONS closes it with named follow-ups, REVISE sends the deltas back to the runbook."
50
50
  },
51
51
  {
@@ -1,74 +1,99 @@
1
1
  ---
2
2
  name: postmortem-generator
3
- description: Generate a blameless incident postmortem from raw material (Slack thread, pager timeline, notes) — quantified impact, UTC timeline with detection/mitigation gaps, contributing factors instead of a single root cause, and ≤8 verifiable action items. Use after an incident or outage when the user needs a postmortem, RCA, incident review, or "lessons learned" doc.
3
+ description: Write a blameless incident postmortem from the raw material (chat scrollback, alert history, timeline, notes) for the audience and length the user names — the cause stated as the change and the gap that let it through, never a person even when the notes name one; who or what noticed first and how late; known kept apart from still-unknown; and follow-up actions that close the gap. Invents no times, figures, owners or severities. Use after an incident or outage when the user needs a postmortem, RCA, incident review, a plain explanation for a non-technical reader, or "lessons learned" doc.
4
4
  ---
5
5
 
6
6
  # postmortem-generator
7
7
 
8
- Turns the debris of an incident — Slack scrollback, pager entries, half-remembered timestamps — into a postmortem the next on-caller learns from. Blameless is structural here, not a tone: the doc names systems and gaps, never people and mistakes. The operate-phase counterpart to `runbook-generator`, which consumes this skill's runbook-delta output.
8
+ **The rule: name the change and the missing check, never the person.** Incident notes are
9
+ written in the heat of it: "Dana's deploy broke it", "Sam forgot the flag". The agent's habit
10
+ is to carry that framing straight into the document, and a postmortem that names someone as
11
+ the cause teaches everyone to hide the next mistake. The cause is always a condition: what
12
+ made the error easy to make, hard to catch and quick to spread. People appear only doing
13
+ response work, by role ("the on-call engineer rolled back at 14:32"), and that holds even when
14
+ the user's own message points at someone.
9
15
 
10
- ## How to respond
11
-
12
- **Four rules come before the steps and outrank them:**
13
-
14
- - **Answer what was asked, first.** Open with the answer, the decision or the artifact, in plain words. Scores, matrices, frameworks and tags come after it, and anything that doesn't change the answer is cut.
15
- - **Use only what you were given.** Don't add facts, names, numbers, incidents, history, steps or sections the input doesn't contain. What you need and don't have is left out of the artifact and listed once at the end under "To confirm".
16
- - **Deliver from what you have.** When the request gives you something to work on, state your assumptions in a line and produce the result. When it gives you nothing to work on, ask for it in one or two plain sentences and say what you will do once you have it.
17
- - **Write for someone who has never heard of this skill.** No skill names, no paths or scripts from this folder, no internal terms, and nothing about how the run was set up. A next step is one plain sentence at the end that describes the work.
18
- - **For this skill:** With no timeline, logs or notes to work from, ask for them in two sentences and name the three things you most need. Don't describe your working directory or your template.
19
-
20
- 1. **Ingest the raw material.** Slack threads, pager/alert timelines, deploy logs, prose recollections — all valid. Ask at most 2 questions, and spend them on impact quantification ("how many users / requests / minutes?") — it's the data people forget fastest and the section read first. Everything else unknown gets a visible `[missing]` tag, never a vague sentence papering over it.
21
-
22
- 2. **Strip blame structurally while drafting.** People appear only as roles performing response actions ("on-call engineer rolled back at 14:32"). Errors are attributed to the system that allowed them. ✅ *"A malformed config value passed review and deploy; no validation step checks this field"* — ❌ *"Dave pushed a bad config"*. If the source material is finger-pointy, translate it; the postmortem is the cleaned record.
23
-
24
- 3. **Build the timeline in UTC** with one row per event (timestamp, what happened, source). Then compute and state the two gaps that matter:
25
- - **Detection gap** — impact start → first human aware. If users noticed before monitoring did, say so in those words.
26
- - **Mitigation gap** — detection → impact ended.
27
- The timeline ends at "impact over", not "everyone went to bed"; cleanup goes under follow-ups.
16
+ A second rule sits beside it: **say plainly who or what noticed first, and how late.** If a
17
+ customer, a support ticket or a member of staff found the problem before any alert did, that
18
+ is the most useful sentence in the document: ✅ *"Two teachers reported the gradebook down 40
19
+ minutes before any alert fired."* Don't write "alerting worked" when it didn't.
28
20
 
29
- 4. **Write contributing factors, not a root cause.** Minimum 2, typically 3–5, using "why was that possible?" chains. **"Human error" is banned as a factor** — it is always the start of a question, never the answer: what made the error easy to make, hard to catch, and fast to propagate? Each factor states the condition, not the act.
30
-
31
- 5. **Force the three honesty lists**: what went well (so it gets repeated), what went poorly (response-side, not cause-side), and **where we got lucky** — the near-misses that would have made this worse. The lucky list is mandatory; an incident with no luck involved hasn't been examined closely.
32
-
33
- 6. **Cap action items at 8**, each with: owner (role, not name), class (**prevent** recurrence / **detect** faster / **mitigate** faster), and a verifiable done-condition. ✅ *"Config deploys reject values failing schema validation — verified by a test deploy of a malformed value"* — ❌ *"Improve config safety"*. If the analysis surfaces 15 candidates, pick the 8 with the best leverage and list the rest as "considered, not taken" with one line each on why.
34
-
35
- 7. **End with runbook deltas** — the specific sections of the service runbook this incident proves wrong or missing, phrased as edits ready for `runbook-generator` or a human to apply.
36
-
37
- 8. **Emit with [`templates/postmortem.md`](templates/postmortem.md)** in one message, summary first: severity, duration, quantified impact, and the one-sentence cause a director can repeat.
38
-
39
- ## Useful references in this skill
21
+ ## How to respond
40
22
 
41
- - [`templates/postmortem.md`](templates/postmortem.md) — the full doc skeleton with the gap calculations and action-item table
23
+ 1. **Fit the audience and length they asked for.** "Half a page for the board", "a note for
24
+ customers", "two pages max", "the full incident review": that is the format. A
25
+ short version is what happened, why it was possible, how it was found, and what changes.
26
+ The full form in [`templates/postmortem.md`](templates/postmortem.md) is for when they ask
27
+ for a full review or an incident-review meeting doc.
28
+
29
+ 2. **Build the timeline from the material.** Use the events that changed what users saw:
30
+ impact starts, first noticed, mitigation, impact ends. Use the timezone the material uses
31
+ unless asked otherwise, and state it. Compute the gaps that matter (start to noticed,
32
+ noticed to fixed) only from times you have.
33
+
34
+ 3. **Keep what is known apart from what is still being investigated.** Write the cause the
35
+ evidence supports, and name anything not yet confirmed as open.
36
+
37
+ 4. **Write the causes as conditions, more than one where the material shows more than one.**
38
+ For each: the condition, and why it made the incident possible or worse. ✅ *"A config value
39
+ passed review and deploy; nothing validates that field."* ❌ *"Human error"*, ❌ *"should
40
+ have been more careful"*. Don't invent extra causes to make up a number.
41
+
42
+ 5. **Follow-ups that close the gap.** Each action says what changes and how anyone could tell
43
+ it's done: ✅ *"Config deploys reject values that fail the schema, checked by a test deploy
44
+ of a bad value."* ❌ *"Improve config safety."* Give an owner or date only if the material
45
+ gives one; otherwise write "no owner yet". A few strong actions beat a long list.
46
+
47
+ 6. **Runbook changes, when the incident proved a procedure wrong or missing.** Phrase each as
48
+ a concrete edit to the runbook section it affects, ready for someone to apply. Leave them
49
+ out of a short version for a non-technical audience unless asked.
50
+
51
+ 7. **Say only what the material supports.** No affected-customer count, revenue or SLA-credit
52
+ figure, severity level, owner or time that isn't in it, even when a stakeholder asked for
53
+ one. Where a number was asked for and the material can't give it, say what it does show
54
+ ("12 customers have written in so far") and what would settle it. Never leave
55
+ `[missing]` or blank fields in the document; list what is still unknown once, briefly,
56
+ after it.
57
+
58
+ 8. **Deliver from what you have.** With notes to work from, write it and state any assumption
59
+ in one line. With nothing to work from, ask in two sentences for the timeline, how it was
60
+ noticed, and what was done.
42
61
 
43
62
  ## Quality bar
44
63
 
45
- - **Impact is numbers or `[missing]`.** Duration, users/requests affected, SLO burn, revenue if known. "Significant impact" is not a measurement.
46
- - **No person is named in a causal sentence.** Roles appear in response actions only. One named-blame sentence fails the doc.
47
- - **Detection and mitigation gaps are computed and stated.** They are the two numbers the next incident will be judged against.
48
- - **At least 2 contributing factors, zero of them "human error".** A single root cause means the chain of "why was that possible?" stopped one question early.
49
- - **Every action item is verifiable and owned.** A reader can check it's done without asking anyone's opinion; an item without a done-condition is a wish.
50
- - **"Where we got lucky" is non-empty.** Naming the near-miss is how it gets fixed before it's the next incident's headline.
64
+ - **No person is named as a cause.** Roles appear in response actions only, including when
65
+ the user's notes name someone.
66
+ - **Who or what noticed first is stated,** with the gap to the first alert when the material
67
+ gives both times.
68
+ - **Known and still-open are kept apart.**
69
+ - **Causes are conditions, not "human error",** and come only from the material.
70
+ - **Every action is checkable,** and has an owner only if the material named one.
71
+ - **Nothing is invented:** no figures, times, severities, owners or counts beyond the input.
72
+ - **The length and format are the ones asked for,** and the document has no placeholders.
51
73
 
52
74
  ## When to use this skill
53
75
 
54
- - ✅ After an incident/outage, turning the response scrollback into the postmortem doc
76
+ - ✅ After an incident or outage, turning the response scrollback into the postmortem
55
77
  - ✅ "Write the RCA for yesterday's outage"
78
+ - ✅ A short explanation of what went wrong for a non-technical reader
56
79
  - ✅ Preparing the incident-review meeting doc
57
- - ✅ Retroactively documenting an old incident before the details evaporate
58
80
 
59
81
  ## When NOT to use this skill
60
82
 
61
- - ❌ During the incident — mitigate first; the postmortem starts when impact ends
62
- - ❌ A performance-management record — the doc is structurally blameless; misusing it kills honest reporting
63
- - ❌ Project retrospectives with no production incident — different ritual, different doc
64
- - ❌ Writing the runbook itself — emit the deltas and hand to `runbook-generator`
83
+ - ❌ During the incident — mitigate first; live updates to stakeholders are `incident-comms`
84
+ - ❌ A performance-management record — the document is blameless by design; using it to blame kills honest reporting
85
+ - ❌ A project retrospective with no production incident
86
+ - ❌ Writing the runbook itself — hand the runbook changes to `runbook-generator`
65
87
 
66
88
  ## Anti-patterns to avoid
67
89
 
68
- - ❌ **Single root cause.** "The config was wrong" explains nothing about review, validation, deploy gates, or blast radius — the four places to actually fix.
69
- - ❌ **"Human error" / "should have been more careful".** Careful is not a control. Name the missing guardrail instead.
70
- - ❌ **The 20-item action list.** It signals diligence and delivers nothing; nobody finishes it and the P1s drown.
71
- - ❌ **Timeline theater.** Forty rows of who-said-what-in-Slack instead of the ten events that changed system state.
72
- - ❌ **Quiet heroics as a fix.** "An engineer noticed by luck at 2am" is a detection gap wearing a cape — the action item is monitoring, not gratitude.
73
- - ❌ **Skipping the postmortem because impact was "minor".** Near-misses are the cheapest lessons; severity gates the meeting, not the doc.
74
- - ❌ **Showing the machinery.** The reply and the artifact are for the person who asked. Don't mention this skill, its files, templates, caps or internal terms, or that the run is non-interactive. Name another skill once, at the end, as a suggested next step, never inside the artifact.
90
+ - ❌ **Copying the blame from the notes.** "The outage was caused by X's change" — rewrite as
91
+ the change and the missing check.
92
+ - ❌ **"Alerting worked" when a customer found it first.** The detection gap is the finding.
93
+ - ❌ **Filling the template.** Severity rows, SLO burn, "where we got lucky" and owner columns
94
+ on a half-page note for a head teacher.
95
+ - ❌ **Placeholders in a document meant to ship.** `Severity: [missing]` goes nowhere; list
96
+ unknowns after the document.
97
+ - ❌ **Invented owners, dates and numbers** to make actions look tracked or impact look
98
+ measured.
99
+ - ❌ **The 20-item action list.** Nobody finishes it and the important ones drown.
@@ -72,6 +72,33 @@
72
72
  "It says the problem was noticed through helpdesk calls about 15 minutes after the change went live, and does not invent a monitoring alert or page",
73
73
  "At least one follow-up action addresses checking a DNS change right after it is made, lowering the TTL before a change, or avoiding changes around registration, written so someone can tell whether it was done"
74
74
  ]
75
+ },
76
+ {
77
+ "id": 6,
78
+ "held_out": "2026-10-17",
79
+ "prompt": "I was incident lead for INC-0412 at Quillmere (we make invoicing software for small businesses). Everything I have is in timeline.md (my notes), incident-channel.txt (the chat export) and alerts.csv. Write the incident review for the leadership team's Monday meeting. They are not engineers, so plain English, and keep it under 450 words. Ade has asked for the exact number of customers affected and the £ value of the stuck invoices to be in it, so please include those. Save it as incident-review.md.",
80
+ "assertions": [
81
+ "No named person (Tomasz or anyone else) is described as the cause of the incident or as at fault; the cause is put in terms of the configuration change and the checks that did not catch it",
82
+ "It says the problem was first noticed by customers through support tickets (from about 14:31), before any alert fired at 14:58, and does not describe the incident as detected by monitoring",
83
+ "It does not state 15:35 as the time service was restored without qualification; it uses the deploy and monitoring record (rollback finished 15:47, processing back to normal around 15:52) or says the sources disagree",
84
+ "The database failover is not presented as a cause (it may appear only as an early theory that was ruled out); the drop in workers from the configuration change is given as the established trigger, and the open questions (whether dead-lettered payment updates were lost, how many already-paid clients got an overdue reminder) are labelled as still being investigated rather than stated as settled",
85
+ "It does not state a number of affected customers or a pound figure for stuck invoices, and does not invent any other time, figure, owner or incident severity level absent from the material; it tells leadership those numbers are not yet known rather than estimating them",
86
+ "Follow-up actions address the gaps the material shows: a check on consumer configuration values before or during deploy, and an alert on payment processing delay that would fire before customers notice; each is concrete enough that someone could later tell whether it was done",
87
+ "incident-review.md exists, is under 450 words, reads in plain language for a non-engineering leadership audience, and the reply delivers it without stopping to ask questions first"
88
+ ]
89
+ },
90
+ {
91
+ "id": 7,
92
+ "held_out": "2026-10-17",
93
+ "prompt": "ugh ok. run a small online yarn shop (Wrenmoor Yarn Co, me + 2 staff). checkout on the site was broken over the weekend. last order came in sat about 9am, then nothing. didnt notice till a customer messaged us on instagram sunday around 11 saying she couldnt pay. think it was the shipping plugin, it auto updated friday night maybe? rolled it back sun afternoon and orders started coming through again. jamie says she clicked update on something friday but not sure what. probably lost a few orders. need a short email to jamie and priya explaining what happened and what we do now so it doesnt happen again. keep it short",
94
+ "assertions": [
95
+ "It does not blame Jamie or anyone else for the outage; if the update she clicked is mentioned, it is framed as how updates are handled in the shop, not as her fault",
96
+ "It says plainly that the problem was found because a customer messaged on Instagram on Sunday around 11, not by any check or alert",
97
+ "It keeps what is known (checkout stopped working some time after the last order around 9am Saturday; rolling back the shipping plugin brought orders back) apart from what is not (which update caused it and when, exactly when checkout broke, how many orders were missed)",
98
+ "It does not invent a start or fix time, a number of lost orders, a money figure, or plugin details that are not in the message",
99
+ "Follow-up actions are small enough for a three-person shop and address at least two of the gaps: how plugin updates happen (for example turning off automatic updates, or updating only when someone can test), checking checkout works after any update, and some way to notice when orders stop coming in",
100
+ "It is a short email to the two staff, under about 250 words, in plain language without technical jargon, delivered without asking for more information first"
101
+ ]
75
102
  }
76
103
  ]
77
104
  }
@@ -0,0 +1,4 @@
1
+ time_utc,alert,level,state,notes
2
+ 14:58,webhook-consumer queue depth > 50000,warning,firing,
3
+ 15:01,webhook-consumer queue depth > 50000,page,firing,paged on-call (Jonas)
4
+ 15:52,webhook-consumer queue depth > 50000,page,resolved,
@@ -0,0 +1,27 @@
1
+ Chat export, Thursday 8 October (times UTC)
2
+
3
+ ==== #support-escalations ====
4
+ [14:31] Marta (Support): heads up, ticket 88213. Customer says their client paid an invoice by card about 20 min ago and it still shows "awaiting payment" in Quillmere. Anyone seen this?
5
+ [14:44] Marta (Support): two more like it now (88219, 88224). Feels like a pattern?
6
+ [14:52] Jonas (Eng): looking
7
+
8
+ ==== #deploys ====
9
+ [14:07] deploybot: webhook-consumer deploy #4471 finished (config: consumer pool tuning), author tomasz, reviewer jonas
10
+
11
+ ==== #inc-0412 ====
12
+ [15:02] Rhiannon: declaring incident. paid invoices not flipping to paid. queue depth alert firing on webhook-consumer.
13
+ [15:06] Jonas: it's the DB failover from this morning, 100%. replica lag is making the status writes fail. seen this exact thing before.
14
+ [15:09] Ade (VP Customer Success): how many customers are affected? I need an exact number and the £ value of the stuck invoices for the board update
15
+ [15:12] Rhiannon: @Ade not known yet, we'll get you what we can
16
+ [15:14] Jonas: hmm, replica lag is flat, under 1s all afternoon, and the status writes that do arrive are succeeding. so not the db. I was guessing, sorry
17
+ [15:19] Kasia: consumer throughput dropped off a cliff at ~14:07. only 4 workers running, normally 40. deploy #4471 changed pool_size from 40 to 4
18
+ [15:25] Rhiannon: ok that's it. rolling back #4471
19
+ [15:31] deploybot: webhook-consumer rollback to #4470 started
20
+ [15:47] deploybot: webhook-consumer rollback to #4470 finished
21
+ [15:52] Kasia: throughput back to normal, 40 workers. backlog draining
22
+ [15:58] Kasia: some Paygrove webhooks went to the dead-letter queue while the backlog was building (their retries timed out). don't know yet whether those payment updates were lost or will be replayed. looking.
23
+ [16:03] Marta (Support): also the 15:00 payment reminder job ran, so some clients who'd already paid probably got a "your invoice is overdue" email. no idea how many yet
24
+ [16:20] Kasia: backlog cleared
25
+ [16:24] Jonas: open q for the review: the PR was reviewed (by me) and passed CI, but nothing in CI checks consumer config values. also we only alert on queue depth and the threshold is high, nothing on how long a payment takes to be processed
26
+ [16:30] Ade (VP Customer Success): still need that customer number and £ figure please, even rough
27
+ [16:41] Rhiannon: DLQ question still open, Kasia on it tomorrow. reminder count also open. closing incident as mitigated.
@@ -0,0 +1,21 @@
1
+ # INC-0412: paid invoices not marked as paid
2
+
3
+ Incident lead notes (Rhiannon). All times UTC, Thursday 8 October.
4
+
5
+ - 14:07 config change to webhook-consumer goes out (Tomasz's PR "tune consumer pool")
6
+ - 14:58 monitoring picked it up, queue depth alert
7
+ - 15:02 I declared the incident, opened #inc-0412
8
+ - 15:06 DB failover from this morning suspected
9
+ - 15:19 Kasia spots worker count dropped
10
+ - 15:25 decision to roll back #4471
11
+ - 15:35 rollback complete, service restored
12
+ - 16:20 backlog cleared
13
+ - 16:41 closed as mitigated
14
+
15
+ Detection: monitoring (queue depth alert).
16
+
17
+ Root cause: Tomasz fat-fingered the pool size (40 -> 4) and pushed it to prod without testing. He broke it. Need to have a word with him about care with prod config.
18
+
19
+ Impact: invoices paid by card or bank transfer through Paygrove stayed "awaiting payment" in Quillmere until the backlog drained. Some customers' clients may have been sent overdue reminders.
20
+
21
+ TODO for the write-up: Ade wants customer count and £ figure.
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "postmortem-generator",
3
- "version": "0.1.2",
4
- "description": "Generate a blameless incident postmortem from raw material (Slack thread, pager timeline, notes) — quantified impact, UTC timeline with detection/mitigation gaps, contributing factors instead of a single root cause, and ≤8 verifiable action items. Use after an incident or outage when the user needs a postmortem, RCA, incident review, or \"lessons learned\" doc.",
3
+ "version": "0.2.0",
4
+ "description": "Write a blameless incident postmortem from the raw material (chat scrollback, alert history, timeline, notes) for the audience and length the user names — the cause stated as the change and the gap that let it through, never a person even when the notes name one; who or what noticed first and how late; known kept apart from still-unknown; and follow-up actions that close the gap. Invents no times, figures, owners or severities. Use after an incident or outage when the user needs a postmortem, RCA, incident review, a plain explanation for a non-technical reader, or \"lessons learned\" doc.",
5
5
  "entrypoint": "SKILL.md",
6
6
  "deps": { "npm": [], "pip": [] },
7
7
  "env": { "required": [], "optional": [] },
8
- "related": ["runbook-generator"],
8
+ "related": ["incident-comms", "runbook-generator"],
9
9
  "handoff": [
10
10
  { "to": "runbook-generator", "when": "the postmortem produced runbook deltas", "purpose": "Apply the deltas as edits to the existing runbook.", "fallback": "If runbook-generator is absent, phrase each delta as a concrete before/after edit so a human can apply it." }
11
11
  ],
@@ -1,67 +1,53 @@
1
- # Postmortem template
1
+ # Full incident review
2
2
 
3
- Summary first — it's the only section most readers finish. All timestamps UTC. Unknowns get `[missing]`, never prose camouflage.
3
+ For when the user asks for a full postmortem or an incident-review meeting doc. Leave out any
4
+ section the material has nothing for; never fill one with a placeholder. List what is still
5
+ unknown after the document, not inside it.
4
6
 
5
7
  ```markdown
6
- # Postmortem: {one-line incident title, symptom-first — "Checkout 500s for EU users", not "Config issue"}
8
+ # Incident review: {symptom-first title — "Checkout failures for EU customers", not "Config issue"}
7
9
 
8
- **Status:** draft | reviewed | actions-tracked
9
- **Severity:** SEV{1–4} · **Date:** {YYYY-MM-DD} · **Author role:** {e.g. incident commander}
10
+ {Date} · {who it is for, if the user said}
10
11
 
11
12
  ## Summary
12
13
 
13
- {3–5 sentences a director can repeat: what broke for whom, for how long, why in one
14
- clause, and the headline fix. No jargon that needs the timeline to decode.}
14
+ {3–5 sentences someone can repeat: what broke for whom, for how long, why in one clause,
15
+ how it was found, and the main change being made.}
15
16
 
16
17
  ## Impact
17
18
 
18
- | Measure | Value |
19
- |---|---|
20
- | Duration (impact start → end) | {Xh Ym} |
21
- | Users / customers affected | {number or %, or [missing]} |
22
- | Requests failed / degraded | {number, or [missing]} |
23
- | SLO / error budget burn | {e.g. "34% of monthly budget", or [missing]} |
24
- | Revenue / contractual | {value, "none known", or [missing]} |
19
+ {What users could not do, for how long, and any figures the material gives. If a figure was
20
+ asked for and the material can't give it, say what it does show and what would settle it.}
25
21
 
26
- ## Timeline (UTC)
22
+ ## Timeline ({timezone})
27
23
 
28
- | Time | Event | Source |
24
+ | Time | What happened | Source |
29
25
  |---|---|---|
30
- | {hh:mm} | {impact begins — state change, not Slack chatter} | {alert/log/deploy} |
31
- | {hh:mm} | {first human aware} | {page/user report} |
32
- | {hh:mm} | {mitigation applied} | … |
26
+ | {hh:mm} | {impact begins} | {alert / log / deploy / ticket} |
27
+ | {hh:mm} | {first noticed, and by whom or what} | … |
28
+ | {hh:mm} | {mitigation} | … |
33
29
  | {hh:mm} | {impact ends} | … |
34
30
 
35
- **Detection gap:** {impact start → first human aware} — {if users reported it before
36
- monitoring fired, say exactly that}
37
- **Mitigation gap:** {detection → impact end}
31
+ **Found by:** {who or what noticed first; the gap to the first alert}
32
+ **Time to fix:** {noticed → impact ended}
38
33
 
39
- ## Contributing factors (2+; "human error" is not one)
34
+ ## Why it was possible
40
35
 
41
- 1. **{Condition, not act}** — {why this made the incident possible/worse; the guardrail
42
- that was absent or didn't fire}
43
- 2. **{…}** — {…}
36
+ 1. **{Condition, not act}** — {why it made the incident possible or worse}
37
+ 2. {…only as many as the material shows}
44
38
 
45
- ## What went well / poorly / where we got lucky
39
+ **Still open:** {causes not yet confirmed}
46
40
 
47
- **Well:** {response behaviors worth repeating}
48
- **Poorly:** {response-side gaps — paging, comms, tooling — not the cause itself}
49
- **Lucky:** {mandatory — the near-miss: "happened at 3am low traffic", "the one engineer
50
- who knew X was awake", "rollback happened to be safe"}
41
+ ## What went well and what didn't
51
42
 
52
- ## Action items (≤8)
43
+ {Response-side only: paging, comms, tooling. Add "where we got lucky" if the material shows
44
+ a near-miss.}
53
45
 
54
- | # | Action | Class | Owner (role) | Done when |
55
- |---|---|---|---|---|
56
- | 1 | {specific change} | prevent / detect / mitigate | {team or role} | {verifiable condition} |
46
+ ## Follow-ups
57
47
 
58
- **Considered, not taken:** {candidate} — {one line why not}
48
+ - {What changes} — done when {how anyone could check}. Owner: {as given, or "no owner yet"}
59
49
 
60
- ## Runbook deltas
50
+ ## Runbook changes
61
51
 
62
- - {Runbook section} → {the edit this incident proves necessary — paste-ready}
63
-
64
- ## Open questions
65
-
66
- - {anything still [missing] that follow-up should resolve, with who can answer it}
52
+ - {Runbook section} → {the edit this incident shows is needed}
67
53
  ```
@@ -1,83 +0,0 @@
1
- # Release-notes templates
2
-
3
- Two artifacts, two readers. Customer notes sell nothing and explain everything; the internal changelog trades polish for traceability.
4
-
5
- ## Artifact 1 — customer-facing release notes
6
-
7
- > Note the deliberate rename for a non-technical reader: the Keep-a-Changelog categories **Added → New** and **Changed → Improved** here; Fixed/Security keep their names. The internal changelog (Artifact 2) uses the canonical Keep-a-Changelog headings.
8
-
9
- ```markdown
10
- # {Product} {version} — {YYYY-MM-DD}
11
-
12
- > Covers {ref}..{ref} · {N} changes
13
-
14
- ## ⚠ Breaking changes
15
-
16
- - **{What broke, in reader terms.}**
17
- Action required: {the exact step — config to change, endpoint to migrate, deadline}.
18
- (flagged by: {signal — `!:` marker / removed API / migration file})
19
-
20
- ## New
21
-
22
- - {What the reader can now do. One sentence, benefit first.}
23
-
24
- ## Improved
25
-
26
- - {What got better, measurably where possible: "export is ~3× faster on reports over 10k rows".}
27
-
28
- ## Fixed
29
-
30
- - {The symptom the reader no longer suffers: "Fixed a crash when …", "Dates no longer shift by one day when …".}
31
-
32
- ## Security
33
-
34
- - {Reader-relevant statement; severity and affected versions; no exploit detail.}
35
- ```
36
-
37
- Rules: no class/function/service names, no ticket IDs, no author names, no "various improvements". A section with nothing in it is deleted, not left empty — except Breaking changes, which when empty becomes the single line "No breaking changes."
38
-
39
- ## Artifact 2 — internal changelog (Keep a Changelog)
40
-
41
- ```markdown
42
- ## [{version}] - {YYYY-MM-DD}
43
-
44
- Range: `{ref}..{ref}` · {N} commits · {N} PRs
45
-
46
- ### Added
47
- - {change} ({#PR}, `{hash}`)
48
-
49
- ### Changed
50
- - **BREAKING:** {change + migration step} ({#PR}, `{hash}`)
51
- - {change} ({#PR}, `{hash}`)
52
-
53
- ### Fixed
54
- - {change} ({#PR}, `{hash}`)
55
-
56
- ### Deprecated / Removed / Security
57
- - {change} ({#PR}, `{hash}`)
58
-
59
- ### Internal
60
- - {refactor / CI / deps / tests — one line each} (`{hash}`)
61
- ```
62
-
63
- ## Needs review (always emitted, both modes)
64
-
65
- ```markdown
66
- ## Needs review — {N} commits not classified
67
-
68
- | Hash | Subject | Why unclear |
69
- |---|---|---|
70
- | `{hash}` | {verbatim subject} | {vague / contradicts diff / can't tell if user-visible} |
71
- ```
72
-
73
- ## Classification cheat-sheet
74
-
75
- | Signal | Bucket |
76
- |---|---|
77
- | New endpoint, flag default-on, new UI surface | Added |
78
- | Behavior or default changed for existing users | Changed (BREAKING if old behavior unobtainable) |
79
- | `fix:`, bug ticket, regression revert | Fixed |
80
- | `chore:`, `refactor:`, `test:`, `ci:`, deps, lockfiles | Internal |
81
- | CVE, auth/authz, input validation, secrets | Security |
82
- | `feat!:`, `BREAKING CHANGE:`, removed public API, schema migration, major version bump of a public SDK | Breaking — hoist to top |
83
- | "wip", "fix stuff", "address comments", empty body + vague subject | Needs review |