Changelog

Notable changes to the book and its tooling. The most recent entries are at the top. Dates use ISO 8601 (YYYY-MM-DD).

[Unreleased]

Added

  • Added Swedish (sv-001) as the 30th complete translated locale: all 63 topics and every other section, with matching .locale-peer-id sidecars, identical in content to sv-se. Wired into the site and served at /sv-001/ (alias /sv/).
  • Added Japanese (ja-001), Korean (ko-001), and Dutch (nl-001) as the 27th to 29th complete translated locales: all 63 topics and every other section, with matching .locale-peer-id sidecars, identical in content to ja-jp, ko-kr, and nl-nl. Wired into the site and served at /ja-001/, /ko-001/, and /nl-001/ (aliases /ja/, /ko/, and /nl/).

Added

  • Translated the front-matter, examples, contributing, and project sections (14 files, plus a changelog, a home index.md, and a table of contents per locale) into every translated locale: ar, bn, cy, de, es, fr, hi, id, ja, ko, nl, pt, ru, sv, ur, and zh, with duplicate-pair locales (ar-001/ar-eg and so on) kept identical. Directories use the per-locale names in spec/section-names.json. New tools/gen_translated_nav.py refreshes each translated home page and table of contents from its topic titles, tests/validate.py exempts the translated testing, style-rules, and index documents by peer id, and the site’s scripts/sync-content.mjs maps translated filenames in these sections back to their canonical English names through the .locale-peer-id sidecars.

Changed

  • Dutch (nl-nl): translated the remaining English titles and slugs of topics 9.0, 9.3, and 9.4 (bijlagen, controlelijsten, sjablonen).
  • Welsh (cy-001, cy-gb): terminology aligned with TermCymru: risg (risk, replacing perygl, with gender agreement), cyfnewidiad (trade-off), dangosydd rhagfynegi and dangosydd ôl-fynegi (leading and lagging indicator, replacing hwyrfrydig), cynhwysedd (capacity), dosraniad (distribution), cydberthynas (correlation), allbwn for output in topic 1.3, and cyfradd gadael staff (attrition). Four topic slugs renamed to match.
  • Site: upgraded @lilydesignsystem/svelte-picker-bar to 0.2.0, which adds a search picker to the header bar; it submits to the existing /?<query> site search.
  • Added scripts/generate-sitemap.mjs, run at the end of pnpm build, which writes sitemap.xml from the prerendered pages (canonical locale URLs only, no two-letter alias duplicates) so the Sitemap: line in robots.txt resolves.
  • AGENTS.md is now a short index; details moved to AGENTS/layout.md, style.md, locales.md, and workflow.md.
  • Documentation sweep: refreshed AGENTS.md, index.md, the generated README locale text, spec/index.md, spec/locales.md, and the site’s AGENTS.md and README.md for 27 locales, per-locale section directory names, and the new tooling; added CLAUDE.md (a pointer to AGENTS.md); corrected the stale docs/ paths in both agent skills and made skills/ the canonical copy of .claude/skills/ (checked by the tests).
  • Added llms.txt and llms.json (an AI-agent index of every served locale and topic) to the site’s static/, generated by tools/gen_llms.py (just llms) and checked by the tests.
  • Site home page: the “nine parts” tile list is now a “Contents” nested list of all parts and topics, and the “Goodhart’s law, everywhere” section is removed.
  • Reworded “chapter” to “topic” throughout the book’s prose in every locale (for example “topic 2.1”, “Topics in this part”), using each language’s own word for topic (tema, sujet, Thema, тема, 主題, and so on), and in the spec, the tools’ generated text, and the site’s interface strings. File names, URLs, and the section keys are unchanged.
  • Translated every section directory name under locales/: chapters/ is now topics/ (and its translation in each other locale, e.g. temas/, sujets/, themen/), and es-001’s examples/ is ejemplos/. The names live in spec/section-names.json; the tools, tests, and the site’s content sync read them from there, and the site’s URLs are unchanged.

Changed

  • Revised the Welsh locales (cy-001, cy-gb, kept identical) against the Welsh Government’s TermCymru terminology list: llesiant for well-being, cynhyrchiant for productivity, gwendid/gwendidau for vulnerability, llywodraethiant for governance, cydberthynas for correlation, ôl-groniad for backlog (previously left in English), cost a budd for cost-benefit, and deallusrwydd artiffisial (AI) at the first mention of AI in each topic.

Added

  • Added German (de-001) as the 26th complete translated locale: all 63 topics with matching .locale-peer-id sidecars, identical in content to de-de. Wired into the site and served at /de-001/ (alias /de/).
  • Added Portuguese (pt-001) as the 25th complete translated locale: all 63 topics with matching .locale-peer-id sidecars, identical in content to pt-pt. Wired into the site and served at /pt-001/ (alias /pt/).
  • Completed a full, from-scratch hand translation of all 63 topics into Urdu (ur-001, right-to-left), the 24th complete translated locale, with matching .locale-peer-id sidecars. Every topic was translated directly from the English source, the index (topic 9.7) remaps every internal link to its Urdu filename, and the section directory is موضوعات. Wired into the site and served at /ur-001/ (alias /ur/).
  • Completed a full, from-scratch hand translation of all 63 topics into Indonesian (id-001), with matching .locale-peer-id sidecars. No prior Indonesian locale existed to build from, so every topic was translated directly from the English source, and the index (topic 9.7) remaps every internal link to its Indonesian filename. Wired into the site and served at /id-001/ (alias /id/).
  • Added Russian (ru-001) and Chinese (zh-001) as the 21st and 22nd complete translated locales: all 63 topics each, with matching .locale-peer-id sidecars, identical in content to ru-ru and zh-cn. Wired into the site and served at /ru-001/ and /zh-001/ (aliases /ru/ and /zh/).
  • Added French (fr-001) as the 20th complete translated locale: all 63 topics with matching .locale-peer-id sidecars, identical in content to fr-fr. Wired into the site and served at /fr-001/ (alias /fr/).
  • Added Bengali (bn-001) as the 19th complete translated locale: all 63 topics with matching .locale-peer-id sidecars, identical in content to bn-bd. Wired into the site and served at /bn-001/ (alias /bn/).
  • Added Arabic (ar-001) as the 18th complete translated locale: all 63 topics with matching .locale-peer-id sidecars, identical in content to ar-eg. Wired into the site and served at /ar-001/ (alias /ar/).
  • Added Welsh, Great Britain (cy-gb) as the 17th complete translated locale: all 63 topics with matching .locale-peer-id sidecars, identical in content to cy-001 (the same relationship hi-id has to hi-001). Wired into the site’s SERVED_LOCALE_CODES and served at /cy-gb/.
  • Completed a full, from-scratch hand translation of all 63 topics into Dutch, Netherlands (nl-nl), with matching .locale-peer-id sidecars and passing just test. No prior Dutch locale existed to build from, so every topic was translated directly from the English source. The index (topic 9.7) remaps every internal topic link to its Dutch filename, following the approach used for ar-eg, bn-bd, ko-kr, es-es, pt-pt, ja-jp, ru-ru, fr-fr, and sv-se. Not yet wired into the site.
  • Completed a full, from-scratch hand translation of all 63 topics into Swedish, Sweden (sv-se), with matching .locale-peer-id sidecars and passing just test. No prior Swedish locale existed to build from, so every topic was translated directly from the English source. The index (topic 9.7) remaps every internal topic link to its Swedish filename, following the approach used for ar-eg, bn-bd, ko-kr, es-es, pt-pt, ja-jp, ru-ru, and fr-fr. Not yet wired into the site.
  • Completed a full, from-scratch hand translation of all 63 topics into French, France (fr-fr), with matching .locale-peer-id sidecars and passing just test. No prior French locale existed to build from, so every topic was translated directly from the English source. The index (topic 9.7) remaps every internal topic link to its French filename, following the approach used for ar-eg, bn-bd, ko-kr, es-es, pt-pt, ja-jp, and ru-ru. Not yet wired into the site.
  • Completed a full, from-scratch hand translation of all 63 topics into Russian, Russia (ru-ru), with matching .locale-peer-id sidecars and passing just test. No prior Russian locale existed to build from, so every topic was translated directly from the English source. The index (topic 9.7) remaps every internal topic link to its Russian filename, following the approach used for ar-eg, bn-bd, ko-kr, es-es, pt-pt, and ja-jp. Not yet wired into the site.
  • Completed a full, from-scratch hand translation of all 63 topics into Japanese, Japan (ja-jp), with matching .locale-peer-id sidecars and passing just test. No prior Japanese locale existed to build from, so every topic was translated directly from the English source. The index (topic 9.7) remaps every internal topic link to its Japanese filename, following the approach used for ar-eg, bn-bd, ko-kr, es-es, and pt-pt. Not yet wired into the site.
  • Completed a full, from-scratch hand translation of all 63 topics into Portuguese, Portugal (pt-pt), with matching .locale-peer-id sidecars and passing just test. No prior Portuguese locale existed to build from, so every topic was translated directly from the English source. The index (topic 9.7) remaps every internal topic link to its Portuguese filename, following the approach used for ar-eg, bn-bd, ko-kr, and es-es. Not yet wired into the site.
  • Added Spanish, Spain (es-es) as a complete translated locale, all 63 topics, starting from a copy of the existing Spanish (es-001) translation (found on inspection to already be grammatically neutral, with vocabulary mostly already Spain-leaning) and then applying a targeted terminology pass for the remaining minority usages, most notably “incidente” to “incidencia” for this book’s incident-metrics domain, with corresponding gender-agreement fixes throughout. Not yet wired into the site.
  • Completed a full hand translation of all 63 topics into Korean, Korea (ko-kr), with matching .locale-peer-id sidecars and passing just test. The index (topic 9.7) remaps every internal topic link to its Korean filename, following the approach used for ar-eg and bn-bd. Not yet wired into the site.
  • Added Hindi, India (hi-id) as a complete translated locale, all 63 topics, by copying the existing Hindi (hi-001) translation verbatim under the country-tagged locale code, since standard Hindi has no distinct India-specific variant to hand-translate separately. Not yet wired into the site.
  • Completed a full hand translation of all 63 topics into Bengali, Bangladesh (bn-bd), with matching .locale-peer-id sidecars and passing just test. Not yet wired into the site.
  • Completed a full hand translation of all 63 topics into Arabic, Egypt (ar-eg), with matching .locale-peer-id sidecars and passing just test. Not yet wired into the site.
  • Completed a full hand translation of all 63 topics into German, Germany (de-de), with matching .locale-peer-id sidecars and passing just test. Not yet wired into the site.
  • Completed full hand translations of all 63 topics into three locales: Welsh (cy-001), Chinese (zh-cn), and Hindi (hi-001), each with matching .locale-peer-id sidecars and passing just test.
  • Added two more planned translated locales, Welsh - Great Britain (cy-gb) and Chinese (zh-001), to spec/locales-for-global-sharing-with-svelte/locales.tsv and spec/locales.md (thirteen planned locales now, up from eleven), and resolved zh-cn’s previously-undecided endonym to 中文. The site’s LOCALE_LABELS gained matching entries (cy-gb: “Cymraeg (Prydain Fawr)“, zh-001: “中文”, zh-cn: “中文 (中国)”). Still infrastructure only: none of these locales has a locales/<code>/ directory or any translated content yet.
  • Published the book in four locales under locales/: en-gb-oxendict (British English, Oxford spelling; the hand-authored source), en-001 (international English), en-gb (mainstream British English), and en-us (American English). en-001, en-gb, and en-us are mechanically derived from en-gb-oxendict by the new tools/localize.py; see spec/locales.md. docs/ no longer exists; every reference to it across spec/, AGENTS.md, tests/validate.py, tools/gen_nav.py, and tools/stats.py now points at locales/<locale>/.
  • Added two Claude Code skills, software-engineering-metrics-skill (for readers applying the book’s guidance to their own team) and software-engineering-metrics-maintainer-skill (for contributors adding or editing topics), under skills/ and mirrored into .claude/skills/.
  • Moved the published website’s source into this repository as software-engineering-metrics.github.io/, previously a separate repository. It now reads locales/ directly from the repository root rather than a sibling checkout. The root .github/workflows/deploy.yml verifies the site still builds on every push to main, then sends a repository_dispatch to the software-engineering-metrics.github.io repository (kept as a thin deploy shell, since GitHub Pages will only serve that naked domain from a repository with exactly that name), which checks out this monorepo, builds the site, and deploys it.
  • Added the infrastructure for translated (not merely spelling-derived) locales, per the new spec/locales-for-global-sharing-with-svelte/ sub-spec: tools/gen_locale_peer_ids.py assigns every content file a .locale-peer-id sidecar, identical across locales, that a future translated locale (with its own native-script slugs) can use to resolve “this page, in locale X” instead of matching on slug; tests/validate.py checks every sidecar exists and matches. spec/locales.md documents ten planned translated locales (Arabic, Bengali, Welsh, Spanish, French, Hindi, Indonesian, Portuguese, Russian, Urdu, and Chinese - China); none has a locales/<code>/ directory yet, since none is translated yet. On the site, scripts/locales.mjs gained LOCALE_LABELS/localeLabel() (a display name for every planned locale, ready ahead of routing) and sortedLocaleEntries() (the sort order a future locale list should use), and src/lib/i18n.js extracted the UI chrome strings (nav, sidebar, pager, picker, footer, skip-link) that every .svelte component previously hardcoded in English, threaded through via ui(locale), falling back to English for any locale without its own translations.
  • Replaced the site’s hand-built locale-only header control with Lily Design System’s @lilydesignsystem/svelte-picker-bar: a real theme picker (light/dark, via new static/assets/themes/{light,dark}.css), the real locale picker (wired to this site’s URL-based routing rather than its default lang/dir-only behaviour), a text-size picker (Lily’s seven-step scale), and a share picker (email, Mastodon, copy link). Pinned @lilydesignsystem/svelte-{theme,locale,text-size,share}-picker to ^0.1.2 and @lilydesignsystem/svelte-headless to ^0.2.0 via pnpm-workspace.yaml overrides, working around a real published bug in svelte-picker-bar 0.1.0’s own dependency ranges (see each picker’s CHANGELOG.md, “0.1.2”, and this site’s AGENTS.md).
  • Removed the home page’s stat row (parts/topics/“Free Always”) and its “How to read it” section, and replaced the “Browse the nine parts” card grid with a plain bullet list.

Changed

  • Added scripts/generate-sitemap.mjs, run at the end of pnpm build, which writes sitemap.xml from the prerendered pages (canonical locale URLs only, no two-letter alias duplicates) so the Sitemap: line in robots.txt resolves.
  • Added topic 2.8, Lean value stream metrics (lead time, process time, cycle time, percent complete and accurate, and takt time from classical Lean value stream mapping, plus the rolled throughput yield calculation), placed after queueing theory. Pull request and code review metrics moved from 2.8 to 2.9, and the DORA metrics topic moved from 2.9 to 2.10. Updated every affected cross-reference across the book.
  • Renamed Part 2 from “Delivery and Flow Metrics” to “Flow Metrics” and reorganized it around Mik Kersten’s Flow Framework. Added four new topics: 2.1 The Flow Framework, 2.2 Flow items (features, defects, risks, debt), 2.3 Flow velocity and flow distribution, and 2.4 Flow time and flow load. Consolidated the four individual DORA metric topics (deployment frequency, lead time, change failure rate, recovery time) into a single reference topic, 2.9 The DORA metrics framework, moved to the end of the part. Renumbered flow efficiency and work in process to 2.5 and renamed and renumbered the queueing theory topic (formerly 2.9) to 2.7 Queueing theory. Cycle time (2.6) and pull request and code review metrics (2.8) keep their numbers. Updated every cross-reference across the book, the glossary, the formulas reference, the maturity self-assessment, and the front matter to match.

Added

  • Initial release: 45 substantive topics across 8 parts, plus front matter and a 7-topic appendix (Part 9), covering the DORA and SPACE frameworks, code and quality metrics, product and business metrics, reliability and security metrics, and the effect of generative AI on engineering metrics.
  • Repository infrastructure mirrored from the sibling software-engineering-guide project: a specification-driven spec/ (index, structure, conventions, oxford spelling, roadmap), a validation suite in tests/validate.py, a navigation generator in tools/gen_nav.py, a justfile, AGENTS.md with contributor guides under docs/contributing/, CONTRIBUTING.md, and this changelog.
  • spec/structure.md, the canonical topic manifest that the tests check the files against.
  • Two worked examples in docs/examples/: a filled-in metrics charter and a dashboard specification.

History

The book was built from the specification outward: the nine-part structure was declared in spec/structure.md first, then every topic was authored against the shared template in docs/contributing/chapter-template.md, with tests/validate.py enforcing structure and house style throughout.

Conventions for this file

  • Group changes under Added, Changed, Fixed, Removed, or Deprecated.
  • Keep entries short and specific. One line each where possible.
  • Do not use em-dashes here either; the tests check this file too.