//! Reference profile **catalogue** — the pre-filled, *editable* profiles offered //! by the first-run wizard (CONTEXT §9, ARCHITECTURE §6 `ConfigureProfiles`). //! //! These are **data, not domain code**: the catalogue lives in the application //! layer (a product decision about *which* AIs to suggest), built from the //! domain's validating constructors. Nothing is imposed — the user picks, edits //! the pre-filled commands, and may add custom profiles. The single //! [`domain::ports::AgentRuntime`] adapter consumes whatever profiles result. //! //! Reference set (CONTEXT §9): //! - **Claude Code** — `claude`, context via `CLAUDE.md` (convention file), //! - **OpenAI Codex CLI** — `codex`, context via `AGENTS.md`, //! - **Gemini CLI** — `gemini`, context via `GEMINI.md`, //! - **Aider** — `aider`, context passed as an argument (`--message-file {path}`). //! //! The ids are **stable, deterministic UUIDs** (derived from a fixed namespace) //! so re-deriving the catalogue yields the same id for "claude" every time, //! making the reference profiles addressable across runs without a registry. use domain::ids::ProfileId; use domain::profile::{AgentProfile, ContextInjection, StructuredAdapter}; /// A fixed UUID namespace used to derive stable ids for reference profiles. /// (Random-looking but constant; only its stability matters.) const REFERENCE_NAMESPACE: uuid::Uuid = uuid::uuid!("6f9b1d2a-7c34-4e58-9a1b-2c3d4e5f6a7b"); /// Derives a stable [`ProfileId`] for a reference profile from its slug. #[must_use] fn reference_id(slug: &str) -> ProfileId { ProfileId::from_uuid(uuid::Uuid::new_v5(&REFERENCE_NAMESPACE, slug.as_bytes())) } /// Returns the stable id a reference profile slug maps to (exposed for tests and /// callers that need to address a reference profile). #[must_use] pub fn reference_profile_id(slug: &str) -> ProfileId { reference_id(slug) } /// Builds the pre-filled, editable reference profiles (CONTEXT §9). /// /// # Panics /// Never in practice: every literal here satisfies the domain invariants, so the /// constructors cannot fail; the `expect`s document that. #[must_use] pub fn reference_profiles() -> Vec { vec![ AgentProfile::new( reference_id("claude"), "Claude Code", "claude", Vec::new(), ContextInjection::convention_file("CLAUDE.md") .expect("CLAUDE.md is a valid convention target"), Some("claude --version".to_owned()), "{agentRunDir}", None, ) .expect("claude reference profile is valid") .with_structured_adapter(StructuredAdapter::Claude), AgentProfile::new( reference_id("codex"), "OpenAI Codex CLI", "codex", Vec::new(), ContextInjection::convention_file("AGENTS.md") .expect("AGENTS.md is a valid convention target"), Some("codex --version".to_owned()), "{agentRunDir}", None, ) .expect("codex reference profile is valid") .with_structured_adapter(StructuredAdapter::Codex), AgentProfile::new( reference_id("gemini"), "Gemini CLI", "gemini", Vec::new(), ContextInjection::convention_file("GEMINI.md") .expect("GEMINI.md is a valid convention target"), Some("gemini --version".to_owned()), "{agentRunDir}", None, ) .expect("gemini reference profile is valid"), AgentProfile::new( reference_id("aider"), "Aider", "aider", Vec::new(), ContextInjection::flag("--message-file {path}") .expect("aider flag template is non-empty"), Some("aider --version".to_owned()), "{agentRunDir}", None, ) .expect("aider reference profile is valid"), ] }