# LogRecord reference emitters (cross-language)

Decision **D1** of the unified-logging program (`docs/inprogress/UNIFIED_LOGGING_DESIGN.md`)
is: **every Magogi runtime emits the one canonical `LogRecord` wire shape** —
Python, Zig (`hrb-*`), and TS/SvelteKit. mgf-common is the source of truth; the
shape is fixed by `mgf.common.observability.LogRecord` and pinned by the golden
artifacts under `src/mgf/common/observability/schema/`:

| Artifact | Purpose |
|---|---|
| `log_record_fixture.jsonl` | canonical conformance fixture — one line per schema corner; the byte-exact golden every language matches |
| `log_record_schema.json` | language-neutral manifest — schema version, core keys, full emit order, per-field type/omit rules, serialisation rules |

Regenerate both with `uv run python tools/gen_log_record_schema.py`. The Python
authority test (`tests/unit/observability/test_log_record_conformance.py`, **OB-10**)
fails if they drift from the source or the live dataclass.

## Reference clients

| Language | Path | Conformance test | Verified |
|---|---|---|---|
| Python | `mgf.common.observability.LogRecord` (native) | `tests/unit/observability/test_log_record_conformance.py` | ✅ in mgf-common CI |
| TypeScript | `clients/typescript/logRecord.ts` | `clients/typescript/conformance.test.ts` | ✅ in mgf-common CI (Node ≥ 22) |
| Zig | `clients/zig/log_record.zig` | `test` block in the same file | ⏳ in **mgf-hrb** CI (Zig 0.16; no Zig toolchain in mgf-common CI) |

Each client's conformance test loads the golden fixture and asserts its emitter
reproduces every line **byte-for-byte**, then re-emits the parsed record and
checks it round-trips. That is the cross-language contract: same bytes, every
runtime.

### Run them

```bash
# Python (the authority)
uv run pytest tests/unit/observability/test_log_record_conformance.py

# TypeScript (no deps — Node's built-in test runner + type stripping)
node --experimental-strip-types --test clients/typescript/conformance.test.ts

# Zig 0.16 (compiled where the toolchain lives — mgf-hrb vendors this module)
zig test clients/zig/log_record.zig
```

## The contract in one breath

Keys in exactly the manifest's `emit_order`, then any unknown (`extra`) keys
appended; compact separators (no spaces); raw UTF-8 (no `\uXXXX` escaping —
matching Python's `ensure_ascii=false`); core keys always present; optional keys
omitted when empty/null/zero; unknown keys from a newer schema preserved
verbatim through a round-trip (OB-09 rule 3). Adding a field is additive +
bumps `LOG_SCHEMA_VERSION`; renaming/removing/retyping is the only breaking move.
