feat(event_envelope): close PARTIAL gaps — dichotomy wave

Oracle src/rune/event_envelope.py 303 lines / 8 fns: 5/8 -> 8/8
per scripts/dichotomy_audit.py (name-preserving match). The three
audit-named gaps land as Go surface in src/go/event-bus: ToDict
(to_dict), ToCanonicalDict (to_canonical_dict, incl. the loud
RuntimeError branch for un-bridged envelopes), TestEnvelope
(test_envelope), plus the canonical-bridge classmethod CreateEnvelope
(EventEnvelope.create) they depend on: event_type follows the CHANNELS
prior vocabulary (tool -> tool_result) with the prior-or-channel-or-
source-or-unknown fallback chain.

Parity repairs found on the way (all oracle-pinned):
- classifyAuthority/classifyUrgency were word-splitting: bare 'stop'
  hit the amendment list (oracle: 'stop doing' is the multi-word
  entry; 'Stop everything!' is emergency), 'stop,' and 'unstoppable'
  misfired, and the low-urgency list matched 'when'/'you'/'can'/'no'/
  'rush' as single words (oracle: 'when you can'/'no rush'; bare
  'when' stays normal). Now \b<word>\b semantics with Unicode word
  chars ('stopé' never matches).
- pyQuoteEvent had no ensure_ascii: unicode payloads hashed with raw
  UTF-8 where the oracle hashes \uXXXX escapes — payload_hash
  diverged on every unicode payload.
- createEnvelope now derives text from payload["text"] (oracle
  signature; CLI folds --text in).
- minted ids/timestamps go through the no-clock/no-random seams
  (EE_FROZEN_NOW + per-op uuid counter) — replayable under pins,
  random uuid4-shaped ids in production.

Truth: scripts/gen_event_envelope_truth.py under the
scripts/ee_freeze_seams sitecustomize rig via the shared freeze_truth
harness (83-case envelope, frozen clock + deterministic uuid counter);
byte-identical across regens and freeze_truth --verify x2; embedded
VERBATIM in truth_envelope_test.go TestFrozenEnvelopeTruthReplay +
seam units (\b matcher, ensure_ascii escaping, event_type fallbacks,
loud bridge failure). Live parity 91/91 (scripts/
check_event_envelope_parity.py, PYTHON-json byte compare; negative
control detects divergence). gofmt/vet/go build clean; Python suite
green both pins (25 live + 25 RUNE_*_CORE=python). Dichotomy audit
5/8 PARTIAL -> 8/8 FULL.
This commit is contained in:
Nick committed 2026-10-14 05:20:27 +01:00
1 parent 870130ccc3
commit fb1fd83466
8 files changed
+2922 -91

No files matched your search

+265
View File
@@ -0,0 +1,265 @@
#!/usr/bin/env python3
"""check_event_envelope_parity.py — live oracle-vs-Go parity sweep for
the event_envelope gap closure (#2479, contract factory-gap-ee).
The frozen envelope (truth_envelope.json, 83 cases) pins the surface
byte-identically. THIS script drives the LIVE Python oracle (under the
scripts/ee_freeze_seams rig: frozen clock + deterministic uuid counter)
and the Go binary (`op` mode, EE_FROZEN_NOW + per-op counter reset)
across the same branches, comparing the PYTHON-json byte form of every
result (separators ", "/": ", ensure_ascii, insertion order):
* classify_authority / classify_urgency — \b<word>\b regex semantics
(multi-word "stop doing" vs bare "stop", punctuation adjacency,
unicode word chars: "stopé" never matches, channel defaults).
* create_envelope — legacy path: auto authority/urgency, explicit
overrides, unicode + nested payloads.
* EventEnvelope.create — canonical bridge: CHANNELS prior vocabulary,
channel/source/unknown fallback chain, canonical asdict nesting.
* to_dict — 9-key legacy dict with insertion-ordered payloads.
* to_canonical_dict — schema_version-first key order,
content-addressed payload_hash (ensure_ascii hashing), and the loud
RuntimeError branch for un-bridged envelopes.
* test_envelope — the in-module self-test's captured stdout.
* CHANNELS / AUTHORITY_CLASSES — the constant tables.
Usage: PYTHONPATH=scripts/ee_freeze_seams:src python3 scripts/check_event_envelope_parity.py
[--bin src/go/event-bus/event-bus]
Exit 0 on 100% parity, 1 with the first divergences.
"""
import argparse
import json
import os
import subprocess
import sys
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "src"))
FROZEN_NOW = "2026-10-14T11:22:33.123456+00:00"
import rune.event_envelope as ee # noqa: E402 (rig active via PYTHONPATH)
CLASSIFY_AUTHORITY = [
("hello there", "conversation"),
("Fix the failing test", "work"),
("run the suite", "work"),
("build it", "conversation"),
("test everything", "conversation"),
("create a file", "work"),
("add the guard", "work"),
("remove the shim", "work"),
("update the docs", "work"),
("change the port", "work"),
("Stop everything!", "work"),
("please cancel the order", "work"),
("abort the run", "work"),
("emergency shutdown", "work"),
("halt", "work"),
("Actually, don't modify the microkernel", "conversation"),
("dont do that", "conversation"),
("stop doing that", "work"),
("use rust instead", "work"),
("rather use go", "work"),
("pause for a bit", "work"),
("wait", "work"),
("hold", "work"),
("resume the work", "work"),
("continue the build", "work"),
("go", "work"),
("how is it going", "work"),
("what is the state", "work"),
("status?", "work"),
("progress report", "work"),
("check the log", "work"),
("hello", "work"),
("hello", "conversation"),
("hello", ""),
("stop,", "work"),
("unstoppable force", "work"),
("stopit now", "work"),
("", "work"),
("", "conversation"),
(" FIX it ", "work"),
("café stop", "work"),
("stopé now", "work"),
("Let's BUILD it, then run tests", "work"),
("what about the status, and check twice", "work"),
]
CLASSIFY_URGENCY = [
("anything", "emergency"),
("urgent please", "directive"),
("asap", "directive"),
("immediately", "conversation"),
("do it now", "directive"),
("critical issue", "conversation"),
("when you can", "directive"),
("no rush", "directive"),
("eventually", "conversation"),
("sometime later", "conversation"),
("when", "directive"),
("rush", "directive"),
("hello", "conversation"),
("", "directive"),
("NOW please", "directive"),
("no rushing", "directive"), # \b boundary: "rushing" ≠ "rush"
]
CREATE_ENVELOPE = [
("user", "conversation", {"text": "hello"}),
("user", "work", {"text": "Fix the failing test"}),
("user", "work", {"text": "Stop everything!"}),
("user", "conversation", {"text": "Actually, don't modify the microkernel"}),
("user", "work", {"text": "when you can"}),
("sensor", "sensor", {}),
("user", "work", {"text": "run it"}, "status_query", "t-42", "low"),
("user", "conversation", {"text": "hi", "extra": {"nested": [1, 2.5, None, True]}}),
("user", "work", {"text": "café résumé 🎯", "z": 1, "a": 2}),
("tool", "tool", {"result": "ok", "code": 0}),
]
CREATE = [
("user", "conversation", {"text": "hello"}),
("tool", "tool", {"x": 1}),
("user", "work", {"text": "Fix it"}),
("system", "system", {}),
("bg", "background", {}),
("sensor", "sensor", {}),
("user", "", {}),
("", "", {}),
("user", "unknown-channel", {"text": "hi"}),
]
TO_DICT_STATES = [
{"event_id": "evt_abc123def456", "timestamp": FROZEN_NOW,
"source": "user", "channel": "conversation", "authority_class": "conversation",
"task_id": None, "payload": {"text": "hi"}, "provenance": {}, "urgency": "normal"},
{"event_id": "id-2", "timestamp": "2026-10-14T00:00:00+00:00",
"source": "tool", "channel": "work", "authority_class": "directive",
"task_id": "t-9", "payload": {"n": 1.5, "b": False, "nil": None, "list": [1, "two"]},
"provenance": {"origin": "café", "chain": ["a", "b"]}, "urgency": "high"},
{"event_id": "id-3", "timestamp": FROZEN_NOW,
"source": "user", "channel": "", "authority_class": "",
"task_id": None, "payload": {}, "provenance": {"k": "v"}, "urgency": "low"},
]
TO_CANONICAL = [
("user", "conversation", {"text": "hello"}),
("tool", "tool", {"x": 1, "a": 2.0}),
("user", "work", {"text": "café résumé", "z": 1, "a": [True, None]}),
("system", "system", {}),
("bg", "background", {"nested": {"deep": [{"k": "v"}, 7]}}),
]
def run_go(binpath, env, req):
p = subprocess.run([str(binpath), "op"], input=json.dumps(req),
capture_output=True, text=True, env=env)
if p.returncode != 0:
raise RuntimeError(f"go op {req.get('op')} exited {p.returncode}: "
f"{p.stdout} {p.stderr}")
return json.loads(p.stdout)["json"]
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--bin", default=str(REPO / "src/go/event-bus/event-bus"))
args = ap.parse_args()
binpath = Path(args.bin)
if not binpath.exists():
print(f"Go binary missing: {binpath} (go build -o event-bus . in src/go/event-bus)")
return 1
go_env = dict(os.environ)
go_env["EE_FROZEN_NOW"] = FROZEN_NOW
go_env.pop("EE_UUID_BASE", None)
fails = total = 0
def check(name, oracle_json, go_json):
nonlocal fails, total
total += 1
if oracle_json != go_json:
fails += 1
print(f"DIVERGE {name}:\n oracle: {oracle_json[:300]}\n"
f" go: {go_json[:300]}")
# classify — public fns (no mints; live semantics)
for text, channel in CLASSIFY_AUTHORITY:
check(f"classify_authority:{text[:30]!r}",
json.dumps(ee.classify_authority(text, channel)),
run_go(binpath, go_env, {"op": "classify_authority",
"text": text, "channel": channel}))
for text, authority in CLASSIFY_URGENCY:
check(f"classify_urgency:{text[:30]!r}",
json.dumps(ee.classify_urgency(text, authority)),
run_go(binpath, go_env, {"op": "classify_urgency",
"text": text, "authority_class": authority}))
# create_envelope — rig seam (per-call mint reset) vs op (per-op reset)
for row in CREATE_ENVELOPE:
source, channel, payload = row[0], row[1], row[2]
req = {"op": "create_envelope", "source": source, "channel": channel,
"payload": payload}
if len(row) > 3:
req["authority_class"] = row[3]
if len(row) > 4:
req["task_id"] = row[4]
if len(row) > 5:
req["urgency"] = row[5]
check(f"create_envelope:{source}/{channel}/{str(payload)[:30]}",
json.dumps(ee.ee_create_envelope(*row)),
run_go(binpath, go_env, req))
# EventEnvelope.create — canonical bridge
for source, channel, payload in CREATE:
check(f"create:{source}/{channel}",
json.dumps(ee.ee_create(source, channel, payload)),
run_go(binpath, go_env, {"op": "create", "source": source,
"channel": channel, "payload": payload}))
# to_dict — explicit states (insertion-ordered payloads byte-compared)
for state in TO_DICT_STATES:
full = dict(state)
full["_canonical"] = None
check(f"to_dict:{state['event_id']}",
json.dumps(ee.ee_to_dict(full)),
run_go(binpath, go_env, {"op": "to_dict", "state": full}))
# to_canonical_dict — bridged
for source, channel, payload in TO_CANONICAL:
check(f"to_canonical_dict:{source}/{channel}/{str(payload)[:30]}",
json.dumps(ee.ee_to_canonical_dict(source, channel, payload)),
run_go(binpath, go_env, {"op": "to_canonical_dict", "source": source,
"channel": channel, "payload": payload}))
# to_canonical_dict — unbridged loud failure
state = dict(TO_DICT_STATES[0])
state["_canonical"] = None
check("to_canonical_dict:unbridged",
json.dumps(ee.ee_to_canonical_dict_unbridged(state)),
run_go(binpath, go_env, {"op": "to_canonical_dict_unbridged",
"state": state}))
# test_envelope — captured stdout
check("test_envelope",
json.dumps(ee.ee_test_envelope()),
run_go(binpath, go_env, {"op": "test_envelope"}))
# constant tables
check("channels",
json.dumps(ee.ee_channels()),
run_go(binpath, go_env, {"op": "channels"}))
check("authority_classes",
json.dumps(ee.ee_authority_classes()),
run_go(binpath, go_env, {"op": "authority_classes"}))
print(f"parity: {total - fails}/{total} match")
return 1 if fails else 0
if __name__ == "__main__":
sys.exit(main())
+127
View File
@@ -0,0 +1,127 @@
"""ee_freeze_seams — sitecustomize rig for freezing event_envelope truth.
Auto-imported on interpreter start (PYTHONPATH=scripts/ee_freeze_seams:src)
by BOTH the truth generator (scripts/gen_event_envelope_truth.py) and the
shared harness's --verify mode, so frozen truth is byte-reproducible in any
process (dichotomy wave #2479 gap port, contract factory-gap-ee):
* datetime.datetime is FROZEN to EE_FROZEN_NOW — the oracle stamps
timestamps at TWO clock sites the shared harness's module pin cannot
both reach: the legacy default_factory
(datetime.now(timezone.utc).isoformat()) and the canonical bridge
(rune.orchestration.records._now, bound import). The class patch
below runs before either module imports.
* uuid.uuid4 is a deterministic counter (ci_freeze_seams precedent) —
records.new_id mints "evt_" + uuid4().hex[:12] and the legacy
default_factory mints str(uuid4()). The counter RESETS per seam
helper call so a case's ids depend only on how many mints happen
inside it.
* The module seams (ee_create, ee_create_envelope, ee_to_dict,
ee_to_canonical_dict, ee_to_canonical_dict_unbridged,
ee_test_envelope) are bound onto rune.event_envelope so the shared
harness's getattr(module, fn) can freeze method/classmethod surface:
wrappers run the REAL oracle fns and return JSON-safe asdicts (or
the captured RuntimeError message / stdout bytes for the
loud-failure and print paths).
"""
import contextlib # noqa: E402
import io # noqa: E402
import itertools # noqa: E402
import os # noqa: E402
import sys # noqa: E402
import uuid as _uuid # noqa: E402
from dataclasses import asdict # noqa: E402
_REPO = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.insert(0, os.path.join(_REPO, "scripts"))
sys.path.insert(0, os.path.join(_REPO, "src"))
from freeze_rigs import pin_clock # noqa: E402
# EE_FROZEN_NOW: the pinned instant every clock site reports.
FROZEN_NOW = "2026-10-14T11:22:33.123456+00:00"
pin_clock(FROZEN_NOW)
_MINT = itertools.count(1)
class _DetUUID:
"""uuid4() stand-in whose .hex (records.new_id) and str() (legacy
default_factory) are pure functions of the counter."""
def __init__(self, n: int):
self.hex = f"{n:032x}"
self.int = int(self.hex, 16)
def __str__(self):
h = self.hex
return f"{h[:8]}-{h[8:12]}-{h[12:16]}-{h[16:20]}-{h[20:]}"
def _reset_mint():
global _MINT
_MINT = itertools.count(1)
_uuid.uuid4 = lambda: _DetUUID(next(_MINT)) # type: ignore[assignment]
import rune.event_envelope as _ee # noqa: E402 (after the clock + uuid pins)
def ee_channels():
return _ee.CHANNELS
def ee_authority_classes():
return _ee.AUTHORITY_CLASSES
def ee_create(source, channel, payload):
_reset_mint()
return asdict(_ee.EventEnvelope.create(source, channel, payload))
def ee_create_envelope(source, channel, payload, authority_class=None,
task_id=None, urgency=None):
_reset_mint()
return asdict(_ee.create_envelope(source, channel, payload,
authority_class, task_id, urgency))
def ee_to_dict(state):
# state carries EVERY legacy field explicitly — no default mints, so
# the row is deterministic without a counter reset.
return _ee.EventEnvelope(**state).to_dict()
def ee_to_canonical_dict(source, channel, payload):
_reset_mint()
return _ee.EventEnvelope.create(source, channel, payload).to_canonical_dict()
def ee_to_canonical_dict_unbridged(state):
env = _ee.EventEnvelope(**state)
try:
env.to_canonical_dict()
return {"error": None}
except RuntimeError as e:
return {"error": "RuntimeError", "message": str(e)}
def ee_test_envelope():
_reset_mint()
buf = io.StringIO()
with contextlib.redirect_stdout(buf):
_ee.test_envelope()
return buf.getvalue()
_ee.ee_channels = ee_channels
_ee.ee_authority_classes = ee_authority_classes
_ee.ee_create = ee_create
_ee.ee_create_envelope = ee_create_envelope
_ee.ee_to_dict = ee_to_dict
_ee.ee_to_canonical_dict = ee_to_canonical_dict
_ee.ee_to_canonical_dict_unbridged = ee_to_canonical_dict_unbridged
_ee.ee_test_envelope = ee_test_envelope
+171
View File
@@ -0,0 +1,171 @@
#!/usr/bin/env python3
"""gen_event_envelope_truth.py — shared-harness truth battery for the
event_envelope gap closure (#2479, contract factory-gap-ee).
Uses scripts/freeze_truth.py (the ONE truth law) under the
scripts/ee_freeze_seams sitecustomize rig (PYTHONPATH carries BOTH) to
freeze src/rune/event_envelope.py behavior for the Go port at
src/go/event-bus:
* classify_authority / classify_urgency — the \\b<word>\\b regex
semantics incl. the multi-word amendment list ("stop doing" is NOT
bare "stop"), punctuation adjacency ("stop," still matches), and the
channel-default fallbacks.
* create_envelope — the legacy direct-constructor path (auto authority
+ urgency from payload["text"], explicit overrides, minted
event_id/timestamp under the deterministic uuid + frozen clock).
* EventEnvelope.create — the canonical-bridge classmethod: event_type
follows the CHANNELS prior vocabulary (tool -> tool_result),
channel-not-in-CHANNELS fallback chain, and the nested canonical
record rides in asdict form (_canonical).
* to_dict — the 9-key legacy dict.
* to_canonical_dict — schema_version-1 dict with content-addressed
payload_hash (key order: schema_version first, payload_hash in
place), incl. the loud RuntimeError branch for un-bridged
envelopes (message-only contract).
* test_envelope — the in-module self-test's exact stdout bytes
(captured under the rig's deterministic ids).
* CHANNELS / AUTHORITY_CLASSES — the constant tables.
Verify (byte-identical law):
PYTHONPATH=scripts/ee_freeze_seams:src \\
python3 scripts/freeze_truth.py --verify src/go/event-bus/truth_envelope.json \\
--module rune.event_envelope
"""
import os
import sys
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "src"))
sys.path.insert(0, str(Path(__file__).resolve().parent))
FROZEN_NOW = "2026-10-14T11:22:33.123456+00:00"
os.environ["RUNE_FROZEN_NOW"] = FROZEN_NOW
from freeze_truth import freeze, write_envelope # noqa: E402
def main():
cases = [
# ── constant tables ────────────────────────────────────────────
("ee_channels", (), {}),
("ee_authority_classes", (), {}),
# ── classify_authority — regex \b semantics ────────────────────
("classify_authority", ("hello there", "conversation"), {}),
("classify_authority", ("Fix the failing test", "work"), {}), # directive
("classify_authority", ("run the suite", "work"), {}), # directive
("classify_authority", ("build it", "conversation"), {}), # directive
("classify_authority", ("test everything", "conversation"), {}), # directive
("classify_authority", ("create a file", "work"), {}), # directive
("classify_authority", ("add the guard", "work"), {}), # directive
("classify_authority", ("remove the shim", "work"), {}), # directive
("classify_authority", ("update the docs", "work"), {}), # directive
("classify_authority", ("change the port", "work"), {}), # directive
("classify_authority", ("Stop everything!", "work"), {}), # emergency
("classify_authority", ("please cancel the order", "work"), {}), # emergency
("classify_authority", ("abort the run", "work"), {}), # emergency
("classify_authority", ("emergency shutdown", "work"), {}), # emergency
("classify_authority", ("halt", "work"), {}), # emergency
# task amendments BEFORE emergency — multi-word lists
("classify_authority", ("Actually, don't modify the microkernel", "conversation"), {}),
("classify_authority", ("dont do that", "conversation"), {}), # dont (no apostrophe)
("classify_authority", ("stop doing that", "work"), {}), # "stop doing" ≠ bare stop
("classify_authority", ("use rust instead", "work"), {}), # instead
("classify_authority", ("rather use go", "work"), {}), # rather
# pause / resume
("classify_authority", ("pause for a bit", "work"), {}), # pause
("classify_authority", ("wait", "work"), {}), # wait
("classify_authority", ("hold", "work"), {}), # hold
("classify_authority", ("resume the work", "work"), {}), # resume
("classify_authority", ("continue the build", "work"), {}), # continue
("classify_authority", ("go", "work"), {}), # go
# status queries
("classify_authority", ("how is it going", "work"), {}), # how
("classify_authority", ("what is the state", "work"), {}), # what
("classify_authority", ("status?", "work"), {}), # status
("classify_authority", ("progress report", "work"), {}), # progress
("classify_authority", ("check the log", "work"), {}), # check
# channel defaults + boundary/adjacency quirks
("classify_authority", ("hello", "work"), {}), # work default → directive
("classify_authority", ("hello", "conversation"), {}), # conversation default
("classify_authority", ("hello", ""), {}), # non-work default
("classify_authority", ("stop,", "work"), {}), # punctuation-adjacent → emergency
("classify_authority", ("unstoppable force", "work"), {}), # \b boundary → no match
("classify_authority", ("stopit now", "work"), {}), # no boundary → resume (now? no—
# ^ "stopit" fails \bstop\b; no other list hits → work default directive
("classify_authority", ("", "work"), {}), # empty text → work default
("classify_authority", ("", "conversation"), {}), # empty → conversation
("classify_authority", (" FIX it ", "work"), {}), # lower().strip() + \b spacing
("classify_authority", ("café stop", "work"), {}), # unicode text, ascii word
("classify_authority", ("stopé now", "work"), {}), # é is a word char: no \b after stop
# ── classify_urgency ──────────────────────────────────────────
("classify_urgency", ("anything", "emergency"), {}), # critical via class
("classify_urgency", ("urgent please", "directive"), {}), # high
("classify_urgency", ("asap", "directive"), {}), # high
("classify_urgency", ("immediately", "conversation"), {}), # high
("classify_urgency", ("do it now", "directive"), {}), # high
("classify_urgency", ("critical issue", "conversation"), {}), # high
("classify_urgency", ("when you can", "directive"), {}), # low (multi-word)
("classify_urgency", ("no rush", "directive"), {}), # low (multi-word)
("classify_urgency", ("eventually", "conversation"), {}), # low
("classify_urgency", ("sometime later", "conversation"), {}), # low
("classify_urgency", ("when", "directive"), {}), # bare "when" → normal (multi-word quirk)
("classify_urgency", ("rush", "directive"), {}), # bare "rush" → normal
("classify_urgency", ("hello", "conversation"), {}), # normal
("classify_urgency", ("", "directive"), {}), # normal
# ── create_envelope — legacy path (auto + explicit) ───────────
("ee_create_envelope", ("user", "conversation", {"text": "hello"}), {}),
("ee_create_envelope", ("user", "work", {"text": "Fix the failing test"}), {}),
("ee_create_envelope", ("user", "work", {"text": "Stop everything!"}), {}),
("ee_create_envelope", ("user", "conversation", {"text": "Actually, don't modify the microkernel"}), {}),
("ee_create_envelope", ("user", "work", {"text": "when you can"}), {}),
("ee_create_envelope", ("sensor", "sensor", {}), {}), # no text key → defaults
("ee_create_envelope", ("user", "work", {"text": "run it"}, "status_query", "t-42", "low"), {}),
("ee_create_envelope", ("user", "conversation", {"text": "hi", "extra": {"nested": [1, 2.5, None, True]}}), {}),
# ── EventEnvelope.create — canonical bridge ───────────────────
("ee_create", ("user", "conversation", {"text": "hello"}), {}),
("ee_create", ("tool", "tool", {"x": 1}), {}), # prior: tool_result
("ee_create", ("user", "work", {"text": "Fix it"}), {}), # prior: directive
("ee_create", ("system", "system", {}), {}), # prior: system_event
("ee_create", ("bg", "background", {}), {}), # prior: background
("ee_create", ("sensor", "sensor", {}), {}), # prior: sensor
("ee_create", ("user", "", {}), {}), # channel "" → source fallback
("ee_create", ("", "", {}), {}), # everything empty → unknown
("ee_create", ("user", "unknown-channel", {"text": "hi"}), {}), # channel not in CHANNELS
# ── to_dict — 9-key legacy dict ───────────────────────────────
("ee_to_dict", ({"event_id": "evt_abc123def456",
"timestamp": "2026-10-14T11:22:33.123456+00:00",
"source": "user", "channel": "conversation",
"authority_class": "conversation", "task_id": None,
"payload": {"text": "hi"}, "provenance": {},
"urgency": "normal", "_canonical": None},), {}),
("ee_to_dict", ({"event_id": "id-2", "timestamp": "2026-10-14T00:00:00+00:00",
"source": "tool", "channel": "work",
"authority_class": "directive", "task_id": "t-9",
"payload": {"n": 1.5, "b": False, "nil": None, "list": [1, "two"]},
"provenance": {"origin": "café", "chain": ["a", "b"]},
"urgency": "high", "_canonical": None},), {}),
# ── to_canonical_dict — bridged + loud failure ────────────────
("ee_to_canonical_dict", ("user", "conversation", {"text": "hello"}), {}),
("ee_to_canonical_dict", ("tool", "tool", {"x": 1, "a": 2.0}), {}), # integral float in hash corpus
("ee_to_canonical_dict", ("user", "work", {"text": "café résumé", "z": 1, "a": [True, None]}), {}),
("ee_to_canonical_dict", ("system", "system", {}), {}), # empty payload hash
("ee_to_canonical_dict_unbridged", ({"event_id": "legacy-1",
"timestamp": "2026-10-14T11:22:33.123456+00:00",
"source": "user", "channel": "conversation",
"authority_class": "", "task_id": None,
"payload": {}, "provenance": {},
"urgency": "normal", "_canonical": None},), {}),
# ── test_envelope — captured stdout ───────────────────────────
("ee_test_envelope", (), {}),
]
truth = freeze("rune.event_envelope", cases, oracle_module="rune.event_envelope")
dest = REPO / "src/go/event-bus/truth_envelope.json"
write_envelope(FROZEN_NOW, truth, dest)
print(f"wrote {len(truth)} cases -> {dest}")
if __name__ == "__main__":
main()
+28 -8
View File
@@ -85,6 +85,19 @@ func writeEventJSON(sb *strings.Builder, v interface{}) {
writeEventJSON(sb, x[k])
}
sb.WriteString("}")
case *ordObj:
// NOT sorted: json.dumps preserves INSERTION order unless
// sort_keys is set; to_dict byte parity needs the input order.
sb.WriteString("{")
for i, k := range x.keys {
if i > 0 {
sb.WriteString(", ")
}
sb.WriteString(pyQuoteEvent(k))
sb.WriteString(": ")
writeEventJSON(sb, x.vals[k])
}
sb.WriteString("}")
default:
b, _ := json.Marshal(x)
sb.Write(b)
@@ -148,15 +161,16 @@ func pyQuoteEvent(s string) string {
case '\t':
sb.WriteString("\\t")
default:
if r < 0x20 {
sb.WriteString("\\u")
const hexdig = "0123456789abcdef"
sb.WriteByte('0')
sb.WriteByte('0')
sb.WriteByte(hexdig[(r>>4)&0xf])
sb.WriteByte(hexdig[r&0xf])
} else {
// ensure_ascii=True: everything outside printable ASCII is
// \uXXXX (lowercase hex; astral runes as surrogate pairs).
if r >= 0x20 && r < 0x7f {
sb.WriteRune(r)
} else if r < 0x10000 {
sb.WriteString(fmtPyUEscape(r))
} else {
r -= 0x10000
sb.WriteString(fmtPyUEscape(0xd800 + (r >> 10)))
sb.WriteString(fmtPyUEscape(0xdc00 + (r & 0x3ff)))
}
}
}
@@ -164,6 +178,12 @@ func pyQuoteEvent(s string) string {
return sb.String()
}
func fmtPyUEscape(r rune) string {
const hexdig = "0123456789abcdef"
return string([]byte{'\\', 'u',
hexdig[(r>>12)&0xf], hexdig[(r>>8)&0xf], hexdig[(r>>4)&0xf], hexdig[r&0xf]})
}
// AddEvent — append an event to a JSONL stream (parity with the Python
// event_bus.py append path). The hash IS the content hash.
func AddEvent(eventJSON string) string {
+544
View File
@@ -0,0 +1,544 @@
package main
// envelope.go — event_envelope.py port (dichotomy gap close, factory-gap-ee).
// The three audit-named gaps land here name-preserving: ToDict (to_dict),
// ToCanonicalDict (to_canonical_dict, incl. the loud RuntimeError branch),
// TestEnvelope (test_envelope), plus the canonical-bridge classmethod
// CreateEnvelope (EventEnvelope.create) they depend on. classifyAuthority /
// classifyUrgency / createEnvelope move to the oracle's regex semantics:
// Python matches \b<re.escape(word)>\b against the lowercased text — word
// BOUNDARIES, not word splitting — with Unicode word chars (é is \w), so
// "stop," fires, "unstoppable" does not, "stopé" does not, and the
// multi-word amendment "stop doing" is NOT bare "stop".
//
// Determinism seams (no-clock/no-random law): EE_FROZEN_NOW pins the
// timestamp, the uuid counter (reset per op, mirroring the ee_freeze_seams
// rig) pins minted ids — the battery and parity replay byte-identical.
import (
cryptorand "crypto/rand"
"encoding/hex"
"fmt"
"os"
"sort"
"strings"
"time"
"unicode"
)
// ── constant tables (CHANNELS / AUTHORITY_CLASSES) ────────────────────────
// ordKV — an *ordObj from ordered key/value pairs (insertion order is
// the serialization order).
func ordKV(pairs ...interface{}) *ordObj {
o := newOrdObj()
for i := 0; i+1 < len(pairs); i += 2 {
o.set(pairs[i].(string), pairs[i+1])
}
return o
}
var eeChannels = map[string]interface{}{
"conversation": ordKV("prior", "conversation", "tools_allowed", false, "verification_expected", false),
"work": ordKV("prior", "directive", "tools_allowed", true, "verification_expected", true),
"system": ordKV("prior", "system_event", "tools_allowed", false, "verification_expected", false),
"tool": ordKV("prior", "tool_result", "tools_allowed", false, "verification_expected", false),
"background": ordKV("prior", "background", "tools_allowed", false, "verification_expected", false),
"sensor": ordKV("prior", "sensor", "tools_allowed", false, "verification_expected", false),
}
var eeAuthorityClasses = map[string]interface{}{
"conversation": ordKV("priority", 1, "can_amend_task", false),
"status_query": ordKV("priority", 2, "can_amend_task", false),
"directive": ordKV("priority", 3, "can_amend_task", true),
"task_amendment": ordKV("priority", 4, "can_amend_task", true),
"pause": ordKV("priority", 5, "can_amend_task", true),
"resume": ordKV("priority", 5, "can_amend_task", true),
"cancel": ordKV("priority", 6, "can_amend_task", true),
"emergency": ordKV("priority", 7, "can_amend_task", true),
"system_event": ordKV("priority", 1, "can_amend_task", false),
}
// ── Python \b<word>\b semantics ───────────────────────────────────────────
// pyIsWordChar — Python re \w for str patterns (Unicode): letters, digits
// (all numeric categories), underscore.
func pyIsWordChar(r rune) bool {
return r == '_' || unicode.IsLetter(r) || unicode.IsNumber(r)
}
// pyWordMatch — \b<word>\b against text: an occurrence of word whose
// neighboring runes are not word chars (string edges are boundaries).
func pyWordMatch(text, word string) bool {
t, w := []rune(text), []rune(word)
if len(w) == 0 || len(w) > len(t) {
return false
}
for i := 0; i+len(w) <= len(t); i++ {
if string(t[i:i+len(w)]) != word {
continue
}
leftOK := i == 0 || !pyIsWordChar(t[i-1])
end := i + len(w)
rightOK := end == len(t) || !pyIsWordChar(t[end])
if leftOK && rightOK {
return true
}
}
return false
}
func anyWordMatch(text string, words []string) bool {
for _, w := range words {
if pyWordMatch(text, w) {
return true
}
}
return false
}
// ── classify (oracle regex semantics) ─────────────────────────────────────
var (
amendmentWords = []string{"don't", "dont", "stop doing", "actually", "instead", "rather"}
emergencyWords = []string{"stop", "cancel", "abort", "emergency", "halt"}
pauseWords = []string{"pause", "wait", "hold"}
resumeWords = []string{"resume", "continue", "go"}
directiveWords = []string{"fix", "run", "build", "test", "create", "add", "remove", "update", "change"}
statusWords = []string{"how", "what", "status", "progress", "check"}
urgencyHigh = []string{"urgent", "asap", "immediately", "now", "critical"}
urgencyLow = []string{"when you can", "no rush", "eventually", "sometime"}
)
func classifyAuthority(text, channel string) string {
lower := strings.ToLower(strings.TrimSpace(text))
// Task amendments BEFORE emergency ("stop doing that" ≠ bare "stop").
if anyWordMatch(lower, amendmentWords) {
return "task_amendment"
}
if anyWordMatch(lower, emergencyWords) {
return "emergency"
}
if anyWordMatch(lower, pauseWords) {
return "pause"
}
if anyWordMatch(lower, resumeWords) {
return "resume"
}
if anyWordMatch(lower, directiveWords) {
return "directive"
}
if anyWordMatch(lower, statusWords) {
return "status_query"
}
if channel == "work" {
return "directive"
}
return "conversation"
}
func classifyUrgency(text, authorityClass string) string {
lower := strings.ToLower(strings.TrimSpace(text))
if authorityClass == "emergency" {
return "critical"
}
if anyWordMatch(lower, urgencyHigh) {
return "high"
}
if anyWordMatch(lower, urgencyLow) {
return "low"
}
return "normal"
}
// ── deterministic id / clock seams ────────────────────────────────────────
var eeUUIDNext int64
// resetEEUUID — per-op counter reset (the rig's _reset_mint law: a case's
// ids depend only on the mints that happen inside it).
func resetEEUUID() {
base := int64(1)
if v := os.Getenv("EE_UUID_BASE"); v != "" {
fmt.Sscanf(v, "%d", &base)
}
eeUUIDNext = base - 1 // eeDetHex increments BEFORE use (count(1) yields 1 first)
}
// eeDetHex — the uuid4() stand-in. Under the determinism pins (battery +
// parity set EE_FROZEN_NOW / EE_UUID_BASE) it is the rig's counter;
// production paths mint a random 32-hex uuid like the oracle's uuid4().
func eeDetHex() string {
eeUUIDNext++
if os.Getenv("EE_FROZEN_NOW") == "" && os.Getenv("EE_UUID_BASE") == "" {
b := make([]byte, 16)
if _, err := cryptorand.Read(b); err != nil {
return fmt.Sprintf("%032x", eeUUIDNext) // unreachable in practice
}
return hex.EncodeToString(b)
}
return fmt.Sprintf("%032x", eeUUIDNext)
}
// eeMintEventID — records.new_id: "evt_" + uuid4().hex[:12].
func eeMintEventID() string {
return "evt_" + eeDetHex()[:12]
}
// eeMintLegacyID — str(uuid4()): the dashed 8-4-4-4-12 form.
func eeMintLegacyID() string {
h := eeDetHex()
return h[:8] + "-" + h[8:12] + "-" + h[12:16] + "-" + h[16:20] + "-" + h[20:]
}
// eeNowISO — datetime.now(timezone.utc).isoformat(): +00:00 offset, the
// microsecond fraction only when nonzero.
func eeNowISO() string {
if v := os.Getenv("EE_FROZEN_NOW"); v != "" {
return v
}
t := time.Now().UTC()
if t.Nanosecond()/1000 == 0 {
return t.Format("2006-01-02T15:04:05+00:00")
}
return t.Format("2006-01-02T15:04:05.000000+00:00")
}
// ── the legacy envelope (event_envelope.py EventEnvelope) ─────────────────
// LegacyEventEnvelope — the legacy dataclass shape. Payload/Provenance stay
// interface{} so the op path can carry insertion-ordered payloads
// (*ordObj) for json.dumps byte parity.
type LegacyEventEnvelope struct {
EventID string
Timestamp string
Source string
Channel string
AuthorityClass string
TaskID *string
Payload interface{}
Provenance interface{}
Urgency string
Canonical *EventEnvelope // _canonical bridge; nil = unbridged
}
func payloadAsMap(v interface{}) map[string]interface{} {
switch x := v.(type) {
case map[string]interface{}:
return x
case *ordObj:
return x.vals
}
return nil
}
func payloadText(v interface{}) string {
if m := payloadAsMap(v); m != nil {
s, _ := m["text"].(string)
return s
}
return ""
}
func strPtr(s string) *string { return &s }
// createEnvelope — event_envelope.py create_envelope: the legacy
// direct-constructor path (auto authority + urgency from payload["text"]).
func createEnvelope(source, channel string, payload interface{},
authorityClass, taskID, urgency *string) LegacyEventEnvelope {
text := payloadText(payload)
if authorityClass == nil {
authorityClass = strPtr(classifyAuthority(text, channel))
}
if urgency == nil {
urgency = strPtr(classifyUrgency(text, *authorityClass))
}
if payload == nil {
payload = map[string]interface{}{}
}
return LegacyEventEnvelope{
EventID: eeMintLegacyID(),
Timestamp: eeNowISO(),
Source: source,
Channel: channel,
AuthorityClass: *authorityClass,
TaskID: taskID,
Payload: payload,
Provenance: map[string]interface{}{},
Urgency: *urgency,
}
}
// CreateEnvelope — EventEnvelope.create classmethod: the canonical record
// is built first, the legacy wrapper derived from it (schema migration
// shim; one dialect, not two).
func CreateEnvelope(source, channel string, payload interface{}) LegacyEventEnvelope {
// event_type = CHANNELS.get(channel, {}).get("prior") or channel or
// source or "unknown"
eventType := channel
if ch, ok := eeChannels[channel].(*ordObj); ok {
if p, ok := ch.vals["prior"].(string); ok && p != "" {
eventType = p
}
}
if eventType == "" {
eventType = source
}
if eventType == "" {
eventType = "unknown"
}
if payload == nil {
payload = map[string]interface{}{}
}
canonical := &EventEnvelope{
EventID: eeMintEventID(),
EventType: eventType,
PartitionKey: channel,
Timestamp: eeNowISO(),
}
return LegacyEventEnvelope{
EventID: canonical.EventID,
Timestamp: canonical.Timestamp,
Source: source,
Channel: channel,
TaskID: nil,
Payload: payload,
Provenance: map[string]interface{}{},
Urgency: "normal",
Canonical: canonical,
}
}
// ToDict — the 9-key legacy dict.
func (e *LegacyEventEnvelope) ToDict() map[string]interface{} {
return map[string]interface{}{
"event_id": e.EventID,
"timestamp": e.Timestamp,
"source": e.Source,
"channel": e.Channel,
"authority_class": e.AuthorityClass,
"task_id": nullableString(e.TaskID),
"payload": payloadValue(e.Payload),
"provenance": payloadValue(e.Provenance),
"urgency": e.Urgency,
}
}
func nullableString(p *string) interface{} {
if p == nil {
return nil
}
return *p
}
func payloadValue(v interface{}) interface{} {
if v == nil {
return map[string]interface{}{}
}
return v
}
// canonicalBridgeUnavailable — the loud-failure contract (X2): direct-
// constructed envelopes have NO canonical bridge; the message is the
// contract (str(e) strips the exception type).
const canonicalBridgeUnavailable = "canonical bridge unavailable: this envelope was not created via EventEnvelope.create(); use create(source, channel, payload) for the canonical-backed path"
// ToCanonicalDict — schema_version-1 canonical dict with the
// content-addressed payload_hash (key order mirrors asdict: schema_version
// first, payload_hash in place).
func (e *LegacyEventEnvelope) ToCanonicalDict() (map[string]interface{}, error) {
if e.Canonical == nil {
return nil, fmt.Errorf("%s", canonicalBridgeUnavailable)
}
c := e.Canonical
var parentID interface{}
if c.ParentID != "" {
parentID = c.ParentID
}
return map[string]interface{}{
"schema_version": 1,
"event_type": c.EventType,
"partition_key": c.PartitionKey,
"event_id": c.EventID,
"parent_id": parentID,
"actor_id": c.ActorID,
"device_id": c.DeviceID,
"authorization": c.Authorization,
"payload_hash": ContentHashEvent(payloadAsMap(e.Payload)),
"timestamp": c.Timestamp,
}, nil
}
// TestEnvelope — event_envelope.py test_envelope: the in-module self-test
// (prints its report, asserts the four classes). Returns the captured
// report exactly as the oracle prints it.
func TestEnvelope() (string, error) {
resetEEUUID()
var sb strings.Builder
sb.WriteString("Testing Event Envelope...\n")
cases := []struct {
label, text, channel, wantAuthority, wantUrgency string
}{
{"Greeting", "hello", "conversation", "conversation", "normal"},
{"Directive", "Fix the failing test", "work", "directive", "normal"},
{"Emergency", "Stop everything!", "work", "emergency", "critical"},
{"Amendment", "Actually, don't modify the microkernel", "conversation", "task_amendment", ""},
}
for _, c := range cases {
env := createEnvelope("user", c.channel,
map[string]interface{}{"text": c.text}, nil, nil, nil)
sb.WriteString(fmt.Sprintf("%s: authority=%s, urgency=%s\n",
c.label, env.AuthorityClass, env.Urgency))
if env.AuthorityClass != c.wantAuthority {
return sb.String(), fmt.Errorf("%s: authority %q != %q",
c.label, env.AuthorityClass, c.wantAuthority)
}
if c.wantUrgency != "" && env.Urgency != c.wantUrgency {
return sb.String(), fmt.Errorf("%s: urgency %q != %q",
c.label, env.Urgency, c.wantUrgency)
}
}
sb.WriteString("✅ All tests passed!\n")
return sb.String(), nil
}
// ── asdict + json.dumps byte-parity serializers ───────────────────────────
// asdictMap — dataclasses.asdict of the legacy envelope (_canonical rides
// along as its own asdict; None bridge → nil).
func asdictMap(e *LegacyEventEnvelope) map[string]interface{} {
var canonical interface{}
if e.Canonical != nil {
canonical = canonicalAsdict(e.Canonical)
}
return map[string]interface{}{
"event_id": e.EventID,
"timestamp": e.Timestamp,
"source": e.Source,
"channel": e.Channel,
"authority_class": e.AuthorityClass,
"task_id": nullableString(e.TaskID),
"payload": payloadValue(e.Payload),
"provenance": payloadValue(e.Provenance),
"urgency": e.Urgency,
"_canonical": canonical,
}
}
// canonicalAsdict — OrchestrationRecord field order: base fields first
// (schema_version), then the subclass's.
func canonicalAsdict(c *EventEnvelope) map[string]interface{} {
return map[string]interface{}{
"schema_version": 1,
"event_type": c.EventType,
"partition_key": c.PartitionKey,
"event_id": c.EventID,
"parent_id": nil, // create() never binds a parent
"actor_id": c.ActorID,
"device_id": c.DeviceID,
"authorization": c.Authorization,
"payload_hash": c.PayloadHash,
"timestamp": c.Timestamp,
}
}
// writeOrderedKV — "\"key\": " + value via the pyDumps writer.
func writeOrderedKV(sb *strings.Builder, key string, val interface{}) {
sb.WriteString(pyQuoteEvent(key))
sb.WriteString(": ")
writeEventJSON(sb, val)
}
var legacyAsdictKeys = append(append([]string(nil), legacyDictKeys...), "_canonical")
// asdictJSON — json.dumps(dataclasses.asdict(envelope)) byte parity:
// dataclass field order (the nested canonical keeps ITS field order —
// schema_version first), payload/provenance keep insertion order.
func asdictJSON(e *LegacyEventEnvelope) string {
var sb strings.Builder
sb.WriteString("{")
for i, k := range legacyAsdictKeys {
if i > 0 {
sb.WriteString(", ")
}
if k == "_canonical" && e.Canonical != nil {
sb.WriteString(pyQuoteEvent(k))
sb.WriteString(": ")
writeOrderedObj(&sb, canonicalDictKeys, func(kk string) interface{} {
return canonicalAsdict(e.Canonical)[kk]
})
continue
}
writeOrderedKV(&sb, k, e.ToDict()[k])
}
sb.WriteString("}")
return sb.String()
}
// writeOrderedObj — {k1: v1, k2: v2, ...} in the SLICE order (json.dumps
// insertion order; NOT sorted).
func writeOrderedObj(sb *strings.Builder, keys []string, get func(string) interface{}) {
sb.WriteString("{")
for i, k := range keys {
if i > 0 {
sb.WriteString(", ")
}
writeOrderedKV(sb, k, get(k))
}
sb.WriteString("}")
}
var legacyDictKeys = []string{"event_id", "timestamp", "source", "channel",
"authority_class", "task_id", "payload", "provenance", "urgency"}
// toDictJSON — json.dumps(envelope.to_dict()) byte parity (Python default
// separators, insertion order — payload/provenance keep THEIR order).
func toDictJSON(e *LegacyEventEnvelope) string {
var sb strings.Builder
writeOrderedObj(&sb, legacyDictKeys, func(k string) interface{} {
return e.ToDict()[k]
})
return sb.String()
}
var canonicalDictKeys = []string{"schema_version", "event_type", "partition_key",
"event_id", "parent_id", "actor_id", "device_id", "authorization",
"payload_hash", "timestamp"}
// toCanonicalDictJSON — json.dumps(to_canonical_dict()) byte parity.
func toCanonicalDictJSON(e *LegacyEventEnvelope) (string, error) {
d, err := e.ToCanonicalDict()
if err != nil {
return "", err
}
var sb strings.Builder
writeOrderedObj(&sb, canonicalDictKeys, func(k string) interface{} {
return d[k]
})
return sb.String(), nil
}
// ── ordObj — insertion-ordered JSON object (byte parity for payloads) ─────
type ordObj struct {
keys []string
vals map[string]interface{}
}
func newOrdObj() *ordObj {
return &ordObj{vals: map[string]interface{}{}}
}
func (o *ordObj) set(k string, v interface{}) {
if _, exists := o.vals[k]; !exists {
o.keys = append(o.keys, k)
}
o.vals[k] = v
}
// sortedKeys — sort_keys=True view (the hash corpus).
func (o *ordObj) sortedKeys() []string {
keys := append([]string(nil), o.keys...)
sort.Strings(keys)
return keys
}
+201 -83
View File
@@ -229,7 +229,45 @@ func main() {
}
}
}
out, _ := json.MarshalIndent(createEnvelope(source, channel, text, payload), "", " ")
if payload == nil {
payload = map[string]interface{}{}
}
if text != "" {
payload["text"] = text
}
env := createEnvelope(source, channel, payload, nil, nil, nil)
out, _ := json.MarshalIndent(env.ToDict(), "", " ")
fmt.Println(string(out))
case "op":
// op — JSON-in/JSON-out parity surface (dichotomy gap close):
// the freeze/parity harnesses drive every ported fn through
// here under the EE_FROZEN_NOW / EE_UUID_BASE pins.
dec := json.NewDecoder(os.Stdin)
dec.UseNumber()
v, err := decodeOrderedValue(dec)
if err != nil {
fmt.Fprintf(os.Stderr, "event-bus op: bad request: %v\n", err)
os.Exit(1)
}
req, ok := v.(*ordObj)
if !ok {
fmt.Fprintf(os.Stderr, "event-bus op: request must be an object\n")
os.Exit(1)
}
pyJSON, err := runOp(req)
if err != nil {
fmt.Fprintf(os.Stderr, "event-bus op: %v\n", err)
os.Exit(1)
}
var semantic interface{}
dec2 := json.NewDecoder(strings.NewReader(pyJSON))
dec2.UseNumber()
dec2.Decode(&semantic)
out, _ := json.Marshal(map[string]interface{}{
"json": pyJSON,
"result": semantic,
})
fmt.Println(string(out))
default:
@@ -238,104 +276,184 @@ func main() {
}
}
// ── event envelope operations (W4: event_envelope port) ──────────────────
// ── op mode — the parity dispatch (envelope.go carries the port) ──────────
type EnvelopeRequest struct {
Source string `json:"source"`
Channel string `json:"channel"`
Payload map[string]interface{} `json:"payload"`
Text string `json:"text"`
// decodeOrderedValue / decodeOrderedFrom — token walk preserving object
// key order (*ordObj) and number literals (json.Number via UseNumber).
func decodeOrderedValue(dec *json.Decoder) (interface{}, error) {
tok, err := dec.Token()
if err != nil {
return nil, err
}
return decodeOrderedFrom(dec, tok)
}
func classifyAuthority(text, channel string) string {
lower := strings.ToLower(strings.TrimSpace(text))
words := strings.Fields(lower)
hasAny := func(words []string, targets ...string) bool {
for _, w := range words {
for _, t := range targets {
if w == t {
return true
func decodeOrderedFrom(dec *json.Decoder, tok json.Token) (interface{}, error) {
if d, ok := tok.(json.Delim); ok {
switch d {
case '{':
o := newOrdObj()
for {
kt, err := dec.Token()
if err != nil {
return nil, err
}
if dd, ok := kt.(json.Delim); ok && dd == '}' {
return o, nil
}
key, _ := kt.(string)
val, err := decodeOrderedValue(dec)
if err != nil {
return nil, err
}
o.set(key, val)
}
case '[':
arr := []interface{}{}
for {
kt, err := dec.Token()
if err != nil {
return nil, err
}
if dd, ok := kt.(json.Delim); ok && dd == ']' {
return arr, nil
}
val, err := decodeOrderedFrom(dec, kt)
if err != nil {
return nil, err
}
arr = append(arr, val)
}
}
return false
return nil, fmt.Errorf("unexpected delimiter %v", d)
}
// Task amendments first (before emergency)
if hasAny(words, "don't", "dont", "stop", "doing", "actually", "instead", "rather") {
return "task_amendment"
}
if hasAny(words, "stop", "cancel", "abort", "emergency", "halt") {
return "emergency"
}
if hasAny(words, "pause", "wait", "hold") {
return "pause"
}
if hasAny(words, "resume", "continue", "go") {
return "resume"
}
if hasAny(words, "fix", "run", "build", "test", "create", "add", "remove", "update", "change") {
return "directive"
}
if hasAny(words, "how", "what", "status", "progress", "check") {
return "status_query"
}
if channel == "work" {
return "directive"
}
return "conversation"
return tok, nil
}
func classifyUrgency(text, authorityClass string) string {
lower := strings.ToLower(strings.TrimSpace(text))
words := strings.Fields(lower)
func opGet(o *ordObj, key string) (interface{}, bool) {
v, ok := o.vals[key]
return v, ok
}
hasAny := func(targets ...string) bool {
for _, w := range words {
for _, t := range targets {
if w == t {
return true
func opStr(o *ordObj, key string) string {
s, _ := o.vals[key].(string)
return s
}
func optStrPtr(o *ordObj, key string) *string {
v, ok := opGet(o, key)
if !ok || v == nil {
return nil
}
s, _ := v.(string)
return &s
}
// legacyStateKeys — the ee_to_dict / ee_to_canonical_dict_unbridged state
// dicts arrive in dataclass field order; values map onto the struct.
func legacyFromState(state interface{}) *LegacyEventEnvelope {
m := payloadAsMap(state)
if m == nil {
return &LegacyEventEnvelope{}
}
taskID := (*string)(nil)
if v, ok := m["task_id"].(string); ok {
taskID = &v
}
var canonical *EventEnvelope
return &LegacyEventEnvelope{
EventID: m["event_id"].(string),
Timestamp: m["timestamp"].(string),
Source: m["source"].(string),
Channel: m["channel"].(string),
AuthorityClass: m["authority_class"].(string),
TaskID: taskID,
Payload: m["payload"],
Provenance: m["provenance"],
Urgency: m["urgency"].(string),
Canonical: canonical,
}
}
// runOp — one parity op; returns the PYTHON-json byte form (separators,
// ensure_ascii, insertion order). The uuid counter resets per op,
// mirroring the ee_freeze_seams rig.
func runOp(req *ordObj) (string, error) {
resetEEUUID()
switch opStr(req, "op") {
case "classify_authority":
return pyDumpsValue(classifyAuthority(opStr(req, "text"), opStr(req, "channel"))), nil
case "classify_urgency":
return pyDumpsValue(classifyUrgency(opStr(req, "text"), opStr(req, "authority_class"))), nil
case "create_envelope":
payload, _ := opGet(req, "payload")
env := createEnvelope(opStr(req, "source"), opStr(req, "channel"), payload,
optStrPtr(req, "authority_class"), optStrPtr(req, "task_id"),
optStrPtr(req, "urgency"))
return asdictJSON(&env), nil
case "create":
payload, _ := opGet(req, "payload")
env := CreateEnvelope(opStr(req, "source"), opStr(req, "channel"), payload)
return asdictJSON(&env), nil
case "to_dict":
env := legacyFromState(mustArg(req, "state"))
return toDictJSON(env), nil
case "to_canonical_dict":
payload, _ := opGet(req, "payload")
env := CreateEnvelope(opStr(req, "source"), opStr(req, "channel"), payload)
return toCanonicalDictJSON(&env)
case "to_canonical_dict_unbridged":
env := legacyFromState(mustArg(req, "state"))
if _, err := env.ToCanonicalDict(); err != nil {
var sb strings.Builder
writeOrderedObj(&sb, []string{"error", "message"}, func(k string) interface{} {
if k == "error" {
return "RuntimeError"
}
}
return canonicalBridgeUnavailable
})
return sb.String(), nil
}
return false
return "", fmt.Errorf("unbridged state unexpectedly bridged")
case "test_envelope":
out, err := TestEnvelope()
if err != nil {
return "", err
}
return pyDumpsValue(out), nil
case "channels":
return pyDumpsValue(orderedTable(eeChannelKeys, func(k string) interface{} { return eeChannels[k] })), nil
case "authority_classes":
return pyDumpsValue(orderedTable(eeAuthorityKeys, func(k string) interface{} { return eeAuthorityClasses[k] })), nil
}
if authorityClass == "emergency" {
return "critical"
}
if hasAny("urgent", "asap", "immediately", "now", "critical") {
return "high"
}
if hasAny("when", "you", "can", "no", "rush", "eventually", "sometime") {
return "low"
}
return "normal"
return "", fmt.Errorf("unknown op: %q", opStr(req, "op"))
}
func createEnvelope(source, channel, text string, payload map[string]interface{}) map[string]interface{} {
authority := classifyAuthority(text, channel)
urgency := classifyUrgency(text, authority)
env := EventEnvelope{
EventID: newID("evt"),
EventType: channel,
PartitionKey: source,
Timestamp: nowISO(),
}
if payload != nil {
env.PayloadHash = contentHash(payload)
}
return map[string]interface{}{
"event_id": env.EventID,
"timestamp": env.Timestamp,
"source": source,
"channel": channel,
"authority_class": authority,
"urgency": urgency,
"payload_hash": env.PayloadHash,
"payload": payload,
func mustArg(req *ordObj, key string) interface{} {
v, _ := opGet(req, key)
return v
}
// eeChannelKeys / eeAuthorityKeys — the tables iterate in the ORACLE's
// definition order (json.dumps insertion-order law).
var eeChannelKeys = []string{"conversation", "work", "system", "tool", "background", "sensor"}
var eeAuthorityKeys = []string{"conversation", "status_query", "directive",
"task_amendment", "pause", "resume", "cancel", "emergency", "system_event"}
func pyDumpsValue(v interface{}) string {
var sb strings.Builder
writeEventJSON(&sb, v)
return sb.String()
}
// orderedTable — an *ordObj built from a fixed key order (table constants
// serialize in the oracle's definition order).
func orderedTable(keys []string, get func(string) interface{}) *ordObj {
o := newOrdObj()
for _, k := range keys {
o.set(k, get(k))
}
return o
}
func init() {
File diff suppressed because it is too large. Load diff
+264
View File
@@ -0,0 +1,264 @@
package main
// truth_envelope_test.go — the event_envelope parity gate (dichotomy gap
// close, factory-gap-ee). Replays every case from truth_envelope.json
// (the shared freeze_truth.py envelope: frozen clock + deterministic uuid
// counter, 83 Python-oracle cases WITH inputs, generated by
// scripts/gen_event_envelope_truth.py under scripts/ee_freeze_seams)
// VERBATIM through the ported Go functions: the constant tables,
// classifyAuthority/classifyUrgency (\b<word>\b regex semantics incl.
// the multi-word amendment list, punctuation adjacency, unicode word
// chars), createEnvelope (legacy path, auto + explicit), CreateEnvelope
// (the canonical-bridge classmethod with the CHANNELS prior vocabulary
// and the channel/source/unknown fallback chain), ToDict (9-key legacy
// dict), ToCanonicalDict (schema_version-first key order,
// content-addressed payload_hash incl. ensure_ascii unicode hashing,
// and the loud RuntimeError branch), and TestEnvelope (captured stdout).
// A divergence fails the port, not the oracle.
import (
_ "embed"
"encoding/json"
"reflect"
"strings"
"testing"
)
//go:embed truth_envelope.json
var frozenEnvelopeTruthJSON string
type envelopeCase struct {
Fn string `json:"fn"`
Args []any `json:"args"`
Kwargs map[string]any `json:"kwargs"`
Expected json.RawMessage `json:"expected"`
}
func canonDecT(t *testing.T, s string) any {
t.Helper()
var out any
dec := json.NewDecoder(strings.NewReader(s))
dec.UseNumber()
if err := dec.Decode(&out); err != nil {
t.Fatalf("decode actual %q: %v", s, err)
}
return out
}
func canonRawT(t *testing.T, raw json.RawMessage) any {
t.Helper()
var out any
dec := json.NewDecoder(strings.NewReader(string(raw)))
dec.UseNumber()
if err := dec.Decode(&out); err != nil {
t.Fatalf("decode expected %q: %v", raw, err)
}
return out
}
// batteryPayload — re-decode a case arg ORDERED (the outer reader lost
// key order) so payload insertion order and number literals ride through
// pyDumpsValue byte-identically.
func batteryPayload(t *testing.T, v any) any {
t.Helper()
if v == nil {
return nil
}
b, err := json.Marshal(v)
if err != nil {
t.Fatalf("re-encode arg: %v", err)
}
dec := json.NewDecoder(strings.NewReader(string(b)))
dec.UseNumber()
out, err := decodeOrderedValue(dec)
if err != nil {
t.Fatalf("ordered decode %s: %v", b, err)
}
return out
}
func argString(t *testing.T, v any, what string) string {
t.Helper()
s, ok := v.(string)
if !ok {
t.Fatalf("expected string %s, got %v (%T)", what, v, v)
}
return s
}
func optArgString(args []any, i int) *string {
if i >= len(args) || args[i] == nil {
return nil
}
s, _ := args[i].(string)
return &s
}
// runEnvelopeCase — dispatch one frozen case; returns the PYTHON-json
// byte form of the actual (same renderer the op surface uses).
func runEnvelopeCase(t *testing.T, c envelopeCase) string {
t.Helper()
resetEEUUID()
switch c.Fn {
case "ee_channels":
return pyDumpsValue(orderedTable(eeChannelKeys, func(k string) interface{} { return eeChannels[k] }))
case "ee_authority_classes":
return pyDumpsValue(orderedTable(eeAuthorityKeys, func(k string) interface{} { return eeAuthorityClasses[k] }))
case "classify_authority":
return pyDumpsValue(classifyAuthority(
argString(t, c.Args[0], "text"), argString(t, c.Args[1], "channel")))
case "classify_urgency":
return pyDumpsValue(classifyUrgency(
argString(t, c.Args[0], "text"), argString(t, c.Args[1], "authority_class")))
case "ee_create_envelope":
env := createEnvelope(
argString(t, c.Args[0], "source"), argString(t, c.Args[1], "channel"),
batteryPayload(t, c.Args[2]),
optArgString(c.Args, 3), optArgString(c.Args, 4), optArgString(c.Args, 5))
return asdictJSON(&env)
case "ee_create":
env := CreateEnvelope(
argString(t, c.Args[0], "source"), argString(t, c.Args[1], "channel"),
batteryPayload(t, c.Args[2]))
return asdictJSON(&env)
case "ee_to_dict":
env := legacyFromState(batteryPayload(t, c.Args[0]))
return toDictJSON(env)
case "ee_to_canonical_dict":
env := CreateEnvelope(
argString(t, c.Args[0], "source"), argString(t, c.Args[1], "channel"),
batteryPayload(t, c.Args[2]))
out, err := toCanonicalDictJSON(&env)
if err != nil {
t.Fatalf("to_canonical_dict: %v", err)
}
return out
case "ee_to_canonical_dict_unbridged":
env := legacyFromState(batteryPayload(t, c.Args[0]))
if _, err := env.ToCanonicalDict(); err == nil {
t.Fatalf("unbridged state unexpectedly bridged")
}
var sb strings.Builder
writeOrderedObj(&sb, []string{"error", "message"}, func(k string) interface{} {
if k == "error" {
return "RuntimeError"
}
return canonicalBridgeUnavailable
})
return sb.String()
case "ee_test_envelope":
out, err := TestEnvelope()
if err != nil {
t.Fatalf("test_envelope: %v", err)
}
return pyDumpsValue(out)
}
t.Fatalf("unknown frozen fn %q", c.Fn)
return ""
}
func TestFrozenEnvelopeTruthReplay(t *testing.T) {
var doc struct {
FrozenNow string `json:"frozen_now"`
Cases []envelopeCase `json:"cases"`
}
dec := json.NewDecoder(strings.NewReader(frozenEnvelopeTruthJSON))
dec.UseNumber()
if err := dec.Decode(&doc); err != nil {
t.Fatalf("decode truth_envelope.json: %v", err)
}
t.Setenv("EE_FROZEN_NOW", doc.FrozenNow)
for i, c := range doc.Cases {
got := runEnvelopeCase(t, c)
want := canonRawT(t, c.Expected)
if !reflect.DeepEqual(canonDecT(t, got), want) {
t.Errorf("case %d fn=%s:\n got %v\nwant %v", i, c.Fn,
canonDecT(t, got), want)
}
}
if len(doc.Cases) != 83 {
t.Fatalf("expected 83 frozen cases, found %d", len(doc.Cases))
}
}
// TestWordMatchSemantics — the \b matcher units the frozen corpus pins
// only through classify: unicode word chars, punctuation adjacency,
// string edges, empty words.
func TestWordMatchSemantics(t *testing.T) {
cases := []struct {
text, word string
want bool
}{
{"stop,", "stop", true},
{"unstoppable", "stop", false},
{"stopé now", "stop", false}, // é is a word char: no boundary
{"café stop", "stop", true},
{"stop doing that", "stop doing", true},
{"stop", "stop", true},
{"a-stop", "stop", true}, // '-' is not a word char
{"a_stop", "stop", false},
{"don't do it", "don't", true},
{"", "stop", false},
{"anything", "", false},
{"STOP", "stop", false}, // case-sensitive core; callers lowercase
}
for _, c := range cases {
if got := pyWordMatch(c.text, c.word); got != c.want {
t.Errorf("pyWordMatch(%q, %q) = %v, want %v", c.text, c.word, got, c.want)
}
}
}
// TestPyQuoteEnsureAscii — json.dumps escaping: DEL, non-ASCII, astral
// surrogate pairs, control chars.
func TestPyQuoteEnsureAscii(t *testing.T) {
cases := map[string]string{
"\x7f": "\"\\u007f\"",
"é": "\"\\u00e9\"",
"\U0001F600": "\"\\ud83d\\ude00\"",
"aéb": "\"a\\u00e9b\"",
"tab\t": "\"tab\\t\"",
}
for in, want := range cases {
if got := pyQuoteEvent(in); got != want {
t.Errorf("pyQuoteEvent(%q) = %s, want %s", in, got, want)
}
}
}
// TestCreateEventTypeFallback — CHANNELS.get(channel, {}).get("prior")
// or channel or source or "unknown", pinned one branch per frozen row.
func TestCreateEventTypeFallback(t *testing.T) {
t.Setenv("EE_FROZEN_NOW", "2026-10-14T11:22:33.123456+00:00")
cases := []struct{ source, channel, want string }{
{"user", "conversation", "conversation"}, // prior
{"tool", "tool", "tool_result"}, // prior remap
{"user", "", "user"}, // channel empty → source
{"", "", "unknown"}, // everything empty
{"user", "unknown-channel", "unknown-channel"},
}
for _, c := range cases {
resetEEUUID()
env := CreateEnvelope(c.source, c.channel, nil)
if env.Canonical.EventType != c.want {
t.Errorf("create(%q,%q) event_type = %q, want %q",
c.source, c.channel, env.Canonical.EventType, c.want)
}
if env.EventID != env.Canonical.EventID {
t.Errorf("legacy id %q != canonical id %q", env.EventID, env.Canonical.EventID)
}
}
}
// TestUnbridgedLoudFailure — the RuntimeError branch's exact message.
func TestUnbridgedLoudFailure(t *testing.T) {
env := LegacyEventEnvelope{}
_, err := env.ToCanonicalDict()
if err == nil || err.Error() != canonicalBridgeUnavailable {
t.Fatalf("want loud bridge error, got %v", err)
}
if !strings.Contains(err.Error(), "canonical bridge unavailable") {
t.Fatal("message contract broken")
}
}