tiny.machine.explore.query
Defined in explore.
Once a run fails, the next questions are which choice, message, or fault led there, and where the failing run first parted from one that passed.
API (46)
Actions
Public operations.
DiffHistory: Returns a history type that records one run in arrays sized by the capacity, so a caller records one run into it, seals it withfinish, and then hands it to queries and comparisons or stores its bytes.Identity.hexQueryRootDifference.anydecodeRefencodeRef
Types and contracts
Public types and contracts.
CapacityChoicePatternCursorDiffCapacityDiffCompletionDiffIncompleteReasonDiffResultDivergenceDivergenceReasonEffectPatternEffectPhaseErrorEvidenceEvidenceRangeEvidenceRefFaultPatternFrameFramePairFrameRefsIdentityIncompleteReasonKindLocatedPacketActionPacketPatternPatternQueryCapacityQueryCompletionQueryOrderQueryPlanQueryResultQueryScopeRefWireRootDifferenceTargetTerminalDirectionTerminalPatternViewVirtualTimeRange
Source
Source: lib/machine/src/explore/query/types.zig:8
pub const Capacity = struct { frames: u16, evidence: u16,};Source: lib/machine/src/explore/query/types.zig:73
Source: lib/machine/src/explore/query/types.zig:130
pub const Cursor = struct { history: Identity, offset: u32, first: u32, end: u32, order: QueryOrder,};Source: lib/machine/src/explore/query/types.zig:201
pub const DiffCapacity = struct { prefix: u16, suffix: u16,};Source: lib/machine/src/explore/query/types.zig:243
pub const DiffCompletion = union(enum) { complete, incomplete: DiffIncompleteReason,};Source: lib/machine/src/explore/query/types.zig:236
pub const DiffIncompleteReason = enum(u8) { prefix_capacity = 1, suffix_capacity = 2, work_budget = 3, source_incomplete = 4,};Source: lib/machine/src/explore/query/types.zig:248
pub const DiffResult = struct { prefix: []const FramePair, left_suffix: []const FrameRefs, right_suffix: []const FrameRefs, divergence: ?Divergence, compared: u32, completion: DiffCompletion,};Source: lib/machine/src/explore/query/types.zig:229
pub const Divergence = struct { reason: DivergenceReason, left: ?FrameRefs, right: ?FrameRefs, roots: RootDifference,};Source: lib/machine/src/explore/query/types.zig:222
pub const DivergenceReason = enum(u8) { choice = 1, evidence = 2, root = 3, length = 4,};Source: lib/machine/src/explore/query/types.zig:103
pub const EffectPattern = struct { correlation: ?u64 = null, phase: ?EffectPhase = null, status: ?os.abi.EffectStatus = null,};Source: lib/machine/src/explore/query/types.zig:96
pub const EffectPhase = enum(u8) { choice = 1, request = 2, result = 3, operation = 4,};Source: lib/machine/src/explore/query/types.zig:21
pub const Evidence = union(enum) { transition: fabric.transition.Wire, machine: os.abi.MessageWire, semantic: explore.Event,};Source: lib/machine/src/explore/query/types.zig:191
pub const EvidenceRange = struct { first: ?EvidenceRef, count: u16,};Source: lib/machine/src/explore/query/types.zig:40
Source: lib/machine/src/explore/query/types.zig:91
Source: lib/machine/src/explore/query/types.zig:27
pub const Frame = struct { decision: explore.SearchDecision, expected: world.Moment, evidence_start: u16, evidence_count: u16,};Source: lib/machine/src/explore/query/types.zig:196
Source: lib/machine/src/explore/query/types.zig:185
pub const FrameRefs = struct { choice: EvidenceRef, evidence: EvidenceRange, root: EvidenceRef,};Source: lib/machine/src/explore/query/types.zig:13
pub const Identity = struct { digest: [32]u8, pub fn hex(self: Identity) [64]u8 { return std.fmt.bytesToHex(self.digest, .lower); }};Source: lib/machine/src/explore/query/types.zig:167
pub const IncompleteReason = enum(u8) { result_capacity = 1, work_budget = 2, source_incomplete = 3,};Source: lib/machine/src/explore/query/types.zig:59
pub const Kind = enum(u8) { all = 1, choice = 2, scheduler = 3, root = 4, semantic = 5, transition = 6, machine = 7, packet = 8, fault = 9, effect = 10, terminal = 11,};Source: lib/machine/src/explore/query/types.zig:52
pub const Located = struct { reference: EvidenceRef, frame: ?u16, virtual_time_tick: ?u64, view: View,};Source: lib/machine/src/explore/query/types.zig:77
pub const PacketAction = enum(u8) { choose = 1, send = 2, deliver = 3, drop = 4, delay = 5, reorder = 6,};Source: lib/machine/src/explore/query/types.zig:86
pub const PacketPattern = struct { id: ?u64 = null, action: ?PacketAction = null,};Source: lib/machine/src/explore/query/types.zig:120
pub const Pattern = union(enum) { kind: Kind, choice: ChoicePattern, semantic: explore.Pattern, packet: PacketPattern, fault: FaultPattern, effect: EffectPattern, terminal: TerminalPattern,};Source: lib/machine/src/explore/query/types.zig:154
pub const QueryCapacity = struct { results: u16,};Source: lib/machine/src/explore/query/types.zig:173
pub const QueryCompletion = union(enum) { complete, incomplete: IncompleteReason,};Source: lib/machine/src/explore/query/types.zig:138
pub const QueryOrder = enum(u8) { forward = 1, reverse = 2,};Source: lib/machine/src/explore/query/types.zig:158
pub const QueryPlan = struct { pattern: Pattern, work: u32, scope: QueryScope = .branch, order: QueryOrder = .forward, virtual_time: ?VirtualTimeRange = null, cursor: ?Cursor = null,};Source: lib/machine/src/explore/query/types.zig:178
pub const QueryResult = struct { matches: []const EvidenceRef, inspected: u32, next: ?Cursor, completion: QueryCompletion,};Source: lib/machine/src/explore/query/types.zig:143
pub const QueryScope = union(enum) { branch, before: EvidenceRef, after: EvidenceRef,};Source: lib/machine/src/explore/query/types.zig:206
pub const RootDifference = struct { moment_digest: bool = false, origin: bool = false, fabric_digest: bool = false, contract: bool = false, entry_frontier: bool = false, admission_frontier: bool = false, fault_frontier: bool = false, pub fn any(self: RootDifference) bool { return self.moment_digest or self.origin or self.fabric_digest or self.contract or self.entry_frontier or self.admission_frontier or self.fault_frontier; }};Source: lib/machine/src/explore/query/types.zig:34
pub const Target = enum(u8) { choice = 1, root = 2, record = 3,};Source: lib/machine/src/explore/query/types.zig:109
pub const TerminalDirection = enum(u8) { either = 1, input = 2, output = 3,};Source: lib/machine/src/explore/query/types.zig:115
pub const TerminalPattern = struct { direction: TerminalDirection = .either, offset: ?u64 = null,};Source: lib/machine/src/explore/query/types.zig:46
pub const View = union(Target) { choice: *const explore.SearchDecision, root: *const world.Moment, record: *const Evidence,};Source: lib/machine/src/explore/query/types.zig:149
pub const VirtualTimeRange = struct { first: u64, last: u64,};Source: lib/machine/src/explore/query/canon.zig:25
pub const RefWire = [80]u8;Source: lib/machine/src/explore/query/canon.zig:127
pub fn decodeRef(input: *const RefWire) types.Error!types.EvidenceRef { if (!std.mem.eql(u8, input[0..8], &ref_magic)) { return error.EvidenceRefBadMagic; } if (get(u16, input, 8) != version) { return error.EvidenceRefVersionUnsupported; } if (input[11] != flags or !os.abi.wire.allZero(input[14..16])) { return error.EvidenceRefFieldInvalid; } var expected: [digest_bytes]u8 = undefined; var hasher = Sha256.init(.{}); hasher.update(ref_domain); hasher.update(&.{0}); hasher.update(input[0..48]); hasher.final(&expected); if (!std.mem.eql(u8, &expected, input[48..80])) { return error.EvidenceRefFieldInvalid; } return .{ .history = .{ .digest = input[16..48].* }, .target = try enumValue(types.Target, input[10]), .index = get(u16, input, 12), };}Source: lib/machine/src/explore/query/canon.zig:109
pub fn encodeRef(value: types.EvidenceRef, output: *RefWire) void { var encoded: RefWire = @splat(0); @memcpy(encoded[0..8], &ref_magic); put(u16, &encoded, 8, version); encoded[10] = @backingInt(value.target); encoded[11] = flags; put(u16, &encoded, 12, value.index); @memcpy(encoded[16..48], &value.history.digest); var hasher = Sha256.init(.{}); hasher.update(ref_domain); hasher.update(&.{0}); hasher.update(encoded[0..48]); var digest: [digest_bytes]u8 = undefined; hasher.final(&digest); @memcpy(encoded[48..80], &digest); output.* = encoded;}Source: lib/machine/src/explore/query/engine.zig:159
pub fn Diff(comptime capacity_value: types.DiffCapacity) type { return struct { prefix_storage: [capacity.prefix]types.FramePair = undefined, left_storage: [capacity.suffix]types.FrameRefs = undefined, right_storage: [capacity.suffix]types.FrameRefs = undefined, prefix_count: u16 = 0, left_count: u16 = 0, right_count: u16 = 0, const Self = @This(); pub const capacity: types.DiffCapacity = capacity_value; pub fn run( self: *Self, left: anytype, right: anytype, work: u32, ) types.Error!types.DiffResult { self.reset(); _ = try left.identity(); _ = try right.identity(); if (!std.meta.eql(left.start, right.start)) return error.RootStartMismatch; const common: usize = @min(left.frames().len, right.frames().len); var compared: u32 = 0; var divergence_index: ?usize = null; var divergence_reason: ?types.DivergenceReason = null; for (0..common) |index| { if (compared == work) { return self.incomplete(compared, null, .work_budget); } const left_frame = left.frames()[index]; const right_frame = right.frames()[index]; compared += 1; const choices_equal = std.meta.eql( left_frame.decision, right_frame.decision, ); const evidence_equal = evidenceEqual( try left.frameEvidence(@intCast(index)), try right.frameEvidence(@intCast(index)), ); const roots_equal = std.meta.eql( left_frame.expected, right_frame.expected, ); if (choices_equal and evidence_equal and roots_equal) { if (self.prefix_count == capacity.prefix) { return self.incomplete(compared, null, .prefix_capacity); } self.prefix_storage[self.prefix_count] = .{ .left = try left.frameRefs(@intCast(index)), .right = try right.frameRefs(@intCast(index)), }; self.prefix_count += 1; continue; } divergence_index = index; divergence_reason = if (!choices_equal) .choice else if (!evidence_equal) .evidence else .root; break; } if (divergence_index == null and left.frames().len != right.frames().len) { divergence_index = common; divergence_reason = .length; } const divergence = if (divergence_index) |index| try divergenceValue(left, right, index, divergence_reason.?) else null; if (divergence_index) |index| { const suffix_incomplete = try self.collectSuffixes( left, right, index, common, work, &compared, ); if (suffix_incomplete) |reason| { return self.incomplete(compared, divergence, reason); } } if (left.traceState() == .incomplete or right.traceState() == .incomplete) { return self.incomplete(compared, divergence, .source_incomplete); } return self.complete(compared, divergence); } fn collectSuffixes( self: *Self, left: anytype, right: anytype, first: usize, common: usize, work: u32, compared: *u32, ) types.Error!?types.DiffIncompleteReason { const end = @max(left.frames().len, right.frames().len); for (first..end) |index| { const already_inspected = index == first and first < common; if (!already_inspected) { if (compared.* == work) return .work_budget; compared.* += 1; } if (index < left.frames().len) { if (self.left_count == capacity.suffix) return .suffix_capacity; self.left_storage[self.left_count] = try left.frameRefs(@intCast(index)); self.left_count += 1; } if (index < right.frames().len) { if (self.right_count == capacity.suffix) return .suffix_capacity; self.right_storage[self.right_count] = try right.frameRefs(@intCast(index)); self.right_count += 1; } } return null; } fn complete( self: *const Self, compared: u32, divergence: ?types.Divergence, ) types.DiffResult { return .{ .prefix = self.prefix_storage[0..self.prefix_count], .left_suffix = self.left_storage[0..self.left_count], .right_suffix = self.right_storage[0..self.right_count], .divergence = divergence, .compared = compared, .completion = .complete, }; } fn incomplete( self: *const Self, compared: u32, divergence: ?types.Divergence, reason: types.DiffIncompleteReason, ) types.DiffResult { var result = self.complete(compared, divergence); result.completion = .{ .incomplete = reason }; return result; } fn reset(self: *Self) void { self.prefix_count = 0; self.left_count = 0; self.right_count = 0; } };}Source: lib/machine/src/explore/query/engine.zig:9
pub fn Query(comptime capacity_value: types.QueryCapacity) type { if (capacity_value.results == 0) { @compileError("query result capacity must be positive"); } return struct { storage: [capacity.results]types.EvidenceRef = undefined, count: u16 = 0, const Self = @This(); pub const capacity: types.QueryCapacity = capacity_value; pub fn run( self: *Self, history: anytype, plan: types.QueryPlan, ) types.Error!types.QueryResult { self.count = 0; const identity = try history.identity(); const total = history.logicalCount(); const range = try queryRange(history, plan.scope, total); if (plan.virtual_time) |window| { if (window.first > window.last) return error.InvalidQueryPlan; } var offset = if (plan.cursor) |cursor| cursor.offset else 0; if (plan.cursor) |cursor| { if (!std.meta.eql(cursor.history, identity)) { return error.CursorHistoryMismatch; } if (cursor.first != range.first or cursor.end != range.end or cursor.order != plan.order) { return error.CursorPlanMismatch; } } const span = range.end - range.first; if (offset > span) return error.EvidenceIndexInvalid; var inspected: u32 = 0; while (offset < span and inspected < plan.work) { const logical_offset = switch (plan.order) { .forward => range.first + offset, .reverse => range.end - 1 - offset, }; const reference = try history.referenceAt(logical_offset); const located = try history.lookup(reference); inspected += 1; offset += 1; if (!withinTime(plan.virtual_time, located.virtual_time_tick)) { continue; } if (!try matches(plan.pattern, located)) continue; self.storage[self.count] = reference; self.count += 1; if (self.count == capacity.results and offset < span) { return self.result( identity, inspected, range, plan.order, offset, .result_capacity, ); } } if (offset < span) { return self.result( identity, inspected, range, plan.order, offset, .work_budget, ); } if (history.traceState() == .incomplete and sourceCanGrow(plan.scope)) { return self.result( identity, inspected, range, plan.order, offset, .source_incomplete, ); } return .{ .matches = self.storage[0..self.count], .inspected = inspected, .next = null, .completion = .complete, }; } fn result( self: *const Self, identity: types.Identity, inspected: u32, range: Range, order: types.QueryOrder, offset: u32, reason: types.IncompleteReason, ) types.QueryResult { return .{ .matches = self.storage[0..self.count], .inspected = inspected, .next = .{ .history = identity, .offset = offset, .first = range.first, .end = range.end, .order = order, }, .completion = .{ .incomplete = reason }, }; } };}Source: lib/machine/src/explore/query/history.zig:31
/// Returns a history type that records one run in arrays sized by the capacity,/// so a caller records one run into it, seals it with `finish`, and then hands/// it to queries and comparisons or stores its bytes. The record starts with/// the run's start *moment*, a position in a world's history. Each step of the/// history (*frame*) holds one alternative taken at a step, the moment reached,/// and the evidence records the step produced. Each evidence record is one of/// three things: an encoded ledger entry, an encoded event message from the/// guest kernel, or an event recorded for checking rules. A frame or evidence/// capacity of zero stops the build with a compile error. While the history is/// open, each record attaches to the latest frame, and `appendFrame` rejects a/// moment that fails to follow the previous one. `finish` checks the whole/// history, marks it exhausted or incomplete, writes the one fixed-size byte/// encoding of a sealed history, and records its SHA-256 identity. A failed/// `finish` leaves the history as it was. After `finish`, every append returns/// `HistorySealed`, so the sealed history stays fixed. Until `finish`,/// `identity`, `encode`, `frameEvidence`, `referenceAt`, `frameRefs`, and/// `lookup` return `HistoryOpen`. Each reference carries the history's/// identity, a target, and an index, and `lookup` rejects a reference made from/// any other history. `decode` rejects bytes that fail to encode back to the/// same bytes. The history holds no pointers.pub fn History(comptime capacity_value: types.Capacity) type { requireCapacity(capacity_value); return struct { start: world.Moment, frames_storage: [capacity.frames]types.Frame = undefined, evidence_storage: [capacity.evidence]types.Evidence = undefined, frame_count: u16 = 0, evidence_count: u16 = 0, state: explore.TraceState = .open, identity_value: types.Identity = .{ .digest = @splat(0) }, const Self = @This(); pub const capacity: types.Capacity = capacity_value; pub const Error: type = types.Error; pub const RefWire: type = canon.RefWire; pub const Wire: type = canon.Wire(capacity); pub fn init(start: world.Moment) Error!Self { try world.verifyMoment(start, start.origin, start.fabric); return .{ .start = start }; } pub fn decode(input: *const Wire) Error!Self { var result: Self = undefined; try canon.decode(capacity, input, &result); return result; } pub fn encode(self: *const Self, output: *Wire) Error!void { try self.requirePublished(); try canon.encode(capacity, self, output); const actual = try canon.identity(capacity, output); if (!std.meta.eql(actual, self.identity_value)) { return error.CanonicalIdentityMismatch; } } pub fn finish( self: *Self, completion: explore.TraceCompletion, output: *Wire, ) Error!types.Identity { if (self.state != .open) return error.HistorySealed; var candidate = self.*; candidate.state = switch (completion) { .exhausted => .exhausted, .incomplete => .incomplete, }; try candidate.validate(); try canon.encode(capacity, &candidate, output); candidate.identity_value = try canon.identity(capacity, output); self.* = candidate; return self.identity_value; } pub fn appendFrame( self: *Self, decision: explore.SearchDecision, expected: world.Moment, ) Error!u16 { try self.requireOpen(); if (self.frame_count == capacity.frames) { return error.FrameCapacityExceeded; } try validateDecision(decision); const previous = self.lastMoment(); if (!momentFollows(previous, expected)) { return error.FrameSequenceInvalid; } const id = self.frame_count; self.frames_storage[id] = .{ .decision = decision, .expected = expected, .evidence_start = self.evidence_count, .evidence_count = 0, }; self.frame_count += 1; return id; } pub fn appendTransition( self: *Self, frame: u16, wire: fabric.transition.Wire, ) Error!void { _ = try fabric.transition.inspect(&wire); try self.appendEvidence(frame, .{ .transition = wire }); } pub fn appendMachine( self: *Self, frame: u16, wire: os.abi.MessageWire, ) Error!void { _ = try os.abi.decodeEvent(&wire); try self.appendEvidence(frame, .{ .machine = wire }); } pub fn appendBatch( self: *Self, frame: u16, batch: *const instance.EventBatch, ) Error!void { try self.requireLatestFrame(frame); if (batch.count > batch.storage.len) { return error.EvidenceSequenceInvalid; } const remaining = capacity.evidence - self.evidence_count; if (batch.count > remaining) return error.EvidenceCapacityExceeded; for (batch.frames()) |wire| try self.appendMachine(frame, wire); } pub fn appendSemantic( self: *Self, frame: u16, event: explore.Event, ) Error!void { try validateSemantic(event); try self.appendEvidence(frame, .{ .semantic = event }); } pub fn frames(self: *const Self) []const types.Frame { std.debug.assert(self.frame_count <= capacity.frames); return self.frames_storage[0..self.frame_count]; } pub fn evidence(self: *const Self) []const types.Evidence { std.debug.assert(self.evidence_count <= capacity.evidence); return self.evidence_storage[0..self.evidence_count]; } pub fn frameEvidence( self: *const Self, frame: u16, ) Error![]const types.Evidence { try self.requirePublished(); if (frame >= self.frame_count) return error.EvidenceFrameInvalid; const retained = self.frames_storage[frame]; const end = retained.evidence_start + retained.evidence_count; return self.evidence_storage[retained.evidence_start..end]; } pub fn traceState(self: *const Self) explore.TraceState { return self.state; } pub fn identity(self: *const Self) Error!types.Identity { try self.requirePublished(); return self.identity_value; } pub fn logicalCount(self: *const Self) u32 { const frames_count: u32 = self.frame_count; const evidence_count_value: u32 = self.evidence_count; return 1 + frames_count * 2 + evidence_count_value; } pub fn referenceAt( self: *const Self, offset: u32, ) Error!types.EvidenceRef { try self.requirePublished(); if (offset >= self.logicalCount()) return error.EvidenceIndexInvalid; if (offset == 0) return self.makeRef(.root, 0); var cursor: u32 = 1; for (self.frames(), 0..) |frame, frame_index| { if (cursor == offset) return self.makeRef(.choice, @intCast(frame_index)); cursor += 1; for (0..frame.evidence_count) |record_offset| { if (cursor == offset) { const index = frame.evidence_start + @as(u16, @intCast(record_offset)); return self.makeRef(.record, index); } cursor += 1; } if (cursor == offset) return self.makeRef(.root, @intCast(frame_index + 1)); cursor += 1; } unreachable; } pub fn frameRefs(self: *const Self, frame: u16) Error!types.FrameRefs { try self.requirePublished(); if (frame >= self.frame_count) return error.EvidenceFrameInvalid; return .{ .choice = self.makeRef(.choice, frame), .evidence = .{ .first = if (self.frames_storage[frame].evidence_count == 0) null else self.makeRef( .record, self.frames_storage[frame].evidence_start, ), .count = self.frames_storage[frame].evidence_count, }, .root = self.makeRef(.root, frame + 1), }; } pub fn logicalOffset( self: *const Self, reference: types.EvidenceRef, ) Error!u32 { _ = try self.lookup(reference); if (reference.target == .root and reference.index == 0) return 0; var offset: u32 = 1; for (self.frames(), 0..) |frame, frame_index| { if (reference.target == .choice and reference.index == frame_index) { return offset; } offset += 1; if (reference.target == .record and reference.index >= frame.evidence_start and reference.index < frame.evidence_start + frame.evidence_count) { return offset + reference.index - frame.evidence_start; } offset += frame.evidence_count; if (reference.target == .root and reference.index == frame_index + 1) { return offset; } offset += 1; } unreachable; } pub fn lookup( self: *const Self, reference: types.EvidenceRef, ) Error!types.Located { try self.requirePublished(); if (!std.meta.eql(reference.history, self.identity_value)) { return error.EvidenceHistoryMismatch; } return switch (reference.target) { .choice => self.lookupChoice(reference), .root => self.lookupRoot(reference), .record => self.lookupRecord(reference), }; } pub fn validate(self: *const Self) Error!void { if (self.frame_count > capacity.frames or self.evidence_count > capacity.evidence) { return error.EvidenceWireCapacityMismatch; } try world.verifyMoment(self.start, self.start.origin, self.start.fabric); var previous = self.start; var evidence_cursor: u16 = 0; var semantic_previous: ?explore.Event = null; for (self.frames()) |frame| { try validateDecision(frame.decision); if (!momentFollows(previous, frame.expected)) return error.FrameSequenceInvalid; if (frame.evidence_start != evidence_cursor or frame.evidence_count > self.evidence_count - evidence_cursor) { return error.EvidenceSequenceInvalid; } try self.validateFrameEvidence( frame, previous.fabric, &semantic_previous, ); evidence_cursor += frame.evidence_count; previous = frame.expected; } if (evidence_cursor != self.evidence_count) { return error.EvidenceSequenceInvalid; } } fn appendEvidence( self: *Self, frame: u16, value: types.Evidence, ) Error!void { try self.requireLatestFrame(frame); if (self.evidence_count == capacity.evidence) { return error.EvidenceCapacityExceeded; } self.evidence_storage[self.evidence_count] = value; self.evidence_count += 1; self.frames_storage[frame].evidence_count += 1; } fn validateFrameEvidence( self: *const Self, frame: types.Frame, previous_root: fabric.Root, semantic_previous: *?explore.Event, ) Error!void { var transition_root = previous_root; var transition_seen = false; const end = frame.evidence_start + frame.evidence_count; for (self.evidence_storage[frame.evidence_start..end]) |record| { switch (record) { .transition => |wire| { const inspected = try fabric.transition.inspect(&wire); try validateTransition(transition_root, inspected); transition_root = inspected.result; transition_seen = true; }, .machine => |wire| _ = try os.abi.decodeEvent(&wire), .semantic => |event| { try validateSemantic(event); if (semantic_previous.*) |prior| { if (event.sequence <= prior.sequence or event.virtual_time_tick < prior.virtual_time_tick) { return error.EvidenceSequenceInvalid; } } semantic_previous.* = event; }, } } if (transition_seen and !std.meta.eql(transition_root, frame.expected.fabric)) { return error.EvidenceSequenceInvalid; } } fn lastMoment(self: *const Self) world.Moment { return if (self.frame_count == 0) self.start else self.frames_storage[self.frame_count - 1].expected; } fn lookupChoice( self: *const Self, reference: types.EvidenceRef, ) Error!types.Located { if (reference.index >= self.frame_count) return error.EvidenceIndexInvalid; return .{ .reference = reference, .frame = reference.index, .virtual_time_tick = self.frames_storage[reference.index] .decision.site.virtual_time_tick, .view = .{ .choice = &self.frames_storage[reference.index].decision }, }; } fn lookupRoot( self: *const Self, reference: types.EvidenceRef, ) Error!types.Located { if (reference.index > self.frame_count) return error.EvidenceIndexInvalid; if (reference.index == 0) return .{ .reference = reference, .frame = null, .virtual_time_tick = null, .view = .{ .root = &self.start }, }; return .{ .reference = reference, .frame = reference.index - 1, .virtual_time_tick = self.frames_storage[reference.index - 1] .decision.site.virtual_time_tick, .view = .{ .root = &self.frames_storage[reference.index - 1].expected }, }; } fn lookupRecord( self: *const Self, reference: types.EvidenceRef, ) Error!types.Located { if (reference.index >= self.evidence_count) return error.EvidenceIndexInvalid; const frame = self.frameForRecord(reference.index); return .{ .reference = reference, .frame = frame, .virtual_time_tick = (try recordTick( self.evidence_storage[reference.index], )) orelse self.frames_storage[frame].decision.site.virtual_time_tick, .view = .{ .record = &self.evidence_storage[reference.index] }, }; } fn frameForRecord(self: *const Self, record: u16) u16 { for (self.frames(), 0..) |frame, index| { const end = frame.evidence_start + frame.evidence_count; if (record >= frame.evidence_start and record < end) return @intCast(index); } unreachable; } fn makeRef(self: *const Self, target: types.Target, index: u16) types.EvidenceRef { return .{ .history = self.identity_value, .target = target, .index = index }; } fn requireLatestFrame(self: *const Self, frame: u16) Error!void { try self.requireOpen(); if (self.frame_count == 0 or frame != self.frame_count - 1) { return error.EvidenceFrameInvalid; } } fn requireOpen(self: *const Self) Error!void { if (self.state != .open) return error.HistorySealed; } fn requirePublished(self: *const Self) Error!void { if (self.state == .open) return error.HistoryOpen; } };}Source: lib/machine/src/explore/query/types.zig:283
pub const Error = world.MomentError || fabric.transition.Error || os.abi.message.Error || QueryError;Source: lib/machine/src/explore/query/root.zig
//! Once a run fails, the next questions are which choice, message, or fault led//! there, and where the failing run first parted from one that passed. This//! namespace records one run in order and answers such questions within bounds//! fixed in advance.//!//! The record holds each step's choice, the position the run reached, and what//! the step produced: entries added to the run's ordered log of inputs and//! faults, event messages from the guest kernel, and the events recorded for//! checking rules. A caller asks for the entries that match one question: a//! kind of entry, a kind of choice, a rule event, a packet, a fault, an outside//! effect, or terminal input and output. A caller compares two runs from the//! same start and learns where they first differ.//!//! An answer has to point at entries in a way that still names the same entry//! after the record is stored and read back in another process, and that cannot//! be resolved against a different record. Answers and comparisons have to fit//! fixed storage and bounded work, so a scan cut short has to say so and be//! resumable. A question asked of a run that was itself cut short cannot claim//! a complete answer. A record has to agree with itself: log entries follow one//! another from each position to the next, and rule events move forward in//! number and in time.//!//! Each run becomes an append-only record, a *causal history*: the start//! position, then for each step the choice, the position reached, and the//! entries that step produced. `finish` checks the record, marks it exhausted//! or incomplete, writes its one canonical byte encoding, and records its//! SHA-256 identity, and after that the record changes no more.//!//! Queries (`Query`) and comparisons answer with references into the record,//! each an *evidence reference* made of the record's identity, a target (a//! choice, a reached position, or an entry), and an index, so an answer holds//! no copies of the entries. A reference also travels as an 80-byte encoding//! with its own SHA-256 check. A query reads the record in one fixed order: the//! start, then for each step its choice, its entries, and the position reached.//! A query scans forward or backward, over the whole record or before or after//! a reference, and optionally only inside a window of simulated time. A query//! stops when its result storage fills or its work budget runs out, returns a//! cursor to resume from, and marks the answer incomplete with the reason. A//! query over an incomplete record that could still grow past the scanned range//! reports its answer incomplete as well.//!//! A comparison (`Diff`) walks two sealed records with the same start step by//! step and collects the common prefix of steps equal in choice, entries, and//! reached position. It reports the first step that differs (the *first//! divergence*), with the reason and which fields of the two positions differ.//! A comparison stays inside its prefix capacity, its suffix capacity, and a//! work budget, and it marks the result incomplete when any of them runs out or//! when either record is incomplete. Records, queries, and comparisons hold no//! pointers.//!//! - *moment*: a position in one world's history, pairing the world root the//! world grew from with the ledger root it has reached since.//! - *frame*: one step of a causal history: its decision, the moment it//! reached, and the range of its evidence records.//! - *transition*: one ledger entry together with the ledger root it produces.//! - *semantic event*: one numbered, timestamped entry in the event list a run//! is checked over.//! - *canonical wire*: the one fixed-size byte encoding of a sealed history for//! a given capacity, ending in its SHA-256 identity. Decoding rejects any//! input that does not encode back to the same bytes.const canon = @import("canon.zig");const engine = @import("engine.zig");const history_owner = @import("history.zig");const types = @import("types.zig");pub const Capacity = types.Capacity;pub const ChoicePattern = types.ChoicePattern;pub const Cursor = types.Cursor;pub const Diff = engine.Diff;pub const DiffCapacity = types.DiffCapacity;pub const DiffCompletion = types.DiffCompletion;pub const DiffIncompleteReason = types.DiffIncompleteReason;pub const DiffResult = types.DiffResult;pub const Divergence = types.Divergence;pub const DivergenceReason = types.DivergenceReason;pub const EffectPattern = types.EffectPattern;pub const EffectPhase = types.EffectPhase;pub const Error = types.Error;pub const Evidence = types.Evidence;pub const EvidenceRange = types.EvidenceRange;pub const EvidenceRef = types.EvidenceRef;pub const FaultPattern = types.FaultPattern;pub const Frame = types.Frame;pub const FramePair = types.FramePair;pub const FrameRefs = types.FrameRefs;pub const History = history_owner.History;pub const Identity = types.Identity;pub const IncompleteReason = types.IncompleteReason;pub const Kind = types.Kind;pub const Located = types.Located;pub const PacketAction = types.PacketAction;pub const PacketPattern = types.PacketPattern;pub const Pattern = types.Pattern;pub const Query = engine.Query;pub const QueryCapacity = types.QueryCapacity;pub const QueryCompletion = types.QueryCompletion;pub const QueryPlan = types.QueryPlan;pub const QueryOrder = types.QueryOrder;pub const QueryResult = types.QueryResult;pub const QueryScope = types.QueryScope;pub const RefWire = canon.RefWire;pub const RootDifference = types.RootDifference;pub const Target = types.Target;pub const TerminalDirection = types.TerminalDirection;pub const TerminalPattern = types.TerminalPattern;pub const View = types.View;pub const VirtualTimeRange = types.VirtualTimeRange;pub const decodeRef = canon.decodeRef;pub const encodeRef = canon.encodeRef;Source: lib/machine/src/explore/root.zig:83
pub const query = @import("query/root.zig");Complete call list for explore.query.History
7 direct calls.
lib.machine.src.explore.query.history.momentFollows[function] — private source atlib/machine/src/explore/query/history.zig:530in nearest public ownerlib.machine.src.explore.query.historylib.machine.src.explore.query.history.recordTick[function] — private source atlib/machine/src/explore/query/history.zig:455in nearest public ownerlib.machine.src.explore.query.historylib.machine.src.explore.query.history.requireCapacity[function] — private source atlib/machine/src/explore/query/history.zig:537in nearest public ownerlib.machine.src.explore.query.historylib.machine.src.explore.query.history.validateDecision[function] — private source atlib/machine/src/explore/query/history.zig:487in nearest public ownerlib.machine.src.explore.query.historylib.machine.src.explore.query.history.validateSemantic[function] — private source atlib/machine/src/explore/query/history.zig:441in nearest public ownerlib.machine.src.explore.query.historylib.machine.src.explore.query.history.validateTransition[function] — private source atlib/machine/src/explore/query/history.zig:500in nearest public ownerlib.machine.src.explore.query.historylib.machine.src.fabric.transition.inspect[module] — private; no exact target atlib/machine/src/fabric/transition/inspect.zig
Audit
| Definitions | 47 |
|---|---|
| Public names | 47 |
| Members | 128 |
| Version | 26.7.0 |
| Revision | daab053ee433 |