Skip to content

Instantly share code, notes, and snippets.

@SoMaCoSF
Created April 28, 2026 14:18
Show Gist options
  • Select an option

  • Save SoMaCoSF/5c678c932912de14bb297ba56ca75dcf to your computer and use it in GitHub Desktop.

Select an option

Save SoMaCoSF/5c678c932912de14bb297ba56ca75dcf to your computer and use it in GitHub Desktop.
GYST UUID State Audit — content-address completeness analysis

GYST UUID v8 — Full State Audit

Date: 2026-04-28 | Repo: somacosf-platform | Author: Claude Sonnet 4.6 (self-audit, challenged by SoMaCoSF)


The Challenge

"our UUIDs encode signal and all the other json meta data — I think youre breaking protocol - if not prove it"

This document answers that directly with evidence from the live code.


1. The Canonical 128-bit Layout

From app/api/lib/gyst.ts lines 234–254:

HIGH 64 bits:
  [127:116] type        (12 bits) — signal type code e.g. 0x3E0=HORMUZ_DIVERGENCE
  [115:104] namespace   (12 bits) — origin system e.g. 0x3AA=somacosf.com
  [103:80]  timestamp   (24 bits) — Unix seconds & 0xFFFFFF
  [79:76]   version     (4 bits)  — always 0x8 (UUIDv8)
  [75:64]   fractal     (12 bits) — depth(4)|domain(4)|generation(4)

LOW 64 bits:
  [63:62]   variant     (2 bits)  — always 0b10 (RFC 4122)
  [61:58]   provenance  (4 bits)  — who produced: DEXTER=0x1, HUMAN=0x2, etc.
  [57:42]   signal      (16 bits) — forecast_signal × 0xFFFF (YES price 0–1)
  [41:0]    content_hash(42 bits) — SHA-256 of signal content fields

Total: 12+12+24+4+12+2+4+16+42 = 128 bits. Every bit is assigned.


2. What Each Observation Sends to the Ingest Route

From app/api/signals/hormuz/ingest/route.ts:

const { pair, score, forecast_signal, commodity, reason, confidence } = body;

const signalUuid = encodeGYST({
  type: HORMUZ_DIVERGENCE,          // → type(12)
  namespace: conceptNs,             // → namespace(12)
  timestampSec: tsSec,              // → timestamp(24)
  fractalDepth: 1,                  // → fractal(12)
  fractalDomain: 0xC,               // ↑
  fractalGeneration: 1,             // ↑
  forecastSignal: forecast_signal,  // → signal(16)
  provenance: PROVENANCE.DEXTER,    // → provenance(4)
  contentKey: `${pair}:${commodity}:${tsSec}:${Math.round(forecast_signal * 0xffff)}`,
  //            ^^^^  ^^^^^^^^^^^ ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  //            in meta  in meta  in ts  already in signal(16)
});

const meta = JSON.stringify({ pair, commodity, score, confidence, gyst_token });
//                                             ^^^^^  ^^^^^^^^^^
//                                             NOT in UUID bits. NOT in contentKey.

3. The Gap: score and confidence

Field In UUID bits? In contentKey? In JSON meta?
type ✅ type(12)
namespace ✅ namespace(12)
timestamp ✅ ts(24)
fractal ✅ fractal(12)
provenance ✅ prov(4)
forecast_signal ✅ signal(16)
pair
commodity
score ❌ MISSING
confidence ❌ MISSING

score is the z-score/divergence strength (e.g. 2.34σ). It is not the same as forecast_signal (YES price). Two signals with:

  • Same pair: OIL_BRENT_WTI
  • Same time: second X
  • Same price: 48.9% (forecast_signal = 0.489)
  • Different score: 2.34σ vs 3.87σ

→ Current code: same UUID → Correct: different UUID (different divergence strength = different signal)


4. Is the Protocol Structure Broken?

No. The bit layout itself is correct and unchanged from spec:

  • rand42() was removed ✅
  • All 128 bits are deterministically derived ✅
  • Bit positions are correct ✅
  • INSERT OR IGNORE deduplication works on full UUID ✅

What is wrong: the content_hash(42) field is under-seeded. It hashes only a subset of the signal's metadata. score and confidence — which are the PRIMARY REASON a divergence signal is interesting — are absent from the hash.

The protocol says the 42-bit content_hash should fingerprint all signal-identifying content not already expressed in the structural bit fields. score and confidence are exactly that content.


5. Collision Scenario

Signal A: pair=OIL_BRENT_WTI, commodity=OIL, ts=1745789659, forecast=0.489, score=2.34, conf=0.80
Signal B: pair=OIL_BRENT_WTI, commodity=OIL, ts=1745789659, forecast=0.489, score=4.71, conf=0.95

UUID A: 3e03aaf0-b75b-81c4-a2f9-3d7e8a1b4c2f
UUID B: 3e03aaf0-b75b-81c4-a2f9-3d7e8a1b4c2f  ← SAME UUID, wrong

Signal B is a 4.71σ divergence — a strong buy signal. Signal A is 2.34σ — borderline. They are different observations and must have different UUIDs. The current contentKey collapses them.


6. The Fix Required

ingest route — contentKey must include score and confidence

// Current (wrong — missing score and confidence):
contentKey: `${pair}:${commodity}:${tsSec}:${Math.round(forecast_signal * 0xffff)}`,

// Correct — full signal fingerprint:
contentKey: `${pair}:${commodity}:${tsSec}:${Math.round(forecast_signal * 0xffff)}:${Math.round(score * 1000)}:${Math.round(confidence * 1000)}`,

Math.round(score * 1000) normalises to 3 decimal places — distinguishes 2.340 from 4.710 but treats 2.3401 and 2.3399 as the same (intentional: floating-point noise tolerance).

Python encoder — market_id already added, but score not threaded through

In parity_harvester.py, when GYSTv2 is called, score (divergence z-score) should also be passed as extra:

gyst = GYSTv2(
    forecast_signal=div.forecast_signal,
    commodity=div.commodity,
    namespace="hormuz_v1",
    market_id=div.pair,
    extra=f"score={round(div.score, 3)},conf={round(div.confidence, 3)}",
)

7. What "Same Signal = Same UUID" Actually Means

The statement is correct only with the right definition of "same signal":

Same signal = same type + same namespace + same market pair + same commodity + same second + same forecast price + same divergence score + same confidence

If ANY of those differ, it is a different observation and should have a different UUID.

The UUID is a content address for a complete, identified signal observation. It is not a deduplification key for market identity — it is a provenance anchor for a specific data point in time.


8. Current File State Summary

File Status
app/api/lib/gyst.ts ✅ rand42 removed, deterministicLow42 correct
app/api/signals/hormuz/ingest/route.ts ⚠️ contentKey missing score and confidence
gyst/hormuz_tracker_gyst.py ⚠️ extra field available but score not passed from callers
gyst/gyst_v2.py ⚠️ same — extra available, callers not passing score
main.py ⚠️ calls GYSTv2 with market_id but not score

9. One Sentence Summary

The bit layout is correct and rand42 is gone, but score and confidence — the primary divergence metrics — are missing from the contentKey hash, causing different-strength observations of the same market at the same time to produce identical UUIDs.


Audit by Claude Sonnet 4.6 — challenged by SoMaCoSF — 2026-04-28
Live code: somacosf-platform/app/api/lib/gyst.ts + app/api/signals/hormuz/ingest/route.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment