@@ -95,6 +95,14 @@ clients can share one session manager.
9595 would require real-time waits the suite refuses.
9696- ** ` transports ` ** names the transports a behaviour applies to; omitted means transport-independent.
9797- ** ` issue ` ** carries the tracking link for a recorded gap once one is filed.
98+ - ** ` note ` ** carries free-form context that does not fit ` divergence ` or ` deferred ` .
99+ - ** ` added_in ` ** / ** ` removed_in ` ** bound the spec versions the behaviour exists in, as a half-open
100+ ` [added_in, removed_in) ` window.
101+ - ** ` supersedes ` ** / ** ` superseded_by ` ** link a retired entry to its replacement; the link is
102+ bidirectional and both ends must be versioned.
103+ - ** ` arm_exclusions ` ** carve specific ` (transport, spec_version) ` matrix cells out with a typed
104+ ` ArmExclusionReason ` .
105+ - ** ` known_failures ` ** mark specific ` (transport, spec_version) ` cells as strict xfail.
98106
99107Tests link themselves to the manifest with a decorator:
100108
@@ -126,15 +134,45 @@ This is also the triage key for any rewrite: a test that fails on the new code p
126134divergence note (the rewrite accidentally fixed a known gap — decide whether to keep the fix) or
127135it does not (the rewrite broke something that was correct — fix the rewrite).
128136
129- ### When a new spec revision is released
130-
131- 1 . Update ` SPEC_REVISION ` and walk the new revision's changelog.
132- 2 . For each changed interaction, find its requirements (the IDs use the wire method strings the
133- changelog speaks in), re-audit the tests against the new text, and update ` source ` links and
134- assertions where behaviour legitimately changed.
135- 3 . New interactions get new requirements and new tests; removed interactions get their
136- requirements deleted along with their tests.
137- 4 . A behaviour that is correct under both revisions needs no change beyond the ` source ` link.
137+ ### Spec versions and the era axis
138+
139+ ` SPEC_VERSIONS ` in ` _requirements.py ` is the ordered tuple of protocol revisions the suite
140+ exercises; ` SPEC_REVISION = SPEC_VERSIONS[-1] ` is the newest. The ` connect ` fixture fans out over
141+ ` CONNECTABLE_TRANSPORTS × SPEC_VERSIONS ` , but the grid is filtered per test:
142+ ` pytest_generate_tests ` reads the test's stacked ` @requirement ` marks and calls ` compute_cells() ` ,
143+ which intersects the admissible cells across every cited requirement — a cell survives only if
144+ ** all** of the test's requirements admit it.
145+
146+ What admits or excludes a cell:
147+
148+ - ** ` added_in ` / ` removed_in ` ** gate which spec versions a requirement exists in, as a half-open
149+ ` [added_in, removed_in) ` window. A test runs only on versions inside every cited requirement's
150+ window.
151+ - ** ` arm_exclusions ` ** carve specific ` (transport, spec_version) ` cells out with a typed
152+ ` ArmExclusionReason ` . The reason vocabulary doubles as a re-admission checklist: when the gap
153+ closes, grep for the reason string to find every cell to re-admit.
154+ - ** ` known_failures ` ** keep a cell in the grid but mark it as a strict xfail — the test runs and
155+ must fail; an unexpected pass fails the suite.
156+ - ** ` transports ` ** is descriptive metadata for the non-` connect ` transport-specific suites under
157+ ` transports/ ` and does ** not** drive cell generation. Only ` arm_exclusions ` , ` added_in ` , and
158+ ` removed_in ` filter the grid.
159+ - ** ` supersedes ` / ` superseded_by ` ** link a retired entry to its replacement. ` test_coverage.py `
160+ enforces that links are bidirectional and versioned: the retired entry carries ` removed_in ` , the
161+ replacement carries ` added_in ` .
162+
163+ Node IDs stay ` [transport] ` while ` len(SPEC_VERSIONS) == 1 ` , so today's test IDs are
164+ byte-identical to before the era axis existed. They become ` [transport-version] ` the moment a
165+ second version is appended to ` SPEC_VERSIONS ` .
166+
167+ When a new spec revision lands:
168+
169+ 1 . Append the version string to ` SPEC_VERSIONS ` (and to the ` SpecVersion ` ` Literal ` ).
170+ 2 . Walk the new revision's changelog.
171+ 3 . For each affected requirement: set ` removed_in ` on retired behaviour, add a new entry with
172+ ` added_in ` for its replacement, and link the pair with ` supersedes ` / ` superseded_by ` .
173+ Behaviour that survives unchanged needs nothing beyond a re-audit of its ` source ` URL.
174+ 4 . For requirements that cannot run on the new era's path, add an ` arm_exclusions ` entry with the
175+ appropriate ` ArmExclusionReason ` .
138176
139177## Writing a test
140178
0 commit comments