Skip to content

Architecture decision records

An ADR is a short note recording one decision: what we chose, why, and what it costs us. One file, numbered, never deleted. If a decision is reversed later, the old record stays and is marked Superseded by ADR-XXXX, so the reasoning is still readable.

The point is not ceremony. It is that in two years somebody — possibly one of us — will ask "why on earth is it done this way?", and the answer should take one minute to find rather than an afternoon of archaeology. It is also the main defence against the bus factor that left RESTest 1.x hard to maintain.

# ADR-NNNN: <decision, as a short statement>
**Status:** Proposed | Accepted | Superseded by ADR-NNNN
**Date:** YYYY-MM-DD
## Context
What forced a decision. Facts, constraints, measurements.
## Decision
What we are doing. Present tense, unambiguous.
## Consequences
What this buys us, what it costs us, and what it rules out.
## Alternatives considered
What else was on the table and why it lost.

Write an ADR when a choice has more than one defensible answer and would be expensive to reverse: a dependency that will spread through the codebase, a boundary between modules, a file format, a licence. Do not write one for ordinary implementation choices — those belong in the pull request.

Records written while 2.0 was built cite its plan and the files that described its process: milestone codes such as M1.9 in their status lines and amendments, rows of ROADMAP.md, and CLAUDE.md or the reviewer's checklist as they were then. Those files are kept, as they were:

  • for records written while 2.0 was built, at the tag history/2.0-development;
  • for records written after it, such as the later amendments of ADR-0025, at commit 0b17e7b7, the last in which this repository held them.

Plans are no longer kept in this repository (ADR-0030), so records written from now on cite none.

# Decision Status
0001 Record architecture decisions Accepted
0002 Rewrite rather than refactor; Apache-2.0; no 1.x source Accepted
0003 Every module targets Java 21; toolchain on 25 Accepted, amended at M0.2
0004 Multi-module structure and inward dependencies Accepted, amended at M0.2 and on 14 and 30 October 2026
0005 Test cases are data, not generated source code Accepted, amended at M1.1b, M2.2, M10.3 and M11.3, and on 10 and 17 October 2026
0006 One event stream; every interaction persisted Accepted, amended at M1.4, M1.6, M1.7, M11.1, M9.1 and M11.3, and in #325, #327 and #334, and on 10, 19 and 25 October 2026
0007 The parser sits behind our own interface; OAS 2.0, 3.0.x and 3.1.x Accepted, amended at M0.2, in #303 and in #328, reversed at M1.2
0008 Extension points, and no AI-specific abstractions Accepted
0009 The engine never blocks; idle time replaces a throughput floor Accepted, amended twice on 29 October 2026
0010 IDL: relicensed assets, ANTLR4 parser, solver behind an interface Accepted, not yet built (14 October 2026)
0011 Evaluation harness in evaluation/, outside the Maven build — amended at M1.9: in a repository of its own, so evaluation/ was never created Accepted, amended at M1.9, on 9 October 2026 and on 3 November 2026
0012 The canonical model: immutable records, sealed types, recorded gaps Accepted, amended at M1.8, M2.1a and M2.1b, and on 17, 26 and 29 October 2026
0013 Where input values come from, and how a campaign is put together Accepted, amended at M1.11, M2.7a, M2.4, M2.10a, M9.1, M9.3, M10.1 and M10.3, and on 10, 12, 13 and 25 October 2026
0014 A reply is judged against the specification document itself Accepted, amended at M1.8 and on 10, 17, 19 and 22 October 2026
0015 One command, a budget spent in full, and what an exit code means Accepted, amended at M1.7, M1.8, M2.7a, M2.10a, M11.1, M9.1, M11.3, M12.1a, M12.1c and M12.1b, in #314 and #344, and on 1, 11, 12, 19, 22, 25 and 28 October 2026
0016 A fault: catalogue number as identity, our words as description, classified twice Accepted, amended at M1.10 and on 10, 12, 15, 17, 22 and 29 October 2026
0017 What we take from the tool that won the 2026 competition, and what we refuse Proposed, amended at M9.1, M9.4 and M10.1
0018 A choice between shapes is one more shape Accepted, amended on 10 October 2026
0019 A document's own sample values are read, sent as written, and named in the record Accepted
0020 A dictionary is a named list of values with one key, and the plan decides what each list is for Accepted, amended at M2.7c, M2.4, M2.10a and M8.3, on 1 October 2026, at 2.1, and on 12 and 13 October 2026
0021 A request body is one more value, and what the API returns is reused leaf by leaf Accepted, amended at M2.5b, M9.2, M9.5, M9.7, M9.8 and M9.9, at 2.1, and on 12 October 2026
0022 The characters a value is made of are read where its length already is, and the regular expressions are somebody else's Accepted, amended at M9.6, at 2.1, and on 12 October 2026
0023 A plan is an ordered list of named sources, and the order is the preference Accepted, amended at M9.1, M10.1 and M10.3, and on 1, 12 and 13 October 2026; its §5 superseded by ADR-0034
0024 v2.0 is the version submitted to the 2027 competition, and what that leaves for 2.1 Accepted, amended on 3, 4, 5, 11 and 12 October 2026
0025 The numbers somebody decided live in one settings object, layered from four sources, and never in the plan Accepted, amended at M11.1, M9.1, M10.1, M10.3, M8.5, M11.2, M12.1b, M9.5, M9.6, M9.7, M10.4-M10.7 and M9.8-M9.9, at 2.1, and on 1, 12, 13, 14, 15, 17, 22, 25, 28 and 29 October 2026
0026 A run opens with every operation once, in five steps, and one part of the tool owns the clock Accepted, amended at M10.3 and on 28 October 2026
0027 A request the API accepted is sent again with one thing changed, and says what it broke Accepted, amended at M10.2, M8.5 and M10.4-M10.7, and on 12, 13, 15 and 17 October 2026
0028 A creation may start a short series about the thing it made, and each series asks one question Accepted, amended at M11.2 and on 12 and 13 October 2026
0029 A key is handed over by the person running the tool, sent where the document says, and hidden in everything the run writes Accepted, amended at M12.1c and on 10 and 25 October 2026
0030 The process RESTest is built with lives outside the repository, and AGENTS.md is the contract it relies on Accepted, amended on 3 November 2026
0031 The manual is the Markdown GitHub shows, and a release carries no PDF of it Accepted, amended on 5 November 2026
0032 A release is a draft until its image and archives are checked, and RESTest starts through the archive's launcher Accepted, amended on 13, 23, 27 and 30 October and 1 November 2026
0033 A dictionary file is written by operation and place Accepted, amended on 13 October 2026
0034 Version 2 of the plan's format: a strategy says its kind, a source has two forms, a group is a map of weights Accepted
0035 The dictionary and the plan have published JSON Schemas, held to their readers Accepted
0036 Kinds of fault RESTest numbers itself: F920 and F921, in the range the catalogue leaves to tools Accepted
0037 Every fault is an error or a warning, and a run fails on its errors Accepted
0038 report.json says how a run went over the time it was given Accepted, amended on 25 October 2026
0039 The HTML report: one page beside report.json, drawn in the browser from the whole of it, fetching nothing Accepted
0040 RESTest is installed with Homebrew from a tap of its own, by a formula that brings its Java and is written into the tap once a release is published Accepted
0041 A run stops sending when the API answers 401 to every request of its opening lap, and ends with 5 Accepted
0042 An operation the API asks to be left alone is left alone, and the whole API once a second one is Accepted, amended on 29 October 2026
0043 A run can be given a rate to keep to, in one line, and keeps to it evenly where it sends Accepted
0044 RESTest's modules are on Maven Central as es.us.isa.restest, uploaded with a release and published there by a person; their POMs name exactly what the archive carries, and their Java code is no part of the promise Accepted
0045 RESTest is run with jbang from a catalog of the ISA group's own, whose alias names RESTest on Maven Central and is written once a release is published Accepted
0046 A skill in the open format of agent skills teaches a coding agent to use RESTest; it ships with every release as the JSON Schemas do, ends the page for coding agents word for word, and is held to the tool by a test Accepted
0047 The documentation is a website, built from a released version's files as they are by a repository of its own, and moved on to each release once it is published; a test holds the pages to the shape the site reads Accepted