Where this actually stands

A protocol page that claims to be finished is not telling you anything you can check. This one is deliberately specific about what is measured and what is not.

Specification Implementations Optional features Open H-items Cross-run
1.2a 2 0 12 divergent

The 12 is the count of numbered items (H24–H36, with H30 decided). It did not move although two things happened: H30 was settled and left the list, and F19 was numbered H36 and took its place. The same number, a different twelve. More findings than that are recorded: an implementer records a finding under their own identifier (F7, F-B2) and proposes it for review, but the H-number is assigned by the specification. Some recorded findings are still waiting for one. Which number is correct depends on which is being asked for, and on this page it is the numbered ones.

Decided

Version 1.2a is approved. All twenty-three review items raised during drafting were addressed. The specification has exactly one deliberate gap: the tolerance value that V1 and V4 refer to. It is absent because the measurement that determines it has not been performed, and it will be closed by measurement rather than by discussion.

Measured

The tick arithmetic passes 47 tests with no dependencies, in integers throughout: ct-core pulls in nothing and touches no audio, no network and no browser. The whole suite — ct-core, the client, the clock server and conformance together — is 155 tests, with the rig's calibration another 18 beside it. The measurement rig reads a known 10.0000 ms delay correctly — but only after PHAT weighting was added: unweighted cross-correlation read the same tape as 0.9086 ms, exactly two periods off, with a correlation coefficient of 0.9969 and no warning of any kind. A correct engine holds p95 0.394 ms against a simulated crystal; a concatenating one breaks at p95 12.47 ms and drifts 4.37 ms per hour. A system clock step of 250 ms mid-run threw a drift estimate to −2965 ppm for two minutes when the true figure was +125.

Not measured

Every number that needs an analogue output and a recorder. The accuracy claims above are made against a simulated crystal, which is a calibration and not a measurement, and they are not the tolerance value. Nothing has yet run on two machines across a real network for three hours, which is the length of a set and not a safety margin.

Correction: "blocks" was a prediction, not a measurement

The open-items table used to carry a single column, Blocks, and that was a mistake. The word reported two different quantities as one number:

  • The consequence if implementations differ is a property of the specification, and it can be read from the text.
  • Whether they differ is a property of the implementations, and it cannot be read at all — it has to be run.

Presented as the product of the two, "blocks" is a figure nobody can check. The column is now split, and the measured column says only what has been run.

Measured against two implementations, four items thought to block V4 turned out to be convergent: id as a non-negative integer compared numerically (H25), bpm as an integer (H26), late[] cleared on send (H27), and a parameter's nominal value before the first command (H35). Both implementers arrived at the same answer without consulting each other. The joining message order (H32) passes when run. They are waiting only for ratification.

See The ask for what actually predicts divergence — it is not the size of the consequence.

Why this page says H30 and not H28

H-numbers are assigned by the specification, but the implementers cannot see the register. Two implementers therefore propose the same number for different things — which happened twice in a row. The value of v was proposed as H28, but it is H30; the meaning of minLeadTicks as H29, and it is H34. The specification's own H28 and H29 are different matters: ct.state cannot report the bound §6 refers to, and the smallest message size an implementation must accept.

The collision is nobody's carelessness. It follows from decisions passing through an intermediary, and it is this page's most measurable example of what that intermediary costs.

Interoperability no longer waits for hardware

This is the most recent change to the plans, and it separates the interoperability gate from the hardware gate.

A client that refuses every loadct.refuse with reason missing — and stays silent under V3 is fully conforming. A cross-run against such a client proves what a schema cannot: that two state machines agree about the handshake, the joining order and the application of a snapshot.

It needs no analogue output, no recorder and not one audio file — and it can be run the same day H30 is decided, which is before a two-input interface has even been ordered. Audio is a different gate and different work.

The cross-run stopped at the first message, and that was the gate working

Two independent implementations exist. The second was written from the specification text alone, by an author who has never seen the first implementation's code. Their cross-run does not get past the first message: N16 requires closing the connection when the v values differ, but the specification never stated what the value is. One sent commontime/1, the other commontime/1.2, and the connection closed correctly in both directions.

Neither author changed their value to match the other. That refusal is the point of the exercise: a value agreed between two implementers is a private convention that no third party could reproduce. It belongs in the specification before it belongs in anybody's source file.

The item was recorded as H30, and for a long time it was the only measured blocker.

H30 was decided on 13 September 2026. The value is commontime/1. It is a compatibility token, not a document version — it changes if and only if the wire breaks, and 1.1, 1.2, 1.2a and the coming 1.3 do not change it. The comparison is byte for byte, not parsed as a version number and not normalised. On a mismatch the connection closes with code 4001; a generic 1000 is indistinguishable from a normal close, and the symptom would then be "nothing happens".

The reasoning rests on N16's own logic rather than on either implementer's value. N16 forbids version negotiation and requires closing on mismatch, so if v carried the document version, every editorial correction would sever every running connection. Version 1.2a was a non-normative fix to a single sentence of rationale. And the specification had been showing the answer at the top of every page without stating it: commontime/1 · version 1.2 · approved 13 September 2026 already separates the token from the version typographically.

What the decision changed, and what it did not. One word will not do, because these are two different quantities — the same distinction H25 and H26 taught, now applied to the outcome of their own resolution:

Cross-run
Specification does not block it — N16's gap is closed
Measured divergent — B still sends commontime/1.2, and the decision has not reached B

The decision changed the upper row, not the lower one. The control-plane cross-run is clear as far as the specification goes, but it has not been run and cannot be until B adopts the value — and until then A closes the connection exactly as N16 requires. Audio remains a separate gate after that.

The decision was verified against an implementation, not merely recorded: the value (including that it is not 1.1, 1.2 or 1.2a), the byte comparison against nine near misses — a space at either end, a newline, case twice, commontime/1.0 read as a version number, commontime/10, commontime as a prefix, and B's commontime/1.2 — and close code 4001, together with its falling in the application range 4000–4999. All three as tests.