<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: stzifkas</title>
    <description>The latest articles on DEV Community by stzifkas (@stzifkas).</description>
    <link>https://dev.to/stzifkas</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3956377%2Fac1527a6-1d6a-4720-b763-987242edea81.png</url>
      <title>DEV Community: stzifkas</title>
      <link>https://dev.to/stzifkas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stzifkas"/>
    <language>en</language>
    <item>
      <title>You Are the Bottleneck</title>
      <dc:creator>stzifkas</dc:creator>
      <pubDate>Mon, 19 Oct 2026 08:24:53 +0000</pubDate>
      <link>https://dev.to/stzifkas/you-are-the-bottleneck-2gok</link>
      <guid>https://dev.to/stzifkas/you-are-the-bottleneck-2gok</guid>
      <description>&lt;p&gt;&lt;em&gt;AI agents can save developers time. Who gets to spend it?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A developer gives an agent a ticket, goes to make coffee, and comes back to a pull request. Implementation, tests, documentation. The whole little ceremony of software production, compressed into the time it takes the kettle to finish.&lt;/p&gt;

&lt;p&gt;Then comes the review.&lt;/p&gt;

&lt;p&gt;The agent has misunderstood a permission boundary. The tests confirm its misunderstanding. The implementation works beautifully for a version of the requirement nobody asked for. Somewhere inside four hundred lines of plausible code is a decision the developer now has to reconstruct.&lt;/p&gt;

&lt;p&gt;This is a hypothetical morning. It is also a useful place to begin thinking about what agents do to development, because the productivity conversation tends to stop just before it.&lt;/p&gt;

&lt;p&gt;The code appeared. The developer was still needed. What happened to the time?&lt;/p&gt;

&lt;p&gt;In the August 2026 version of &lt;a href="https://fion.ac/jellyfish.pdf" rel="noopener noreferrer"&gt;Artificial Intelligence in the Firm&lt;/a&gt;, Fiona Chen and James Stratton examine 300 million work events across 718 firms. Agent adoption increases lines of code by about 30%, while estimated changes in finished software output are statistically insignificant. Average pull-request review time rises by 49%. This is observational working-paper evidence, dependent on assumptions about adoption timing, rather than a verdict on every agent or team.&lt;/p&gt;

&lt;p&gt;Demirer, Musolff and Yang find a related pattern in &lt;a href="https://www.nber.org/papers/w35275" rel="noopener noreferrer"&gt;Writing Code vs. Shipping Code&lt;/a&gt;: gains diminish as measurement moves downstream towards released software. Their &lt;a href="https://cepr.org/voxeu/columns/writing-code-versus-shipping-code-productivity-effects-across-generations-ai-coding" rel="noopener noreferrer"&gt;account of the research&lt;/a&gt; emphasises complementary stages of production.&lt;/p&gt;

&lt;p&gt;There is a reasonably simple way to think about this. Suppose finished work requires both generation and verification:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;Q&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;min&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size3"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;G&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;h&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size3"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Here, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the number of candidate changes generated per day, 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the developer-hours available for verification, and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;h&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the verification time each change requires. 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;Q&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the number of changes that can actually be completed. Assume comparable changes and fixed requirements; this is an illustrative model, not the papers' estimated specification.&lt;/p&gt;

&lt;p&gt;If agents generate a hundred changes and developers can verify twenty, output is capped at twenty. Doubling generation gives you a larger queue. If the additional changes are harder to understand, verification time rises and completed output can fall.&lt;/p&gt;

&lt;p&gt;There are plenty of engineering responses. Smaller changes. Better specifications. Better tests. Agents that check their work more effectively. Some teams will find substantial gains through exactly these improvements.&lt;/p&gt;

&lt;p&gt;But the equation also leaves something out: who decides how much human attention the system is entitled to consume.&lt;/p&gt;

&lt;p&gt;Calling a developer a bottleneck is a perfectly legitimate description of throughput. It becomes a different kind of statement when the proposed solution is that the developer must supervise more concurrent tasks, switch contexts faster, and sign off on more work in the same afternoon.&lt;/p&gt;

&lt;p&gt;The bottleneck is where human judgment still takes time. A production system organised around increasing throughput will experience that time as a constraint. The developer experiences it as the time required to understand what they are being asked to approve.&lt;/p&gt;

&lt;p&gt;Both descriptions can be accurate. They carry very different priorities.&lt;/p&gt;

&lt;p&gt;An agent can therefore make coding easier while making the job more demanding. There may be less time spent implementing a solution and more time spent reconstructing someone else's solution, except the someone else can generate another one before you finish reading the first.&lt;/p&gt;

&lt;p&gt;Responsibility survives the automation. The failed migration still belongs to a team. The permission bug still wakes a person. The agent's confidence does not take the incident call.&lt;/p&gt;

&lt;p&gt;This is one possible reorganisation of development: a smaller amount of direct implementation supporting a larger volume of supervision, with developers carrying responsibility for decisions they had less opportunity to form.&lt;/p&gt;

&lt;p&gt;The papers establish a narrower empirical pattern. This account of its possible consequences is an interpretation, and the distinction matters. A review bottleneck does not by itself demonstrate intensified work, deteriorating autonomy, or declining pay. Those require their own evidence.&lt;/p&gt;

&lt;p&gt;Still, it gives us a better question to investigate than whether the agent writes good code.&lt;/p&gt;

&lt;p&gt;What happens to the developer's control over the working day?&lt;/p&gt;

&lt;p&gt;Suppose the engineering problems get solved. Agents become reliable. Review gets easier. The same useful software can genuinely be delivered with fewer developer-hours, after accounting for inference, integration, maintenance and failures.&lt;/p&gt;

&lt;p&gt;At this point the technical success is real. The distribution of its benefits remains open.&lt;/p&gt;

&lt;p&gt;A team could work fewer hours for the same pay. It could keep its hours and tackle a useful backlog. It could finally spend time on accessibility, maintenance and the awkward architectural repair that never survives planning.&lt;/p&gt;

&lt;p&gt;The company could also reduce headcount, leave vacancies unfilled, or raise delivery expectations until the saved time disappears into a new baseline.&lt;/p&gt;

&lt;p&gt;These possibilities do not require different models. They require different decisions about the use of the models.&lt;/p&gt;

&lt;p&gt;We can make that separation explicit. Let 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 be the net economic gain from adoption over some period, after its costs. In a deliberately simplified accounting exercise, divide it between developers and owners:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;βS&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;o&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;β&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the benefit reaching developers through compensation or paid time released; 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;o&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the benefit retained by owners. The parameter 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;β&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, between zero and one, records the division. We are holding customer benefits and other claimants outside this small example.&lt;/p&gt;

&lt;p&gt;This is bookkeeping, not an estimated law. Its usefulness is that it makes a missing variable visible.&lt;/p&gt;

&lt;p&gt;A benchmark can help us understand whether a system might increase 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. It says nothing by itself about 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;β&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.&lt;/p&gt;

&lt;p&gt;The division depends on contracts, bargaining power, ownership, hiring conditions and developers' ability to influence how work is organised. Technical indispensability may strengthen that influence. It does not automatically turn into authority over staffing, deadlines or compensation.&lt;/p&gt;

&lt;p&gt;You can be essential to approving the output and have very little say over how much output arrives.&lt;/p&gt;

&lt;p&gt;The same separation appears at a larger scale in Korinek and colleagues' September 2026 working paper, &lt;a href="https://www.anthropic.com/institute/econ-scenarios" rel="noopener noreferrer"&gt;Economic Scenarios for Transformative AI&lt;/a&gt;. Its extreme scenario combines rapid growth with a fall in labour's income share from roughly 60% to 45%. These are conditional outcomes from an Anthropic Institute model, not forecasts of developers' salaries.&lt;/p&gt;

&lt;p&gt;The point worth carrying back to software is the distinction between producing more and receiving more.&lt;/p&gt;

&lt;p&gt;An expanding company can afford better conditions. Affordability does not decide whether it provides them. That decision runs through institutions and competing claims on the additional income.&lt;/p&gt;

&lt;p&gt;There is another reason developers should pay attention to this, even when the tools feel empowering.&lt;/p&gt;

&lt;p&gt;Software expertise lives partly in individuals and partly in a shared working environment: code, documentation, conventions, review discussions, remembered failures. An agent connected to that environment can make parts of its knowledge easier to reuse. Decisions that once required a conversation with a particular developer may become available through a system.&lt;/p&gt;

&lt;p&gt;That can be useful. It can reduce tedious repetition and let more people contribute.&lt;/p&gt;

&lt;p&gt;It can also change who controls access to the team's accumulated knowledge. A developer's skill remains theirs. The repository, internal records, agent configuration and permission to deploy the resulting system may belong to the company. The model itself may be accessed through infrastructure controlled by another company again.&lt;/p&gt;

&lt;p&gt;The ability to use a powerful tool during employment is a particular kind of access. Whether developers can retain that access, change its terms, take their contributions elsewhere, or participate in deciding its purpose are separate questions.&lt;/p&gt;

&lt;p&gt;This is why the cheerful image of every developer becoming a manager of agents feels incomplete. Giving someone ten automated implementers expands their capacity to execute. It does not necessarily give them authority to choose the product, refuse a deadline, control the budget, or decide what happens to the additional revenue.&lt;/p&gt;

&lt;p&gt;They may get a larger span of responsibility inside the same employment relationship.&lt;/p&gt;

&lt;p&gt;None of this requires rejecting the tools. There are tasks developers would gladly stop doing, and good reasons to want software to become cheaper and easier to build. A credible argument for better working conditions should take those gains seriously.&lt;/p&gt;

&lt;p&gt;It should also ask what changes developers can actually observe.&lt;/p&gt;

&lt;p&gt;Has paid working time fallen? Has compensation improved? Is there room to maintain the system properly? Can the team limit incoming work when verification capacity is exhausted? Can developers challenge an adoption decision whose costs are being hidden in their evenings?&lt;/p&gt;

&lt;p&gt;Those are concrete measures of whether saved time has become a benefit to the people doing the development.&lt;/p&gt;

&lt;p&gt;The pull request is ready when the kettle finishes. That is an impressive technical achievement.&lt;/p&gt;

&lt;p&gt;Whether the developer gets to drink the coffee depends on who controls the schedule.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Cover: Adolph Menzel, The Iron Rolling Mill (Modern Cyclopes), 1872–1875. Alte Nationalgalerie, Berlin. Public domain, via &lt;a href="https://commons.wikimedia.org/wiki/File:Adolph_Menzel_-_Eisenwalzwerk_-_Google_Art_Project.jpg" rel="noopener noreferrer"&gt;Wikimedia Commons&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://stzifkas.github.io/llm/software/economics/2026/10/17/you-are-the-bottleneck.html" rel="noopener noreferrer"&gt;Fire Walk With Middleware&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>career</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Pluto-ecss: A transpiler and runtime for PLUTO procedure language</title>
      <dc:creator>stzifkas</dc:creator>
      <pubDate>Sat, 30 May 2026 11:22:34 +0000</pubDate>
      <link>https://dev.to/stzifkas/pluto-ecss-a-transpiler-and-runtime-for-pluto-procedure-language-5c59</link>
      <guid>https://dev.to/stzifkas/pluto-ecss-a-transpiler-and-runtime-for-pluto-procedure-language-5c59</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-05-21"&gt;GitHub Finish-Up-A-Thon Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/stzifkas/pluto-ecss" rel="noopener noreferrer"&gt;pluto-ecss&lt;/a&gt;&lt;/strong&gt; is a transpiler and&lt;br&gt;
runtime for &lt;strong&gt;PLUTO&lt;/strong&gt; — the procedure language standardised by ECSS&lt;br&gt;
(&lt;a href="https://ecss.nl/standard/ecss-e-st-70-32c-test-and-operations-procedure-language/" rel="noopener noreferrer"&gt;ECSS-E-ST-70-32C&lt;/a&gt;)&lt;br&gt;
for spacecraft testing and operations. It's the DSL ground operators write to&lt;br&gt;
bring up a star tracker, run a parallel safety sequence, or react to an on-board&lt;br&gt;
event.&lt;/p&gt;

&lt;p&gt;You hand it a PLUTO procedure and it gives you back &lt;strong&gt;readable, runnable Python&lt;/strong&gt;&lt;br&gt;
— plus a small runtime library, a CLI, a live TUI, and a browser playground.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pluto-ecss run examples/01_original.pluto
&lt;span class="o"&gt;[&lt;/span&gt;ACTIVITY] Switch on Star Tracker2
&lt;span class="o"&gt;[&lt;/span&gt;ACTIVITY] Switch on Reaction Wheel3 of AOC of Satellite
&lt;span class="o"&gt;[&lt;/span&gt;ACTIVITY] Switch on Star Tracker1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It started life in &lt;strong&gt;2019&lt;/strong&gt; as a Google Summer of Code work product: a sample&lt;br&gt;
parser that built a tree from one hard-coded script and "ran" it by walking the&lt;br&gt;
tree. It never grew past that one file, and it sat dormant for nearly seven&lt;br&gt;
years. Finishing it means closing a loop I'd quietly written off — turning a&lt;br&gt;
"sample for a proposal" into something you can actually &lt;code&gt;pip install&lt;/code&gt; and use.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live playground (no install):&lt;/strong&gt; &lt;a href="https://stzifkas.github.io/pluto-ecss/playground/" rel="noopener noreferrer"&gt;https://stzifkas.github.io/pluto-ecss/playground/&lt;/a&gt; — write PLUTO and compile/run it entirely in your browser via Pyodide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://stzifkas.github.io/pluto-ecss/" rel="noopener noreferrer"&gt;https://stzifkas.github.io/pluto-ecss/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/stzifkas/pluto-ecss" rel="noopener noreferrer"&gt;https://github.com/stzifkas/pluto-ecss&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install:&lt;/strong&gt; &lt;code&gt;pip install pluto-ecss&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ctebvx5ov2bcd36lpce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ctebvx5ov2bcd36lpce.png" alt="A friendly parse error" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vh34anh9gzxkc349g9y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vh34anh9gzxkc349g9y.png" alt="A compiled output" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The TUI demo (&lt;code&gt;pluto-ecss demo SCRIPT&lt;/code&gt;) lights up a fake satellite as the&lt;br&gt;
procedure executes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;╭──────────────── 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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Comeback Story
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before — the 2019 GSoC snapshot&lt;/strong&gt; (still browsable on the&lt;br&gt;
&lt;a href="https://github.com/stzifkas/pluto-ecss/tree/legacy/gsoc-2019" rel="noopener noreferrer"&gt;&lt;code&gt;legacy/gsoc-2019&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
branch): two &lt;code&gt;.py&lt;/code&gt; files, a ~30-line grammar covering five constructs, a&lt;br&gt;
tree-walking interpreter tangled into the parser, zero tests, no CLI, no&lt;br&gt;
packaging — and real bugs (&lt;code&gt;setExecutionSatus&lt;/code&gt; typo, &lt;code&gt;super.__init__&lt;/code&gt; with no&lt;br&gt;
parens, &lt;code&gt;types&lt;/code&gt; never imported). It ran exactly one script and &lt;code&gt;NameError&lt;/code&gt;'d on&lt;br&gt;
anything else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After — &lt;code&gt;main&lt;/code&gt; today:&lt;/strong&gt; a proper transpiler (PLUTO → parse tree → readable&lt;br&gt;
Python), a standalone runtime, and a real toolchain.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;2019&lt;/th&gt;
&lt;th&gt;2026&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Grammar&lt;/td&gt;
&lt;td&gt;~30 lines&lt;/td&gt;
&lt;td&gt;168 lines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tests&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;164 passing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Examples&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Package LOC&lt;/td&gt;
&lt;td&gt;~600&lt;/td&gt;
&lt;td&gt;~3,600&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLI&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;&lt;code&gt;parse / compile / run / demo / fmt / gen&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtimes&lt;/td&gt;
&lt;td&gt;inline tree walker&lt;/td&gt;
&lt;td&gt;threaded + asyncio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output formats&lt;/td&gt;
&lt;td&gt;side effects only&lt;/td&gt;
&lt;td&gt;Python (sync / async / class / no-runtime) + JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docs&lt;/td&gt;
&lt;td&gt;one README&lt;/td&gt;
&lt;td&gt;mkdocs site + Pygments lexer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Playground&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;browser-based (Pyodide)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ECSS coverage&lt;/td&gt;
&lt;td&gt;a handful of constructs&lt;/td&gt;
&lt;td&gt;most of Annex A.1 and A.3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;What I added/fixed to finish it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rebuilt the grammar with proper keyword-priority handling (the old one used
brittle negative-lookahead patterns that broke on common words).&lt;/li&gt;
&lt;li&gt;Replaced the interpreter with a transpiler that emits self-contained Python.&lt;/li&gt;
&lt;li&gt;Implemented most of the ECSS spec: steps and sub-bodies (A.1.7), object
property requests (A.3.9.8), &lt;code&gt;in the context of …&lt;/code&gt; (A.3.9.10), reporting data
and &lt;code&gt;save context&lt;/code&gt; (A.3.9.5/.25), &lt;code&gt;refer by&lt;/code&gt; (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).&lt;/li&gt;
&lt;li&gt;Added the everyday language layer (&lt;code&gt;if/case/while/for/repeat&lt;/code&gt;, &lt;code&gt;wait until&lt;/code&gt;,
expressions), a runtime with concurrency primitives, friendly parse errors
with file:line:column carets, a CLI, an mkdocs docs site, and the playground.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My Experience with GitHub Copilot
&lt;/h2&gt;

&lt;p&gt;Copilot is genuinely visible in the history — several release commits are&lt;br&gt;
co-authored by it. Where it helped most:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The grammar's keyword-priority resolution.&lt;/strong&gt; Earley grammars for a DSL full
of multi-word identifiers (&lt;code&gt;Star Tracker2&lt;/code&gt;, &lt;code&gt;Reaction Wheel3 of AOC of
Satellite&lt;/code&gt;) 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The transpiler's parse-tree walker&lt;/strong&gt; — a lot of repetitive &lt;code&gt;_stmt_*&lt;/code&gt;
emit methods where Copilot's suggestions removed most of the typing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The runtime's threading/concurrency primitives&lt;/strong&gt; (&lt;code&gt;parallel_until_all&lt;/code&gt;,
&lt;code&gt;wait_for_event&lt;/code&gt;, watchdogs) — boilerplate it could draft and I could refine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The architectural calls were mine — choosing a transpiler over an interpreter,&lt;br&gt;
the &lt;code&gt;src/&lt;/code&gt; layout, the multiple compile targets, the test design. What Copilot&lt;br&gt;
changed most was the &lt;em&gt;psychology&lt;/em&gt; of returning to old code: the 2019 version was&lt;br&gt;
full of bugs and missing imports that, back then, felt like cliff-edges. With&lt;br&gt;
Copilot at hand, fixing those and &lt;em&gt;then&lt;/em&gt; doing the real spec work felt like one&lt;br&gt;
continuous flow instead of three separate undertakings. That's largely why this&lt;br&gt;
finally got finished.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>python</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
