Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions kernel/relayflowd-core/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ const STEP_AGENT_FIELDS: &[&str] = &[
"instruction",
"cli",
"model",
"transport",
"recovery_mode",
"surfaces",
"permissions",
Expand Down Expand Up @@ -423,6 +424,11 @@ pub enum StepKind {
/// then handed to the worker, which surfaces it to the CLI.
#[serde(default, skip_serializing_if = "Option::is_none")]
model: Option<String>,
/// How the attached worker invokes the declared CLI. The kernel does
/// not implement either transport; it journals and dispatches the
/// choice so the worker can honor it deterministically.
#[serde(default, skip_serializing_if = "Option::is_none")]
transport: Option<AgentTransport>,
#[serde(default)]
recovery_mode: RecoveryMode,
/// Declared mutable surfaces (RFC Appendix A rule 1) — names only.
Expand Down Expand Up @@ -450,6 +456,13 @@ pub enum StepType {
Agent,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum AgentTransport {
Direct,
Relay,
}

#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum RecoveryMode {
Expand Down
35 changes: 35 additions & 0 deletions kernel/relayflowd-core/tests/spec_parity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,41 @@ fn the_kernel_parses_the_rung_c_agent_spec_and_stamps_the_same_hash() {
);
}

#[test]
fn the_kernel_round_trips_declared_agent_transports_and_rejects_unknown_values() {
for transport in ["direct", "relay"] {
let value = serde_json::json!({
"steps": [{
"id": "agent",
"type": "agent",
"instruction": "work",
"transport": transport,
}],
});
let parsed = RunSpec::parse(&value).expect("declared agent transport must parse");
parsed
.validate()
.expect("declared agent transport must validate");
assert_eq!(
serde_json::to_value(parsed).unwrap()["steps"][0]["transport"],
transport
);
}

let unknown = serde_json::json!({
"steps": [{
"id": "agent",
"type": "agent",
"instruction": "work",
"transport": "telepathy",
}],
});
assert!(
RunSpec::parse(&unknown).is_err(),
"unknown transport must fail closed"
);
}

#[test]
fn the_kernel_parses_the_event_triggered_spec_and_stamps_the_same_hash() {
assert_parity(
Expand Down
Loading