39 lines
1.4 KiB
Python
39 lines
1.4 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Any, Dict
|
|
|
|
from .dsl import LocalProblem, PlanDelta
|
|
from .safety import verify_plan
|
|
|
|
|
|
@dataclass
|
|
class PlanResult:
|
|
"""Outcome from planning, including a safe delta and a proof flag."""
|
|
|
|
plan_delta: PlanDelta
|
|
proof_valid: bool
|
|
justification: str
|
|
|
|
|
|
class ShadowPlanner:
|
|
"""A lightweight shadow planner that runs in parallel to the executor.
|
|
|
|
For this MVP, it generates a conservative delta by slightly increasing
|
|
resource buffers to create a safe alternative plan if the primary plan is
|
|
infeasible with respect to LocalProblem.risk_budget.
|
|
"""
|
|
|
|
def __init__(self, local_problem: LocalProblem):
|
|
self.local_problem = local_problem
|
|
|
|
def plan(self, primary_delta: PlanDelta) -> PlanResult:
|
|
# Very simple heuristic: if risk_budget is low, persevere using a safer delta.
|
|
risk = float(self.local_problem.risk_budget or 0.0)
|
|
safe_delta = PlanDelta(delta={"safe_buffer": max(0.0, risk * 0.5)}, version=primary_delta.version + 1, metadata={"owner": "shadow"})
|
|
|
|
# Verify safety using the same (mocked) verify_plan hook
|
|
is_safe = verify_plan(self.local_problem, safe_delta)
|
|
justification = "Shadow plan generated" if is_safe else "Shadow plan could not be validated safely"
|
|
return PlanResult(plan_delta=safe_delta, proof_valid=is_safe, justification=justification)
|