<?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: Ordewell</title>
    <description>The latest articles on DEV Community by Ordewell (@ordewell).</description>
    <link>https://dev.to/ordewell</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%2F4064893%2F5b79a8f3-ad3b-4205-acc1-3fc849867172.png</url>
      <title>DEV Community: Ordewell</title>
      <link>https://dev.to/ordewell</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ordewell"/>
    <language>en</language>
    <item>
      <title>How to tell when a coding agent has actually finished</title>
      <dc:creator>Ordewell</dc:creator>
      <pubDate>Fri, 18 Sep 2026 17:22:38 +0000</pubDate>
      <link>https://dev.to/ordewell/how-to-tell-when-a-coding-agent-has-actually-finished-3d4b</link>
      <guid>https://dev.to/ordewell/how-to-tell-when-a-coding-agent-has-actually-finished-3d4b</guid>
      <description>&lt;p&gt;Every harness that runs a coding agent eventually has to answer one question: is this&lt;br&gt;
task done? The three signals you reach for first all fail, in ways that are quiet&lt;br&gt;
enough to cost you an afternoon.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; I build Ordewell, and this page is how it answers that&lt;br&gt;
question. The method is not a product feature though. It is a convention you can put in&lt;br&gt;
any harness in an afternoon, and the pitfalls below will bite you in any language, so&lt;br&gt;
they are worth reading even if you never run my tool.&lt;/p&gt;
&lt;h2&gt;
  
  
  The three obvious signals, and why they fail
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. The terminal went quiet.&lt;/strong&gt; An interactive agent TUI does not close when&lt;br&gt;
the work is finished. It stays open, waiting for you to say something else. Silence means&lt;br&gt;
the model stopped printing, which is also what it does while it thinks, waits on a tool,&lt;br&gt;
or gives up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The process exited cleanly.&lt;/strong&gt; Exit code 0 means the program ended without&lt;br&gt;
an error. An agent running out of context, hitting a stop condition, or deciding the task&lt;br&gt;
was already satisfied exits 0 too. The exit code tells you the process finished, not the work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The agent said it was done.&lt;/strong&gt; This is the one that hurts, because it is&lt;br&gt;
confident. Models announce success over a build that does not compile, in a tidy paragraph,&lt;br&gt;
with a summary of changes that were only partly made. When a coordinator agent supervises&lt;br&gt;
worker agents, a version of this scales up: a model reading a model's report and ruling on&lt;br&gt;
it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix is to stop asking for an opinion and start watching for evidence.&lt;/strong&gt;&lt;br&gt;
A task carries a unique token. The prompt asks for that token on the final line. The&lt;br&gt;
harness watches the runner's output for it. Token present means pass. Token missing means&lt;br&gt;
fail, loudly, even when the session exited cleanly.&lt;/p&gt;
&lt;h2&gt;
  
  
  It cannot be a simple string search
&lt;/h2&gt;

&lt;p&gt;Here is the part that surprised me. Watching for a token in terminal output sounds like&lt;br&gt;
&lt;code&gt;output.includes(token)&lt;/code&gt;. It is not, and the reason is that a PTY stream is a&lt;br&gt;
rendering protocol, not a document.&lt;/p&gt;

&lt;p&gt;The raw bytes carry ANSI colour codes, OSC sequences, box-drawing gutter characters from the&lt;br&gt;
TUI's borders, cursor moves, and line erases. Interactive TUIs soft-wrap long lines, so a&lt;br&gt;
single token can arrive split across two writes with an escape sequence in the middle. A&lt;br&gt;
raw string search misses it.&lt;/p&gt;

&lt;p&gt;The first pass is a flatten: strip escapes, strip the box-drawing range, strip all&lt;br&gt;
whitespace. Dropping whitespace sounds reckless until you notice the token itself has none,&lt;br&gt;
so the flattened view can be scanned safely.&lt;/p&gt;

&lt;p&gt;scan, flattened&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```&lt;code&gt;// strip ANSI/OSC escapes, box-drawing gutters, then every space&lt;br&gt;
function flattenTerminalOutput(raw) {&lt;br&gt;
return raw&lt;br&gt;
.replace(ANSI_OR_CTRL_RE, /* escapes, control bytes */ "")&lt;br&gt;
.replace(/[─-▟]/g, "")   // TUI borders and gutters&lt;br&gt;
.replace(/\s+/g, "");&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
That handles the byte-stream case. It does not handle the screen case.

## A full-screen TUI is not a stream

Some agent TUIs paint fragments at absolute cursor positions and repaint unrelated widgets
between those writes. Frame a spinner, then finish the token on a row that was already
partly drawn. Flattened chronologically, the spinner lands in the middle of the token and
nothing matches:

what the bytes look like

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
row 9:  &amp;lt;&amp;lt;
row 23: ⟳ spinner repaint&lt;br&gt;
row 9:  ELL_DONE_9f3c…&amp;gt;&amp;gt;&amp;gt;&lt;code&gt;&lt;br&gt;
&lt;/code&gt;``&lt;/p&gt;

&lt;p&gt;So there is a second pass: replay the cursor and erase sequences to reconstruct the small&lt;br&gt;
screen the user is actually looking at, then scan that. The chronological flatten stays as&lt;br&gt;
the fallback for plain piped output and for soft-wrapped lines.&lt;/p&gt;

&lt;p&gt;Two scans, one verdict. If either sees the token, the task passed. Being strict here costs&lt;br&gt;
throughput for no gain, because a false &lt;em&gt;negative&lt;/em&gt; is the failure that erodes trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three rules that make the token trustworthy
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Rule 1: one token per task.&lt;/strong&gt; Not per plan, not per run. Generate it when the&lt;br&gt;
task is created, keep it on the task, and scan for that exact string. A shared token across&lt;br&gt;
tasks means task six passes on task two's evidence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 2: the instruction must not contain the token.&lt;/strong&gt; Whatever you append to&lt;br&gt;
the prompt gets echoed into the session, and you are scanning that session's output. A&lt;br&gt;
literal token in the instruction would settle the task before the work started. So the&lt;br&gt;
instruction asks the model to assemble the token from two pieces, and the assembled form&lt;br&gt;
never appears in the text you send:&lt;/p&gt;

&lt;p&gt;what the runner is asked for&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;When you have fully completed this task, print one final line containing&lt;br&gt;
only the completion marker. Build it by writing &lt;code&gt;&amp;lt;&amp;lt;&amp;lt;ORDEWELL_&lt;/code&gt;&lt;br&gt;
immediately followed by &lt;code&gt;DONE_&amp;lt;task token&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt;, joined into a single&lt;br&gt;
unbroken token, with no space, quote, or any other character between&lt;br&gt;
the two parts.&lt;code&gt;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 3: break tokens in anything you hand to the next task.&lt;/strong&gt; Tasks receive&lt;br&gt;
their predecessors' notes and summaries. If a finished task's captured output still carries&lt;br&gt;
a live token and that text becomes context for the next one, the model can echo it back and&lt;br&gt;
settle the wrong task. One replacement when the notes are assembled is enough: the token&lt;br&gt;
prefix gets a hyphen spliced into it, and it can never match again.&lt;/p&gt;

&lt;h2&gt;
  
  
  When the token never shows up
&lt;/h2&gt;

&lt;p&gt;The mission is to make that state unmistakable. The session ended, the model claimed the&lt;br&gt;
work, and no token arrived. That is a failed verification, with the exit code kept beside it&lt;br&gt;
as separate evidence rather than as a verdict in its own right. These are the two messages&lt;br&gt;
the card can carry:&lt;/p&gt;

&lt;p&gt;verdict&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;br&gt;
&lt;br&gt;
&lt;/code&gt;``Verified: completion marker detected in agent output. Task completed successfully.&lt;/p&gt;

&lt;p&gt;Failed verification: agent exited cleanly but did not emit the completion marker.`&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


Note what the exit code does *not* do: it never overturns the token in either
direction. A clean exit after a missing token is still a failure. A non-zero exit after a
seen token is still a pass, because the agent did the work and then something unrelated
tripped on the way out.

It is also worth giving long tasks a mid-run checkpoint. The same output scan can carry a
second token type that pauses the task and asks you to approve or reject before it goes
further, which turns "review the diff at the end" into "decide at the risky step".

## Honest limits

- **A marker proves a claim, not correctness.** It shows the session finished and said so. It does not show the tests pass, the build compiles, or the change is right. Nothing here replaces reviewing the diff.

- **The scan is bounded.** Ordewell scans the recent tail of the output buffer, not the whole session, so a token printed an hour before the session ends can in principle sit outside the window. That is a deliberate trade for not re-flattening an unbounded buffer on every write.

- **Trimming output can hide evidence.** If your harness caps or truncates what it keeps, you can hide your own token. Keep the tail, drop the middle.

- **Manual overrides exist and are humiliating.** Marking a task complete by hand records that no automatic verification was performed. It is honest, and it should feel like a warning.

- **This is a convention, not a proof.** A model that prints the token without doing the work defeats it. A task-specific smoke check in the plan is the answer to that, and it is a real gap in the method, not a footnote to it.

## If you want it already wired

Ordewell generates one token per task, appends the instruction above, runs one real
coding-agent session per task, and verdicts each one by evidence. That is the whole loop:

bash



````ordewell plan --goal "Add rate limiting to the public API"
ordewell run`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The planner reads your repo read-only, so planning needs no API key: a coding agent you&lt;br&gt;
already pay for can be the planner. Install with &lt;code&gt;npm install -g ordewell&lt;/code&gt;, or&lt;br&gt;
read the docs first. The source for everything on this page is in&lt;br&gt;
the repo.&lt;/p&gt;

&lt;p&gt;Licensed under Apache-2.0.&lt;/p&gt;

&lt;p&gt;Home&lt;br&gt;
Docs&lt;br&gt;
Plan-first vs parallel&lt;br&gt;
GitHub&lt;br&gt;
Design decisions&lt;br&gt;
License&lt;/p&gt;

</description>
      <category>ai</category>
      <category>coding</category>
      <category>devtools</category>
      <category>llm</category>
    </item>
    <item>
      <title>Why I stopped choosing one coding agent — and route each task to the one that fits</title>
      <dc:creator>Ordewell</dc:creator>
      <pubDate>Wed, 05 Aug 2026 23:31:19 +0000</pubDate>
      <link>https://dev.to/ordewell/why-i-stopped-choosing-one-coding-agent-and-route-each-task-to-the-one-that-fits-370n</link>
      <guid>https://dev.to/ordewell/why-i-stopped-choosing-one-coding-agent-and-route-each-task-to-the-one-that-fits-370n</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclosure up front:&lt;/strong&gt; I built the tool described here. Free and Apache-2.0;&lt;br&gt;
the point of this post is the design thinking, not a purchase.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most agent tooling assumes you've picked a vendor. You're a Claude Code shop or&lt;br&gt;
a Codex shop or a Cursor shop, and everything you run is that one thing. But&lt;br&gt;
that assumption was never true for me — Codex is better at some tasks, Claude&lt;br&gt;
Code at others, and I wanted a single plan that could use both without me&lt;br&gt;
shepherding each step by hand.&lt;/p&gt;

&lt;p&gt;This post is about the design decision behind letting one plan hand work to&lt;br&gt;
different agents — and what it takes to make that safe.&lt;/p&gt;

&lt;h3&gt;
  
  
  A plan as a portfolio decision
&lt;/h3&gt;

&lt;p&gt;The tool starts the same way each time: a goal in, a planner reads the repo&lt;br&gt;
read-only, and an ordered list of tasks comes back. What's different is that&lt;br&gt;
each task carries its own runner, model, thinking effort, and mode. The planner&lt;br&gt;
makes one portfolio decision across the whole plan — a security refactor and a&lt;br&gt;
README update should not get the same model, let alone the same agent — and&lt;br&gt;
shows you every assignment before anything runs. You can change any of it.&lt;/p&gt;

&lt;p&gt;That's the part worth dwelling on: &lt;strong&gt;per-task routing as a first-class feature,&lt;br&gt;
decided in the open, rather than "pick one agent and hope."&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding an agent is a plugin manifest, not a fork
&lt;/h3&gt;

&lt;p&gt;The barrier that usually stops multi-agent setups is that wiring in a second&lt;br&gt;
agent means invasive code. Here, adding an agent is a small plugin manifest, not&lt;br&gt;
a code change. Claude Code, Codex, and OpenCode ship built-in; Aider or your own&lt;br&gt;
CLI is just another manifest. The planner reads each runner's catalog, so a&lt;br&gt;
task's mode and model re-derive from what that runner can actually spawn — you&lt;br&gt;
can't configure a task into a runner that can't run it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The safety boundary that makes mixed plans viable
&lt;/h3&gt;

&lt;p&gt;Routing work across agents raises an obvious question: what stops the &lt;em&gt;planner&lt;/em&gt;&lt;br&gt;
from doing damage in your repo? Two answers, both deliberate.&lt;/p&gt;

&lt;p&gt;First, the planner can't write. Research commands are lexed the way a shell&lt;br&gt;
would lex them and classified per segment; the write tier returns refused before&lt;br&gt;
any approval prompt exists, so there's no "allow once" to click through.&lt;br&gt;
Mutation belongs to the runners.&lt;/p&gt;

&lt;p&gt;Second, completion is evidence-based. A task is done only when its unique&lt;br&gt;
completion marker appears in the runner's output, exit code retained separately.&lt;br&gt;
No agent grades its own work — the marker and the exit code agree, or it fails.&lt;/p&gt;

&lt;h3&gt;
  
  
  Honest limits
&lt;/h3&gt;

&lt;p&gt;The planner is an LLM and occasionally produces a bad plan — the argument for&lt;br&gt;
this design is that you &lt;em&gt;see&lt;/em&gt; the bad plan before a single execution token is&lt;br&gt;
spent. Also, mixing runners means you hold the subscriptions for whatever you&lt;br&gt;
mix: it rides the Claude subscription you already have for Claude Code, the&lt;br&gt;
Codex subscription for Codex. No extra API key, but also no free ride for a&lt;br&gt;
runner you don't already pay for. And the TUI needs tmux (WSL on Windows); the&lt;br&gt;
CLI and VS Code extension don't.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; ordewell &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ordewell
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;GitHub: github.com/ordewell/ordewell&lt;/li&gt;
&lt;li&gt;Apache-2.0, free.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One question I'd genuinely like input on: is per-task model routing useful, or a&lt;br&gt;
knob nobody touches? Curious what multi-agent people think.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>programming</category>
    </item>
    <item>
      <title>How I stopped my coding agents from writing files before I could see the plan</title>
      <dc:creator>Ordewell</dc:creator>
      <pubDate>Wed, 05 Aug 2026 23:04:43 +0000</pubDate>
      <link>https://dev.to/ordewell/how-i-stopped-my-coding-agents-from-writing-files-before-i-could-see-the-plan-10g7</link>
      <guid>https://dev.to/ordewell/how-i-stopped-my-coding-agents-from-writing-files-before-i-could-see-the-plan-10g7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclosure up front:&lt;/strong&gt; I built the tool this article walks through. It's&lt;br&gt;
free and Apache-2.0, so my interest is "people find this useful" more than&lt;br&gt;
"people pay me."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The failure that sent me down this path is probably familiar. I give an agent a&lt;br&gt;
multi-step goal: refactor this module, update the README, add tests. Everything&lt;br&gt;
goes fine until step 4 — where I discover it misread step 1 back at the start.&lt;br&gt;
By then files are written. There's no plan to correct, because the plan lived in&lt;br&gt;
the model's head. There's only something to undo.&lt;/p&gt;

&lt;p&gt;That's the core problem: &lt;strong&gt;the plan is a side effect of the session, not an&lt;br&gt;
artifact you can inspect and edit.&lt;/strong&gt; This post is about the design decision I&lt;br&gt;
landed on to fix it — make the plan the thing you approve, not the thing you&lt;br&gt;
hope for.&lt;/p&gt;

&lt;h3&gt;
  
  
  The plan is a typed artifact
&lt;/h3&gt;

&lt;p&gt;The tool reads your repo read-only, then hands back an ordered list of tasks.&lt;br&gt;
Each task carries four pieces of metadata: the runner (Claude Code, Codex, or&lt;br&gt;
OpenCode), the model, the thinking effort, and the mode. That's not decoration —&lt;br&gt;
those four are what the task &lt;em&gt;actually runs as&lt;/em&gt;. You can rewrite any prompt, add&lt;br&gt;
or delete a task, rewire dependencies (&lt;code&gt;task 4 depends on task 2&lt;/code&gt;), or change&lt;br&gt;
the model on a single task. Completed work stays done. Nothing round-trips the&lt;br&gt;
AI while you edit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why a separate planner
&lt;/h3&gt;

&lt;p&gt;The natural question is "why not just use plan mode?" Two reasons.&lt;/p&gt;

&lt;p&gt;First, plan mode plans &lt;em&gt;inside&lt;/em&gt; the session that then executes — the plan is&lt;br&gt;
advisory and the model can drift from it. Here, the plan is produced by a&lt;br&gt;
separate process that physically cannot write to your repo. Its exploration is&lt;br&gt;
strictly read-only; commands that would write are refused before an approval&lt;br&gt;
prompt even exists, so there's no "allow once" to click through. Mutation&lt;br&gt;
belongs to the runners, not the planner.&lt;/p&gt;

&lt;p&gt;Second, per-task assignment. A security refactor and a README update do not&lt;br&gt;
deserve the same model. The planner makes that portfolio decision across the&lt;br&gt;
whole plan, in the open, before you spend a single execution token — and you can&lt;br&gt;
override any of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verdicts from evidence, not opinion
&lt;/h3&gt;

&lt;p&gt;The part I care most about happened later. Agents are bad at grading themselves&lt;br&gt;
— and worse, they'll announce success on a build that doesn't compile. So a task&lt;br&gt;
here is marked done only when its &lt;strong&gt;unique completion marker&lt;/strong&gt; appears in the&lt;br&gt;
runner's output, with the exit code retained beside it as separate evidence. The&lt;br&gt;
model is never the tie-breaker. If the session finished and claimed the work&lt;br&gt;
without the marker, it fails loudly.&lt;/p&gt;

&lt;p&gt;If you've watched an agent say "done" and then open a file that's still broken,&lt;br&gt;
that's the whole motivation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Honest limits
&lt;/h3&gt;

&lt;p&gt;The planner is still an LLM and writes bad plans sometimes. The argument isn't&lt;br&gt;
that it's always right — it's that &lt;em&gt;a bad plan you can see and edit costs a&lt;br&gt;
minute, and one you can't costs an afternoon.&lt;/em&gt; The completion marker proves the&lt;br&gt;
session finished and claimed the work, not that the code is correct.&lt;/p&gt;

&lt;p&gt;Also: the TUI needs tmux on every platform (on Windows, that means WSL). The CLI&lt;br&gt;
and the VS Code extension run natively without it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; ordewell &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ordewell
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Point it at a repo you know well and read the plan it hands back. That first&lt;br&gt;
plan is the whole argument.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: github.com/ordewell/ordewell&lt;/li&gt;
&lt;li&gt;Apache-2.0, free, no paid tier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy to answer anything, including "why not just do X."&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
