build(agent): weasel-1#856f80 iteration

This commit is contained in:
agent-856f80a92b1141b4 2026-04-24 17:54:35 +02:00
parent 8f0e9dbeda
commit e66cc61623
8 changed files with 123 additions and 30 deletions

5
.gitignore vendored
View File

@ -1,3 +1,8 @@
__pycache__/
*.pyc
dist/
build/
*.egg-info/
node_modules/
.npmrc
.env

View File

@ -1,24 +1,16 @@
EdgeMind: Verifiable Onboard AI Planning Runtime for Embedded Robots
# EdgeMind - Verifiable Onboard IR (initial skeleton)
Overview
- EdgeMind is a modular, contract-driven runtime for autonomous planning on resource-constrained hardware (ARM, RISC-V). It enables offline-first planning with safety contracts, delta-sync updates, and a data-contract layer for cross-vendor interoperability.
This repository contains an initial Python skeleton for the EdgeMind IR (Intermediate Representation) and a small set of Pydantic models representing the canonical IR types used by the EnergiBridge and EdgeMind runtime.
Key components (minimal MVP, production-ready architecture):
- Planner: lightweight, bounded-complexity planning with per-goal action selection
- Safety contracts: pre/post conditions and simple budget-based risk controls
- EnergiBridge: a CatOpt-inspired data-contract bridge with LocalProblem, SharedSignals, PlanDelta, DualVariables, AuditLog, and AdapterContract
- Adapters: skeletons and bindings for sensors/actuators; TLS-ready communication in MVP
- Sandbox & governance: audit trails and deterministic replay
- Simulation hooks: Gazebo/ROS-based testbeds for validation
What is included in this change:
- pyproject.toml with packaging metadata and dependency on pydantic
- specs/ir.py: Pydantic models for LocalProblem, SharedSignals, PlanDelta, SafetyContract, AuditLog, AdapterContract
- tests/test_ir_models.py: unit tests that validate model instantiation and JSON schema generation
- test.sh: convenience script to run tests and build
Usage
- Run tests: bash test.sh
- Package: python3 -m build
- You can import the package as: from idea15_edgemind_verifiable_onboard import EdgeMindPlanner, SafetyContract, EnergiBridge
How to run tests and build (also invoked by the CI harness):
This repository already ships a working Python MVP that passes tests and builds a wheel. This README documents the intended MVP roadmap and how to extend it further.
bash test.sh
Roadmap (aligned with the Canonical Interop bridge concept)
- Phase 0: Skeleton MVP with 2 starter adapters (sensor gateway, navigator controller)
- Phase 1: Governance ledger scaffolding and adapter conformance tests
- Phase 2: Gazebo/ROS-based cross-domain demo and KPI dashboards
Notes:
- This is a focused, well-scoped first chunk of the overall EdgeMind idea: it provides canonical, typed IR models and tests that the models behave and can produce JSON Schema. Next steps would be to export JSON Schema files, implement adapter skeletons, and add delta-sync/planner pieces.

View File

@ -1,19 +1,16 @@
[build-system]
requires = ["setuptools>=61", "wheel"]
requires = ["setuptools>=40.8.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "idea15-edgemind-verifiable-onboard"
name = "edgemind-verifiable-onboard"
version = "0.1.0"
description = "Verifiable onboard AI planning runtime for embedded robotics"
description = "EdgeMind: Verifiable Onboard AI Planning Runtime (IR schema + small spec)"
readme = "README.md"
requires-python = ">=3.8"
dependencies = [
"numpy",
"pydantic",
"pyyaml",
"typing-extensions",
"pydantic>=1.10",
]
[tool.setuptools.packages.find]
where = ["src"]
where = ["."]

2
specs/__init__.py Normal file
View File

@ -0,0 +1,2 @@
"""Specs package for EdgeMind IR"""
from .ir import *

59
specs/ir.py Normal file
View File

@ -0,0 +1,59 @@
"""IR Pydantic models for EdgeMind: LocalProblem, SharedSignals, PlanDelta, SafetyContract, AuditLog, AdapterContract
This module provides compact, well-documented Pydantic models that serve both
as runtime types and as a single-source-of-truth for JSON Schema generation.
"""
from typing import Dict, List, Optional, Any
from pydantic import BaseModel, Field
class LocalProblem(BaseModel):
id: str = Field(..., description="Unique task id")
goal_type: str = Field(..., description="Type of goal, e.g., reach, survey, charge")
state_vars: Dict[str, Any] = Field(default_factory=dict, description="Observed or tracked state variables")
hard_constraints: List[str] = Field(default_factory=list, description="List of boolean predicates (string form) that must hold")
soft_costs: Dict[str, float] = Field(default_factory=dict, description="Named soft-cost terms to optimize")
energy_budget: Optional[float] = Field(None, description="Available energy budget (Joules)")
time_window: Optional[Dict[str, Any]] = Field(None, description="Optional time window, e.g. {\"start\":..., \"end\":...}")
actuator_interface: Optional[str] = Field(None, description="Target actuator adapter id")
class SharedSignals(BaseModel):
signals: Dict[str, Any] = Field(default_factory=dict, description="Versioned, privacy-bounded signals shared between agents")
version: Optional[str] = Field(None, description="Schema or contract version")
class PlanDelta(BaseModel):
plan_id: str = Field(..., description="Plan this delta applies to")
timestamp: float = Field(..., description="Unix epoch timestamp")
patch: Dict[str, Any] = Field(..., description="Minimal patch representation (CRDT-ish) describing changes")
safety_tags: List[str] = Field(default_factory=list, description="Tags indicating safety relevance or categories")
vector_clock: Optional[Dict[str, int]] = Field(None, description="Optional version vector for merges")
class SafetyContract(BaseModel):
contract_id: str = Field(..., description="Unique contract id")
invariants: List[str] = Field(default_factory=list, description="Boolean predicates that must hold pre/post plan")
fail_actions: List[str] = Field(default_factory=lambda: ["halt"], description="Actions to take when contract violated")
class AuditLog(BaseModel):
entries: List[Dict[str, Any]] = Field(default_factory=list, description="List of audit records")
privacy_budget: Optional[float] = Field(None, description="Optional privacy budget remaining for this log")
class AdapterContract(BaseModel):
adapter_id: str = Field(..., description="Adapter identifier")
supported_domains: List[str] = Field(default_factory=list, description="Domains this adapter can handle, e.g., nav, sensor")
contract_version: Optional[str] = Field(None, description="Semantic version of the adapter contract")
metadata: Dict[str, Any] = Field(default_factory=dict, description="Per-message metadata schema hints")
__all__ = [
"LocalProblem",
"SharedSignals",
"PlanDelta",
"SafetyContract",
"AuditLog",
"AdapterContract",
]

2
specs/schemas/README.md Normal file
View File

@ -0,0 +1,2 @@
This directory can hold generated JSON Schema files for the IR models in specs/ir.py
Use the models' `.schema()` or `.schema_json()` in Python to export updated schemas.

View File

@ -1,10 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
echo "=== Running Python tests ==="
echo "Running pytest..."
pytest -q
echo "=== Building package (verification) ==="
echo "Building package to verify pyproject metadata..."
python3 -m build
echo "All tests passed and packaging verified."
echo "All checks passed."

36
tests/test_ir_models.py Normal file
View File

@ -0,0 +1,36 @@
import json
import pytest
from specs.ir import (
LocalProblem,
SharedSignals,
PlanDelta,
SafetyContract,
AuditLog,
AdapterContract,
)
def test_localproblem_minimal():
lp = LocalProblem(id="task-1", goal_type="reach")
assert lp.id == "task-1"
assert lp.goal_type == "reach"
def test_plan_delta_and_vector_clock():
pd = PlanDelta(plan_id="p1", timestamp=1.23, patch={"ops": []}, safety_tags=["none"], vector_clock={"a": 1})
assert pd.vector_clock["a"] == 1
def test_safety_contract_default_fail_action():
sc = SafetyContract(contract_id="c1")
assert "halt" in sc.fail_actions
def test_schema_generation_json():
# ensure schema JSON generation works for all models
models = [LocalProblem, SharedSignals, PlanDelta, SafetyContract, AuditLog, AdapterContract]
for m in models:
s = m.schema()
# ensure basic JSON-serializable
json.dumps(s)
assert "title" in s or "properties" in s