Imported from Sarthak90210/Rust-Planner (
AGENTS.md). Install upstream withnpx skills add Sarthak90210/Rust-Planner. Copyright stays with the author.
AGENTS.md — read this before touching anything
You are working on Rust Planner: a port of Mission Planner (the ArduPilot ground control station) from C#/WinForms to Rust + Tauri + React. We are not redefining or redesigning Mission Planner — we are porting it. A normal or power user must not be able to tell the apps apart; only someone writing the code would notice the language change.
Where we are
Sub-phases 1.0–1.50 are done; the DATA tab is not finished. 1.51 was ticked without ever being run and has been un-ticked — the user reported every symptom still present, four of the five agents' stated causes were wrong, and one "fix" created the bug it claimed to solve.
About half of it is now genuinely closed and verified on screen: the missing .data-left-lower
CSS rule that made every bottom tab 0 px tall (which was both the invisible gauges and the
two-line Messages box), and the three HUD context-menu items that were wired to nothing.
The next sub-phase is 1.52, briefed in
docs/agent-brief-1-52-runtime-parity.md. Read that
first; it supersedes the status of
docs/agent-brief-phase-1-parity.md, whose instructions
still stand.
First instruction
Open and read CLAUDE.md in full before doing anything else. It is the single
source of truth for how work happens on this project. This file exists only because not every AI
tool reads CLAUDE.md; it is a pointer plus a summary of the rules you must not break. Where the
two differ, CLAUDE.md wins.
Then read, in this order:
ROADMAP.md— find the next sub-phase (the first⬜).docs/phase-N-*.mdfor that phase — the control inventory and layout spec.docs/brain/index.md— the project's memory. Read thecode/note for any module you're about to touch.
The map
| File | Is | Ask it |
|---|---|---|
CLAUDE.md |
How we work | What's the process? |
ROADMAP.md |
What we build | What's next? |
docs/phase-1..5-*.md |
What Mission Planner is | Where does this control go? |
docs/ui-style.md |
Mission Planner's exact appearance | What is MP's real colour/size/font here? |
docs/brain/ |
What our code is and why | Why is it like this? |
../MissionPlanner/ |
The C# original | What does MP actually do here? |
Non-negotiables
1. This is a teaching project. The AI writes the code; the human reads it to learn Rust. Every piece of code gets explained: what it does, the Rust concept behind it, why this approach, what was rejected, and what it means for the drone. Never dump code without a walkthrough.
But keep the closing recap short — what changed, how to run it, anything blocking. The
walkthrough is where teaching happens; the recap is not a second pass at it. Longer write-ups
belong in docs/brain/, not in chat.
2. One sub-phase at a time. Work through ROADMAP.md in order. Do not batch sub-phases. Do
not leave one broken. The full ritual is in CLAUDE.md; the short version is: read the spec →
preview → concepts → code → walkthrough → verify against SITL → tick the box → update the brain.
3. The C# source is the spec. Mission Planner is checked out at ../MissionPlanner/. From now on, any sub-phase, phase, or feature MUST be implemented by looking at the source code in the Mission Planner codebase first. Read the matching .cs / .Designer.cs before building any control. After implementation of that feature, you MUST check again for any bloatware or errors. If the roadmap and the C# disagree, the C# wins — say so, then fix the roadmap.
4. Port Mission Planner exactly — layout, appearance, and behaviour. Every panel, tab and
button goes where MP puts it, with MP's exact label text including its quirks (Arm/ Disarm
with the space, Tlog > Kml or Graph, Servo/Relay), and looks and acts like MP — same
colours, fonts, gradients, borders, control chrome, sizes, spacing, prompts, and MAVLink
sequences. Nothing is restyled, modernised, or “improved”. The only difference a user should
be unable to see is the implementation language (Rust instead of C#). docs/ui-style.md
records MP's exact values (from its C#/.resx); port them, never approximate.
5. Nothing is dropped, and nothing is hardcoded. This is a port of Mission Planner. If MP
prompts the user for a value, we prompt too — a hardcoded constant in place of a prompt is a bug.
Port controls that seem pointless. Record every gap in docs/parity-gaps.md (🔴 gap / 🟡 on
hold / 🔵 deviation) before ticking a roadmap box. Deferring is allowed; forgetting is not.
6. Maintain the brain. docs/brain/ is an Obsidian vault and it is part of the deliverable,
not documentation debt. See below.
7. Safety. This commands real aircraft. Never fake an acknowledgement. Never show optimistic UI for an unconfirmed command. Anything that can spin a motor gets an explicit confirmation step.
8. Ask a lot of questions. If a request has more than one reasonable reading, ask before building.
9. Nothing carries over from the prototype. gcs/ previously held a one-page proof of
concept. It is deleted at sub-phase 1.1, after being preserved on the prototype git tag —
creating that tag is the first step of 1.1, not an afterthought. Read the prototype for
reference; never copy-paste from it.
Maintaining the brain
Read docs/brain/README.md for the full conventions. The rules that
matter most:
- Four folders:
code/(one note per module),concepts/(one per Rust or MAVLink idea),decisions/(one per choice with a rejected alternative),journal/(one per sub-phase). - At the end of every sub-phase: update the touched
code/notes, addconcepts/notes for anything newly explained, add adecisions/note if a real choice was made, write thejournal/entry, and register everything inindex.md. - Frontmatter on every note:
type,phase,tags,updated. - Link with
[[wikilinks]], liberally. Links to notes that don't exist yet are fine. - Notes stand alone — no references to the chat, absolute dates only.
- If the brain and the code disagree, the code wins and you fix the brain.
Stack (decided — do not change without asking)
Rust · Tauri · React in plain JavaScript (not TypeScript) · rust-mavlink ·
Leaflet/MapLibre · ArduPilot SITL over UDP as the test bench.
Rationale for each is in docs/brain/decisions/.
Build and test
cd gcs && npm run tauri dev # run the app
sim_vehicle.py -v ArduCopter --map --console # run the simulated vehicle
Before ticking any box, all three must pass:
node tools/check-seams.mjs # the seams between the Rust and React halves
cd gcs/src-tauri && cargo clippy --all-targets && cargo test
cd gcs && npm run build
check-seams catches the class of bug five audits missed: a call to a command nobody wrote, a
command nobody calls, a file nothing imports, a wikilink to a note nobody wrote. A reviewer reads
within a file; those live between files.
None of the three gates can see the screen, so a fourth rule applies to anything visual:
reproduce the symptom on the running app before you touch it, and reproduce the fix on the running
app before you write it down. Right-click anywhere in the app → Inspect opens the WebView2
devtools; type allow pasting into the console once before it will accept a pasted expression.
Measure with getBoundingClientRect() and getComputedStyle() — do not reason about layout from
the source. tools/render-check.mjs cannot help here and says so in its own header: jsdom has no
layout engine, so a zero-height panel looks fine to it.
A claim you cannot verify stays open. Never mark a docs/parity-gaps.md row closed on the
strength of an argument — say how you checked it, on screen. Five rounds of work have now been
lost to that exact mistake; see
docs/brain/journal/1-51b-runtime-verification.md.
Watch the dev-server console for net::ERR_INSUFFICIENT_RESOURCES and [vite] Failed to reload.
Both have been seen on this app. When they appear the webview has stopped fetching and your code
changes are no longer being applied — restart before concluding anything.
Connect to UDP 127.0.0.1:14550. Full detail: docs/brain/how-to-run.md.