Add versioned effective policy
This commit is contained in:
parent
a9a75c5c27
commit
34cd5f74c1
11 changed files with 708 additions and 70 deletions
166
src/docforge/policy.py
Normal file
166
src/docforge/policy.py
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
"""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),
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue