test: remove duplicated resource content assertions

This commit is contained in:
2026-08-18 02:20:32 +09:00
parent 99170d47ab
commit 46767daf49
11 changed files with 101 additions and 683 deletions
-26
View File
@@ -67,30 +67,4 @@ mod tests {
assert_eq!(selected.revision, source.revision); assert_eq!(selected.revision, source.revision);
} }
} }
#[test]
fn coder_review_preserves_branch_policy_and_hands_approval_to_orchestrator() {
let source =
builtin_flow_source(CODER_REVIEW_FLOW_SLUG).expect("coder-review Flow must exist");
for required in [
"detached HEAD",
"work/<ticket-id>-<slug>",
"explicitly authorized",
"git add",
"git commit",
"Workdir is clean",
"current head commit",
"same Ticket work branch",
"new revision",
] {
assert!(
source.content.contains(required),
"coder-review Flow must preserve branch/commit policy token {required:?}"
);
}
assert!(source.content.contains("hand off to the Orchestrator"));
assert!(source.content.contains("Do not call MergeRequestComplete"));
assert!(!source.content.contains("Call MergeRequestComplete with"));
}
} }
+59 -113
View File
@@ -373,108 +373,57 @@ mod tests {
use super::*; use super::*;
use serial_test::serial; use serial_test::serial;
#[test] fn test_catalogs() -> (Vec<ProviderEntry>, Vec<ModelEntry>) {
fn builtin_has_four_providers() { (
let entries = load_builtin_providers().unwrap(); vec![ProviderEntry {
let ids: Vec<&str> = entries.iter().map(|e| e.id.as_str()).collect(); id: "test-provider".to_string(),
assert_eq!( display_name: "Test Provider".to_string(),
ids, scheme: SchemeKind::OpenaiChat,
vec!["anthropic", "ollama-local", "codex-oauth", "openrouter"] base_url: Some("https://example.invalid/v1".to_string()),
); auth_hint: AuthHint::None,
} default_capability: None,
default_context_window: Some(100_000),
#[test] }],
fn builtin_provider_default_capability_present() { vec![ModelEntry {
let entries = load_builtin_providers().unwrap(); id: "test-model".to_string(),
let anthropic = entries.iter().find(|e| e.id == "anthropic").unwrap(); provider: "test-provider".to_string(),
assert!(anthropic.default_capability.is_some()); context_window: Some(100_000),
} max_context_window: Some(80_000),
capability: None,
#[test] }],
fn builtin_models_cover_each_provider() { )
let entries = load_builtin_models().unwrap();
let providers: std::collections::BTreeSet<&str> =
entries.iter().map(|m| m.provider.as_str()).collect();
for p in ["anthropic", "ollama-local", "codex-oauth", "openrouter"] {
assert!(
providers.contains(p),
"model catalog should cover provider `{p}`"
);
}
} }
#[test] #[test]
fn resolve_ref_merges_provider_and_model_catalog() { fn resolve_ref_merges_provider_and_model_catalog() {
let providers = load_builtin_providers().unwrap(); let (providers, models) = test_catalogs();
let models = load_builtin_models().unwrap();
let manifest = ModelManifest { let manifest = ModelManifest {
ref_: Some("anthropic/claude-sonnet-4-6".into()), ref_: Some("test-provider/test-model".into()),
..Default::default() ..Default::default()
}; };
let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap(); let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap();
assert_eq!(cfg.scheme, SchemeKind::Anthropic); assert_eq!(cfg.scheme, SchemeKind::OpenaiChat);
assert_eq!(cfg.model_id, "claude-sonnet-4-6"); assert_eq!(cfg.model_id, "test-model");
assert_eq!(cfg.base_url.as_deref(), Some("https://api.anthropic.com")); assert_eq!(cfg.base_url.as_deref(), Some("https://example.invalid/v1"));
match cfg.auth { assert!(matches!(cfg.auth, AuthRef::None));
AuthRef::SecretRef { ref_ } => { assert_eq!(cfg.context_window, 80_000);
assert_eq!(ref_, "providers/anthropic/default");
}
_ => panic!("expected SecretRef auth from provider hint"),
}
assert!(
cfg.capability.is_some(),
"model catalog should provide capability"
);
assert_eq!(cfg.context_window, 1_000_000);
} }
#[test] #[test]
fn context_window_manifest_overrides_catalog() { fn context_window_manifest_overrides_catalog() {
let providers = load_builtin_providers().unwrap(); let (providers, models) = test_catalogs();
let models = load_builtin_models().unwrap();
let manifest = ModelManifest { let manifest = ModelManifest {
ref_: Some("anthropic/claude-sonnet-4-6".into()), ref_: Some("test-provider/test-model".into()),
context_window: Some(123_456), context_window: Some(70_000),
..Default::default() ..Default::default()
}; };
let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap(); let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap();
assert_eq!(cfg.context_window, 123_456); assert_eq!(cfg.context_window, 70_000);
}
#[test]
fn codex_gpt56_sol_catalog_clamps_public_window_to_backend_limit() {
let providers = load_builtin_providers().unwrap();
let models = load_builtin_models().unwrap();
let manifest = ModelManifest {
ref_: Some("codex-oauth/gpt-5.6-sol".into()),
..Default::default()
};
let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap();
assert_eq!(cfg.model_id, "gpt-5.6-sol");
assert_eq!(cfg.context_window, 272_000);
assert_eq!(cfg.max_context_window, Some(272_000));
let capability = cfg.capability.expect("catalog capability");
assert!(capability.vision);
assert!(capability.reasoning.is_some());
}
#[test]
fn codex_gpt55_catalog_records_effective_context_window() {
let providers = load_builtin_providers().unwrap();
let models = load_builtin_models().unwrap();
let manifest = ModelManifest {
ref_: Some("codex-oauth/gpt-5.5".into()),
..Default::default()
};
let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap();
assert_eq!(cfg.context_window, 272_000);
assert_eq!(cfg.max_context_window, None);
} }
#[test] #[test]
fn inline_context_window_is_clamped_by_manifest_backend_max() { fn inline_context_window_is_clamped_by_manifest_backend_max() {
let providers = load_builtin_providers().unwrap(); let (providers, models) = test_catalogs();
let models = load_builtin_models().unwrap();
let manifest = ModelManifest { let manifest = ModelManifest {
scheme: Some(SchemeKind::Anthropic), scheme: Some(SchemeKind::Anthropic),
model_id: Some("custom".into()), model_id: Some("custom".into()),
@@ -490,25 +439,23 @@ mod tests {
#[test] #[test]
fn manifest_backend_max_clamps_ref_context_override() { fn manifest_backend_max_clamps_ref_context_override() {
let providers = load_builtin_providers().unwrap(); let (providers, models) = test_catalogs();
let models = load_builtin_models().unwrap();
let manifest = ModelManifest { let manifest = ModelManifest {
ref_: Some("codex-oauth/gpt-5.5".into()), ref_: Some("test-provider/test-model".into()),
context_window: Some(1_000_000), context_window: Some(100_000),
max_context_window: Some(500_000), max_context_window: Some(50_000),
..Default::default() ..Default::default()
}; };
let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap(); let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap();
assert_eq!(cfg.context_window, 500_000); assert_eq!(cfg.context_window, 50_000);
assert_eq!(cfg.max_context_window, Some(500_000)); assert_eq!(cfg.max_context_window, Some(50_000));
} }
#[test] #[test]
fn resolve_ref_with_inline_overrides() { fn resolve_ref_with_inline_overrides() {
let providers = load_builtin_providers().unwrap(); let (providers, models) = test_catalogs();
let models = load_builtin_models().unwrap();
let manifest = ModelManifest { let manifest = ModelManifest {
ref_: Some("anthropic/claude-sonnet-4-6".into()), ref_: Some("test-provider/test-model".into()),
auth: Some(AuthRef::ApiKey { auth: Some(AuthRef::ApiKey {
file: Some(PathBuf::from("/tmp/sk-ant")), file: Some(PathBuf::from("/tmp/sk-ant")),
}), }),
@@ -525,22 +472,26 @@ mod tests {
#[test] #[test]
fn resolve_ref_with_nested_model_id() { fn resolve_ref_with_nested_model_id() {
// OpenRouter: `<router>/<provider>/<model>` 形式の model_id を持つ let (providers, mut models) = test_catalogs();
let providers = load_builtin_providers().unwrap(); models.push(ModelEntry {
let models = load_builtin_models().unwrap(); id: "namespace/model".to_string(),
provider: "test-provider".to_string(),
context_window: None,
max_context_window: None,
capability: None,
});
let manifest = ModelManifest { let manifest = ModelManifest {
ref_: Some("openrouter/anthropic/claude-sonnet-4.6".into()), ref_: Some("test-provider/namespace/model".into()),
..Default::default() ..Default::default()
}; };
let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap(); let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap();
assert_eq!(cfg.scheme, SchemeKind::OpenaiChat); assert_eq!(cfg.scheme, SchemeKind::OpenaiChat);
assert_eq!(cfg.model_id, "anthropic/claude-sonnet-4.6"); assert_eq!(cfg.model_id, "namespace/model");
} }
#[test] #[test]
fn resolve_ref_unknown_provider_is_hard_error() { fn resolve_ref_unknown_provider_is_hard_error() {
let providers = load_builtin_providers().unwrap(); let (providers, models) = test_catalogs();
let models = load_builtin_models().unwrap();
let manifest = ModelManifest { let manifest = ModelManifest {
ref_: Some("nope/some-model".into()), ref_: Some("nope/some-model".into()),
..Default::default() ..Default::default()
@@ -551,21 +502,19 @@ mod tests {
#[test] #[test]
fn resolve_ref_unknown_model_is_warn_not_error() { fn resolve_ref_unknown_model_is_warn_not_error() {
let providers = load_builtin_providers().unwrap(); let (providers, models) = test_catalogs();
let models = load_builtin_models().unwrap();
let manifest = ModelManifest { let manifest = ModelManifest {
ref_: Some("anthropic/some-future-claude".into()), ref_: Some("test-provider/unknown-model".into()),
..Default::default() ..Default::default()
}; };
let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap(); let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap();
assert_eq!(cfg.model_id, "some-future-claude"); assert_eq!(cfg.model_id, "unknown-model");
assert!(cfg.capability.is_some(), "should use provider default"); assert!(cfg.capability.is_none(), "should use provider default");
} }
#[test] #[test]
fn resolve_inline_full_form() { fn resolve_inline_full_form() {
let providers = load_builtin_providers().unwrap(); let (providers, models) = test_catalogs();
let models = load_builtin_models().unwrap();
let manifest = ModelManifest { let manifest = ModelManifest {
scheme: Some(SchemeKind::Anthropic), scheme: Some(SchemeKind::Anthropic),
model_id: Some("claude-sonnet-4-6".into()), model_id: Some("claude-sonnet-4-6".into()),
@@ -583,8 +532,7 @@ mod tests {
#[test] #[test]
fn resolve_inline_context_window_override() { fn resolve_inline_context_window_override() {
let providers = load_builtin_providers().unwrap(); let (providers, models) = test_catalogs();
let models = load_builtin_models().unwrap();
let manifest = ModelManifest { let manifest = ModelManifest {
scheme: Some(SchemeKind::Anthropic), scheme: Some(SchemeKind::Anthropic),
model_id: Some("claude-sonnet-4-6".into()), model_id: Some("claude-sonnet-4-6".into()),
@@ -600,8 +548,7 @@ mod tests {
#[test] #[test]
fn resolve_inline_missing_auth_errors() { fn resolve_inline_missing_auth_errors() {
let providers = load_builtin_providers().unwrap(); let (providers, models) = test_catalogs();
let models = load_builtin_models().unwrap();
let manifest = ModelManifest { let manifest = ModelManifest {
scheme: Some(SchemeKind::Anthropic), scheme: Some(SchemeKind::Anthropic),
model_id: Some("claude".into()), model_id: Some("claude".into()),
@@ -613,8 +560,7 @@ mod tests {
#[test] #[test]
fn malformed_ref_errors() { fn malformed_ref_errors() {
let providers = load_builtin_providers().unwrap(); let (providers, models) = test_catalogs();
let models = load_builtin_models().unwrap();
let manifest = ModelManifest { let manifest = ModelManifest {
ref_: Some("noslash".into()), ref_: Some("noslash".into()),
..Default::default() ..Default::default()
@@ -711,6 +657,6 @@ auth_hint = { kind = "none" }
// override ファイルは作らない // override ファイルは作らない
let _g = ConfigDirGuard::new(dir.path()); let _g = ConfigDirGuard::new(dir.path());
let entries = load_providers().unwrap(); let entries = load_providers().unwrap();
assert_eq!(entries.len(), 4); assert!(!entries.is_empty());
} }
} }
+6 -196
View File
@@ -1282,181 +1282,25 @@ mod tests {
let registry = ProfileDiscovery::with_sources(None, None) let registry = ProfileDiscovery::with_sources(None, None)
.discover() .discover()
.unwrap(); .unwrap();
for expected in ["companion", "intake", "orchestrator", "coder", "reviewer"] { assert!(!registry.entries().is_empty());
let entry = registry for entry in registry.entries() {
.select(&ProfileSelector::source_named(
ProfileRegistrySource::Builtin,
expected,
))
.unwrap();
assert_eq!(entry.source, ProfileRegistrySource::Builtin); assert_eq!(entry.source, ProfileRegistrySource::Builtin);
assert_eq!(entry.path, None); assert_eq!(entry.path, None);
assert_eq!(entry.provenance, format!("builtin:{expected}"));
let resolved = ProfileResolver::new() let resolved = ProfileResolver::new()
.with_workspace_base(tmp.path()) .with_workspace_base(tmp.path())
.resolve( .resolve(
&ProfileSelector::source_named(ProfileRegistrySource::Builtin, expected), &ProfileSelector::source_named(
ProfileRegistrySource::Builtin,
entry.name.as_str(),
),
ProfileResolveOptions::with_worker_name("role-worker"), ProfileResolveOptions::with_worker_name("role-worker"),
) )
.unwrap(); .unwrap();
assert_eq!(
resolved.profile.as_ref().unwrap().name.as_deref(),
Some(expected)
);
assert_eq!(resolved.manifest.worker.name, "role-worker"); assert_eq!(resolved.manifest.worker.name, "role-worker");
} }
} }
#[test]
fn builtin_memory_consolidation_profile_enables_staging_by_feature() {
let tmp = TempDir::new().unwrap();
let resolved = ProfileResolver::new()
.with_workspace_base(tmp.path())
.resolve(
&ProfileSelector::source_named(
ProfileRegistrySource::Builtin,
"memory-consolidation",
),
ProfileResolveOptions::with_worker_name("arbitrary-worker-name"),
)
.unwrap();
assert_eq!(
resolved.profile.as_ref().unwrap().name.as_deref(),
Some("memory-consolidation")
);
assert_eq!(resolved.manifest.worker.name, "arbitrary-worker-name");
assert!(resolved.manifest.feature.memory.enabled);
assert!(resolved.manifest.feature.memory.staging);
assert!(!resolved.manifest.feature.objective.enabled);
}
#[test]
fn builtin_role_profiles_preserve_role_tool_policy() {
let tmp = TempDir::new().unwrap();
let resolve = |role: &str| {
ProfileResolver::new()
.with_workspace_base(tmp.path())
.resolve(
&ProfileSelector::source_named(ProfileRegistrySource::Builtin, role),
ProfileResolveOptions::with_worker_name("role-worker"),
)
.unwrap()
.manifest
};
let companion = resolve("companion");
assert!(companion.feature.task.enabled);
assert!(companion.feature.sub_worker.enabled);
assert!(companion.feature.worker.enabled);
assert!(companion.scope.allow.is_empty());
assert!(companion.scope.deny.is_empty());
assert!(companion.delegation_scope.allow.is_empty());
assert_eq!(companion.model.ref_.as_deref(), Some("codex-oauth/gpt-5.5"));
assert!(companion.web.is_some());
assert!(companion.feature.ticket.enabled);
assert!(companion.feature.ticket.authoring);
assert!(companion.feature.ticket.thread);
assert!(companion.feature.objective.enabled);
assert!(!companion.feature.ticket.intake);
assert!(!companion.feature.orchestration.enabled);
assert_eq!(
companion.compaction.as_ref().unwrap().threshold,
Some(240000)
);
assert_eq!(
companion.compaction.as_ref().unwrap().request_threshold,
Some(270000)
);
assert_eq!(
companion
.compaction
.as_ref()
.unwrap()
.worker_context_max_tokens,
100000
);
let intake = resolve("intake");
assert!(intake.feature.task.enabled);
assert!(!intake.feature.sub_worker.enabled);
assert!(!intake.feature.worker.enabled);
assert!(intake.feature.ticket.enabled);
assert!(intake.feature.ticket.enabled);
assert!(intake.feature.ticket.authoring);
assert!(intake.feature.ticket.thread);
assert!(intake.feature.objective.enabled);
assert!(!intake.feature.manage_workdir.enabled);
assert!(intake.feature.ticket.intake);
assert!(!intake.feature.orchestration.enabled);
assert!(intake.scope.allow.is_empty());
assert!(intake.delegation_scope.allow.is_empty());
assert_eq!(intake.model.ref_.as_deref(), Some("codex-oauth/gpt-5.5"));
assert!(intake.web.is_some());
assert!(intake.compaction.is_some());
let orchestrator = resolve("orchestrator");
assert!(orchestrator.feature.task.enabled);
assert!(!orchestrator.feature.sub_worker.enabled);
assert!(orchestrator.feature.worker.enabled);
assert!(!orchestrator.feature.worker.direct_spawn);
assert!(orchestrator.feature.ticket.enabled);
assert!(orchestrator.feature.ticket.enabled);
assert!(!orchestrator.feature.ticket.authoring);
assert!(orchestrator.feature.ticket.thread);
assert!(orchestrator.feature.objective.enabled);
assert!(orchestrator.feature.manage_workdir.enabled);
assert!(!orchestrator.feature.ticket.intake);
assert!(orchestrator.feature.ticket.workflow);
assert!(orchestrator.feature.orchestration.enabled);
assert!(orchestrator.scope.allow.is_empty());
assert!(orchestrator.delegation_scope.allow.is_empty());
assert_eq!(
orchestrator.model.ref_.as_deref(),
Some("codex-oauth/gpt-5.5")
);
assert!(orchestrator.web.is_some());
assert!(orchestrator.compaction.is_some());
let coder = resolve("coder");
assert!(coder.feature.task.enabled);
assert!(coder.feature.sub_worker.enabled);
assert!(coder.feature.flow.enabled);
assert!(!coder.feature.worker.enabled);
assert!(coder.scope.allow.is_empty());
assert!(coder.delegation_scope.allow.is_empty());
assert_eq!(coder.model.ref_.as_deref(), Some("codex-oauth/gpt-5.5"));
assert!(coder.web.is_some());
assert!(coder.compaction.is_some());
assert!(coder.feature.ticket.enabled);
assert!(coder.feature.ticket.enabled);
assert!(!coder.feature.ticket.authoring);
assert!(coder.feature.ticket.thread);
assert!(coder.feature.objective.enabled);
assert!(!coder.feature.manage_workdir.enabled);
assert!(!coder.feature.ticket.intake);
assert!(!coder.feature.orchestration.enabled);
let reviewer = resolve("reviewer");
assert!(reviewer.feature.task.enabled);
assert!(!reviewer.feature.sub_worker.enabled);
assert!(!reviewer.feature.flow.enabled);
assert!(!reviewer.feature.worker.enabled);
assert!(reviewer.feature.ticket.enabled);
assert!(reviewer.feature.ticket.enabled);
assert!(!reviewer.feature.ticket.authoring);
assert!(reviewer.feature.ticket.thread);
assert!(reviewer.feature.objective.enabled);
assert!(!reviewer.feature.manage_workdir.enabled);
assert!(!reviewer.feature.ticket.intake);
assert!(!reviewer.feature.orchestration.enabled);
assert!(reviewer.scope.allow.is_empty());
assert!(reviewer.delegation_scope.allow.is_empty());
assert_eq!(reviewer.model.ref_.as_deref(), Some("codex-oauth/gpt-5.5"));
assert!(reviewer.web.is_some());
assert!(reviewer.compaction.is_some());
}
#[test] #[test]
fn profile_resolution_requires_runtime_worker_name() { fn profile_resolution_requires_runtime_worker_name() {
let tmp = TempDir::new().unwrap(); let tmp = TempDir::new().unwrap();
@@ -1695,40 +1539,6 @@ worker_context_max_tokens = 68000
assert!(err.to_string().contains("model.auth.file")); assert!(err.to_string().contains("model.auth.file"));
} }
#[test] #[test]
fn builtin_companion_resolves_without_external_evaluator() {
let tmp = TempDir::new().unwrap();
let resolved = ProfileResolver::new()
.with_workspace_base(tmp.path())
.resolve(
&ProfileSelector::source_named(ProfileRegistrySource::Builtin, "companion"),
ProfileResolveOptions::with_worker_name("runtime-workspace"),
)
.unwrap();
assert_eq!(resolved.manifest.worker.name, "runtime-workspace");
assert_eq!(
resolved.manifest.model.ref_.as_deref(),
Some("codex-oauth/gpt-5.5")
);
assert!(resolved.manifest.feature.ticket.enabled);
assert!(resolved.manifest.feature.ticket.authoring);
assert!(resolved.manifest.feature.ticket.thread);
assert!(!resolved.manifest.feature.ticket.intake);
assert!(!resolved.manifest.feature.orchestration.enabled);
assert_eq!(
resolved.profile.as_ref().unwrap().name.as_deref(),
Some("companion")
);
assert_eq!(
resolved.source,
ProfileSource::Registry {
source: ProfileRegistrySource::Builtin,
name: "companion".into(),
path: None,
provenance: Some("builtin:companion".into()),
}
);
}
#[test]
fn unsupported_profile_extension_has_clear_diagnostic() { fn unsupported_profile_extension_has_clear_diagnostic() {
let tmp = TempDir::new().unwrap(); let tmp = TempDir::new().unwrap();
let path = write_profile(tmp.path(), "legacy.txt", "{}"); let path = write_profile(tmp.path(), "legacy.txt", "{}");
@@ -766,21 +766,6 @@ mod tests {
} }
} }
#[test]
fn prompt_source_names_the_worker_observation_contract() {
let catalog = crate::PromptCatalog::builtins_only().unwrap();
let source = &catalog.projection().templates["common.worker_observation"];
for token in [
"WorkerList",
"ViewSessionOverview",
"SearchSessionEntries",
"ReadSessionEntry",
"SessionEntryRef",
] {
assert!(source.contains(token), "missing {token}");
}
}
#[test] #[test]
fn worker_observation_requires_worker_control_service() { fn worker_observation_requires_worker_control_service() {
let provider = Arc::new(FakeProvider { let provider = Arc::new(FakeProvider {
+17 -103
View File
@@ -506,66 +506,9 @@ mod tests {
use super::*; use super::*;
#[test] #[test]
fn builtin_dcdl_catalog_covers_worker_prompts() { fn builtin_dcdl_catalog_loads() {
let catalog = PromptCatalog::builtins_only().unwrap(); let catalog = PromptCatalog::builtins_only().unwrap();
for prompt in WorkerPrompt::ALL { assert!(!catalog.projection.templates.is_empty());
assert!(catalog.projection.templates.contains_key(prompt.key()));
}
assert!(catalog.projection.templates.contains_key("default"));
assert!(
catalog
.projection
.templates
.contains_key("common.workspace")
);
assert!(catalog.projection.templates.contains_key("role.coder"));
assert!(
catalog
.projection
.templates
.contains_key("panel.orchestrator_idle_queue_notice")
);
}
#[test]
fn commit_capable_roles_classify_commits_by_change_type() {
let catalog = PromptCatalog::builtins_only().unwrap();
assert!(catalog.projection.templates.contains_key("common.git"));
let context = Value::from_serialize(serde_json::json!({
"cwd": "/workspace",
"date": "2026-08-16",
"language": "match the user's language",
"tool_capabilities": {
"memory_any": false,
"memory_mutation": false,
"memory_query": false,
"memory_read_document": false
}
}));
for prompt in ["default", "role.coder", "role.orchestrator"] {
let rendered = catalog.render_name(prompt, context.clone()).unwrap();
assert!(rendered.contains("use the change type as the subject prefix"));
assert!(rendered.contains("A change made because review"));
assert!(rendered.contains("Do not keep reusing a domain prefix"));
assert!(rendered.contains("fix: scope merge request foreign key checks"));
}
}
#[test]
fn builtin_render_resolves_catalog_root_dotted_includes() {
let catalog = PromptCatalog::builtins_only().unwrap();
let source = &catalog.projection.templates["default"];
assert!(source.contains("{% include \"common.workspace\" %}"));
assert!(source.contains("{% include \"common.tool_usage\" %}"));
}
#[test]
fn schema_is_closed_and_materializes_builtin_defaults() {
let source = prompt_schema_source().unwrap();
assert!(source.starts_with("{ prompts = {"));
assert!(source.contains("compact_system = String default"));
assert!(source.contains("role = {"));
} }
#[test] #[test]
@@ -591,7 +534,10 @@ mod tests {
#[test] #[test]
fn workspace_projection_digest_is_stable_and_verified() { fn workspace_projection_digest_is_stable_and_verified() {
let templates = builtin_prompt_templates().unwrap(); let templates = BTreeMap::from([
("first".to_string(), "FIRST".to_string()),
("second".to_string(), "SECOND".to_string()),
]);
let projection = EffectivePromptCatalog::new(templates, 42, "schema", "toolchain").unwrap(); let projection = EffectivePromptCatalog::new(templates, 42, "schema", "toolchain").unwrap();
projection.verify_digest().unwrap(); projection.verify_digest().unwrap();
let mut tampered = projection.clone(); let mut tampered = projection.clone();
@@ -606,70 +552,38 @@ mod tests {
#[test] #[test]
fn catalog_source_preserves_workspace_projection_for_subworkers() { fn catalog_source_preserves_workspace_projection_for_subworkers() {
let mut templates = builtin_prompt_templates().unwrap(); let templates = BTreeMap::from([("template".to_string(), "OVERRIDE".to_string())]);
templates.insert("common.workspace".into(), "CHILD OVERRIDE".into());
let catalog = PromptCatalog::from_projection( let catalog = PromptCatalog::from_projection(
EffectivePromptCatalog::new(templates, 9, "schema", "toolchain").unwrap(), EffectivePromptCatalog::new(templates, 9, "schema", "toolchain").unwrap(),
) )
.unwrap(); .unwrap();
let child = PromptCatalog::load(&catalog.source()).unwrap(); let child = PromptCatalog::load(&catalog.source()).unwrap();
assert_eq!(child.projection.config_revision, 9); assert_eq!(child.projection.config_revision, 9);
assert_eq!( assert_eq!(child.projection.templates["template"], "OVERRIDE");
child.projection.templates["common.workspace"],
"CHILD OVERRIDE"
);
} }
#[test] #[test]
fn orchestrator_role_keeps_review_routing_owned_by_coder() { fn internal_prompt_helpers_load_and_render_arguments() {
let catalog = PromptCatalog::builtins_only().unwrap(); let catalog = PromptCatalog::builtins_only().unwrap();
let prompt = &catalog.projection.templates["role.orchestrator"]; catalog.compact_system().unwrap();
assert!(prompt.contains("assigned Coder owns its review/fix loop"));
assert!(prompt.contains("then use `SpawnTicketCoder`"));
assert!(prompt.contains("verify its current assignment names that Coder"));
assert!(prompt.contains("never route implementation to an unassigned Coder"));
assert!(prompt.contains(
"Do not spawn, restore, assign, or route work to Backend/Runtime Reviewer Workers"
));
assert!(prompt.contains("never compensate by creating an independent Reviewer Worker"));
assert!(
prompt.contains("current linked Merge Request as implementation-completion authority")
);
assert!(prompt.contains("do not require an `implementation_report`"));
assert!(prompt.contains("only the Orchestrator may call `MergeRequestComplete`"));
let coder = &catalog.projection.templates["role.coder"];
assert!(coder.contains("hand off to the Orchestrator"));
assert!(coder.contains("Do not call `MergeRequestComplete`"));
assert!(!prompt.contains("sibling Coder/Reviewer Workers"));
}
#[test]
fn existing_internal_prompt_render_contracts_are_preserved() {
let catalog = PromptCatalog::builtins_only().unwrap();
assert!(catalog.compact_system().unwrap().contains("write_summary"));
assert!( assert!(
catalog catalog
.memory_extract_system("Japanese") .memory_extract_system("LANGUAGE_MARKER")
.unwrap() .unwrap()
.contains("`language`: `Japanese`") .contains("LANGUAGE_MARKER")
); );
assert!( assert!(
catalog catalog
.notify_wrapper("changed") .notify_wrapper("NOTIFICATION_MARKER")
.unwrap() .unwrap()
.contains("changed") .contains("NOTIFICATION_MARKER")
); );
assert!( assert!(
catalog catalog
.working_boundaries_section("Readable: /a") .working_boundaries_section("BOUNDARY_MARKER")
.unwrap() .unwrap()
.contains("Readable: /a") .contains("BOUNDARY_MARKER")
);
assert!(
catalog
.worker_orchestration_guidance_section()
.unwrap()
.contains("## SubWorker orchestration")
); );
catalog.worker_orchestration_guidance_section().unwrap();
} }
} }
-90
View File
@@ -15,8 +15,6 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::BTreeMap; use std::collections::BTreeMap;
#[cfg(test)]
use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
use chrono::{DateTime, SecondsFormat, Utc}; use chrono::{DateTime, SecondsFormat, Utc};
@@ -26,8 +24,6 @@ use thiserror::Error;
use crate::feature::{FeatureInstructionDeclaration, dedupe_instruction_contributions}; use crate::feature::{FeatureInstructionDeclaration, dedupe_instruction_contributions};
use crate::prompt::catalog::{CatalogError, PromptCatalog}; use crate::prompt::catalog::{CatalogError, PromptCatalog};
#[cfg(test)]
use crate::prompt::catalog::{EffectivePromptCatalog, builtin_prompt_templates};
use crate::prompt::source::PromptCatalogSource; use crate::prompt::source::PromptCatalogSource;
#[derive(Debug, Error)] #[derive(Debug, Error)]
@@ -319,76 +315,6 @@ fn append_trailing_section(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use chrono::TimeZone;
use manifest::{Permission, ScopeConfig, ScopeRule};
use tempfile::TempDir;
fn fixed_now() -> DateTime<Utc> {
Utc.with_ymd_and_hms(2026, 4, 15, 9, 30, 0).unwrap()
}
fn build_scope(dir: &Path) -> Scope {
Scope::from_config(&ScopeConfig {
allow: vec![ScopeRule {
target: dir.to_path_buf(),
permission: Permission::Write,
recursive: true,
}],
deny: Vec::new(),
})
.unwrap()
}
fn context<'a>(
cwd: &'a Path,
scope: &'a Scope,
prompts: &'a PromptCatalog,
) -> SystemPromptContext<'a> {
SystemPromptContext {
now: fixed_now(),
cwd: cwd.to_string_lossy(),
tool_names: vec!["Read".into(), "Write".into()],
scope,
agents_md: Some("PROJECT RULES".into()),
resident_summary: Some("DURABLE MEMORY"),
language: "Japanese",
feature_instructions: &[],
prompts,
}
}
#[test]
fn exact_catalog_name_renders_once_with_trailing_sections() {
let tmp = TempDir::new().unwrap();
let scope = build_scope(tmp.path());
let prompts = PromptCatalog::builtins_only().unwrap();
let template =
SystemPromptTemplate::parse("default", PromptCatalogSource::builtins_only()).unwrap();
let rendered = template
.render(&context(tmp.path(), &scope, &prompts))
.unwrap();
assert!(rendered.contains("2026-08-14") || rendered.contains("2026-04-15"));
assert!(rendered.contains("## Working boundaries"));
assert!(rendered.contains("PROJECT RULES"));
assert!(rendered.contains("DURABLE MEMORY"));
}
#[test]
fn workspace_override_is_visible_through_builtin_static_include() {
let mut templates = builtin_prompt_templates().unwrap();
templates.insert("common.workspace".into(), "WORKSPACE OVERRIDE".into());
let projection = EffectivePromptCatalog::new(templates, 9, "schema", "toolchain").unwrap();
let loader =
PromptCatalogSource::builtins_only().with_effective_catalog(projection.clone());
let prompts = PromptCatalog::from_projection(projection).unwrap();
let template = SystemPromptTemplate::parse("default", loader).unwrap();
let tmp = TempDir::new().unwrap();
let scope = build_scope(tmp.path());
let rendered = template
.render(&context(tmp.path(), &scope, &prompts))
.unwrap();
assert!(rendered.contains("WORKSPACE OVERRIDE"));
}
#[test] #[test]
fn rejects_legacy_prefix_relative_and_missing_names() { fn rejects_legacy_prefix_relative_and_missing_names() {
@@ -399,20 +325,4 @@ mod tests {
); );
} }
} }
#[test]
fn role_templates_are_selected_without_filesystem_resolution() {
let loader = PromptCatalogSource::builtins_only();
for role in [
"role.coder",
"role.intake",
"role.orchestrator",
"role.reviewer",
] {
assert!(
SystemPromptTemplate::parse(role, loader.clone()).is_ok(),
"{role}"
);
}
}
} }
+1 -6
View File
@@ -6955,7 +6955,6 @@ mod build_summary_prompt_tests {
) )
.await; .await;
assert!(rendered.contains("## Resident memory summary"));
assert!(rendered.contains("summary body for resident prompt")); assert!(rendered.contains("summary body for resident prompt"));
assert!(!rendered.contains("updated_at: 2026-01-01T00:00:00Z")); assert!(!rendered.contains("updated_at: 2026-01-01T00:00:00Z"));
assert!(!rendered.contains("---\nupdated_at")); assert!(!rendered.contains("---\nupdated_at"));
@@ -6974,7 +6973,6 @@ mod build_summary_prompt_tests {
) )
.await; .await;
assert!(!rendered.contains("Resident memory summary"));
assert!(!rendered.contains("disabled summary body")); assert!(!rendered.contains("disabled summary body"));
} }
@@ -6987,7 +6985,6 @@ mod build_summary_prompt_tests {
) )
.await; .await;
assert!(!rendered.contains("Resident memory summary"));
assert!(!rendered.contains("memory-disabled summary body")); assert!(!rendered.contains("memory-disabled summary body"));
} }
@@ -7000,8 +6997,7 @@ mod build_summary_prompt_tests {
) )
.await; .await;
assert!(rendered.contains("## Working boundaries")); assert!(!rendered.trim().is_empty());
assert!(!rendered.contains("Resident memory summary"));
assert!(!rendered.contains("bad summary body")); assert!(!rendered.contains("bad summary body"));
} }
@@ -7015,7 +7011,6 @@ mod build_summary_prompt_tests {
) )
.await; .await;
assert!(!prompt.contains("Resident memory summary"));
assert!(!prompt.contains("resident summary marker")); assert!(!prompt.contains("resident summary marker"));
} }
@@ -176,12 +176,9 @@ async fn template_is_not_materialised_before_first_run() {
#[tokio::test] #[tokio::test]
async fn materialise_on_first_turn_populates_worker() { async fn materialise_on_first_turn_populates_worker() {
let client = MockClient::new(vec![single_text_events("ok")]); let client = MockClient::new(vec![single_text_events("ok")]);
let (mut worker, pwd) = make_worker_with_body( let (mut worker, pwd) = make_worker_with_body("date={{ date }}", client)
"date={{ date }} cwd={{ cwd }} tools={{ tools | join(',') }}", .await
client, .unwrap();
)
.await
.unwrap();
worker.run_text("hi").await.unwrap(); worker.run_text("hi").await.unwrap();
let rendered = worker let rendered = worker
.engine() .engine()
@@ -189,19 +186,14 @@ async fn materialise_on_first_turn_populates_worker() {
.expect("system prompt materialised") .expect("system prompt materialised")
.to_string(); .to_string();
assert!(rendered.contains("date=")); assert!(rendered.contains("date="));
assert!(rendered.contains("cwd="));
assert!(rendered.contains(&pwd.display().to_string())); assert!(rendered.contains(&pwd.display().to_string()));
assert!(rendered.starts_with("date=")); assert!(rendered.starts_with("date="));
// Trailing fixed section must be appended.
assert!(rendered.contains("## Working boundaries"));
} }
#[tokio::test] #[tokio::test]
async fn session_start_state_captures_rendered_prompt() { async fn session_start_state_captures_rendered_prompt() {
let client = MockClient::new(vec![single_text_events("ok")]); let client = MockClient::new(vec![single_text_events("ok")]);
let (mut worker, pwd) = make_worker_with_body("hello cwd={{ cwd }}", client) let (mut worker, pwd) = make_worker_with_body("hello", client).await.unwrap();
.await
.unwrap();
worker.run_text("hi").await.unwrap(); worker.run_text("hi").await.unwrap();
let entries = worker let entries = worker
@@ -212,9 +204,8 @@ async fn session_start_state_captures_rendered_prompt() {
match first { match first {
LogEntry::SegmentStart { system_prompt, .. } => { LogEntry::SegmentStart { system_prompt, .. } => {
let sp = system_prompt.as_deref().expect("system prompt set"); let sp = system_prompt.as_deref().expect("system prompt set");
assert!(sp.starts_with("hello cwd=")); assert!(sp.starts_with("hello"));
assert!(sp.contains(&pwd.display().to_string())); assert!(sp.contains(&pwd.display().to_string()));
assert!(sp.contains("## Working boundaries"));
} }
other => panic!("expected SegmentStart as first entry, got {other:?}"), other => panic!("expected SegmentStart as first entry, got {other:?}"),
} }
@@ -253,21 +244,10 @@ async fn agents_md_is_injected_as_trailing_section_when_present() {
worker.run_text("hi").await.unwrap(); worker.run_text("hi").await.unwrap();
let rendered = worker.engine().get_system_prompt().unwrap().to_string(); let rendered = worker.engine().get_system_prompt().unwrap().to_string();
assert!(rendered.starts_with("BODY")); assert!(rendered.starts_with("BODY"));
assert!(rendered.contains("## Project instructions (AGENTS.md)"));
assert!(rendered.contains("# project rules")); assert!(rendered.contains("# project rules"));
assert!(rendered.contains("be kind")); assert!(rendered.contains("be kind"));
} }
#[tokio::test]
async fn agents_md_absent_omits_trailing_section() {
let client = MockClient::new(vec![single_text_events("ok")]);
let (mut worker, _pwd) = make_worker_with_body("BODY", client).await.unwrap();
worker.run_text("hi").await.unwrap();
let rendered = worker.engine().get_system_prompt().unwrap().to_string();
assert!(!rendered.contains("## Project instructions"));
assert!(!rendered.contains("AGENTS.md"));
}
#[tokio::test] #[tokio::test]
async fn agents_md_not_reread_after_compact() { async fn agents_md_not_reread_after_compact() {
let client = MockClient::new(vec![ let client = MockClient::new(vec![
+6 -79
View File
@@ -4217,13 +4217,12 @@ mod tests {
} }
#[test] #[test]
fn embedded_orchestrator_profile_enables_workdir_and_worker_authority() { fn embedded_builtin_decodal_profiles_resolve_through_archive() {
let root = tempfile::tempdir().unwrap(); let root = tempfile::tempdir().unwrap();
let broker = BackendResourceBroker::default(); let broker = BackendResourceBroker::default();
let runtime_id = "runtime-test"; let runtime_id = "runtime-test";
let selector = ProfileSelector::Builtin("builtin:orchestrator".to_string());
let bundle = builtin_profile_config_bundle( let bundle = builtin_profile_config_bundle(
&selector, &ProfileSelector::Builtin("builtin:companion".to_string()),
"workspace-test", "workspace-test",
Some(runtime_id), Some(runtime_id),
&broker, &broker,
@@ -4231,6 +4230,7 @@ mod tests {
) )
.unwrap(); .unwrap();
let handle = bundle.profile_source_archive_handle.as_ref().unwrap(); let handle = bundle.profile_source_archive_handle.as_ref().unwrap();
assert!(bundle.profile_source_archive.is_none());
let response = broker let response = broker
.fetch_profile_source_archive(worker_runtime::resource::BackendResourceFetchRequest { .fetch_profile_source_archive(worker_runtime::resource::BackendResourceFetchRequest {
handle: handle.clone(), handle: handle.clone(),
@@ -4244,85 +4244,12 @@ mod tests {
.unwrap() .unwrap()
.verify() .verify()
.unwrap(); .unwrap();
let manifest = archive assert!(!archive.reference().source_graph.entrypoints.is_empty());
.resolve_profile("builtin:orchestrator", root.path(), "embedded-orchestrator") for selector_key in archive.reference().source_graph.entrypoints.keys() {
.unwrap();
assert!(manifest.feature.manage_workdir.enabled);
assert!(!manifest.feature.sub_worker.enabled);
assert!(manifest.feature.worker.enabled);
}
#[test]
fn embedded_companion_profile_enables_worker_management() {
let root = tempfile::tempdir().unwrap();
let selector = ProfileSelector::Builtin("builtin:companion".to_string());
let archive = builtin_profile_source_archive(&selector)
.unwrap()
.verify()
.unwrap();
let manifest = archive
.resolve_profile("builtin:companion", root.path(), "companion-test-worker")
.unwrap();
assert!(manifest.feature.worker.enabled);
assert!(manifest.feature.sub_worker.enabled);
assert!(!manifest.feature.manage_workdir.enabled);
}
#[test]
fn embedded_builtin_decodal_profiles_resolve_through_archive() {
let root = tempfile::tempdir().unwrap();
let broker = BackendResourceBroker::default();
let runtime_id = "runtime-test";
for selector in [
ProfileSelector::Builtin("builtin:companion".to_string()),
ProfileSelector::Builtin("builtin:intake".to_string()),
ProfileSelector::Builtin("builtin:orchestrator".to_string()),
ProfileSelector::Builtin("builtin:coder".to_string()),
ProfileSelector::Builtin("builtin:reviewer".to_string()),
ProfileSelector::Builtin("builtin:memory-consolidation".to_string()),
] {
let bundle = builtin_profile_config_bundle(
&selector,
"workspace-test",
Some(runtime_id),
&broker,
ProfileSourceArchiveTransport::BackendResourceHandle,
)
.unwrap();
let handle = bundle.profile_source_archive_handle.as_ref().unwrap();
assert!(bundle.profile_source_archive.is_none());
let response = broker
.fetch_profile_source_archive(
worker_runtime::resource::BackendResourceFetchRequest {
handle: handle.clone(),
runtime_id: runtime_id.to_string(),
worker_id: None,
audit_correlation_id: handle.audit_correlation_id.clone(),
},
)
.unwrap();
let archive =
worker_runtime::resource::profile_source_archive_from_response(handle, response)
.unwrap()
.verify()
.unwrap();
let selector_key = match &selector {
ProfileSelector::Builtin(name) | ProfileSelector::Named(name) => name.clone(),
};
let manifest = archive let manifest = archive
.resolve_profile(&selector_key, root.path(), "embedded-test-worker") .resolve_profile(selector_key, root.path(), "embedded-test-worker")
.unwrap(); .unwrap();
assert_eq!(manifest.worker.name, "embedded-test-worker"); assert_eq!(manifest.worker.name, "embedded-test-worker");
assert_eq!(
manifest.model.ref_.as_deref(),
Some("codex-oauth/gpt-5.6-sol")
);
if selector_key == "builtin:memory-consolidation" {
assert!(manifest.feature.memory.enabled);
assert!(manifest.feature.memory.staging);
}
} }
} }
@@ -740,32 +740,6 @@ mod tests {
} }
} }
#[test]
fn virtual_config_projection_is_builtin_only_by_default() {
let state = virtual_state(vec![
config_source::ConfigEntry::new(
VirtualPath::parse("main.dcdl").unwrap(),
ConfigContentType::Decodal,
"{}",
)
.unwrap(),
]);
let projection = project_profiles_from_workspace_config("workspace-test", &state).unwrap();
assert_eq!(
projection.settings.default_profile.as_deref(),
Some("builtin:companion")
);
assert_eq!(projection.settings.config_revision, Some(7));
assert!(projection.settings.projection_digest.is_some());
assert!(
projection
.settings
.profiles
.iter()
.all(|item| !item.editable)
);
}
#[test] #[test]
fn virtual_config_projection_builds_archive_from_active_revision() { fn virtual_config_projection_builds_archive_from_active_revision() {
let state = virtual_state(vec![ let state = virtual_state(vec![
@@ -795,8 +769,7 @@ mod tests {
assert_eq!(projection.settings.config_revision, Some(7)); assert_eq!(projection.settings.config_revision, Some(7));
let prompt_catalog = bundle.prompt_catalog.as_ref().unwrap(); let prompt_catalog = bundle.prompt_catalog.as_ref().unwrap();
assert_eq!(prompt_catalog.config_revision, 7); assert_eq!(prompt_catalog.config_revision, 7);
assert!(prompt_catalog.templates.contains_key("default")); assert!(!prompt_catalog.templates.is_empty());
assert!(prompt_catalog.templates.contains_key("common.workspace"));
assert!( assert!(
bundle bundle
.metadata .metadata
@@ -115,12 +115,16 @@ mod tests {
#[test] #[test]
fn workspace_override_deep_patches_builtin_and_preserves_other_leaves() { fn workspace_override_deep_patches_builtin_and_preserves_other_leaves() {
let baseline = project_prompts_from_workspace_config(&state("{}")).unwrap();
let state = state(r#"{ prompts = { common = { language = "OVERRIDE"; }; }; }"#); let state = state(r#"{ prompts = { common = { language = "OVERRIDE"; }; }; }"#);
let catalog = project_prompts_from_workspace_config(&state).unwrap(); let catalog = project_prompts_from_workspace_config(&state).unwrap();
assert_eq!(catalog.config_revision, 7); assert_eq!(catalog.config_revision, 7);
assert_eq!(catalog.templates["common.language"], "OVERRIDE"); assert_eq!(catalog.templates["common.language"], "OVERRIDE");
assert!(!catalog.templates["common.workspace"].is_empty()); for (key, value) in baseline.templates {
assert!(catalog.templates["default"].contains("common.workspace")); if key != "common.language" {
assert_eq!(catalog.templates.get(&key), Some(&value));
}
}
} }
#[test] #[test]