<?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: ForgeCoreAi</title>
    <description>The latest articles on DEV Community by ForgeCoreAi (@forgecore-ai).</description>
    <link>https://dev.to/forgecore-ai</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%2F4176809%2Fd2936523-371e-42d8-81fc-61342a90052f.png</url>
      <title>DEV Community: ForgeCoreAi</title>
      <link>https://dev.to/forgecore-ai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/forgecore-ai"/>
    <language>en</language>
    <item>
      <title>The worker never writes its own test: how my agents are kept from grading their own homework</title>
      <dc:creator>ForgeCoreAi</dc:creator>
      <pubDate>Tue, 13 Oct 2026 10:15:12 +0000</pubDate>
      <link>https://dev.to/forgecoreai/the-worker-never-writes-its-own-test-how-my-agents-are-kept-from-grading-their-own-homework-1l5m</link>
      <guid>https://dev.to/forgecoreai/the-worker-never-writes-its-own-test-how-my-agents-are-kept-from-grading-their-own-homework-1l5m</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/forgecoreai/i-built-an-agentic-workforce-where-done-means-a-command-exited-0-475i"&gt;last post&lt;/a&gt; the rule was: no model says done, a command exits 0. The obvious hole came up in the first comment I imagined writing to myself: &lt;strong&gt;who writes the command?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the same agent that writes the code also writes the check, "exit 0" means "the agent agreed with itself". A check written after the work can be shaped to fit the work. So there are three separate rules in Hermes.Crew, and each one closes a different way to cheat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule 1: the proof is frozen when the card opens
&lt;/h2&gt;

&lt;p&gt;The proof command is snapshotted in the card's &lt;code&gt;origin&lt;/code&gt; event, at the moment the card opens. A later edit of the &lt;code&gt;proof command:&lt;/code&gt; line in the card text changes nothing: the only command that can produce a PASS is the snapshotted one. The one legitimate way to change it is a coordinator &lt;code&gt;rescope&lt;/code&gt;, which is a recorded decision, not an edit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule 2: closing is refused without a PASS line
&lt;/h2&gt;

&lt;p&gt;Every run of the proof appends a verdict line (who ran it, which run, PASS only on exit code 0) to a per-card file. &lt;code&gt;kanban_complete&lt;/code&gt; on a crew card is refused, in every profile, unless that file has a PASS for the card's proof command and no check failed after it.&lt;/p&gt;

&lt;p&gt;The agent cannot argue its way past this. It is not a prompt asking for honesty, it is a tool that returns an error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule 3: when the proof is a script, the verifier writes it
&lt;/h2&gt;

&lt;p&gt;Some work cannot be proven by a one-liner. For those, the proof is a script in a &lt;code&gt;.crew/&lt;/code&gt; folder, one folder per card. Here the split matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;strong&gt;verifier&lt;/strong&gt; writes the script, from the card's "Done when" and its inputs, never the worker&lt;/li&gt;
&lt;li&gt;the plugin's role guard refuses a worker's write, patch or terminal write under &lt;code&gt;.crew/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the verifier's own file tools reach only &lt;code&gt;.crew/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;a card whose proof is such a script is always verified independently, even if the card asked for the cheaper mode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The script is bound by hash at its first run. It changes only through a coordinator &lt;code&gt;revise_script&lt;/code&gt; decision, and the new hash is recorded with who wrote it and which decision authorized it. If the worker finds the script annoying, there is no path to a quieter version.&lt;/p&gt;

&lt;h2&gt;
  
  
  And after "done", someone checks again
&lt;/h2&gt;

&lt;p&gt;When a card is done, the coordinator re-runs the proof once more. A fail comments on the done card and opens one follow-up card under it. One lucky green run does not close the matter.&lt;/p&gt;

&lt;p&gt;The owner can still override from the CLI with &lt;code&gt;hermes kanban complete --force&lt;/code&gt;; that shows up as an &lt;code&gt;owner_close&lt;/code&gt; decision rather than a silent pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does not buy you
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It does not make the proof correct.&lt;/strong&gt; A verifier can write a script that checks the wrong thing. Independence removes the worker's incentive to fit the test to the work. It does not remove misunderstanding of the brief.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It costs a second model session&lt;/strong&gt; on every independent card, plus a proof run. On a one-line change that is a bad trade, which is why a plain command-only proof stays the cheap mode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hashes make tampering visible, not impossible.&lt;/strong&gt; The guarantees are about what the plugin lets an agent do through its tools. They are not a sandbox against a person with a shell on your machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The pattern, without my plugin
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Whoever does the work does not write the acceptance check.&lt;/li&gt;
&lt;li&gt;The check is fixed before the work starts, or changes only through a recorded decision.&lt;/li&gt;
&lt;li&gt;The "close" action is physically refused without a passing result.&lt;/li&gt;
&lt;li&gt;Something other than the worker re-runs it afterwards.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Any agent framework can do all four with a file, a hash and a guard in front of the close call.&lt;/p&gt;

&lt;p&gt;Hermes.Crew is Apache-2.0, self-hosted, no telemetry: &lt;a href="https://github.com/macd2/Crew" rel="noopener noreferrer"&gt;github.com/macd2/Crew&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hermes plugins &lt;span class="nb"&gt;install &lt;/span&gt;macd2/Crew
python3 ~/.hermes/plugins/crew/install.py &lt;span class="nt"&gt;--profile&lt;/span&gt; NAME
hermes &lt;span class="nt"&gt;-p&lt;/span&gt; NAME plugins doctor crew
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;in your agent setup, who writes the acceptance check, and could the worker edit it?&lt;/strong&gt; If yes, I would like to hear what happened.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>ai</category>
      <category>devtools</category>
      <category>agents</category>
    </item>
    <item>
      <title>I built the faster way to drive herdr: every binding one keypress away</title>
      <dc:creator>ForgeCoreAi</dc:creator>
      <pubDate>Tue, 13 Oct 2026 09:19:35 +0000</pubDate>
      <link>https://dev.to/forgecoreai/i-built-the-faster-way-to-drive-herdr-every-binding-one-keypress-away-i51</link>
      <guid>https://dev.to/forgecoreai/i-built-the-faster-way-to-drive-herdr-every-binding-one-keypress-away-i51</guid>
      <description>&lt;p&gt;The fastest thing you can do in a terminal is the thing you never have to leave it for. herdr gives you a lot of actions and then buries them: the ones you reach for most sit below help, settings and detach in its own list, moving a pane between tabs exists only on the command line, and even splits have no action, keybinding or CLI at all. Every one of those is a reason to lift your hand off the keyboard.&lt;/p&gt;

&lt;p&gt;This plugin is about not doing that. One key shows every binding you have - not the defaults, your resolved keymap - ordered so the things you reach for are at the top. Three more keys do the pane work herdr leaves to the CLI: send a pane to another tab, walk it through its neighbours, set every split back to half.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F19hfrkjwnk4vy5a50s5t.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F19hfrkjwnk4vy5a50s5t.png" alt="The keymap reference card: every binding, grouped by commands, panes, tabs, workspaces and session" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nothing to configure beyond the bindings you want, because the list is not stored anywhere. It is derived from your own config every time it opens.&lt;/p&gt;

&lt;h2&gt;
  
  
  One key, and the whole keymap
&lt;/h2&gt;

&lt;p&gt;herdr will not print your resolved keybindings. There is no CLI for it. What exists is &lt;code&gt;herdr --default-config&lt;/code&gt;, where every action appears as a commented line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# action = "binding"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and &lt;code&gt;~/.config/herdr/config.toml&lt;/code&gt;, which overrides those. The set your fingers actually know is the merge of the two, and nothing in the tool shows it. So the plugin does the merge and renders it - which is also why it cannot go stale: bind a new chord, and the popup is right on the next keypress.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F78h35vcx6yzwh41b858j.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F78h35vcx6yzwh41b858j.png" alt="Keycaps: the popup with its three columns" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The popup has three columns under one title. &lt;strong&gt;KEYCAPS&lt;/strong&gt; is what your config adds, &lt;strong&gt;PREFIX&lt;/strong&gt; is herdr's stock binding for the same action, spelled out as &lt;code&gt;ctrl+b h&lt;/code&gt; rather than &lt;code&gt;prefix+h&lt;/code&gt; because the prefix is released before the next key and that is how the chord is typed. Keeping them apart is what makes the page scannable: your own chords line up down the left, instead of being pushed around by the longer prefix forms. An action with nothing under KEYCAPS is one still waiting for a direct chord.&lt;/p&gt;

&lt;p&gt;Your own commands come first, because herdr's config order opens with help, settings and detach - the things you reach for least - and pushes pane and tab movement to the bottom of a popup that already has limited height.&lt;/p&gt;

&lt;p&gt;Colours are ANSI 16 only, so the popup resolves through the terminal's own palette and follows whatever herdr theme is active. &lt;code&gt;NO_COLOR=1&lt;/code&gt; turns that off; piped output is plain either way.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pane work herdr leaves to the CLI, as keys
&lt;/h2&gt;

&lt;p&gt;Three things, and the third has no CLI at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Move a pane to another tab&lt;/strong&gt; on &lt;code&gt;alt+m&lt;/code&gt;. A picker, arrows or &lt;code&gt;j&lt;/code&gt;/&lt;code&gt;k&lt;/code&gt; to move, a number to jump straight there, Enter to confirm, &lt;code&gt;q&lt;/code&gt; or Esc to cancel. Destinations are grouped by workspace, so a pane can cross into another one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  MOVE PANE  pick a destination

  Redesign
  › 1  Claude1  (2 panes)
    2  a new tab here

  Infra
    3  Notes  (1 pane)
    4  a new tab here

    5  a new workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Headings are not selectable and the cursor skips them, the tab the pane is already in is never offered, and "a new tab here" carries the workspace it sits under, so it lands there rather than in whichever workspace has focus.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Swap a pane with its neighbour&lt;/strong&gt; on &lt;code&gt;alt+shift+h/j/k/l&lt;/code&gt;. herdr's own &lt;code&gt;move_tab_previous&lt;/code&gt; and &lt;code&gt;move_tab_next&lt;/code&gt; move whole tabs, not panes. Hold the same direction and the pane keeps walking, and at the edge it wraps to the far end instead of stopping dead, so a row behaves as a closed cycle - because herdr reports a missing neighbour as &lt;code&gt;changed: false&lt;/code&gt; with exit code 0 rather than as an error, and that is the cue to wrap. The walk is bounded so a misbehaving swap cannot spin forever.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Even out the panes&lt;/strong&gt; on &lt;code&gt;alt+shift+e&lt;/code&gt;, which sets every split in the tab back to half. &lt;code&gt;pane resize&lt;/code&gt; only shifts a divider by a relative amount, so there is nothing to call with: this one goes through the socket API's &lt;code&gt;layout.set_split_ratio&lt;/code&gt;, over newline-delimited JSON on &lt;code&gt;~/.config/herdr/herdr.sock&lt;/code&gt;. A split is addressed by the path taken to reach it - &lt;code&gt;[]&lt;/code&gt; is the root, then &lt;code&gt;false&lt;/code&gt; descends into &lt;code&gt;first&lt;/code&gt; and &lt;code&gt;true&lt;/code&gt; into &lt;code&gt;second&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The parts that took longest are the parts herdr does not document
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Keybindings can only target plugin actions, never plugin panes.&lt;/strong&gt; The popup is not what you bind. You bind an action, and that action opens the pane:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alt+h  -&amp;gt;  action "show"  -&amp;gt;  show.py  -&amp;gt;  herdr plugin pane open
                                            -&amp;gt; pane "keys" (popup)
                                              -&amp;gt; keycaps.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;placement = "popup"&lt;/code&gt; has to live in the manifest, not on the open request,&lt;/strong&gt; because the CLI's &lt;code&gt;--placement&lt;/code&gt; flag has no &lt;code&gt;popup&lt;/code&gt; value. A popup also takes all terminal input, Escape included, and closes the moment its command exits - so handing the list to a pager is out. It pages in-process instead: Escape closes it, &lt;code&gt;q&lt;/code&gt; and &lt;code&gt;ctrl+c&lt;/code&gt; too, arrows and page keys and &lt;code&gt;g&lt;/code&gt;/&lt;code&gt;G&lt;/code&gt; scroll when it does not fit. (&lt;code&gt;less&lt;/code&gt; would have needed &lt;code&gt;--lesskey-src&lt;/code&gt; to rebind Escape, which arrived in less 582 while macOS still ships 581 - a plugin that works on one machine only is not a plugin.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The install has a step herdr cannot tell you about.&lt;/strong&gt; A plugin manifest has no field for a keybinding, and &lt;code&gt;herdr plugin install&lt;/code&gt; never touches &lt;code&gt;config.toml&lt;/code&gt;. So after the install every action is registered and no key reaches any of them, which looks exactly like a broken plugin. Hence the second command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;herdr plugin &lt;span class="nb"&gt;install &lt;/span&gt;macd2/herdr-keycaps
python3 ~/.config/herdr/plugins/github/macd2.keycaps-&lt;span class="k"&gt;*&lt;/span&gt;/setup.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;setup.py&lt;/code&gt; merges this plugin's seven bindings - plus the single-modifier &lt;code&gt;alt+&lt;/code&gt; layer that fills the KEYCAPS column for herdr's own actions - into your &lt;code&gt;config.toml&lt;/code&gt;. It backs the file up first, keeps your comments and ordering, adds only what is missing, and leaves any chord you already spent where it is, naming it on the way out. Running it twice changes nothing.&lt;/p&gt;

&lt;p&gt;herdr cannot print a warning at install time either: the install preview emits only herdr's own fields, and a build command's output is piped and discarded unless the command fails, which aborts the install. So the plugin waits for the next server start and puts one notification in the top right, naming the command - and only while &lt;em&gt;nothing&lt;/em&gt; at all is bound. Bind a subset on purpose and it stays quiet, because a half-spent config is a choice, not a mistake.&lt;/p&gt;

&lt;h2&gt;
  
  
  Both scripts would rather fail than mangle the file
&lt;/h2&gt;

&lt;p&gt;Your whole herdr setup lives in that one file, so a wrong edit is worse than no edit. &lt;code&gt;setup.py&lt;/code&gt; and &lt;code&gt;uninstall.py&lt;/code&gt; both state what they intend, build the result in memory, re-parse it and compare it against that intent before anything is written. One unexplained difference - another table changed, a value that came out wrong, output that is not valid TOML - and nothing is written at all. Shapes a line-based edit cannot see are refused rather than guessed at: a &lt;code&gt;keys.command&lt;/code&gt; inline array, a value spread over several lines.&lt;/p&gt;

&lt;p&gt;A refusal exits 1 and prints the reason, the path, and the steps to do it by hand - addressed to an agent, telling it to ask the human first rather than editing the file to get past the refusal. Stock config, then &lt;code&gt;setup.py&lt;/code&gt;, then &lt;code&gt;uninstall.py --also-direct-layer&lt;/code&gt; gives back the original file byte for byte.&lt;/p&gt;

&lt;h2&gt;
  
  
  The failure that is worth a paragraph
&lt;/h2&gt;

&lt;p&gt;If you attach with &lt;code&gt;herdr --remote&lt;/code&gt;, nothing in this plugin works until you pass one flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;herdr &lt;span class="nt"&gt;--remote&lt;/span&gt; &amp;lt;target&amp;gt; &lt;span class="nt"&gt;--remote-keybindings&lt;/span&gt; server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;herdr --remote&lt;/code&gt; uses your &lt;strong&gt;local&lt;/strong&gt; keybindings by default, and local custom command bindings are never sent to the remote host. This fails silently, which is what makes it worth knowing: &lt;code&gt;herdr config check&lt;/code&gt; says &lt;code&gt;config: ok&lt;/code&gt;, &lt;code&gt;herdr server reload-config&lt;/code&gt; says &lt;code&gt;applied&lt;/code&gt;, the plugin links fine and lists its actions - and no key does anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tests
&lt;/h2&gt;

&lt;p&gt;Four of them, because a plugin that edits someone's config should be boring to trust:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 tests/test_manifest.py     &lt;span class="c"&gt;# the required metadata the marketplace parses&lt;/span&gt;
python3 tests/test_grouping.py     &lt;span class="c"&gt;# group order, custom first, unknown actions kept&lt;/span&gt;
python3 tests/test_popup_pager.py  &lt;span class="c"&gt;# stays open on a real pty, closes on esc&lt;/span&gt;
python3 tests/test_show_action.py  &lt;span class="c"&gt;# action opens the right pane, opens no popup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The manifest one matters more than it sounds: the herdr marketplace indexes public repositories tagged &lt;code&gt;herdr-plugin&lt;/code&gt; whose default branch carries a &lt;code&gt;herdr-plugin.toml&lt;/code&gt;. Discovery is automatic and unreviewed, so a typo there is an invisible delisting rather than an error anyone sees.&lt;/p&gt;

&lt;p&gt;An action no group knows about still renders, under &lt;code&gt;OTHER&lt;/code&gt;, so a binding added by a future herdr release is never silently dropped.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;herdr plugin &lt;span class="nb"&gt;install &lt;/span&gt;macd2/herdr-keycaps
python3 ~/.config/herdr/plugins/github/macd2.keycaps-&lt;span class="k"&gt;*&lt;/span&gt;/setup.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MIT, Linux and macOS, built and verified against herdr 0.9.3. The source is &lt;a href="https://github.com/macd2/herdr-keycaps" rel="noopener noreferrer"&gt;github.com/macd2/herdr-keycaps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So the question I would like answered in the comments: &lt;strong&gt;which action in your setup is still not one keypress away?&lt;/strong&gt; That list is what this plugin is built around, and for me it was moving panes - the one thing I did with a right-click for months because herdr only exposed it on the command line.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Drafted with an AI assistant and edited by me.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>herdr</category>
      <category>showdev</category>
      <category>terminal</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I built an agentic workforce where done means a command exited 0</title>
      <dc:creator>ForgeCoreAi</dc:creator>
      <pubDate>Sun, 11 Oct 2026 11:20:03 +0000</pubDate>
      <link>https://dev.to/forgecoreai/i-built-an-agentic-workforce-where-done-means-a-command-exited-0-475i</link>
      <guid>https://dev.to/forgecoreai/i-built-an-agentic-workforce-where-done-means-a-command-exited-0-475i</guid>
      <description>&lt;p&gt;Every failure I have had with coding agents looks the same at the end. The agent writes a summary that reads like&lt;br&gt;
success: the feature is implemented, the tests pass, the branch is ready. Then I open the thing, and half of it is not&lt;br&gt;
there.&lt;/p&gt;

&lt;p&gt;The interesting part is that the model is not lying. It has no way to check. It generated the most plausible&lt;br&gt;
continuation of the conversation, and "done, with a tidy summary" is an extremely plausible continuation. Nothing in&lt;br&gt;
the loop ever asked for evidence.&lt;/p&gt;

&lt;p&gt;So I stopped trying to make the model more honest and changed the shape of the loop instead. In the agentic workforce I run now, no&lt;br&gt;
model is allowed to say done. A command says done, and it has to exit 0.&lt;/p&gt;
&lt;h2&gt;
  
  
  The proof command gets written before the work exists
&lt;/h2&gt;

&lt;p&gt;When I type an ask, the first thing that happens is not work. It is a contract.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/crew add a pricing page with a monthly / annual toggle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The card that opens carries six things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;goal&lt;/strong&gt; - what this is, in my words&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;artifact&lt;/strong&gt; - the file or surface that changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;where it lands&lt;/strong&gt; - the branch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;done when&lt;/strong&gt; - the same thing, in plain language&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;proof command&lt;/strong&gt; - the exact command whose exit code decides&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;budget&lt;/strong&gt; - tokens, so a run cannot spin&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The order is the point. The proof is frozen while the work does not exist yet. At that moment I am uninformed and&lt;br&gt;
honest, so I write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;:e2e &lt;span class="nt"&gt;--&lt;/span&gt; pricing.spec.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and not "looks right to me". Later, with work already on the branch and the temptation to call it finished, the&lt;br&gt;
command is a fact from an earlier conversation. Neither I nor the agent can quietly move it. That is most of the value:&lt;br&gt;
not detection, but removing the option.&lt;/p&gt;
&lt;h2&gt;
  
  
  Done is decided by a tool, not by a model
&lt;/h2&gt;

&lt;p&gt;In the workforce, done is not a status an agent sets. It is the exit code of that command, run as a tool call, at the point&lt;br&gt;
where the card would otherwise close.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;strong&gt;worker&lt;/strong&gt; does the work&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;proof&lt;/strong&gt; runs, exactly as written when the card opened; a non-zero exit is the only failure signal that counts&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;coordinator&lt;/strong&gt; re-runs the proof before the card can close, so one lucky green run does not close it&lt;/li&gt;
&lt;li&gt;a card that asks for a stronger guarantee gets one independent verifier run instead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The model writes the code and the summary. It never writes the verdict.&lt;/p&gt;
&lt;h2&gt;
  
  
  One owner per card, one writer per card
&lt;/h2&gt;

&lt;p&gt;The second failure mode is drift: three agents on the same branch, each doing something locally reasonable, together&lt;br&gt;
producing nothing. So a card has one writer, and a card has one owner - a coordinator that wakes on every card event&lt;br&gt;
with the whole record in hand and takes exactly one decision: retry, rescope, split, or ask me.&lt;/p&gt;

&lt;p&gt;The asks are bounded too. Before any work starts, the chat asks at most five questions in one batch, or none. After&lt;br&gt;
that I am out of the loop until the card ends, and it ends either with a verified result in the thread I asked from, or&lt;br&gt;
with one concrete question. Token budgets are per card, so a run that reaches its budget stops instead of burning&lt;br&gt;
through the rest of the night, and a worker that fails five tool calls in a row stops itself.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it looks like from the outside
&lt;/h2&gt;

&lt;p&gt;Illustrative card, from the demo board:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;16:12:04  /crew add a pricing page with a monthly / annual toggle
16:12:09  contract: artifact app/pricing/page.tsx
          proof    npm run test:e2e -- pricing.spec.ts
16:12:11  card opened - coordinator owns it, your turn ends
   ...
16:41:21  done - proof exit 0 - 2 runs, 1 fix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last line is what reaches the chat: not a summary of feelings, the proof that passed and how many attempts it&lt;br&gt;
took. If the proof had failed twice, I would have got one question instead, with the two failure lines attached.&lt;/p&gt;
&lt;h2&gt;
  
  
  Where this shape stops working
&lt;/h2&gt;

&lt;p&gt;Three honest limits, because a post about verification that only lists wins is its own kind of bullshit.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A proof proves what you wrote, not what you meant.&lt;/strong&gt; &lt;code&gt;test:e2e -- pricing.spec.ts&lt;/code&gt; can be green while the toggle
does nothing, if the test asserts the wrong thing. The leverage is all in writing the command well, and that is
human work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It is bad for work where done is a judgement.&lt;/strong&gt; Naming, positioning, "write the launch post" - no command decides
those. The workforce falls back to a person, which is correct behaviour, but it means this shape only pays off on tasks
with a checkable end.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proofs cost a minute each.&lt;/strong&gt; On trivial work that is a bad trade. On the work you would otherwise re-check at
23:00 anyway, it is the cheapest minute in the task.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is also a fourth thing I did not expect: because the proof fixes the artifact, "can you also just..." turns into&lt;br&gt;
a second card instead of a scope creep inside the first one. Annoying, and correct.&lt;/p&gt;
&lt;h2&gt;
  
  
  The pattern is the point, not my plugin
&lt;/h2&gt;

&lt;p&gt;The generalisable rule is not complicated:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;before the agent starts, write down an executable definition of done;&lt;/li&gt;
&lt;li&gt;let only that definition close the loop;&lt;/li&gt;
&lt;li&gt;let a tool run it, not the model that did the work.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Any agent framework can do this. Most do not, because "done" is much easier to print than to prove.&lt;/p&gt;

&lt;p&gt;I built it as a plugin for Hermes Agent - Apache-2.0, self-hosted, runs on your own machine, no telemetry - and the&lt;br&gt;
whole thing is &lt;a href="https://github.com/macd2/Crew" rel="noopener noreferrer"&gt;github.com/macd2/Crew&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hermes plugins &lt;span class="nb"&gt;install &lt;/span&gt;macd2/Crew
python3 ~/.hermes/plugins/crew/install.py &lt;span class="nt"&gt;--profile&lt;/span&gt; NAME
hermes &lt;span class="nt"&gt;-p&lt;/span&gt; NAME plugins doctor crew
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you would rather watch it before installing anything - the 53 second launch film, one ask through to the verified&lt;br&gt;
result:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/uQcXAd70pFw" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://crew.forgecoreai.com/" rel="noopener noreferrer"&gt;crew.forgecoreai.com&lt;/a&gt; is the same loop as a page, if you would rather read than watch.&lt;/p&gt;

&lt;p&gt;So the question I would actually like answered in the comments: &lt;strong&gt;what does done mean in your setup?&lt;/strong&gt; Do you have a&lt;br&gt;
command, or is it a feeling? I am collecting the ones people genuinely trust - a solo dev with &lt;code&gt;pytest&lt;/code&gt;, a team with a&lt;br&gt;
deploy smoke test, someone checking a number in a dashboard. A proof you cannot write is a task you cannot delegate,&lt;br&gt;
and the interesting stories are the tasks where you had to admit that.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Drafted with an AI assistant and edited by me.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>showdev</category>
      <category>ai</category>
      <category>devtools</category>
      <category>hermes</category>
    </item>
  </channel>
</rss>
