---
title: 'Release Notes'
source: 'https://academia.sh/en/courses/technical-writing/release-notes'
course: 'Technical Writing and Documentation'
language: en
updated: '2026-08-17T18:10:49+00:00'
license: 'CC BY-SA 4.0'
---

# Release Notes

The four types describe the product as it is today and none carries time; the raw change list dates 17 of 56 stale claims by version twelve and 0 of the silent ones, while a note that writes what each entry falsifies dates 56 of 56 and 39 of 39 silent ones.

The previous lesson left the generated reference at **13/15** by version six and left
the reader owing a question: **when** did the remaining two drop? The second lesson had
already given this question a name — one of the six reader questions, "what version did
this change in," landed on none of the four types.

This lesson measures the text that closes that gap. What is being asked is not how
release notes get published, but **what they make datable**: a reader looking at a
stale claim — where will they learn which version falsified that sentence?

## The One Text That Carries Time

The four types share a trait that has never yet been named: **all four are written in
the present tense.** A tutorial says how to start today, a how-to says how to do it
today, an explanation says why it is that way today, a reference says which field is of
which type today. All four are texts that erase the past; when a field's type changes,
the reference does not mention the old type, it writes the new one, and the old one is
treated as if it never existed.

This is a correct design for the four types. If history were folded into the
reference, the reader would have to sort out, in every cell, which line belongs to
today, and the reference's one job — fast confirmation — would be lost. But it has a
cost: **because no type carries time, none of them can answer "when did this
change."**

Release notes sit exactly in this gap, and what separates them from the others is not
their content but their **index**. The four types are indexed by subject: the reader
looks for a subject, opens that subject's section. Release notes are indexed **by
time**: the reader looks for a version, opens that version's entry. This is why
release notes are not a fifth type but a separate type standing on a separate axis.

Which pipeline a release ships through, how the note's fields meet the reader's six
questions, and what a tag marks were measured in the Code Review and Team Process
course and are not repeated here. What was measured there was what the note says to
**the reader**; what is measured here is what it does to **the other documents**.

## Two Lists

The same release can be written in two forms, and both are produced from the same
event.

```text
# two forms of the invented product's release notes
# example text, not executed

raw change list
  v6  measurement call's option names were reorganized
  v6  step order in the summary flow changed

meaning list
  v6  measurement call's option names were reorganized
      falsified: reference's parameter lines,
      how-to text's call examples
  v6  step order in the summary flow changed
      falsified: tutorial's third and fourth step
```

The two lists carry the same number of entries. The difference is in a single field:
the second writes, for every entry, **what it falsified.** This field looks like an
ordinary detail but it reverses the direction. The raw list is written **from the
change's side**: it narrates the work done. The meaning list is written **from the
document's side**: it says which sentences are false as of today.

This distinction's effect on the reader has to do with when the note is useful. A
reader looking at the raw list has to **already know** what they are looking for. If an
example blew up on them, they know which call broke and search the list for that call;
once found, they also learn the date. But if nothing has blown up, they have no reason
to look at the list at all, because they do not know which sentence went false. **A raw
list serves a reader who has already heard about the failure.**

## The Length of a Note

The cost of writing a note is its number of entries, and that number is not as large as
it seems. Across twelve versions, surfaces change at their own rates; some versions no
surface changes, and some, more than one changes at once. A note carries an entry only
for versions **where a change happens.** The measurement will also give this entry
count, and the number of claims dated per entry.

**When** an entry gets written is a choice too, and it determines the result. If the
note is written all at once on release day, the writer has to reconstruct, after the
fact, which sentences every change falsified; by that point this information is not
easy to find and in practice does not get written. If the entry is written **at the
moment of the change**, the person who knows the falsified sentence is already there:
the person making the change. The gap looks like a discipline question, but it directly
determines the measured column — in the table below, the only field separating the
meaning list from the raw list is cheap **only at that moment.**

The measurement's assumptions:

- **DT37** — The measured set is the course's shared setup: **56** claims, four types,
  four surfaces, and **17** embedded examples. The mix is not changed.
- **DT38** — Surface frequencies are fixed: signature every **2**, flow every **3**,
  name every **5**, concept every **12** versions. A surface changes once at every
  version that is a multiple of its frequency.
- **DT39** — A claim's **fall version** is the first version at which the surface it is
  bound to changes, and it is known because we wrote the setup. The reader knows it
  only if it was written down.
- **DT40** — Release notes carry one entry for every version at which at least one
  surface changes. Versions where no surface changes carry no entry.
- **DT41** — Three note formats are tried: **no release notes**, **raw change list**,
  and **meaning list**. All three are produced from the same events.
- **DT42** — **With no release notes**, a stale claim cannot be dated; none of the four
  types carries time.
- **DT43** — **The raw change list** writes only what was done. For it to make a claim
  datable, the reader has to have already suspected that claim; in this measurement,
  suspicion only arises when an **embedded** claim breaks.
- **DT44** — **The meaning list** writes the falsified claims into every entry; the
  reader does not need to suspect anything, every stale claim becomes datable.
- **DT45** — For a claim to count as **datable**, it must first be **stale**; a claim
  still true does not enter this column.
- **DT46** — The set's resolution is **1/56**; at the note-entry scale it is **1/9**.

## Measurement

```python
"""Release notes: is a claim's fall datable for the reader when it goes stale.

Part 1 - change events across twelve versions and the note's entry count.
Part 2 - datable stale claims and the silent share, under three note formats.
"""
TYPES = {
    "tutorial":      {"flow": 9, "signature": 3, "name": 2, "concept": 1},
    "how-to":        {"flow": 6, "signature": 5, "name": 2, "concept": 1},
    "explanation":   {"flow": 1, "signature": 1, "name": 1, "concept": 9},
    "reference":     {"flow": 0, "signature": 13, "name": 2, "concept": 0},
}
FREQUENCY = {"signature": 2, "flow": 3, "name": 5, "concept": 12}
EMBEDDED = {"tutorial": 0.60, "how-to": 0.70, "explanation": 0.10,
            "reference": 0.00}
VERSIONS = (2, 3, 5, 6, 12)
LAST = 12


def claims():
    entries, no = [], 0
    for kind, mix in TYPES.items():
        embedded_target = 0
        for surface, count in mix.items():
            for _ in range(count):
                no += 1
                embedded_target += EMBEDDED[kind]
                embedded = embedded_target >= 1 and surface != "concept"
                if embedded:
                    embedded_target -= 1
                entries.append({"no": no, "type": kind, "surface": surface,
                                 "embedded": embedded, "fall_version": FREQUENCY[surface]})
    return entries


def events(last=LAST):
    """Which surfaces change at each version: the entries the note will write."""
    return [(s, [y for y in FREQUENCY if s % FREQUENCY[y] == 0])
            for s in range(1, last + 1)
            if any(s % FREQUENCY[y] == 0 for y in FREQUENCY)]


# Note formats: under what condition they make a stale claim datable.
FORMATS = {
    "no release notes": lambda i: False,
    "raw change list": lambda i: i["embedded"],
    "meaning list": lambda i: True,
}

L = claims()
O = events()
print(f"claims {len(L)} | embedded in example {sum(i['embedded'] for i in L)} | "
      f"change events across twelve versions {sum(len(y) for _, y in O)} | "
      f"note entries {len(O)}")
print("note entries: " + "; ".join(f"v{s}: {', '.join(y)}" for s, y in O))

print()
print(f"{'version':>7s} {'stale':>5s} {'silent':>6s} " +
      " ".join(f"{ad:>23s}" for ad in FORMATS))
print(f"{'':7s} {'':5s} {'':6s} " +
      " ".join(f"{'datable/of silent':>23s}" for _ in FORMATS))
for s in VERSIONS:
    stale = [i for i in L if s // FREQUENCY[i["surface"]] >= 1]
    silent = [i for i in stale if not i["embedded"]]
    row = f"{s:5d} {len(stale):5d} {len(silent):6d} "
    for ad, rule in FORMATS.items():
        t = [i for i in stale if rule(i)]
        ts = [i for i in t if not i["embedded"]]
        row += f" {f'{len(t)}/{len(ts)}':>23s}"
    print(row)

print()
print(f"{'note format':<24s} {'entries':>7s} {'dated claims':>12s} "
      f"{'per entry':>10s} {'of silent':>9s}")
last_stale = [i for i in L if LAST // FREQUENCY[i["surface"]] >= 1]
last_silent = [i for i in last_stale if not i["embedded"]]
for ad, rule in FORMATS.items():
    t = [i for i in last_stale if rule(i)]
    ts = [i for i in t if not i["embedded"]]
    entries = 0 if ad == "no release notes" else len(O)
    share = len(t) / entries if entries else 0
    print(f"{ad:<24s} {entries:7d} {f'{len(t)}/{len(last_stale)}':>12s} "
          f"{share:10.3f} {f'{len(ts)}/{len(last_silent)}':>9s}")
```

```
claims 56 | embedded in example 17 | change events across twelve versions 13 | note entries 9
note entries: v2: signature; v3: flow; v4: signature; v5: name; v6: signature, flow; v8: signature; v9: flow; v10: signature, name; v12: signature, flow, concept

version stale silent        no release notes         raw change list            meaning list
                           datable/of silent       datable/of silent       datable/of silent
    2    22     17                      0/0                     5/0                   22/17
    3    38     24                      0/0                    14/0                   38/24
    5    45     28                      0/0                    17/0                   45/28
    6    45     28                      0/0                    17/0                   45/28
   12    56     39                      0/0                    17/0                   56/39

note format              entries dated claims  per entry of silent
no release notes               0         0/56      0.000      0/39
raw change list                9        17/56      1.889      0/39
meaning list                   9        56/56      6.222     39/39
```

## Reading Datability

The first line gives the note's length: across twelve versions there are **13** change
events, but the note carries only **9** entries. At three versions more than one
surface changes at once — signature and flow at version six, signature and name at
ten, all three at twelve. At three other versions nothing changes, and the note
carries no entry for them.

The top table's left columns give the course's familiar numbers: stale claims are
**22** at version two, **38** at three, **45** at five, **56** at twelve; silent ones
are **17**, **24**, **28**, and **39** respectively. The three columns on the right show
what the reader can date at those same rows.

**With no release notes**, every row gives **0/0**. This is the numeric counterpart of
the lesson's opening claim: no matter how well the four types are written, none can say
when a single claim went false.

**The raw change list** dates **5** at version two, **14** at three, **17** at five,
and stops there. Even though stale claims climb to **56** by version twelve, the raw
list stays stuck at **17**. This is not a coincidence: the embedded claim count is
**17**, and the raw list dates exactly those, not one more. Past version five the raw
list's curve flattens: changes keep happening, the note keeps growing, but the number of
dated claims stays fixed. The effort spent writing the note rises; its return does not.

The real finding sits in the raw list's share on the right: **0/39**. Of the thirty-nine
silently stale claims, **not one** can be dated with the raw change list. The reason is
plain — a raw list serves only a reader who already suspects something, and a silent
claim raises no suspicion in anyone. A raw list is text that does nothing **unless the
reader already knows**; for a reader who does not know, it does nothing at all.

**The meaning list** dates the entire stale count at the same rows: **22/17**,
**38/24**, **45/28**, and **56/39**. The last column gives this in a single ratio —
**39** of the thirty-nine silent claims become datable.

The bottom table measures the cost, and it holds the lesson's most practical result.
**Both formats carry 9 entries.** The meaning list is not a longer note; it is the same
nine entries with one extra field written into them. In exchange, dated claims per
entry climb from **1.889** to **6.222** — more than three times. The writing order can
be said in one sentence: **it is not enough to write what was done to an entry; what it
falsified has to be written too.**

This is the first mechanism in the course that reaches silent staleness, and how it
gets there matters. What made silent staleness invisible was that no signal came from
the document itself. The meaning list draws its signal not from the document but from
**the change itself**: which sentences went false is known at the moment the code
changes, not afterward. What the note holds is that moment. If it is not written, it is
lost and can never be produced again.

## What the Note Does Not Close

The table says what the note does; what it does not do also needs writing, because the
**56/56** picture promises more than it delivers.

First: dating is not fixing. The meaning list tells the reader "the reference's
parameter line went false at version six"; it does not say **what the correct value
is.** The reader learns the wrong, not the right. This is still a large gain — knowing
something is wrong is better than believing it is right — but it does not move the
claim back into the true column. In the table, the **true** column never changes under
any note format; what changes is only how visible the stale one is.

Second: the note's reader is not the document's reader. Whoever follows release notes
already uses the product. A reader arriving for the first time today does not read past
notes; for them the document is still timeless, and nothing but the **17** embedded
claims gives them any warning. The meaning list makes staleness visible **for the
maintainer**, not for the **new reader**.

Third: a note is only as correct as it is written, and it is itself a document. The
"falsified" field in its entries depends on the document's structure at the moment it
was written; when sections get reorganized, that field goes stale too. The note itself
was kept outside this measurement, but in a real repository it also enters the counted
set.

## Summary

- The four types are written in the present tense and indexed by subject; release
  notes are a separate type indexed **by time**, and only they close the "what version
  did this change in" question.
- Thirteen change events across twelve versions become **9** note entries; some
  versions see more than one surface change at once, some see none.
- With no release notes, **0/56** of stale claims are datable; with the raw change
  list, **17/56** — equal to the embedded claim count — and it does not grow further by
  version twelve.
- The raw change list dates **0** of the **39** silently stale claims; it serves only a
  reader who has already heard about the failure.
- The meaning list dates **56/56** with the same **9** entries and **39/39** of the
  silent ones; dated claims per entry climb from **1.889** to **6.222**.
- The gap is not in entry count but in the **falsified-claims** field written into an
  entry; this information exists at the moment of change and cannot be produced
  afterward if not written down.

## Next Step

This lesson closed one of the reader's two unanswered questions. The second remains,
and it is asked far more often than the first: **"why is this not working?"** The
reader arriving with this question knows neither a subject name nor a version number;
all they have is a **symptom** — an error line, an empty output, a result other than
expected. What they have is only what the product showed them, and what it showed
matches no section heading in the document. The next lesson compares the reader
questions a symptom-first text covers against those a concept-first text covers, and
names the boundary troubleshooting content cannot reach.
