feat(missions): choose the independent validator per mission (#53)
`CLAWMATES_VALIDATOR_MODEL` is deployment-wide, so proving Slice 2 put a second
provider on the critical path of EVERY phase verdict. `cross_provider_judge`
deliberately does not fall back when the independent judge fails — a verdict
quietly produced by a same-family model would claim a property it does not have —
so a z.ai outage makes phases unmeetable rather than merely unverified. That is a
per-mission trade, not a per-deployment one.
`missions.validator_model` (0068), settable at create, with three distinct states
because an empty string and NULL mean opposite things in a nullable text column:
NULL use the deployment default
'' explicitly NO independent validator — judge with the house model.
The default must not quietly reinstate independence a mission was
told to skip.
'glm:glm-4.7' this spec, subject to the same three refusals as before:
same-family rejected, unregistered provider rejected, and a failed
independent judge does not fall back.
Whitespace counts as empty: a column hand-set to " " meant to say nothing.
478 tests pass, clippy clean. Behaviour is unchanged for existing missions — they
have NULL and so keep following the deployment default.
This commit is contained in:
@@ -41,6 +41,10 @@ pub struct CreateMissionRequest {
|
||||
/// Which per-CLI rootfs a `microvm` mission boots (`missions.backend`), e.g.
|
||||
/// "claude". NULL boots the node's default image.
|
||||
pub backend: Option<String>,
|
||||
/// Model that independently validates this mission's phase verdicts, e.g.
|
||||
/// `glm:glm-4.7`. Omit to use the deployment default; send `""` to opt out of
|
||||
/// independent validation and judge with the house model.
|
||||
pub validator_model: Option<String>,
|
||||
}
|
||||
|
||||
fn default_schedule() -> Value {
|
||||
@@ -285,6 +289,7 @@ pub async fn create(
|
||||
runtime_kind: Some(runtime_kind),
|
||||
target_node_id: body.target_node_id,
|
||||
backend: body.backend.as_deref(),
|
||||
validator_model: body.validator_model.as_deref(),
|
||||
phases: phases_for_create(
|
||||
crate::workflow_registry::get(body.template_kind.trim()),
|
||||
body.phases,
|
||||
|
||||
Reference in New Issue
Block a user