feat(research,campaign): optional selection group on the sweep stage (#210 T1-T2)
The std::sweep selection triple (metric/select/deflate) becomes ONE
optional group, Option<SweepSelection>, serde-flattened so the wire
form keeps the flat slots: every existing document parses to Some and
its canonical bytes — and content id — are unchanged (golden pin
byte-untouched). A half-populated group is refused by the schema-strict
parser (all-or-nothing); a bare {"block":"std::sweep"} is the
selection-free sweep.
Campaign side: preflight permits a selection-free sweep only as the
pipeline's terminal stage (new ExecFault::SelectionFreeSweepNotTerminal,
prose in aura-cli's exhaustive exec_fault_prose); the executor's
selection-free arm appends the family exactly as before but records no
StageSelection and produces no nominee (recording one would fabricate
intent — #210 fork decision 1).
Introspection follows: the sweep block's schema table marks the group
optional; CLI introspection pins updated. New tests: group-or-nothing
refusals, selection-free round-trip + distinct content id, terminal-only
preflight accept/refuse, selection-free execute realization.
refs #210
This commit is contained in:
@@ -67,6 +67,10 @@ pub(crate) fn exec_fault_prose(f: &ExecFault) -> String {
|
||||
ExecFault::DeflatePlateauConflict { stage } => format!(
|
||||
"process stage {stage}: sweep deflate: true composes only with select \"argmax\""
|
||||
),
|
||||
ExecFault::SelectionFreeSweepNotTerminal { stage } => format!(
|
||||
"process stage {stage}: a sweep without a selection group (metric + \
|
||||
select) must be the last stage of its process"
|
||||
),
|
||||
ExecFault::GeneralizeNeedsInstruments { available } => format!(
|
||||
"campaign has {available} instrument(s); std::generalize needs at least 2"
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user