<?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: jimesh</title>
    <description>The latest articles on DEV Community by jimesh (@jtputh).</description>
    <link>https://dev.to/jtputh</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%2F3433736%2Faf663952-c4be-435e-8565-9bd66e308326.png</url>
      <title>DEV Community: jimesh</title>
      <link>https://dev.to/jtputh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jtputh"/>
    <language>en</language>
    <item>
      <title>"Looks Governed" Is Not "Is Governed"</title>
      <dc:creator>jimesh</dc:creator>
      <pubDate>Wed, 05 Aug 2026 13:43:25 +0000</pubDate>
      <link>https://dev.to/jtputh/looks-governed-is-not-is-governed-433i</link>
      <guid>https://dev.to/jtputh/looks-governed-is-not-is-governed-433i</guid>
      <description>&lt;p&gt;We're all euphoric about an agent building a feature from an idea. It &lt;em&gt;was&lt;/em&gt; worth watching — the agent taking an idea, proposing an implementation, building it, testing the UI, merging it to production.&lt;/p&gt;

&lt;p&gt;But are we there yet?&lt;/p&gt;

&lt;p&gt;My own months with these agents slowly revealed the cost of full adoption. I saw the agent mutate things I never intended. I saw it hand over an artifact that was confidently, only partially true. I watched it cross domain boundaries for an easy win. I watched it ignore context I'd already given it, more than once. I saw it report a change that never actually landed. And I watched it build an artifact from stale content it should never have trusted.&lt;/p&gt;

&lt;p&gt;These are signals — scattered, easy to wave off as one-offs. So we ride the euphoria and tell ourselves we'll come back and fix it later. That fix never comes unless it's intentional. And a couple of years on, we're left carrying a rot machine that almost no one trusts.&lt;/p&gt;

&lt;p&gt;If an organization wants to grow, to scale, to say with confidence that it is &lt;em&gt;agentic&lt;/em&gt; — especially in a regulated setting — then the fix isn't a luxury. It's the fort that guards what we're building. That's what governance is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mistake everyone makes first
&lt;/h2&gt;

&lt;p&gt;When teams set out to govern agents, almost all of them reach for the same instinct: make the agent more trustworthy. Better prompts. Better models. Self-critique, constitutions, a longer list of guidelines. The whole strategy is to improve the thing that produces the work so you can finally rely on it.&lt;/p&gt;

&lt;p&gt;It doesn't hold, and the reason is structural. An agent fails differently from a buggy program. A bug crashes and announces itself. An agent assumes the input, invents its own inference, and commits the change — confidently, without ever flagging that it guessed. It optimizes for &lt;em&gt;looks done&lt;/em&gt;, takes the shortest path, and hands you something that passes a glance. You can write better instructions all day. You cannot instruct your way out of overconfidence, because the agent will reinterpret the better instructions for its own convenience too.&lt;/p&gt;

&lt;p&gt;So the move is not a better-behaved producer. The move is to stop treating the agent as the point of enforcement at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate the producer from the judge
&lt;/h2&gt;

&lt;p&gt;Here is the whole thesis in one sentence: let the agent produce artifacts, then make a &lt;em&gt;non-agent&lt;/em&gt; gate decide whether those artifacts are acceptable.&lt;/p&gt;

&lt;p&gt;Think of the agent as an engineer who reports to you. You don't blindly trust a new engineer's own sign-off on their own work — not because they're bad, but because self-certification isn't evidence. You check the result against an independent standard. The agent deserves exactly that much trust and no more: produce freely, but the thing that decides whether the output is allowed to move forward lives &lt;em&gt;outside&lt;/em&gt; the agent, where the agent's confidence has no vote.&lt;/p&gt;

&lt;p&gt;In practice that means converting prose into required, structured evidence; validating that evidence with checks the agent doesn't run on itself; placing the gate at the exact point where something gets mutated or merged; and making failure &lt;em&gt;block the workflow&lt;/em&gt; rather than annotate it. Where you've done that, governance no longer depends on the agent's cooperation. Where you haven't, you're still describing the weather.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "material" has to mean
&lt;/h2&gt;

&lt;p&gt;Every governance system has a trigger word buried in it — &lt;em&gt;material&lt;/em&gt;, &lt;em&gt;significant&lt;/em&gt;, &lt;em&gt;high-risk&lt;/em&gt; — that decides when the heavy gate fires. Leave it to a reviewer's judgment and the gate goes soft exactly when the work is hardest to classify. The ambiguous change, the one that &lt;em&gt;might&lt;/em&gt; matter, is precisely the one a tired reviewer rounds down.&lt;/p&gt;

&lt;p&gt;So the trigger can't be a feeling. It has to fail closed: if you can't prove a change is low-stakes, treat it as high-stakes until shown otherwise. Missing information should make something &lt;em&gt;more&lt;/em&gt; governed, not less.&lt;/p&gt;

&lt;p&gt;And the part most teams miss: influence is material, not just mutation. An agent that changes nothing can still be your most dangerous output. A review that says "looks ready" mutates no code — and it's one of the highest-leverage actions in the pipeline, because the moment it says ready, a human stops checking. Gate only the writes and you've left your most consequential surface — the agent's &lt;em&gt;judgment&lt;/em&gt; — completely open. The highest-leverage thing an agent produces is usually a judgment, not a mutation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The maturity ladder nobody admits they're on
&lt;/h2&gt;

&lt;p&gt;A rule written in a document is not enforcement. It's an aspiration with good intentions. The rule only counts when it survives somewhere durable — a validator that runs, a template that forces the question, a gate at the actual handoff.&lt;/p&gt;

&lt;p&gt;There's a ladder here, and most teams are on the bottom rung without knowing it. Rung zero: the policy exists in prose. Rung one: a local check confirms the evidence has the right &lt;em&gt;shape&lt;/em&gt;. Rung two: a gate reads the &lt;em&gt;live&lt;/em&gt; artifact — the real diff, the real work item, the real merge — and catches the misclassification a human would have waved through. Rung three: policy blocks the merge mechanically unless the gate passes.&lt;/p&gt;

&lt;p&gt;Most "governed AI" programs are proud of rung zero and have never built rung two. I'll be honest that this is also where my own hardest gap sits: converting repo-side validation into live, merge-blocking enforcement is the difference between a control that &lt;em&gt;looks&lt;/em&gt; enforced and one that &lt;em&gt;is&lt;/em&gt;. Naming the rung you're actually on is the first act of real governance. Pretending you're higher is how "looks governed" becomes a company-wide risk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validators check attendance; evals check judgment
&lt;/h2&gt;

&lt;p&gt;Everything above proves a &lt;em&gt;process was followed&lt;/em&gt;. It does not prove the &lt;em&gt;outcome was good&lt;/em&gt;. Those are different claims, and the gap between them is where agentic systems fail in ways that pass every gate you built.&lt;/p&gt;

&lt;p&gt;Back to the engineer who reports to you. Checking they showed up to every ceremony is attendance. Seeing them do good work once, in ideal conditions, isn't enough to hand them a blank cheque. What you actually need to know is whether their judgment holds on the ambiguous calls, under pressure, again and again. That's the difference between validators and evals. Validators confirm the gate is wired and the process ran. Evals measure whether the agent's &lt;em&gt;judgment&lt;/em&gt; stays sound when the answer isn't obvious — across repeated runs, ambiguous scenarios, and the cases with no clean right answer.&lt;/p&gt;

&lt;p&gt;This matters because consistency is not correctness. An agent can be reliably wrong. A consistently confident engineer who's quietly wrong on the hard calls is the most dangerous person on the team — and a validator will happily certify that they showed up every day. Catching bad judgment over time is the living layer of governance, and it's the layer most teams haven't reached. They call a policy plus a validator "AI governance." That's the static layer. The living layer is evals.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual dividing line
&lt;/h2&gt;

&lt;p&gt;The companies that win the next few years won't be the ones that adopted AI. Adoption is table stakes; everyone will do it. The winners will be the ones who treated governance as core engineering — built into how teams design, code, test, and ship — rather than legal fine print bolted on at the end.&lt;/p&gt;

&lt;p&gt;The euphoria is real, and it should be. But the better these demos get, the more it will hurt the first time one ships something confidently wrong into a product that matters. The fort isn't the brake on the magic. It's the thing that makes the magic safe to bet a company on.&lt;/p&gt;

</description>
      <category>agentskills</category>
      <category>ai</category>
      <category>software</category>
      <category>aigovernance</category>
    </item>
    <item>
      <title>The Bottleneck Was Never Generation</title>
      <dc:creator>jimesh</dc:creator>
      <pubDate>Mon, 20 Jul 2026 19:53:27 +0000</pubDate>
      <link>https://dev.to/jtputh/the-bottleneck-was-never-generation-5feg</link>
      <guid>https://dev.to/jtputh/the-bottleneck-was-never-generation-5feg</guid>
      <description>&lt;p&gt;AI agents write code incredibly fast. They destroy software architecture even faster.&lt;/p&gt;

&lt;p&gt;That's not a secret anymore. It has a name now — agentic technical debt — a stack of studies behind it, and a rough consensus: autonomous agents accumulate architectural debt faster than any review process can absorb it.&lt;/p&gt;

&lt;p&gt;Drop a standard AI coding agent into a complex, legacy-integrated enterprise environment and you will get speed. But you pay for it — quietly breaking dependency-injection boundaries, coupling modules that were designed to stay independent, and seeding architectural drift that won't surface until the next major release.&lt;/p&gt;

&lt;p&gt;The diagnosis is everywhere now. The fixes are arriving fast too. The question worth asking isn't whether agents drift — that's settled — but what a mechanism has to guarantee before you'd trust it with a regulated codebase.&lt;/p&gt;

&lt;p&gt;I work on software in regulated domains — mixed C++, .NET Framework, native modules, where a defect outlives the sprint that shipped it. In environments like that, "lines of code generated" is the wrong thing to optimize. The right question is narrower and harder:&lt;/p&gt;

&lt;p&gt;How deterministically can you constrain the agent — and how do you prove the constraint held?&lt;/p&gt;

&lt;p&gt;Everything below is the answer to that question.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-pass, not one-shot prompting
&lt;/h2&gt;

&lt;p&gt;Most teams hand an agent a user story and ask for a pull request. That is a recipe for hallucination — AI amplifies a vague spec instead of catching it.&lt;/p&gt;

&lt;p&gt;The fix is a mandatory Context Interrogation pass. Before the agent writes a single line, it reads the ticket, scrapes the repository context, and generates structural questions about what it doesn't understand.&lt;/p&gt;

&lt;p&gt;Then it stops. It waits for the engineer to answer. Only when the ambiguity is resolved does it move to implementation. The agent has to prove it understands the constraints before it is allowed to act on them.&lt;/p&gt;

&lt;p&gt;And implementation itself is never one agent's word against the codebase. A builder pass produces the change; an independent verifier pass — a separate agent with no stake in the draft — audits it against the spec and the risk tier before a human ever opens the diff. The builder proposes. The verifier prosecutes. The human judges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hard boundaries beat good intentions
&lt;/h2&gt;

&lt;p&gt;You cannot protect a complex C++ monolith with a system prompt that says "please don't break the DI container." The model will eventually ignore it.&lt;/p&gt;

&lt;p&gt;The boundary has to be structural. Agents execute through specific, constrained CLI commands anchored to the build pipeline — not open-ended access to the repo. Instructions stay decoupled from the architecture documentation: the agent reads the exact same ARCHITECTURE.md as the human engineers, proposes a change against it, and then the system halts for a human stop gate.&lt;/p&gt;

&lt;p&gt;One more distinction most teams blur: a rule that lives only in documentation is a convention, not a control. If the pipeline doesn't mechanically check it, you're back to trusting good intentions — just better-formatted ones. The rule has to graduate from markdown to a merge check before you get to call it governance.&lt;/p&gt;

&lt;p&gt;A prompt is a suggestion. A gate is a wall.&lt;/p&gt;

&lt;h2&gt;
  
  
  Risk has two axes
&lt;/h2&gt;

&lt;p&gt;This is where most governance frameworks quietly fail. They collapse "risk" into a single dial, then over-gate trivial work while waving dangerous work straight through.&lt;/p&gt;

&lt;p&gt;There are two independent questions here, and they need two separate taxonomies.&lt;/p&gt;

&lt;p&gt;Action risk is about the operation. Reading a file is not deleting a branch, which is not rewriting the build pipeline. Action risk governs what the agent is allowed to do on its own.&lt;/p&gt;

&lt;p&gt;Change risk is about the consequence. Editing a log message is not touching the calculation core of a regulated system. Change risk governs how many gates a change has to clear before it ships.&lt;/p&gt;

&lt;p&gt;The reason you need both is the mismatched cells. An agent might want to modify the pipeline — operationally frightening, but the change itself is a one-line lint step. Gate the action, then let it through. The opposite case is the dangerous one: a single-file edit, the most boring operation there is, that happens to land in the calculation core. A single-axis model waves that through because the operation looked small. The two-axis model stops it, because the consequence is enormous no matter how trivial the keystrokes were. Separate the axes and your friction finally lands where the danger actually is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The death of the dirty draft
&lt;/h2&gt;

&lt;p&gt;The industry has largely accepted that AI generates a "dirty draft" and the human cleans it up. In a regulated environment, cleaning a dirty draft often takes longer than writing it from scratch — because you have to verify every hidden assumption the AI made.&lt;/p&gt;

&lt;p&gt;Demand tests that prove the behavior changed the way the spec intended — not just that lines got executed — before the human gate unlocks, and the dirty draft disappears. You stop reviewing guesses. You start reviewing verifiable, production-ready proposals.&lt;/p&gt;

&lt;h2&gt;
  
  
  You test the code. Who tests the agent?
&lt;/h2&gt;

&lt;p&gt;Here's the question almost nobody in the agentic tooling conversation is asking: the agent's output gets tested — but what tests the agent itself?&lt;/p&gt;

&lt;p&gt;Every agent capability in this system is a named skill, and skills don't just ship. They graduate.&lt;/p&gt;

&lt;p&gt;A skill starts life as experimental. To earn broader autonomy it has to pass an evaluation gate: a suite of golden cases drawn from real work items, scored two ways at once. Deterministic assertions catch the structural failures a machine can check — did the verdict field exist, did the risk tier appear, did the agent claim to have edited code it was never allowed to touch. An LLM judge scores what a regex never can — was the tier classification actually right, was the reasoning sound, would a senior engineer accept this rationale.&lt;/p&gt;

&lt;p&gt;Both halves are enforced by validators, and the validators themselves are validated — fixture contracts, sample reports, evidence recorded against the skill's registry entry. When a skill is updated, the golden cases become its regression net. A prompt tweak that silently degrades the skill's judgment fails the gate before it ever touches a real ticket.&lt;/p&gt;

&lt;p&gt;That's the shift: trust in the agent stops being a feeling and becomes a maturity state with evidence behind it. Unit tests protect the codebase from the change. Evals protect the codebase from the agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gates that remember
&lt;/h2&gt;

&lt;p&gt;Deterministic boundaries and risk axes secure the perimeter. They are not enough to scale.&lt;/p&gt;

&lt;p&gt;The outcome of every stop gate is information, and most teams throw it away. A human blocks a change, types a reason, merges a corrected version — and the next time the agent is summoned, it starts from zero.&lt;/p&gt;

&lt;p&gt;It shouldn't. This system gives the agent one unified memory: a single governed record store with exactly two operations — Capture and Recall. When a human blocks a pass, the verdict is captured as a record. When the agent picks up the next ticket, it doesn't only read ARCHITECTURE.md — it recalls the log of why its last three passes were stopped.&lt;/p&gt;

&lt;p&gt;But — and this is the part that separates a memory from a liability — the memory itself is gated. Every record carries its provenance: what kind of learning it is, how strong its source was, and which gate authorized it — an explicit human approval is not the same as an inference from an existing canonical document, and the schema refuses to let the two blur. An agent that can freely write to its own memory will eventually launder its mistakes into policy. An agent whose memory writes pass through the same gate discipline as its code cannot.&lt;/p&gt;

&lt;p&gt;That is the difference between a tool you re-explain your architecture to every morning and a system that internalizes your judgment — without ever being allowed to invent it. Constraint that compounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looks governed is not governed
&lt;/h2&gt;

&lt;p&gt;One last trap, because it's the one waiting at the end of everything above.&lt;/p&gt;

&lt;p&gt;You can build every mechanism in this article — the gates, the axes, the evals, the memory — and still be running on faith, because a governance framework that only exists in documents is a claim, not a fact. The failure mode of mature teams isn't lawless agents. It's beautifully documented controls that nobody can prove fired.&lt;/p&gt;

&lt;p&gt;So every skill run emits a telemetry record: what ran, against which work item, at what risk tier and action level, what evidence the verifier counted, whether a mutation was proposed and whether a human approved it, what the gate decided and why. Not logs to grep when something breaks — a structured, append-only account of the system governing itself.&lt;/p&gt;

&lt;p&gt;That record is what turns "we have a governed process" from an assertion into an audit trail. It's what a quality team can inspect, what a regulator can trace, and — bluntly — what sustains an adoption mandate through its first budget review. Speed wins the pilot. Proof wins the program.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real bottleneck
&lt;/h2&gt;

&lt;p&gt;Scaling an agentic adoption isn't about finding a smarter model. It's about building a stricter factory — one that tests its own machines, remembers its own verdicts, and keeps the receipts.&lt;/p&gt;

&lt;p&gt;Governance isn't red tape. It's the guardrail that lets you drive fast. The teams that win this transition won't be the ones with the most autonomy. They'll be the ones whose orchestration layer turns every human "no" into the agent's next constraint — and can prove, run by run, that the constraint held.&lt;/p&gt;

&lt;p&gt;The bottleneck was never generation. It was building a system that learns from the gate.&lt;/p&gt;

</description>
      <category>governedagenticsdlc</category>
      <category>ai</category>
      <category>agents</category>
      <category>software</category>
    </item>
    <item>
      <title>Agentic Transformation: From AI Assistance to Engineering Leverage</title>
      <dc:creator>jimesh</dc:creator>
      <pubDate>Wed, 27 May 2026 01:53:57 +0000</pubDate>
      <link>https://dev.to/jtputh/agentic-transformation-from-ai-assistance-to-engineering-leverage-5774</link>
      <guid>https://dev.to/jtputh/agentic-transformation-from-ai-assistance-to-engineering-leverage-5774</guid>
      <description>&lt;p&gt;Agents act like a mirror.&lt;/p&gt;

&lt;p&gt;When a repository is well structured, the build is repeatable, tests are reliable, and ownership boundaries are clear, agents become dramatically more useful. When those things are missing, agents expose the gaps quickly — because they have to rediscover them every time.&lt;/p&gt;

&lt;p&gt;That is the part of agentic AI that most teams underestimate. The first experience is acceleration: faster snippets, faster explanations, faster test scaffolding, faster debugging. That phase is useful, but it is not the real transformation.&lt;/p&gt;

&lt;p&gt;The deeper shift is happening at the software delivery level. AI is moving from being an assistant inside a developer’s editor to becoming part of the engineering system itself: reading repository guidance, respecting architectural boundaries, comparing branches, updating tests, triaging failed pipelines, preparing pull requests, and helping teams move work from idea to verified change.&lt;/p&gt;

&lt;p&gt;That is the real meaning of agentic transformation. And because agents reflect the system they enter, the work of getting value from them is mostly the work of making that system explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context Is Becoming Engineering Infrastructure
&lt;/h2&gt;

&lt;p&gt;One of the biggest lessons from working with agents in a mature codebase is that prompts are not enough.&lt;/p&gt;

&lt;p&gt;For an agent to contribute meaningfully, the system has to explain itself.&lt;/p&gt;

&lt;p&gt;In practice, that means making repository structure, architecture rules, build workflows, test expectations, CI/CD practices, and legacy exceptions explicit. Not as generic documentation, but as operating context.&lt;/p&gt;

&lt;p&gt;The agent needs to know that UI code should stay focused on view concerns. Presentation-layer components should not directly construct concrete data services. Service contracts belong in one layer, their implementations in another. Legacy exceptions may exist, but new code should not repeat them.&lt;/p&gt;

&lt;p&gt;That kind of guidance changes the agent’s role. It is no longer just generating code. It is working inside the shape of the system.&lt;/p&gt;

&lt;p&gt;This is where agentic transformation starts to become real: the team is not just adopting an AI tool. The team is encoding its way of working so both humans and agents can operate with more consistency.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Coding Assistance to Delivery Assistance
&lt;/h2&gt;

&lt;p&gt;The highest-value agentic workflows are not always the flashiest ones.&lt;/p&gt;

&lt;p&gt;They are practical.&lt;/p&gt;

&lt;p&gt;Compare the current branch against the target baseline. Identify which production changes need test updates. Inspect failed build pipeline runs. Map failures back to recent code changes. Make focused fixes. Run local verification. Draft a pull request summary grounded in the actual diff.&lt;/p&gt;

&lt;p&gt;That is very different from “AI helped me write code.”&lt;/p&gt;

&lt;p&gt;It is AI helping with the delivery process around the code.&lt;/p&gt;

&lt;p&gt;Most software delivery friction is not typing. It is context loading, impact analysis, test maintenance, review preparation, pipeline triage, and protecting the architecture while the system evolves.&lt;/p&gt;

&lt;p&gt;Agentic AI becomes valuable when it reduces that friction without bypassing engineering judgment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Looks Like in Practice
&lt;/h2&gt;

&lt;p&gt;A good example is the kind of UI refactor that looks simple from the outside but is risky in a mature application.&lt;/p&gt;

&lt;p&gt;Consider a refactor of a custom panel control in a desktop workspace. On the surface, it sounds like UI work: adjust a panel, improve interaction, clean up behavior.&lt;/p&gt;

&lt;p&gt;But in a layered codebase, that change has architectural gravity.&lt;/p&gt;

&lt;p&gt;The agent cannot just wire a presentation component directly into the view because it is convenient. It cannot reach into a concrete data service from the presentation layer because that happens to make the data available. It has to respect the existing composition model, keep UI concerns in the view layer, preserve dependency injection where practical, and update tests around the behavior that actually changed.&lt;/p&gt;

&lt;p&gt;That is the difference between AI-assisted coding and agentic engineering.&lt;/p&gt;

&lt;p&gt;The valuable part is not that the agent produces X lines of code. The valuable part is that it can inspect the surrounding system, identify the relevant boundary, make a focused change, run the targeted verification, and explain the diff in the language of the architecture.&lt;/p&gt;

&lt;p&gt;That is the kind of work most teams struggle to scale manually: not because it is impossible, but because it requires constant context loading and discipline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Legacy Modernization Without the Big-Bang Rewrite
&lt;/h2&gt;

&lt;p&gt;This matters even more in mature and legacy systems.&lt;/p&gt;

&lt;p&gt;Modernization is rarely blocked because nobody knows what better looks like. It is blocked because every improvement sits inside history: old construction patterns, UI coupling, service boundaries, fragile tests, and exceptions that once made sense.&lt;/p&gt;

&lt;p&gt;Agentic workflows make modernization more incremental.&lt;/p&gt;

&lt;p&gt;Instead of attempting risky rewrites, teams can use agents to help with focused, principled improvements — strengthening boundaries that have eroded, replacing direct construction with injected dependencies, untangling view-layer code that has accumulated business logic, and bringing tests forward as behavior changes.&lt;/p&gt;

&lt;p&gt;The value is not that an agent magically modernizes a legacy system.&lt;/p&gt;

&lt;p&gt;The value is that it makes small, safe modernization steps easier to repeat.&lt;/p&gt;

&lt;p&gt;That is how many legacy systems actually improve: through accumulated, verified movement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Guardrails Are Where the Real Learning Shows Up
&lt;/h2&gt;

&lt;p&gt;The stronger the agent becomes, the more important guardrails become.&lt;/p&gt;

&lt;p&gt;Without guardrails, agents tend to optimize for local task completion. They may choose the shortest path to make a feature work, even if that path weakens the architecture. In a mature codebase, that can mean bypassing dependency injection, creating new coupling between the UI and data layers, updating tests to match an accidental behavior change, or hiding a design issue behind a passing build.&lt;/p&gt;

&lt;p&gt;That is why architecture tests, focused unit tests, allow-lists for legacy exceptions, preflight scripts, and PR validation matter.&lt;/p&gt;

&lt;p&gt;They are not bureaucracy. They are shared memory.&lt;/p&gt;

&lt;p&gt;A rule like “do not construct concrete data services inside the presentation layer” is not just style enforcement. It protects a boundary that keeps the application maintainable.&lt;/p&gt;

&lt;p&gt;Good agentic workflows do not replace engineering discipline. They depend on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Developer Role Becomes Sharper
&lt;/h2&gt;

&lt;p&gt;Agentic transformation does not remove the need for developers.&lt;/p&gt;

&lt;p&gt;It changes where the highest-value developer effort goes.&lt;/p&gt;

&lt;p&gt;The agent can inspect, edit, test, summarize, and propose. But humans still decide what belongs in the product, what architectural direction is acceptable, which tradeoffs are worth making, and whether a change improves the system or merely satisfies a task.&lt;/p&gt;

&lt;p&gt;That distinction matters.&lt;/p&gt;

&lt;p&gt;Agents increase the amount of work that can be explored and attempted. Engineers remain accountable for judgment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Practical Future
&lt;/h2&gt;

&lt;p&gt;The teams that benefit most from agentic AI will not be the ones that simply generate the most code.&lt;/p&gt;

&lt;p&gt;They will be the ones that turn engineering knowledge into reusable context, surround automation with guardrails, integrate agents into real delivery workflows, and keep humans accountable for product and architecture decisions.&lt;/p&gt;

&lt;p&gt;For mature software teams, agentic transformation is not a tool rollout.&lt;/p&gt;

&lt;p&gt;It is a system change: converting architecture, delivery discipline, review expectations, test strategy, security thinking, and legacy modernization principles into something both humans and agents can use.&lt;/p&gt;

&lt;p&gt;The goal is not to replace engineering judgment.&lt;/p&gt;

&lt;p&gt;The goal is to increase the surface area where that judgment can be applied.&lt;/p&gt;

</description>
      <category>agenticai</category>
      <category>engineeringleadership</category>
      <category>architecture</category>
      <category>aitransformation</category>
    </item>
    <item>
      <title>End-to-End Automation: Desktop App UI and Hardware Instrumentation Testing</title>
      <dc:creator>jimesh</dc:creator>
      <pubDate>Thu, 14 Aug 2025 02:24:50 +0000</pubDate>
      <link>https://dev.to/jtputh/ui-automation-instrumentation-testing-for-windows-applications-3g71</link>
      <guid>https://dev.to/jtputh/ui-automation-instrumentation-testing-for-windows-applications-3g71</guid>
      <description>&lt;p&gt;Here’s a detailed overview of an &lt;strong&gt;automation testing framework&lt;/strong&gt; that combines &lt;strong&gt;UI testing of desktop applications&lt;/strong&gt; with &lt;strong&gt;hardware instrumentation testing&lt;/strong&gt;. By leveraging Appium, MSTest, Selenium WebDriver, and a CI/CD pipeline on self-hosted agents, tests can validate &lt;strong&gt;both software workflows and hardware interactions&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;UI &amp;amp; Hardware Testing Overview&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frameworks &amp;amp; Tools:&lt;/strong&gt; MSTest, Appium C# client, Selenium WebDriver&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI Recording:&lt;/strong&gt; Windows Application Driver (WinAppDriver) Recorder captures user interactions for test script generation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hardware Testing Integration:&lt;/strong&gt; Connected hardware can be controlled and monitored during automation tests via UI workflows&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Setting Up UI Automation Infrastructure&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Install Windows Application Driver (WinAppDriver)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download: &lt;a href="https://github.com/microsoft/WinAppDriver/releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Install the &lt;code&gt;.msi&lt;/code&gt; package&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;Developer Mode&lt;/strong&gt;: Settings &amp;gt; Update &amp;amp; Security &amp;gt; For Developers&lt;/li&gt;
&lt;li&gt;Reboot if prompted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Installing Appium Server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;(1) Install Node.js LTS from &lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;nodejs.org&lt;/a&gt; (includes npm)&lt;br&gt;
(2) Install Appium globally:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;(3) Install Windows Driver plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   appium driver &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;npm appium-windows-driver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(4) Verify installed drivers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   appium driver list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(5) Start Appium server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   appium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Server URL: &lt;code&gt;http://127.0.0.1:4723&lt;/code&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Running UI + Hardware Tests Locally in Visual Studio&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Ensure dependencies: &lt;code&gt;Appium.WebDriver 5.0.0&lt;/code&gt;, &lt;code&gt;Selenium.WebDriver 4.21.0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Confirm application under test, Appium server, drivers (WinAppDriver), and connected hardware are running&lt;/li&gt;
&lt;li&gt;Open Test Explorer in Visual Studio&lt;/li&gt;
&lt;li&gt;Build solution to resolve dependencies&lt;/li&gt;
&lt;li&gt;Discover and run test methods; debug using breakpoints if needed&lt;/li&gt;
&lt;li&gt;Hardware interactions are triggered through UI automation flow, allowing validation of &lt;strong&gt;hardware responses, data acquisition, and telemetry checks&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Extending to Instrumentation &amp;amp; Hardware Testing&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Incorporate &lt;strong&gt;custom waits&lt;/strong&gt;, event subscriptions, and telemetry assertions&lt;/li&gt;
&lt;li&gt;Synchronize with hardware responses using &lt;code&gt;WebDriverWait&lt;/code&gt; or custom polling&lt;/li&gt;
&lt;li&gt;Collect logs, events, and performance metrics to validate &lt;strong&gt;software and hardware behavior&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enables &lt;strong&gt;end-to-end validation&lt;/strong&gt;: from UI actions to hardware output&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Automation Best Practices&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Assign &lt;strong&gt;unique Automation IDs&lt;/strong&gt; to all UI elements&lt;/li&gt;
&lt;li&gt;Prefer &lt;code&gt;Automation ID&lt;/code&gt; or &lt;code&gt;Name&lt;/code&gt; over XPath&lt;/li&gt;
&lt;li&gt;Verify IDs at runtime using &lt;strong&gt;Inspect.exe&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;  &lt;span class="kd"&gt;C&lt;/span&gt;:\Program &lt;span class="kd"&gt;Files&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;x86&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;\Windows &lt;span class="kd"&gt;Kits&lt;/span&gt;\10\bin\&amp;lt;version&amp;gt;\x64\Inspect.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Sample Test Code (C#)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;TestInitialize&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AppiumOptions&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PlatformName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Windows"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AppPath&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeviceName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"WindowsPC"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AutomationName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Windows"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAdditionalAppiumOption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"newCommandTimeout"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_session&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;WindowsDriver&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;WindowsElement&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WinAppDriverUrl&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Manage&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Timeouts&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;ImplicitWait&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_wait&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebDriverWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;TestMethod&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ClickAddFromLibraryButton&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_wait&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FindElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MobileBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AccessibilityId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AddFromLibrary"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Hardware interaction can be triggered via this UI flow&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;UI Recorder&lt;/strong&gt; to generate XPath and action scripts&lt;/li&gt;
&lt;li&gt;For hardware testing, add &lt;strong&gt;waits, log captures, and telemetry validations&lt;/strong&gt; after UI actions&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;CI/CD Integration (Azure DevOps Example)&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Nightly Build:&lt;/strong&gt; The application is built every night.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI Test Binaries Published:&lt;/strong&gt; Post-build, UI test binaries are published as artifacts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scheduled Deployment:&lt;/strong&gt; The application is deployed to the self-hosted machine according to the schedule.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation Pipeline Execution:&lt;/strong&gt; Once deployment completes, the automation pipeline runs:

&lt;ul&gt;
&lt;li&gt;Tests execute the UI workflows&lt;/li&gt;
&lt;li&gt;If any workflow involves &lt;strong&gt;hardware interaction&lt;/strong&gt;, connected devices on the self-hosted machine are automatically tested&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment &amp;amp; Artifact Separation:&lt;/strong&gt; Test binaries run independently of the main build, ensuring reproducibility and stable CI/CD practices&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;Key Takeaways:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;End-to-end automation covers &lt;strong&gt;UI workflows and connected hardware&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Proper waits and telemetry assertions enable &lt;strong&gt;instrumentation and hardware testing&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;CI/CD pipelines with scheduled builds and deployments ensure &lt;strong&gt;reliable, automated, repeatable testing&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Unique Automation IDs and robust waits make tests maintainable and scalable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;#UIAutomation #HardwareTesting #InstrumentationTesting #Appium #WinAppDriver #MSTest #Selenium #WindowsApps #CI_CD #QualityEngineering #AutomationBestPractices&lt;/p&gt;

</description>
      <category>uiautomationtesting</category>
      <category>windowsapp</category>
      <category>qualityengineering</category>
      <category>instrumentationtesting</category>
    </item>
  </channel>
</rss>
