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.
Implementations§
Source§impl ReportOrigin
impl ReportOrigin
Sourcepub fn from_report(report: &Value) -> Option<Self>
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.
Sourcepub fn report_is_confirmed_merge(report: &Value) -> bool
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.
Sourcepub fn stamp(&self, report: &mut Value)
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
impl Clone for ReportOrigin
Source§fn clone(&self) -> ReportOrigin
fn clone(&self) -> ReportOrigin
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more