1
0
Fork 0
Code Issues Pull requests Projects Releases 2 Packages Wiki Activity Actions Pages
DocForge2/src/docforge/models.py

218 lines
4.9 KiB
Python
Raw Normal View History

"""Immutable generic project, node, edge, and context contracts."""
from __future__ import annotations
from collections.abc import Mapping
from dataclasses import asdict, dataclass
from pathlib import Path
from typing import Protocol, runtime_checkable
@dataclass(frozen=True)
class Limits:
max_source_bytes: int = 1_000_000
max_nodes: int = 10_000
max_query_chars: int = 500
max_results: int = 100
max_traversal_depth: int = 8
max_context_tokens: int = 32_000
max_tool_output_chars: int = 200_000
2026-07-22 02:58:51 -04:00
max_changesets: int = 1_000
max_changeset_operations: int = 100
max_changeset_bytes: int = 1_000_000
max_render_views: int = 100
max_template_bytes: int = 1_000_000
max_render_bytes: int = 1_000_000
2026-07-22 02:58:51 -04:00
@dataclass(frozen=True)
class ProposalWriter:
writer_id: str
families: tuple[str, ...]
operations: tuple[str, ...]
@dataclass(frozen=True)
class RenderView:
view_id: str
renderer: str
template_path: Path
output_path: Path
title: str
families: tuple[str, ...]
@dataclass(frozen=True)
class RenderConfig:
template_root: Path
preview_root: Path
views: tuple[RenderView, ...]
@dataclass(frozen=True)
class ContextProfile:
profile_id: str
families: tuple[str, ...]
statuses: tuple[str, ...]
required_nodes: tuple[str, ...]
token_budget: int
dependency_depth: int
@dataclass(frozen=True)
class ProjectDescriptor:
schema_version: int
project_id: str
title: str
adapter: str
root: Path
descriptor_path: Path
descriptor_hash: str
content_roots: tuple[Path, ...]
authority_files: tuple[Path, ...]
cache_root: Path
index_path: Path
2026-07-22 02:58:51 -04:00
changeset_root: Path
proposal_writers: tuple[ProposalWriter, ...]
render: RenderConfig | None
allowed_relations: tuple[str, ...]
profiles: tuple[ContextProfile, ...]
limits: Limits
@dataclass(frozen=True)
class Node:
node_id: str
title: str
family: str
authority: str
status: str
tags: tuple[str, ...]
summary: str
content: str
source_path: str
source_anchor: str | None
content_hash: str
def as_dict(self, *, include_content: bool = True) -> dict[str, object]:
result = asdict(self)
if not include_content:
result.pop("content")
return result
@dataclass(frozen=True)
class Edge:
source_id: str
relation: str
target_id: str
def as_dict(self) -> dict[str, str]:
return asdict(self)
@dataclass(frozen=True)
class LogicNode:
"""One function-scoped control-flow node kept outside the primary graph."""
logic_id: str
kind: str
label: str
source_anchor: str | None
def as_dict(self) -> dict[str, object]:
return asdict(self)
@dataclass(frozen=True)
class LogicEdge:
"""One directed control-flow transition with an explicit branch label."""
source_id: str
relation: str
target_id: str
label: str | None = None
ordinal: int = 0
def as_dict(self) -> dict[str, object]:
return asdict(self)
@dataclass(frozen=True)
class LogicProjection:
"""A lazy control-flow projection owned by one primary graph symbol."""
owner_node_id: str
source_id: str
nodes: tuple[LogicNode, ...]
edges: tuple[LogicEdge, ...]
def as_dict(self) -> dict[str, object]:
return {
"owner_node_id": self.owner_node_id,
"source_id": self.source_id,
"nodes": [node.as_dict() for node in self.nodes],
"edges": [edge.as_dict() for edge in self.edges],
}
@dataclass(frozen=True)
class ProjectSnapshot:
descriptor: ProjectDescriptor
nodes: tuple[Node, ...]
edges: tuple[Edge, ...]
source_hash: str
revision: str
@dataclass(frozen=True)
class ProjectState:
"""Cheap canonical identity used to prove a derived snapshot is current."""
source_hash: str
revision: str
class ProjectService(Protocol):
"""Minimum immutable project boundary required by derived read services."""
descriptor: ProjectDescriptor
def load(self) -> ProjectSnapshot: ...
def canonical_source_paths(self) -> tuple[Path, ...]: ...
def validate_proposal(
self,
base: ProjectSnapshot,
projected: ProjectSnapshot,
operations: tuple[Mapping[str, object], ...],
) -> None: ...
@runtime_checkable
class BuildReportingProject(ProjectService, Protocol):
"""Optional project boundary exposing extraction metrics for builds."""
def build_report(self) -> dict[str, object]: ...
@runtime_checkable
class IncrementalStateProject(ProjectService, Protocol):
"""Optional project boundary for manifest-only stale-state checks."""
def incremental_state(self) -> ProjectState | None: ...
@dataclass(frozen=True)
class ContextEntry:
node_id: str
reason: str
estimated_tokens: int
source_path: str
content_hash: str
text: str
def as_dict(self) -> dict[str, object]:
return asdict(self)