<?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: Alexander Ivanov</title>
    <description>The latest articles on DEV Community by Alexander Ivanov (@someone_somewhere_05cad9e).</description>
    <link>https://dev.to/someone_somewhere_05cad9e</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%2F3941191%2Feb591200-9c40-441f-a313-918124a62f41.jpg</url>
      <title>DEV Community: Alexander Ivanov</title>
      <link>https://dev.to/someone_somewhere_05cad9e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/someone_somewhere_05cad9e"/>
    <language>en</language>
    <item>
      <title>A compliance monitor that does not busywork</title>
      <dc:creator>Alexander Ivanov</dc:creator>
      <pubDate>Thu, 15 Oct 2026 04:25:40 +0000</pubDate>
      <link>https://dev.to/someone_somewhere_05cad9e/a-compliance-monitor-that-does-not-busywork-5f6b</link>
      <guid>https://dev.to/someone_somewhere_05cad9e/a-compliance-monitor-that-does-not-busywork-5f6b</guid>
      <description>&lt;p&gt;&lt;em&gt;First published on &lt;a href="https://openspec-ui.dev/articles/a-compliance-monitor-that-does-not-busywork/" rel="noopener noreferrer"&gt;openspec-ui.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;OpenSpec Workbench initializes repositories and runs agents on changes. It&lt;br&gt;
did not, until now, check that its own runtime files are ignored, or that&lt;br&gt;
its repository rules are consistent. A compliance monitor has been added to&lt;br&gt;
the shared core, and it does three things that matter: it keeps a versioned&lt;br&gt;
catalogue of rules, it runs only when the host reports idle, and it reports&lt;br&gt;
findings without moving or deleting anything.&lt;/p&gt;
&lt;h2&gt;
  
  
  The catalogue, versioned and evidence-linked
&lt;/h2&gt;

&lt;p&gt;Every rule in the catalogue carries a stable identifier, a description of&lt;br&gt;
what it checks, and metadata about the check's cost and whether it supports&lt;br&gt;
automatic repair. Each finding is linked back to the rule that produced it&lt;br&gt;
and to the evidence that triggered it, so you can trace a finding to the&lt;br&gt;
exact check and the exact file or state that caused it.&lt;/p&gt;

&lt;p&gt;The catalogue is versioned. When a rule changes, the new version is applied&lt;br&gt;
to future checks, and old findings remain linked to the version that&lt;br&gt;
produced them. This matters when a rule's threshold is tightened or&lt;br&gt;
relaxed: old findings do not retroactively become violations or pass.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it checks, on initialization
&lt;/h2&gt;

&lt;p&gt;On explicit repository initialization, the monitor verifies that Workbench&lt;br&gt;
runtime state is ignored by Git. It adds only the missing managed ignore&lt;br&gt;
rule, preserving the rest of &lt;code&gt;.gitignore&lt;/code&gt; exactly as you wrote it. Nothing&lt;br&gt;
is overwritten.&lt;/p&gt;

&lt;p&gt;It also checks Workbench runtime files in the main checkout and in&lt;br&gt;
worktrees. It identifies untracked or visible state and explains the&lt;br&gt;
expected root for each state kind without moving or deleting it. A run&lt;br&gt;
journal in &lt;code&gt;.openspec-ui/&lt;/code&gt; is expected to be untracked; a lease file in the&lt;br&gt;
main checkout is expected to be ignored. The monitor says which is which,&lt;br&gt;
and why.&lt;/p&gt;
&lt;h2&gt;
  
  
  Grouping, deduplication and shadow detection
&lt;/h2&gt;

&lt;p&gt;When the same change id appears in multiple worktrees, the monitor groups&lt;br&gt;
them as one logical change and reports the count. It flags a change id&lt;br&gt;
present in both active and archive trees, an archived change left in a&lt;br&gt;
stale worktree, or a shadow copy in main beside its owning worktree. The&lt;br&gt;
Pipeline card count is reconciled with the Changes list, and active changes&lt;br&gt;
missing from the OpenSpec README index are flagged with a suggested link,&lt;br&gt;
not an automatic edit.&lt;/p&gt;
&lt;h2&gt;
  
  
  Per-rule reactions and a periodic schedule
&lt;/h2&gt;

&lt;p&gt;Each rule accepts one of three response settings: &lt;code&gt;autorepair&lt;/code&gt;, &lt;code&gt;advice&lt;/code&gt;&lt;br&gt;
or &lt;code&gt;none&lt;/code&gt;. &lt;code&gt;autorepair&lt;/code&gt; applies a fix without asking; &lt;code&gt;advice&lt;/code&gt; produces a&lt;br&gt;
finding with a suggested action; &lt;code&gt;none&lt;/code&gt; records the finding silently. A&lt;br&gt;
global periodic-monitor switch enables or disables the entire schedule.&lt;/p&gt;

&lt;p&gt;The monitor runs one bounded batch only after the host reports idle and no&lt;br&gt;
mutating Workbench run is active. It measures each check's elapsed time,&lt;br&gt;
schedules by due date and conservative cost, and spreads expensive checks&lt;br&gt;
across later idle windows. Nothing runs as a separate OS daemon.&lt;/p&gt;
&lt;h2&gt;
  
  
  Process ledger and orphan detection
&lt;/h2&gt;

&lt;p&gt;A companion capability, the process ledger, records a synchronous snapshot&lt;br&gt;
for every process spawned by Workbench: PID, OS start time, executable,&lt;br&gt;
hostname, cwd, change, and a secret-free command-line hash. Records are&lt;br&gt;
marked exited on normal close and kept durable across host restarts, keyed&lt;br&gt;
by canonical repository identity and hostname.&lt;/p&gt;

&lt;p&gt;Before any kill, the snapshot is re-verified against the operating system.&lt;br&gt;
Orphaned and overdue processes are surfaced as read-only Compliance&lt;br&gt;
findings. An explicit, confirmable kill lives in the existing recovery&lt;br&gt;
surface, never in Compliance itself. The two capabilities share the same&lt;br&gt;
catalogue but never cross their boundaries: Compliance explains, recovery&lt;br&gt;
acts.&lt;/p&gt;
&lt;h2&gt;
  
  
  What this deliberately does not do
&lt;/h2&gt;

&lt;p&gt;The monitor does not start a background daemon, does not modify source code,&lt;br&gt;
does not run on every file change, and does not replace a linter or a&lt;br&gt;
formatter. It checks Workbench's own runtime hygiene and the consistency of&lt;br&gt;
its repository state.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The code is at&lt;br&gt;
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI" rel="noopener noreferrer"&gt;github.com/VeryComplexAndLongName/OpenSpec-UI&lt;/a&gt;,&lt;br&gt;
where the repository and packages keep the name OpenSpec-UI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openspec-ui-cli compliance check &lt;span class="nt"&gt;--cwd&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>openspec</category>
      <category>devtools</category>
      <category>compliance</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Pay for the plan, not the typing</title>
      <dc:creator>Alexander Ivanov</dc:creator>
      <pubDate>Sun, 11 Oct 2026 05:35:43 +0000</pubDate>
      <link>https://dev.to/someone_somewhere_05cad9e/pay-for-the-plan-not-the-typing-20lc</link>
      <guid>https://dev.to/someone_somewhere_05cad9e/pay-for-the-plan-not-the-typing-20lc</guid>
      <description>&lt;p&gt;&lt;em&gt;First published on &lt;a href="https://openspec-ui.dev/articles/pay-for-the-plan-not-the-typing/" rel="noopener noreferrer"&gt;openspec-ui.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;stepAgents&lt;/code&gt; has let you name a different agent for &lt;code&gt;propose&lt;/code&gt;, &lt;code&gt;review&lt;/code&gt;, &lt;code&gt;apply&lt;/code&gt;&lt;br&gt;
and &lt;code&gt;verify&lt;/code&gt; since 0.42. What is new is a reason to actually do it: the four&lt;br&gt;
stages do not cost the same thing to run well, and they do not need to.&lt;/p&gt;

&lt;p&gt;Deciding what a change should do and reading whether the result is right both&lt;br&gt;
call for judgement. Writing the diff that gets there is comparatively&lt;br&gt;
mechanical - which is not an insult to the work, it is why a cheap, fast model&lt;br&gt;
does it about as well as an expensive one. So the obvious split is: a capable&lt;br&gt;
agent on &lt;code&gt;propose&lt;/code&gt; and &lt;code&gt;review&lt;/code&gt;, and a cheap one on &lt;code&gt;apply&lt;/code&gt;. This is that&lt;br&gt;
split, what it costs at today's prices, and - the part worth reading past the&lt;br&gt;
headline number - exactly what this project's own telemetry can and cannot&lt;br&gt;
prove about the savings.&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%2Ffh7c5kytrwteonkpo6ip.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%2Ffh7c5kytrwteonkpo6ip.png" alt="One chain, four stages, three agents, three ways of reporting what they spent - two convert to money you can cap, one reports nothing at all" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The four stages take different things seriously
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;harness.json&lt;/code&gt; entry accepts &lt;code&gt;agent&lt;/code&gt;, &lt;code&gt;model&lt;/code&gt;, &lt;code&gt;effort&lt;/code&gt;, &lt;code&gt;budget&lt;/code&gt; and&lt;br&gt;
&lt;code&gt;customAgent&lt;/code&gt; - and only &lt;code&gt;propose&lt;/code&gt;, &lt;code&gt;review&lt;/code&gt;, &lt;code&gt;apply&lt;/code&gt; and &lt;code&gt;verify&lt;/code&gt; accept a&lt;br&gt;
&lt;code&gt;stepAgents&lt;/code&gt; entry at all; &lt;code&gt;archive&lt;/code&gt; and &lt;code&gt;git&lt;/code&gt; are mechanical, with nothing to&lt;br&gt;
configure. A &lt;code&gt;model&lt;/code&gt; is only accepted for the four adapters whose registry&lt;br&gt;
entry declares a &lt;code&gt;--model&lt;/code&gt; flag: &lt;code&gt;claude-cli&lt;/code&gt;, &lt;code&gt;copilot-cli&lt;/code&gt;, &lt;code&gt;claude-cli-acp&lt;/code&gt;&lt;br&gt;
and &lt;code&gt;copilot-cli-acp&lt;/code&gt;. &lt;code&gt;budget&lt;/code&gt; is &lt;code&gt;maxCostUsd&lt;/code&gt; or &lt;code&gt;maxAiCredits&lt;/code&gt;, whichever&lt;br&gt;
unit the chosen agent's own capabilities accept - the other is rejected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"stepAgents"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"propose"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claude-cli-acp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claude-opus-5-5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"effort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"budget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"maxCostUsd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"review"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claude-cli-acp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claude-opus-5-5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"effort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"budget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"maxCostUsd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"apply"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deepseek-cli-acp"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"verify"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"copilot-cli-acp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"effort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"medium"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"budget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"maxAiCredits"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timeout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"maxStageSeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2700&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;propose&lt;/code&gt; and &lt;code&gt;review&lt;/code&gt; above pin &lt;code&gt;claude-opus-5-5&lt;/code&gt; at &lt;code&gt;high&lt;/code&gt; effort, with a&lt;br&gt;
dollar ceiling each. &lt;code&gt;claude-fable-5-1&lt;/code&gt; is the other reasonable choice for&lt;br&gt;
either - cheaper per token, still a model built for judgement rather than&lt;br&gt;
throughput; which of the two is worth its price on your own changes is&lt;br&gt;
something to measure, not assume. &lt;code&gt;apply&lt;/code&gt; carries no &lt;code&gt;model&lt;/code&gt;, no &lt;code&gt;effort&lt;/code&gt; and&lt;br&gt;
no &lt;code&gt;budget&lt;/code&gt; at all, and that is not an oversight: &lt;code&gt;deepseek-cli-acp&lt;/code&gt; accepts&lt;br&gt;
none of the three. Its model is a session option this project's driver never&lt;br&gt;
sends, so DeepSeek's own default runs; nothing here can raise or lower how&lt;br&gt;
hard it thinks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the harness can prove, and what it flatly cannot see
&lt;/h2&gt;

&lt;p&gt;This is the part a "save money" article usually skips, and it is the most&lt;br&gt;
useful thing this one has to say.&lt;/p&gt;

&lt;p&gt;Two of the three agents in this split convert cleanly to a ceiling you can&lt;br&gt;
actually set. &lt;code&gt;claude-cli-acp&lt;/code&gt; reports a cost figure directly - measured in&lt;br&gt;
this repository on 2026-09-05, one stage: 60 input, 8,262 output and&lt;br&gt;
1,693,507 cache tokens for &lt;strong&gt;$1.57&lt;/strong&gt;, and &lt;code&gt;budget.maxCostUsd&lt;/code&gt; compares&lt;br&gt;
against exactly that number. &lt;code&gt;copilot-cli-acp&lt;/code&gt; reports no dollar figure, but&lt;br&gt;
it reports &lt;strong&gt;AI Credits&lt;/strong&gt;, which are not a proxy this project invented - they&lt;br&gt;
are the unit Copilot itself bills in, 1 credit = $0.01 - so&lt;br&gt;
&lt;code&gt;budget.maxAiCredits&lt;/code&gt; is a real ceiling in real money, just denominated&lt;br&gt;
differently. Two agents, two currencies, both enforceable.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;deepseek-cli-acp&lt;/code&gt; is the one genuine blind spot. Measured 2026-09-23, its&lt;br&gt;
one usage figure is a context gauge - tokens used against the model's&lt;br&gt;
window - never a cost, a credit count or even a token split. &lt;code&gt;budget&lt;/code&gt; has no&lt;br&gt;
mechanism to set on it, in either unit, because there is nothing to compare&lt;br&gt;
a ceiling against.&lt;/p&gt;

&lt;p&gt;So the honest description of the &lt;code&gt;harness.json&lt;/code&gt; above is: three of the four&lt;br&gt;
stages carry a leash denominated in real money - two in dollars, one in AI&lt;br&gt;
Credits - and the cheap one does not. &lt;code&gt;timeout.maxStageSeconds&lt;/code&gt; still bounds&lt;br&gt;
how &lt;em&gt;long&lt;/em&gt; &lt;code&gt;apply&lt;/code&gt; can run, because elapsed time needs no report from the&lt;br&gt;
agent - but nothing in this product will tell you, or stop you, if a&lt;br&gt;
&lt;code&gt;deepseek-cli-acp&lt;/code&gt; stage is burning through a prepaid balance faster than&lt;br&gt;
expected. That balance lives entirely on DeepSeek's side. Watch it there.&lt;/p&gt;

&lt;p&gt;Two more limits worth knowing before you lean on the cheap stage. Neither&lt;br&gt;
&lt;code&gt;copilot --acp&lt;/code&gt; nor &lt;code&gt;dsh&lt;/code&gt; (DeepSeek's CLI) asks for permission before writing&lt;br&gt;
a file or running a command, despite the Agent Client Protocol supporting the&lt;br&gt;
mechanism - both were observed completing writes and shell commands here&lt;br&gt;
without ever raising &lt;code&gt;session/request_permission&lt;/code&gt;. Cheaper is not the same as&lt;br&gt;
better-supervised; the review gate between &lt;code&gt;apply&lt;/code&gt; and &lt;code&gt;verify&lt;/code&gt; is what is&lt;br&gt;
actually watching this stage, not the permission channel. And &lt;code&gt;dsh&lt;/code&gt; needs&lt;br&gt;
Node 22.18+ on the 22 line, or 24.2+ - below that floor it exits with code 0&lt;br&gt;
before answering, silently. If your repository pins an older Node for its own&lt;br&gt;
tooling the way this one pins 22.11 with Volta, that is the first place to&lt;br&gt;
look when an &lt;code&gt;apply&lt;/code&gt; stage using DeepSeek produces nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this costs, at today's prices
&lt;/h2&gt;

&lt;p&gt;These are vendor list prices, read 2026-09-24, not a figure this project&lt;br&gt;
measured. Nothing here converts one into the other, and the harness has no&lt;br&gt;
opinion about which subscription you carry - that lives entirely outside it,&lt;br&gt;
in each CLI's own login.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setup&lt;/th&gt;
&lt;th&gt;Monthly&lt;/th&gt;
&lt;th&gt;Runs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Max 5x alone&lt;/td&gt;
&lt;td&gt;$100&lt;/td&gt;
&lt;td&gt;every stage on &lt;code&gt;claude-cli&lt;/code&gt;/&lt;code&gt;claude-cli-acp&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Pro + Copilot Pro + DeepSeek API credit&lt;/td&gt;
&lt;td&gt;$20 + $10 + about $5 in tokens ≈ &lt;strong&gt;$35&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;propose&lt;/code&gt;/&lt;code&gt;review&lt;/code&gt; on Claude, &lt;code&gt;apply&lt;/code&gt; on DeepSeek, &lt;code&gt;verify&lt;/code&gt; on Copilot&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Claude Pro is $20/month billed monthly, $17 annually; Claude Max starts at&lt;br&gt;
$100/month for the 5x tier. Copilot Pro is $10/month, including $10 of AI&lt;br&gt;
Credits at 1 credit = $0.01 - which is also where &lt;code&gt;budget.maxAiCredits&lt;/code&gt;'s&lt;br&gt;
minimum of 30 comes from: thirty cents is the smallest ceiling the product&lt;br&gt;
will accept, because Copilot itself will not meter anything finer. DeepSeek&lt;br&gt;
has no subscription tier at all: &lt;code&gt;deepseek-flash&lt;/code&gt; (what this project's own&lt;br&gt;
measurement on 2026-09-22 recorded as &lt;code&gt;DeepSeek-V4-Flash&lt;/code&gt; - names move&lt;br&gt;
faster than documentation; check what &lt;code&gt;dsh&lt;/code&gt; reports before you trust either)&lt;br&gt;
prices output at $0.60 per million tokens off-peak, $1.20 during DeepSeek's&lt;br&gt;
own weekday peak windows. Five dollars of prepaid credit is, at off-peak&lt;br&gt;
rates, upward of eight million output tokens - many multiples of what one&lt;br&gt;
&lt;code&gt;apply&lt;/code&gt; stage moves by the only measurement available here (1.7 million&lt;br&gt;
tokens, all kinds, on a &lt;code&gt;claude-cli-acp&lt;/code&gt; stage). Read that as "a lot", not as&lt;br&gt;
a number of stages: different models tokenize and work differently, and this&lt;br&gt;
project has no &lt;code&gt;apply&lt;/code&gt;-stage measurement on DeepSeek to compare it against&lt;br&gt;
directly.&lt;/p&gt;

&lt;p&gt;The arithmetic says $65 a month, and it survives the correction: GitHub's own&lt;br&gt;
current price for Copilot Pro is $10, not the $20 an older plan once charged,&lt;br&gt;
and the saving lands in the same place regardless, because the difference&lt;br&gt;
comes out of the Claude Max to Claude Pro step either way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this article is not
&lt;/h2&gt;

&lt;p&gt;Not a benchmark. Nothing here measured whether &lt;code&gt;deepseek-cli-acp&lt;/code&gt; produces&lt;br&gt;
work as good as &lt;code&gt;claude-cli-acp&lt;/code&gt; on the same &lt;code&gt;apply&lt;/code&gt; stage - that is a&lt;br&gt;
real, answerable question, and it is not this one. Not a recommendation for&lt;br&gt;
your specific changes: an architecture decision or a security-sensitive&lt;br&gt;
&lt;code&gt;apply&lt;/code&gt; stage may be exactly the case where the expensive agent belongs on&lt;br&gt;
every stage, ceilings included. And not a claim that Codex or Gemini would&lt;br&gt;
be a worse or better third leg of this - both remain agents this project has&lt;br&gt;
never run against a real binary, on any stage.&lt;/p&gt;

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

&lt;p&gt;The full field reference for &lt;code&gt;stepAgents&lt;/code&gt;, &lt;code&gt;model&lt;/code&gt;, &lt;code&gt;effort&lt;/code&gt; and &lt;code&gt;budget&lt;/code&gt; is&lt;br&gt;
in &lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI/blob/main/HARNESS.md" rel="noopener noreferrer"&gt;HARNESS.md&lt;/a&gt;.&lt;br&gt;
Which agents report what, in which unit, is in&lt;br&gt;
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI/blob/main/LIMITS.md" rel="noopener noreferrer"&gt;LIMITS.md&lt;/a&gt;.&lt;br&gt;
The code is at&lt;br&gt;
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI" rel="noopener noreferrer"&gt;github.com/VeryComplexAndLongName/OpenSpec-UI&lt;/a&gt;,&lt;br&gt;
where the repository and packages keep the name OpenSpec-UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where each claim comes from
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;stepAgents&lt;/code&gt;, its four fields, which stages accept it, and which agents
accept a &lt;code&gt;model&lt;/code&gt;: &lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI/blob/main/HARNESS.md" rel="noopener noreferrer"&gt;HARNESS.md&lt;/a&gt;,
"&lt;code&gt;stepAgents&lt;/code&gt;".&lt;/li&gt;
&lt;li&gt;The agent capability table (&lt;code&gt;model&lt;/code&gt;, &lt;code&gt;effort&lt;/code&gt;, spending-cap unit, run
against a real binary): HARNESS.md, "Agents, models, effort, and spending
caps".&lt;/li&gt;
&lt;li&gt;Which agents report usage, in which unit, and the $1.57 and
1,701,829-token measurements: &lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI/blob/main/LIMITS.md" rel="noopener noreferrer"&gt;LIMITS.md&lt;/a&gt;,
"Which agents report usage".&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deepseek-cli-acp&lt;/code&gt;'s context gauge, its measurement date, and that it
reports no cost, no credits and no token split: LIMITS.md, the same
section, and the archived change
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI/blob/main/openspec/changes/archive/2026-09-23-a-run-can-outgrow-its-context/proposal.md" rel="noopener noreferrer"&gt;&lt;code&gt;a-run-can-outgrow-its-context&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Neither &lt;code&gt;copilot --acp&lt;/code&gt; nor &lt;code&gt;dsh&lt;/code&gt; asking for permission, and the Node
22.18+/24.2+ floor: HARNESS.md, "ACP effort and budget capabilities", and
the article
&lt;a href="https://openspec-ui.dev/articles/a-new-agent-and-nothing-else-moved/" rel="noopener noreferrer"&gt;A new agent, and nothing else moved&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Claude Pro and Max prices: &lt;a href="https://claude.com/pricing" rel="noopener noreferrer"&gt;claude.com/pricing&lt;/a&gt;,
read 2026-09-24.&lt;/li&gt;
&lt;li&gt;Copilot Pro's price and its AI Credits: &lt;a href="https://github.blog/news-insights/company-news/github-copilot-is-moving-to-usage-based-billing/" rel="noopener noreferrer"&gt;GitHub's own announcement&lt;/a&gt;,
read 2026-09-24.&lt;/li&gt;
&lt;li&gt;DeepSeek's per-token prices and peak windows:
&lt;a href="https://api-docs.deepseek.com/quick_start/pricing" rel="noopener noreferrer"&gt;DeepSeek's own pricing page&lt;/a&gt;,
read 2026-09-24.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>openspec</category>
      <category>ai</category>
      <category>deepseek</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Two things nobody was watching</title>
      <dc:creator>Alexander Ivanov</dc:creator>
      <pubDate>Tue, 06 Oct 2026 02:34:25 +0000</pubDate>
      <link>https://dev.to/someone_somewhere_05cad9e/two-things-nobody-was-watching-5b2e</link>
      <guid>https://dev.to/someone_somewhere_05cad9e/two-things-nobody-was-watching-5b2e</guid>
      <description>&lt;p&gt;&lt;em&gt;First published on &lt;a href="https://openspec-ui.dev/articles/two-things-nobody-was-watching/" rel="noopener noreferrer"&gt;openspec-ui.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;OpenSpec Workbench's whole pitch is watching an agent while it works. Two&lt;br&gt;
small fixes this week are about the product not watching itself closely&lt;br&gt;
enough - one where cleanup quietly stopped, one where a number was arriving&lt;br&gt;
the whole time and nothing was reading it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The leftover that survived being asked twice
&lt;/h2&gt;

&lt;p&gt;A working directory is removed in two steps: git forgets it, then whatever&lt;br&gt;
git left is deleted. Where the second step meets a file a live process&lt;br&gt;
still has open, the deletion fails, something is left behind, and nobody&lt;br&gt;
ever looks again - every later pass walks the directories git lists, and&lt;br&gt;
git has already forgotten this one.&lt;/p&gt;

&lt;p&gt;That is not a hypothetical. A shell from an already-archived change,&lt;br&gt;
&lt;code&gt;a-change-knows-its-stage&lt;/code&gt;, sat under the worktree root from one day to the&lt;br&gt;
next: 54 megabytes, holding nothing but a downloaded copy of VS Code under&lt;br&gt;
&lt;code&gt;packages/extension/.vscode-test&lt;/code&gt;, which the extension's own test run had&lt;br&gt;
been holding open at the exact moment something tried to remove it. Asked&lt;br&gt;
again a day later, it went without complaint - one retry was all it ever&lt;br&gt;
needed.&lt;/p&gt;

&lt;p&gt;Two things had kept that retry from happening. The rule for "is this ours&lt;br&gt;
to delete" was emptiness: a shell holding no file at any depth was cleared,&lt;br&gt;
and anything else was left alone, on the reasoning that a directory with a&lt;br&gt;
file in it belongs to someone. But a half-finished removal leaves exactly&lt;br&gt;
the opposite - the files that could not be deleted are the ones still&lt;br&gt;
there, so the rule excused the one case it existed for. And almost nothing&lt;br&gt;
called the cleanup in the first place: it ran from a button in the&lt;br&gt;
standalone app, and the periodic sweep that both hosts already run for&lt;br&gt;
everything else never called it at all.&lt;/p&gt;

&lt;p&gt;The fix changes what "ours" means: a shell named after a change this&lt;br&gt;
repository knows, with no &lt;code&gt;.git&lt;/code&gt; of its own, is cleared whatever is inside&lt;br&gt;
it - what is in a directory says nothing about whose it is; its name and&lt;br&gt;
the absence of a checkout do. The periodic sweep now clears these itself,&lt;br&gt;
on every pass, and says what it removed and what it is still waiting on. A&lt;br&gt;
shell it cannot clear yet is asked again next time, not forgotten.&lt;/p&gt;

&lt;p&gt;Checked live against the real worktree root this repository uses: 320&lt;br&gt;
known change names, two live working directories, one shell from an&lt;br&gt;
archived change planted holding a file under &lt;code&gt;.vscode-test&lt;/code&gt;. Read correctly&lt;br&gt;
as not empty and ours, removed, with neither live working directory&lt;br&gt;
touched.&lt;/p&gt;

&lt;h2&gt;
  
  
  The number that was arriving the whole time
&lt;/h2&gt;

&lt;p&gt;DeepSeek's CLI reports no cost, no credits, no token split - the answer to&lt;br&gt;
"how do we put a spending ceiling on it" turned out to be "you can't; only&lt;br&gt;
a time limit binds it at all." But it does send one figure over the Agent&lt;br&gt;
Client Protocol: &lt;code&gt;usage_update&lt;/code&gt;, carrying how many of the model's window&lt;br&gt;
tokens the session is using right now. That figure was already arriving.&lt;br&gt;
Nothing was reading it.&lt;/p&gt;

&lt;p&gt;It is a strange number to build a ceiling on, and the reasoning for&lt;br&gt;
leaving it alone still holds: it falls after a compaction, so counting it&lt;br&gt;
as spend would under-count exactly the long runs that compact. But it&lt;br&gt;
says something a spending figure never could, and says it while a stage is&lt;br&gt;
still running rather than after: a session that has filled most of its&lt;br&gt;
window makes every further turn carry the whole conversation again -&lt;br&gt;
slower, more expensive, and worse at the task than the same work started&lt;br&gt;
fresh.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;budget.maxContextShare&lt;/code&gt; is a share of the window - &lt;code&gt;0.8&lt;/code&gt; for eighty&lt;br&gt;
percent - and reaching it now ends the run as cancelled, not failed, the&lt;br&gt;
same way a time limit already does: a ceiling doing its job is not a&lt;br&gt;
defect. A value outside &lt;code&gt;(0, 1]&lt;/code&gt; is refused up front, so someone who means&lt;br&gt;
eighty percent and types &lt;code&gt;80&lt;/code&gt; is told rather than handed a ceiling that&lt;br&gt;
could never fire.&lt;/p&gt;

&lt;p&gt;Checked live: a chain running &lt;code&gt;deepseek-cli-acp&lt;/code&gt; with the ceiling set&lt;br&gt;
absurdly low. On this project's own pinned Node version, &lt;code&gt;dsh&lt;/code&gt; refused to&lt;br&gt;
start at all - the Node-version problem &lt;a href="https://openspec-ui.dev/articles/a-new-agent-and-nothing-else-moved/" rel="noopener noreferrer"&gt;an earlier article&lt;/a&gt;&lt;br&gt;
already found, showing up again in a different feature. On Node 24.18, the&lt;br&gt;
run's first reading arrived, and the stage stopped mid-run with a reason&lt;br&gt;
naming exactly what happened: "stopped at the context ceiling:&lt;br&gt;
&lt;code&gt;budget.maxContextShare&lt;/code&gt; is 0.0%, and the agent reported 8,277 of&lt;br&gt;
1,000,000 tokens in its context (0.8%)."&lt;/p&gt;

&lt;p&gt;The product also now knows, and says, which agents this can even work on.&lt;br&gt;
&lt;code&gt;contextGauge&lt;/code&gt; is a separate question from whether an agent reports&lt;br&gt;
spending: &lt;code&gt;"none"&lt;/code&gt; where that is certain, &lt;code&gt;"sends"&lt;/code&gt; for &lt;code&gt;deepseek-cli-acp&lt;/code&gt;&lt;br&gt;
from this measurement, &lt;code&gt;"unknown"&lt;/code&gt; for every other ACP agent nobody here&lt;br&gt;
has watched yet. A stage this ceiling can bind is no longer listed as&lt;br&gt;
unbounded - and one it cannot bind still says so honestly, rather than&lt;br&gt;
implying a safety net that was never there.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern, twice
&lt;/h2&gt;

&lt;p&gt;Neither of these was a code path that ran and did the wrong thing. Both&lt;br&gt;
were something already true - a file still open, a number already&lt;br&gt;
arriving - that nothing had been asked to look at. The fix, in both cases,&lt;br&gt;
was smaller than finding the gap.&lt;/p&gt;

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

&lt;p&gt;The code is at&lt;br&gt;
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI" rel="noopener noreferrer"&gt;github.com/VeryComplexAndLongName/OpenSpec-UI&lt;/a&gt;,&lt;br&gt;
where the repository and packages keep the name OpenSpec-UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where each claim comes from
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The leftover shell, the rule that excused it, and the fix: the archived
change
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI/blob/main/openspec/changes/archive/2026-09-23-the-sweep-comes-back-for-what-it-left/proposal.md" rel="noopener noreferrer"&gt;&lt;code&gt;the-sweep-comes-back-for-what-it-left&lt;/code&gt;&lt;/a&gt;,
and its own &lt;code&gt;tasks.md&lt;/code&gt; for the live numbers (320 known change names, the
54 MB find).&lt;/li&gt;
&lt;li&gt;The context ceiling, the live cancellation message, and the Node-version
refusal: the archived change
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI/blob/main/openspec/changes/archive/2026-09-23-a-run-can-outgrow-its-context/proposal.md" rel="noopener noreferrer"&gt;&lt;code&gt;a-run-can-outgrow-its-context&lt;/code&gt;&lt;/a&gt;
and its &lt;code&gt;tasks.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;maxContextShare&lt;/code&gt;, why it is not counted as spend, and &lt;code&gt;contextGauge&lt;/code&gt;:
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI/blob/main/LIMITS.md" rel="noopener noreferrer"&gt;LIMITS.md&lt;/a&gt;,
"caps how full the context gets" and the &lt;code&gt;contextGauge&lt;/code&gt; section.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>openspec</category>
      <category>devtools</category>
      <category>deepseek</category>
      <category>opensource</category>
    </item>
    <item>
      <title>A new agent, and nothing else moved</title>
      <dc:creator>Alexander Ivanov</dc:creator>
      <pubDate>Thu, 01 Oct 2026 02:40:01 +0000</pubDate>
      <link>https://dev.to/someone_somewhere_05cad9e/a-new-agent-and-nothing-else-moved-5hca</link>
      <guid>https://dev.to/someone_somewhere_05cad9e/a-new-agent-and-nothing-else-moved-5hca</guid>
      <description>&lt;p&gt;&lt;em&gt;First published on &lt;a href="https://openspec-ui.dev/articles/a-new-agent-and-nothing-else-moved/" rel="noopener noreferrer"&gt;openspec-ui.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The last article argued that a shared core is what keeps a VS Code extension&lt;br&gt;
and a web app from drifting apart. Two days after it went out, a new agent&lt;br&gt;
arrived, and it is as good a test of that argument as any: DeepSeek, over the&lt;br&gt;
Agent Client Protocol, requested by the owner and added the same day.&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%2Fdb2v8r4h7d1rfs00plsm.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%2Fdb2v8r4h7d1rfs00plsm.png" alt="One new file joins the registry of ten agents; the core is the only place that changed; the server and the extension are not touched" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What it took
&lt;/h2&gt;

&lt;p&gt;One new file, &lt;code&gt;deepseek-acp.ts&lt;/code&gt;, implementing the same &lt;code&gt;AgentAdapter&lt;/code&gt;&lt;br&gt;
interface every other agent implements. It runs &lt;code&gt;dsh --profile acp&lt;/code&gt;, the&lt;br&gt;
DeepSeek CLI's own Agent Client Protocol mode, through the driver the other&lt;br&gt;
ACP-flavored adapters already share. It is added to the registry, allowed by&lt;br&gt;
the default allowlist for exactly those arguments, and detected on &lt;code&gt;PATH&lt;/code&gt; like&lt;br&gt;
every other agent. Neither host's code changed. Both the standalone&lt;br&gt;
application and the VS Code extension picked it up because both read the same&lt;br&gt;
registry.&lt;/p&gt;

&lt;p&gt;DeepSeek is the tenth agent, and the fifth that speaks ACP, beside Claude,&lt;br&gt;
Copilot, Codex and Gemini.&lt;/p&gt;

&lt;h2&gt;
  
  
  What checking it live actually found
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;initialize&lt;/code&gt; answers as &lt;code&gt;deepseek-harness-acp&lt;/code&gt;, with no auth method to run:&lt;br&gt;
the key lives in the person's own &lt;code&gt;dsh&lt;/code&gt; profile, never in this project.&lt;br&gt;
&lt;code&gt;session/new&lt;/code&gt; offers DeepSeek-V4-Flash as the default model and&lt;br&gt;
DeepSeek-V4-Pro as an option, though nothing here sends that option yet, so&lt;br&gt;
V4-Flash is what runs.&lt;/p&gt;

&lt;p&gt;Two things worth a person's attention, both found by running it rather than&lt;br&gt;
by reading its documentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On Node 22.11, &lt;code&gt;dsh&lt;/code&gt; exits with code 0 before answering, saying nothing at&lt;br&gt;
all.&lt;/strong&gt; This repository pins Node 22.11 with Volta for its own tooling, and&lt;br&gt;
Volta puts it first on the &lt;code&gt;PATH&lt;/code&gt; of anything it starts, including an agent&lt;br&gt;
CLI. The same run on Node 24.18 completed. "ACP connection closed" is not a&lt;br&gt;
sentence a person can act on, so a run that ends this way is now told which&lt;br&gt;
Node it met and that a newer one is needed on the &lt;code&gt;PATH&lt;/code&gt; a host starts agents&lt;br&gt;
with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It reports no usage at all.&lt;/strong&gt; The live run sent no &lt;code&gt;usage_update&lt;/code&gt; and no&lt;br&gt;
usage figure on its answer, so a spending ceiling over &lt;code&gt;deepseek-cli-acp&lt;/code&gt;&lt;br&gt;
counts nothing and cannot fire, the same as over five of the other nine&lt;br&gt;
agents. Only a time ceiling has any force over it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What was asked, and what was left for later
&lt;/h2&gt;

&lt;p&gt;The owner has used DeepSeek enough to know it does best with instructions&lt;br&gt;
taken literally, one at a time, rather than left to infer how strictly to&lt;br&gt;
read what follows. So every prompt to it now opens with a short preamble:&lt;br&gt;
follow the steps in order, do exactly what each one asks, name a step as it&lt;br&gt;
finishes, and stop and say why rather than improvise if a step cannot be done&lt;br&gt;
as written.&lt;/p&gt;

&lt;p&gt;What it does not do yet: choose a model. DeepSeek's model is an Agent Client&lt;br&gt;
Protocol session option (&lt;code&gt;session/set_config_option&lt;/code&gt;), and nothing in this&lt;br&gt;
project's shared driver sends session options. Whichever model &lt;code&gt;dsh&lt;/code&gt; defaults&lt;br&gt;
to is the one that runs. Fixing the Node a host starts agents with is also out&lt;br&gt;
of reach from here: the product cannot choose what is on someone's &lt;code&gt;PATH&lt;/code&gt;; it&lt;br&gt;
can only say which one it met.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is the article, and not just a changelog line
&lt;/h2&gt;

&lt;p&gt;Adding a tenth agent is not, by itself, news. What is worth a reader's time is&lt;br&gt;
that adding it stayed inside the one package the architecture says it should:&lt;br&gt;
&lt;code&gt;core&lt;/code&gt;, and nowhere else. An implement run against this same change wrote its&lt;br&gt;
own file and ticked its own task in 22 seconds, over the very mechanism the&lt;br&gt;
article describes.&lt;/p&gt;

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

&lt;p&gt;The code is at&lt;br&gt;
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI" rel="noopener noreferrer"&gt;github.com/VeryComplexAndLongName/OpenSpec-UI&lt;/a&gt;,&lt;br&gt;
where the repository and packages keep the name OpenSpec-UI. The architecture&lt;br&gt;
this rests on is in&lt;br&gt;
&lt;a href="https://openspec-ui.dev/articles/one-core-two-hosts/" rel="noopener noreferrer"&gt;One core, two hosts&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where each claim comes from
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The adapter, the live &lt;code&gt;initialize&lt;/code&gt;/&lt;code&gt;session/new&lt;/code&gt; answers, the Node 22.11
exit and its explanation, and the preamble:
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI/blob/main/packages/core/src/agents/deepseek-acp.ts" rel="noopener noreferrer"&gt;&lt;code&gt;packages/core/src/agents/deepseek-acp.ts&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The decision, the live findings and what was left out: the archived change,
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI/blob/main/openspec/changes/archive/2026-09-22-deepseek-joins-as-an-acp-agent/proposal.md" rel="noopener noreferrer"&gt;&lt;code&gt;deepseek-joins-as-an-acp-agent&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The agent table and the ten agents:
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI/blob/main/README.md" rel="noopener noreferrer"&gt;README.md, "Agent Selection"&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;That it reports no usage, and what that means for a spending ceiling:
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI/blob/main/HARNESS.md" rel="noopener noreferrer"&gt;HARNESS.md&lt;/a&gt;,
the agent capability table and "needs a Node newer than 22.11".&lt;/li&gt;
&lt;li&gt;The 22-second implement run: &lt;code&gt;HARNESS.md&lt;/code&gt;'s own row for &lt;code&gt;deepseek-cli-acp&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>openspec</category>
      <category>ai</category>
      <category>deepseek</category>
      <category>typescript</category>
    </item>
    <item>
      <title>A team works through git</title>
      <dc:creator>Alexander Ivanov</dc:creator>
      <pubDate>Sun, 27 Sep 2026 02:34:12 +0000</pubDate>
      <link>https://dev.to/someone_somewhere_05cad9e/a-team-works-through-git-32cg</link>
      <guid>https://dev.to/someone_somewhere_05cad9e/a-team-works-through-git-32cg</guid>
      <description>&lt;p&gt;&lt;em&gt;First published on &lt;a href="https://openspec-ui.dev/articles/a-team-works-through-git/" rel="noopener noreferrer"&gt;openspec-ui.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every pitch for team features reaches for the same two things first: a&lt;br&gt;
server, and a database. OpenSpec Workbench now answers three questions a&lt;br&gt;
team actually asks - whose change is this, why did it go back a step, how&lt;br&gt;
long did it spend in each step - and it does it with neither.&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%2F25q6v9o09ka1gasbyoyw.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%2F25q6v9o09ka1gasbyoyw.png" alt="The Pipeline arranged by stage: Proposed, Planned, In progress, In review, Landed, Archived, each a column, with a toggle between this arrangement and the order changes declare" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The three questions
&lt;/h2&gt;

&lt;p&gt;The repository already had a team, even if the product did not know it:&lt;br&gt;
the owner, the agents that run changes, and a second agent that writes&lt;br&gt;
these articles. Three questions kept coming back, and nothing answered&lt;br&gt;
them. Whose change is this, and who is doing it right now. Why did it go&lt;br&gt;
back a step, and who sent it back. How long did it spend in each step,&lt;br&gt;
counting every time it visited.&lt;/p&gt;

&lt;p&gt;The answer, decided on 2026-09-22 and written down as ADR 0037: team work,&lt;br&gt;
with no server and no database, git and the forge as the only shared&lt;br&gt;
truth.&lt;/p&gt;
&lt;h2&gt;
  
  
  People are files, and joining is a pull request
&lt;/h2&gt;

&lt;p&gt;Each person on a team gets one file, &lt;code&gt;openspec/people/&amp;lt;handle&amp;gt;.json&lt;/code&gt;: a&lt;br&gt;
handle, a display name, one public key per machine they sign on, and&lt;br&gt;
optionally the git e-mail addresses that are theirs. Joining writes this&lt;br&gt;
file. Nothing is committed on its own - joining is the pull request that&lt;br&gt;
carries the file, the same way any other change reaches the repository.&lt;/p&gt;

&lt;p&gt;A key is never removed, only retired with a date. What it signed before&lt;br&gt;
keeps verifying for as long as the history is kept, which is for good. The&lt;br&gt;
merge gate refuses a pull request that takes a person or a key out,&lt;br&gt;
replaces a key, or edits a retirement already recorded - the same kind of&lt;br&gt;
refusal that already guards a change's specs.&lt;/p&gt;
&lt;h2&gt;
  
  
  History is signed events, one file per event
&lt;/h2&gt;

&lt;p&gt;A change has an Owner, who answers for it, and an Implementer, who does&lt;br&gt;
the work, by hand or through agents. An agent is never either one: it acts&lt;br&gt;
for a person and signs with that person's key, and every record of what it&lt;br&gt;
did names it as an agent, not as the person.&lt;/p&gt;

&lt;p&gt;Who holds a change is played forward from its history, kept as one signed&lt;br&gt;
file per event in &lt;code&gt;openspec/changes/&amp;lt;id&amp;gt;/history/&lt;/code&gt;. The events are a&lt;br&gt;
closed list: &lt;code&gt;owner-set&lt;/code&gt;, &lt;code&gt;implementer-set&lt;/code&gt;, and &lt;code&gt;sent-back&lt;/code&gt;, which carries&lt;br&gt;
the stage it returns to, the reason, and every task item it reopens with&lt;br&gt;
why. One file per event, rather than one shared file for the whole team,&lt;br&gt;
is a small engineering decision with a real payoff: two branches never&lt;br&gt;
edit the same file, so a merge on this never conflicts.&lt;/p&gt;

&lt;p&gt;The reason in a &lt;code&gt;sent-back&lt;/code&gt; event is shown as plain text, never run - the&lt;br&gt;
same rule the rest of this product holds for everything a repository's own&lt;br&gt;
contents might say.&lt;/p&gt;
&lt;h2&gt;
  
  
  Stages are derived, never declared
&lt;/h2&gt;

&lt;p&gt;This is the same argument the project has made about a change's state&lt;br&gt;
since its first months, applied one layer up. A change's stage - Proposed,&lt;br&gt;
Planned, In progress, In review, Landed, Archived - is never set by a&lt;br&gt;
person or a button. Each is proved by a dated fact: the commit that adds&lt;br&gt;
&lt;code&gt;proposal.md&lt;/code&gt;, the commit that adds &lt;code&gt;tasks.md&lt;/code&gt;, a closed task line or a&lt;br&gt;
run, a pull request opening, its merge, the archive commit. A &lt;code&gt;sent-back&lt;/code&gt;&lt;br&gt;
event moves a change back to a named stage, and after that only a fact&lt;br&gt;
newer than the event moves it on again - so a change can visit a stage more&lt;br&gt;
than once, and every visit is kept.&lt;/p&gt;

&lt;p&gt;Getting the times right meant asking three different forges the same&lt;br&gt;
question. The pull request's creation and merge times now come from&lt;br&gt;
whichever one &lt;code&gt;origin&lt;/code&gt; is on: GitHub, through &lt;code&gt;gh&lt;/code&gt; or its own API, GitLab,&lt;br&gt;
or Gitea - built on the same &lt;code&gt;Forge&lt;/code&gt; interface this project described&lt;br&gt;
&lt;a href="https://openspec-ui.dev/articles/one-interface-three-forges/" rel="noopener noreferrer"&gt;two articles ago&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  The board
&lt;/h2&gt;

&lt;p&gt;The Pipeline already drew every active change as a card. It now offers a&lt;br&gt;
second arrangement of the same cards: &lt;strong&gt;By step&lt;/strong&gt;, the order changes&lt;br&gt;
declare, and &lt;strong&gt;By stage&lt;/strong&gt;, a column per stage from Proposed to Archived.&lt;br&gt;
There are no lines between cards on the board - a stage says where a&lt;br&gt;
change is, not what it waits for - and every card says who owns it and who&lt;br&gt;
implements it, in either arrangement. Both hosts show the same board,&lt;br&gt;
because both read the same core function, and the choice between them is&lt;br&gt;
kept for the next visit.&lt;/p&gt;
&lt;h2&gt;
  
  
  What this deliberately does not do yet
&lt;/h2&gt;

&lt;p&gt;The ADR is explicit about what it leaves for later, and only if people ask&lt;br&gt;
for it: a server or a database (ruled out on purpose, not postponed), board&lt;br&gt;
columns of the team's own choosing, transition policies such as&lt;br&gt;
work-in-progress limits or required approvals, reports beyond time in&lt;br&gt;
stage, one-way sync to an outside board, a plugin API, and licensing. A&lt;br&gt;
paid plugin, if one ever comes, would build on the facts this records and&lt;br&gt;
change none of them.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The code is at&lt;br&gt;
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI" rel="noopener noreferrer"&gt;github.com/VeryComplexAndLongName/OpenSpec-UI&lt;/a&gt;,&lt;br&gt;
where the repository and packages keep the name OpenSpec-UI.&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 start &lt;span class="nt"&gt;--workspace&lt;/span&gt; @openspec-ui/cli &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt; &lt;span class="nt"&gt;--handle&lt;/span&gt; ada &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"Ada Lovelace"&lt;/span&gt; &lt;span class="nt"&gt;--cwd&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>openspec</category>
      <category>git</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
    <item>
      <title>One interface, three forges</title>
      <dc:creator>Alexander Ivanov</dc:creator>
      <pubDate>Sat, 26 Sep 2026 02:29:20 +0000</pubDate>
      <link>https://dev.to/someone_somewhere_05cad9e/one-interface-three-forges-2k8f</link>
      <guid>https://dev.to/someone_somewhere_05cad9e/one-interface-three-forges-2k8f</guid>
      <description>&lt;p&gt;&lt;em&gt;First published on &lt;a href="https://openspec-ui.dev/articles/one-interface-three-forges/" rel="noopener noreferrer"&gt;openspec-ui.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Until this week, OpenSpec Workbench knew one way to open a pull request,&lt;br&gt;
check it, and merge it: &lt;code&gt;gh&lt;/code&gt;, GitHub's own CLI. If your repository lived on&lt;br&gt;
GitLab or Gitea, or if &lt;code&gt;gh&lt;/code&gt; simply was not installed, the archive stage said&lt;br&gt;
so and stopped. That is fixed now, on all three, and the way it got fixed is&lt;br&gt;
the more interesting part.&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%2Ff9zc7sb0wfp8wrkidvtd.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%2Ff9zc7sb0wfp8wrkidvtd.png" alt="Your repository's origin decides which forge answers: GitHub, GitLab or another host probed for Gitea, all behind one Forge interface" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The interface, not the tool
&lt;/h2&gt;

&lt;p&gt;The fix is not "support GitLab too" bolted onto the GitHub path. It is one&lt;br&gt;
&lt;code&gt;Forge&lt;/code&gt; interface - list a pull request by branch, open one, ask for a merge,&lt;br&gt;
read its checks - that the &lt;code&gt;git&lt;/code&gt; stage and the archive pass call without&lt;br&gt;
knowing which host answers. Three implementations sit behind it: GitHub's&lt;br&gt;
own REST and GraphQL, GitLab's REST API, and Gitea's. Which one runs is&lt;br&gt;
decided once, by reading the repository's own &lt;code&gt;origin&lt;/code&gt;: github.com is&lt;br&gt;
GitHub, gitlab.com is GitLab, and anything else is probed - Gitea's&lt;br&gt;
&lt;code&gt;/api/v1/version&lt;/code&gt; first, then GitLab's &lt;code&gt;/api/v4/version&lt;/code&gt; - so a self-hosted&lt;br&gt;
instance is found without being told what it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The token decides the way, even for GitHub
&lt;/h2&gt;

&lt;p&gt;GitHub is the one host that had two paths from the start: &lt;code&gt;gh&lt;/code&gt;, or now its&lt;br&gt;
own API when &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; or &lt;code&gt;GH_TOKEN&lt;/code&gt; (the same variable &lt;code&gt;gh&lt;/code&gt; itself&lt;br&gt;
reads) is set in the environment. Without one, the product goes through&lt;br&gt;
&lt;code&gt;gh&lt;/code&gt; exactly as before - this did not become a breaking change for anyone&lt;br&gt;
already running it. Where neither a token nor &lt;code&gt;gh&lt;/code&gt; is available, the&lt;br&gt;
reading says so plainly: "gh is not installed, and GITHUB_TOKEN is not&lt;br&gt;
set", rather than failing on a command that was never going to work.&lt;/p&gt;

&lt;h2&gt;
  
  
  What running it against real hosts found
&lt;/h2&gt;

&lt;p&gt;Reading a REST API's documentation and calling it in anger are two&lt;br&gt;
different exercises, and this is where the honest part of the story is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gitea&lt;/strong&gt; was tested live on 1.26.4, in a throwaway repository deleted&lt;br&gt;
after each run. Two behaviours needed handling that no amount of reading&lt;br&gt;
would have surfaced: a repository with a single branch answers a pull&lt;br&gt;
request listing with 404 rather than an empty list, and a merged pull&lt;br&gt;
request's head can report a label naming a branch that no longer exists.&lt;br&gt;
Handled once, both stay handled everywhere Gitea is the forge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitLab&lt;/strong&gt; was tested live on gitlab.com, in a throwaway private project.&lt;br&gt;
The first token given for it was fine-grained without quite enough scope,&lt;br&gt;
and GitLab said so plainly (&lt;code&gt;insufficient_granular_scope&lt;/code&gt;) rather than&lt;br&gt;
failing silently. Once a token with the right scope was in place, the&lt;br&gt;
first merge attempt was refused with a 422, "Branch cannot be merged" -&lt;br&gt;
not because it could not be merged, but because GitLab had not yet finished&lt;br&gt;
deciding whether it could. The forge now waits and asks again before&lt;br&gt;
believing a 422. On both hosts, once that was in place, the full path ran&lt;br&gt;
end to end with the real archive command: it found the finished change,&lt;br&gt;
opened a pull request, watched it merge by itself, and the repository held&lt;br&gt;
the archived change afterward, spec applied.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub's own API&lt;/strong&gt; was tested live too, on 2026-09-22, with &lt;code&gt;gh&lt;/code&gt;'s own&lt;br&gt;
token handed to the process as &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; and &lt;code&gt;gh&lt;/code&gt; itself kept off the&lt;br&gt;
&lt;code&gt;PATH&lt;/code&gt; - so there was no fallback to quietly catch a mistake. Against this&lt;br&gt;
repository it read 147 pull requests and a real check run as a pass,&lt;br&gt;
read-only. Against a fresh throwaway repository, the first automatic merge&lt;br&gt;
was refused outright: "Auto merge is not allowed for this repository",&lt;br&gt;
GitHub's own setting on a brand-new repo. The archive pass left the pull&lt;br&gt;
request open and said why, exactly as the project's own rule requires&lt;br&gt;
rather than pretending the merge had happened. Turning the setting on let&lt;br&gt;
the same request merge by squash. A second pull request, opened to test&lt;br&gt;
what the &lt;code&gt;git&lt;/code&gt; stage's own gateway does with no checks configured at all,&lt;br&gt;
correctly read "no check result was available" and declined to merge -&lt;br&gt;
absence of information is not the same as a green light.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does not cover
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GitHub Enterprise Server&lt;/strong&gt; is not detected as its own case. A host that&lt;br&gt;
answers neither Gitea's nor GitLab's version probe is assumed to be GitHub&lt;br&gt;
and handled through &lt;code&gt;gh&lt;/code&gt;, which already knows how to reach a GitHub host of&lt;br&gt;
its own. &lt;strong&gt;The allowlist that gates what the &lt;code&gt;git&lt;/code&gt; stage may push, create or&lt;br&gt;
merge&lt;/strong&gt; still speaks in &lt;code&gt;gh&lt;/code&gt;'s own terms - the remote and the branches it&lt;br&gt;
names - regardless of which forge actually does the work underneath.&lt;/p&gt;

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

&lt;p&gt;The code is at&lt;br&gt;
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI" rel="noopener noreferrer"&gt;github.com/VeryComplexAndLongName/OpenSpec-UI&lt;/a&gt;,&lt;br&gt;
where the repository and packages keep the name OpenSpec-UI. The core this&lt;br&gt;
rests on is described in&lt;br&gt;
&lt;a href="https://openspec-ui.dev/articles/one-core-two-hosts/" rel="noopener noreferrer"&gt;One core, two hosts&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>openspec</category>
      <category>git</category>
      <category>gitlab</category>
      <category>gitea</category>
    </item>
    <item>
      <title>One core, two hosts</title>
      <dc:creator>Alexander Ivanov</dc:creator>
      <pubDate>Thu, 24 Sep 2026 05:33:56 +0000</pubDate>
      <link>https://dev.to/someone_somewhere_05cad9e/one-core-two-hosts-3dai</link>
      <guid>https://dev.to/someone_somewhere_05cad9e/one-core-two-hosts-3dai</guid>
      <description>&lt;p&gt;&lt;em&gt;First published on &lt;a href="https://openspec-ui.dev/articles/one-core-two-hosts/" rel="noopener noreferrer"&gt;openspec-ui.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;OpenSpec Workbench ships in two forms: a VS Code extension and a standalone&lt;br&gt;
web application that runs on your machine. They show the same OpenSpec and Git&lt;br&gt;
data and run the same workflows. The first architectural decision was how to&lt;br&gt;
stop them from becoming two different products, because two deliveries of "the&lt;br&gt;
same" behaviour diverge, and they do it quietly.&lt;/p&gt;

&lt;p&gt;The answer was to write the behaviour once and let each host be a thin adapter&lt;br&gt;
around it. This is what that looks like, what was turned down, and where "thin"&lt;br&gt;
turned out to cost something.&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%2F5re2a01v96xq26a2dmld.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%2F5re2a01v96xq26a2dmld.png" alt="The shared core with the server, the extension and the command line as adapters around it, and the shared UI between the two hosts" width="799" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The decision
&lt;/h2&gt;

&lt;p&gt;Five packages, one of them holding all of the behaviour:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;core&lt;/code&gt; owns execution, OpenSpec and Git integration, security, persistence
and the derived state of a change.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;webui&lt;/code&gt; holds the React components, written so they do not know how they are
reached.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;server&lt;/code&gt; and &lt;code&gt;extension&lt;/code&gt; are the two hosts, and &lt;code&gt;cli&lt;/code&gt; is a third,
non-interactive one for CI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The protocol began as five commands (&lt;code&gt;plan&lt;/code&gt;, &lt;code&gt;implement&lt;/code&gt;, &lt;code&gt;review&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;status&lt;/code&gt; and &lt;code&gt;cancel&lt;/code&gt;) and seven events (&lt;code&gt;started&lt;/code&gt;, &lt;code&gt;stdout&lt;/code&gt;, &lt;code&gt;stderr&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;progress&lt;/code&gt;, &lt;code&gt;completed&lt;/code&gt;, &lt;code&gt;failed&lt;/code&gt; and &lt;code&gt;cancelled&lt;/code&gt;), and it has grown since,&lt;br&gt;
with events such as &lt;code&gt;checkpoint&lt;/code&gt; and &lt;code&gt;permissionRequest&lt;/code&gt;. It is defined in&lt;br&gt;
&lt;code&gt;core&lt;/code&gt; and nowhere else. A host serialises it and does not reimplement any of the&lt;br&gt;
execution behind it.&lt;/p&gt;

&lt;p&gt;Security is in the core too, from the start and not as a later addition. Every&lt;br&gt;
run is restricted to the workspace, commands and their arguments are&lt;br&gt;
allowlisted, executions are audited, and the contents of the repository are&lt;br&gt;
treated as data, never as instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What was rejected
&lt;/h2&gt;

&lt;p&gt;Three alternatives were written down and refused.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Running the standalone server inside the extension.&lt;/strong&gt; It would have made both&lt;br&gt;
hosts share one transport, but the extension host already runs Node and needs no&lt;br&gt;
HTTP for ordinary work. Dynamic ports, window collisions, authentication and&lt;br&gt;
process clean-up would have burdened the most common workflow. So the extension&lt;br&gt;
imports the core directly and talks to its webview over a message bridge, and&lt;br&gt;
the local server stays an optional mode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementing execution separately in each host.&lt;/strong&gt; Streaming, cancellation,&lt;br&gt;
errors and security would have drifted apart. Both hosts adapt the same&lt;br&gt;
protocol instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Storing a change's state in &lt;code&gt;.openspec.yaml&lt;/code&gt;.&lt;/strong&gt; That would have extended a&lt;br&gt;
format that belongs to OpenSpec. Draft, in progress, implemented and archived&lt;br&gt;
are inferred from where a change sits and from its &lt;code&gt;tasks.md&lt;/code&gt;, by a heuristic&lt;br&gt;
in the core, so the tool never forks the format it depends on.&lt;/p&gt;

&lt;p&gt;The delivery model was also reviewed independently after the first proposal,&lt;br&gt;
and that review changed the recommendation for the extension's transport while&lt;br&gt;
keeping the shared core.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it bought
&lt;/h2&gt;

&lt;p&gt;A defect is fixed once, in the core, which depends on neither HTTP nor the VS&lt;br&gt;
Code API. The run status record that the Pipeline draws on a card is the same&lt;br&gt;
record &lt;code&gt;openspec-ui-cli status&lt;/code&gt; prints, whichever host started the run. A new&lt;br&gt;
agent is one adapter in the core's registry, and both hosts see it.&lt;/p&gt;

&lt;p&gt;One choice in that registry is worth naming. The plain agent adapters treat a&lt;br&gt;
CLI's output as opaque text on purpose, so that a change in a CLI's output&lt;br&gt;
format between versions cannot break the event stream. The price is that they&lt;br&gt;
cannot see or gate a single action mid-run, which is what the adapters that&lt;br&gt;
speak the Agent Client Protocol were added for, beside the plain ones and not in&lt;br&gt;
place of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where "thin" was not free
&lt;/h2&gt;

&lt;p&gt;A thin adapter is still an adapter, and each host has to route each command.&lt;/p&gt;

&lt;p&gt;When an agent asked for permission in the middle of a chain, the chain had no&lt;br&gt;
way to receive the answer. The core routed &lt;code&gt;cancel&lt;/code&gt; to the stage in flight but&lt;br&gt;
not &lt;code&gt;resolvePermission&lt;/code&gt;. The fix was in the core, and both hosts gained the matching branch. The run&lt;br&gt;
did not fail. It waited.&lt;/p&gt;

&lt;p&gt;So the rule is narrower than "hosts contain no logic". Hosts contain no&lt;br&gt;
behaviour, but each of them still has to carry every command to the core, and a&lt;br&gt;
command that one host forgets to carry is invisible until somebody uses it.&lt;br&gt;
The project requires contract tests between the shared UI and the server before&lt;br&gt;
a change is archived, for that reason.&lt;/p&gt;

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

&lt;p&gt;The code is at&lt;br&gt;
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI" rel="noopener noreferrer"&gt;github.com/VeryComplexAndLongName/OpenSpec-UI&lt;/a&gt;,&lt;br&gt;
where the repository and packages keep the name OpenSpec-UI. A short tour of&lt;br&gt;
what it does is in&lt;br&gt;
&lt;a href="https://openspec-ui.dev/articles/supervise-agents-on-openspec-changes/" rel="noopener noreferrer"&gt;Supervise agents on OpenSpec changes&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>openspec</category>
      <category>architecture</category>
      <category>vscode</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Supervise the agents that build your OpenSpec changes</title>
      <dc:creator>Alexander Ivanov</dc:creator>
      <pubDate>Thu, 24 Sep 2026 05:28:47 +0000</pubDate>
      <link>https://dev.to/someone_somewhere_05cad9e/supervise-the-agents-that-build-your-openspec-changes-5fb9</link>
      <guid>https://dev.to/someone_somewhere_05cad9e/supervise-the-agents-that-build-your-openspec-changes-5fb9</guid>
      <description>&lt;p&gt;&lt;em&gt;First published on &lt;a href="https://openspec-ui.dev/articles/supervise-agents-on-openspec-changes/" rel="noopener noreferrer"&gt;openspec-ui.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;OpenSpec gives an agent something to build from: a proposal, a design, a list&lt;br&gt;
of tasks, and the spec deltas the change will leave behind. What it does not&lt;br&gt;
give you is a way to see the agent while it works.&lt;/p&gt;

&lt;p&gt;Several tools draw OpenSpec changes as boards and lists, and they do it well.&lt;br&gt;
Read on 2026-09-20 in their own words, none of the three I compared starts an&lt;br&gt;
agent. OpenSpec Workbench does: it runs an agent CLI on a change, says what&lt;br&gt;
the run is doing while it does it, and lets a person stop it. This is a short&lt;br&gt;
tour of how, and of what it will not promise.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhb9mmcjtehhbujvpzo1z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhb9mmcjtehhbujvpzo1z.gif" alt="A run started from a change's card, stopping at a checkpoint, and a stop asked for with a reason" width="799" height="562"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  A change becomes a card
&lt;/h2&gt;

&lt;p&gt;The Pipeline draws every active change in the order the changes declare, with&lt;br&gt;
what a live run last said and what can start alongside what. A card is where&lt;br&gt;
you act: it starts a run, answers a checkpoint, and asks a run to stop, with a&lt;br&gt;
reason. The same Pipeline is in the standalone web application and in the VS&lt;br&gt;
Code extension, and both read the same shared core.&lt;/p&gt;

&lt;p&gt;A run is a chain of stages: propose, review, apply, verify, archive, git. You&lt;br&gt;
choose the agent for each stage, and where the chain pauses for you.&lt;/p&gt;
&lt;h2&gt;
  
  
  What a run says it is doing
&lt;/h2&gt;

&lt;p&gt;Every run writes a status record: whose it is, where it runs, what it last&lt;br&gt;
said it was doing and how long ago. The Pipeline draws it on the card, and&lt;br&gt;
&lt;code&gt;openspec-ui-cli status&lt;/code&gt; prints it for every run of the repository, whichever&lt;br&gt;
host started it.&lt;/p&gt;

&lt;p&gt;It never says a run is stuck. A silent agent and a hung one look identical,&lt;br&gt;
and telling them apart is a person's judgement, so the tool leaves that call&lt;br&gt;
to you and gives you the last thing the run said and its age.&lt;/p&gt;

&lt;p&gt;Changes can run side by side. Each one can have its own git worktree, guarded&lt;br&gt;
by a lease, and &lt;code&gt;openspec-ui-cli ready&lt;/code&gt; says which ready changes can start&lt;br&gt;
alongside which, and why the others cannot.&lt;/p&gt;
&lt;h2&gt;
  
  
  Stop it where its work is sound
&lt;/h2&gt;

&lt;p&gt;A card's Stop asks for a reason. The request is signed with the machine's key.&lt;br&gt;
The run reads it at its next renewal and acts only if it is verified and&lt;br&gt;
fresh, and it stops where its work is sound. From a terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openspec-ui-cli stop &amp;lt;instanceId&amp;gt; &lt;span class="nt"&gt;--reason&lt;/span&gt; &lt;span class="s2"&gt;"wrong branch"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--after &amp;lt;task&amp;gt;&lt;/code&gt; lets the run finish a named task first and stops at the next&lt;br&gt;
sound point after it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Your agent, per stage
&lt;/h2&gt;

&lt;p&gt;The picker drives the agent CLIs you already have: Claude CLI, GitHub Copilot&lt;br&gt;
CLI, Codex CLI, Gemini CLI, DeepSeek CLI, and a local model behind an&lt;br&gt;
OpenAI-compatible endpoint. The CLI-based ones also come in a variant that&lt;br&gt;
speaks the Agent Client Protocol, which carries structured progress instead of&lt;br&gt;
scraped text. The tool never handles an API key: each CLI keeps its own login.&lt;/p&gt;

&lt;p&gt;Here is what has actually been run. Claude CLI and Copilot CLI have been run&lt;br&gt;
against the real binaries, and so has DeepSeek CLI over ACP, on Node 22.18+ or&lt;br&gt;
24.2+. Codex and Gemini never have, raw or over ACP: their adapters are&lt;br&gt;
written to the vendors' documented interfaces and tested against a mocked&lt;br&gt;
peer, and if either misbehaves for you, that is the likeliest reason and a&lt;br&gt;
report would be useful. Two ACP caveats are worth knowing before you choose&lt;br&gt;
one: the Claude adapter never asks for permission, and &lt;code&gt;copilot --acp&lt;/code&gt;&lt;br&gt;
completed file writes and shell commands here without asking either.&lt;/p&gt;
&lt;h2&gt;
  
  
  Checkpoints, ceilings and a record
&lt;/h2&gt;

&lt;p&gt;Where a person decides is configuration, and the runner enforces it: an&lt;br&gt;
autonomy level, checkpoints between stages, a review gate that only a change's&lt;br&gt;
own settings can relax, and tasks marked as human-only or delegated to a named&lt;br&gt;
agent. Each stage has its own spending cap in the unit its agent honours, each&lt;br&gt;
chain has a ceiling, and every run lands in an audit log. The project also&lt;br&gt;
states plainly which limits do not exist, in a document of their own.&lt;/p&gt;

&lt;p&gt;The Workbench ships 17 change templates, for things like a Vite migration, a&lt;br&gt;
production Dockerfile, an authentication middleware or a testing baseline, so&lt;br&gt;
a new change can start from a proposal that already has the right shape.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;In VS Code, install it from the Marketplace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code &lt;span class="nt"&gt;--install-extension&lt;/span&gt; openspec-ui.openspec-ui-vscode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or run the standalone application from a clone of the repository:&lt;br&gt;
&lt;/p&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;npm run build &lt;span class="nt"&gt;--workspace&lt;/span&gt; @openspec-ui/server
npm run start &lt;span class="nt"&gt;--workspace&lt;/span&gt; @openspec-ui/server &lt;span class="nt"&gt;--&lt;/span&gt; &amp;lt;workspaceRoot&amp;gt; 4317
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It prints a URL with a one-time token; open that exact URL. Everything runs on&lt;br&gt;
your machine, against your own agent CLIs.&lt;/p&gt;

&lt;p&gt;The repository, the packages and the extension are still called OpenSpec-UI;&lt;br&gt;
the product's name is OpenSpec Workbench. The code and the issues are at&lt;br&gt;
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI" rel="noopener noreferrer"&gt;github.com/VeryComplexAndLongName/OpenSpec-UI&lt;/a&gt;,&lt;br&gt;
and I would like to hear from anyone who tries it, above all from people who&lt;br&gt;
run Codex or Gemini, which I have not been able to.&lt;/p&gt;

</description>
      <category>openspec</category>
      <category>ai</category>
      <category>vscode</category>
      <category>opensource</category>
    </item>
    <item>
      <title>A viewer is not a cockpit</title>
      <dc:creator>Alexander Ivanov</dc:creator>
      <pubDate>Thu, 24 Sep 2026 05:28:47 +0000</pubDate>
      <link>https://dev.to/someone_somewhere_05cad9e/a-viewer-is-not-a-cockpit-31ao</link>
      <guid>https://dev.to/someone_somewhere_05cad9e/a-viewer-is-not-a-cockpit-31ao</guid>
      <description>&lt;p&gt;&lt;em&gt;First published on &lt;a href="https://openspec-ui.dev/articles/a-viewer-is-not-a-cockpit/" rel="noopener noreferrer"&gt;openspec-ui.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Spec-driven development gives a coding agent a brief: a proposal, a design, a&lt;br&gt;
list of tasks. There are already several good ways to read that brief. Boards,&lt;br&gt;
dashboards and editor views show a change's documents and where it stands. I&lt;br&gt;
read three of them on 2026-09-20, in their own words, and none of the three&lt;br&gt;
starts an agent.&lt;/p&gt;

&lt;p&gt;That is a fine thing for a viewer to be. But the moment an agent runs, the&lt;br&gt;
questions change. Not "what does the change say?" but "what is it doing now,&lt;br&gt;
what will it cost, and how do I stop it?" A viewer has no answer to those,&lt;br&gt;
because it is not in the loop. A cockpit is.&lt;/p&gt;

&lt;p&gt;I am building one, OpenSpec Workbench, and most of what I know about what a&lt;br&gt;
cockpit needs I learned from it getting things wrong. Three of those mistakes&lt;br&gt;
are worth writing down.&lt;/p&gt;

&lt;h2&gt;
  
  
  A run that hangs tells you less than one that fails
&lt;/h2&gt;

&lt;p&gt;An agent asked for permission in the middle of a chain. The chain had no way to&lt;br&gt;
answer. The request was routed to nobody, so the run did not fail and did not&lt;br&gt;
time out. It waited, on a promise that nothing in the system could resolve.&lt;/p&gt;

&lt;p&gt;The fix was to route the answer to the stage in flight, and, where a chain runs&lt;br&gt;
fully autonomously with nobody to ask, to fail the stage with a stated reason&lt;br&gt;
instead of waiting on a channel that does not exist. Failure is information.&lt;br&gt;
Hanging is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  A limit that cannot act reads as protection
&lt;/h2&gt;

&lt;p&gt;A spending ceiling can be configured, saved, accepted by validation and never&lt;br&gt;
fire. It counts only what an agent reports, and of the ten agents the tool&lt;br&gt;
supports, six report no usage at all. Over those six a spending ceiling counts&lt;br&gt;
nothing.&lt;/p&gt;

&lt;p&gt;Two facts about ceilings are easy to assume away. A spending ceiling can stop&lt;br&gt;
the next stage from starting, but it cannot interrupt the stage that is&lt;br&gt;
already running, because a run's cost is not known until it ends. Only a time&lt;br&gt;
ceiling can. And a run that fails may record nothing, so a ceiling protects you&lt;br&gt;
from a long successful run, not from a sequence of expensive failures.&lt;/p&gt;

&lt;p&gt;So the tool says which of a change's ceilings cannot act, where the&lt;br&gt;
configuration is edited and before the run starts:&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%2Fgip4nlq5i2qwmizai7ca.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%2Fgip4nlq5i2qwmizai7ca.png" alt="The run dialog for a change, with a section headed " width="800" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Silence is not a diagnosis
&lt;/h2&gt;

&lt;p&gt;An agent that has said nothing for ten minutes might be thinking, or might be&lt;br&gt;
hung. From outside the two look identical. A tool that draws a red "stuck"&lt;br&gt;
badge is guessing, and a guess that looks like a measurement is worse than&lt;br&gt;
none.&lt;/p&gt;

&lt;p&gt;So the Workbench never says a run is stuck. It says what the run last said it&lt;br&gt;
was doing, and how long ago. Telling a long turn from a hang is a person's&lt;br&gt;
judgement, and the tool leaves it there.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a cockpit has to do
&lt;/h2&gt;

&lt;p&gt;Those three come down to four obligations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Say what it will do before it does it.&lt;/strong&gt; Which agent runs each stage, which
setting it read, and which limits will not act.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Say what it is doing while it does it.&lt;/strong&gt; The stage, the last thing said, how
long ago.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stop where the work is sound.&lt;/strong&gt; A stop asks for a reason, is signed with the
machine's key, and is honoured only if it is verified and fresh.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Say why it stopped.&lt;/strong&gt; A run that hits a time ceiling ends as cancelled, with
the reason naming the ceiling and its value, so a rule firing is not mistaken
for a person's click, or for a failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of that is about agents being smarter. It is about a tool being answerable&lt;br&gt;
for what it is doing with your time and money.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it still does not do
&lt;/h2&gt;

&lt;p&gt;Claude CLI and Copilot CLI have been run against the real binaries. Codex and&lt;br&gt;
Gemini never have: their adapters follow the vendors' documented interfaces and&lt;br&gt;
are tested against a mocked peer, and a report from anyone who runs them would&lt;br&gt;
be useful. Two ACP caveats: the Claude adapter never asks for permission, and&lt;br&gt;
&lt;code&gt;copilot --acp&lt;/code&gt; completed file writes and shell commands here without asking.&lt;/p&gt;

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

&lt;p&gt;OpenSpec Workbench is a VS Code extension and a local web application, both over&lt;br&gt;
the same core. There is a short tour of it in&lt;br&gt;
&lt;a href="https://openspec-ui.dev/articles/supervise-agents-on-openspec-changes/" rel="noopener noreferrer"&gt;Supervise the agents that build your OpenSpec changes&lt;/a&gt;.&lt;br&gt;
The code and the issues are at&lt;br&gt;
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI" rel="noopener noreferrer"&gt;github.com/VeryComplexAndLongName/OpenSpec-UI&lt;/a&gt;,&lt;br&gt;
where the repository and packages keep the name OpenSpec-UI.&lt;/p&gt;

</description>
      <category>openspec</category>
      <category>ai</category>
      <category>vscode</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Supervise the agents that build your OpenSpec changes</title>
      <dc:creator>Alexander Ivanov</dc:creator>
      <pubDate>Sun, 20 Sep 2026 13:03:51 +0000</pubDate>
      <link>https://dev.to/someone_somewhere_05cad9e/supervise-the-agents-that-build-your-openspec-changes-c04</link>
      <guid>https://dev.to/someone_somewhere_05cad9e/supervise-the-agents-that-build-your-openspec-changes-c04</guid>
      <description>&lt;p&gt;First published on &lt;a href="https://openspec-ui.dev/articles/supervise-agents-on-openspec-changes/" rel="noopener noreferrer"&gt;openspec-ui.dev&lt;/a&gt;.*&lt;/p&gt;

&lt;p&gt;OpenSpec gives an agent something to build from: a proposal, a design, a list&lt;br&gt;
of tasks, and the spec deltas the change will leave behind. What it does not&lt;br&gt;
give you is a way to see the agent while it works.&lt;/p&gt;

&lt;p&gt;Several tools draw OpenSpec changes as boards and lists, and they do it well.&lt;br&gt;
Read on 2026-09-20 in their own words, none of the three I compared starts an&lt;br&gt;
agent. OpenSpec Workbench does: it runs an agent CLI on a change, says what&lt;br&gt;
the run is doing while it does it, and lets a person stop it. This is a short&lt;br&gt;
tour of how, and of what it will not promise.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm1d5w1hbc08qtns0t7rx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm1d5w1hbc08qtns0t7rx.gif" alt="A run started from a change's card, stopping at a checkpoint, and a stop asked for with a reason" width="799" height="562"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  A change becomes a card
&lt;/h2&gt;

&lt;p&gt;The Pipeline draws every active change in the order the changes declare, with&lt;br&gt;
what a live run last said and what can start alongside what. A card is where&lt;br&gt;
you act: it starts a run, answers a checkpoint, and asks a run to stop, with a&lt;br&gt;
reason. The same Pipeline is in the standalone web application and in the VS&lt;br&gt;
Code extension, and both read the same shared core.&lt;/p&gt;

&lt;p&gt;A run is a chain of stages: propose, review, apply, verify, archive, git. You&lt;br&gt;
choose the agent for each stage, and where the chain pauses for you.&lt;/p&gt;
&lt;h2&gt;
  
  
  What a run says it is doing
&lt;/h2&gt;

&lt;p&gt;Every run writes a status record: whose it is, where it runs, what it last&lt;br&gt;
said it was doing and how long ago. The Pipeline draws it on the card, and&lt;br&gt;
&lt;code&gt;openspec-ui-cli status&lt;/code&gt; prints it for every run of the repository, whichever&lt;br&gt;
host started it.&lt;/p&gt;

&lt;p&gt;It never says a run is stuck. A silent agent and a hung one look identical,&lt;br&gt;
and telling them apart is a person's judgement, so the tool leaves that call&lt;br&gt;
to you and gives you the last thing the run said and its age.&lt;/p&gt;

&lt;p&gt;Changes can run side by side. Each one can have its own git worktree, guarded&lt;br&gt;
by a lease, and &lt;code&gt;openspec-ui-cli ready&lt;/code&gt; says which ready changes can start&lt;br&gt;
alongside which, and why the others cannot.&lt;/p&gt;
&lt;h2&gt;
  
  
  Stop it where its work is sound
&lt;/h2&gt;

&lt;p&gt;A card's Stop asks for a reason. The request is signed with the machine's key.&lt;br&gt;
The run reads it at its next renewal and acts only if it is verified and&lt;br&gt;
fresh, and it stops where its work is sound. From a terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openspec-ui-cli stop &amp;lt;instanceId&amp;gt; &lt;span class="nt"&gt;--reason&lt;/span&gt; &lt;span class="s2"&gt;"wrong branch"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--after &amp;lt;task&amp;gt;&lt;/code&gt; lets the run finish a named task first and stops at the next&lt;br&gt;
sound point after it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Your agent, per stage
&lt;/h2&gt;

&lt;p&gt;The picker drives the agent CLIs you already have: Claude CLI, GitHub Copilot&lt;br&gt;
CLI, Codex CLI, Gemini CLI, and a local model behind an OpenAI-compatible&lt;br&gt;
endpoint. The CLI-based ones also come in a variant that speaks the Agent&lt;br&gt;
Client Protocol, which carries structured progress instead of scraped text.&lt;br&gt;
The tool never handles an API key: each CLI keeps its own login.&lt;/p&gt;

&lt;p&gt;Here is what has actually been run. Claude CLI and Copilot CLI have been run&lt;br&gt;
against the real binaries. Codex and Gemini never have, raw or over ACP: their&lt;br&gt;
adapters are written to the vendors' documented interfaces and tested against&lt;br&gt;
a mocked peer, and if either misbehaves for you, that is the likeliest reason&lt;br&gt;
and a report would be useful. Two ACP caveats are worth knowing before you&lt;br&gt;
choose one: the Claude adapter never asks for permission, and &lt;code&gt;copilot --acp&lt;/code&gt;&lt;br&gt;
completed file writes and shell commands here without asking either.&lt;/p&gt;
&lt;h2&gt;
  
  
  Checkpoints, ceilings and a record
&lt;/h2&gt;

&lt;p&gt;Where a person decides is configuration, and the runner enforces it: an&lt;br&gt;
autonomy level, checkpoints between stages, a review gate that only a change's&lt;br&gt;
own settings can relax, and tasks marked as human-only or delegated to a named&lt;br&gt;
agent. Each stage has its own spending cap in the unit its agent honours, each&lt;br&gt;
chain has a ceiling, and every run lands in an audit log. The project also&lt;br&gt;
states plainly which limits do not exist, in a document of their own.&lt;/p&gt;

&lt;p&gt;The Workbench ships 17 change templates, for things like a Vite migration, a&lt;br&gt;
production Dockerfile, an authentication middleware or a testing baseline, so&lt;br&gt;
a new change can start from a proposal that already has the right shape.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;In VS Code, install it from the Marketplace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code &lt;span class="nt"&gt;--install-extension&lt;/span&gt; openspec-ui.openspec-ui-vscode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or run the standalone application from a clone of the repository:&lt;br&gt;
&lt;/p&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;npm run build &lt;span class="nt"&gt;--workspace&lt;/span&gt; @openspec-ui/server
npm run start &lt;span class="nt"&gt;--workspace&lt;/span&gt; @openspec-ui/server &lt;span class="nt"&gt;--&lt;/span&gt; &amp;lt;workspaceRoot&amp;gt; 4317
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It prints a URL with a one-time token; open that exact URL. Everything runs on&lt;br&gt;
your machine, against your own agent CLIs.&lt;/p&gt;

&lt;p&gt;The repository, the packages and the extension are still called OpenSpec-UI;&lt;br&gt;
the product's name is OpenSpec Workbench. The code and the issues are at&lt;br&gt;
&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI" rel="noopener noreferrer"&gt;github.com/VeryComplexAndLongName/OpenSpec-UI&lt;/a&gt;,&lt;br&gt;
and I would like to hear from anyone who tries it, above all from people who&lt;br&gt;
run Codex or Gemini, which I have not been able to.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>automation</category>
      <category>tools</category>
    </item>
    <item>
      <title>OpenSpec-UI: A Visual Workspace for Spec-Driven AI Development</title>
      <dc:creator>Alexander Ivanov</dc:creator>
      <pubDate>Tue, 18 Aug 2026 12:41:17 +0000</pubDate>
      <link>https://dev.to/someone_somewhere_05cad9e/openspec-ui-a-visual-workspace-for-spec-driven-ai-development-3l3o</link>
      <guid>https://dev.to/someone_somewhere_05cad9e/openspec-ui-a-visual-workspace-for-spec-driven-ai-development-3l3o</guid>
      <description>&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%2Fagpzoonpg8ys1hcrjrac.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%2Fagpzoonpg8ys1hcrjrac.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
AI coding agents are getting very good at writing code.&lt;/p&gt;

&lt;p&gt;The harder problem is increasingly &lt;em&gt;controlling what they are supposed to build&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;When a project uses specification-driven development, the workflow is no longer just:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Prompt → AI → Code&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It becomes something closer to:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Specification&lt;br&gt;
    ↓&lt;br&gt;
Change proposal&lt;br&gt;
    ↓&lt;br&gt;
Design&lt;br&gt;
    ↓&lt;br&gt;
Tasks&lt;br&gt;
    ↓&lt;br&gt;
AI coding agent&lt;br&gt;
    ↓&lt;br&gt;
Implementation&lt;br&gt;
    ↓&lt;br&gt;
Validation&lt;br&gt;
    ↓&lt;br&gt;
Archive&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This workflow works well from the command line, but as the number of changes, specifications, agents, and repositories grows, a CLI-only interface can become difficult to navigate.&lt;/p&gt;

&lt;p&gt;That's the problem I wanted to solve with &lt;strong&gt;OpenSpec-UI&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is OpenSpec-UI?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI" rel="noopener noreferrer"&gt;OpenSpec-UI&lt;/a&gt; is an open-source visual workspace for &lt;a href="https://github.com/Fission-AI/OpenSpec" rel="noopener noreferrer"&gt;OpenSpec&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It provides a graphical way to work with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Changes&lt;/li&gt;
&lt;li&gt;Proposals&lt;/li&gt;
&lt;li&gt;Designs&lt;/li&gt;
&lt;li&gt;Specs&lt;/li&gt;
&lt;li&gt;Tasks&lt;/li&gt;
&lt;li&gt;Archived changes&lt;/li&gt;
&lt;li&gt;Templates&lt;/li&gt;
&lt;li&gt;Repository setup&lt;/li&gt;
&lt;li&gt;Validation workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also provides an interface for launching AI coding agents directly from the same workspace.&lt;/p&gt;

&lt;p&gt;The project currently supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude CLI&lt;/li&gt;
&lt;li&gt;GitHub Copilot CLI&lt;/li&gt;
&lt;li&gt;Codex CLI&lt;/li&gt;
&lt;li&gt;Gemini CLI&lt;/li&gt;
&lt;li&gt;local LLMs through an OpenAI-compatible API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important part is that OpenSpec-UI is not intended to replace OpenSpec.&lt;/p&gt;

&lt;p&gt;It is a workspace around it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why build another UI?
&lt;/h2&gt;

&lt;p&gt;OpenSpec already provides &lt;code&gt;openspec view&lt;/code&gt;, which is useful for browsing specifications and changes.&lt;/p&gt;

&lt;p&gt;So why build another interface?&lt;/p&gt;

&lt;p&gt;There are several practical reasons.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Working with archived changes
&lt;/h3&gt;

&lt;p&gt;One useful addition is the ability to inspect differences between versions of archived changes.&lt;/p&gt;

&lt;p&gt;When a project has accumulated many changes, simply browsing the current state is not always enough. Sometimes you want to understand how a particular proposal evolved.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. AI agents become part of the workflow
&lt;/h3&gt;

&lt;p&gt;An increasingly common development workflow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create specification
        ↓
Review specification
        ↓
Create implementation tasks
        ↓
Start AI coding agent
        ↓
Agent modifies repository
        ↓
Run validation
        ↓
Review result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the specification management tool and the coding agent are separate applications, developers constantly switch between terminals, editors and browser windows.&lt;/p&gt;

&lt;p&gt;OpenSpec-UI puts these operations closer together.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. VS Code integration
&lt;/h3&gt;

&lt;p&gt;Many developers already spend most of their working day inside VS Code.&lt;/p&gt;

&lt;p&gt;For that reason, OpenSpec-UI has two delivery modes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                   OpenSpec-UI
                       │
            ┌──────────┴──────────┐
            │                     │
      VS Code extension      Standalone Web UI
            │                     │
       native workbench       local browser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both use the same underlying core.&lt;/p&gt;

&lt;p&gt;The VS Code extension provides native integration with the editor, while the standalone application is useful when a separate local web interface is preferable.&lt;/p&gt;

&lt;h2&gt;
  
  
  One core, two interfaces
&lt;/h2&gt;

&lt;p&gt;One architectural decision was particularly important: &lt;strong&gt;the business logic should not be duplicated between the Web UI and the VS Code extension.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The repository is organized as a TypeScript monorepo with shared packages.&lt;/p&gt;

&lt;p&gt;At a high level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    OpenSpec / Git / CLI Agents
                              │
                              ▼
                       ┌─────────────┐
                       │    Core     │
                       │             │
                       │ OpenSpec    │
                       │ parser      │
                       │ Git         │
                       │ security    │
                       │ execution   │
                       │ agents      │
                       └──────┬──────┘
                              │
                 ┌────────────┴────────────┐
                 │                         │
                 ▼                         ▼
             REST / WS                Direct import
                 │                         │
                 ▼                         ▼
          Standalone Web UI          VS Code Extension
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repository currently separates responsibilities into packages such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;core&lt;/code&gt; — execution engine, OpenSpec parsing, Git integration, agent orchestration and security&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;server&lt;/code&gt; — REST/WebSocket layer for the standalone application&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;webui&lt;/code&gt; — shared React UI&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;extension&lt;/code&gt; — VS Code integration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cli&lt;/code&gt; — non-interactive CLI functionality for CI workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows the UI to remain relatively independent from the transport mechanism.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running everything locally
&lt;/h2&gt;

&lt;p&gt;Another design goal is that OpenSpec-UI should work as a &lt;strong&gt;local developer tool&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The standalone application runs locally and operates on the local repository.&lt;/p&gt;

&lt;p&gt;The VS Code extension also works without requiring a remote OpenSpec-UI service.&lt;/p&gt;

&lt;p&gt;A typical standalone setup is currently as simple as:&lt;br&gt;
&lt;/p&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;npm run build &lt;span class="nt"&gt;--workspace&lt;/span&gt; @openspec-ui/server
npm run start &lt;span class="nt"&gt;--workspace&lt;/span&gt; @openspec-ui/server &lt;span class="nt"&gt;--&lt;/span&gt; &amp;lt;workspaceRoot&amp;gt; 4317
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server exposes a localhost URL containing a temporary access token.&lt;/p&gt;

&lt;p&gt;This is useful for workflows where source code and specifications should remain on the developer's machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI agents as an execution layer
&lt;/h2&gt;

&lt;p&gt;One of the interesting parts of the project is the agent integration.&lt;/p&gt;

&lt;p&gt;Instead of treating an AI coding agent as a completely separate tool, OpenSpec-UI treats it as an execution component of the specification workflow.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OpenSpec Change
      │
      ├── Proposal
      ├── Design
      ├── Spec
      └── Tasks
             │
             ▼
       Agent Launcher
             │
      ┌──────┼──────┬──────┐
      ▼      ▼      ▼      ▼
   Claude  Copilot Codex  Gemini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is deliberately designed around a command/event protocol rather than tightly coupling the application to one particular AI provider.&lt;/p&gt;

&lt;p&gt;That makes it possible to use different agents for different tasks.&lt;/p&gt;

&lt;p&gt;For example, a developer might use one agent for implementation and another for review.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about local LLMs?
&lt;/h2&gt;

&lt;p&gt;The project also supports a local LLM through an OpenAI-compatible API.&lt;/p&gt;

&lt;p&gt;That means the execution layer does not have to be limited to hosted AI services.&lt;/p&gt;

&lt;p&gt;This can be particularly useful for development environments where source code cannot be sent to external services or where developers already operate their own inference infrastructure.&lt;/p&gt;

&lt;p&gt;The goal is not to build another LLM runtime.&lt;/p&gt;

&lt;p&gt;The goal is to make the model or agent available as one of the execution options in the development workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  A specification-first workflow
&lt;/h2&gt;

&lt;p&gt;The larger idea behind OpenSpec-UI is that AI coding does not have to start with a prompt.&lt;/p&gt;

&lt;p&gt;A more structured workflow can be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    Human
                      │
                      ▼
              Define the change
                      │
                      ▼
                 OpenSpec
                      │
          ┌───────────┼───────────┐
          ▼           ▼           ▼
       Proposal      Design      Tasks
          │           │           │
          └───────────┼───────────┘
                      ▼
                  AI Agent
                      │
                      ▼
                  Codebase
                      │
                      ▼
                  Validation
                      │
                      ▼
                   Archive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The human remains responsible for defining and reviewing the intended change.&lt;/p&gt;

&lt;p&gt;The AI agent becomes an implementation tool operating within that context.&lt;/p&gt;

&lt;p&gt;This distinction becomes increasingly important as coding agents become more autonomous.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not just use an AI coding IDE?
&lt;/h2&gt;

&lt;p&gt;Tools such as AI-enabled IDEs are very good at generating and modifying code.&lt;/p&gt;

&lt;p&gt;But specification management is a slightly different problem.&lt;/p&gt;

&lt;p&gt;An IDE answers questions such as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What code should I edit?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A specification workflow also needs to answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What are we changing?&lt;/p&gt;

&lt;p&gt;Why are we changing it?&lt;/p&gt;

&lt;p&gt;What requirements does the change introduce?&lt;/p&gt;

&lt;p&gt;What tasks are required?&lt;/p&gt;

&lt;p&gt;What was changed previously?&lt;/p&gt;

&lt;p&gt;What is the canonical specification?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These are different layers of the development process.&lt;/p&gt;

&lt;p&gt;OpenSpec-UI is intended to sit between the specification layer and the coding-agent layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The project is still evolving
&lt;/h2&gt;

&lt;p&gt;OpenSpec-UI is actively developed.&lt;/p&gt;

&lt;p&gt;The current implementation already contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;standalone Web UI&lt;/li&gt;
&lt;li&gt;VS Code extension&lt;/li&gt;
&lt;li&gt;shared execution core&lt;/li&gt;
&lt;li&gt;OpenSpec integration&lt;/li&gt;
&lt;li&gt;Git integration&lt;/li&gt;
&lt;li&gt;AI agent orchestration&lt;/li&gt;
&lt;li&gt;archived change management&lt;/li&gt;
&lt;li&gt;Specs and Tasks views&lt;/li&gt;
&lt;li&gt;templates&lt;/li&gt;
&lt;li&gt;repository setup tools&lt;/li&gt;
&lt;li&gt;CLI functionality&lt;/li&gt;
&lt;li&gt;local execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the project is intentionally still evolving.&lt;/p&gt;

&lt;p&gt;One of the reasons for publishing it publicly is to get feedback from developers who are experimenting with specification-driven development and AI coding agents.&lt;/p&gt;

&lt;p&gt;There are still many questions worth exploring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How should agents and specifications interact?&lt;/li&gt;
&lt;li&gt;What should an AI-native development workbench look like?&lt;/li&gt;
&lt;li&gt;How much autonomy should an agent have?&lt;/li&gt;
&lt;li&gt;How should changes be reviewed before execution?&lt;/li&gt;
&lt;li&gt;How should multiple agents cooperate?&lt;/li&gt;
&lt;li&gt;What is the right UI for long-running agent workflows?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are not completely solved problems yet.&lt;/p&gt;

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

&lt;p&gt;The project is open source:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/VeryComplexAndLongName/OpenSpec-UI" rel="noopener noreferrer"&gt;https://github.com/VeryComplexAndLongName/OpenSpec-UI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are experimenting with OpenSpec, AI coding agents, or specification-driven development, I'd be interested in your feedback.&lt;/p&gt;

&lt;p&gt;In particular, I'm interested in whether a visual workspace makes specification-driven AI development easier to manage than a CLI-only workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;AI coding agents are rapidly improving at implementation.&lt;/p&gt;

&lt;p&gt;That makes the &lt;strong&gt;specification and orchestration layer&lt;/strong&gt; increasingly important.&lt;/p&gt;

&lt;p&gt;The future workflow may not simply be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Human → AI → Code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It may look more like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Human
  ↓
Specification
  ↓
Change
  ↓
Agent
  ↓
Implementation
  ↓
Validation
  ↓
Human review
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenSpec-UI is an experiment in building the workspace around that workflow.&lt;/p&gt;

&lt;p&gt;The code is open, the architecture is visible, and contributions and feedback are welcome.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Built a Python Prompt Orchestrator for Structured LLM Pipelines</title>
      <dc:creator>Alexander Ivanov</dc:creator>
      <pubDate>Fri, 29 May 2026 04:00:51 +0000</pubDate>
      <link>https://dev.to/someone_somewhere_05cad9e/i-built-a-python-prompt-orchestrator-for-structured-llm-pipelines-2nmi</link>
      <guid>https://dev.to/someone_somewhere_05cad9e/i-built-a-python-prompt-orchestrator-for-structured-llm-pipelines-2nmi</guid>
      <description>&lt;p&gt;Most LLM applications eventually hit the same problem:&lt;/p&gt;

&lt;p&gt;prompts become unmanageable.&lt;/p&gt;

&lt;p&gt;At first, everything fits into a single string.&lt;/p&gt;

&lt;p&gt;Then you add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;summaries&lt;/li&gt;
&lt;li&gt;RAG&lt;/li&gt;
&lt;li&gt;memory&lt;/li&gt;
&lt;li&gt;safety checks&lt;/li&gt;
&lt;li&gt;token budgets&lt;/li&gt;
&lt;li&gt;conversation compaction&lt;/li&gt;
&lt;li&gt;provider switching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And suddenly your prompt pipeline becomes harder to maintain than the model itself.&lt;/p&gt;

&lt;p&gt;So I built &lt;code&gt;prompt_orchestrator&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;prompt_orchestrator&lt;/code&gt; is a Python module for structured prompt orchestration with:&lt;/p&gt;

&lt;p&gt;static/semi-stable/dynamic prompt layout&lt;br&gt;
configurable summarization providers&lt;br&gt;
optional RAG integration&lt;br&gt;
safety heuristics&lt;br&gt;
token budgeting&lt;br&gt;
centralized configuration&lt;br&gt;
prompt efficiency analysis&lt;/p&gt;

&lt;p&gt;The goal was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make prompt pipelines deterministic, modular, and production-friendly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Structured prompt sections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The orchestrator separates prompts into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;static parts&lt;/li&gt;
&lt;li&gt;semi-stable parts&lt;/li&gt;
&lt;li&gt;dynamic conversation context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This improves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cacheability&lt;/li&gt;
&lt;li&gt;token efficiency&lt;/li&gt;
&lt;li&gt;prompt readability&lt;/li&gt;
&lt;li&gt;debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Works with or without RAG&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The module supports optional RAG providers.&lt;/p&gt;

&lt;p&gt;It integrates directly with &lt;code&gt;rag_orchestrator&lt;/code&gt; and compatible retrieval systems.&lt;/p&gt;

&lt;p&gt;One particularly useful detail:&lt;/p&gt;

&lt;p&gt;Both projects share a compatible &lt;code&gt;DocChunk&lt;/code&gt; structure.&lt;/p&gt;

&lt;p&gt;This makes integration extremely simple.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Safety checks included&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The project includes lightweight safety heuristics for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;injection detection&lt;/li&gt;
&lt;li&gt;contradiction checks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;without requiring a separate moderation service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary providers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Supported summary backends:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenAI&lt;/li&gt;
&lt;li&gt;Ollama&lt;/li&gt;
&lt;li&gt;deterministic local fallback&lt;/li&gt;
&lt;li&gt;custom providers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the orchestration layer is not tied to a single vendor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token-aware orchestration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The orchestrator includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;token counting via tiktoken&lt;/li&gt;
&lt;li&gt;automatic trimming&lt;/li&gt;
&lt;li&gt;prompt fitting&lt;/li&gt;
&lt;li&gt;configurable token budgets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;which becomes critical for long-running conversations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Designed for integration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The module was intentionally designed to integrate into existing systems.&lt;/p&gt;

&lt;p&gt;It does not force:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a framework&lt;/li&gt;
&lt;li&gt;an agent runtime&lt;/li&gt;
&lt;li&gt;a specific LLM provider&lt;/li&gt;
&lt;li&gt;a database stack&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tests and simulations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The repository already includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;interactive simulations&lt;/li&gt;
&lt;li&gt;safety simulations&lt;/li&gt;
&lt;li&gt;conversation replay tests&lt;/li&gt;
&lt;li&gt;console pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;which makes experimentation easy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;pip install -e .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A lot of current LLM tooling focuses on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;agents&lt;/li&gt;
&lt;li&gt;autonomous loops&lt;/li&gt;
&lt;li&gt;framework ecosystems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But prompt orchestration itself is still an unsolved infrastructure problem.&lt;/p&gt;

&lt;p&gt;This project focuses specifically on making that layer cleaner and easier to reason about.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>rag</category>
      <category>promptengineering</category>
    </item>
  </channel>
</rss>
