This is a submission for the GitHub Finish-Up-A-Thon Challenge
What I Built
pluto-ecss is a transpiler and
runtime for PLUTO — the procedure language standardised by ECSS
(ECSS-E-ST-70-32C)
for spacecraft testing and operations. It's the DSL ground operators write to
bring up a star tracker, run a parallel safety sequence, or react to an on-board
event.
You hand it a PLUTO procedure and it gives you back readable, runnable Python
— plus a small runtime library, a CLI, a live TUI, and a browser playground.
$ pluto-ecss run examples/01_original.pluto
[ACTIVITY] Switch on Star Tracker2
[ACTIVITY] Switch on Reaction Wheel3 of AOC of Satellite
[ACTIVITY] Switch on Star Tracker1
It started life in 2019 as a Google Summer of Code work product: a sample
parser that built a tree from one hard-coded script and "ran" it by walking the
tree. It never grew past that one file, and it sat dormant for nearly seven
years. Finishing it means closing a loop I'd quietly written off — turning a
"sample for a proposal" into something you can actually pip install and use.
Demo
- Live playground (no install): https://stzifkas.github.io/pluto-ecss/playground/ — write PLUTO and compile/run it entirely in your browser via Pyodide.
- Docs: https://stzifkas.github.io/pluto-ecss/
- Repo: https://github.com/stzifkas/pluto-ecss
-
Install:
pip install pluto-ecss
The TUI demo (pluto-ecss demo SCRIPT) lights up a fake satellite as the
procedure executes:
╭──────────────── Procedure: 05_full_bringup.pluto ────────────────╮
│ EXECUTING │
╰──────────────────────────────────────────────────────────────────╯
🛰 Satellite (AOC subsystem)
Component │ Status
─────────────────────┼─────────────────
Reaction Wheel3 │ ON
Star Tracker1 │ ON
Star Tracker2 │ OFF
📡 Activity feed: ▶ Switch on Reaction Wheel3 … ⚡ Events: declared: boom
The Comeback Story
Before — the 2019 GSoC snapshot (still browsable on the
legacy/gsoc-2019
branch): two .py files, a ~30-line grammar covering five constructs, a
tree-walking interpreter tangled into the parser, zero tests, no CLI, no
packaging — and real bugs (setExecutionSatus typo, super.__init__ with no
parens, types never imported). It ran exactly one script and NameError'd on
anything else.
After — main today: a proper transpiler (PLUTO → parse tree → readable
Python), a standalone runtime, and a real toolchain.
| 2019 | 2026 | |
|---|---|---|
| Grammar | ~30 lines | 168 lines |
| Tests | 0 | 164 passing |
| Examples | 1 | 16 |
| Package LOC | ~600 | ~3,600 |
| CLI | none | parse / compile / run / demo / fmt / gen |
| Runtimes | inline tree walker | threaded + asyncio |
| Output formats | side effects only | Python (sync / async / class / no-runtime) + JSON |
| Docs | one README | mkdocs site + Pygments lexer |
| Playground | none | browser-based (Pyodide) |
| ECSS coverage | a handful of constructs | most of Annex A.1 and A.3 |
What I added/fixed to finish it:
- Rebuilt the grammar with proper keyword-priority handling (the old one used brittle negative-lookahead patterns that broke on common words).
- Replaced the interpreter with a transpiler that emits self-contained Python.
- Implemented most of the ECSS spec: steps and sub-bodies (A.1.7), object
property requests (A.3.9.8),
in the context of …(A.3.9.10), reporting data andsave context(A.3.9.5/.25),refer by(A.3.9.26/.27), record/array activity arguments (A.3.9.28), and continuation tests with all seven actions and A.2.5 defaults (A.3.9.33). - Added the everyday language layer (
if/case/while/for/repeat,wait until, expressions), a runtime with concurrency primitives, friendly parse errors with file:line:column carets, a CLI, an mkdocs docs site, and the playground.
My Experience with GitHub Copilot
Copilot is genuinely visible in the history — several release commits are
co-authored by it. Where it helped most:
-
The grammar's keyword-priority resolution. Earley grammars for a DSL full
of multi-word identifiers (
Star Tracker2,Reaction Wheel3 of AOC of Satellite) are finicky. Copilot helped me reason through lexer priorities and surfaced an Earley lexer-priority bug that would have cost me hours to chase down alone. -
The transpiler's parse-tree walker — a lot of repetitive
_stmt_*emit methods where Copilot's suggestions removed most of the typing. -
The runtime's threading/concurrency primitives (
parallel_until_all,wait_for_event, watchdogs) — boilerplate it could draft and I could refine.
The architectural calls were mine — choosing a transpiler over an interpreter,
the src/ layout, the multiple compile targets, the test design. What Copilot
changed most was the psychology of returning to old code: the 2019 version was
full of bugs and missing imports that, back then, felt like cliff-edges. With
Copilot at hand, fixing those and then doing the real spec work felt like one
continuous flow instead of three separate undertakings. That's largely why this
finally got finished.















