Engineering Perspective

AI Made Syntax Cheap. Engineering Judgment Is Still Expensive.

Why I stopped treating manually typed code as the measure of engineering-and started using AI to spend more time on architecture, validation, and larger problems.

Published September 4, 2026 Robert H. Osborne AI-Assisted Engineering
Disclosure: I use generative AI extensively when designing, writing, reviewing, and documenting automation. I do not treat generated code as trusted, and I remain responsible for every implementation I approve and deploy. When I work with AI, I use synthetic information, fabricated examples, and test data rather than real client, customer, credential, production, or other sensitive data.

I am extremely good at PowerShell.

That is not résumé inflation or confidence borrowed from an AI-generated script. I have spent years using PowerShell to automate infrastructure, integrate APIs, build reporting systems, troubleshoot production environments, and turn repetitive operational work into reusable platforms. I also learned HTML, CSS, and JavaScript because automation eventually needs interfaces, reports, and outputs that other people can actually use.

For a long time, being able to cross those boundaries made me unusual. Then generative AI made producing functional code dramatically faster.

I could respond by defending the act of manually writing code as though typing syntax were the source of my value. I do not think it is. If AI can produce in thirty seconds what might take me hours to write, spending those hours manually recreating it is often a poor engineering decision.

But that does not mean I can type write me an Ansible playbook, deploy whatever appears, and call the result engineering.

My position: Writing every line manually is no longer the highest-value use of my time. Understanding the system, controlling the risks, validating the result, and owning the outcome still are.

The Code Was Never the Hardest Part

Syntax matters. A missing bracket, malformed YAML block, incorrect property, or invalid API request can stop an automation immediately. But syntax is rarely the hardest part of a serious infrastructure project.

The difficult work is deciding:

  • What problem should actually be solved?
  • What is the desired state?
  • Which system is authoritative for each piece of data?
  • Which identities and permissions are required?
  • What should happen when an operation partially succeeds?
  • Can the automation be rerun safely?
  • How will failures become visible?
  • How will the result be validated?
  • What evidence proves that the intended outcome occurred?
  • Who owns the consequences when an assumption is wrong?

AI can generate code for a badly defined system just as quickly as it can generate code for a well-designed one. Speed does not correct the premise.

Why Experience Makes AI More Useful

People sometimes describe effective AI use as knowing how to prompt. That is true in the shallowest sense, but the important skill is not finding magic words. The quality of my prompts comes from knowing what information an implementation requires.

I can specify runtime versions, input contracts, output schemas, trust boundaries, failure behavior, security requirements, idempotency expectations, configuration sources, naming standards, deployment validation, and existing functionality that must not be removed. Those are engineering requirements expressed through a prompt.

A less experienced person may ask:

Write an Ansible playbook that patches Windows servers.

I am more likely to define:

  • The supported Windows Server versions and inventory groups
  • Maintenance-window boundaries and preflight checks
  • Approved update categories and rejected KBs
  • Separate discovery, download, installation, and verification phases
  • Fork, serial, and throttling behavior
  • Reboot detection, reboot limits, and reconnect handling
  • SQL Server, cluster, and availability-group safeguards
  • Offline-host and partial-failure behavior
  • Credential handling and logging restrictions
  • Post-patching validation and evidence collection
  • Safe reruns and platform compatibility
  • The normalized data required for the client report

The generated YAML may arrive quickly. The years of experience that taught me to recognize those constraints did not.

My Job Moved Up the Stack

01 · FrameDefine the Problem

Identify the business outcome, consumer, scope, constraints, and unacceptable results.

02 · DesignChoose the Architecture

Define components, data flow, identities, state, boundaries, and ownership.

03 · SpecifyDescribe the Contract

State exactly how the implementation must behave during success, failure, and reruns.

04 · GenerateCompress Implementation

Use AI to produce code, tests, documentation, and repetitive supporting artifacts.

05 · ValidateReview and Test

Challenge assumptions, inspect the code, exercise failure paths, and verify outcomes.

06 · OwnAccept Responsibility

Deploy, monitor, maintain, troubleshoot, and improve the system in production.

My workflow did not remove engineering. It moved more of my time away from mechanical implementation and toward decisions with a larger blast radius.

Generation and Engineering Are Not the Same Thing

AI Can GenerateThe Engineer Must Determine
PowerShell functionsWhat responsibility belongs in each function and what state it may change
Ansible tasksThe desired state, target scope, execution order, and safe concurrency
API requestsThe authentication model, permissions, data contract, and trust boundary
Error handlingWhich failures are recoverable and which must stop the deployment
Retry logicWhether repeating the operation is safe or creates duplicate state
HTML reportsWhich evidence supports an operational or business decision
Infrastructure as CodeWhether the architecture is appropriate, secure, operable, and worth its cost
TestsWhat correctness means and which failure modes actually matter
DocumentationWhether the documented claims match the behavior of the deployed system

AI is excellent at creating plausible implementations. Plausibility is not the same as correctness.

The Ansible Problem

PowerShell is deeply familiar to me. I can usually recognize suspicious code quickly because I understand the language, runtime, object model, error behavior, and common failure patterns. Ansible is newer to me. I can read and troubleshoot playbooks, but I have not accumulated the same amount of muscle memory from writing them manually.

That creates a real tension. It is inefficient to spend hours typing a playbook that AI can generate in seconds. It is also dangerous to approve an artifact whose execution model I do not sufficiently understand.

My solution is not to reject AI. It is to resist making an underspecified request.

Before asking for the playbook, I define how it should work. After receiving it, I trace the plays, tasks, variables, conditions, handlers, registered results, loops, delegation, concurrency, and failure behavior. I check the relevant module documentation. I make sure I understand what changes on the first run, what changes on the second run, and what happens when the tenth host fails halfway through a maintenance window.

Review standard: If I cannot explain what the automation will do, why it will do it, and how it behaves when something fails, I am not ready to deploy it.

Understanding Is Still Mandatory

AI-generated code creates a tempting illusion: if the code runs, the work must be complete. Infrastructure automation can run successfully while producing the wrong outcome.

A deployment may exit with code zero while granting excessive permissions. A patching job may complete while leaving systems outside the inventory untouched. An API integration may create duplicate records on every retry. A report may render beautifully while calculating the wrong metric. A script may suppress the exception that should have stopped the deployment.

Review therefore has to extend beyond syntax:

  • Intent: Does the implementation solve the problem I defined?
  • Correctness: Are the APIs, modules, parameters, data types, and assumptions valid?
  • Security: Are credentials protected, permissions minimized, and inputs treated as untrusted?
  • Idempotency: Can the automation determine whether the desired state already exists?
  • Failure behavior: Does it stop, retry, compensate, or report appropriately?
  • Observability: Can an operator distinguish success, failure, partial completion, and unknown state?
  • Maintainability: Can another engineer understand and safely change it later?
  • Validation: Does the automation prove the outcome rather than merely report that commands ran?

My AI-Assisted Engineering Workflow

1. Frame the Problem

I begin with the operational or business outcome-not the language or tool. Who needs the result? What is currently painful or risky? What does success look like? What must never happen?

2. Design the System

I identify components, data flows, authoritative systems, identities, configuration boundaries, failure states, observability, and recovery. If the architecture is unclear, generating code only creates a faster path to rework.

3. Specify the Implementation

I provide the runtime, inputs, outputs, existing behavior, code standards, security requirements, noninteractive behavior, error handling, idempotency, and post-deployment validation. Client-specific values must remain separate from reusable logic. Secrets must never be embedded in code.

4. Generate in Complete Units

I prefer complete scripts, playbooks, functions, deployment modules, or pages that can be reviewed as coherent artifacts. Fragmented suggestions encourage manual merging errors and make it harder to see whether existing functionality disappeared.

5. Review the Artifact

I read the code. I look for invented parameters, invalid assumptions, broad permissions, unsafe string construction, swallowed exceptions, hidden interactive behavior, unnecessary dependencies, destructive commands, and missing validation.

6. Test Beyond the Happy Path

I test missing configuration, authentication failure, empty input, partial API responses, offline hosts, duplicate execution, reboots, rate limits, stale evidence, unexpected data types, partial deployment, and safe reruns. The exact tests change with the system; the obligation to test failure does not.

7. Own the Production Result

Once I approve and deploy generated code, it is my code. If it fails during a maintenance window, grants the wrong access, creates a security exposure, or produces a misleading report, saying that AI wrote it is not an operational defense.

Define → Design → Specify → Generate → Review → Test → Deploy → Observe → Improve

Does This Cause Skill Atrophy?

It can.

If I stop reading code, stop debugging, stop checking documentation, and accept generated output because it looks professional, my ability to recognize bad engineering will deteriorate. The answer is not to recreate every production artifact manually for practice. The answer is deliberate practice where it improves the mental model I need for review.

When learning an unfamiliar technology, I may write a smaller implementation manually, reconstruct a generated section, test one module in isolation, or deliberately break the automation and repair it. That is different from spending an entire day manually typing boilerplate that contributes nothing new to my understanding.

Learning principle: I do not need to hand-write every production artifact. I do need enough direct practice to recognize when a generated artifact is wrong.

When I Still Write Code Manually

  • The implementation is small enough that describing it would take longer.
  • I am learning an unfamiliar execution model.
  • The code crosses a sensitive security or identity boundary.
  • I am debugging behavior hidden behind an abstraction.
  • Performance or low-level behavior requires precise control.
  • The model repeatedly chooses the wrong abstraction.
  • The available context cannot be shared safely with an AI system.
  • I need direct practice to maintain the skill required for meaningful review.

AI is a tool, not a ceremony. Insisting on AI for every six-line function would be as irrational as refusing to use it for a repetitive 1,000-line report generator.

Security Experience Changes the Review

I have spent years working across infrastructure, identity, automation, and security. I have compromised hundreds of systems in authorized environments and completed extensive penetration-testing exercises. That experience shapes how I review generated automation and helps me identify risks that may not be immediately obvious.

I look for exposed secrets, injection opportunities, unsafe temporary files, wildcard sudo rules, uncontrolled command construction, excessive permissions, weak authentication, insecure transport, missing authorization checks, and data that should not appear in logs. I think about how a feature behaves when the input is malicious rather than merely malformed.

AI did not provide that judgment. It gives me another way to apply it faster.

The Two Unhelpful Extremes

There are two unhelpful extremes.

One extreme treats manual implementation as inherently more valuable, even when the problem is already well understood and generation would save substantial time. That approach may preserve craftsmanship but spend expensive hours reproducing patterns that could have been generated and reviewed in a fraction of the time.

The second delegates thinking along with typing. That person can produce large amounts of polished, plausible code without understanding its architecture, security properties, failure behavior, or operational consequences.

The effective approach sits between them:

  • Use AI aggressively where it compresses implementation.
  • Do not outsource problem definition or architectural judgment.
  • Increase review depth when familiarity with the technology decreases.
  • Validate outcomes instead of trusting appearances.
  • Remain capable of troubleshooting without the original AI conversation.
  • Accept responsibility for every deployed artifact.

AI Raises the Value of Experience

Generative AI lowers the cost of producing syntax. It does not eliminate the value of knowing which solution should exist.

An experienced engineer can use the saved implementation time to solve broader problems: connecting systems, improving security, standardizing delivery, designing evidence, reducing operational ambiguity, documenting tradeoffs, and building platforms instead of isolated scripts.

That is how I have adapted my own workflow. I write less code manually, but I design more systems. I review more critically. I produce more complete solutions. I can move from an idea to a working implementation fast enough to spend time improving the architecture instead of exhausting the project budget on boilerplate.

The result is not less engineering. It is more engineering per unit of time.

Final Thoughts

I still need to understand code. I still need to troubleshoot it when an automation fails during a maintenance window. I still need enough fluency to recognize insecure behavior, invented parameters, broken error handling, and incorrect assumptions.

What I no longer need is to prove my competence by manually typing every line.

AI can write the implementation.

I define what it must accomplish.
I design how it should behave.
I recognize what it got wrong.
I prove whether it worked.
I own what happens in production.

AI made syntax cheap. It did not make judgment, accountability, architecture, or experience cheap.

The engineers who benefit most from AI will not be the ones who surrender their thinking to it. They will be the ones who use it to compress implementation time while applying more judgment to larger problems.

AI can write the playbook. I still have to know what the playbook should do.

Tags: AI-Assisted Engineering, PowerShell, Ansible, Automation, Solutions Architecture, Platform Engineering, Code Review, Infrastructure as Code, Generative AI, Engineering Judgment

Published: September 4, 2026
Author: Robert H. Osborne

🛸