<?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: Mykola Kondratiuk</title>
    <description>The latest articles on DEV Community by Mykola Kondratiuk (@itskondrat).</description>
    <link>https://dev.to/itskondrat</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%2F3753205%2Fa206f74a-98be-4c2b-abbd-f06ec964327b.jpg</url>
      <title>DEV Community: Mykola Kondratiuk</title>
      <link>https://dev.to/itskondrat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/itskondrat"/>
    <language>en</language>
    <item>
      <title>I Wired an AI Fallback Runbook After a 19-Day Outage - Here's All 3 Parts</title>
      <dc:creator>Mykola Kondratiuk</dc:creator>
      <pubDate>Fri, 03 Jul 2026 07:37:30 +0000</pubDate>
      <link>https://dev.to/itskondrat/i-wired-an-ai-fallback-runbook-after-a-19-day-outage-heres-all-3-parts-579d</link>
      <guid>https://dev.to/itskondrat/i-wired-an-ai-fallback-runbook-after-a-19-day-outage-heres-all-3-parts-579d</guid>
      <description>&lt;p&gt;When your primary model goes dark for 19 days, what does your workflow actually do in that first hour? Fail silently? Stall until someone notices? Or route somewhere else and keep moving?&lt;/p&gt;

&lt;p&gt;If you can't answer that, you don't have a resilience posture. You have luck, and luck just got tested in public.&lt;/p&gt;

&lt;p&gt;Fable 5 came back globally on July 1 after a 19-day export-control shutdown pulled it offline. The post-mortems are landing this week, and most fall into two buckets: "it's back" and "here's what the outage cost." MarketScale had the sharper read. Teams that treat any single model as permanent infrastructure keep getting surprised, while teams with a routing map, banked reserves, and a named backup treated the whole thing as an arbitrage window instead of a fire.&lt;/p&gt;

&lt;p&gt;I went and looked at my own setup the morning it came back, and I found gaps. This is the runbook I wired after, written on a calm day so I'm not writing it during the next scramble. None of it is PM scope-creep. It's the same reliability thinking you'd apply to a database sitting on a single replica.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1: A routing policy you can actually read
&lt;/h2&gt;

&lt;p&gt;"We use Claude" is not a routing policy. It's a default nobody voted for.&lt;/p&gt;

&lt;p&gt;A routing policy is a named map: this class of task goes to this model, that class goes to a cheaper or faster one. Bulk classification doesn't need your most expensive reasoning pass. The gnarly multi-step agent run does. Most teams carry this map around in one engineer's head, which means it doesn't survive that person taking a week off, and it definitely doesn't survive the model itself going offline.&lt;/p&gt;

&lt;p&gt;Get it out of the head and into a file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# routing.yaml - the map, not the vibe&lt;/span&gt;
&lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;bulk_classify&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;haiku-tier&lt;/span&gt;
    &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gemini-flash&lt;/span&gt;
  &lt;span class="na"&gt;long_agent_run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;opus-tier&lt;/span&gt;
    &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sonnet-5&lt;/span&gt;
  &lt;span class="na"&gt;code_review&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sonnet-5&lt;/span&gt;
    &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gpt-tier&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The value isn't the YAML. It's that "what runs where" is now a decision on paper instead of a habit in someone's memory. When the primary for a task class disappears, the router already knows where to send the work. Nobody improvises at 2am.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: Plan-banking, the canned goods in your pantry
&lt;/h2&gt;

&lt;p&gt;There's a handful of workflows you genuinely cannot afford to have stall. For those, keep a reserve.&lt;/p&gt;

&lt;p&gt;Plan-banking means pre-generating the plans, scaffolds, and outputs for your critical workflows while the model is up and cheap, then drawing from that bank when it isn't. Think of it as canning vegetables in summer so a February storm doesn't mean an empty plate. On a calm day it costs you a scheduled job and some storage. During a 19-day blackout it's the gap between "we drew from the reserve" and "we're blocked until further notice."&lt;/p&gt;

&lt;p&gt;I keep it dead simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# nightly: bank fresh plans for the workflows that can't stall&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;wf &lt;span class="k"&gt;in &lt;/span&gt;onboarding_flow release_notes triage_playbook&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;generate_plan &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$wf&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"bank/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;wf&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%F&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;.json"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="c"&gt;# keep 14 days, prune the rest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trap I fell into first was banking everything. You don't need reserves for the workflow that runs twice a year. Bank the two or three that would actually hurt, and let the rest fail loudly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 3: A second source you've actually tested
&lt;/h2&gt;

&lt;p&gt;For every critical use case, name the specific fallback model. Then prove it works for that task before you need it.&lt;/p&gt;

&lt;p&gt;This is where the Fable shutdown got concrete. Teams with a named, tested second source rerouted in hours. Teams with "we'll figure it out" lost real weeks. And "no viable alternate exists" stopped being an honest excuse this year, because the menu got deep. Sonnet 5 shipped June 30 at $2/$10 per million tokens as the most agentic Sonnet yet, so the backup is now cheaper and more capable than the thing it's backing up. Gemini 3.5 Pro is clearing for July. The alternates are there.&lt;/p&gt;

&lt;p&gt;The part people skip is the testing. A fallback you've never run against your real prompts is a guess wearing a helmet. Wire a weekly canary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# canary.yaml - does the backup still pass our bar?&lt;/span&gt;
&lt;span class="na"&gt;second_source_check&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;weekly&lt;/span&gt;
  &lt;span class="na"&gt;for_each&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;critical_use_case&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fallback_model against golden_prompts&lt;/span&gt;
  &lt;span class="na"&gt;alert_if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pass_rate &amp;lt; &lt;/span&gt;&lt;span class="m"&gt;0.95&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the second source silently drifts below your bar, you want to know on a quiet Thursday, not in the middle of the outage you built it for.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that's easy to miss
&lt;/h2&gt;

&lt;p&gt;There's a geopolitics wrinkle worth one line. The same government that pulled Fable's export license is now being offered a 5% stake in a competitor. Which model gets restricted next is not something you can predict, but it is something you can hedge, and a routing policy spanning more than one vendor is the hedge.&lt;/p&gt;

&lt;p&gt;Here's what shifted my thinking most. None of these three moves is expensive. They're all cheap on a calm day and completely impossible in a panic, which is exactly why they get skipped. There's never a fire forcing you to do them, right up until there is. The 19-day shutdown didn't create a new risk. It just mailed everyone the bill for a decision they made by not deciding.&lt;/p&gt;

&lt;p&gt;So, honest question for the comments: of the three parts, which one does your team actually have written down right now? Not "we could stand it up." Written down, today. I'll go first. My routing map was solid, and my second-source canary didn't exist until last week.&lt;/p&gt;

&lt;p&gt;Tags: #AI&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>ai</category>
      <category>leadership</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I Managed AI Agents Like Junior Hires for a Month - Here Are the 4 Manager Moves That Don't Transfer</title>
      <dc:creator>Mykola Kondratiuk</dc:creator>
      <pubDate>Wed, 01 Jul 2026 07:56:33 +0000</pubDate>
      <link>https://dev.to/itskondrat/i-managed-ai-agents-like-junior-hires-for-a-month-here-are-the-4-manager-moves-that-dont-transfer-23o4</link>
      <guid>https://dev.to/itskondrat/i-managed-ai-agents-like-junior-hires-for-a-month-here-are-the-4-manager-moves-that-dont-transfer-23o4</guid>
      <description>&lt;p&gt;The first agent I put into production, I treated like a new hire. Clear brief, checked its first handful of outputs, saw they were clean, and started trusting it. About two weeks in it confidently pushed a config change that broke a downstream job. No error. No flag. It just went quiet and moved to the next task.&lt;/p&gt;

&lt;p&gt;That was the day I figured out the advice everyone's repeating right now is only half true.&lt;/p&gt;

&lt;p&gt;Ethan Mollick published "The Twilight of the Chatbots" yesterday and told 500,000-plus readers the best way to use agents is to think of yourself as a manager. He's right about the shift. Work moved from chatting with a model to handing tasks to one that runs for weeks on its own. But "think like a manager" quietly smuggles in an assumption: that the moves you'd use on a person carry over. Most of them don't.&lt;/p&gt;

&lt;p&gt;Here are the four that broke for me, and what I do now instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Move 1: The trust curve runs backwards
&lt;/h2&gt;

&lt;p&gt;With a person, trust compounds. A junior dev earns a code review, then a lighter review, then eventually you stop looking because they've proven it a hundred times. Competence banks.&lt;/p&gt;

&lt;p&gt;An agent re-earns trust every single run. Yesterday's clean output tells you almost nothing about today's, because the same prompt against a slightly different input can wander somewhere you didn't test. There's no "proven it a hundred times" that carries forward. You never get to graduate an agent to "I don't need to look."&lt;/p&gt;

&lt;p&gt;The mental adjustment that helped: I stopped thinking of review as a phase the agent grows out of and started treating it as a permanent property of the system. I treat it the way I'd treat rate limits or a flaky network, a fixed constraint of the tool rather than a comment on any teammate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Move 2: Silence is not progress
&lt;/h2&gt;

&lt;p&gt;Managing people, silence usually means things are fine. A good report pings you when they hit something they can't resolve. Absence of a question is a weak signal that the work is on track.&lt;/p&gt;

&lt;p&gt;Agents invert this too. Mine sailed straight past the point a human would have stopped to ask, and did it with total confidence. "No error thrown" got read by me as "did the thing correctly," and those are not the same claim. The failure wasn't a crash. It was a plausible-looking wrong answer delivered without hesitation.&lt;/p&gt;

&lt;p&gt;So I stopped waiting for the agent to surface problems and started instrumenting the moments where I most wanted a human to look up. A cheap version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# check-in tripwire, not a full test suite&lt;/span&gt;
&lt;span class="na"&gt;tripwires&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;files_changed&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;5"&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pause_for_review&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;touches:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;[migrations/,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;infra/,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;auth/]"&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pause_for_review&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;external_api_write&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;==&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pause_for_review&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;None of that is clever. The point is I decide &lt;em&gt;when I look&lt;/em&gt; up front, instead of hoping the agent tells me. It won't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Move 3: You re-scope every task, not once
&lt;/h2&gt;

&lt;p&gt;You onboard a person one time. They absorb how the team works, what "good" looks like here, which shortcuts are fine and which will get someone paged. That context rides along on every future task for free.&lt;/p&gt;

&lt;p&gt;An agent carries none of that between tasks unless you build the memory yourself. Each assignment starts closer to cold than you expect. Early on I kept writing terse tickets the way I would for someone who already knew our conventions, and the agent kept filling the gaps with reasonable-sounding guesses that were wrong for us specifically.&lt;/p&gt;

&lt;p&gt;Now scoping is per-task until the shared context is actually encoded somewhere durable. More words up front, fewer surprises at the end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Move 4: Corrections have to be written down, not remembered
&lt;/h2&gt;

&lt;p&gt;This is the one that cost me the most rework. Tell a person "we never do X" once and they adapt. The correction lives in their head from then on.&lt;/p&gt;

&lt;p&gt;Tell an agent, watch it fix the thing in that run, then watch it make the identical mistake on the next run. The feedback didn't stick because there was nowhere for it to stick. A correction only survives if it lives in the prompt or a guardrail the next run actually reads:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# AGENTS.md&lt;/span&gt;
&lt;span class="gu"&gt;## Hard rules (read every run)&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Never edit files under generated/. They are build output.
&lt;span class="p"&gt;-&lt;/span&gt; Config changes to prod/ require an explicit human approval line.
&lt;span class="p"&gt;-&lt;/span&gt; "Done" means the check passed AND the diff is under review, not just committed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a correction isn't in a file the next run loads, you didn't correct anything. You just watched it behave once.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three moves that make the mindset operational
&lt;/h2&gt;

&lt;p&gt;Mollick handed a huge audience the mindset. The part he left open is the method, so here's the version that's working for me.&lt;/p&gt;

&lt;p&gt;First, check-in tripwires, from Move 2. Decide the moments you look before the work starts, not at the end.&lt;/p&gt;

&lt;p&gt;Second, treat effort as a management call. Anthropic shipped adjustable effort levels on Sonnet 5 yesterday, and the interesting question isn't the setting, it's which class of task deserves the expensive, careful pass. That's a scoping decision, the same kind you'd make deciding whether a task needs your senior engineer or can go to anyone.&lt;/p&gt;

&lt;p&gt;Third, define "done" and "escalate" before you assign, not after. A person can infer both from context. An agent can infer neither. If you can't write down what finished looks like and what should make it stop and come find you, the task isn't ready to hand off.&lt;/p&gt;

&lt;p&gt;One thing making all of this easier: tools are starting to ship auditable artifacts, work products with a built-in trail of what the agent actually did. When you can read back the path instead of just the result, managing the thing gets a lot less like guesswork.&lt;/p&gt;

&lt;p&gt;And this is about to stop being a specialist skill. Copilot became a permanent SKU baked into M365 tiers as of today, which means whole orgs are getting an agent to manage whether they asked for one or not. "How do you actually manage one of these" is turning into a question everybody has to answer, not just the people who opted in early.&lt;/p&gt;

&lt;p&gt;I'll leave you with the one I want to argue about: of these four, which bit you first? Mine was the confident silence, and I still don't fully trust that I've fixed it.&lt;/p&gt;

&lt;p&gt;Tags: #AIAgents&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>ai</category>
      <category>productivity</category>
      <category>leadership</category>
    </item>
    <item>
      <title>I Built a 5-Metric Dashboard for AI's Impact on My Team - Here's the One I'd Refuse to Skip</title>
      <dc:creator>Mykola Kondratiuk</dc:creator>
      <pubDate>Fri, 26 Jun 2026 08:10:46 +0000</pubDate>
      <link>https://dev.to/itskondrat/i-built-a-5-metric-dashboard-for-ais-impact-on-my-team-heres-the-one-id-refuse-to-skip-1h1g</link>
      <guid>https://dev.to/itskondrat/i-built-a-5-metric-dashboard-for-ais-impact-on-my-team-heres-the-one-id-refuse-to-skip-1h1g</guid>
      <description>&lt;p&gt;A US state shipped an observability tool for AI yesterday and most engineers didn't notice.&lt;/p&gt;

&lt;p&gt;California turned on a monthly tracker (June 25) that links AI-exposure data to unemployment claims, so the state can watch AI's effect on the workforce in near real time. It's a macro dashboard for a thing nobody was instrumenting before.&lt;/p&gt;

&lt;p&gt;You already know where I'm going with this. You instrument your services. Latency, error rate, saturation, the whole golden-signals stack. You'd never run a system in prod with no dashboard. So why is the AI workforce inside your own org running completely uninstrumented?&lt;/p&gt;

&lt;h2&gt;
  
  
  The metrics we actually have are the wrong ones
&lt;/h2&gt;

&lt;p&gt;Pull up how most teams "measure AI" today. Two dashboards, tops.&lt;/p&gt;

&lt;p&gt;One is spend. Tokens, seats, API bills. Useful for finance, tells you nothing about impact.&lt;/p&gt;

&lt;p&gt;The other is model evals. Benchmark scores, pass rates on a test set. Useful for the model, tells you nothing about your team.&lt;/p&gt;

&lt;p&gt;Neither one answers the question an exec is about to start asking: what is this actually doing to how the work gets done? That's not a cost question and it's not a benchmark question. It's an observability question, and it's ours to own before it gets handed to someone who'll measure it badly.&lt;/p&gt;

&lt;p&gt;So I sketched the dashboard I'd build. Five signals, one screen. Here's the shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ai-workforce-dashboard.yaml&lt;/span&gt;
&lt;span class="na"&gt;metrics&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;agent_task_coverage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;real&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;workflow's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;steps&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;running&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;agents"&lt;/span&gt;
    &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agent_steps / total_steps&lt;/span&gt;
    &lt;span class="na"&gt;note&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;measure&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Tuesday&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;reality,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;not&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;demo"&lt;/span&gt;

  &lt;span class="na"&gt;role_reclassification_rate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;roles&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;that&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;changed&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;shape&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;vs&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;roles&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;eliminated"&lt;/span&gt;
    &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;reclassified / (reclassified + eliminated)&lt;/span&gt;
    &lt;span class="na"&gt;note&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;augmentation&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;signal&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;—&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;counts&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;shift,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;not&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;loss"&lt;/span&gt;

  &lt;span class="na"&gt;upskilling_completion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;changed-role&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;people&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;who&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;finished&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;training"&lt;/span&gt;
    &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;completed / affected&lt;/span&gt;

  &lt;span class="na"&gt;error_escalation_rate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;outputs&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;caught&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;+&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;kicked&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;back&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;human"&lt;/span&gt;
    &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;escalated / agent_outputs&lt;/span&gt;
    &lt;span class="na"&gt;note&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;reliability&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;trend&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;—&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;rising&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;trouble"&lt;/span&gt;

  &lt;span class="na"&gt;output_vs_headcount_delta&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;desc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;growing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;faster&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;than&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;team?"&lt;/span&gt;
    &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;d(output) - d(headcount)&lt;/span&gt;
    &lt;span class="na"&gt;refuse_to_skip&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The two metrics a dev will actually trust
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;error_escalation_rate&lt;/code&gt; is the one that should feel familiar. It's just your error budget, pointed at agents instead of services. An agent ships output, a human catches a bad one and escalates, you log it. The ratio over time is a trust curve. Falling means you can safely hand the agent more. Rising means something regressed and you're about to find out in production.&lt;/p&gt;

&lt;p&gt;The honest part: this one is hard to instrument cleanly, because "a human caught it" isn't always a logged event. The first version is manual and noisy. I'd still rather have a rough trend line than pretend reliability is fine because no one filed a ticket.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;output_vs_headcount_delta&lt;/code&gt; is the one I'd refuse to skip. It's the only line on the screen that ties everything to economics in one number. Output growing faster than the team is the entire argument for the budget you're spending, and it's the number a non-technical board will actually read.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why reclassification is the metric that keeps it honest
&lt;/h2&gt;

&lt;p&gt;The peg here is a job-displacement tracker, and the lazy version of this article is "here's how to watch the layoffs arrive." I think that frame is wrong, and &lt;code&gt;role_reclassification_rate&lt;/code&gt; is why.&lt;/p&gt;

&lt;p&gt;When you measure roles that changed shape instead of only roles that vanished, you catch what the doom story misses. The reviewer who now supervises an agent and owns the judgment calls didn't get deleted. Their job moved up the stack. If your dashboard only counts headcount, every shift looks like loss. If it counts reclassification, you can see the work redistributing and actually manage it.&lt;/p&gt;

&lt;p&gt;That's the difference between an instrument and an alarm. I want the instrument.&lt;/p&gt;

&lt;h2&gt;
  
  
  You already own observability. Extend it.
&lt;/h2&gt;

&lt;p&gt;None of this needs a new platform. It needs the discipline you already apply to your services, pointed one layer up at how agents and people are splitting the work. Five queries, one board, checked weekly.&lt;/p&gt;

&lt;p&gt;If you had to ship this dashboard with three metrics instead of five, which two would you cut, and which one would you defend in the room?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>ai</category>
      <category>leadership</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Porting my mobile app to the web: 3 silent bugs that only exist in the browser</title>
      <dc:creator>Mykola Kondratiuk</dc:creator>
      <pubDate>Thu, 25 Jun 2026 14:47:45 +0000</pubDate>
      <link>https://dev.to/itskondrat/porting-my-mobile-app-to-the-web-3-silent-bugs-that-only-exist-in-the-browser-28kh</link>
      <guid>https://dev.to/itskondrat/porting-my-mobile-app-to-the-web-3-silent-bugs-that-only-exist-in-the-browser-28kh</guid>
      <description>&lt;p&gt;I'm a solo founder. My app is a Flutter + Supabase thing that picks your dinner for you. It started on iOS, where it worked. Then I put it on the web.&lt;/p&gt;

&lt;p&gt;"Put it on the web" sounds like a build target. It's mostly true: the same Dart compiles, the same screens render. But the browser is a different planet with different physics, and three of my bugs only exist &lt;em&gt;there&lt;/em&gt;. A user gesture that expires. A session that leaks across tabs. A checkout someone else has to approve.&lt;/p&gt;

&lt;p&gt;The thing they had in common is the thing that makes web bugs so nasty: &lt;strong&gt;none of them crashed.&lt;/strong&gt; No red screen, no stack trace, no error in the console. The app just quietly did the wrong thing while every log said 200 OK.&lt;/p&gt;

&lt;p&gt;Here are the three, with the mechanism and the fix for each.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The button that did nothing: a pop-up dies if you &lt;code&gt;await&lt;/code&gt; first
&lt;/h2&gt;

&lt;p&gt;The "Manage subscription" button on the web did absolutely nothing. No error. No crash. You tapped it, and nothing opened. Every single time.&lt;/p&gt;

&lt;p&gt;I went to the logs braced for a 500. Instead, every click produced a clean &lt;strong&gt;POST 200&lt;/strong&gt; from my server with a perfectly valid customer-portal URL. The data was right. The function was right. The tab just... never opened. And the browser API I used to open it &lt;em&gt;returned &lt;code&gt;true&lt;/code&gt;&lt;/em&gt;, so my own code thought it had succeeded and never showed an error.&lt;/p&gt;

&lt;p&gt;Here's the rule I'd forgotten: &lt;strong&gt;a browser only lets you open a new tab during a real user gesture.&lt;/strong&gt; The click. Not 50ms after the click. The moment your handler does &lt;code&gt;await&lt;/code&gt; and waits on the network, the browser decides the gesture is over and silently blocks any pop-up you try to open afterward. Safari is the strictest about this.&lt;/p&gt;

&lt;p&gt;My code did the obvious-looking thing: fetch the URL, then open it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ pop-up blocked: the await "spends" the user gesture&lt;/span&gt;
&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchPortalUrl&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// network round-trip&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_blank&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;           &lt;span class="c1"&gt;// browser: "what click? blocked."&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix is to open the tab &lt;em&gt;synchronously&lt;/em&gt;, inside the gesture, while it's still valid, and only then point it at the URL once the network call comes back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ open the tab on the gesture, redirect it after&lt;/span&gt;
&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tab&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_blank&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// opened inside the click&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchPortalUrl&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;           &lt;span class="c1"&gt;// redirect the tab you already own&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;showError&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                      &lt;span class="c1"&gt;// popup blocker said no up front&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On mobile this whole class of bug doesn't exist. You call a native "open URL" API and the OS just does it. The web has a security model that says &lt;em&gt;"prove a human asked for this,"&lt;/em&gt; and an &lt;code&gt;await&lt;/code&gt; quietly fails that proof.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Apply it:&lt;/strong&gt; if a web button "does nothing," it isn't always broken. Anything that opens a tab, a window, or a file picker must happen synchronously on the gesture. Need server data first? Open the blank tab on the click, fetch, then redirect it. And don't trust a launcher that returns &lt;code&gt;true&lt;/code&gt; to mean "the user actually saw something."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. The login that hijacked the whole app
&lt;/h2&gt;

&lt;p&gt;This one made paying members look like they'd never paid, and it took me a minute to even believe what the logs were telling me.&lt;/p&gt;

&lt;p&gt;On the web, "restore my subscription" emails you a code. To keep that flow clean, I ran it on a &lt;strong&gt;separate, isolated auth client&lt;/strong&gt; so it couldn't disturb the main app. Sign in over there, verify the purchase, done. The main app, with its own anonymous guest identity, shouldn't even notice.&lt;/p&gt;

&lt;p&gt;It noticed.&lt;/p&gt;

&lt;p&gt;The auth library stores its session in browser storage under a key derived from the &lt;strong&gt;backend host&lt;/strong&gt; (&lt;code&gt;sb-&amp;lt;host&amp;gt;-auth-token&lt;/code&gt;) and broadcasts session changes to every client on that origin through a &lt;code&gt;BroadcastChannel&lt;/code&gt;. The channel is keyed by the &lt;em&gt;host&lt;/em&gt;, &lt;strong&gt;not by which client opened it.&lt;/strong&gt; So when my "isolated" restore client signed in, that sign-in was broadcast to the &lt;em&gt;main&lt;/em&gt; client, which dutifully saved it and &lt;strong&gt;dropped the device's own anonymous identity.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now the device was a different user. And because my row-level security ties every row to the current identity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the premium read came back with &lt;strong&gt;no row&lt;/strong&gt; → the app showed &lt;strong&gt;free&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;writing the user's own settings started failing with &lt;strong&gt;permission denied&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The logs were almost comically precise about it. The email login landed at &lt;code&gt;08:10:21&lt;/code&gt;. The first permission failures started at &lt;code&gt;08:10:35&lt;/code&gt;. &lt;strong&gt;Fourteen seconds&lt;/strong&gt; from "isolated login" to "the app is lying to a paying customer." The restore had actually &lt;em&gt;succeeded&lt;/em&gt; on the server the whole time. The client just quietly clobbered itself.&lt;/p&gt;

&lt;p&gt;Two fixes, because there were two problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Root cause:&lt;/strong&gt; snapshot the device's real anonymous session &lt;em&gt;before&lt;/em&gt; the code flow, and restore it the instant the flow finishes, no matter how it finishes (success, failure, whatever). Re-applying the saved token re-broadcasts the right identity and it wins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Defense in depth:&lt;/strong&gt; treat a membership row I &lt;em&gt;can't read&lt;/em&gt; as &lt;strong&gt;unknown&lt;/strong&gt;, never as a downgrade. A real cancellation returns a readable row that says "not premium." An empty result means "I don't know," and "I don't know" must never silently flip someone to free.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On mobile, none of this happens. There's no shared &lt;code&gt;BroadcastChannel&lt;/code&gt;, no per-origin token in a storage bucket every tab can see. The web's gift is that "separate client" is a polite fiction. Global state you didn't know was global is the most expensive kind.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Apply it:&lt;/strong&gt; on the web, auth/session state is frequently shared across the whole origin, not scoped to the object you instantiated. Before you spin up a "second, isolated" client, find out what storage key and what broadcast channel it uses. And anywhere a missing read could change a user's status, encode the difference between "the answer is no" and "I couldn't get an answer."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. The checkout my payment processor wouldn't approve
&lt;/h2&gt;

&lt;p&gt;The last one isn't a code bug at all. It's the kind of wall you only hit on the web, and it killed a launch.&lt;/p&gt;

&lt;p&gt;To take subscription payments on the web, I'd wired in a subscriptions tool whose checkout page is &lt;strong&gt;hosted on their domain&lt;/strong&gt;. Clean in theory: send the user to their hosted page, they handle the card, you get a webhook. The catch is that the company that actually moves the money, my payment processor, requires the checkout to run on a domain &lt;em&gt;they've approved&lt;/em&gt; for my account. And they wouldn't approve a checkout page sitting on a third party's domain.&lt;/p&gt;

&lt;p&gt;So the elegant hosted-checkout path was a dead end before a single real card touched it. Not because of a bug in my code. Because of where the page lived.&lt;/p&gt;

&lt;p&gt;The fix was to &lt;strong&gt;remove a layer, not add one.&lt;/strong&gt; I dropped the hosted-checkout middleman on the web and integrated the payment processor &lt;em&gt;directly&lt;/em&gt;, as an overlay on my own already-approved domain. The iPhone build never changed (it uses native in-app purchases and never touched any of this). Only the web path got simpler by getting shorter.&lt;/p&gt;

&lt;p&gt;The lesson generalizes way past payments: on the web especially, every service you bolt on "to make things easier" is also a new party who can say no, on their schedule, for their reasons. A hosted page on someone else's domain, an embed that needs allow-listing, an OAuth app pending review. Each is a dependency you don't control, sitting on your critical path.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Apply it:&lt;/strong&gt; when you add a third party to your money path, check &lt;em&gt;whose domain the user actually transacts on&lt;/em&gt; and who has to approve it, before you build around it. And keep your integration shallow enough that "rip out the middleman and go direct" stays a one-day change, not a rewrite.&lt;/p&gt;
&lt;/blockquote&gt;




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

&lt;p&gt;Three bugs, one shape. The browser shares more state than you think (a login leaked across "isolated" clients), trusts you less than you think (a pop-up needs a live human gesture), and hands you less control than you think (a checkout you don't get to host). And not one of them announced itself. They returned 200s and &lt;code&gt;true&lt;/code&gt;s and blank screens while the actual product quietly broke.&lt;/p&gt;

&lt;p&gt;Mobile lets you reach for the OS and mostly get a yes. The web makes you prove intent, share an origin, and ask permission. Porting isn't recompiling. It's relearning the platform's rules, usually one silent failure at a time.&lt;/p&gt;




&lt;h3&gt;
  
  
  What I'm building
&lt;/h3&gt;

&lt;p&gt;The app is &lt;strong&gt;SomeYum&lt;/strong&gt;, and it takes the nightly "what do I eat today?" decision off your plate. You swipe through a handful of dishes (not 200), say yes to one, and get the recipe. It learns your taste from what you swipe, speaks 15 languages, and now it runs on the web too, browser physics and all. Free to use; premium is $4.99/mo or $29.99/yr, no trial games.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🌐 Try it / read the build log: &lt;strong&gt;&lt;a href="https://visieasy.com" rel="noopener noreferrer"&gt;https://visieasy.com&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;📱 App Store: &lt;strong&gt;&lt;a href="https://apps.apple.com/app/id6748638722" rel="noopener noreferrer"&gt;https://apps.apple.com/app/id6748638722&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've shipped a mobile app to the web: which browser-only rule bit you first? Pop-ups, storage, CORS, gestures? The comments are where I'm collecting these. 👇&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>frontend</category>
      <category>mobile</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Read the Claude Tag Launch Twice - Here's the Control Surface Devs Now Own</title>
      <dc:creator>Mykola Kondratiuk</dc:creator>
      <pubDate>Wed, 24 Jun 2026 06:08:10 +0000</pubDate>
      <link>https://dev.to/itskondrat/i-read-the-claude-tag-launch-twice-heres-the-control-surface-devs-now-own-4h9e</link>
      <guid>https://dev.to/itskondrat/i-read-the-claude-tag-launch-twice-heres-the-control-surface-devs-now-own-4h9e</guid>
      <description>&lt;p&gt;canonical_url:&lt;/p&gt;

&lt;p&gt;Yesterday an AI moved into Slack and didn't leave. Not as a bot you /invoke. As a standing presence in the channel.&lt;/p&gt;

&lt;p&gt;Anthropic shipped Claude Tag on June 23. One Claude per channel, shared by the team, and in ambient mode it watches threads, flags relevant info, follows up on stalled work, and can act on connected tools without anyone prompting it. I read the announcement, then read it again, because the interesting part isn't a capability. It's a category change, and it lands squarely on the people who wire these things up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reactive and ambient are two different control surfaces
&lt;/h2&gt;

&lt;p&gt;Every AI integration most of us have shipped is reactive. A human calls it, a human reads the output, a human decides. That request/response shape has a free safety property baked in: there's a person on both ends of every interaction.&lt;/p&gt;

&lt;p&gt;Ambient removes the call. Sometimes it removes the read too. The AI is triggered by events in the channel, not by a person typing. If you've built event-driven systems, you already know the failure modes - the trigger fires when you didn't expect, the side effect runs while nobody's watching, and the audit log is the only record that it happened at all.&lt;/p&gt;

&lt;p&gt;So treating ambient AI like "reactive AI, but in Slack" is a category error in code, not just in policy. The control surface is different. Reactive: you gate the invocation. Ambient: you gate two separate things - perception and action - and they are not the same gate.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two gates devs actually configure
&lt;/h2&gt;

&lt;p&gt;When I mapped Claude Tag onto a system diagram, the governance question stopped being abstract and became two concrete config decisions someone on the eng side owns:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gate 1 - scope of perception. What is it allowed to notice?&lt;/strong&gt; Which channels it sits in, which threads, which connected tools it can read. This is a read-scope problem and it behaves like one. An ambient agent reading &lt;code&gt;#incidents&lt;/code&gt; is a different blast radius than one reading &lt;code&gt;#design-crit&lt;/code&gt;. Every channel you add to its perception is an input you've now made actionable, because nothing gets acted on that wasn't first observed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gate 2 - perception-to-action threshold. When does noticing become acting?&lt;/strong&gt; This is the gate people will under-configure. There are at least three distinct modes hiding under "it helps":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flag-only      -&amp;gt; it tells a human, human acts        (read-only)
follow-up       -&amp;gt; it nudges/pings without side effects (low-write)
autonomous      -&amp;gt; it mutates a connected tool itself   (write)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Tag gives admins tool-access controls, spend limits, and full audit logs - which is exactly the toolkit you'd want for Gate 2. But the defaults are a decision, and "whoever clicked enable" is not a great owner for where flag-only ends and autonomous begins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is a dev problem, not PM scope-creep
&lt;/h2&gt;

&lt;p&gt;I'll be direct, because this is Dev.to and someone's already typing it: this isn't a PM showing up to govern your integration. The perception scope and the action threshold are configured in the same place you configure any other service account - tokens, read scopes, write permissions, audit retention. It's least-surprise engineering applied to an agent that fires on its own.&lt;/p&gt;

&lt;p&gt;The piece that's genuinely new is that the trigger is ambient. A cron job runs on a schedule you wrote. A webhook fires on an event you registered. An ambient agent decides for itself that a thread looks stalled and a follow-up is warranted. That judgment is the new variable, and the only thing standing between "helpful nudge" and "unrequested write to prod tooling" is where you set Gate 2.&lt;/p&gt;

&lt;p&gt;So before ambient mode gets flipped on in your workspace, the useful thing isn't a policy doc. It's one line in the config review: this agent may &lt;em&gt;notice&lt;/em&gt; X, and it may &lt;em&gt;act&lt;/em&gt; up to Y, and past Y a human is in the loop. Write that line on purpose, or inherit whatever the default was.&lt;/p&gt;

&lt;p&gt;Where would you put Y - flag-only, follow-up, or let it act? And who on your team is actually making that call right now?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Cross-posted from my Substack on AI-native project management.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>leadership</category>
      <category>ai</category>
      <category>projectmanagement</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Never trust the client: 9 production lessons from 5 months building an app solo</title>
      <dc:creator>Mykola Kondratiuk</dc:creator>
      <pubDate>Mon, 22 Jun 2026 13:03:01 +0000</pubDate>
      <link>https://dev.to/itskondrat/never-trust-the-client-9-production-lessons-from-5-months-building-an-app-solo-3ff1</link>
      <guid>https://dev.to/itskondrat/never-trust-the-client-9-production-lessons-from-5-months-building-an-app-solo-3ff1</guid>
      <description>&lt;p&gt;I'm a solo founder. My only teammate is an AI coding agent. In five months the two of us shipped close to &lt;strong&gt;40 releases&lt;/strong&gt; of a Flutter + Supabase app that picks your dinner for you.&lt;/p&gt;

&lt;p&gt;People assume that means the AI writes the app and I sip coffee. It's the opposite. The AI is fast hands with zero taste, so the bottleneck moved from &lt;em&gt;typing&lt;/em&gt; to &lt;em&gt;thinking&lt;/em&gt; — which is exactly where it should be. And thinking is where I made every one of these mistakes.&lt;/p&gt;

&lt;p&gt;None of these are "I forgot a semicolon" mistakes. Each one shipped to production, ran quietly for a while, and taught me something I'd now tattoo on every builder. The ones that hurt most had a common shape: &lt;strong&gt;they never crashed.&lt;/strong&gt; They just silently stopped the app from doing the one thing it exists to do.&lt;/p&gt;

&lt;p&gt;Here they are, in the order they punched me.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Silent failures are the dangerous ones. Alert on your critical path.
&lt;/h2&gt;

&lt;p&gt;The app picks your dinner using an LLM. At the time, that model was one of Google's. One day Google retired it — just shut it down, the way big companies do on a schedule you don't control.&lt;/p&gt;

&lt;p&gt;Nothing crashed. No error on my phone, no red dashboard, no alarm. The app looked completely fine. It just &lt;strong&gt;silently stopped recommending anything to anyone for ten straight days.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I found out because a user messaged me: &lt;em&gt;"hey, is the app broken? nothing's loading."&lt;/em&gt; That is the single worst way to learn your product is down — from the person you're supposed to be serving.&lt;/p&gt;

&lt;p&gt;The bugs that crash loudly are easy; your stack traces point right at them. The dangerous ones don't break anything. They quietly stop the thing that matters while every health check stays green.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Apply it:&lt;/strong&gt; put a synthetic check on your &lt;em&gt;actual&lt;/em&gt; critical path, not just "is the server up." For me that's "does a recommendation request return a real dish in the last hour." Alert on the outcome your users care about, and never assume a third-party dependency will stay alive just because it was alive yesterday.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. Never trust the client. Validate on the server, and lock down who can read each row.
&lt;/h2&gt;

&lt;p&gt;My app has a premium tier. The bug: I let the &lt;em&gt;phone&lt;/em&gt; decide whether someone was premium. The client would tell my server "hey, I'm a paying customer," and the server just... believed it. No proof.&lt;/p&gt;

&lt;p&gt;Anyone who knew what they were doing could flip that flag and get premium free, forever.&lt;/p&gt;

&lt;p&gt;But while fixing that, I found the scarier one underneath it: a gap in my database row-level security meant a user could, in theory, read &lt;em&gt;other people's&lt;/em&gt; data. That's not a missing-feature bug. That's a someone-could-get-hurt bug.&lt;/p&gt;

&lt;p&gt;I moved every entitlement check to the server (where the user can't touch it), wired premium status to the payment provider's webhook instead of the client's word, and audited every table's read policy.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Apply it:&lt;/strong&gt; assume the user can lie to anything running on their device — the phone, the browser, the network tab — because they can. Authorization lives on the server. And "row-level security is on" is not the same as "row-level security is correct" — actually test that user A cannot read user B's rows.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. With an LLM, every blank you leave gets filled with chaos.
&lt;/h2&gt;

&lt;p&gt;Early on, my app started recommending dinner... in Chinese. To English speakers. Nobody asked for Chinese. I don't speak Chinese.&lt;/p&gt;

&lt;p&gt;What happened: when I set up the model prompt, I never explicitly told it what language to respond in. And an LLM doesn't leave a blank blank — it confidently fills it with whatever it feels like. So it picked a language. Sometimes Chinese. Sometimes who-knows.&lt;/p&gt;

&lt;p&gt;The fix was one line: &lt;code&gt;respond in English&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is the whole job of prompting in production. The model is not reading your mind; it's pattern-matching into the gaps you left. (Same model, months later, taught me the sequel to this lesson: today's "thinking" models burn hidden reasoning tokens against your output budget, so if you don't explicitly turn that down, your responses silently truncate. Another blank, another surprise.)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Apply it:&lt;/strong&gt; be painfully explicit. Language, format, length, tone, what to do when it's unsure — pin all of it. Then feed the model garbage and adversarial inputs in testing and watch what it does with the gaps, because your users will find them.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  4. Monitor your money path harder than anything else.
&lt;/h2&gt;

&lt;p&gt;Someone actually &lt;em&gt;wanted&lt;/em&gt; to pay me. They used the free app, liked it, tapped "subscribe" with their wallet open... and my paywall showed them a &lt;strong&gt;blank screen.&lt;/strong&gt; No prices. No button. Nothing.&lt;/p&gt;

&lt;p&gt;Why: on startup the app asked the store for my subscription prices, that request quietly failed, and the code &lt;strong&gt;never retried.&lt;/strong&gt; So for some users, the single most important screen in the entire business was broken and showing nothing.&lt;/p&gt;

&lt;p&gt;I had no idea. Nobody emails you "I tried to give you money and couldn't." They just leave. I added retries and monitoring on exactly that moment and fixed it — but I will never know how many people I lost first.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Apply it:&lt;/strong&gt; instrument the moment someone tries to pay you more heavily than any other event in your app. Track "paywall rendered with prices" as an explicit success metric, alert when it dips, and never let a one-shot network call guard your revenue without a retry. Silent revenue loss is the most expensive bug there is, precisely because it never shows up as a bug.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  5. Ship lean. Every unused permission, library, and line is a liability.
&lt;/h2&gt;

&lt;p&gt;Apple rejected my app. Three reasons, all useful if you're about to submit:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;My subscription products weren't configured to match &lt;em&gt;exactly&lt;/em&gt; across App Store Connect and my code (prices and terms have to line up perfectly).&lt;/li&gt;
&lt;li&gt;I needed a public refund-policy page online before they'd approve a paid app.&lt;/li&gt;
&lt;li&gt;My favorite: they flagged me for &lt;strong&gt;location and tracking code I wasn't even using.&lt;/strong&gt; It was dead code, left over from an abandoned idea, just sitting there. Apple saw the API references, assumed I was tracking people, and said no.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I ripped the dead code out, fixed the subscription config, published the policy page, resubmitted, got in.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Apply it:&lt;/strong&gt; every permission you declare, every SDK you link, every line you keep is something you have to defend — to a reviewer, to a security audit, to your future self. Delete what you don't use &lt;em&gt;before&lt;/em&gt; someone else makes you. Rejection isn't failure; it's a checklist you didn't know existed.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  6. Treat your AI model as a swappable commodity. Don't marry a provider.
&lt;/h2&gt;

&lt;p&gt;The model that picks dinner used to be one provider's. It worked, but it was a little slow and a little expensive — and for an app whose entire magic is &lt;em&gt;speed&lt;/em&gt;, slow is death.&lt;/p&gt;

&lt;p&gt;I swapped it for a different model from a different company in one afternoon. Same app, same features, recommendations come back about &lt;strong&gt;42% faster&lt;/strong&gt;, and it costs less to run.&lt;/p&gt;

&lt;p&gt;The only reason that was an afternoon and not a rewrite is that I'd put the model behind a thin proxy layer with the model ID in exactly one place in my code. New models ship every few months, each cheaper or faster than the last. If your provider is welded into 40 call sites, you can't take that deal.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Apply it:&lt;/strong&gt; put one seam between your app and any LLM (a proxy function, an interface, whatever). Keep the model name in a single constant. Then "the new model is 2x cheaper" becomes a config change instead of a project. Bonus: nobody ever posts a screenshot of "42% faster," but your users feel invisible wins even when they can't name them.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  7. Subtraction is a feature. Deleting code is the work, not a break from it.
&lt;/h2&gt;

&lt;p&gt;My favorite thing I did all month wasn't building a feature. It was &lt;strong&gt;deleting 2,012 lines of my own code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Old experiments I never finished. Clever solutions to problems I no longer had. Three different ways of doing the same thing. I ripped it all out, and the app does &lt;em&gt;exactly&lt;/em&gt; what it did before — same features, same speed, just less surface area for bugs to hide in.&lt;/p&gt;

&lt;p&gt;Every line you keep is a line you maintain, debug, and carry forever. Less code is less liability. This isn't a coding quirk — writers cut paragraphs, designers remove elements. The hard, valuable skill in anything creative is the nerve to remove what doesn't earn its place.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Apply it:&lt;/strong&gt; schedule deletion like you schedule features. If a code path hasn't justified itself in months, it's not an asset, it's debt with a nice haircut.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  8. Make reversible bets, and have the nerve to actually reverse them.
&lt;/h2&gt;

&lt;p&gt;I once shipped a big new push across my marketing site at 9am, felt great, made coffee — then looked at the site like a stranger would and realized it muddied the one clear message I actually wanted people to get. It wasn't &lt;em&gt;bad&lt;/em&gt;. It was &lt;em&gt;wrong for right now&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I reverted the whole thing the same day. Hours of work, undone.&lt;/p&gt;

&lt;p&gt;Shipping fast gets all the hype; knowing when to &lt;em&gt;un&lt;/em&gt;-ship fast is just as important and almost never talked about. The trap is sunk cost — "I worked hard on this, so I have to keep it." But the work is gone either way. The only question left is whether keeping it makes the product better.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Apply it:&lt;/strong&gt; prefer changes you can roll back cleanly (feature flags, small PRs, decoupled deploys). Then judge a shipped change on the product as it is now, not on the effort you already spent. Don't fall in love with your own code.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  9. Most of building is invisible plumbing that has to be perfect. That's the job, not a detour.
&lt;/h2&gt;

&lt;p&gt;A few of the least glamorous things I did, that no user will ever thank me for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Migrated the payment system twice in one week&lt;/strong&gt; to get web payments, taxes, refunds, and multi-country handling actually correct. Two full rewrites of the most boring, most critical part of the app in seven days.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three months on SEO&lt;/strong&gt; — pages, tiny tags, redirects, structured data, the same post rewritten four times for one keyword. Zero dopamine. But you can build the best app in the world and if nobody can find it, it doesn't exist. A great product nobody discovers isn't a product, it's a secret.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spent a day tracing one broken deploy&lt;/strong&gt; to a transitive dependency three levels deep that I never directly installed, which quietly became incompatible with my web build and took down &lt;em&gt;both&lt;/em&gt; of my sites. My code was fine. The bug was, as always, not where I thought it was.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The build-in-public highlight reels are all shiny features and launch-day champagne. The actual job is mostly this: the unglamorous 80% that has to work before anyone sees the 20%.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Apply it:&lt;/strong&gt; if it feels like you're grinding on infra, taxes, edge cases, and distribution instead of "real progress" — you're not behind. That &lt;em&gt;is&lt;/em&gt; the work. Pin your dependency versions, read what's actually in your &lt;code&gt;node_modules&lt;/code&gt;/&lt;code&gt;pubspec&lt;/code&gt;, and treat distribution as half the product, not an afterthought.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Two more that aren't bugs, but cost the most to learn
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Honesty compounds; fake social proof spends trust.&lt;/strong&gt; When I launched, every template screamed "add testimonials, look bigger." So I dropped placeholder reviews and an inflated user count on my own site, told myself I'd fix it later, and felt a little gross every time I opened it. Eventually I deleted all of it and put my real, much smaller numbers up. People can smell fake — and the moment someone catches one fake number, they stop believing the true ones too. Small and honest beats big and fake, because honesty is the one thing a tiny app can offer that the giants usually won't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't assume your users are like you.&lt;/strong&gt; I'm Ukrainian; I think in English when I code, so I launched English-only. Most people on Earth aren't browsing in English. The app now speaks &lt;strong&gt;15 languages&lt;/strong&gt;, and not the lazy way where only the buttons translate — it rewrites the actual dish names and recipes live. The most expensive assumption you can make as a builder is that your users share your language, your phone, and your life. They don't.&lt;/p&gt;

&lt;p&gt;I also gave users &lt;em&gt;less&lt;/em&gt; for free on purpose (tightened the daily free limit) and ripped out all the tracking — no ad SDKs, no location, no cross-app cookies — because I kept asking "do I actually need this to make the app good?" and the answer was almost always no. Free can't be infinite or the thing dies and helps no one; and trust is worth more than data when you're asking people to tell you what they eat every day.&lt;/p&gt;




&lt;h2&gt;
  
  
  The honest scoreboard
&lt;/h2&gt;

&lt;p&gt;In five months, solo, with an AI as my only teammate, I:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;let a third party silently kill my app's brain for 10 days&lt;/li&gt;
&lt;li&gt;shipped a security hole that gave away premium (and nearly leaked user data)&lt;/li&gt;
&lt;li&gt;got rejected by Apple over code I forgot to delete&lt;/li&gt;
&lt;li&gt;showed a blank paywall to someone who wanted to pay&lt;/li&gt;
&lt;li&gt;deleted features I was &lt;em&gt;most&lt;/em&gt; excited to build because testing said no one wanted them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's a lot of mistakes for one person. And every one is in this post, because I'd rather show you the real thing than a polished one.&lt;/p&gt;

&lt;p&gt;Here's what's underneath all of it: building isn't a straight line from idea to launch. It's a loop — ship, watch it break, fix it, forever. The people who "make it" aren't the ones who avoid mistakes. They're the ones who show up the next morning after each one.&lt;/p&gt;




&lt;h3&gt;
  
  
  What I'm building
&lt;/h3&gt;

&lt;p&gt;The app is &lt;strong&gt;SomeYum&lt;/strong&gt; — it takes the nightly "what do I eat today?" decision off your plate. You swipe through a handful of dishes (not 200), say yes to one, and get the recipe. It learns your taste from what you actually swipe, speaks 15 languages, and there's a literal spin-the-wheel panic button for when you want &lt;em&gt;zero&lt;/em&gt; choices. Free to use; premium is $4.99/mo or $29.99/yr with no trial games.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🌐 Try it / read the build log: &lt;strong&gt;&lt;a href="https://visieasy.com" rel="noopener noreferrer"&gt;https://visieasy.com&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;📱 App Store: &lt;strong&gt;&lt;a href="https://apps.apple.com/app/id6748638722" rel="noopener noreferrer"&gt;https://apps.apple.com/app/id6748638722&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building something solo, especially with an AI in the loop: which of these have you already hit? I'm collecting war stories, and the comments here are where the best ones live. 👇&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>indiehackers</category>
      <category>webdev</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Track What My AI Costs Every Day - Here's the Scoreboard Most Teams Skip</title>
      <dc:creator>Mykola Kondratiuk</dc:creator>
      <pubDate>Wed, 17 Jun 2026 08:15:28 +0000</pubDate>
      <link>https://dev.to/itskondrat/i-track-what-my-ai-costs-every-day-heres-the-scoreboard-most-teams-skip-h5i</link>
      <guid>https://dev.to/itskondrat/i-track-what-my-ai-costs-every-day-heres-the-scoreboard-most-teams-skip-h5i</guid>
      <description>&lt;p&gt;A headline went around last week: 2026 is running over a thousand tech layoffs a day, and roughly 55% of them name AI as the cause.&lt;/p&gt;

&lt;p&gt;Then I hit the line buried underneath it. Experts flagged that the productivity gains those cuts are based on mostly haven't shown up at scale yet.&lt;/p&gt;

&lt;p&gt;So companies are cutting headcount on a forecast of AI output that hasn't arrived. That's not an engineering problem or a PM problem. It's a measurement problem. And it's the exact thing I deal with every day, so let me show you the boring tool that fixes it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying is not delivering, and the gap is where careers get decided
&lt;/h2&gt;

&lt;p&gt;I run AI through real delivery work. Not demos. Actual shipped output with deadlines attached.&lt;/p&gt;

&lt;p&gt;The most expensive lesson I've learned: deploying a tool and delivering value with it are two different events, and there's a pile of unglamorous work between them.&lt;/p&gt;

&lt;p&gt;Deploying is easy. You wire it up, it generates something, the demo looks great, the slide says "40% faster."&lt;/p&gt;

&lt;p&gt;Delivering is when you come back two weeks later and ask the question nobody enjoys: what did this actually return, after I subtract what it cost me to run and babysit it?&lt;/p&gt;

&lt;p&gt;Most teams never ask. They deployed, so they assume they delivered. That assumption is now being used to justify layoffs. If you can't tell the difference with a number, you're guessing with a bigger budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  The accountability layer was the measurement layer
&lt;/h2&gt;

&lt;p&gt;Gergely Orosz wrote a piece this week about Meta restructuring into AI pods and stripping out a chunk of the program-management accountability layer in the name of speed.&lt;/p&gt;

&lt;p&gt;Here's the trap. That accountability layer was the measurement layer. The people whose job was "did this work, what did it cost, do we keep it" weren't overhead. They were the part of the system that notices when a fast-moving bet is moving fast in the wrong direction.&lt;/p&gt;

&lt;p&gt;Pull that out while you bet the company on AI and you don't get a leaner org. You get one that can no longer tell whether its biggest bet is paying off.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scoreboard, as actual data
&lt;/h2&gt;

&lt;p&gt;Enough principle. Here's the shape I keep for any AI workflow I depend on. It lives in one tracked file, not a dashboard with a vendor logo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ai-scoreboard.yml  - one entry per workflow you depend on&lt;/span&gt;
&lt;span class="na"&gt;workflow&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pr-triage-agent&lt;/span&gt;
&lt;span class="na"&gt;baseline_minutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;45&lt;/span&gt;        &lt;span class="c1"&gt;# how long this took BEFORE the agent&lt;/span&gt;
&lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kolya&lt;/span&gt;                &lt;span class="c1"&gt;# one name. not "the team".&lt;/span&gt;

&lt;span class="na"&gt;cost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;tokens_usd_per_run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.42&lt;/span&gt;
  &lt;span class="na"&gt;seat_usd_per_month&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
  &lt;span class="na"&gt;steering_minutes_per_run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;   &lt;span class="c1"&gt;# the cost everyone forgets&lt;/span&gt;

&lt;span class="na"&gt;return&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;minutes_saved_per_run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;31&lt;/span&gt;     &lt;span class="c1"&gt;# vs baseline, not vs zero&lt;/span&gt;
  &lt;span class="na"&gt;output_kept_pct&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;           &lt;span class="c1"&gt;# shipped without a human redo&lt;/span&gt;

&lt;span class="na"&gt;rework_tax_pct&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;              &lt;span class="c1"&gt;# redone, overridden, or thrown out&lt;/span&gt;
&lt;span class="na"&gt;kill_if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;rework_tax_pct&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;50"&lt;/span&gt;        &lt;span class="c1"&gt;# decided in advance, no sunk-cost debate&lt;/span&gt;
  &lt;span class="na"&gt;net_minutes_saved&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;5"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing clever here. The value is in three fields people skip:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;steering_minutes_per_run&lt;/code&gt;. The time you spend prompting, correcting, and cleaning up. This is usually the biggest hidden cost and it's the one demos never show.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rework_tax_pct&lt;/code&gt;. The share of output you had to redo. When this creeps up, the tool is quietly costing more than it looks, even though it still "works."&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kill_if&lt;/code&gt;. Thresholds decided in advance. When a workflow crosses them, it gets cut without a meeting about how much you've already invested.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A quick gut check you can run in your head on any AI workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;net_value = minutes_saved - steering_minutes - (rework_tax * output_volume)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that comes out near zero or negative, you deployed something that looks productive and delivers nothing. You only find that out if you write the numbers down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is the moat, not the chore
&lt;/h2&gt;

&lt;p&gt;The doom framing says AI is coming for your job. I think that's backwards for anyone who measures.&lt;/p&gt;

&lt;p&gt;The people who survive this era aren't the ones who deployed the most AI. Deploying is table stakes now. The ones who lead through it can sit in a room when budgets are tight and put a real scoreboard on the table: here's what we ran, what it cost, what it returned, what we killed and why.&lt;/p&gt;

&lt;p&gt;That's extreme ownership of AI output. You don't get to claim ROI you never measured. But if you can prove it, you're very hard to cut, because you're the one person who can tell AI that works from AI that just looks busy. In a year defined by exactly that confusion, that skill is the whole moat.&lt;/p&gt;

&lt;p&gt;A thousand cuts a day are being justified by a return nobody's keeping receipts for. So I'll ask you the way I ask myself every Friday: the AI you're running right now, are you measuring what it delivers, or trusting the slide? And if someone asked you to defend the spend on Monday, what would you actually put on the table?&lt;/p&gt;

</description>
      <category>leadership</category>
      <category>ai</category>
      <category>career</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Fable 5 Went Dark Friday Night. I Ran My Critical Workflow on a Backup Saturday - Here's What Broke</title>
      <dc:creator>Mykola Kondratiuk</dc:creator>
      <pubDate>Mon, 15 Jun 2026 07:42:36 +0000</pubDate>
      <link>https://dev.to/itskondrat/fable-5-went-dark-friday-night-i-ran-my-critical-workflow-on-a-backup-saturday-heres-what-broke-349d</link>
      <guid>https://dev.to/itskondrat/fable-5-went-dark-friday-night-i-ran-my-critical-workflow-on-a-backup-saturday-heres-what-broke-349d</guid>
      <description>&lt;p&gt;On Friday afternoon a government order hit Anthropic, and by Saturday morning Fable 5 and Mythos 5 were disabled for every customer worldwide. Not deprecated. Gone. Two days later OpenAI shut Sora down because it was losing fifteen million dollars a day.&lt;br&gt;
&lt;em&gt;Disclosure: This article was written with AI assistance. I use AI tools as part of my workflow for building and writing about AI-native PM practices.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I don't have a strong take on the politics. What I had was a smaller, more selfish question at 8am Saturday: if I'd staffed a real workflow on either of those, what would I actually do right now?&lt;/p&gt;

&lt;p&gt;So I tested it. Here's what happened.&lt;/p&gt;
&lt;h2&gt;
  
  
  "We'd just switch" is a hope, not a plan
&lt;/h2&gt;

&lt;p&gt;I'd been telling myself I had redundancy for months. If my main model fell over, I'd move to a second vendor. Easy.&lt;/p&gt;

&lt;p&gt;The problem with that sentence is that I had never once run it. A fallback you've never executed isn't a fallback. It's a guess with good posture.&lt;/p&gt;

&lt;p&gt;So Saturday I took my single most critical AI-dependent workflow - a spec-to-task-breakdown pipeline I lean on every day - and ran it end to end on a different vendor's model. One time. Just to find out whether the guess held.&lt;/p&gt;

&lt;p&gt;It didn't.&lt;/p&gt;
&lt;h2&gt;
  
  
  Break #1: the prompt was overfit to one model
&lt;/h2&gt;

&lt;p&gt;The first thing that broke was the prompt itself. My prompt had drifted into a shape that worked beautifully on the model I built it against. Tight, terse, lots of implicit structure the model had learned to fill in.&lt;/p&gt;

&lt;p&gt;The backup model read the same prompt and produced mush. Not wrong exactly, just vague and unstructured, the kind of output you'd toss.&lt;/p&gt;

&lt;p&gt;The fix was real work, not a config flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- summarize the spec and break it into tasks
&lt;/span&gt;&lt;span class="gi"&gt;+ You are breaking a spec into engineering tasks.
+ Output JSON only, matching this shape:
+ { "tasks": [{ "title": "", "estimate_pts": 0, "depends_on": [] }] }
+ Rules:
+ - every task must be independently shippable
+ - no task larger than 3 points; split if larger
+ - depends_on references task titles, not indexes
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Model A filled in all that structure on its own. Model B needed it spelled out. That's twenty minutes of restructuring I'd much rather spend on a calm Saturday than during an actual outage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Break #2: a silent tool-call dependency
&lt;/h2&gt;

&lt;p&gt;The second break scared me more because it was invisible. One step in the pipeline depended on a tool call - a function the model invokes to pull live data. The backup model's tool-calling format was different enough that the call silently no-op'd.&lt;/p&gt;

&lt;p&gt;The output still looked plausible. It just used stale data and didn't tell me. That's the worst failure mode there is: confidently wrong, no error, no flag. I only caught it because I was looking for trouble. On a normal day that bad output flows downstream and someone makes a decision on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Availability belongs on the risk register
&lt;/h2&gt;

&lt;p&gt;Here's the reframe I walked away with. We already handle the API being &lt;em&gt;down&lt;/em&gt;. You get a 503, you back off, you retry, it comes back. That's an outage with an SLA and a status page that eventually goes green.&lt;/p&gt;

&lt;p&gt;This is the model being &lt;em&gt;gone&lt;/em&gt;. No SLA. No restore ETA. No green status page, because it isn't coming back. A policy order or a vendor's burn-rate review can end it overnight, and you find out the same way everyone else does.&lt;/p&gt;

&lt;p&gt;For a service you don't control and can't restore, that's a single point of failure on your critical path. We'd never ship that for a database. Most of us are shipping it for the model doing half the thinking.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one-pager that deletes your worst hour
&lt;/h2&gt;

&lt;p&gt;The cheapest move turned out to be the most useful. The first hour after a model goes dark gets burned figuring out &lt;em&gt;what just broke&lt;/em&gt; - which workflows touched that model, what versions, where the outputs live.&lt;/p&gt;

&lt;p&gt;IBM found 88% of enterprises don't keep a complete inventory of the AI and agents they run. You can't reroute around a dead model if you don't know what depended on it. So I wrote one file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;workflows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;spec-to-tasks&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;primary-vendor/model-a&lt;/span&gt;
    &lt;span class="na"&gt;criticality&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;must-survive&lt;/span&gt;
    &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tested 2026-06-13, prompt needs restructure&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;standup-digest&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;primary-vendor/model-a&lt;/span&gt;
    &lt;span class="na"&gt;criticality&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;can-wait&lt;/span&gt;
    &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;none, recovery order documented&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;video-assets&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openai/sora&lt;/span&gt;
    &lt;span class="na"&gt;criticality&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;can-wait&lt;/span&gt;
    &lt;span class="na"&gt;export_path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;download MP4s + project json before EOL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last line is the Sora lesson. When a vendor kills a &lt;em&gt;product&lt;/em&gt;, not just a model, you also have to ask where your outputs go and how you get them out. One extra column.&lt;/p&gt;

&lt;h2&gt;
  
  
  The point isn't fear
&lt;/h2&gt;

&lt;p&gt;I want to be clear, because the lazy version of this post is "AI is unreliable, panic." It isn't, and that's not useful. Depending on these models is the right call. The teams that win aren't the ones who avoided the dependency. They're the ones who can keep the work moving the morning it disappears.&lt;/p&gt;

&lt;p&gt;That competence costs an afternoon to build and almost nobody has built it yet:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run your most critical workflow on a second model once. The rehearsal is the whole instrument.&lt;/li&gt;
&lt;li&gt;Sort workflows into must-survive-today vs can-wait. Only the short list earns a tested fallback.&lt;/li&gt;
&lt;li&gt;Keep a one-page workflow-to-model list so the first lost hour becomes a glance.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I ran my test on a quiet Saturday and it cost me twenty minutes and a little ego. The alternative was running it for the first time on the morning it counted.&lt;/p&gt;

&lt;p&gt;What would break first in your stack if your main model wasn't there tomorrow - and have you ever actually checked?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I Lead AI Agents Every Day - Here Are 5 Shifts No Standard Tells You How to Make</title>
      <dc:creator>Mykola Kondratiuk</dc:creator>
      <pubDate>Fri, 12 Jun 2026 07:09:26 +0000</pubDate>
      <link>https://dev.to/itskondrat/i-lead-ai-agents-every-day-here-are-5-shifts-no-standard-tells-you-how-to-make-1pg4</link>
      <guid>https://dev.to/itskondrat/i-lead-ai-agents-every-day-here-are-5-shifts-no-standard-tells-you-how-to-make-1pg4</guid>
      <description>&lt;p&gt;A Google DeepMind safety lead said this week that they're putting $10M behind multi-agent safety because "there just isn't really a field of research for multi-agent safety yet."&lt;br&gt;
&lt;em&gt;Disclosure: This article was written with AI assistance. I use AI tools as part of my workflow for building and writing about AI-native PM practices.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I read that and laughed, because I'm already running the thing the research field doesn't exist for yet. Most of us are. You spin up a couple of agents, hand them work, and somewhere in there you quietly become a manager of workers that don't think like workers.&lt;/p&gt;

&lt;p&gt;Two days before that, PMI published the first official standard for AI in project work. It's a solid document. It also leaves the entire "how do you actually do this on a Tuesday" layer to you. So here's my Tuesday layer: five shifts I had to make, each one learned by getting it wrong first.&lt;/p&gt;
&lt;h2&gt;
  
  
  You stop filling the queue and start drawing the line
&lt;/h2&gt;

&lt;p&gt;My first instinct with an agent was the same as with a person: here's work, go.&lt;/p&gt;

&lt;p&gt;That broke the first time an agent made a reasonable decision on something that turned out to be irreversible. It wasn't the agent's fault. I never told it which decisions were one-way doors.&lt;/p&gt;

&lt;p&gt;So now the first artifact I write isn't a task list. It's a boundary file. Something like this lives next to the work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# decision-boundaries.yml&lt;/span&gt;
&lt;span class="na"&gt;autonomous&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;reformat, refactor, rename within a module&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;anything reversible with a git revert&lt;/span&gt;
&lt;span class="na"&gt;escalate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;schema changes, public API shape&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deletes, migrations, anything touching prod data&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;spend over $0 or any external send&lt;/span&gt;
&lt;span class="na"&gt;on_unsure&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stop_and_ask&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That file does more for me than any standup. Leadership moved from assigning the work to defining what may be decided without me.&lt;/p&gt;

&lt;h2&gt;
  
  
  You read work you never watched happen
&lt;/h2&gt;

&lt;p&gt;I used to review work I'd seen get built. I knew the steps, so "looks right" was usually safe.&lt;/p&gt;

&lt;p&gt;Then I started getting finished diffs with no memory of how they came to be. "Looks right" stopped being safe. The code was clean and the reasoning under it was wrong in a way you only catch if you go digging.&lt;/p&gt;

&lt;p&gt;The skill now is judging a result cold, with zero context on the path. Ethan Mollick wrote this week about a model holding twelve hours of focus on one spec. When the attention window outlasts mine, my job isn't checking steps. It's scoping the spec so tightly the steps don't need a babysitter.&lt;/p&gt;

&lt;h2&gt;
  
  
  You plan capability, not headcount
&lt;/h2&gt;

&lt;p&gt;"How many engineers do I need" is a question I catch myself asking and kill.&lt;/p&gt;

&lt;p&gt;The real one: what mix of people and agents produces this outcome, and what's the human-only core I'd never hand off? The plan turned into a capability map with a deliberately protected center.&lt;/p&gt;

&lt;p&gt;Gergely Orosz's June job-market analysis lands in the same place from the data side: the roles that compound are where judgment about AI systems is the scarce input, not execution on a known stack. Capability planning is that judgment pointed at your own team.&lt;/p&gt;

&lt;h2&gt;
  
  
  You design the alarm before the fire
&lt;/h2&gt;

&lt;p&gt;Standup tells you something broke. Which means it tells you late.&lt;/p&gt;

&lt;p&gt;Workers that fail unpredictably need the alarm built up front. I keep a short tripwire list, each one a single sentence: if this observable crosses this line, halt and ping me, and here's who owns the ping.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tripwires.yml&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;watch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test_pass_rate&lt;/span&gt;
  &lt;span class="na"&gt;trip&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;100%&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;touched&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;files"&lt;/span&gt;
  &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;halt + page me&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;watch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;files_changed&lt;/span&gt;
  &lt;span class="na"&gt;trip&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;20&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;one&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;task"&lt;/span&gt;
  &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pause for scope review&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It feels too simple to matter. It has saved more bad mornings than any dashboard I've built.&lt;/p&gt;

&lt;h2&gt;
  
  
  You own the system, not the deliverable
&lt;/h2&gt;

&lt;p&gt;This is the one that's actually a promotion.&lt;/p&gt;

&lt;p&gt;Ownership used to mean the outcome is mine. It still is. The level changed. I don't own the deliverable directly anymore. I own the system that makes it: people, agents, and the rules between them. That's the only level that scales.&lt;/p&gt;

&lt;p&gt;Boris Cherny, who runs Claude Code, said this week he hasn't written a line of code himself in eight months. People hear a flex. I hear the shift in one sentence: stopped producing the work, started owning the system that produces it. Bigger job, not a smaller one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where are you on these
&lt;/h2&gt;

&lt;p&gt;I'm not clean on all five. Solid on three, shaky on two, and the shaky ones cost me the most.&lt;/p&gt;

&lt;p&gt;Rate yourself one to five on each, fast. The two you score lowest are the two behaviors that move you this quarter. Which one did you make first, and which are you still avoiding?&lt;/p&gt;

&lt;p&gt;Tags: #projectmanagement #ai #career&lt;/p&gt;

</description>
      <category>projectmanagement</category>
      <category>leadership</category>
      <category>ai</category>
      <category>career</category>
    </item>
    <item>
      <title>I Took the Keyboard Back From an Agent Mid-Task - Here's What the New PMP Can't Test</title>
      <dc:creator>Mykola Kondratiuk</dc:creator>
      <pubDate>Fri, 05 Jun 2026 06:22:24 +0000</pubDate>
      <link>https://dev.to/itskondrat/i-took-the-keyboard-back-from-an-agent-mid-task-heres-what-the-new-pmp-cant-test-55n1</link>
      <guid>https://dev.to/itskondrat/i-took-the-keyboard-back-from-an-agent-mid-task-heres-what-the-new-pmp-cant-test-55n1</guid>
      <description>&lt;p&gt;A few weeks back I had an agent reconciling a vendor list. It ran clean. No error, no crash, output looked right. Then I noticed it had merged two suppliers that share a parent company into a single row, which would have thrown off every spend rollup downstream by a real number.&lt;/p&gt;

&lt;p&gt;I stopped it and fixed it by hand. Not because anything alerted me. Because I'd been burned by that exact shape before, and the burn taught me something a tutorial never did.&lt;/p&gt;

&lt;p&gt;I'm telling you this because on July 9 the PMP changes, and the change points straight at that moment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed in the exam
&lt;/h2&gt;

&lt;p&gt;For the first time, the PMP makes AI mandatory content instead of an elective. The Business Environment domain goes from 8% of the exam to 26%. PMBOK 8 becomes the base. Fees climb in August.&lt;/p&gt;

&lt;p&gt;The largest project-management body on earth just put it in writing: AI fluency is core PM competency now, not a specialty track. If you've been treating "PM + AI" as a buzzword, the institution that certifies the role just disagreed with you.&lt;/p&gt;

&lt;p&gt;I think that's the right move. It's also where it gets interesting for anyone who actually ships work through agents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Certified is not practiced
&lt;/h2&gt;

&lt;p&gt;A multiple-choice exam can certify that you know what an agentic workflow is. It can check that you'll pick the textbook answer about AI risk, define non-determinism, name the correct oversight principle.&lt;/p&gt;

&lt;p&gt;That's awareness, and awareness is worth certifying.&lt;/p&gt;

&lt;p&gt;What it can't reach is the reflex that runs real work. The exam can't certify that you've handed live stakes to an agent, watched it drift, and built the instinct for when it can act versus when you take over. You don't recall that instinct. You earn it, and the only way to earn it is to need it.&lt;/p&gt;

&lt;p&gt;I learned the vendor-merge thing from the run where I caught it too late.&lt;/p&gt;

&lt;h2&gt;
  
  
  What AI fluency looks like in the editor, not the exam
&lt;/h2&gt;

&lt;p&gt;Let me put it in do-this terms. Here's the practiced version, and none of it is a question you can bubble in.&lt;/p&gt;

&lt;p&gt;You scope the agent's slice like a statement of work. Not "improve onboarding." Bounded edges, in and out defined before it touches anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;reconcile vendor list for Q2&lt;/span&gt;
&lt;span class="na"&gt;in_scope&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;dedupe exact-match names&lt;/span&gt;
&lt;span class="na"&gt;out_of_scope&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;merging distinct legal entities&lt;/span&gt;   &lt;span class="c1"&gt;# &amp;lt;- the line that would have saved me&lt;/span&gt;
&lt;span class="na"&gt;acceptance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;row count change is human-reviewed before rollup runs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You know the override moment. This one I'd put first. You only learn the veto by having needed it.&lt;/p&gt;

&lt;p&gt;You read the output for what it didn't do, not just whether what's there is correct. The skipped supplier, the untouched edge case.&lt;/p&gt;

&lt;p&gt;You design the work so a human can actually check it. If the only way to verify is to redo the whole thing, the slice was wrong.&lt;/p&gt;

&lt;p&gt;You size the blast radius before deploy. How wrong can this go, who feels it, answered up front the way you'd treat a change to a live service.&lt;/p&gt;

&lt;p&gt;Five reps. All earned. Zero on the exam.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is a level-up, not a layoff
&lt;/h2&gt;

&lt;p&gt;The panic read of this is backwards. The credential catching up doesn't shrink the role, it raises the floor. When the institution names AI fluency as baseline, the person who's practiced it instead of read about it becomes the scarce one. Certified-and-practiced is a much smaller set than certified.&lt;/p&gt;

&lt;p&gt;So I wouldn't study the new section and stop. I'd go get the reps it's gesturing at. Hand something real to an agent this week, let it run a little past comfortable, and watch the moment your hand goes for the keyboard. That moment is the competency. It never shows up on a scorecard.&lt;/p&gt;

&lt;p&gt;For those of you shipping work through agents already: what's the moment that taught you to override, and could a test have taught it instead?&lt;/p&gt;

&lt;p&gt;Tags: #projectmanagement&lt;/p&gt;

</description>
      <category>projectmanagement</category>
      <category>ai</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>I Sorted 40 Backlog Items by Shape Instead of Who's Free - Here's What Broke</title>
      <dc:creator>Mykola Kondratiuk</dc:creator>
      <pubDate>Wed, 03 Jun 2026 07:29:49 +0000</pubDate>
      <link>https://dev.to/itskondrat/i-sorted-40-backlog-items-by-shape-instead-of-whos-free-heres-what-broke-4h0a</link>
      <guid>https://dev.to/itskondrat/i-sorted-40-backlog-items-by-shape-instead-of-whos-free-heres-what-broke-4h0a</guid>
      <description>&lt;p&gt;canonical_url:&lt;/p&gt;

&lt;p&gt;Two Fortune 500 execs stood on a summit stage last week and gave opposite answers to one question: is an AI agent a colleague or a tool?&lt;/p&gt;

&lt;p&gt;One names his agents and seats them in reviews. The other won't call them colleagues. I watched the debate go by and realized I'd stopped caring about the noun a while ago, because it never once changed what I did with my backlog on a Monday.&lt;/p&gt;

&lt;p&gt;So here's the thing I actually changed, and the part of it that broke.&lt;/p&gt;

&lt;h2&gt;
  
  
  The old default: sort by who's free
&lt;/h2&gt;

&lt;p&gt;For years my planning loop was the same. Look at what needs doing. Look at who has capacity. Assign. The unit was always the person. "Who's free" was the first question.&lt;/p&gt;

&lt;p&gt;When agents showed up in the loop, I just slotted them in as another row in the capacity table. Same question, one more name. That's the "tool" answer in practice - an agent is a faster hand, you point it at whatever's next.&lt;/p&gt;

&lt;p&gt;It worked until it didn't. The agent would happily take a task that needed a human to even scope it correctly, produce something plausible, and I'd find out two steps later that the plausible thing was wrong in a way that cost me a half-day to unwind.&lt;/p&gt;

&lt;h2&gt;
  
  
  The change: sort by shape first
&lt;/h2&gt;

&lt;p&gt;I flipped the order. Before I look at who's free, I sort the backlog by &lt;em&gt;shape&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Two buckets. Person-shaped work needs judgment, lives in ambiguity, depends on taste or a relationship I can't write down. Agent-shaped work is defined, repeatable, and gate-able - I can describe the input, the output, and the check it has to pass.&lt;/p&gt;

&lt;p&gt;The discipline is that I write the agent's slice like a contractor's statement of work, not a chat prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# agent slice — scoped like an SOW, not a vibe&lt;/span&gt;
&lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;regenerate API client from updated OpenAPI spec&lt;/span&gt;
&lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;openapi.yaml (v3.1, committed)&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;existing client at src/clients/&lt;/span&gt;
&lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;regenerated client, same public surface&lt;/span&gt;
&lt;span class="na"&gt;gate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;all existing contract tests pass&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;public exports diff reviewed by a human before merge&lt;/span&gt;
&lt;span class="na"&gt;owner_of_outcome&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;me&lt;/span&gt;   &lt;span class="c1"&gt;# not the agent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I can't fill in &lt;code&gt;gate&lt;/code&gt; and &lt;code&gt;output&lt;/code&gt; cleanly, that's my signal: this isn't agent-shaped yet. It's person-shaped work I was about to mislabel because I wanted it off my plate.&lt;/p&gt;

&lt;p&gt;I ran this across about 40 backlog items. Roughly a third of what I'd have handed to an agent under the old "who's free" sort failed the shape test and went back to a human.&lt;/p&gt;

&lt;h2&gt;
  
  
  What broke
&lt;/h2&gt;

&lt;p&gt;Two things broke, and both were useful.&lt;/p&gt;

&lt;p&gt;First, my sense of which work was "important." I'd been guarding a pile of tasks as too critical to automate. Half of them were just defined work I was emotionally attached to. They sorted cleanly into the agent bucket and ran fine. The status I'd assigned them was about me, not the work.&lt;/p&gt;

&lt;p&gt;Second - and this is the one I underscoped - the gate is only as good as the human watching it. There's research showing that once you treat an agent like a teammate, you review its output &lt;em&gt;less&lt;/em&gt; carefully. Naming the thing lowers your guard. So the "colleague" framing isn't warmth, it's a quiet accountability leak. I caught myself rubber-stamping a passing gate because the agent had "been reliable lately." A tool doesn't earn trust. Work does, run by run.&lt;/p&gt;

&lt;p&gt;There's an old line going around that fits: you automate the boring, and then humans just manage the failure modes. That's not a downgrade of the human job. The failure modes ARE the job now. Managing the part the agent can't hold is the work that's left, and it's the work that compounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is a career thing, not just a workflow thing
&lt;/h2&gt;

&lt;p&gt;The same exec who named his agents also said the hardest part isn't the technology, it's the managers. I think that's exactly right, and it cuts both ways.&lt;/p&gt;

&lt;p&gt;If the manager is the bottleneck, the manager is also the leverage. The skill that pays off from here isn't prompt-writing - that floor keeps dropping. It's the older skill of looking at a pile of work and knowing fast which parts are person-shaped and which you can scope, gate, and let run. That's "golden age of the generalist" energy: when the specialization tax drops, the person who holds judgment AND can design the work is the one who wins.&lt;/p&gt;

&lt;p&gt;The execs on stage were missing a practitioner, so they argued about the label. The label was never the leadership problem. The work was.&lt;/p&gt;

&lt;p&gt;So I'm curious where you've landed: when an agent is in your loop, do you still plan by who's free, or have you started cutting the work by shape first? And where has the gate let something through on you?&lt;/p&gt;

</description>
      <category>projectmanagement</category>
      <category>ai</category>
      <category>career</category>
      <category>management</category>
    </item>
    <item>
      <title>I Added a Human Veto to My PM Agent — Here's What Broke First</title>
      <dc:creator>Mykola Kondratiuk</dc:creator>
      <pubDate>Fri, 29 May 2026 19:46:10 +0000</pubDate>
      <link>https://dev.to/itskondrat/i-added-a-human-veto-to-my-pm-agent-heres-what-broke-first-103g</link>
      <guid>https://dev.to/itskondrat/i-added-a-human-veto-to-my-pm-agent-heres-what-broke-first-103g</guid>
      <description>&lt;p&gt;Running automation agents for a while now. Most work fine hands-off. But one of them - my project status agent - kept making decisions that felt right in isolation but wrong in context.&lt;/p&gt;

&lt;p&gt;So I added a human approval step. Not a "review and confirm" UI widget. An actual veto gate in the workflow itself: the agent drafts the action, pauses, and waits for my explicit go-ahead before doing anything irreversible.&lt;/p&gt;

&lt;p&gt;Here's what I didn't expect: the first thing to break wasn't the agent logic. It was my own habits.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem I Was Trying to Solve
&lt;/h2&gt;

&lt;p&gt;My status reporting agent does three things: pulls data from Jira, formats a weekly PM summary, and posts it to the team Slack channel. Straightforward automation.&lt;/p&gt;

&lt;p&gt;Except twice in three months it posted something embarrassing. Once it included a stale blocker that had been resolved 48 hours prior. Once it flagged a team member's ticket as overdue when they'd actually shipped early and the tracker hadn't caught up.&lt;/p&gt;

&lt;p&gt;Neither was catastrophic. Both were awkward.&lt;/p&gt;

&lt;p&gt;The traditional fix would be "add better logic to catch these cases." I tried that. Added freshness checks, added resolved-status validation. Still leaked edge cases.&lt;/p&gt;

&lt;p&gt;So I took a different approach: make human review a structural part of the workflow, not a safety net I bolt on when things go wrong.&lt;/p&gt;

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

&lt;p&gt;The architecture is boring. Agent generates the Slack message draft, posts to a private review channel, waits for a thumbs-up emoji reaction, only then posts to the team channel.&lt;/p&gt;

&lt;p&gt;If no reaction within 2 hours, it pings me directly and kills the task. No silent failures.&lt;/p&gt;

&lt;p&gt;The human approval isn't optional and it isn't a fallback. It's a required step in the sequence. The workflow can't progress without it.&lt;/p&gt;

&lt;p&gt;I got the idea from reading about Microsoft Conductor, which open-sources a similar pattern for multi-agent orchestration. Human approval as a default workflow step, not a retrofit. Their framing stuck with me: &lt;strong&gt;designed-in, not bolted-on.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Broke
&lt;/h2&gt;

&lt;p&gt;I expected the agent to break. It didn't.&lt;/p&gt;

&lt;p&gt;I expected me to approve everything in under 5 minutes. I did, mostly.&lt;/p&gt;

&lt;p&gt;What I didn't expect: I stopped trusting my own review. The first week, I read every draft carefully. By week three, I was rubber-stamping. My brain had offloaded judgment to "well the agent probably got it right." The approval gate existed, but the actual human review stopped happening.&lt;/p&gt;

&lt;p&gt;This is the invisible failure mode nobody talks about. You add a human step. The human shows up. But they're not really there.&lt;/p&gt;

&lt;p&gt;The fix was embarrassingly simple: I added friction. Required a comment, not just an emoji. Had to type at least one word before the workflow could advance. Stupid? Maybe. Effective? Completely.&lt;/p&gt;

&lt;p&gt;Turns out &lt;strong&gt;the veto gate only works if the human has to engage to use it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Things I Didn't Know I Needed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Escalation hooks, not just approval gates.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not all decisions are equal. Minor formatting choices don't need a veto. Anything that posts externally or modifies data does. I ended up building a simple severity classifier: low = auto-approve, medium = soft review prompt, high = hard gate. Saved probably 70% of the friction without sacrificing coverage where it mattered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. A timeout that fails loudly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My 2-hour window was too long. If I'm in back-to-back meetings, the agent just hung. Switched to 30 minutes with an escalating Slack ping. Now if I haven't approved it, I can't miss it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. A clear distinction between "irreversible" and "annoying-to-undo."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I started gating everything. Caught myself adding a veto to the agent that sends me my own daily brief. Nobody else sees that. No irreversible action involved. Human gate added zero value there, only friction.&lt;/p&gt;

&lt;p&gt;The useful mental model: &lt;strong&gt;if I had to undo this action at 11pm on a Friday, would I care?&lt;/strong&gt; Yes = human gate. No = let it run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters More Than It Looks
&lt;/h2&gt;

&lt;p&gt;Most of the "AI safety" conversation in enterprise is about governance frameworks and audit trails. That's real. But the practical engineering question is simpler:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which steps in your agent workflow require a human in the loop by design, not by accident?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Design it from the start and the workflow is reliable. Bolt it on after an incident and you're playing catch-up forever.&lt;/p&gt;

&lt;p&gt;The Microsoft Conductor open-source was notable to me not for the code but for the default: human approval ON unless you opt out. Most agent frameworks do the opposite. They default to autonomous and assume you'll add guardrails when you need them.&lt;/p&gt;

&lt;p&gt;I think that's backwards. Especially for agents touching anything external: posting, sending, modifying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I'm Landing
&lt;/h2&gt;

&lt;p&gt;The veto gate has been running about 6 weeks now. Two incidents caught before they shipped. One case where my review actually improved the draft - not just filtered a bad one. About 3 minutes of daily overhead.&lt;/p&gt;

&lt;p&gt;Worth it. But only because I designed the friction deliberately. The version without the comment requirement was almost worse than no gate at all - it gave me false confidence in an approval that wasn't really happening.&lt;/p&gt;

&lt;p&gt;If you're building agent workflows that touch anything irreversible, the question I'd ask first: &lt;strong&gt;what happens if this runs at 2am and you're asleep?&lt;/strong&gt; Whatever you wouldn't want to explain the next morning - that's where your human gate goes.&lt;/p&gt;




&lt;p&gt;If any of this maps to workflows you're building, curious what the "irreversible action" problem looks like on your end.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>vibecoding</category>
      <category>agents</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
