Files
SciMesh/scimesh/sdk/protocols.py
T

142 lines
3.6 KiB
Python

"""Author-facing planner, runner, reducer, and verifier protocols."""
from __future__ import annotations
from pathlib import Path
from typing import Mapping, Protocol
from .artifacts import (
ArtifactCollection,
ArtifactRef,
ArtifactSchema,
OutputManifest,
Provenance,
)
from .identity import ComponentRef
from .plans import JobRequest, TaskSpec, ValidatedJob, WorkflowPlan
from .runtime import NegotiatedWorkload
from .verification import CandidateOutputs, VerificationDecision, VerifyContext
class ArtifactCatalog(Protocol):
"""Bridge-owned, read-only access to durable input artifacts."""
def materialize(self, artifact: ArtifactRef) -> Path:
"""Return an attempt-scoped verified local copy without exposing credentials."""
...
class ArtifactSink(Protocol):
"""Agent/bridge-owned sealing boundary for scientific output files."""
def seal(
self,
path: Path,
*,
declaration: ArtifactSchema,
records: int | None = None,
dimensions: tuple[int, ...] = (),
) -> ArtifactRef:
"""Validate/upload bytes and return coordinator-owned immutable metadata."""
...
class CancellationToken(Protocol):
"""Cooperative cancellation observable by workload handlers."""
def cancelled(self) -> bool: ...
def raise_if_cancelled(self) -> None: ...
class PlanningResources(Protocol):
"""Caller-provided catalog, sink, and workspace for registry planning."""
@property
def catalog(self) -> ArtifactCatalog: ...
@property
def sink(self) -> ArtifactSink: ...
@property
def workspace(self) -> Path: ...
class PlanningContext(PlanningResources, Protocol):
"""Planner-facing resources augmented by completed negotiation."""
@property
def negotiated(self) -> NegotiatedWorkload:
"""Resolved optional fallbacks and the exact negotiated manifest."""
...
class TaskContext(Protocol):
"""Everything a runner needs: the pinned task, scoped catalog/sink,
workspace, cancellation, and provenance to stamp on outputs."""
@property
def task(self) -> TaskSpec: ...
@property
def catalog(self) -> ArtifactCatalog: ...
@property
def sink(self) -> ArtifactSink: ...
@property
def workspace(self) -> Path: ...
@property
def cancellation(self) -> CancellationToken: ...
@property
def provenance(self) -> Provenance: ...
class ReduceContext(TaskContext, Protocol):
"""TaskContext plus the keyed partial artifacts accepted for reduction."""
@property
def accepted_inputs(self) -> Mapping[str, ArtifactCollection]: ...
class Planner(Protocol):
"""Validates a job and produces a digest-pinned ``WorkflowPlan``.
``entry_point`` must match the workflow's PLAN stage when one exists.
"""
entry_point: str
def validate(self, request: JobRequest) -> ValidatedJob: ...
def plan(self, job: ValidatedJob, context: PlanningContext) -> WorkflowPlan: ...
class Runner(Protocol):
"""Executes one map (or verify) task and seals its partial output."""
def run(self, context: TaskContext) -> OutputManifest: ...
class Reducer(Protocol):
"""Merges accepted partial artifacts into the final result."""
def reduce(self, context: ReduceContext) -> OutputManifest: ...
class Verifier(Protocol):
"""Accepts or rejects candidate outputs with bounded sanitized evidence.
``identity`` must match the key under which the verifier is registered.
"""
identity: ComponentRef
def verify(
self,
context: VerifyContext,
candidates: CandidateOutputs,
) -> VerificationDecision: ...