use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum CapabilityOutcome {
Native,
RealizeVia,
Degrade,
Fail,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ProvidedBy {
Runtime,
Warble,
None,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum Criticality {
SafetyCritical,
Required,
BestEffort,
}
pub(crate) const CONTEXT_ISOLATION_CAPABILITY: &str = "context_isolation";
#[derive(Debug, Clone)]
pub struct CapabilityEntry {
pub outcome: CapabilityOutcome,
pub via: Option<Cow<'static, str>>,
pub provided_by: ProvidedBy,
pub criticality: Criticality,
pub note: Option<Cow<'static, str>>,
}
pub type CapabilityProfile = HashMap<String, CapabilityEntry>;
fn profile(
entries: impl IntoIterator<Item = (&'static str, CapabilityEntry)>,
) -> CapabilityProfile {
entries
.into_iter()
.map(|(k, v)| (k.to_string(), v))
.collect()
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TargetId {
Headless,
Interactive,
CodexInteractive,
}
impl TargetId {
pub fn as_str(&self) -> &'static str {
match self {
TargetId::Headless => "claude-code:headless",
TargetId::Interactive => "claude-code:interactive",
TargetId::CodexInteractive => "codex:interactive",
}
}
pub fn mode(&self) -> &'static str {
match self {
TargetId::Headless => "headless",
TargetId::Interactive => "interactive",
TargetId::CodexInteractive => "interactive",
}
}
pub fn parse(value: &str) -> Option<TargetId> {
match value {
"claude-code:headless" => Some(TargetId::Headless),
"claude-code:interactive" => Some(TargetId::Interactive),
"codex:interactive" => Some(TargetId::CodexInteractive),
_ => None,
}
}
pub fn profile(&self) -> CapabilityProfile {
match self {
TargetId::Headless => headless_profile(),
TargetId::Interactive => interactive_profile(),
TargetId::CodexInteractive => codex_interactive_profile(),
}
}
}
pub const DEFAULT_TARGET: TargetId = TargetId::Headless;
pub fn is_known_target(value: &str) -> bool {
TargetId::parse(value).is_some()
}
pub fn known_target_names() -> [&'static str; 3] {
[
TargetId::Headless.as_str(),
TargetId::Interactive.as_str(),
TargetId::CodexInteractive.as_str(),
]
}
fn entry(
outcome: CapabilityOutcome,
via: Option<&'static str>,
provided_by: ProvidedBy,
criticality: Criticality,
note: Option<&'static str>,
) -> CapabilityEntry {
CapabilityEntry {
outcome,
via: via.map(Cow::Borrowed),
provided_by,
criticality,
note: note.map(Cow::Borrowed),
}
}
fn headless_profile() -> CapabilityProfile {
use CapabilityOutcome::*;
use Criticality::*;
use ProvidedBy::{Runtime, Warble};
profile([
(
"component_invocation",
entry(
Fail,
None,
ProvidedBy::None,
Required,
Some("no trusted component-invocation handler is installed for this file target"),
),
),
(
"sql_execution:read_only",
entry(Native, Some("bash-wren"), Runtime, Required, None),
),
(
"genbi_build",
entry(Native, Some("bash-wren"), Runtime, Required, None),
),
(
"semantic_introspection",
entry(RealizeVia, Some("bash-wren"), Runtime, Required, None),
),
(
"schema_introspection",
entry(RealizeVia, Some("bash-wren"), Runtime, Required, None),
),
("llm:strong", entry(Native, None, Runtime, Required, None)),
("llm:cheap", entry(Native, None, Runtime, Required, None)),
(
"llm:per_step_tier",
entry(RealizeVia, Some("subagents"), Runtime, Required, None),
),
(
"llm:per_step_provider",
entry(
RealizeVia,
Some("bash-script|mcp-server"),
Warble,
Required,
Some("local step via a bash-script script or an mcp-server (warble mcp-serve); cloud steps are the driver's own wren work"),
),
),
(
"render_contract",
entry(RealizeVia, Some("html-file"), Runtime, BestEffort, None),
),
(
"structured_output_capture",
entry(Native, Some("stream-json"), Runtime, Required, None),
),
(
"human_approval",
entry(
Fail,
None,
ProvidedBy::None,
SafetyCritical,
Some("no human in the loop in headless mode"),
),
),
(
"write_authz",
entry(RealizeVia, Some("fs"), Runtime, SafetyCritical, None),
),
(
"context_write_authz",
entry(RealizeVia, Some("scoped-fs"), Runtime, SafetyCritical, None),
),
(
"artifact_write",
entry(RealizeVia, Some("fs"), Runtime, SafetyCritical, None),
),
(
CONTEXT_ISOLATION_CAPABILITY,
entry(RealizeVia, Some("subagent"), Runtime, Required, None),
),
(
"scheduler",
entry(RealizeVia, Some("os-cron"), Runtime, Required, None),
),
(
"event_bus",
entry(RealizeVia, Some("pub-sub"), Runtime, Required, None),
),
(
"notify_channel",
entry(RealizeVia, Some("mcp-notify"), Runtime, Required, None),
),
(
"blast_radius",
entry(
Fail,
None,
Warble,
SafetyCritical,
Some("requires fine_grained_binding"),
),
),
(
"version_control",
entry(RealizeVia, Some("git"), Runtime, Required, None),
),
])
}
fn interactive_profile() -> CapabilityProfile {
use CapabilityOutcome::*;
use Criticality::*;
use ProvidedBy::{Runtime, Warble};
profile([
(
"component_invocation",
entry(
Fail,
None,
ProvidedBy::None,
Required,
Some("no trusted component-invocation handler is installed for this file target"),
),
),
(
"sql_execution:read_only",
entry(Native, Some("bash-wren"), Runtime, Required, None),
),
(
"genbi_build",
entry(Native, Some("bash-wren"), Runtime, Required, None),
),
(
"semantic_introspection",
entry(RealizeVia, Some("bash-wren"), Runtime, Required, None),
),
(
"source_connect",
entry(RealizeVia, Some("native-interactive-command"), Runtime, Required, None),
),
(
"schema_introspection",
entry(RealizeVia, Some("bash-wren"), Runtime, Required, None),
),
("raw_material_read", entry(Native, Some("Read"), Runtime, Required, Some("Claude Code's cwd-scoped Read tool; prompts forbid credentials and raw excerpts"))),
("context_validate", entry(RealizeVia, Some("Bash(wren:*)"), Runtime, Required, None)),
("context_build", entry(RealizeVia, Some("Bash(wren:*)"), Runtime, Required, None)),
("enrichment_apply:deterministic", entry(RealizeVia, Some("native-interactive-approved-tool"), Runtime, SafetyCritical, Some("only after the native human-approval gate; Warble does not run it"))),
("llm:strong", entry(Native, None, Runtime, Required, None)),
("llm:cheap", entry(Native, None, Runtime, Required, None)),
(
"llm:per_step_tier",
entry(RealizeVia, Some("subagents"), Runtime, Required, None),
),
(
"llm:per_step_provider",
entry(
RealizeVia,
Some("bash-script|mcp-server"),
Warble,
Required,
Some("local step via an emitted local-inference script (Bash); cloud steps stay native subagents"),
),
),
(
"render_contract",
entry(
Degrade,
Some("terminal-markdown"),
Runtime,
BestEffort,
None,
),
),
(
"structured_output_capture",
entry(
Degrade,
None,
ProvidedBy::None,
BestEffort,
Some("not captured in the interactive TUI"),
),
),
(
"human_approval",
entry(Native, None, Runtime, SafetyCritical, None),
),
(
"write_authz",
entry(RealizeVia, Some("fs"), Runtime, SafetyCritical, None),
),
(
"context_write_authz",
entry(RealizeVia, Some("scoped-fs"), Runtime, SafetyCritical, None),
),
(
"artifact_write",
entry(RealizeVia, Some("fs"), Runtime, SafetyCritical, None),
),
(
CONTEXT_ISOLATION_CAPABILITY,
entry(RealizeVia, Some("subagent"), Runtime, Required, None),
),
(
"scheduler",
entry(RealizeVia, Some("os-cron"), Runtime, Required, None),
),
(
"event_bus",
entry(RealizeVia, Some("pub-sub"), Runtime, Required, None),
),
(
"notify_channel",
entry(RealizeVia, Some("mcp-notify"), Runtime, Required, None),
),
(
"blast_radius",
entry(
Fail,
None,
Warble,
SafetyCritical,
Some("requires fine_grained_binding"),
),
),
(
"version_control",
entry(RealizeVia, Some("git"), Runtime, Required, None),
),
])
}
fn codex_interactive_profile() -> CapabilityProfile {
use CapabilityOutcome::*;
use Criticality::*;
use ProvidedBy::{Runtime, Warble};
profile([
(
"component_invocation",
entry(
Fail,
None,
ProvidedBy::None,
Required,
Some("codex interactive emits discovery artifacts and has no invocation runtime"),
),
),
("sql_execution:read_only", entry(RealizeVia, Some("native-interactive-command"), Runtime, Required, None)),
("genbi_build", entry(RealizeVia, Some("native-interactive-command"), Runtime, Required, None)),
("source_connect", entry(RealizeVia, Some("native-interactive-command"), Runtime, Required, None)),
("semantic_introspection", entry(RealizeVia, Some("codex-repository-read"), Runtime, Required, None)),
("raw_material_read", entry(RealizeVia, Some("codex-repository-read"), Runtime, Required, Some("repository-scoped native TUI reads only; prompts forbid credentials and raw excerpts"))),
("llm:strong", entry(Native, None, Runtime, Required, None)),
("llm:cheap", entry(Native, None, Runtime, Required, None)),
("llm:per_step_tier", entry(RealizeVia, Some("native-interactive-subagents"), Runtime, Required, None)),
("context_write_authz", entry(RealizeVia, Some("native-interactive-human-approval"), Runtime, SafetyCritical, None)),
("context_validate", entry(RealizeVia, Some("native-interactive-command"), Runtime, Required, None)),
("context_build", entry(RealizeVia, Some("native-interactive-command"), Runtime, Required, None)),
("version_control", entry(RealizeVia, Some("git"), Runtime, Required, None)),
("human_approval", entry(Native, Some("native-interactive-human"), Runtime, SafetyCritical, None)),
("enrichment_apply:deterministic", entry(RealizeVia, Some("native-interactive-approved-tool"), Runtime, SafetyCritical, Some("only after the native human-approval gate; Warble does not run it"))),
("render_contract", entry(Degrade, Some("terminal-markdown"), Runtime, BestEffort, None)),
("artifact_write", entry(RealizeVia, Some("session-scoped-artifact-api"), Runtime, SafetyCritical, Some("the host owns the artifact API and persistence"))),
("blast_radius", entry(Fail, None, Warble, SafetyCritical, Some("requires fine_grained_binding"))),
])
}