From 1c50d1bf5e1965341a4e656def433b9abefbbafe Mon Sep 17 00:00:00 2001 From: Jonathan Haas <15969068+haasonsaas@users.noreply.github.com> Date: Tue, 18 Aug 2026 16:48:56 -0700 Subject: [PATCH 01/10] chore: stage Platform controller handshake --- ...platform-controller-handshake.part1.pyfrag | 220 ++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 scripts/codex/apply-platform-controller-handshake.part1.pyfrag diff --git a/scripts/codex/apply-platform-controller-handshake.part1.pyfrag b/scripts/codex/apply-platform-controller-handshake.part1.pyfrag new file mode 100644 index 000000000..4fb03e4a4 --- /dev/null +++ b/scripts/codex/apply-platform-controller-handshake.part1.pyfrag @@ -0,0 +1,220 @@ +from __future__ import annotations + +import argparse +import re +from pathlib import Path + +ROOT = Path('.') + + +def replace_once(path: Path, old: str, new: str, label: str) -> None: + text = path.read_text() + count = text.count(old) + if count != 1: + raise SystemExit(f"{label}: expected one match in {path}, found {count}") + path.write_text(text.replace(old, new, 1)) + + +def regex_replace_all(path: Path, pattern: str, repl, label: str) -> int: + text = path.read_text() + updated, count = re.subn(pattern, repl, text, flags=re.MULTILINE) + if count == 0: + raise SystemExit(f"{label}: no matches in {path}") + path.write_text(updated) + return count + + +TEST_FILE = ROOT / 'packages/tui-rs/src/headless/controller_binding_test.rs' +MOD_FILE = ROOT / 'packages/tui-rs/src/headless/mod.rs' + +TEST_CONTENT = r'''use serde_json::json; + +use super::controller_binding::{ + controller_binding_from_hello_json, controller_binding_sha256, + ControllerContext, ControllerLifetimeProfile, ControllerScopeExpectation, + CONTROLLER_BINDING_VERSION, CONTROLLER_CONTEXT_SCHEMA_VERSION, +}; + +fn context() -> ControllerContext { + ControllerContext { + schema_version: CONTROLLER_CONTEXT_SCHEMA_VERSION.to_string(), + controller_id: "evalops.platform".to_string(), + organization_id: "org-1".to_string(), + workspace_id: "workspace-1".to_string(), + thread_id: "thread-1".to_string(), + channel_id: Some("channel-1".to_string()), + request_id: Some("request-1".to_string()), + lifetime_profile: ControllerLifetimeProfile::Ephemeral, + runtime_generation: None, + } +} + +fn manifest() -> serde_json::Value { + json!({ + "schema_version": "evalops.maestro.capability-manifest.v1", + "engine_kind": "maestro", + "protocol_version": "2026-08-08", + "tool_protocol_version": "evalops.maestro.tool-bridge.v1", + "supported_tools": ["artifact.create_document", "artifact.create_presentation"], + "native_tool_calls": true, + "approvals": true, + "continuation": false, + "cancellation": true, + "idempotent_replay": true, + "streaming": true + }) +} + +#[test] +fn controller_binding_matches_the_cross_repository_digest_vector() { + assert_eq!( + controller_binding_sha256(CONTROLLER_BINDING_VERSION, &context(), &manifest()) + .expect("binding digest"), + "sha256:bd127868ecacc1994952c5fb6ca60b989b91c05defb70016d826a2ee97136375" + ); +} + +#[test] +fn native_capabilities_advertise_the_controller_binding_version() { + assert_eq!( + super::native_server_capabilities().controller_binding_versions, + vec![CONTROLLER_BINDING_VERSION.to_string()] + ); +} + +#[test] +fn controller_binding_requires_complete_scope_and_matching_runtime_identity() { + let raw = json!({ + "type": "hello", + "protocol_version": "2026-08-08", + "controller_binding_version": CONTROLLER_BINDING_VERSION, + "controller_context": context(), + "capability_manifest": manifest() + }) + .to_string(); + let expected = ControllerScopeExpectation { + organization_id: Some("org-1".to_string()), + workspace_id: Some("workspace-1".to_string()), + thread_id: Some("thread-1".to_string()), + channel_id: Some("channel-1".to_string()), + request_id: Some("request-1".to_string()), + }; + let receipt = controller_binding_from_hello_json(&raw, "2026-08-08", &expected) + .expect("valid binding") + .expect("binding present"); + assert_eq!(receipt.binding_version, CONTROLLER_BINDING_VERSION); + assert_eq!( + receipt.binding_sha256, + "sha256:bd127868ecacc1994952c5fb6ca60b989b91c05defb70016d826a2ee97136375" + ); + + let wrong_scope = ControllerScopeExpectation { + organization_id: Some("org-2".to_string()), + ..expected + }; + assert!( + controller_binding_from_hello_json(&raw, "2026-08-08", &wrong_scope).is_err() + ); +} + +#[test] +fn controller_binding_is_optional_but_partial_or_late_generation_shapes_fail_closed() { + assert!( + controller_binding_from_hello_json( + r#"{"type":"hello","protocol_version":"2026-08-08"}"#, + "2026-08-08", + &ControllerScopeExpectation::default(), + ) + .expect("legacy hello") + .is_none() + ); + + let partial = json!({ + "type": "hello", + "controller_binding_version": CONTROLLER_BINDING_VERSION, + "controller_context": context() + }) + .to_string(); + assert!( + controller_binding_from_hello_json( + &partial, + "2026-08-08", + &ControllerScopeExpectation::default(), + ) + .is_err() + ); + + let mut resident = context(); + resident.lifetime_profile = ControllerLifetimeProfile::Resident; + resident.runtime_generation = Some(0); + let invalid_generation = json!({ + "type": "hello", + "controller_binding_version": CONTROLLER_BINDING_VERSION, + "controller_context": resident, + "capability_manifest": manifest() + }) + .to_string(); + assert!( + controller_binding_from_hello_json( + &invalid_generation, + "2026-08-08", + &ControllerScopeExpectation::default(), + ) + .is_err() + ); +} +''' + +IMPLEMENTATION_CONTENT = r'''//! Typed, non-authoritative Platform controller identity bound during headless hello. +//! +//! This contract is correlation and compatibility evidence only. It does not +//! grant tools, connections, credentials, or execution authority; governed +//! effects continue to require the signed [`super::messages::GovernedToolGrant`]. + +use std::fmt::Write as _; + +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use sha2::{Digest, Sha256}; +use thiserror::Error; + +/// Version of the optional Platform-to-Maestro controller binding handshake. +pub(crate) const CONTROLLER_BINDING_VERSION: &str = "evalops.maestro.controller-binding.v1"; +/// Schema version for the secret-free controller context inside the binding. +pub(crate) const CONTROLLER_CONTEXT_SCHEMA_VERSION: &str = + "evalops.maestro.controller-context.v1"; +const PLATFORM_CONTROLLER_ID: &str = "evalops.platform"; + +/// Lifetime selected by Platform before the Maestro process is admitted. +#[derive(Debug, Clone, Copy, Deserialize, Eq, PartialEq, Serialize)] +#[serde(rename_all = "snake_case")] +pub(crate) enum ControllerLifetimeProfile { + /// One bounded operating turn. + Ephemeral, + /// One durable hosted thread generation. + Resident, +} + +/// Secret-free Platform scope and request correlation for one headless child. +#[derive(Debug, Clone, Deserialize, Eq, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub(crate) struct ControllerContext { + pub(crate) schema_version: String, + pub(crate) controller_id: String, + pub(crate) organization_id: String, + pub(crate) workspace_id: String, + pub(crate) thread_id: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub(crate) channel_id: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub(crate) request_id: Option, + pub(crate) lifetime_profile: ControllerLifetimeProfile, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub(crate) runtime_generation: Option, +} + +/// Runtime identity values that a managed process may require the hello to match. +#[derive(Debug, Clone, Default, Eq, PartialEq)] +pub(crate) struct ControllerScopeExpectation { + pub(crate) organization_id: Option, + pub(crate) workspace_id: Option, From fcb22b3f286fe5b04d18e60128262a5fac660777 Mon Sep 17 00:00:00 2001 From: Jonathan Haas <15969068+haasonsaas@users.noreply.github.com> Date: Tue, 18 Aug 2026 16:49:53 -0700 Subject: [PATCH 02/10] chore: stage Platform controller handshake part 2 --- ...platform-controller-handshake.part2.pyfrag | 220 ++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 scripts/codex/apply-platform-controller-handshake.part2.pyfrag diff --git a/scripts/codex/apply-platform-controller-handshake.part2.pyfrag b/scripts/codex/apply-platform-controller-handshake.part2.pyfrag new file mode 100644 index 000000000..b5db49f6d --- /dev/null +++ b/scripts/codex/apply-platform-controller-handshake.part2.pyfrag @@ -0,0 +1,220 @@ + pub(crate) thread_id: Option, + pub(crate) channel_id: Option, + pub(crate) request_id: Option, +} + +impl ControllerScopeExpectation { + /// Reads only secret-free identity variables populated by the Platform adapter. + #[must_use] + pub(crate) fn from_evalops_environment() -> Self { + Self { + organization_id: std::env::var("MAESTRO_EVALOPS_ORG_ID").ok(), + workspace_id: std::env::var("MAESTRO_EVALOPS_WORKSPACE_ID").ok(), + thread_id: std::env::var("MAESTRO_EVALOPS_THREAD_ID").ok(), + channel_id: std::env::var("MAESTRO_EVALOPS_CHANNEL_ID").ok(), + request_id: std::env::var("MAESTRO_EVALOPS_REQUEST_ID").ok(), + } + } +} + +/// Echoed proof that Maestro parsed and accepted the exact binding payload. +#[derive(Debug, Clone, Eq, PartialEq)] +pub(crate) struct ControllerBindingReceipt { + pub(crate) binding_version: String, + pub(crate) binding_sha256: String, +} + +/// Strict controller-binding validation failures. +#[derive(Debug, Error, Eq, PartialEq)] +pub(crate) enum ControllerBindingError { + #[error("controller binding fields must be supplied together")] + Incomplete, + #[error("unsupported controller binding version")] + UnsupportedBindingVersion, + #[error("unsupported controller context schema")] + UnsupportedContextSchema, + #[error("controller context field is empty: {0}")] + EmptyField(&'static str), + #[error("controller context is not owned by EvalOps Platform")] + InvalidController, + #[error("controller lifetime profile and runtime generation disagree")] + InvalidLifetime, + #[error("controller context does not match managed runtime field: {0}")] + ScopeMismatch(&'static str), + #[error("capability manifest is not an object")] + InvalidManifest, + #[error("capability manifest field is missing or invalid: {0}")] + InvalidManifestField(&'static str), + #[error("capability manifest protocol does not match the negotiated protocol")] + ManifestProtocolMismatch, + #[error("controller binding JSON is invalid")] + InvalidJson, + #[error("controller binding digest could not be encoded")] + DigestEncoding, +} + +#[derive(Debug, Deserialize)] +struct ControllerHelloExtension { + #[serde(default)] + controller_binding_version: Option, + #[serde(default)] + controller_context: Option, + #[serde(default)] + capability_manifest: Option, +} + +/// Parses and validates the optional controller extension carried by `hello`. +pub(crate) fn controller_binding_from_hello_json( + raw: &str, + negotiated_protocol_version: &str, + expected: &ControllerScopeExpectation, +) -> Result, ControllerBindingError> { + let extension: ControllerHelloExtension = + serde_json::from_str(raw).map_err(|_| ControllerBindingError::InvalidJson)?; + let supplied = extension.controller_binding_version.is_some() + || extension.controller_context.is_some() + || extension.capability_manifest.is_some(); + if !supplied { + return Ok(None); + } + let binding_version = extension + .controller_binding_version + .ok_or(ControllerBindingError::Incomplete)?; + let context = extension + .controller_context + .ok_or(ControllerBindingError::Incomplete)?; + let manifest = extension + .capability_manifest + .ok_or(ControllerBindingError::Incomplete)?; + + validate_context(&binding_version, &context, expected)?; + validate_manifest(&manifest, negotiated_protocol_version)?; + let binding_sha256 = controller_binding_sha256(&binding_version, &context, &manifest)?; + Ok(Some(ControllerBindingReceipt { + binding_version, + binding_sha256, + })) +} + +fn validate_context( + binding_version: &str, + context: &ControllerContext, + expected: &ControllerScopeExpectation, +) -> Result<(), ControllerBindingError> { + if binding_version != CONTROLLER_BINDING_VERSION { + return Err(ControllerBindingError::UnsupportedBindingVersion); + } + if context.schema_version != CONTROLLER_CONTEXT_SCHEMA_VERSION { + return Err(ControllerBindingError::UnsupportedContextSchema); + } + if context.controller_id != PLATFORM_CONTROLLER_ID { + return Err(ControllerBindingError::InvalidController); + } + for (field, value) in [ + ("organization_id", context.organization_id.as_str()), + ("workspace_id", context.workspace_id.as_str()), + ("thread_id", context.thread_id.as_str()), + ] { + if value.trim().is_empty() { + return Err(ControllerBindingError::EmptyField(field)); + } + } + for (field, value) in [ + ("channel_id", context.channel_id.as_deref()), + ("request_id", context.request_id.as_deref()), + ] { + if value.is_some_and(|value| value.trim().is_empty()) { + return Err(ControllerBindingError::EmptyField(field)); + } + } + match (context.lifetime_profile, context.runtime_generation) { + (ControllerLifetimeProfile::Ephemeral, None) => {} + (ControllerLifetimeProfile::Resident, Some(generation)) if generation > 0 => {} + _ => return Err(ControllerBindingError::InvalidLifetime), + } + require_expected( + expected.organization_id.as_deref(), + &context.organization_id, + "organization_id", + )?; + require_expected( + expected.workspace_id.as_deref(), + &context.workspace_id, + "workspace_id", + )?; + require_expected( + expected.thread_id.as_deref(), + &context.thread_id, + "thread_id", + )?; + require_expected_optional( + expected.channel_id.as_deref(), + context.channel_id.as_deref(), + "channel_id", + )?; + require_expected_optional( + expected.request_id.as_deref(), + context.request_id.as_deref(), + "request_id", + )?; + Ok(()) +} + +fn require_expected( + expected: Option<&str>, + actual: &str, + field: &'static str, +) -> Result<(), ControllerBindingError> { + if expected.is_some_and(|expected| expected != actual) { + return Err(ControllerBindingError::ScopeMismatch(field)); + } + Ok(()) +} + +fn require_expected_optional( + expected: Option<&str>, + actual: Option<&str>, + field: &'static str, +) -> Result<(), ControllerBindingError> { + if expected.is_some_and(|expected| Some(expected) != actual) { + return Err(ControllerBindingError::ScopeMismatch(field)); + } + Ok(()) +} + +fn validate_manifest( + manifest: &Value, + negotiated_protocol_version: &str, +) -> Result<(), ControllerBindingError> { + let object = manifest + .as_object() + .ok_or(ControllerBindingError::InvalidManifest)?; + let required_string = |field: &'static str| { + object + .get(field) + .and_then(Value::as_str) + .filter(|value| !value.trim().is_empty()) + .ok_or(ControllerBindingError::InvalidManifestField(field)) + }; + required_string("schema_version")?; + if required_string("engine_kind")? != "maestro" { + return Err(ControllerBindingError::InvalidManifestField("engine_kind")); + } + if required_string("protocol_version")? != negotiated_protocol_version { + return Err(ControllerBindingError::ManifestProtocolMismatch); + } + Ok(()) +} + +/// Computes the cross-repository canonical binding digest. +pub(crate) fn controller_binding_sha256( + binding_version: &str, + context: &ControllerContext, + capability_manifest: &Value, +) -> Result { + let value = serde_json::json!({ + "binding_version": binding_version, + "capability_manifest": capability_manifest, + "controller_context": context, + }); + let mut canonical = String::new(); From 96f3f23eb94a2d9ebc92b68a7d81f3a6a00d84ff Mon Sep 17 00:00:00 2001 From: Jonathan Haas <15969068+haasonsaas@users.noreply.github.com> Date: Tue, 18 Aug 2026 16:51:03 -0700 Subject: [PATCH 03/10] chore: stage Platform controller handshake part 3 --- ...platform-controller-handshake.part3.pyfrag | 220 ++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 scripts/codex/apply-platform-controller-handshake.part3.pyfrag diff --git a/scripts/codex/apply-platform-controller-handshake.part3.pyfrag b/scripts/codex/apply-platform-controller-handshake.part3.pyfrag new file mode 100644 index 000000000..f1797485a --- /dev/null +++ b/scripts/codex/apply-platform-controller-handshake.part3.pyfrag @@ -0,0 +1,220 @@ + write_canonical_json(&value, &mut canonical)?; + let digest = Sha256::digest(canonical.as_bytes()); + let mut encoded = String::with_capacity("sha256:".len() + digest.len() * 2); + encoded.push_str("sha256:"); + for byte in digest { + write!(&mut encoded, "{byte:02x}").map_err(|_| ControllerBindingError::DigestEncoding)?; + } + Ok(encoded) +} + +fn write_canonical_json( + value: &Value, + output: &mut String, +) -> Result<(), ControllerBindingError> { + match value { + Value::Null | Value::Bool(_) | Value::Number(_) | Value::String(_) => { + output.push_str( + &serde_json::to_string(value) + .map_err(|_| ControllerBindingError::DigestEncoding)?, + ); + } + Value::Array(items) => { + output.push('['); + for (index, item) in items.iter().enumerate() { + if index > 0 { + output.push(','); + } + write_canonical_json(item, output)?; + } + output.push(']'); + } + Value::Object(object) => { + output.push('{'); + let mut keys = object.keys().collect::>(); + keys.sort_unstable(); + for (index, key) in keys.into_iter().enumerate() { + if index > 0 { + output.push(','); + } + output.push_str( + &serde_json::to_string(key) + .map_err(|_| ControllerBindingError::DigestEncoding)?, + ); + output.push(':'); + write_canonical_json(&object[key], output)?; + } + output.push('}'); + } + } + Ok(()) +} +''' + +DOC_CONTENT = r'''# Platform controller binding for headless Maestro + +Status: implemented +Protocol: `evalops.maestro.controller-binding.v1` +Context schema: `evalops.maestro.controller-context.v1` + +Platform may attach a secret-free controller extension to the normal headless +`hello` message. The extension binds organization, workspace, thread, channel, +request, lifetime profile, and runtime generation to the exact capability +manifest used for the connection. + +This binding is correlation and compatibility evidence. It is not an +authorization mechanism. It grants no native tools, external tools, +connections, credentials, or side effects. Governed effects continue to require +a signed `GovernedToolGrant` and Platform-owned policy admission. + +## Hello extension + +```json +{ + "type": "hello", + "protocol_version": "2026-08-08", + "controller_binding_version": "evalops.maestro.controller-binding.v1", + "controller_context": { + "schema_version": "evalops.maestro.controller-context.v1", + "controller_id": "evalops.platform", + "organization_id": "org-1", + "workspace_id": "workspace-1", + "thread_id": "thread-1", + "channel_id": "channel-1", + "request_id": "request-1", + "lifetime_profile": "ephemeral" + }, + "capability_manifest": { + "schema_version": "evalops.maestro.capability-manifest.v1", + "engine_kind": "maestro", + "protocol_version": "2026-08-08" + } +} +``` + +All three controller fields are optional for ordinary clients, but they must be +supplied together. Managed Platform identity environment variables, when +present, must match the context exactly. `ephemeral` forbids a runtime +generation; `resident` requires a positive generation. + +## Acknowledgement + +`hello_ok` returns the accepted binding version and a canonical SHA-256 digest: + +```json +{ + "type": "hello_ok", + "controller_binding_version": "evalops.maestro.controller-binding.v1", + "controller_binding_sha256": "sha256:..." +} +``` + +The digest input is the object +`{binding_version, capability_manifest, controller_context}` serialized as +UTF-8 JSON with object keys recursively sorted, arrays preserved in order, and +no insignificant whitespace. Platform computes the same value and rejects a +missing or mismatched acknowledgement before sending `init`. + +Repeated identical bindings are idempotent. A different binding cannot replace +an accepted binding, and a first binding cannot be introduced after init. +''' + + +def apply_tests_only() -> None: + if TEST_FILE.exists(): + raise SystemExit(f"test file already exists: {TEST_FILE}") + replace_once( + MOD_FILE, + "mod async_transport;\n", + "mod async_transport;\n#[cfg(test)]\nmod controller_binding_test;\n", + "controller binding test module", + ) + TEST_FILE.write_text(TEST_CONTENT) + + +def add_hello_ok_fields_to_literals() -> None: + # Add None defaults to every explicit HelloOk literal, then specialize the + # native server acknowledgement below. + for path in (ROOT / 'packages/tui-rs/src').rglob('*.rs'): + text = path.read_text() + pattern = re.compile( + r'(FromAgentMessage::HelloOk\s*\{\s*\n(?P\s*)protocol_version:\s*[^\n]+,\n)' + ) + def repl(match: re.Match[str]) -> str: + indent = match.group('indent') + return ( + match.group(1) + + f"{indent}controller_binding_version: None,\n" + + f"{indent}controller_binding_sha256: None,\n" + ) + updated, count = pattern.subn(repl, text) + if count: + path.write_text(updated) + + + +def add_server_capability_fields_to_literals() -> None: + for path in (ROOT / 'packages/tui-rs/src').rglob('*.rs'): + text = path.read_text() + pattern = re.compile( + r'(?\s*)' + ) + def repl(match: re.Match[str]) -> str: + indent = match.group('indent') + return ( + match.group(1) + + f"{indent}controller_binding_versions: Vec::new(),\n" + + indent + ) + updated, count = pattern.subn(repl, text) + if count: + path.write_text(updated) + +def add_hello_ok_pattern_fields() -> None: + path = ROOT / 'packages/tui-rs/src/headless/messages/state.rs' + text = path.read_text() + pattern = re.compile( + r'(FromAgentMessage::HelloOk\s*\{\s*\n(?P\s*)protocol_version,\n)' + ) + def repl(match: re.Match[str]) -> str: + indent = match.group('indent') + return ( + match.group(1) + + f"{indent}controller_binding_version,\n" + + f"{indent}controller_binding_sha256,\n" + ) + updated, count = pattern.subn(repl, text) + if count != 1: + raise SystemExit(f"HelloOk state pattern: expected one match, found {count}") + updated = updated.replace( + " pub client_protocol_version: Option,\n", + " pub client_protocol_version: Option,\n" + " pub controller_binding_version: Option,\n" + " pub controller_binding_sha256: Option,\n", + 1, + ) + updated = updated.replace( + " self.protocol_version = Some(protocol_version);\n" + " self.client_protocol_version = client_protocol_version;\n", + " self.protocol_version = Some(protocol_version);\n" + " self.controller_binding_version = controller_binding_version;\n" + " self.controller_binding_sha256 = controller_binding_sha256;\n" + " self.client_protocol_version = client_protocol_version;\n", + 1, + ) + path.write_text(updated) + + +def apply_implementation() -> None: + controller_path = ROOT / 'packages/tui-rs/src/headless/controller_binding.rs' + if controller_path.exists(): + raise SystemExit(f"implementation file already exists: {controller_path}") + controller_path.write_text(IMPLEMENTATION_CONTENT) + + replace_once( + MOD_FILE, + "mod async_transport;\n#[cfg(test)]\nmod controller_binding_test;\n", + "mod async_transport;\npub(crate) mod controller_binding;\n#[cfg(test)]\nmod controller_binding_test;\n", + "controller binding implementation module", + ) + From 3dd11a34d44d1ba12cca2cd72b0b716692c4cc95 Mon Sep 17 00:00:00 2001 From: Jonathan Haas <15969068+haasonsaas@users.noreply.github.com> Date: Tue, 18 Aug 2026 16:52:01 -0700 Subject: [PATCH 04/10] chore: stage Platform controller handshake part 4 --- ...platform-controller-handshake.part4.pyfrag | 215 ++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 scripts/codex/apply-platform-controller-handshake.part4.pyfrag diff --git a/scripts/codex/apply-platform-controller-handshake.part4.pyfrag b/scripts/codex/apply-platform-controller-handshake.part4.pyfrag new file mode 100644 index 000000000..ae0cfedf0 --- /dev/null +++ b/scripts/codex/apply-platform-controller-handshake.part4.pyfrag @@ -0,0 +1,215 @@ + messages = ROOT / 'packages/tui-rs/src/headless/messages.rs' + replace_once( + messages, + " HelloOk {\n protocol_version: String,\n", + " HelloOk {\n protocol_version: String,\n" + " #[serde(default, skip_serializing_if = \"Option::is_none\")]\n" + " controller_binding_version: Option,\n" + " #[serde(default, skip_serializing_if = \"Option::is_none\")]\n" + " controller_binding_sha256: Option,\n", + "HelloOk controller acknowledgement fields", + ) + replace_once( + messages, + " #[serde(default)]\n pub governed_tool_grant_algorithms: Vec,\n", + " #[serde(default)]\n pub governed_tool_grant_algorithms: Vec,\n" + " /// Optional controller-binding protocol versions understood by this runtime.\n" + " #[serde(default)]\n" + " pub controller_binding_versions: Vec,\n", + "server capability controller binding versions", + ) + + add_hello_ok_fields_to_literals() + add_server_capability_fields_to_literals() + add_hello_ok_pattern_fields() + replace_once( + MOD_FILE, + " messages::ServerCapabilities {\n controller_binding_versions: Vec::new(),\n", + " messages::ServerCapabilities {\n" + " controller_binding_versions: vec![\n" + " controller_binding::CONTROLLER_BINDING_VERSION.to_string(),\n" + " ],\n", + "native controller binding capability", + ) + + server = ROOT / 'packages/tui-rs/src/headless_server.rs' + replace_once( + server, + "use crate::headless::{native_server_capabilities, HEADLESS_PROTOCOL_VERSION};\n", + "use crate::headless::controller_binding::{\n" + " controller_binding_from_hello_json, ControllerBindingReceipt,\n" + " ControllerScopeExpectation,\n" + "};\n" + "use crate::headless::{native_server_capabilities, HEADLESS_PROTOCOL_VERSION};\n", + "headless server controller binding imports", + ) + replace_once( + server, + " governed_grant: Option,\n ready_emitted: bool,\n", + " governed_grant: Option,\n" + " controller_binding_sha256: Option,\n" + " ready_emitted: bool,\n", + "headless state controller binding", + ) + replace_once( + server, + " governed_grant: None,\n ready_emitted: false,\n", + " governed_grant: None,\n" + " controller_binding_sha256: None,\n" + " ready_emitted: false,\n", + "headless state binding initialization", + ) + replace_once( + server, + " fn ensure_agent(&mut self) -> Result<&NativeAgent> {\n", + r''' fn accept_controller_binding( + &mut self, + binding: Option<&ControllerBindingReceipt>, + ) -> Result<()> { + let next = binding.map(|binding| binding.binding_sha256.as_str()); + match (self.controller_binding_sha256.as_deref(), next) { + (None, None) => Ok(()), + (Some(existing), Some(next)) if existing == next => Ok(()), + (Some(_), _) => anyhow::bail!("controller binding cannot be removed or replaced"), + (None, Some(_)) if self.init_applied => { + anyhow::bail!("controller binding must be accepted before init") + } + (None, Some(next)) => { + self.controller_binding_sha256 = Some(next.to_string()); + Ok(()) + } + } + } + + fn ensure_agent(&mut self) -> Result<&NativeAgent> { +''', + "accept controller binding method", + ) + replace_once( + server, + " let client_capabilities = capabilities.clone();\n", + r''' let controller_binding = match controller_binding_from_hello_json( + line, + HEADLESS_PROTOCOL_VERSION, + &ControllerScopeExpectation::from_evalops_environment(), + ) { + Ok(binding) => binding, + Err(error) => { + emit(&FromAgentMessage::Error { + request_id: None, + message: format!("Invalid controller binding: {error}"), + fatal: true, + terminal: true, + error_type: Some(HeadlessErrorType::Protocol), + })?; + break; + } + }; + if let Err(error) = state.accept_controller_binding(controller_binding.as_ref()) { + emit(&FromAgentMessage::Error { + request_id: None, + message: format!("Invalid controller binding: {error}"), + fatal: true, + terminal: true, + error_type: Some(HeadlessErrorType::Protocol), + })?; + break; + } + let client_capabilities = capabilities.clone(); +''', + "controller binding validation before hello acknowledgement", + ) + replace_once( + server, + " controller_binding_version: None,\n" + " controller_binding_sha256: None,\n" + " connection_id: Some(\"native-local\".to_string()),\n", + " controller_binding_version: controller_binding\n" + " .as_ref()\n" + " .map(|binding| binding.binding_version.clone()),\n" + " controller_binding_sha256: controller_binding\n" + " .as_ref()\n" + " .map(|binding| binding.binding_sha256.clone()),\n" + " connection_id: Some(\"native-local\".to_string()),\n", + "native hello acknowledgement binding echo", + ) + + proto = ROOT / 'proto/maestro/v1/headless.proto' + replace_once( + proto, + "enum ExecutorType {\n", + r'''enum ControllerLifetimeProfile { + CONTROLLER_LIFETIME_PROFILE_UNSPECIFIED = 0; + CONTROLLER_LIFETIME_PROFILE_EPHEMERAL = 1; + CONTROLLER_LIFETIME_PROFILE_RESIDENT = 2; +} + +message ControllerContext { + string schema_version = 1; + string controller_id = 2; + string organization_id = 3; + string workspace_id = 4; + string thread_id = 5; + optional string channel_id = 6; + optional string request_id = 7; + ControllerLifetimeProfile lifetime_profile = 8; + optional uint64 runtime_generation = 9; +} + +enum ExecutorType { +''', + "controller context protobuf schema", + ) + replace_once( + proto, + " repeated string governed_tool_grant_algorithms = 6;\n}\n", + " repeated string governed_tool_grant_algorithms = 6;\n" + " repeated string controller_binding_versions = 7;\n" + "}\n", + "server controller binding capability protobuf field", + ) + replace_once( + proto, + "message HelloMessage {\n" + " optional string protocol_version = 1;\n" + " ClientInfo client_info = 2;\n" + " ClientCapabilities capabilities = 3;\n" + " optional ConnectionRole role = 4;\n" + " repeated NotificationType opt_out_notifications = 5;\n" + "}\n", + "message HelloMessage {\n" + " optional string protocol_version = 1;\n" + " ClientInfo client_info = 2;\n" + " ClientCapabilities capabilities = 3;\n" + " optional ConnectionRole role = 4;\n" + " repeated NotificationType opt_out_notifications = 5;\n" + " optional string controller_binding_version = 6;\n" + " ControllerContext controller_context = 7;\n" + " google.protobuf.Value capability_manifest = 8;\n" + "}\n", + "Hello controller binding protobuf fields", + ) + replace_once( + proto, + " ServerCapabilities server_capabilities = 10;\n}\n\nmessage ConnectionInfoMessage", + " ServerCapabilities server_capabilities = 10;\n" + " optional string controller_binding_version = 11;\n" + " optional string controller_binding_sha256 = 12;\n" + "}\n\nmessage ConnectionInfoMessage", + "HelloOk controller binding protobuf fields", + ) + + doc = ROOT / 'docs/protocols/platform-controller-binding.md' + if doc.exists(): + raise SystemExit(f"documentation already exists: {doc}") + doc.write_text(DOC_CONTENT) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--phase', choices=['tests', 'implementation'], required=True) + args = parser.parse_args() + if args.phase == 'tests': + apply_tests_only() + else: + apply_implementation() From 30927698d6c961e0ae954d2c4bd0bb5bd5004d3e Mon Sep 17 00:00:00 2001 From: Jonathan Haas <15969068+haasonsaas@users.noreply.github.com> Date: Tue, 18 Aug 2026 16:52:25 -0700 Subject: [PATCH 05/10] chore: activate Platform controller handshake build --- .../apply-platform-controller-handshake.yml | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 .github/workflows/apply-platform-controller-handshake.yml diff --git a/.github/workflows/apply-platform-controller-handshake.yml b/.github/workflows/apply-platform-controller-handshake.yml new file mode 100644 index 000000000..234013f05 --- /dev/null +++ b/.github/workflows/apply-platform-controller-handshake.yml @@ -0,0 +1,78 @@ +name: Apply Platform controller handshake + +on: + push: + branches: + - codex/platform-controller-handshake + paths: + - scripts/codex/apply-platform-controller-handshake.part1.pyfrag + - scripts/codex/apply-platform-controller-handshake.part2.pyfrag + - scripts/codex/apply-platform-controller-handshake.part3.pyfrag + - scripts/codex/apply-platform-controller-handshake.part4.pyfrag + - .github/workflows/apply-platform-controller-handshake.yml + +permissions: + contents: write + +concurrency: + group: apply-platform-controller-handshake + cancel-in-progress: true + +jobs: + apply: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ github.ref_name }} + + - name: Verify reviewed source boundary + shell: bash + run: | + set -euo pipefail + test "$(git hash-object packages/tui-rs/src/headless/messages.rs)" = "106cdbfb055179ae7fce517e54b564d80a696bee" + test "$(git hash-object packages/tui-rs/src/headless_server.rs)" = "ddd9b75c8f1b5262aab14bb17c0937ad41783e29" + test "$(git hash-object packages/tui-rs/src/headless/mod.rs)" = "db4b869830759f70bc13ce27884671846a3c92c6" + test "$(git hash-object packages/tui-rs/src/headless/messages/state.rs)" = "809a71d0671ce19572b9a114f48cc0c4010f910a" + test "$(git hash-object proto/maestro/v1/headless.proto)" = "ac6e042aa382f68fd0d30fb2f938177e1417e2ef" + cat scripts/codex/apply-platform-controller-handshake.part*.pyfrag > /tmp/apply-platform-controller-handshake.py + python3 -m py_compile /tmp/apply-platform-controller-handshake.py + + - name: Prove controller-binding tests fail before implementation + shell: bash + run: | + set -euo pipefail + python3 /tmp/apply-platform-controller-handshake.py --phase tests + set +e + cargo test -p maestro-tui controller_binding --lib > /tmp/controller-binding-red.log 2>&1 + red_status=$? + set -e + cat /tmp/controller-binding-red.log + test "$red_status" -ne 0 + grep -q "controller_binding" /tmp/controller-binding-red.log + + - name: Implement and verify typed Platform handshake + shell: bash + run: | + set -euo pipefail + python3 /tmp/apply-platform-controller-handshake.py --phase implementation + cargo fmt --all + cargo test -p maestro-tui controller_binding --lib + cargo test -p maestro-tui generated_headless_proto_types_compile --lib + cargo check -p maestro-tui --lib + git diff --check + + - name: Commit clean product diff + shell: bash + run: | + set -euo pipefail + rm -f scripts/codex/apply-platform-controller-handshake.part*.pyfrag + rm -f .github/workflows/apply-platform-controller-handshake.yml + rmdir --ignore-fail-on-non-empty scripts/codex 2>/dev/null || true + git diff --check + git config user.name "OpenAI Codex" + git config user.email "noreply@openai.com" + git add -A + git commit -m "feat(headless): bind Platform controller context" + git push origin "HEAD:${GITHUB_REF_NAME}" From 0ccb5d12bb8ee23a5302d5a6745a0cca65d07e56 Mon Sep 17 00:00:00 2001 From: Jonathan Haas <15969068+haasonsaas@users.noreply.github.com> Date: Tue, 18 Aug 2026 16:58:30 -0700 Subject: [PATCH 06/10] chore: trigger controller handshake build --- .github/workflows/apply-platform-controller-handshake.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/apply-platform-controller-handshake.yml b/.github/workflows/apply-platform-controller-handshake.yml index 234013f05..b6409dd31 100644 --- a/.github/workflows/apply-platform-controller-handshake.yml +++ b/.github/workflows/apply-platform-controller-handshake.yml @@ -76,3 +76,5 @@ jobs: git add -A git commit -m "feat(headless): bind Platform controller context" git push origin "HEAD:${GITHUB_REF_NAME}" + +# Trigger after the workflow exists on the branch. From f0e392db940e73016d8ef8b8cb0490436a55580e Mon Sep 17 00:00:00 2001 From: Jonathan Haas <15969068+haasonsaas@users.noreply.github.com> Date: Tue, 18 Aug 2026 17:05:42 -0700 Subject: [PATCH 07/10] chore: scope headless capability literal migration --- .../codex/apply-platform-controller-handshake.part3.pyfrag | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/codex/apply-platform-controller-handshake.part3.pyfrag b/scripts/codex/apply-platform-controller-handshake.part3.pyfrag index f1797485a..96deaae14 100644 --- a/scripts/codex/apply-platform-controller-handshake.part3.pyfrag +++ b/scripts/codex/apply-platform-controller-handshake.part3.pyfrag @@ -154,7 +154,12 @@ def add_hello_ok_fields_to_literals() -> None: def add_server_capability_fields_to_literals() -> None: - for path in (ROOT / 'packages/tui-rs/src').rglob('*.rs'): + paths = list((ROOT / 'packages/tui-rs/src/headless').rglob('*.rs')) + paths.extend([ + ROOT / 'packages/tui-rs/src/hosted_runner.rs', + ROOT / 'packages/tui-rs/src/hosted_runner/manifests.rs', + ]) + for path in paths: text = path.read_text() pattern = re.compile( r'(?\s*)' From 86c452bf545ed102e1e37ffa3fef37bf4604ae55 Mon Sep 17 00:00:00 2001 From: Jonathan Haas <15969068+haasonsaas@users.noreply.github.com> Date: Tue, 18 Aug 2026 17:10:44 -0700 Subject: [PATCH 08/10] chore: run controller handshake transform on PR sync --- .../apply-platform-controller-handshake.yml | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/.github/workflows/apply-platform-controller-handshake.yml b/.github/workflows/apply-platform-controller-handshake.yml index b6409dd31..dd088bb6a 100644 --- a/.github/workflows/apply-platform-controller-handshake.yml +++ b/.github/workflows/apply-platform-controller-handshake.yml @@ -1,31 +1,25 @@ name: Apply Platform controller handshake on: - push: - branches: - - codex/platform-controller-handshake - paths: - - scripts/codex/apply-platform-controller-handshake.part1.pyfrag - - scripts/codex/apply-platform-controller-handshake.part2.pyfrag - - scripts/codex/apply-platform-controller-handshake.part3.pyfrag - - scripts/codex/apply-platform-controller-handshake.part4.pyfrag - - .github/workflows/apply-platform-controller-handshake.yml + pull_request: + types: [opened, synchronize, reopened] permissions: contents: write concurrency: - group: apply-platform-controller-handshake + group: apply-platform-controller-handshake-${{ github.event.pull_request.number }} cancel-in-progress: true jobs: apply: + if: github.head_ref == 'codex/platform-controller-handshake' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - ref: ${{ github.ref_name }} + ref: ${{ github.head_ref }} - name: Verify reviewed source boundary shell: bash @@ -75,6 +69,4 @@ jobs: git config user.email "noreply@openai.com" git add -A git commit -m "feat(headless): bind Platform controller context" - git push origin "HEAD:${GITHUB_REF_NAME}" - -# Trigger after the workflow exists on the branch. + git push origin "HEAD:${GITHUB_HEAD_REF}" From 6c4ee8f9578c5f882d095312c5521213e5d8e867 Mon Sep 17 00:00:00 2001 From: Jonathan Haas <15969068+haasonsaas@users.noreply.github.com> Date: Tue, 18 Aug 2026 17:15:47 -0700 Subject: [PATCH 09/10] chore: constrain controller capability literal migration --- ...latform-controller-handshake.part3b.pyfrag | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 scripts/codex/apply-platform-controller-handshake.part3b.pyfrag diff --git a/scripts/codex/apply-platform-controller-handshake.part3b.pyfrag b/scripts/codex/apply-platform-controller-handshake.part3b.pyfrag new file mode 100644 index 000000000..d0c965be2 --- /dev/null +++ b/scripts/codex/apply-platform-controller-handshake.part3b.pyfrag @@ -0,0 +1,25 @@ + + +def add_server_capability_fields_to_literals() -> None: + paths = list((ROOT / 'packages/tui-rs/src/headless').rglob('*.rs')) + paths.extend([ + ROOT / 'packages/tui-rs/src/hosted_runner.rs', + ROOT / 'packages/tui-rs/src/hosted_runner/manifests.rs', + ]) + for path in paths: + text = path.read_text() + pattern = re.compile( + r'((?:[A-Za-z0-9_]+::)*ServerCapabilities\s*\{\s*\n)' + r'(?P\s*)' + r'(?=(?:server_requests|utility_operations|raw_agent_events|connection_roles|native_tools|governed_tool_grant_algorithms)\s*:)' + ) + def repl(match: re.Match[str]) -> str: + indent = match.group('indent') + return ( + match.group(1) + + f"{indent}controller_binding_versions: Vec::new(),\n" + + indent + ) + updated, count = pattern.subn(repl, text) + if count: + path.write_text(updated) From 5e0cf9934f14915ae6b5c33248e5f7f8c99445cf Mon Sep 17 00:00:00 2001 From: Jonathan Haas <15969068+haasonsaas@users.noreply.github.com> Date: Tue, 18 Aug 2026 17:23:47 -0700 Subject: [PATCH 10/10] chore: keep controller transform in one implementation scope --- ...latform-controller-handshake.part3b.pyfrag | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/scripts/codex/apply-platform-controller-handshake.part3b.pyfrag b/scripts/codex/apply-platform-controller-handshake.part3b.pyfrag index d0c965be2..7e60e7042 100644 --- a/scripts/codex/apply-platform-controller-handshake.part3b.pyfrag +++ b/scripts/codex/apply-platform-controller-handshake.part3b.pyfrag @@ -1,25 +1,27 @@ -def add_server_capability_fields_to_literals() -> None: - paths = list((ROOT / 'packages/tui-rs/src/headless').rglob('*.rs')) - paths.extend([ - ROOT / 'packages/tui-rs/src/hosted_runner.rs', - ROOT / 'packages/tui-rs/src/hosted_runner/manifests.rs', - ]) - for path in paths: - text = path.read_text() - pattern = re.compile( - r'((?:[A-Za-z0-9_]+::)*ServerCapabilities\s*\{\s*\n)' - r'(?P\s*)' - r'(?=(?:server_requests|utility_operations|raw_agent_events|connection_roles|native_tools|governed_tool_grant_algorithms)\s*:)' - ) - def repl(match: re.Match[str]) -> str: - indent = match.group('indent') - return ( - match.group(1) - + f"{indent}controller_binding_versions: Vec::new(),\n" - + indent + def add_server_capability_fields_to_literals() -> None: + paths = list((ROOT / 'packages/tui-rs/src/headless').rglob('*.rs')) + paths.extend([ + ROOT / 'packages/tui-rs/src/hosted_runner.rs', + ROOT / 'packages/tui-rs/src/hosted_runner/manifests.rs', + ]) + for path in paths: + text = path.read_text() + pattern = re.compile( + r'((?:[A-Za-z0-9_]+::)*ServerCapabilities\s*\{\s*\n)' + r'(?P\s*)' + r'(?=(?:server_requests|utility_operations|raw_agent_events|connection_roles|native_tools|governed_tool_grant_algorithms)\s*:)' ) - updated, count = pattern.subn(repl, text) - if count: - path.write_text(updated) + + def repl(match: re.Match[str]) -> str: + indent = match.group('indent') + return ( + match.group(1) + + f"{indent}controller_binding_versions: Vec::new(),\n" + + indent + ) + + updated, count = pattern.subn(repl, text) + if count: + path.write_text(updated)