Skip to content

v2026.7.21: SPEC-236 Phase C — SBI PromiseId + Schema Fingerprints

v2026.7.21: SPEC-236 Phase C — SBI PromiseId + Schema Fingerprints

Section titled “v2026.7.21: SPEC-236 Phase C — SBI PromiseId + Schema Fingerprints”

Phase C hardens the identity of a local Promise[T]. Phase A made the cell safe; Phase B made request/response pleasant. Phase C makes the handle an SBI-shaped PromiseId and fails closed on stale epoch or schema mismatch.

Promise[T] remains a single u64 SBI scalar in Janus source. The runtime packs:

BitsFieldNotes
[63:48]authority_scopeLocal default 1 (ID_SCOPE_LOCAL)
[47:32]epochProcess runtime epoch
[31:0]slotMap key; 0 is invalid

Every bridge access unpacks the handle and rejects wrong scope, wrong epoch, or a destroyed/missing slot ([PROM:6.2]).

use std.cluster.promise as promise
let p: Promise[u64] = promise.new[u64]()
let slot = promise.id_slot[u64](p)
let epoch = promise.id_epoch[u64](p)
let scope = promise.id_scope[u64](p)
// scope == promise.ID_SCOPE_LOCAL

After promise.runtime_reset(), prior handles are stale: resolve / await / destroy fail closed. New promises stamp the advanced epoch.

Create a promise that expects a result schema fingerprint. On resolve, pass the actual fingerprint. Mismatch transitions the promise to Failed(SchemaMismatch) and returns 0.

let expected: u64 = 0xA11CE001 as u64
let wrong: u64 = 0xB0B00002 as u64
let p = promise.new_with_schema[u64](expected)
let r = promise.resolver[u64](p)
// Mismatch → fail closed
_ = promise.resolve_with_schema[u64](r, 1 as u64, wrong)
// state == STATE_FAILED, failure_kind == ERR_SCHEMA_MISMATCH
// Match → resolve
let p2 = promise.new_with_schema[u64](expected)
let r2 = promise.resolver[u64](p2)
_ = promise.resolve_with_schema[u64](r2, 55 as u64, expected)
// await_or → 55

promise.new[u64]() remains the unchecked path (expected fingerprint 0): resolve_with_schema still accepts any actual fingerprint.

v0.1 fingerprints are caller-supplied u64 values. Full SBI BLAKE3/u128 type CIDs (SPEC-039) will feed this gate when the compiler emits them.

APIRole
new_with_schema[T](fp)Create with expected fingerprint (0 = unchecked)
resolve_with_schema[T](r, v, fp)Resolve with actual fingerprint
id_slot / id_epoch / id_scopeDecode packed PromiseId fields
runtime_epoch / runtime_resetDiagnostics + restart simulation
ERR_SCHEMA_MISMATCHFailure kind 2
Terminal window
./scripts/zb test-cluster-promise-sbi-id
./scripts/zb test-cluster-promise-sbi-fingerprint
./scripts/zb test-cluster-promise-call-sugar
./scripts/zb test-cluster-promise-request-response
./scripts/zb test-cluster-promise-terminal-states
SPEC-236 phaseStatus
A — local Promise slots✅ Complete
B — .call() sugar (local)✅ Complete
C — SBI PromiseId layout✅ Complete (this release)
D v0.1 — local pipeline graph✅ Complete — Phase D notes
D.1 — wire envelopes + Promise.callDeferred (distributed + compiler)

Full 16-byte on-wire PromiseId (slot:u64 | epoch:u32 | scope:u32) and promise-on-promise pipeline segments remain Phase D.

Full-width hex u64 literals (for example 0xA11CE00000000001) currently collapse to 0 in AOT (Gap 107). Smokes use 32-bit-wide hex constants; the runtime ABI is still u64.

  • std.cluster reference — PromiseId + fingerprint section
  • Phase A · Phase B
  • Monastery: Promise IDs and Schema Fingerprints (07-promise-id-and-schema.md)
  • SPEC-039 §16 — PromiseId local handle form