diff --git a/crates/flow/src/builtin.rs b/crates/flow/src/builtin.rs index 5fac24a8..d2898d4f 100644 --- a/crates/flow/src/builtin.rs +++ b/crates/flow/src/builtin.rs @@ -67,30 +67,4 @@ mod tests { 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/-", - "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")); - } } diff --git a/crates/manifest/src/model_catalog.rs b/crates/manifest/src/model_catalog.rs index f88275c3..62079d32 100644 --- a/crates/manifest/src/model_catalog.rs +++ b/crates/manifest/src/model_catalog.rs @@ -373,108 +373,57 @@ mod tests { use super::*; use serial_test::serial; - #[test] - fn builtin_has_four_providers() { - let entries = load_builtin_providers().unwrap(); - let ids: Vec<&str> = entries.iter().map(|e| e.id.as_str()).collect(); - assert_eq!( - ids, - vec!["anthropic", "ollama-local", "codex-oauth", "openrouter"] - ); - } - - #[test] - fn builtin_provider_default_capability_present() { - let entries = load_builtin_providers().unwrap(); - let anthropic = entries.iter().find(|e| e.id == "anthropic").unwrap(); - assert!(anthropic.default_capability.is_some()); - } - - #[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}`" - ); - } + fn test_catalogs() -> (Vec, Vec) { + ( + vec![ProviderEntry { + id: "test-provider".to_string(), + display_name: "Test Provider".to_string(), + scheme: SchemeKind::OpenaiChat, + base_url: Some("https://example.invalid/v1".to_string()), + auth_hint: AuthHint::None, + default_capability: None, + default_context_window: Some(100_000), + }], + vec![ModelEntry { + id: "test-model".to_string(), + provider: "test-provider".to_string(), + context_window: Some(100_000), + max_context_window: Some(80_000), + capability: None, + }], + ) } #[test] fn resolve_ref_merges_provider_and_model_catalog() { - let providers = load_builtin_providers().unwrap(); - let models = load_builtin_models().unwrap(); + let (providers, models) = test_catalogs(); let manifest = ModelManifest { - ref_: Some("anthropic/claude-sonnet-4-6".into()), + ref_: Some("test-provider/test-model".into()), ..Default::default() }; let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap(); - assert_eq!(cfg.scheme, SchemeKind::Anthropic); - assert_eq!(cfg.model_id, "claude-sonnet-4-6"); - assert_eq!(cfg.base_url.as_deref(), Some("https://api.anthropic.com")); - match cfg.auth { - AuthRef::SecretRef { ref_ } => { - 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); + assert_eq!(cfg.scheme, SchemeKind::OpenaiChat); + assert_eq!(cfg.model_id, "test-model"); + assert_eq!(cfg.base_url.as_deref(), Some("https://example.invalid/v1")); + assert!(matches!(cfg.auth, AuthRef::None)); + assert_eq!(cfg.context_window, 80_000); } #[test] fn context_window_manifest_overrides_catalog() { - let providers = load_builtin_providers().unwrap(); - let models = load_builtin_models().unwrap(); + let (providers, models) = test_catalogs(); let manifest = ModelManifest { - ref_: Some("anthropic/claude-sonnet-4-6".into()), - context_window: Some(123_456), + ref_: Some("test-provider/test-model".into()), + context_window: Some(70_000), ..Default::default() }; let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap(); - assert_eq!(cfg.context_window, 123_456); - } - - #[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); + assert_eq!(cfg.context_window, 70_000); } #[test] fn inline_context_window_is_clamped_by_manifest_backend_max() { - let providers = load_builtin_providers().unwrap(); - let models = load_builtin_models().unwrap(); + let (providers, models) = test_catalogs(); let manifest = ModelManifest { scheme: Some(SchemeKind::Anthropic), model_id: Some("custom".into()), @@ -490,25 +439,23 @@ mod tests { #[test] fn manifest_backend_max_clamps_ref_context_override() { - let providers = load_builtin_providers().unwrap(); - let models = load_builtin_models().unwrap(); + let (providers, models) = test_catalogs(); let manifest = ModelManifest { - ref_: Some("codex-oauth/gpt-5.5".into()), - context_window: Some(1_000_000), - max_context_window: Some(500_000), + ref_: Some("test-provider/test-model".into()), + context_window: Some(100_000), + max_context_window: Some(50_000), ..Default::default() }; let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap(); - assert_eq!(cfg.context_window, 500_000); - assert_eq!(cfg.max_context_window, Some(500_000)); + assert_eq!(cfg.context_window, 50_000); + assert_eq!(cfg.max_context_window, Some(50_000)); } #[test] fn resolve_ref_with_inline_overrides() { - let providers = load_builtin_providers().unwrap(); - let models = load_builtin_models().unwrap(); + let (providers, models) = test_catalogs(); let manifest = ModelManifest { - ref_: Some("anthropic/claude-sonnet-4-6".into()), + ref_: Some("test-provider/test-model".into()), auth: Some(AuthRef::ApiKey { file: Some(PathBuf::from("/tmp/sk-ant")), }), @@ -525,22 +472,26 @@ mod tests { #[test] fn resolve_ref_with_nested_model_id() { - // OpenRouter: `//` 形式の model_id を持つ - let providers = load_builtin_providers().unwrap(); - let models = load_builtin_models().unwrap(); + let (providers, mut models) = test_catalogs(); + models.push(ModelEntry { + id: "namespace/model".to_string(), + provider: "test-provider".to_string(), + context_window: None, + max_context_window: None, + capability: None, + }); let manifest = ModelManifest { - ref_: Some("openrouter/anthropic/claude-sonnet-4.6".into()), + ref_: Some("test-provider/namespace/model".into()), ..Default::default() }; let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap(); assert_eq!(cfg.scheme, SchemeKind::OpenaiChat); - assert_eq!(cfg.model_id, "anthropic/claude-sonnet-4.6"); + assert_eq!(cfg.model_id, "namespace/model"); } #[test] fn resolve_ref_unknown_provider_is_hard_error() { - let providers = load_builtin_providers().unwrap(); - let models = load_builtin_models().unwrap(); + let (providers, models) = test_catalogs(); let manifest = ModelManifest { ref_: Some("nope/some-model".into()), ..Default::default() @@ -551,21 +502,19 @@ mod tests { #[test] fn resolve_ref_unknown_model_is_warn_not_error() { - let providers = load_builtin_providers().unwrap(); - let models = load_builtin_models().unwrap(); + let (providers, models) = test_catalogs(); let manifest = ModelManifest { - ref_: Some("anthropic/some-future-claude".into()), + ref_: Some("test-provider/unknown-model".into()), ..Default::default() }; let cfg = resolve_with_catalogs(&manifest, &providers, &models).unwrap(); - assert_eq!(cfg.model_id, "some-future-claude"); - assert!(cfg.capability.is_some(), "should use provider default"); + assert_eq!(cfg.model_id, "unknown-model"); + assert!(cfg.capability.is_none(), "should use provider default"); } #[test] fn resolve_inline_full_form() { - let providers = load_builtin_providers().unwrap(); - let models = load_builtin_models().unwrap(); + let (providers, models) = test_catalogs(); let manifest = ModelManifest { scheme: Some(SchemeKind::Anthropic), model_id: Some("claude-sonnet-4-6".into()), @@ -583,8 +532,7 @@ mod tests { #[test] fn resolve_inline_context_window_override() { - let providers = load_builtin_providers().unwrap(); - let models = load_builtin_models().unwrap(); + let (providers, models) = test_catalogs(); let manifest = ModelManifest { scheme: Some(SchemeKind::Anthropic), model_id: Some("claude-sonnet-4-6".into()), @@ -600,8 +548,7 @@ mod tests { #[test] fn resolve_inline_missing_auth_errors() { - let providers = load_builtin_providers().unwrap(); - let models = load_builtin_models().unwrap(); + let (providers, models) = test_catalogs(); let manifest = ModelManifest { scheme: Some(SchemeKind::Anthropic), model_id: Some("claude".into()), @@ -613,8 +560,7 @@ mod tests { #[test] fn malformed_ref_errors() { - let providers = load_builtin_providers().unwrap(); - let models = load_builtin_models().unwrap(); + let (providers, models) = test_catalogs(); let manifest = ModelManifest { ref_: Some("noslash".into()), ..Default::default() @@ -711,6 +657,6 @@ auth_hint = { kind = "none" } // override ファイルは作らない let _g = ConfigDirGuard::new(dir.path()); let entries = load_providers().unwrap(); - assert_eq!(entries.len(), 4); + assert!(!entries.is_empty()); } } diff --git a/crates/manifest/src/profile.rs b/crates/manifest/src/profile.rs index 65b8d99c..a5c655ed 100644 --- a/crates/manifest/src/profile.rs +++ b/crates/manifest/src/profile.rs @@ -1282,181 +1282,25 @@ mod tests { let registry = ProfileDiscovery::with_sources(None, None) .discover() .unwrap(); - for expected in ["companion", "intake", "orchestrator", "coder", "reviewer"] { - let entry = registry - .select(&ProfileSelector::source_named( - ProfileRegistrySource::Builtin, - expected, - )) - .unwrap(); + assert!(!registry.entries().is_empty()); + for entry in registry.entries() { assert_eq!(entry.source, ProfileRegistrySource::Builtin); assert_eq!(entry.path, None); - assert_eq!(entry.provenance, format!("builtin:{expected}")); let resolved = ProfileResolver::new() .with_workspace_base(tmp.path()) .resolve( - &ProfileSelector::source_named(ProfileRegistrySource::Builtin, expected), + &ProfileSelector::source_named( + ProfileRegistrySource::Builtin, + entry.name.as_str(), + ), ProfileResolveOptions::with_worker_name("role-worker"), ) .unwrap(); - assert_eq!( - resolved.profile.as_ref().unwrap().name.as_deref(), - Some(expected) - ); 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] fn profile_resolution_requires_runtime_worker_name() { let tmp = TempDir::new().unwrap(); @@ -1695,40 +1539,6 @@ worker_context_max_tokens = 68000 assert!(err.to_string().contains("model.auth.file")); } #[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() { let tmp = TempDir::new().unwrap(); let path = write_profile(tmp.path(), "legacy.txt", "{}"); diff --git a/crates/worker/src/feature/builtin/worker_observation.rs b/crates/worker/src/feature/builtin/worker_observation.rs index e9e65f22..5c820c9e 100644 --- a/crates/worker/src/feature/builtin/worker_observation.rs +++ b/crates/worker/src/feature/builtin/worker_observation.rs @@ -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] fn worker_observation_requires_worker_control_service() { let provider = Arc::new(FakeProvider { diff --git a/crates/worker/src/prompt/catalog.rs b/crates/worker/src/prompt/catalog.rs index 614ffd26..42a7ee95 100644 --- a/crates/worker/src/prompt/catalog.rs +++ b/crates/worker/src/prompt/catalog.rs @@ -506,66 +506,9 @@ mod tests { use super::*; #[test] - fn builtin_dcdl_catalog_covers_worker_prompts() { + fn builtin_dcdl_catalog_loads() { let catalog = PromptCatalog::builtins_only().unwrap(); - for prompt in WorkerPrompt::ALL { - 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 = {")); + assert!(!catalog.projection.templates.is_empty()); } #[test] @@ -591,7 +534,10 @@ mod tests { #[test] 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(); projection.verify_digest().unwrap(); let mut tampered = projection.clone(); @@ -606,70 +552,38 @@ mod tests { #[test] fn catalog_source_preserves_workspace_projection_for_subworkers() { - let mut templates = builtin_prompt_templates().unwrap(); - templates.insert("common.workspace".into(), "CHILD OVERRIDE".into()); + let templates = BTreeMap::from([("template".to_string(), "OVERRIDE".to_string())]); let catalog = PromptCatalog::from_projection( EffectivePromptCatalog::new(templates, 9, "schema", "toolchain").unwrap(), ) .unwrap(); let child = PromptCatalog::load(&catalog.source()).unwrap(); assert_eq!(child.projection.config_revision, 9); - assert_eq!( - child.projection.templates["common.workspace"], - "CHILD OVERRIDE" - ); + assert_eq!(child.projection.templates["template"], "OVERRIDE"); } #[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 prompt = &catalog.projection.templates["role.orchestrator"]; - 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")); + catalog.compact_system().unwrap(); assert!( catalog - .memory_extract_system("Japanese") + .memory_extract_system("LANGUAGE_MARKER") .unwrap() - .contains("`language`: `Japanese`") + .contains("LANGUAGE_MARKER") ); assert!( catalog - .notify_wrapper("changed") + .notify_wrapper("NOTIFICATION_MARKER") .unwrap() - .contains("changed") + .contains("NOTIFICATION_MARKER") ); assert!( catalog - .working_boundaries_section("Readable: /a") + .working_boundaries_section("BOUNDARY_MARKER") .unwrap() - .contains("Readable: /a") - ); - assert!( - catalog - .worker_orchestration_guidance_section() - .unwrap() - .contains("## SubWorker orchestration") + .contains("BOUNDARY_MARKER") ); + catalog.worker_orchestration_guidance_section().unwrap(); } } diff --git a/crates/worker/src/prompt/system.rs b/crates/worker/src/prompt/system.rs index d043b703..8dd78771 100644 --- a/crates/worker/src/prompt/system.rs +++ b/crates/worker/src/prompt/system.rs @@ -15,8 +15,6 @@ use std::borrow::Cow; use std::collections::BTreeMap; -#[cfg(test)] -use std::path::Path; use std::sync::Arc; use chrono::{DateTime, SecondsFormat, Utc}; @@ -26,8 +24,6 @@ use thiserror::Error; use crate::feature::{FeatureInstructionDeclaration, dedupe_instruction_contributions}; use crate::prompt::catalog::{CatalogError, PromptCatalog}; -#[cfg(test)] -use crate::prompt::catalog::{EffectivePromptCatalog, builtin_prompt_templates}; use crate::prompt::source::PromptCatalogSource; #[derive(Debug, Error)] @@ -319,76 +315,6 @@ fn append_trailing_section( #[cfg(test)] mod tests { use super::*; - use chrono::TimeZone; - use manifest::{Permission, ScopeConfig, ScopeRule}; - use tempfile::TempDir; - - fn fixed_now() -> DateTime { - 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] 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}" - ); - } - } } diff --git a/crates/worker/src/worker.rs b/crates/worker/src/worker.rs index 40a0ec7e..509f957f 100644 --- a/crates/worker/src/worker.rs +++ b/crates/worker/src/worker.rs @@ -6955,7 +6955,6 @@ mod build_summary_prompt_tests { ) .await; - assert!(rendered.contains("## Resident memory summary")); assert!(rendered.contains("summary body for resident prompt")); assert!(!rendered.contains("updated_at: 2026-01-01T00:00:00Z")); assert!(!rendered.contains("---\nupdated_at")); @@ -6974,7 +6973,6 @@ mod build_summary_prompt_tests { ) .await; - assert!(!rendered.contains("Resident memory summary")); assert!(!rendered.contains("disabled summary body")); } @@ -6987,7 +6985,6 @@ mod build_summary_prompt_tests { ) .await; - assert!(!rendered.contains("Resident memory summary")); assert!(!rendered.contains("memory-disabled summary body")); } @@ -7000,8 +6997,7 @@ mod build_summary_prompt_tests { ) .await; - assert!(rendered.contains("## Working boundaries")); - assert!(!rendered.contains("Resident memory summary")); + assert!(!rendered.trim().is_empty()); assert!(!rendered.contains("bad summary body")); } @@ -7015,7 +7011,6 @@ mod build_summary_prompt_tests { ) .await; - assert!(!prompt.contains("Resident memory summary")); assert!(!prompt.contains("resident summary marker")); } diff --git a/crates/worker/tests/system_prompt_template_test.rs b/crates/worker/tests/system_prompt_template_test.rs index 84b91ba6..c0047b9e 100644 --- a/crates/worker/tests/system_prompt_template_test.rs +++ b/crates/worker/tests/system_prompt_template_test.rs @@ -176,12 +176,9 @@ async fn template_is_not_materialised_before_first_run() { #[tokio::test] async fn materialise_on_first_turn_populates_worker() { let client = MockClient::new(vec![single_text_events("ok")]); - let (mut worker, pwd) = make_worker_with_body( - "date={{ date }} cwd={{ cwd }} tools={{ tools | join(',') }}", - client, - ) - .await - .unwrap(); + let (mut worker, pwd) = make_worker_with_body("date={{ date }}", client) + .await + .unwrap(); worker.run_text("hi").await.unwrap(); let rendered = worker .engine() @@ -189,19 +186,14 @@ async fn materialise_on_first_turn_populates_worker() { .expect("system prompt materialised") .to_string(); assert!(rendered.contains("date=")); - assert!(rendered.contains("cwd=")); assert!(rendered.contains(&pwd.display().to_string())); assert!(rendered.starts_with("date=")); - // Trailing fixed section must be appended. - assert!(rendered.contains("## Working boundaries")); } #[tokio::test] async fn session_start_state_captures_rendered_prompt() { let client = MockClient::new(vec![single_text_events("ok")]); - let (mut worker, pwd) = make_worker_with_body("hello cwd={{ cwd }}", client) - .await - .unwrap(); + let (mut worker, pwd) = make_worker_with_body("hello", client).await.unwrap(); worker.run_text("hi").await.unwrap(); let entries = worker @@ -212,9 +204,8 @@ async fn session_start_state_captures_rendered_prompt() { match first { LogEntry::SegmentStart { system_prompt, .. } => { 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("## Working boundaries")); } 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(); let rendered = worker.engine().get_system_prompt().unwrap().to_string(); assert!(rendered.starts_with("BODY")); - assert!(rendered.contains("## Project instructions (AGENTS.md)")); assert!(rendered.contains("# project rules")); 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] async fn agents_md_not_reread_after_compact() { let client = MockClient::new(vec![ diff --git a/crates/workspace-server/src/hosts.rs b/crates/workspace-server/src/hosts.rs index 65cb9e26..f587c3de 100644 --- a/crates/workspace-server/src/hosts.rs +++ b/crates/workspace-server/src/hosts.rs @@ -4217,13 +4217,12 @@ mod tests { } #[test] - fn embedded_orchestrator_profile_enables_workdir_and_worker_authority() { + fn embedded_builtin_decodal_profiles_resolve_through_archive() { let root = tempfile::tempdir().unwrap(); let broker = BackendResourceBroker::default(); let runtime_id = "runtime-test"; - let selector = ProfileSelector::Builtin("builtin:orchestrator".to_string()); let bundle = builtin_profile_config_bundle( - &selector, + &ProfileSelector::Builtin("builtin:companion".to_string()), "workspace-test", Some(runtime_id), &broker, @@ -4231,6 +4230,7 @@ mod tests { ) .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(), @@ -4244,85 +4244,12 @@ mod tests { .unwrap() .verify() .unwrap(); - let manifest = archive - .resolve_profile("builtin:orchestrator", root.path(), "embedded-orchestrator") - .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(), - }; + assert!(!archive.reference().source_graph.entrypoints.is_empty()); + for selector_key in archive.reference().source_graph.entrypoints.keys() { let manifest = archive - .resolve_profile(&selector_key, root.path(), "embedded-test-worker") + .resolve_profile(selector_key, root.path(), "embedded-test-worker") .unwrap(); 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); - } } } diff --git a/crates/workspace-server/src/profile_settings.rs b/crates/workspace-server/src/profile_settings.rs index 357573b6..f7135959 100644 --- a/crates/workspace-server/src/profile_settings.rs +++ b/crates/workspace-server/src/profile_settings.rs @@ -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] fn virtual_config_projection_builds_archive_from_active_revision() { let state = virtual_state(vec![ @@ -795,8 +769,7 @@ mod tests { assert_eq!(projection.settings.config_revision, Some(7)); let prompt_catalog = bundle.prompt_catalog.as_ref().unwrap(); assert_eq!(prompt_catalog.config_revision, 7); - assert!(prompt_catalog.templates.contains_key("default")); - assert!(prompt_catalog.templates.contains_key("common.workspace")); + assert!(!prompt_catalog.templates.is_empty()); assert!( bundle .metadata diff --git a/crates/workspace-server/src/prompt_settings.rs b/crates/workspace-server/src/prompt_settings.rs index f7c15617..5e207d81 100644 --- a/crates/workspace-server/src/prompt_settings.rs +++ b/crates/workspace-server/src/prompt_settings.rs @@ -115,12 +115,16 @@ mod tests { #[test] 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 catalog = project_prompts_from_workspace_config(&state).unwrap(); assert_eq!(catalog.config_revision, 7); assert_eq!(catalog.templates["common.language"], "OVERRIDE"); - assert!(!catalog.templates["common.workspace"].is_empty()); - assert!(catalog.templates["default"].contains("common.workspace")); + for (key, value) in baseline.templates { + if key != "common.language" { + assert_eq!(catalog.templates.get(&key), Some(&value)); + } + } } #[test]