Skip to main content

ReportOrigin

Enum ReportOrigin 

Source
pub enum ReportOrigin {
    Agent,
    Supervisor,
    RunMerge {
        op_id: Option<String>,
        worker_oid: Option<String>,
    },
}
Expand description

The typed provenance of a node.report — WHO authored it (issue typed-report-origin).

Before this field, supervise::outcome split a terminal report’s outcome by sniffing string conventions: a reason that starts_with("agent-") or is one of a hard-coded set meant “supervisor failure”, and via: "explicit-merge" from any author meant “merged”. Those conventions are brittle (a new supervisor reason silently misclassifies) and conflate the report’s AUTHOR with its content. ReportOrigin records the author explicitly on the event, so the outcome table can read a typed fact instead of pattern-matching prose.

The origin is stamped by the code path that appends the report, never accepted from an untrusted payload: run merge stamps ReportOrigin::RunMerge (the SOLE merge authority — an agent’s node report cannot assert it; that path normalizes any supplied origin back to ReportOrigin::Agent), the supervisor stamps ReportOrigin::Supervisor on every report it synthesizes, and an agent self-submission is ReportOrigin::Agent. This keeps merge authorization tied to the run-merge path exactly as the legacy via marker did — the typed origin is a parallel, higher-fidelity signal, not a new trust boundary.

Serialized under REPORT_ORIGIN_KEY with an internal kind tag, e.g. {"kind": "agent"}, {"kind": "supervisor"}, {"kind": "run-merge", "op_id": "…", "worker_oid": "…"}.

Variants§

§

Agent

The worker agent authored this report itself — a node report self-submission (a success handoff, or a blocked success: false handoff).

§

Supervisor

The supervisor/launcher synthesized this report: a told worker-exit failure, the crash backstop, or a re-spawn-exhausted failure.

§

RunMerge

Stamped by the run merge transaction (or its crash recovery) — the ONLY authority for a merge/success outcome. The immutable transaction OIDs are carried for provenance/forensics; they are absent only on the legacy unguarded merge path (no concrete source branch / stubbed git) where no transaction was recorded, but the discriminant alone still identifies the report as a genuine run merge.

Fields

§op_id: Option<String>

The merge transaction’s op_id, when a transaction was recorded.

§worker_oid: Option<String>

The worker tip OID the merge integrated, when a transaction was recorded.

Implementations§

Source§

impl ReportOrigin

Source

pub fn from_report(report: &Value) -> Option<Self>

Read the typed origin from a report payload, returning None for BOTH an absent origin field (a legacy report written before this field existed) AND a present-but-malformed one (corrupt / hand-edited / a future variant).

IMPORTANT — None does NOT mean “fall back to the legacy via/reason string path”. That fallback is gated on the origin KEY being genuinely ABSENT (report.get(REPORT_ORIGIN_KEY).is_none()), NOT on this returning None. A present-but-malformed origin is “typed, but unknown authority”: it must NEVER re-unlock the forgeable legacy path (a merge on a forged via, a supervisor failure on a spoofed reason). Every consumer (report_is_confirmed_merge, supervise::outcome::classify / is_supervisor_failure) checks key presence separately for exactly this reason — do not collapse the two. See report_is_confirmed_merge.

Source

pub fn report_is_confirmed_merge(report: &Value) -> bool

True when a terminal node.report payload is a CONFIRMED, SUCCESSFUL run merge — the sole authority for a merge/success outcome (issue retire-via-string).

The typed ReportOrigin::RunMerge (stamped only by the run merge transaction / its crash recovery — an agent’s node report is normalized to ReportOrigin::Agent) is the authoritative marker. The legacy via: "explicit-merge" string is honored ONLY as a fallback for a report that carries NO origin field at all — a legacy on-disk report written before the typed origin existed. Gating the via fallback on a genuinely ABSENT origin (not on from_report returning None) is what makes the typed field strictly stronger: a report that DOES carry an origin field — parsed or malformed/hand-edited — never earns merge status on a forged via string alone. This mirrors supervise::outcome::classify’s merge gate exactly, so the reducer, the landed fallback, and run wait’s merged flag all agree on the one merge truth.

Requires success == true and cancelled absent/false: a payload carrying the merge marker but success: false (malformed/spoofed) or a cancel is NOT a merge. Boolean typing is strict — a non-boolean success / cancelled reads as not-a-merge rather than erroring, so a replay of such a dead event stays a clean no-op.

Source

pub fn stamp(&self, report: &mut Value)

Stamp this origin into a report payload under REPORT_ORIGIN_KEY, overwriting any existing value. A no-op if report is not a JSON object (callers always pass an object — the §7.3 validator rejects non-objects before this point).

Trait Implementations§

Source§

impl Clone for ReportOrigin

Source§

fn clone(&self) -> ReportOrigin

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ReportOrigin

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for ReportOrigin

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for ReportOrigin

Source§

impl PartialEq for ReportOrigin

Source§

fn eq(&self, other: &ReportOrigin) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for ReportOrigin

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for ReportOrigin

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more