From a443cdc79700c0c5e02c1b98f782c9297a2ca7c0 Mon Sep 17 00:00:00 2001 From: agent-dd492b85242a98c5 Date: Tue, 21 Apr 2026 11:02:55 +0200 Subject: [PATCH] build(agent): new-agents-3#dd492b iteration --- .gitignore | 21 ++++++++++++++++ AGENTS.md | 29 ++++++++++++++++++++++ README.md | 22 +++++++++++++++-- conftest.py | 7 ++++++ missionledger/__init__.py | 23 +++++++++++++++++ missionledger/dsl.py | 49 +++++++++++++++++++++++++++++++++++++ missionledger/governance.py | 38 ++++++++++++++++++++++++++++ missionledger/planner.py | 38 ++++++++++++++++++++++++++++ missionledger/safety.py | 24 ++++++++++++++++++ pyproject.toml | 15 ++++++++++++ sitecustomize.py | 20 +++++++++++++++ test.sh | 9 +++++++ tests/test_basic.py | 40 ++++++++++++++++++++++++++++++ 13 files changed, 333 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 AGENTS.md create mode 100644 conftest.py create mode 100644 missionledger/__init__.py create mode 100644 missionledger/dsl.py create mode 100644 missionledger/governance.py create mode 100644 missionledger/planner.py create mode 100644 missionledger/safety.py create mode 100644 pyproject.toml create mode 100644 sitecustomize.py create mode 100644 test.sh create mode 100644 tests/test_basic.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd5590b --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +node_modules/ +.npmrc +.env +.env.* +__tests__/ +coverage/ +.nyc_output/ +dist/ +build/ +.cache/ +*.log +.DS_Store +tmp/ +.tmp/ +__pycache__/ +*.pyc +.venv/ +venv/ +*.egg-info/ +.pytest_cache/ +READY_TO_PUBLISH diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..a8d86a0 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,29 @@ +# MissionLedger Agents Guide + +Overview +- MissionLedger is a production-grade core for verifiable, contract-driven planning in intermittently-connected fleets. +- This repo contains a minimal but production-oriented MVP to bootstrap the ecosystem: a DSL for per-asset LocalProblems, safety contracts, a shadow planner, a lightweight safety verifier, and a governanced ledger. + +Architecture (high level) +- missionledger.dsl: Defines the LocalProblem, SafetyContracts, PrivacyContracts, and PlanDelta data models. +- missionledger.planner: ShadowPlanner that proposes a safe alternative plan in parallel to the executor. +- missionledger.safety: Lightweight safety verifier used by both the main planner and shadow planner. +- missionledger.governance: Tamper-evident governance ledger with hash chaining for auditability. +- missionledger.adapter (placeholder): SDK adapters for various assets and runtime stacks (rover, drone, habitat, orbiters). + +Tech stack (current MVP) +- Python 3.8+ with a small, typed core using dataclasses. +- No external runtime dependencies for MVP; easy to extend with real solvers later. + +Development commands +- Run tests: bash test.sh +- Build the package: python3 -m build +- Lint/type checks: not included in MVP yet; plan to add flake8/ruff and mypy in future iterations. + +Tests and verification +- The test suite exercises the LocalProblem DSL, the ShadowPlanner, the safety verifier, and the governance ledger entries. +- Extend tests to cover full end-to-end delta-sync, proofs, and HIL adapters in later phases. + +Contribution guidelines +- Follow the architecture layout described above. +- Add tests for any new feature and ensure tests pass locally before proposing PRs. diff --git a/README.md b/README.md index 83953a8..2957362 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,21 @@ -# idea19-missionledger-verifiable-contract +# MissionLedger: Verifiable, Contract-Driven AI Mission Planner (MVP) -Source logic for Idea #19 \ No newline at end of file +MissionLedger provides a minimal, production-ready core for contract-driven planning on intermittently-connected fleets. This MVP focuses on a clean, testable Python implementation of the DSL, a shadow planner, a lightweight safety verifier, and a tamper-evident governance ledger. + +What’s included in this MVP +- LocalProblem DSL: per-asset objectives, variables, constraints, and risk budgets. +- SafetyContracts and PrivacyContracts scaffolding for future integration with verifiable proofs and privacy controls. +- ShadowPlanner: a simple, parallel planning agent that generates a safe delta alongside the primary plan. +- Lightweight safety verifier: deterministic checks for plan validity in the MVP. +- GovernanceLedger: append-only, tamper-evident log with hash chaining for auditability. +- A minimal tests suite to verify the core components. + +Getting started +- Install dependencies and run tests via the provided test script. +- Build the package with the standard Python tooling. + +Package metadata +- Package name: idea19_missionledger_verifiable_contract (Python project) +- Version: 0.1.0 + +This repository is intentionally minimal but designed to evolve into a full production-ready platform. diff --git a/conftest.py b/conftest.py new file mode 100644 index 0000000..f5a543b --- /dev/null +++ b/conftest.py @@ -0,0 +1,7 @@ +import sys +import os + +# Ensure the repository root is on sys.path for test discovery/imports +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__))) +if ROOT not in map(os.path.abspath, sys.path): + sys.path.insert(0, ROOT) diff --git a/missionledger/__init__.py b/missionledger/__init__.py new file mode 100644 index 0000000..c6a5337 --- /dev/null +++ b/missionledger/__init__.py @@ -0,0 +1,23 @@ +"""MissionLedger: Verifiable, Contract-Driven AI Mission Planner (Core) + +This package provides a tiny, production-ready core to bootstrap the +MissionLedger MVP. It includes a lightweight DSL for per-asset LocalProblems +and Safety/Privacy contracts, a shadow planner, a simple on-device safety proof +hook, and a tamper-evident governance ledger. +""" + +from .dsl import LocalProblem, SafetyContracts, PrivacyContracts, PlanDelta +from .planner import ShadowPlanner, PlanResult +from .safety import verify_plan +from .governance import GovernanceLedger + +__all__ = [ + "LocalProblem", + "SafetyContracts", + "PrivacyContracts", + "PlanDelta", + "ShadowPlanner", + "PlanResult", + "verify_plan", + "GovernanceLedger", +] diff --git a/missionledger/dsl.py b/missionledger/dsl.py new file mode 100644 index 0000000..ad0debb --- /dev/null +++ b/missionledger/dsl.py @@ -0,0 +1,49 @@ +from __future__ import annotations + +from dataclasses import dataclass, field +from typing import Any, Dict, List + + +@dataclass +class LocalProblem: + """Per-asset planning objective and constraints. + + - assets: mapping from asset_id to asset-specific objectives. + - variables: free-form variables used by the planner (e.g., timing, routing). + - constraints: list of simple constraint descriptors. + - risk_budget: a rough budget to limit risk (abstracted for this MVP). + """ + + asset_objectives: Dict[str, Dict[str, Any]] = field(default_factory=dict) + variables: Dict[str, Any] = field(default_factory=dict) + constraints: List[str] = field(default_factory=list) + risk_budget: float = 0.0 + + +@dataclass +class SafetyContracts: + """Pre/post conditions and risk terms for safety proofs.""" + + pre_conditions: List[str] = field(default_factory=list) + post_conditions: List[str] = field(default_factory=list) + safety_budget: float = 0.0 + collision_envelope: float = 0.0 + cost_of_violation: float = 0.0 + + +@dataclass +class PrivacyContracts: + """Minimal data-exposure policies for privacy.""" + + allowed_publishers: List[str] = field(default_factory=list) + aggregate_signals: bool = True + per_message_privacy_budget: float = 0.0 + + +@dataclass +class PlanDelta: + """Compact representation of plan changes with metadata for auditability.""" + + delta: Dict[str, Any] = field(default_factory=dict) + version: int = 0 + metadata: Dict[str, Any] = field(default_factory=dict) diff --git a/missionledger/governance.py b/missionledger/governance.py new file mode 100644 index 0000000..6513ee1 --- /dev/null +++ b/missionledger/governance.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +import hashlib +import json +from datetime import datetime +from typing import List + + +class GovernanceLedger: + """A simple tamper-evident governance ledger with per-entry hashes. + + Logs are append-only and anchored via a rolling hash to the previous entry, + producing a chain of custody suitable for auditing even on intermittent + connectivity. + """ + + def __init__(self, device_id: str = "unknown"): + self.device_id = device_id + self._entries: List[dict] = [] + self._head_hash = "" + + def log(self, entry: dict) -> None: + timestamp = datetime.utcnow().isoformat() + "Z" + payload = { + "device_id": self.device_id, + "timestamp": timestamp, + "entry": entry, + "parent": self._head_hash, + } + self._head_hash = hashlib.sha256(json.dumps(payload, sort_keys=True).encode()).hexdigest() + self._entries.append(payload) + + @property + def entries(self) -> List[dict]: + return self._entries[:] + + def latest_hash(self) -> str: + return self._head_hash diff --git a/missionledger/planner.py b/missionledger/planner.py new file mode 100644 index 0000000..ace9123 --- /dev/null +++ b/missionledger/planner.py @@ -0,0 +1,38 @@ +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) diff --git a/missionledger/safety.py b/missionledger/safety.py new file mode 100644 index 0000000..7862449 --- /dev/null +++ b/missionledger/safety.py @@ -0,0 +1,24 @@ +from __future__ import annotations + +from typing import Dict + +from .dsl import LocalProblem, PlanDelta + + +def verify_plan(local_problem: LocalProblem, plan_delta: PlanDelta) -> bool: + """Lightweight safety verification hook. + + This is a minimal, deterministic verifier for the MVP: + - If the plan delta carries a non-negative 'safe_buffer', and the local + problem's risk_budget is compatible, accept the plan. + - Otherwise, reject. + This should be replaced with real formal verification hooks in a full build. + """ + buf = plan_delta.delta.get("safe_buffer", 0.0) + try: + risk = float(local_problem.risk_budget) + except Exception: + risk = 0.0 + + # Basic rule: safe if buffer does not exceed the risk budget. + return float(buf) <= max(0.0, risk) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..7994ee0 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,15 @@ +[build-system] +requires = ["setuptools>=61.0", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "idea19_missionledger_verifiable_contract" +version = "0.1.0" +description = "MVP core for verifiable contract-driven mission planning in intermittently-connected fleets." +readme = "README.md" +requires-python = ">=3.8" +license = {text = "MIT"} + +[tool.setuptools.packages.find] +where = ["."] +include = ["missionledger*"] diff --git a/sitecustomize.py b/sitecustomize.py new file mode 100644 index 0000000..4414983 --- /dev/null +++ b/sitecustomize.py @@ -0,0 +1,20 @@ +""" +Site customization for Python startup. + +Ensures the repository root is on sys.path so tests can reliably import +the local package (e.g. `import missionledger.dsl`). This is a small, +non-invasive shim that helps CI environments where the Python path may not +include the project root by default. +""" + +import sys +import os + +try: + # Path to the repository root (directory containing this file) + _repo_root = os.path.dirname(os.path.abspath(__file__)) + if _repo_root not in map(os.path.abspath, sys.path): + sys.path.insert(0, _repo_root) +except Exception: + # Be conservative: do not fail startup if this ever goes wrong + pass diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..c3c6dda --- /dev/null +++ b/test.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -euo pipefail + +echo "==> Running tests with pytest ..." +pytest -q + +echo "==> Building the package (python3 -m build) ..." +python3 -m build +echo "==> Build completed successfully." diff --git a/tests/test_basic.py b/tests/test_basic.py new file mode 100644 index 0000000..aaff448 --- /dev/null +++ b/tests/test_basic.py @@ -0,0 +1,40 @@ +import json + +from missionledger.dsl import LocalProblem +from missionledger.planner import ShadowPlanner +from missionledger.dsl import PlanDelta +from missionledger.safety import verify_plan +from missionledger.governance import GovernanceLedger + + +def test_shadow_planner_and_safety_verification(): + # Basic LocalProblem with a modest risk budget + lp = LocalProblem( + asset_objectives={"rover-1": {"energy": 1.0, "time": 2.0}}, + variables={"start_time": 0}, + constraints=["no_overload"], + risk_budget=1.0, + ) + + primary_delta = PlanDelta(delta={"basic_plan": True}, version=1, metadata={}) + + planner = ShadowPlanner(lp) + shadow = planner.plan(primary_delta) + + # Validate safety proof via the lightweight verifier + assert shadow is not None + assert isinstance(shadow.plan_delta, PlanDelta) + assert shadow.proof_valid in (True, False) + + # Sanity check: the safety verifier should be deterministic for the MVP + safe = verify_plan(lp, shadow.plan_delta) + assert safe == shadow.proof_valid + + # Governance ledger usage: log an entry and inspect its wiring + gl = GovernanceLedger(device_id="test-device") + gl.log({"type": "plan_evaluation", "delta_version": shadow.plan_delta.version}) + assert len(gl.entries) == 1 + assert "parent" in gl.entries[0] + # latest_hash should be a non-empty string hash + assert isinstance(gl.latest_hash(), str) + assert len(gl.latest_hash()) > 0