Menu

Conformance

AECS-1 §5 makes a hard determinism claim: threadId “must be identical for all messages in the same conversation, across implementations.” A claim like that is only useful if implementations can check themselves against it — so specs/conformance/ is a small, versioned set of test vectors covering the threading algorithm (§5) and the timestamp rules (§6), independent of any particular implementation or programming language.

This mirrors how other structural specs (CommonMark, JSON:API, JSON Schema) ship fixture suites alongside prose: the prose says what MUST happen, the fixtures say exactly what that means for concrete input.

Fixture format

Each file in fixtures/*.json has the shape:

{
  "description": "human-readable summary of what this fixture exercises",
  "specSection": "AECS-1 §5.1",
  "input": {
    "messageId": "string | null",
    "inReplyTo": "string | null",
    "references": ["string, ..."],
    "from": "string | null",
    "subject": "string | null",
    "date": "string | null"
  },
  "expected": {
    "threadId": "string",
    "metadataDate": "string | null",
    "metadataTimestamp": "number | null"
  }
}

input is deliberately the already-decoded header values (not raw RFC 5322 bytes) — these fixtures test the threading/timestamp algorithm in AECS-1 §5–§6, not MIME parsing, which AECS-1 does not specify byte-for-byte.

The 8 fixtures

File Covers
references-present.json §5 rule 1 — References present, multiple IDs
in-reply-to-only.json §5 rule 2 — no References, In-Reply-To present
root-message.json §5 rule 3 — neither header present, own Message-ID used
fallback-hash.json §5 rule 4 — no valid Message-ID anywhere, SHA-256 fallback
fallback-hash-missing-date.json §5 rule 4 + §5.4 — fallback hash when Date is absent
invalid-reference-skipped.json §5 rule 1 — invalid References entries skipped until first valid ID
angle-brackets-and-whitespace.json §5 requirement — angle brackets stripped, whitespace trimmed before comparison
missing-date.json §6 — absent/unparseable Date header → metadata.date/metadata.timestamp are null

Running the checker

verify.py is an independent reference implementation of §5/§6 — not the SDK, a second, from-scratch implementation — that checks each fixture’s expected values are internally consistent with the spec’s own algorithm:

python3 specs/conformance/verify.py

@mvrx/mail also runs every fixture in packages/mail/test/core.test.mjs via pnpm --filter @mvrx/mail test. Both checkers are CI-gated (.github/workflows/ci.yml) — a fixture with a typo’d expected value can’t merge.

Why two checkers

A single implementation checking its own fixtures only proves that implementation is self-consistent, not that the spec text is unambiguous enough for a second author to reproduce the same behavior from scratch. verify.py is written independently against the spec’s prose, not against @mvrx/mail’s source — if verify.py and @mvrx/mail agree on every fixture, that’s the actual conformance signal, not just internal test coverage.