"""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 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", "free_claude_code.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", "free_claude_code.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", "free_claude_code.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", "free_claude_code.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", "free_claude_code.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", "free_claude_code.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", "bearer_authorization", "optional_authentication", "free_claude_code.api.dependencies.require_proxy_auth", "authorization: bearer token", "request accepted or 401", "401 missing/invalid proxy authentication token", ("tests/api/test_auth.py",), ("test_bearer_auth_is_the_only_supported_header_shape",), ), CapabilityContract( "provider_routing", "provider_runtime", "provider_matrix", "free_claude_code.runtime.provider_manager.ProviderRuntimeManager", "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", "free_claude_code.application.routing.ModelRouter", "Claude model name and configured MODEL_* values", "provider id plus provider model name", "settings validation rejects invalid provider prefixes", ("tests/application/test_routing.py", "tests/config/test_config.py"), ("test_model_mapping_configuration_is_consistent",), ), CapabilityContract( "provider_routing", "mixed_provider_resolution", "mixed_provider_mapping", "free_claude_code.application.routing.ModelRouter", "Fable/Opus/Sonnet/Haiku/fallback model config", "distinct provider selections per request", "skip live execution when providers are not configured", ("tests/application/test_routing.py", "tests/config/test_config.py"), ("test_mixed_provider_model_mapping_when_configured",), ), CapabilityContract( "provider_routing", "provider_runtime_config", "provider_proxy_timeout_config", "free_claude_code.providers.runtime.ProviderRuntime", "provider proxy, timeout, and rate-limit settings", "provider client and generation-owned admission config", "provider construction failure", ( "tests/api/test_dependencies.py", "tests/providers/test_provider_runtime.py", "tests/providers/test_provider_admission.py", ), ), CapabilityContract( "provider_routing", "zero_cost_backends", "zero_cost_provider_access", "free_claude_code.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", "free_claude_code.core.failures.ExecutionFailure", "provider stream failures before or after the HTTP commit boundary", "protocol-specific JSON failure or terminal stream event", "ordinary request failures remain distinct from terminal execution", ( "tests/api/test_execution_failure_contract.py", "tests/api/test_ordinary_error_phases.py", "tests/core/test_failure_protocol_mapping.py", "tests/providers/test_execution_failure_boundary.py", "tests/providers/test_failure_policy.py", ), ), CapabilityContract( "streaming_conversion", "thinking_blocks", "thinking_token_support", "free_claude_code.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_route_reasoning_config_e2e", "test_provider_reasoning_tool_continuation_e2e", ), ), CapabilityContract( "streaming_conversion", "heuristic_tools", "heuristic_tool_parser", "free_claude_code.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", "free_claude_code.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", "free_claude_code.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", "free_claude_code.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", "free_claude_code.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", "free_claude_code.config.settings.Settings", "retired ENABLE_MODEL_THINKING or tier override in an FCC-owned dotenv", "owned dotenv is migrated to the typed reasoning policy", "explicit dotenv receives an actionable warning", ("tests/config/test_env_migrations.py", "tests/config/test_config.py"), ("test_removed_env_migration_e2e",), ), CapabilityContract( "provider_runtime", "rate_limit_and_disconnect", "smart_rate_limiting", "free_claude_code.providers.admission.ProviderAdmissionController", "concurrent provider requests and transient upstream/disconnect failures", "provider-specific classification, proactive throttle, coordinated retry, cleanup", "mapped provider error or smoke skip for upstream disconnect", ( "tests/providers/test_provider_admission.py", "tests/providers/test_nvidia_nim_degraded_retry.py", ), ("test_client_disconnect_mid_stream_does_not_crash_server",), ), CapabilityContract( "provider_runtime", "generation_hot_swap", "provider_hot_swap", "free_claude_code.runtime.provider_manager.ProviderRuntimeManager", "validated Admin provider config and concurrent request streams", "atomic generation publication with old-stream completion", "failed candidate or persistence leaves current generation unchanged", ( "tests/runtime/test_provider_manager.py", "tests/api/test_response_streams.py", "tests/api/test_admin.py", ), ("test_provider_hot_swap_preserves_inflight_stream_e2e",), ), CapabilityContract( "local_providers", "lmstudio_messages", "lmstudio_endpoint", "free_claude_code.providers.lmstudio.LMStudioProvider", "Anthropic Messages request and local LM Studio URL", "Anthropic SSE converted from an OpenAI Chat upstream", "typed provider failure for local upstream errors", ("tests/providers/test_lmstudio.py",), ("test_lmstudio_messages_e2e",), ), CapabilityContract( "local_providers", "llamacpp_openai_chat", "llamacpp_endpoint", "free_claude_code.providers.openai_chat.OpenAIChatProvider", "OpenAI Chat request and llama.cpp URL", "Anthropic SSE converted from OpenAI Chat chunks", "typed provider failure for local upstream errors", ("tests/providers/test_llamacpp.py",), ("test_llamacpp_models_endpoint_when_available",), ), CapabilityContract( "local_providers", "ollama_openai_chat", "ollama_endpoint", "free_claude_code.providers.openai_chat.OpenAIChatProvider", "OpenAI Chat request and local Ollama root URL", "Anthropic SSE converted from OpenAI Chat chunks", "typed provider failure for local upstream errors", ("tests/providers/test_ollama.py",), ("test_ollama_models_endpoint_when_available",), ), CapabilityContract( "openrouter", "openai_chat_provider", "provider_matrix", "free_claude_code.providers.open_router.OpenRouterProvider", "OpenAI Chat request for OpenRouter", "OpenAI stream mapped to Anthropic SSE", "Anthropic SSE error shape", ( "tests/providers/test_open_router.py", "tests/providers/test_openai_compat_5xx_retry.py", ), ("test_configured_provider_models_stream_successfully",), ), CapabilityContract( "messaging", "discord_telegram_platforms", "discord_telegram_bot", "free_claude_code.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", "tests/messaging/test_limiter.py", "tests/messaging/test_platform_outbox.py", "tests/runtime/test_application_runtime.py", ), ("test_telegram_bot_api_permissions", "test_discord_bot_api_permissions"), ), CapabilityContract( "messaging", "commands", "messaging_commands", "free_claude_code.messaging.commands", "/stop, /clear, /stats command messages", "chat-wide cleanup or literal reply-subtree deletion", "terminal status edit, no-op feedback, or best-effort platform cleanup", ( "tests/messaging/test_handler.py", "tests/messaging/test_handler_integration.py", "tests/messaging/test_tree_ownership_concurrency.py", ), ( "test_messaging_commands_stop_clear_stats_e2e", "test_reply_clear_uses_literal_platform_subtree_e2e", "test_messaging_startup_notice_is_clearable_e2e", "test_messaging_active_stop_uses_status_only_e2e", "test_messaging_queued_scoped_cancel_e2e", ), ), CapabilityContract( "messaging", "tree_threading", "tree_threading", "free_claude_code.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", "tests/messaging/test_message_tree_transitions.py", "tests/messaging/test_tree_ownership_concurrency.py", ), ( "test_tree_threading_e2e", "test_messaging_queued_scoped_cancel_e2e", "test_same_message_ids_are_isolated_by_chat_e2e", ), ), CapabilityContract( "persistence", "restart_restore", "restart_restore", "free_claude_code.messaging.session.SessionStore", "stored tree JSON", "restored scoped reply lookup", "stale pending work marked lost", ("tests/messaging/test_restart_reply_restore.py",), ), CapabilityContract( "persistence", "session_store", "session_persistence", "free_claude_code.messaging.session.SessionStore", "scoped tree data 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", "free_claude_code.messaging.voice.Transcriber", "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", "tests/messaging/test_transcription_nim.py", "tests/messaging/test_platform_voice_flow.py", ), ("test_voice_transcription_backend_when_explicitly_enabled",), ), CapabilityContract( "cli", "package_entrypoints", "package_cli_entrypoints", "free_claude_code.cli.entrypoints", "installed console scripts", "package version or uvicorn server startup", "process cleanup in finally", ("tests/cli/test_entrypoints.py", "tests/core/test_version.py"), ( "test_fcc_server_entrypoint_starts_server", "test_entrypoint_version_e2e", ), ), CapabilityContract( "cli", "claude_cli_drop_in", "claude_cli_drop_in", "free_claude_code.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_claude_cli_provider_error_e2e", "test_nvidia_nim_cli_matrix_e2e", "test_openrouter_free_cli_matrix_e2e", ), ), CapabilityContract( "cli", "codex_cli_drop_in", "drop_in_codex_replacement", "free_claude_code.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( "cli", "pi_cli_integration", "pi_cli_integration", "free_claude_code.cli.launchers.pi", "Pi CLI binary, bundled extension, and FCC child-process environment", "Anthropic Messages provider with an FCC-scoped live model catalog", "proxy preflight, missing extension, or catalog failure exits without fallback", ("tests/cli/test_entrypoints.py",), ("test_pi_cli_prompt_e2e",), ), CapabilityContract( "extensibility", "provider_platform_abcs", "extensible_provider_platform_abcs", "free_claude_code.providers.runtime and free_claude_code.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}