The build plan · 10 steps · 100 tasks · in public
The path from one sentence to a fleet.
FlyMax turns one English sentence into a flying formation. A Claude reasoning model decomposes the operator's goal into a typed, schema-locked MissionPlan, checks it against hard safety and DGCA airspace guards before any motor arms, dispatches the legs across one or many drones over identical backends — sim, Crazyflie, PX4 — watches for completion, and recovers deterministically on failure, leaving a tamper-evident flight log behind. The orchestrator (Layer 1) is the moat and is MIT-open; the drones are interchangeable effectors. The same agent brain that runs GetMax's RCM fleet, pointed at the sky.
North star — The same triangle_patrol.mission.json flies — on green CI — through Dryrun, Gazebo, a real Crazyflie and a DGCA-legal PX4 hex over Chennai, while a public registry, an open skill + template library, and a first paying DaaS pilot prove the brain is worth more than any airframe.
- Emit the canonical JSON Schema from PydanticcommunityS
Add flymax/missions/schema.py:export_json_schema() and a `flymax schema --out` CLI writing schema/mission.schema.json from Mission.model_json_schema() — one file becomes the contract.
ships: schema/mission.schema.json + CLI command
- Generate the TS type from that schema, gate drift in CIcommunityM
json-schema-to-typescript into flymax-site/lib/mission.ts; a GitHub Action fails if lib/mission.ts is stale vs the schema, so Python/TS divergence can never silently return.
ships: drift-check GitHub Action
- Replace single-shot json.loads with forced tool-usecommunityM
Swap orchestrator.py plan() for Anthropic tool_choice submit_mission built from model_json_schema(); delete the brittle _mission_schema_hint() string, mirroring the working app/api/plan/route.ts.
ships: orchestrator.py PR
- Reconcile ENU-local and WGS-84 framesM
Keep ENU-local for Phase 1-3 indoor, add lat/lon/alt GLOBAL fields for Phase 4 outdoor, with a validator that rejects mixed-frame legs; add one outdoor example mission.
ships: frame validator + examples/outdoor_*.json
- Add a content-addressable plan_hashcommunityS
Mission.plan_hash = sha256 of the canonical-serialized plan, written into metadata on plan() — every plan becomes diffable and signable (closes ARCHITECTURE.md open-question #1).
ships: plan_hash field + ARCHITECTURE.md decision
- Test the tool-use path with a mocked clientcommunityS
Assert the planner returns a schema-valid Mission for 5 canned goals using a recorded Anthropic response — no live key needed in CI; extends tests/test_schema_and_dryrun.py.
ships: tests/test_planner_tooluse.py
- Ship `flymax diff <runA> <runB>`S
Diff two missions by hash and print waypoint/leg deltas — proves plan stability across Claude model versions and across refactors.
ships: flymax diff CLI command
- Cache the static system-prompt prefixS
Apply Anthropic prompt caching to the schema + skills prefix; assert cached calls are measurably cheaper — the cost/latency control the moat needs at scale.
ships: prompt-cache + cost regression test
- Add an outdoor + indoor example paircommunityS
Refresh examples/two_drone_patrol.json and add one outdoor WGS-84 example so both frames have a runnable reference the docs point at.
ships: examples/*.json
- Tag v0.1.1 — unified schema + tool-usecommunityS
Cut the release that closes the schema-divergence gap, and rewrite the README hero around the dual-use thesis (same brain as the RCM agents).
ships: v0.1.1 release tag + README
- Write flymax/safety/guards.pycommunityM
Pure functions check_geofence / check_altitude / check_speed / check_abort_keyword, each returning a typed list[SafetyViolation] with the leg + waypoint index and the breached limit.
ships: flymax/safety/guards.py
- Gate fly() with validate_safe() before connect()M
Aggregate all guards and wire them as a hard gate in orchestrator.fly() BEFORE backend.connect(); raise UnsafeMissionError with the violation list so no backend is ever reached with an unsafe plan.
ships: safety gate in orchestrator.fly()
- Enforce the never-arm invariant in Backend.baseS
connect() must call validate_safe() and refuse to arm on failure; test that a deliberately out-of-geofence mission is rejected by the dryrun backend.
ships: Backend.base guard + test
- Make the ABORT path real and LLM-independentM
Operator types ABORT -> orchestrator calls backend.emergency_land() within one leg; the Guardian Drone (flies near people) cannot depend on an LLM round-trip to stop.
ships: abort handler + stop-within-leg test
- Auto-RTL on low battery mid-legS
Trigger return-to-home below safety.low_battery_pct during a leg and emit a recovery TelemetryEvent — the threat-table row that has no implementation today.
ships: low-battery monitor
- Build the adversarial unsafe-plan fixture setcommunityM
tests/fixtures/unsafe/ with 8 plans (above ceiling, outside fence, no abort keyword, negative speed, NaN position) — assert every one is rejected with the correct violation code.
ships: tests/fixtures/unsafe/
- Make the docs match the codecommunityS
Update the ARCHITECTURE.md threat table with the actual guard function names and add a SECURITY.md note that guards run host-side and never trust the LLM.
ships: ARCHITECTURE.md + SECURITY.md
- Predict geofence breaches, do not just reactM
Before each leg dispatches, check planned waypoints against the geofence and refuse a leg whose path would exit the safe envelope mid-flight — prevention beats post-breach RTL.
ships: pre-dispatch breach predictor
- Block CI on the safety suitecommunityS
Run the deterministic (mocked) safety subset as a blocking CI check so a safety regression can never merge.
ships: blocking safety CI gate
- Publish docs/SAFETY_CASES.mdcommunityM
A fail-safe matrix (failure mode -> detection -> action -> log evidence) that gates every release tag, so v0.2.0+ ships with a reproducible safety case.
ships: docs/SAFETY_CASES.md
This plan is the contract.
Every task names the artefact it ships — a file, an endpoint, a release tag, a video, a flight. We build it in public. Watch the repo for the tags that close each step; join the community to pick one up.