Refactor world-state rendering tests into snapshots (#33412)

## What changed

- Add a shared test helper that renders before-and-after section states alongside the resulting role and content.
- Convert the agents, environment, apps, and plugins world-state tests to snapshot tables covering absent, unknown, unchanged, changed, and removed states.

GitOrigin-RevId: 03372a5f925d2019f37bf5a5a2f060261899026c
This commit is contained in:
pakrym-oai
2026-07-15 20:01:33 +00:00
committed by copyberry
parent 2cd6ed7509
commit 8530440b91
10 changed files with 395 additions and 323 deletions
@@ -1,101 +1,29 @@
use super::super::PreviousSectionState;
use super::super::test_support::render_section_cases;
use super::*;
use crate::context::world_state::WorldState;
use codex_protocol::models::ContentItem;
use codex_protocol::models::ResponseItem;
use pretty_assertions::assert_eq;
use serde_json::json;
#[test]
fn renders_full_state_and_omits_unchanged_state() {
let loaded = LoadedAgentsMd::from_text_for_testing("use the project formatter");
let mut state = WorldState::default();
state.add_section(AgentsMdState::new(Some(&loaded)));
fn snapshots() {
use PreviousSectionState::Absent;
use PreviousSectionState::Known;
use PreviousSectionState::Unknown;
assert_eq!(
vec![user_message(
"# AGENTS.md instructions\n\n<INSTRUCTIONS>\nuse the project formatter\n</INSTRUCTIONS>",
)],
render_fragments(state.render_full()),
);
assert_eq!(
Vec::<ResponseItem>::new(),
render_fragments(state.render_diff(&state.snapshot()))
);
assert_eq!(
state.snapshot().into_value(),
json!({"agents_md": {"text": "use the project formatter"}}),
);
}
let empty = AgentsMdState::default();
let project_formatter = LoadedAgentsMd::from_text_for_testing("use the project formatter");
let project_formatter = AgentsMdState::new(Some(&project_formatter));
let old = LoadedAgentsMd::from_text_for_testing("old instructions");
let old = AgentsMdState::new(Some(&old));
let new = LoadedAgentsMd::from_text_for_testing("new instructions");
let new = AgentsMdState::new(Some(&new));
#[test]
fn changed_and_removed_state_supersedes_previous_instructions() {
let previous_loaded = LoadedAgentsMd::from_text_for_testing("old instructions");
let mut previous = WorldState::default();
previous.add_section(AgentsMdState::new(Some(&previous_loaded)));
let current_loaded = LoadedAgentsMd::from_text_for_testing("new instructions");
let mut current = WorldState::default();
current.add_section(AgentsMdState::new(Some(&current_loaded)));
assert_eq!(
vec![user_message(
"# AGENTS.md instructions\n\n<INSTRUCTIONS>\nThese AGENTS.md instructions replace all previously provided AGENTS.md instructions.\n\nnew instructions\n</INSTRUCTIONS>",
)],
render_fragments(current.render_diff(&previous.snapshot())),
);
let mut removed = WorldState::default();
removed.add_section(AgentsMdState::default());
assert_eq!(
vec![user_message(
"# AGENTS.md instructions\n\n<INSTRUCTIONS>\nThe previously provided AGENTS.md instructions no longer apply.\n</INSTRUCTIONS>",
)],
render_fragments(removed.render_diff(&current.snapshot())),
);
}
#[test]
fn unknown_previous_state_is_explicitly_superseded() {
let loaded = LoadedAgentsMd::from_text_for_testing("current instructions");
let current = AgentsMdState::new(Some(&loaded));
assert_eq!(
vec![user_message(
"# AGENTS.md instructions\n\n<INSTRUCTIONS>\nThese AGENTS.md instructions replace all previously provided AGENTS.md instructions.\n\ncurrent instructions\n</INSTRUCTIONS>",
)],
render_fragments(vec![
WorldStateSection::render_diff(&current, PreviousSectionState::Unknown)
.expect("unknown state should be replaced"),
]),
);
assert_eq!(
vec![user_message(
"# AGENTS.md instructions\n\n<INSTRUCTIONS>\nThe previously provided AGENTS.md instructions no longer apply.\n</INSTRUCTIONS>",
)],
render_fragments(vec![
WorldStateSection::render_diff(
&AgentsMdState::default(),
PreviousSectionState::Unknown,
)
.expect("unknown state should be removed"),
]),
);
}
fn render_fragments(fragments: Vec<Box<dyn ContextualUserFragment>>) -> Vec<ResponseItem> {
fragments
.into_iter()
.map(ContextualUserFragment::into_boxed_response_item)
.collect()
}
fn user_message(text: &str) -> ResponseItem {
ResponseItem::Message {
id: None,
role: "user".to_string(),
content: vec![ContentItem::InputText {
text: text.to_string(),
}],
phase: None,
internal_chat_message_metadata_passthrough: None,
}
insta::assert_snapshot!(render_section_cases(&[
(Absent, Absent),
(Absent, Known(&empty)),
(Absent, Known(&project_formatter)),
(Known(&project_formatter), Known(&project_formatter)),
(Known(&old), Known(&new)),
(Known(&new), Known(&empty)),
(Unknown, Known(&new)),
(Unknown, Known(&empty)),
]));
}
@@ -1,40 +1,29 @@
use super::*;
use crate::context::ContextualUserFragment;
use crate::context::world_state::PreviousSectionState;
use crate::context::world_state::test_support::render_section_cases;
use codex_protocol::models::ResponseItem;
use pretty_assertions::assert_eq;
fn render(state: AppsInstructionsState, previous: PreviousSectionState<'_, bool>) -> Vec<String> {
state
.render_diff(previous)
.into_iter()
.map(|fragment| fragment.render())
.collect()
}
#[test]
fn renders_only_when_apps_become_available() {
fn snapshots() {
use PreviousSectionState::Absent;
use PreviousSectionState::Known;
use PreviousSectionState::Unknown;
let unavailable = AppsInstructionsState::new(/*available*/ false);
let available = AppsInstructionsState::new(/*available*/ true);
let false_snapshot = false;
let true_snapshot = true;
assert_eq!(
render(unavailable, PreviousSectionState::Absent),
Vec::<String>::new()
);
assert_eq!(render(available, PreviousSectionState::Absent).len(), 1);
assert_eq!(
render(available, PreviousSectionState::Known(&false_snapshot)).len(),
1
);
assert_eq!(
render(available, PreviousSectionState::Known(&true_snapshot)),
Vec::<String>::new()
);
assert_eq!(
render(unavailable, PreviousSectionState::Known(&true_snapshot)),
Vec::<String>::new()
);
insta::assert_snapshot!(render_section_cases(&[
(Absent, Absent),
(Absent, Known(&unavailable)),
(Absent, Known(&available)),
(Known(&unavailable), Known(&available)),
(Known(&available), Known(&available)),
(Known(&available), Known(&unavailable)),
(Unknown, Known(&unavailable)),
(Unknown, Known(&available)),
]));
}
#[test]
@@ -1,18 +1,18 @@
use super::super::PreviousSectionState;
use super::super::test_support::render_section_cases;
use super::*;
use crate::context::ContextualUserFragment;
use crate::context::world_state::WorldState;
use anyhow::Result;
use codex_exec_server::LOCAL_ENVIRONMENT_ID;
use codex_protocol::models::ContentItem;
use codex_protocol::models::PermissionProfile;
use codex_protocol::models::ResponseItem;
use codex_protocol::permissions::NetworkSandboxPolicy;
use pretty_assertions::assert_eq;
use serde_json::json;
#[test]
fn renders_full_environment_state() -> Result<()> {
let context = EnvironmentsState {
fn snapshots() -> Result<()> {
use PreviousSectionState::Absent;
use PreviousSectionState::Known;
use PreviousSectionState::Unknown;
let full = EnvironmentsState {
environments: [
("laptop".to_string(), available("file:///repo", "zsh")?),
(
@@ -24,34 +24,7 @@ fn renders_full_environment_state() -> Result<()> {
.collect(),
..Default::default()
};
let mut world_state = WorldState::default();
world_state.add_section(context);
assert_eq!(
vec![user_message(
r#"<environment_context>
<environments>
<environment id="devbox">
<cwd>/workspace</cwd>
<shell>bash</shell>
</environment>
<environment id="laptop">
<cwd>/repo</cwd>
<shell>zsh</shell>
</environment>
</environments>
</environment_context>"#,
)],
render_fragments(world_state.render_full()),
);
Ok(())
}
#[test]
fn renders_only_changed_environments() -> Result<()> {
let mut previous = WorldState::default();
previous.add_section(EnvironmentsState {
let before_environment_changes = EnvironmentsState {
environments: [
("laptop".to_string(), available("file:///repo", "bash")?),
("devbox".to_string(), starting("file:///workspace")?),
@@ -60,9 +33,8 @@ fn renders_only_changed_environments() -> Result<()> {
.into_iter()
.collect(),
..Default::default()
});
let mut current = WorldState::default();
current.add_section(EnvironmentsState {
};
let after_environment_changes = EnvironmentsState {
environments: [
("laptop".to_string(), available("file:///repo", "zsh")?),
(
@@ -74,35 +46,7 @@ fn renders_only_changed_environments() -> Result<()> {
.into_iter()
.collect(),
..Default::default()
});
assert_eq!(
vec![user_message(
r#"<environment_context>
<environments>
<environment id="devbox">
<cwd>/workspace</cwd>
<shell>powershell</shell>
</environment>
<environment id="laptop">
<cwd>/repo</cwd>
<shell>zsh</shell>
</environment>
<environment id="old" status="unavailable" />
<environment id="remote">
<cwd>/remote</cwd>
<status>starting</status>
</environment>
</environments>
</environment_context>"#,
)],
render_fragments(current.render_diff(&previous.snapshot())),
);
Ok(())
}
#[test]
fn persisted_turn_context_values_render_a_diff() -> Result<()> {
};
let environments = EnvironmentsState {
environments: [(
LOCAL_ENVIRONMENT_ID.to_string(),
@@ -112,8 +56,7 @@ fn persisted_turn_context_values_render_a_diff() -> Result<()> {
.collect(),
..Default::default()
};
let mut previous = WorldState::default();
previous.add_section(EnvironmentsState {
let before_turn_context_changes = EnvironmentsState {
current_date: Some("2026-06-19".to_string()),
timezone: Some("UTC".to_string()),
network: Some(NetworkContext::new(
@@ -126,9 +69,8 @@ fn persisted_turn_context_values_render_a_diff() -> Result<()> {
&[],
)),
..environments.clone()
});
let mut current = WorldState::default();
current.add_section(EnvironmentsState {
};
let after_turn_context_changes = EnvironmentsState {
current_date: Some("2026-06-20".to_string()),
timezone: Some("America/Los_Angeles".to_string()),
network: Some(NetworkContext::new(
@@ -143,26 +85,8 @@ fn persisted_turn_context_values_render_a_diff() -> Result<()> {
&[],
)),
..environments
});
assert_eq!(
vec![user_message(
r#"<environment_context>
<current_date>2026-06-20</current_date>
<timezone>America/Los_Angeles</timezone>
<network enabled="true"><allowed>new.example.com</allowed><denied>blocked.example.com</denied></network>
<filesystem><permission_profile type="external"><file_system type="external" /></permission_profile></filesystem>
</environment_context>"#,
)],
render_fragments(current.render_diff(&previous.snapshot())),
);
Ok(())
}
#[test]
fn persisted_snapshot_uses_model_visible_path_and_context_values() -> Result<()> {
let mut world_state = WorldState::default();
world_state.add_section(EnvironmentsState {
};
let foreign_windows = EnvironmentsState {
environments: [(
"remote".to_string(),
available("file:///C:/windows", "powershell")?,
@@ -174,29 +98,8 @@ fn persisted_snapshot_uses_model_visible_path_and_context_values() -> Result<()>
&[],
)),
..Default::default()
});
assert_eq!(
serde_json::to_value(world_state.snapshot())?,
json!({
"environments": {
"environments": {
"remote": {
"cwd": "C:\\windows",
"status": "available",
"shell": "powershell"
}
},
"filesystem": "<filesystem><permission_profile type=\"disabled\"><file_system type=\"unrestricted\" /></permission_profile></filesystem>"
}
}),
);
Ok(())
}
#[test]
fn single_environment_diff_ignores_unknown_shell() -> Result<()> {
let previous = EnvironmentsState {
};
let unknown_shell = EnvironmentsState {
environments: [(
LOCAL_ENVIRONMENT_ID.to_string(),
EnvironmentState {
@@ -209,7 +112,7 @@ fn single_environment_diff_ignores_unknown_shell() -> Result<()> {
.collect(),
..Default::default()
};
let current = EnvironmentsState {
let known_shell = EnvironmentsState {
environments: [(
LOCAL_ENVIRONMENT_ID.to_string(),
available("file:///repo", "zsh")?,
@@ -218,21 +121,7 @@ fn single_environment_diff_ignores_unknown_shell() -> Result<()> {
.collect(),
..Default::default()
};
let previous = WorldStateSection::snapshot(&previous);
assert_eq!(
None,
render_fragment(WorldStateSection::render_diff(
&current,
PreviousSectionState::Known(&previous),
))
);
Ok(())
}
#[test]
fn removed_legacy_environment_renders_unavailable() -> Result<()> {
let previous = EnvironmentsState {
let legacy_environment = EnvironmentsState {
environments: [(
LOCAL_ENVIRONMENT_ID.to_string(),
available("file:///repo", "bash")?,
@@ -241,21 +130,24 @@ fn removed_legacy_environment_renders_unavailable() -> Result<()> {
.collect(),
..Default::default()
};
let previous = WorldStateSection::snapshot(&previous);
let empty = EnvironmentsState::default();
assert_eq!(
Some(user_message(
r#"<environment_context>
<environments>
<environment id="local" status="unavailable" />
</environments>
</environment_context>"#,
)),
render_fragment(WorldStateSection::render_diff(
&EnvironmentsState::default(),
PreviousSectionState::Known(&previous),
)),
);
insta::assert_snapshot!(render_section_cases(&[
(Absent, Absent),
(Absent, Known(&full)),
(Unknown, Known(&full)),
(
Known(&before_environment_changes),
Known(&after_environment_changes),
),
(
Known(&before_turn_context_changes),
Known(&after_turn_context_changes),
),
(Absent, Known(&foreign_windows)),
(Known(&unknown_shell), Known(&known_shell)),
(Known(&legacy_environment), Known(&empty)),
]));
Ok(())
}
@@ -274,26 +166,3 @@ fn starting(cwd: &str) -> Result<EnvironmentState> {
shell: None,
})
}
fn render_fragments(fragments: Vec<Box<dyn ContextualUserFragment>>) -> Vec<ResponseItem> {
fragments
.into_iter()
.map(ContextualUserFragment::into_boxed_response_item)
.collect()
}
fn render_fragment(fragment: Option<Box<dyn ContextualUserFragment>>) -> Option<ResponseItem> {
fragment.map(ContextualUserFragment::into_boxed_response_item)
}
fn user_message(text: &str) -> ResponseItem {
ResponseItem::Message {
id: None,
role: "user".to_string(),
content: vec![ContentItem::InputText {
text: text.to_string(),
}],
phase: None,
internal_chat_message_metadata_passthrough: None,
}
}
@@ -2,6 +2,8 @@ mod agents_md;
mod apps_instructions;
mod environment;
mod plugins_instructions;
#[cfg(test)]
mod test_support;
use crate::context::ContextualUserFragment;
use codex_extension_api::PreviousWorldStateSection;
@@ -1,43 +1,29 @@
use super::*;
use crate::context::ContextualUserFragment;
use crate::context::world_state::PreviousSectionState;
use crate::context::world_state::test_support::render_section_cases;
use codex_protocol::models::ResponseItem;
use pretty_assertions::assert_eq;
fn render(
state: PluginsInstructionsState,
previous: PreviousSectionState<'_, bool>,
) -> Vec<String> {
state
.render_diff(previous)
.into_iter()
.map(|fragment| fragment.render())
.collect()
}
#[test]
fn renders_only_when_plugins_become_available() {
fn snapshots() {
use PreviousSectionState::Absent;
use PreviousSectionState::Known;
use PreviousSectionState::Unknown;
let unavailable = PluginsInstructionsState::new(/*available*/ false);
let available = PluginsInstructionsState::new(/*available*/ true);
let false_snapshot = false;
let true_snapshot = true;
assert_eq!(
render(unavailable, PreviousSectionState::Absent),
Vec::<String>::new()
);
assert_eq!(render(available, PreviousSectionState::Absent).len(), 1);
assert_eq!(
render(available, PreviousSectionState::Known(&false_snapshot)).len(),
1
);
assert_eq!(
render(available, PreviousSectionState::Known(&true_snapshot)),
Vec::<String>::new()
);
assert_eq!(
render(unavailable, PreviousSectionState::Known(&true_snapshot)),
Vec::<String>::new()
);
insta::assert_snapshot!(render_section_cases(&[
(Absent, Absent),
(Absent, Known(&unavailable)),
(Absent, Known(&available)),
(Known(&unavailable), Known(&available)),
(Known(&available), Known(&available)),
(Known(&available), Known(&unavailable)),
(Unknown, Known(&unavailable)),
(Unknown, Known(&available)),
]));
}
#[test]
@@ -0,0 +1,51 @@
---
source: core/src/context/world_state/agents_md_tests.rs
expression: "render_section_cases(&[(Absent, Absent), (Absent, Known(&empty)),\n(Absent, Known(&project_formatter)),\n(Known(&project_formatter), Known(&project_formatter)),\n(Known(&old), Known(&new)), (Known(&new), Known(&empty)),\n(Unknown, Known(&new)), (Unknown, Known(&empty)),])"
---
Absent -> Absent
None
Absent -> {}
None
Absent -> {"text":"use the project formatter"} (role - user)
# AGENTS.md instructions
<INSTRUCTIONS>
use the project formatter
</INSTRUCTIONS>
{"text":"use the project formatter"} -> {"text":"use the project formatter"}
None
{"text":"old instructions"} -> {"text":"new instructions"} (role - user)
# AGENTS.md instructions
<INSTRUCTIONS>
These AGENTS.md instructions replace all previously provided AGENTS.md instructions.
new instructions
</INSTRUCTIONS>
{"text":"new instructions"} -> {} (role - user)
# AGENTS.md instructions
<INSTRUCTIONS>
The previously provided AGENTS.md instructions no longer apply.
</INSTRUCTIONS>
Unknown -> {"text":"new instructions"} (role - user)
# AGENTS.md instructions
<INSTRUCTIONS>
These AGENTS.md instructions replace all previously provided AGENTS.md instructions.
new instructions
</INSTRUCTIONS>
Unknown -> {} (role - user)
# AGENTS.md instructions
<INSTRUCTIONS>
The previously provided AGENTS.md instructions no longer apply.
</INSTRUCTIONS>
@@ -0,0 +1,39 @@
---
source: core/src/context/world_state/apps_instructions_tests.rs
expression: "render_section_cases(&[(Absent, Absent), (Absent, Known(&unavailable)),\n(Absent, Known(&available)), (Known(&unavailable), Known(&available)),\n(Known(&available), Known(&available)),\n(Known(&available), Known(&unavailable)), (Unknown, Known(&unavailable)),\n(Unknown, Known(&available)),])"
---
Absent -> Absent
None
Absent -> false
None
Absent -> true (role - developer)
<apps_instructions>
## Apps (Connectors)
Apps (Connectors) can be explicitly triggered in user messages in the format `[$app-name](app://{connector_id})`. Apps can also be implicitly triggered as long as the context suggests usage of available apps.
An app is equivalent to a set of MCP tools within the `codex_apps` MCP.
An installed app's MCP tools are either provided to you already, or can be lazy-loaded through the `tool_search` tool. If `tool_search` is available, the apps that are searchable by `tools_search` will be listed by it.
Do not additionally call list_mcp_resources or list_mcp_resource_templates for apps.
</apps_instructions>
false -> true (role - developer)
<apps_instructions>
## Apps (Connectors)
Apps (Connectors) can be explicitly triggered in user messages in the format `[$app-name](app://{connector_id})`. Apps can also be implicitly triggered as long as the context suggests usage of available apps.
An app is equivalent to a set of MCP tools within the `codex_apps` MCP.
An installed app's MCP tools are either provided to you already, or can be lazy-loaded through the `tool_search` tool. If `tool_search` is available, the apps that are searchable by `tools_search` will be listed by it.
Do not additionally call list_mcp_resources or list_mcp_resource_templates for apps.
</apps_instructions>
true -> true
None
true -> false
None
Unknown -> false
None
Unknown -> true
None
@@ -0,0 +1,78 @@
---
source: core/src/context/world_state/environment_tests.rs
expression: "render_section_cases(&[(Absent, Absent), (Absent, Known(&full)),\n(Unknown, Known(&full)),\n(Known(&before_environment_changes), Known(&after_environment_changes),),\n(Known(&before_turn_context_changes), Known(&after_turn_context_changes),),\n(Absent, Known(&foreign_windows)),\n(Known(&unknown_shell), Known(&known_shell)),\n(Known(&legacy_environment), Known(&empty)),])"
---
Absent -> Absent
None
Absent -> {"environments":{"devbox":{"cwd":"/workspace","shell":"bash","status":"available"},"laptop":{"cwd":"/repo","shell":"zsh","status":"available"}}} (role - user)
<environment_context>
<environments>
<environment id="devbox">
<cwd>/workspace</cwd>
<shell>bash</shell>
</environment>
<environment id="laptop">
<cwd>/repo</cwd>
<shell>zsh</shell>
</environment>
</environments>
</environment_context>
Unknown -> {"environments":{"devbox":{"cwd":"/workspace","shell":"bash","status":"available"},"laptop":{"cwd":"/repo","shell":"zsh","status":"available"}}} (role - user)
<environment_context>
<environments>
<environment id="devbox">
<cwd>/workspace</cwd>
<shell>bash</shell>
</environment>
<environment id="laptop">
<cwd>/repo</cwd>
<shell>zsh</shell>
</environment>
</environments>
</environment_context>
{"environments":{"devbox":{"cwd":"/workspace","status":"starting"},"laptop":{"cwd":"/repo","shell":"bash","status":"available"},"old":{"cwd":"/old","shell":"sh","status":"available"}}} -> {"environments":{"devbox":{"cwd":"/workspace","shell":"powershell","status":"available"},"laptop":{"cwd":"/repo","shell":"zsh","status":"available"},"remote":{"cwd":"/remote","status":"starting"}}} (role - user)
<environment_context>
<environments>
<environment id="devbox">
<cwd>/workspace</cwd>
<shell>powershell</shell>
</environment>
<environment id="laptop">
<cwd>/repo</cwd>
<shell>zsh</shell>
</environment>
<environment id="old" status="unavailable" />
<environment id="remote">
<cwd>/remote</cwd>
<status>starting</status>
</environment>
</environments>
</environment_context>
{"current_date":"2026-06-19","environments":{"local":{"cwd":"/repo","shell":"zsh","status":"available"}},"filesystem":"<filesystem><permission_profile type=\"disabled\"><file_system type=\"unrestricted\" /></permission_profile></filesystem>","network":"<network enabled=\"true\"><allowed>old.example.com</allowed></network>","timezone":"UTC"} -> {"current_date":"2026-06-20","environments":{"local":{"cwd":"/repo","shell":"zsh","status":"available"}},"filesystem":"<filesystem><permission_profile type=\"external\"><file_system type=\"external\" /></permission_profile></filesystem>","network":"<network enabled=\"true\"><allowed>new.example.com</allowed><denied>blocked.example.com</denied></network>","timezone":"America/Los_Angeles"} (role - user)
<environment_context>
<current_date>2026-06-20</current_date>
<timezone>America/Los_Angeles</timezone>
<network enabled="true"><allowed>new.example.com</allowed><denied>blocked.example.com</denied></network>
<filesystem><permission_profile type="external"><file_system type="external" /></permission_profile></filesystem>
</environment_context>
Absent -> {"environments":{"remote":{"cwd":"C:\\windows","shell":"powershell","status":"available"}},"filesystem":"<filesystem><permission_profile type=\"disabled\"><file_system type=\"unrestricted\" /></permission_profile></filesystem>"} (role - user)
<environment_context>
<cwd>C:\windows</cwd>
<shell>powershell</shell>
<filesystem><permission_profile type="disabled"><file_system type="unrestricted" /></permission_profile></filesystem>
</environment_context>
{"environments":{"local":{"cwd":"/repo","status":"available"}}} -> {"environments":{"local":{"cwd":"/repo","shell":"zsh","status":"available"}}}
None
{"environments":{"local":{"cwd":"/repo","shell":"bash","status":"available"}}} -> {"environments":{}} (role - user)
<environment_context>
<environments>
<environment id="local" status="unavailable" />
</environments>
</environment_context>
@@ -0,0 +1,47 @@
---
source: core/src/context/world_state/plugins_instructions_tests.rs
expression: "render_section_cases(&[(Absent, Absent), (Absent, Known(&unavailable)),\n(Absent, Known(&available)), (Known(&unavailable), Known(&available)),\n(Known(&available), Known(&available)),\n(Known(&available), Known(&unavailable)), (Unknown, Known(&unavailable)),\n(Unknown, Known(&available)),])"
---
Absent -> Absent
None
Absent -> false
None
Absent -> true (role - developer)
<plugins_instructions>
## Plugins
A plugin is a local bundle of skills, MCP servers, and apps.
### How to use plugins
- Skill naming: If a plugin contributes skills, those skill entries are prefixed with `plugin_name:` in the Skills list.
- MCP naming: Plugin-provided MCP tools keep standard MCP identifiers such as `mcp__server__tool`; use tool provenance to tell which plugin they come from.
- Trigger rules: If the user explicitly names a plugin, prefer capabilities associated with that plugin for that turn.
- Relationship to capabilities: Plugins are not invoked directly. Use their underlying skills, MCP tools, and app tools to help solve the task.
- Relevance: Determine what a plugin can help with from explicit user mention or from the plugin-associated skills, MCP tools, and apps exposed elsewhere in this turn.
- Missing/blocked: If the user requests a plugin that does not have relevant callable capabilities for the task, say so briefly and continue with the best fallback.
</plugins_instructions>
false -> true (role - developer)
<plugins_instructions>
## Plugins
A plugin is a local bundle of skills, MCP servers, and apps.
### How to use plugins
- Skill naming: If a plugin contributes skills, those skill entries are prefixed with `plugin_name:` in the Skills list.
- MCP naming: Plugin-provided MCP tools keep standard MCP identifiers such as `mcp__server__tool`; use tool provenance to tell which plugin they come from.
- Trigger rules: If the user explicitly names a plugin, prefer capabilities associated with that plugin for that turn.
- Relationship to capabilities: Plugins are not invoked directly. Use their underlying skills, MCP tools, and app tools to help solve the task.
- Relevance: Determine what a plugin can help with from explicit user mention or from the plugin-associated skills, MCP tools, and apps exposed elsewhere in this turn.
- Missing/blocked: If the user requests a plugin that does not have relevant callable capabilities for the task, say so briefly and continue with the best fallback.
</plugins_instructions>
true -> true
None
true -> false
None
Unknown -> false
None
Unknown -> true
None
@@ -0,0 +1,83 @@
use super::ErasedWorldStateSection;
use super::PreviousSectionState;
use super::WorldStateSection;
use crate::context::ContextualUserFragment;
pub(super) fn render_section_cases<'a, S: WorldStateSection>(
cases: &[(PreviousSectionState<'a, S>, PreviousSectionState<'a, S>)],
) -> String {
cases
.iter()
.map(|(before, after)| {
let rendered = render_diff(before, after);
let role = rendered.as_ref().map_or_else(String::new, |fragment| {
format!(" (role - {})", fragment.role())
});
let content = rendered
.as_ref()
.map_or_else(|| "None".to_string(), |fragment| fragment.render());
format!(
"{} -> {}{role}\n{content}",
render_state(before),
render_state(after),
)
})
.collect::<Vec<_>>()
.join("\n\n")
}
fn render_state<S: WorldStateSection>(state: &PreviousSectionState<'_, S>) -> String {
match state {
PreviousSectionState::Absent => "Absent".to_string(),
PreviousSectionState::Unknown => "Unknown".to_string(),
PreviousSectionState::Known(section) => render_snapshot(*section),
}
}
fn render_diff<S: WorldStateSection>(
before: &PreviousSectionState<'_, S>,
after: &PreviousSectionState<'_, S>,
) -> Option<Box<dyn ContextualUserFragment>> {
let PreviousSectionState::Known(after) = after else {
return None;
};
let previous_snapshot;
let previous = match before {
PreviousSectionState::Absent => PreviousSectionState::Absent,
PreviousSectionState::Unknown => PreviousSectionState::Unknown,
PreviousSectionState::Known(before) => {
previous_snapshot = snapshot_value(*before);
PreviousSectionState::Known(&previous_snapshot)
}
};
ErasedWorldStateSection::render_diff(*after, previous)
}
fn render_snapshot<S: WorldStateSection>(section: &S) -> String {
serde_json::to_string(&sort_json(snapshot_value(section)))
.expect("world-state section snapshot should serialize")
}
fn sort_json(value: serde_json::Value) -> serde_json::Value {
match value {
serde_json::Value::Array(values) => {
serde_json::Value::Array(values.into_iter().map(sort_json).collect())
}
serde_json::Value::Object(values) => {
let mut values = values.into_iter().collect::<Vec<_>>();
values.sort_by(|(left, _), (right, _)| left.cmp(right));
serde_json::Value::Object(
values
.into_iter()
.map(|(key, value)| (key, sort_json(value)))
.collect(),
)
}
value => value,
}
}
fn snapshot_value<S: WorldStateSection>(section: &S) -> serde_json::Value {
ErasedWorldStateSection::snapshot(section)
.expect("world-state section snapshot should serialize to a non-null value")
}