"""Versioned immutable policy composition for one project-bound server.""" from __future__ import annotations from dataclasses import dataclass from typing import Literal from .errors import DocForgeError CapabilityMode = Literal["read", "proposal", "application", "operator"] CAPABILITY_MODES: tuple[CapabilityMode, ...] = ( "read", "proposal", "application", "operator", ) POLICY_PRECEDENCE = ( "core_safety", "explicit_binding", "no_ast_shorthand", "resource_availability", ) def capability_mode(value: str | None, *, default: CapabilityMode) -> CapabilityMode: """Validate one additive capability-mode selection.""" selected = default if value is None else value if selected not in CAPABILITY_MODES: raise DocForgeError( "invalid_capability_mode", "Capability mode is unsupported", capability_mode=selected, allowed=list(CAPABILITY_MODES), ) return selected # type: ignore[return-value] @dataclass(frozen=True) class EffectivePolicyV1: """One fully composed process policy shared by every public projection.""" capability_mode: CapabilityMode capability_source: Literal["factory_default", "explicit"] adapter_evolution: Literal["allowed", "preserve"] ast_analysis: Literal["allowed", "forbidden"] logic_indexing: Literal["full", "off"] synchronization: Literal["automatic"] integrity: Literal["validated"] manual_render: Literal["auto", "explicit", "disabled"] graph_render: Literal["disabled"] live_viewer: Literal["on-demand"] profiling: Literal["enabled", "disabled"] blocked_tools: tuple[str, ...] prohibitions: tuple[str, ...] @property def no_ast(self) -> bool: return self.ast_analysis == "forbidden" def as_dict(self) -> dict[str, object]: return { "schema_version": 1, "capability_mode": self.capability_mode, "capability_source": self.capability_source, "adapter_evolution": self.adapter_evolution, "ast_analysis": self.ast_analysis, "logic_indexing": self.logic_indexing, "synchronization": self.synchronization, "integrity": self.integrity, "manual_render": self.manual_render, "graph_render": self.graph_render, "live_viewer": self.live_viewer, "profiling": self.profiling, "blocked_tools": list(self.blocked_tools), "prohibitions": list(self.prohibitions), "precedence": list(POLICY_PRECEDENCE), } def adapter_policy(self) -> dict[str, object]: """Preserve the exact legacy adapter-policy projection.""" if not self.no_ast: return { "mode": "standard", "ast_analysis": "allowed", "logic_projection": "allowed", "incremental_extraction": "allowed", "adapter_rewrite": "not_requested", } return { "mode": "preserve-no-ast", "ast_analysis": "forbidden", "logic_projection": "forbidden", "incremental_extraction": "allowed", "adapter_rewrite": "forbidden", "blocked_tools": ["docforge_get_logic"], "instruction": ( "Preserve the existing adapter extraction strategy. Do not add Python AST, " "Tree-sitter, compiler-AST, or function-Logic extraction. Non-AST incremental " "fingerprinting and caching remain allowed." ), } def compose_effective_policy( *, selected_mode: CapabilityMode, capability_source: Literal["factory_default", "explicit"], no_ast: bool, diagnostics: bool, render_configured: bool, application_enabled: bool, ) -> EffectivePolicyV1: """Compose fixed defaults with restrictive compatibility shorthands.""" if selected_mode == "application" and not application_enabled: raise DocForgeError( "capability_unavailable", "Application capability requires a startup-bound canonical applier", capability_mode=selected_mode, required="canonical_applier", ) prohibitions = [ "arbitrary_file_access", "arbitrary_renderer_execution", "shell_execution", "git_mutation", "deployment", "publication", "project_switching", ] blocked_tools: tuple[str, ...] = () if no_ast: prohibitions.extend( ( "adapter_ast_upgrade", "tree_sitter_upgrade", "compiler_ast_upgrade", "function_logic_extraction", ) ) blocked_tools = ("docforge_get_logic",) manual_render: Literal["auto", "explicit", "disabled"] if not render_configured: manual_render = "disabled" elif application_enabled and selected_mode in {"application", "operator"}: manual_render = "auto" else: manual_render = "explicit" return EffectivePolicyV1( capability_mode=selected_mode, capability_source=capability_source, adapter_evolution="preserve" if no_ast else "allowed", ast_analysis="forbidden" if no_ast else "allowed", logic_indexing="off" if no_ast else "full", synchronization="automatic", integrity="validated", manual_render=manual_render, graph_render="disabled", live_viewer="on-demand", profiling="enabled" if diagnostics else "disabled", blocked_tools=blocked_tools, prohibitions=tuple(prohibitions), )