build(agent): c3po#b883b4 iteration

This commit is contained in:
agent-b883b4bc188823a2 2026-04-26 22:11:17 +02:00
parent cc737ceb84
commit 66a3d7a538
12 changed files with 526 additions and 2 deletions

21
.gitignore vendored Normal file
View File

@ -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

32
AGENTS.md Normal file
View File

@ -0,0 +1,32 @@
# AGENTS.md
## Architecture
- `idea153_aidmesh_mobile_first` is a small Python package for offline-first disaster-response planning.
- Core pieces:
- `contracts.py`: parses a tiny ContractScript dialect and compiles it into a canonical portable module.
- `solver.py`: deterministic bounded solver for allocating scarce resources to tasks.
- `sync.py`: signed plan deltas, merge policy, and append-only plan ledger.
- `replay.py`: deterministic replay from signed logs.
- `adapters.py`: starter adapters for field inventory and drone routing.
## Tech Stack
- Python 3.11+
- `pydantic` for validation
- `pytest` for tests
- `setuptools` for packaging
## Rules
- Keep changes deterministic and replayable.
- Prefer minimal, explicit data structures over hidden state.
- Preserve canonical JSON ordering when hashing or signing.
- Add tests for any behavior change in parsing, solving, syncing, or replay.
- Keep public APIs small and stable.
## Test Commands
- `bash test.sh`
- `PYTHONPATH=src python3 -m pytest`
- `python3 -m build`

View File

@ -1,3 +1,54 @@
# idea153-aidmesh-mobile-first
# AidMesh
Source logic for Idea #153
AidMesh is a small offline-first planning engine for disaster response and humanitarian logistics.
This repository currently ships a production-shaped core slice focused on deterministic field coordination:
- `ContractScript` parsing into a canonical portable module
- bounded resource allocation for scarce field supplies
- signed plan deltas with replayable merge semantics
- starter adapters for inventory and drone routing
- deterministic replay for after-action review
## What It Does
- Models a site as capacities plus prioritized tasks.
- Compiles a tiny ContractScript into canonical JSON bytes and a stable digest.
- Solves tasks greedily under resource limits.
- Signs and verifies plan deltas with HMAC-SHA256.
- Merges and replays offline updates deterministically.
## Project Layout
- `src/idea153_aidmesh_mobile_first/contracts.py`
- `src/idea153_aidmesh_mobile_first/solver.py`
- `src/idea153_aidmesh_mobile_first/sync.py`
- `src/idea153_aidmesh_mobile_first/replay.py`
- `src/idea153_aidmesh_mobile_first/adapters.py`
- `tests/test_aidmesh.py`
## Install
```bash
python3 -m pip install -e .
```
## Test
```bash
bash test.sh
```
## ContractScript Example
```text
site "field-clinic-7"
capacity meds 10
capacity water 6
task triage priority 10 demand meds=4, water=2
task shelter priority 4 demand water=4
```
## Package Metadata
The distribution name is `idea153-aidmesh-mobile-first` and the long description is sourced from this `README.md`.

20
pyproject.toml Normal file
View File

@ -0,0 +1,20 @@
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "idea153-aidmesh-mobile-first"
version = "0.1.0"
description = "AidMesh is a mobile-first offline planning engine for disaster response."
readme = "README.md"
requires-python = ">=3.11"
dependencies = ["pydantic>=2.13"]
[project.optional-dependencies]
test = ["pytest>=8"]
[tool.setuptools]
package-dir = {"" = "src"}
[tool.setuptools.packages.find]
where = ["src"]

View File

@ -0,0 +1,21 @@
"""AidMesh: offline-first planning and reconciliation primitives."""
from .adapters import inventory_to_contract, route_to_contract
from .contracts import ContractProgram, ContractScriptCompiler
from .replay import replay_ledger
from .solver import PlanAction, PlanResult, solve_program
from .sync import PlanDelta, PlanLedger, merge_deltas
__all__ = [
"ContractProgram",
"ContractScriptCompiler",
"PlanAction",
"PlanResult",
"PlanDelta",
"PlanLedger",
"inventory_to_contract",
"merge_deltas",
"replay_ledger",
"route_to_contract",
"solve_program",
]

View File

@ -0,0 +1,38 @@
from __future__ import annotations
from dataclasses import dataclass
from .contracts import ContractProgram, TaskSpec
@dataclass(frozen=True)
class InventoryItem:
name: str
quantity: int
criticality: int
@dataclass(frozen=True)
class RouteWaypoint:
name: str
x: float
y: float
priority: int
def inventory_to_contract(site: str, items: list[InventoryItem]) -> ContractProgram:
capacities = {item.name: item.quantity for item in items}
tasks = [TaskSpec(name=f"restock_{item.name}", priority=item.criticality, demand={item.name: max(1, item.quantity // 4 or 1)}) for item in items]
return ContractProgram(site=site, capacities=capacities, tasks=tasks, notes=["generated from inventory adapter"])
def route_to_contract(site: str, origin: tuple[float, float], waypoints: list[RouteWaypoint]) -> ContractProgram:
route_budget = max(1, len(waypoints))
capacities = {"route_steps": route_budget}
ordered = sorted(waypoints, key=lambda wp: (-wp.priority, _distance(origin, (wp.x, wp.y)), wp.name))
tasks = [TaskSpec(name=f"visit_{wp.name}", priority=wp.priority, demand={"route_steps": 1}) for wp in ordered]
return ContractProgram(site=site, capacities=capacities, tasks=tasks, notes=["generated from route adapter"])
def _distance(a: tuple[float, float], b: tuple[float, float]) -> float:
return ((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2) ** 0.5

View File

@ -0,0 +1,110 @@
from __future__ import annotations
import json
import re
from dataclasses import dataclass, field
from hashlib import sha256
from typing import Any
from pydantic import BaseModel, Field, field_validator
class TaskSpec(BaseModel):
name: str
priority: int = Field(ge=0)
demand: dict[str, int]
tags: list[str] = Field(default_factory=list)
@field_validator("demand")
@classmethod
def _validate_demand(cls, value: dict[str, int]) -> dict[str, int]:
if not value:
raise ValueError("task demand must not be empty")
if any(amount <= 0 for amount in value.values()):
raise ValueError("task demand values must be positive")
return value
class ContractProgram(BaseModel):
site: str
capacities: dict[str, int]
tasks: list[TaskSpec]
notes: list[str] = Field(default_factory=list)
@field_validator("capacities")
@classmethod
def _validate_capacities(cls, value: dict[str, int]) -> dict[str, int]:
if not value:
raise ValueError("capacities must not be empty")
if any(amount < 0 for amount in value.values()):
raise ValueError("capacity values must be non-negative")
return value
@dataclass(frozen=True)
class PortableModule:
"""Canonical portable representation of a compiled contract."""
program: ContractProgram
module_bytes: bytes
digest: str
metadata: dict[str, Any] = field(default_factory=dict)
class ContractScriptCompiler:
"""Parse a tiny ContractScript dialect into a deterministic module."""
_capacity_re = re.compile(r"^capacity\s+(?P<name>[A-Za-z_][A-Za-z0-9_]*)\s+(?P<amount>\d+)$")
_task_re = re.compile(
r"^task\s+(?P<name>[A-Za-z_][A-Za-z0-9_]*)\s+priority\s+(?P<priority>\d+)\s+demand\s+(?P<demand>.+)$"
)
_site_re = re.compile(r'^site\s+"(?P<site>.+)"$')
_note_re = re.compile(r'^note\s+"(?P<note>.+)"$')
def compile(self, source: str) -> PortableModule:
site = ""
capacities: dict[str, int] = {}
tasks: list[TaskSpec] = []
notes: list[str] = []
for raw_line in source.splitlines():
line = raw_line.strip()
if not line or line.startswith("#"):
continue
if match := self._site_re.match(line):
site = match.group("site")
continue
if match := self._note_re.match(line):
notes.append(match.group("note"))
continue
if match := self._capacity_re.match(line):
capacities[match.group("name")] = int(match.group("amount"))
continue
if match := self._task_re.match(line):
tasks.append(
TaskSpec(
name=match.group("name"),
priority=int(match.group("priority")),
demand=_parse_demand(match.group("demand")),
)
)
continue
raise ValueError(f"unrecognized ContractScript line: {raw_line}")
if not site:
raise ValueError("missing site declaration")
program = ContractProgram(site=site, capacities=capacities, tasks=sorted(tasks, key=lambda t: (-t.priority, t.name)), notes=notes)
payload = program.model_dump(mode="json")
canonical = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8")
digest = sha256(canonical).hexdigest()
module_bytes = canonical
return PortableModule(program=program, module_bytes=module_bytes, digest=digest, metadata={"format": "canonical-json", "version": 1})
def _parse_demand(raw: str) -> dict[str, int]:
demand: dict[str, int] = {}
for item in raw.split(","):
name, amount = item.strip().split("=")
demand[name.strip()] = int(amount.strip())
return demand

View File

@ -0,0 +1,22 @@
from __future__ import annotations
from dataclasses import dataclass
from .sync import PlanDelta, apply_delta
@dataclass(frozen=True)
class ReplayResult:
state: dict
applied: list[str]
def replay_ledger(initial_state: dict, deltas: list[PlanDelta], secret: str) -> ReplayResult:
state = dict(initial_state)
applied: list[str] = []
for delta in sorted(deltas, key=lambda d: (d.sequence, d.device_id)):
if not delta.verify(secret):
raise ValueError(f"invalid signature for {delta.device_id}:{delta.sequence}")
state = apply_delta(state, delta)
applied.append(f"{delta.device_id}:{delta.sequence}")
return ReplayResult(state=state, applied=applied)

View File

@ -0,0 +1,47 @@
from __future__ import annotations
from dataclasses import dataclass, field
from .contracts import ContractProgram, TaskSpec
@dataclass(frozen=True)
class PlanAction:
task: str
allocations: dict[str, int]
score: float
@dataclass(frozen=True)
class PlanResult:
site: str
selected_tasks: list[PlanAction]
remaining_capacity: dict[str, int]
audit_log: list[str] = field(default_factory=list)
def solve_program(program: ContractProgram) -> PlanResult:
remaining = dict(program.capacities)
selected: list[PlanAction] = []
audit_log: list[str] = []
for task in program.tasks:
if _fits(task, remaining):
for resource, amount in task.demand.items():
remaining[resource] -= amount
score = _task_score(task)
selected.append(PlanAction(task=task.name, allocations=dict(task.demand), score=score))
audit_log.append(f"selected {task.name} score={score:.3f}")
else:
audit_log.append(f"skipped {task.name} insufficient capacity")
return PlanResult(site=program.site, selected_tasks=selected, remaining_capacity=remaining, audit_log=audit_log)
def _fits(task: TaskSpec, remaining: dict[str, int]) -> bool:
return all(remaining.get(resource, 0) >= amount for resource, amount in task.demand.items())
def _task_score(task: TaskSpec) -> float:
demand_weight = sum(task.demand.values())
return task.priority / max(demand_weight, 1)

View File

@ -0,0 +1,85 @@
from __future__ import annotations
import hmac
import json
from dataclasses import dataclass, field
from hashlib import sha256
from typing import Any
def _canonical_bytes(payload: dict[str, Any]) -> bytes:
return json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8")
@dataclass(frozen=True)
class PlanDelta:
device_id: str
sequence: int
parents: list[str]
changes: dict[str, Any]
summary: str
timestamp: str
signature: str = ""
def payload(self) -> dict[str, Any]:
return {
"device_id": self.device_id,
"sequence": self.sequence,
"parents": list(self.parents),
"changes": self.changes,
"summary": self.summary,
"timestamp": self.timestamp,
}
def sign(self, secret: str) -> "PlanDelta":
digest = hmac.new(secret.encode("utf-8"), _canonical_bytes(self.payload()), sha256).hexdigest()
return PlanDelta(
device_id=self.device_id,
sequence=self.sequence,
parents=list(self.parents),
changes=dict(self.changes),
summary=self.summary,
timestamp=self.timestamp,
signature=digest,
)
def verify(self, secret: str) -> bool:
expected = hmac.new(secret.encode("utf-8"), _canonical_bytes(self.payload()), sha256).hexdigest()
return hmac.compare_digest(expected, self.signature)
@dataclass
class PlanLedger:
secret: str
state: dict[str, Any] = field(default_factory=dict)
entries: list[PlanDelta] = field(default_factory=list)
def append(self, delta: PlanDelta) -> None:
if not delta.verify(self.secret):
raise ValueError("invalid plan delta signature")
self.state = apply_delta(self.state, delta)
self.entries.append(delta)
def merge_deltas(base_state: dict[str, Any], deltas: list[PlanDelta], secret: str) -> dict[str, Any]:
state = dict(base_state)
for delta in sorted(deltas, key=lambda d: (d.sequence, d.device_id)):
if not delta.verify(secret):
raise ValueError(f"invalid signature for {delta.device_id}:{delta.sequence}")
state = apply_delta(state, delta)
return state
def apply_delta(state: dict[str, Any], delta: PlanDelta) -> dict[str, Any]:
next_state = json.loads(json.dumps(state, sort_keys=True))
for key, value in delta.changes.items():
if isinstance(value, dict) and isinstance(next_state.get(key), dict):
merged = dict(next_state[key])
merged.update(value)
next_state[key] = merged
else:
next_state[key] = value
next_state.setdefault("audit", [])
next_state["audit"] = list(next_state["audit"]) + [f"{delta.device_id}:{delta.sequence}:{delta.summary}"]
next_state["last_hash"] = sha256(_canonical_bytes(delta.payload())).hexdigest()
return next_state

5
test.sh Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -euo pipefail
PYTHONPATH=src python3 -m pytest
python3 -m build

72
tests/test_aidmesh.py Normal file
View File

@ -0,0 +1,72 @@
from __future__ import annotations
from idea153_aidmesh_mobile_first import ContractScriptCompiler, PlanDelta, PlanLedger, merge_deltas, replay_ledger, solve_program
from idea153_aidmesh_mobile_first.adapters import InventoryItem, RouteWaypoint, inventory_to_contract, route_to_contract
def test_compiler_and_solver_select_high_priority_tasks():
source = """
site "field-clinic-7"
capacity meds 10
capacity water 6
task triage priority 10 demand meds=4, water=2
task shelter priority 4 demand water=4
"""
module = ContractScriptCompiler().compile(source)
assert module.digest
result = solve_program(module.program)
assert [action.task for action in result.selected_tasks] == ["triage", "shelter"]
assert result.remaining_capacity == {"meds": 6, "water": 0}
def test_plan_deltas_sign_merge_and_replay():
secret = "shared-key"
delta_a = PlanDelta(
device_id="truck-1",
sequence=1,
parents=[],
changes={"inventory": {"meds": 12}},
summary="restocked meds",
timestamp="2026-04-26T20:00:00Z",
).sign(secret)
delta_b = PlanDelta(
device_id="drone-2",
sequence=2,
parents=[delta_a.signature],
changes={"routes": {"drone-2": ["clinic", "depot"]}},
summary="published route",
timestamp="2026-04-26T20:01:00Z",
).sign(secret)
merged = merge_deltas({}, [delta_b, delta_a], secret)
assert merged["inventory"]["meds"] == 12
assert merged["routes"]["drone-2"] == ["clinic", "depot"]
replay = replay_ledger({}, [delta_a, delta_b], secret)
assert replay.state["inventory"]["meds"] == 12
assert replay.applied == ["truck-1:1", "drone-2:2"]
def test_adapters_generate_valid_contracts():
inventory_program = inventory_to_contract(
"warehouse-1",
[InventoryItem(name="bandages", quantity=20, criticality=8), InventoryItem(name="saline", quantity=12, criticality=6)],
)
route_program = route_to_contract(
"airstrip-a",
(0.0, 0.0),
[RouteWaypoint(name="north-hill", x=2.0, y=3.0, priority=9), RouteWaypoint(name="river-base", x=1.0, y=1.0, priority=4)],
)
assert solve_program(inventory_program).selected_tasks
assert solve_program(route_program).selected_tasks
ledger = PlanLedger(secret="shared-key")
delta = PlanDelta(
device_id="inventory-1",
sequence=1,
parents=[],
changes={"inventory": {"bandages": 20}},
summary="inventory snapshot",
timestamp="2026-04-26T20:02:00Z",
).sign("shared-key")
ledger.append(delta)
assert ledger.state["inventory"]["bandages"] == 20