"""Hierarchical public capability map. This module is the architectural companion to ``smoke.features``. The feature inventory says which public features must be covered; this map records the subfeature contracts, owning module boundary, and coverage owners that protect them while the internals are refactored. """ from __future__ import annotations from dataclasses import dataclass @dataclass(frozen=True, slots=True) class CapabilityContract: capability: str subfeature: str feature_id: str owner: str inputs: str outputs: str failure: str pytest_tests: tuple[str, ...] smoke_tests: tuple[str, ...] = () CAPABILITY_CONTRACTS: tuple[CapabilityContract, ...] = ( CapabilityContract( "api_compatibility", "routes_and_probes", "anthropic_api_routes", "api.routes", "Anthropic-compatible HTTP requests", "JSON or Anthropic SSE responses", "HTTPException or Anthropic error payload", ("tests/api/test_api.py",), ("test_probe_and_models_routes", "test_stop_endpoint_reports_no_messaging"), ), CapabilityContract( "api_compatibility", "head_options_probes", "probe_routes", "api.routes", "HEAD/OPTIONS probe requests", "204 with Allow header", "auth failure when configured", ("tests/api/test_api.py::test_probe_endpoints_return_204_with_allow_headers",), ("test_probe_and_models_routes",), ), CapabilityContract( "api_compatibility", "client_request_shapes", "drop_in_claude_code_replacement", "api.handlers.messages.MessagesHandler", "Claude Code, VS Code, and JetBrains shaped requests", "compatible streaming response", "provider or validation error in Anthropic shape", ("tests/api/test_api.py", "tests/cli/test_cli.py"), ("test_vscode_and_jetbrains_shaped_requests",), ), CapabilityContract( "api_compatibility", "responses_api", "drop_in_codex_replacement", "api.handlers.responses.ResponsesHandler", "OpenAI Responses requests from Codex", "Responses SSE or JSON response", "OpenAI-shaped error or conversion error", ( "tests/api/test_openai_responses.py", "tests/core/openai_responses/test_sse.py", "tests/cli/test_entrypoints.py", "tests/cli/test_codex_model_catalog.py", ), ( "test_probe_and_models_routes", "test_provider_codex_responses_text_e2e", ), ), CapabilityContract( "api_compatibility", "client_extensions", "vscode_extension", "api.handlers.messages.MessagesHandler", "VS Code beta query/header variants", "accepted Anthropic-compatible response", "HTTP error only for auth/provider failures", (), ("test_vscode_and_jetbrains_shaped_requests",), ), CapabilityContract( "api_compatibility", "client_extensions", "intellij_extension", "api.handlers.messages.MessagesHandler", "JetBrains/ACP request variants", "accepted Anthropic-compatible response", "HTTP error only for auth/provider failures", (), ("test_vscode_and_jetbrains_shaped_requests",), ), CapabilityContract( "auth", "anthropic_headers", "optional_authentication", "api.dependencies.require_api_key", "x-api-key, authorization, anthropic-auth-token", "request accepted or 401", "401 missing/invalid API key", ("tests/api/test_auth.py",), ("test_auth_token_is_enforced_for_all_supported_header_shapes",), ), CapabilityContract( "provider_routing", "provider_runtime", "provider_matrix", "providers.runtime.ProviderRuntime", "provider id and Settings", "configured BaseProvider instance", "503 for missing credentials; invalid_request_error for unknown provider", ("tests/api/test_dependencies.py", "tests/providers/test_provider_runtime.py"), ( "test_configured_provider_models_stream_successfully", "test_provider_matrix_presence_e2e", ), ), CapabilityContract( "provider_routing", "claude_model_resolution", "per_model_mapping", "api.model_router.ModelRouter", "Claude model name and configured MODEL_* values", "provider id plus provider model name", "settings validation rejects invalid provider prefixes", ("tests/api/test_model_router.py", "tests/config/test_config.py"), ("test_model_mapping_configuration_is_consistent",), ), CapabilityContract( "provider_routing", "mixed_provider_resolution", "mixed_provider_mapping", "api.model_router.ModelRouter", "Opus/Sonnet/Haiku/fallback model config", "distinct provider selections per request", "skip live execution when providers are not configured", ("tests/api/test_model_router.py", "tests/config/test_config.py"), ("test_mixed_provider_model_mapping_when_configured",), ), CapabilityContract( "provider_routing", "provider_runtime_config", "provider_proxy_timeout_config", "providers.runtime.ProviderRuntime", "provider proxy, timeout, and rate-limit settings", "provider client and scoped limiter config", "provider construction failure", ("tests/api/test_dependencies.py", "tests/providers/test_provider_runtime.py"), ), CapabilityContract( "provider_routing", "zero_cost_backends", "zero_cost_provider_access", "providers.runtime.ProviderRuntime", "configured free/local provider", "streaming response from selected backend", "missing env or upstream unavailable skip in smoke", ("tests/api/test_dependencies.py", "tests/providers/"), ("test_configured_provider_models_stream_successfully",), ), CapabilityContract( "streaming_conversion", "anthropic_sse_lifecycle", "streaming_error_mapping", "core.anthropic.streaming.AnthropicStreamLedger", "provider stream chunks or native SSE events", "Anthropic message/content/error SSE lifecycle", "Anthropic-compatible error event", ( "tests/contracts/test_stream_contracts.py", "tests/providers/test_streaming_errors.py", ), ), CapabilityContract( "streaming_conversion", "thinking_blocks", "thinking_token_support", "core.anthropic.thinking", "reasoning_content, reasoning_details, text, native thinking", "Claude thinking blocks or suppression", "thinking hidden when disabled", ( "tests/contracts/test_stream_contracts.py", "tests/providers/test_converter.py", "tests/providers/test_deepseek.py", "tests/providers/test_nvidia_nim_request.py", "tests/providers/test_open_router.py", ), ( "test_per_model_thinking_config_e2e", "test_provider_reasoning_tool_continuation_e2e", ), ), CapabilityContract( "streaming_conversion", "heuristic_tools", "heuristic_tool_parser", "core.anthropic.tools", "textual tool-call output", "structured Anthropic tool_use blocks", "text fallback when malformed", ("tests/providers/test_parsers.py", "tests/contracts/test_stream_contracts.py"), ( "test_live_tool_use_when_configured_model_supports_tools", "test_provider_reasoning_tool_continuation_e2e", ), ), CapabilityContract( "streaming_conversion", "subagent_task_control", "subagent_control", "core.anthropic.streaming.AnthropicStreamLedger", "Task tool call arguments", "run_in_background=false", "invalid JSON flushed as safe object", ("tests/providers/test_subagent_interception.py",), ), CapabilityContract( "request_behavior", "local_optimizations", "request_optimization", "api.optimization_handlers", "Claude Code probe/title/suggestion/filepath requests", "local MessagesResponse without provider call", "falls through to provider when unmatched/disabled", ( "tests/api/test_optimization_handlers.py", "tests/api/test_routes_optimizations.py", ), ("test_optimization_fast_paths_do_not_need_provider",), ), CapabilityContract( "request_behavior", "token_counting", "count_tokens_contract", "core.anthropic.get_token_count", "messages, system blocks, tools, images, thinking, tool results", "positive input token estimate", "500 with readable detail on unexpected failure", ("tests/api/test_request_utils.py",), ("test_count_tokens_accepts_thinking_tools_and_results",), ), CapabilityContract( "config", "env_precedence", "config_env_precedence", "config.settings.Settings", "process env, user env file, repo env file, FCC_ENV_FILE", "deterministic settings values", "validation error for invalid settings", ("tests/config/test_config.py",), ), CapabilityContract( "config", "removed_env_migration", "removed_env_migration", "config.settings.Settings", "NIM_ENABLE_THINKING or ENABLE_THINKING in env or dotenv", "startup succeeds and stale keys do not change thinking defaults", "removed key ignored", ("tests/config/test_config.py",), ), CapabilityContract( "provider_runtime", "rate_limit_and_disconnect", "smart_rate_limiting", "providers.rate_limit.GlobalRateLimiter", "concurrent provider requests and 429/disconnect failures", "proactive throttle, retry, cleanup", "mapped provider error or smoke skip for upstream disconnect", ("tests/providers/test_provider_rate_limit.py",), ("test_client_disconnect_mid_stream_does_not_crash_server",), ), CapabilityContract( "local_providers", "lmstudio_native_messages", "lmstudio_endpoint", "providers.anthropic_messages.AnthropicMessagesTransport", "Anthropic request body and local LM Studio URL", "native /messages stream pass-through", "SSE error event for local upstream failure", ( "tests/providers/test_lmstudio.py", "tests/providers/test_anthropic_messages.py", ), ("test_lmstudio_models_endpoint_when_available",), ), CapabilityContract( "local_providers", "llamacpp_native_messages", "llamacpp_endpoint", "providers.anthropic_messages.AnthropicMessagesTransport", "Anthropic request body and llama.cpp URL", "native /messages stream pass-through", "SSE error event for local upstream failure", ( "tests/providers/test_llamacpp.py", "tests/providers/test_anthropic_messages.py", ), ("test_llamacpp_models_endpoint_when_available",), ), CapabilityContract( "local_providers", "ollama_native_messages", "ollama_endpoint", "providers.ollama.OllamaProvider", "Anthropic request body and local Ollama root URL", "Anthropic SSE stream through the proxy", "SSE error event for local upstream failure", ("tests/providers/test_ollama.py",), ("test_ollama_models_endpoint_when_available",), ), CapabilityContract( "openrouter", "native_anthropic_messages", "provider_matrix", "providers.open_router.OpenRouterProvider", "Anthropic Messages request for OpenRouter", "native OpenRouter Anthropic SSE", "Anthropic SSE error shape", ( "tests/providers/test_open_router.py", "tests/providers/test_anthropic_messages.py", ), ("test_configured_provider_models_stream_successfully",), ), CapabilityContract( "messaging", "discord_telegram_platforms", "discord_telegram_bot", "messaging.workflow.MessagingWorkflow", "Discord/Telegram incoming messages and API callbacks", "live progress edits and final transcript", "platform retry/fallback or user-facing error", ( "tests/messaging/test_discord_platform.py", "tests/messaging/test_telegram.py", ), ("test_telegram_bot_api_permissions", "test_discord_bot_api_permissions"), ), CapabilityContract( "messaging", "commands", "messaging_commands", "messaging.commands", "/stop, /clear, /stats command messages", "task cancellation, cleanup, or stats response", "best-effort platform cleanup", ( "tests/messaging/test_handler.py", "tests/messaging/test_handler_integration.py", ), ), CapabilityContract( "messaging", "tree_threading", "tree_threading", "messaging.trees.TreeQueueManager", "reply-based message graph", "queued branches and scoped cancellation", "node error propagation", ( "tests/messaging/test_tree_queue.py", "tests/messaging/test_tree_concurrency.py", ), ), CapabilityContract( "persistence", "restart_restore", "restart_restore", "messaging.session.SessionStore", "stored tree JSON", "restored node-to-tree mapping", "stale pending work marked lost", ("tests/messaging/test_restart_reply_restore.py",), ), CapabilityContract( "persistence", "session_store", "session_persistence", "messaging.session.SessionStore", "tree data, node mapping, and message log", "JSON persistence compatible with existing files", "best-effort flush error logging", ("tests/messaging/test_session_store_edge_cases.py",), ), CapabilityContract( "voice", "voice_transcription", "voice_notes", "messaging.voice.VoiceTranscriptionService", "Discord/Telegram audio file and voice backend settings", "transcribed prompt routed to handler", "missing optional extra or backend error shown to user", ( "tests/messaging/test_voice_handlers.py", "tests/messaging/test_transcription.py", ), ("test_voice_transcription_backend_when_explicitly_enabled",), ), CapabilityContract( "cli", "package_entrypoints", "package_cli_entrypoints", "cli.entrypoints", "installed console scripts", "config scaffold or uvicorn server startup", "process cleanup in finally", ("tests/cli/test_entrypoints.py",), ( "test_fcc_init_scaffolds_user_config", "test_free_claude_code_entrypoint_starts_server", ), ), CapabilityContract( "cli", "claude_cli_drop_in", "claude_cli_drop_in", "cli.managed.session.ManagedClaudeSession", "Claude CLI binary and proxy env", "stream-json events and session id mapping", "stderr/error event and process cleanup", ("tests/cli/test_cli.py",), ( "test_claude_cli_prompt_when_available", "test_nvidia_nim_cli_matrix_e2e", "test_openrouter_free_cli_matrix_e2e", ), ), CapabilityContract( "cli", "codex_cli_drop_in", "drop_in_codex_replacement", "cli.launchers.codex", "Codex CLI binary and fcc provider env", "Responses config, auth env, and native /model catalog injection", "proxy preflight and catalog fail-open warning", ( "tests/cli/test_codex_model_catalog.py", "tests/cli/test_entrypoints.py", ), (), ), CapabilityContract( "extensibility", "provider_platform_abcs", "extensible_provider_platform_abcs", "providers.runtime and messaging.platforms.factory", "new provider/platform implementations", "registered BaseProvider or messaging component bundle", "unknown platform returns None; unknown provider errors", ( "tests/contracts/test_feature_manifest.py", "tests/providers/test_provider_runtime.py", ), ), ) def capability_names() -> set[str]: return {contract.capability for contract in CAPABILITY_CONTRACTS} def contracted_feature_ids() -> set[str]: return {contract.feature_id for contract in CAPABILITY_CONTRACTS}