<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[c.swing | Engineering Notes]]></title><description><![CDATA[Practical insights on backend development, system architecture, databases, security, and automation from building and operating software systems.]]></description><link>https://cswing.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6ac6da603022b7e1d968c381/a2fc0fc8-afdc-4431-bc81-4664e5b3b250.png</url><title>c.swing | Engineering Notes</title><link>https://cswing.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 18 Oct 2026 15:33:04 GMT</lastBuildDate><atom:link href="https://cswing.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Designing a QA Harness for AI: From Business Understanding to Verifiable Results]]></title><description><![CDATA[1. The Question That Started the Project
In November 2025, I documented an idea: could AI automate the repetitive work involved in testing a web application?
Whenever a feature changed, someone had to]]></description><link>https://cswing.hashnode.dev/designing-a-qa-harness-for-ai-from-business-understanding-to-verifiable-results</link><guid isPermaLink="true">https://cswing.hashnode.dev/designing-a-qa-harness-for-ai-from-business-understanding-to-verifiable-results</guid><category><![CDATA[Quality Assurance]]></category><category><![CDATA[AI]]></category><category><![CDATA[TestAutomation]]></category><category><![CDATA[- #AIEngineering]]></category><category><![CDATA[harnessengineering]]></category><category><![CDATA[agenticai]]></category><category><![CDATA[Feedback loops]]></category><category><![CDATA[playwright]]></category><category><![CDATA[pytest]]></category><category><![CDATA[knowledgebase]]></category><category><![CDATA[SoftwareTesting]]></category><category><![CDATA[#HumanInTheLoop ]]></category><dc:creator><![CDATA[sung woon cho]]></dc:creator><pubDate>Thu, 08 Oct 2026 01:19:21 GMT</pubDate><content:encoded><![CDATA[<h2>1. The Question That Started the Project</h2>
<p>In November 2025, I documented an idea: could AI automate the repetitive work involved in testing a web application?</p>
<p>Whenever a feature changed, someone had to open the application, enter values, click buttons, and check the results. Because a change could affect other features, previously tested workflows also needed to be checked again.</p>
<p>My question was:</p>
<p><strong>If AI can understand an application’s interface and source code, could it identify what needs testing and carry out those tests?</strong></p>
<p>The initial plan had two stages. First, build an automated quality verification system. Then, use the knowledge gathered during testing to connect AI with existing web applications.</p>
<p>QA seemed like a useful starting point. Testing requires understanding what a screen means, how it should be operated, what results to expect, and how to recover from changes. That knowledge could eventually support broader workflow automation.</p>
<p>As I moved from the idea to implementation, another question became more important:</p>
<p><strong>When AI says, “I verified it,” what evidence should make me believe that claim?</strong></p>
<h2>2. Designing the Environment in Which AI Works</h2>
<p>In this project, I use <em>harness</em> to mean the structure connecting AI’s inputs, tools, execution constraints, evaluation criteria, evidence, and review process.</p>
<p>Delegating analysis and implementation to AI did not remove the need to decide:</p>
<ul>
<li><p>What counts as a valid source for an expected result?</p>
</li>
<li><p>Which actions are permitted or restricted?</p>
</li>
<li><p>How are test preconditions established and verified?</p>
</li>
<li><p>How are product defects distinguished from test or tool errors?</p>
</li>
<li><p>What must be completed before a task can be reported as verified?</p>
</li>
</ul>
<p>These decisions shaped the system. As failures appeared, I incorporated them into its rules and tools.</p>
<p>AI performed much of the analysis and implementation. I remained responsible for defining the problem, reviewing the evidence, and deciding which results could be accepted.</p>
<h2>3. The Architecture: From Evidence to Execution and Back</h2>
<p>The architecture connects a test execution pipeline with an evidence and review process. Product names and internal identifiers have been generalized.</p>
<pre><code class="language-mermaid">flowchart TB
    subgraph INPUT["1. Inputs and Evidence"]
        S["Product Source · QA Documents&lt;br/&gt;Existing Test Specifications"]
        O["AI Browser Exploration&lt;br/&gt;Network and Data Observations"]
        K["Static and Runtime Knowledge Bases"]
        S --&gt; K
        O --&gt; K
    end

    subgraph PIPE["2. Execution Pipeline"]
        T["Test Case Specification&lt;br/&gt;Purpose · Preconditions · Expectations · Evidence"]
        G["Test Case Compiler&lt;br/&gt;Specification to Execution Plan"]
        B["KB Gate&lt;br/&gt;Targets · Consistency · Assertions · Restrictions"]
        P["Execution Preparation&lt;br/&gt;Accounts · Permissions · Test Data"]
        X["Browser Executor&lt;br/&gt;Actions · Observations · Evidence Collection"]
        V["Result Evaluation&lt;br/&gt;Pass · Fail · Error · Blocked"]
        T --&gt; G --&gt; B --&gt; P --&gt; X --&gt; V
    end

    A["3. Application Under Test&lt;br/&gt;Isolated Business Web Application"]
    E["4. Evidence and Records&lt;br/&gt;Reports · Screenshots · Data Comparisons&lt;br/&gt;Defects · Reviews · Screen Manuals"]
    C["5. Operations Console and Human Review&lt;br/&gt;Select Scope · Review Results · Make Decisions"]
    H["6. Harness Verification&lt;br/&gt;pytest Contract Tests · Test Index"]

    S --&gt; T
    O --&gt; T
    K --&gt; B
    X --&gt;|"Perform actions"| A
    A --&gt;|"UI, network, and data results"| X
    V --&gt; E
    E --&gt; C
    C --&gt;|"Request execution"| P
    E --&gt;|"Update verified observations"| K
    C --&gt;|"Refine test cases"| T
    C --&gt;|"Convert failures into rules and tests"| H
    H -.-&gt; G
    H -.-&gt; B
    H -.-&gt; X
    H -.-&gt; V
</code></pre>
<p>The central pipeline describes execution. The evidence records and review process determine what the execution means. Feedback connections allow verified findings to improve test specifications and the harness.</p>
<p>An AI-generated explanation does not automatically become a fact for the next run. Its supporting evidence must be checked before the finding is incorporated into the system.</p>
<h2>4. How AI Builds an Understanding of a Screen</h2>
<p>Finding buttons is different from understanding a business workflow.</p>
<p>A registration button raises several questions: what does it register, under what conditions, where is the result stored, and which other features depend on that data?</p>
<p>I structured AI’s analysis around three sources.</p>
<table>
<thead>
<tr>
<th>Source</th>
<th>What It Helps Establish</th>
</tr>
</thead>
<tbody><tr>
<td>Business documentation and existing QA specifications</td>
<td>Workflow purpose, intended behavior, and existing test intent</td>
</tr>
<tr>
<td>Product source code</td>
<td>Event handling, validation conditions, APIs, and data relationships</td>
</tr>
<tr>
<td>Runtime observations</td>
<td>Visibility, enabled states, exact messages, requests, and data changes</td>
</tr>
</tbody></table>
<p>Browser exploration covered tabs, buttons, input fields, list columns, available options, and dialogs. Source analysis followed event handlers, validation functions, server requests, and data references.</p>
<p>Each tab was treated as a separate functional area. Tabs within the same screen could have different search conditions, required-field checks, and deletion confirmations. Nested dialogs were investigated independently rather than assumed to behave like their parents.</p>
<p>The analysis recorded both what had been inspected and what remained unverified. Conflicts between source code and runtime behavior were documented rather than silently resolved through inference.</p>
<p>The goal was to evaluate business understanding through <strong>traceable evidence</strong>, rather than the fluency of an explanation.</p>
<h2>5. Turning Business Understanding into Test Cases</h2>
<p>A test case defines an action under specific preconditions and the expected result to be checked.</p>
<p>Discovering a button does not produce a complete test case. Selection state, permissions, input conditions, and data types can all change its behavior.</p>
<p>Before generating executable tests, I used a verification ledger containing:</p>
<table>
<thead>
<tr>
<th>Field</th>
<th>Question</th>
</tr>
</thead>
<tbody><tr>
<td>Purpose</td>
<td>What behavior is being verified?</td>
</tr>
<tr>
<td>Preconditions</td>
<td>Which data, account, permissions, and mode are required?</td>
</tr>
<tr>
<td>Actions</td>
<td>What sequence should be performed?</td>
</tr>
<tr>
<td>Expected result</td>
<td>Which observable result determines the outcome?</td>
</tr>
<tr>
<td>Evidence</td>
<td>Which document, source location, or runtime observation supports the expectation?</td>
</tr>
<tr>
<td>Data changes</td>
<td>What changes, and how will it be restored?</td>
</tr>
<tr>
<td>Status</td>
<td>Is it executable, deferred, restricted, or unresolved?</td>
</tr>
</tbody></table>
<p>Observation and verification were kept separate.</p>
<p>“The delete button exists” is an observation. “The delete button must be unavailable when no item is selected” is a behavioral assertion.</p>
<h3>Required Fields Need More Than One Warning</h3>
<p>Leaving every field empty and checking for a warning does not establish that each required field is validated.</p>
<p>One validation could disappear while another still triggers the same warning, leaving the test green.</p>
<p>I therefore used the save-validation code to enumerate conditions and compared them with the required-field indicators on the screen. Each condition was tested by completing the other fields and leaving only the target field empty.</p>
<p>Positive controls also needed care. Completing all fields could cause a real save. Where persistence had to be verified, the test included controlled data creation and restoration.</p>
<h3>Search Filters Need Inclusion and Exclusion Checks</h3>
<p>An empty result does not prove that a filter works. The application may have had no matching data to begin with.</p>
<p>Tests therefore used both matching and non-matching records and checked that:</p>
<ul>
<li><p>Matching records remained.</p>
</li>
<li><p>Non-matching records were excluded.</p>
</li>
<li><p>Removing the filter restored the original results.</p>
</li>
</ul>
<p>Test data values came from the values actually used by the application. Inferring a code from a column name could create an invalid precondition and make a working feature appear defective.</p>
<h2>6. The KB Gate: Checking AI’s Claims Against Application Evidence</h2>
<p>One distinctive part of the design is the knowledge-base gate, or KB gate.</p>
<p>It goes beyond validating the format of an execution plan. It checks whether referenced targets, declared conditions, and assertions are consistent with the application’s structure and available evidence.</p>
<p>For example, a button identifier may exist in the source code but belong to a dialog that the current screen never opens. An existence check would pass, while the execution target would still be wrong.</p>
<p>The gate addresses questions such as:</p>
<ul>
<li><p>Does the referenced element exist in the supporting evidence?</p>
</li>
<li><p>Is the screen-to-dialog relationship correct?</p>
</li>
<li><p>Do precondition declarations contradict one another?</p>
</li>
<li><p>Can the assertions distinguish the execution conditions being tested?</p>
</li>
<li><p>Is the tool checking a product result, or merely reading back a value it inserted itself?</p>
</li>
<li><p>Could an ambiguous selector bypass an action restriction?</p>
</li>
</ul>
<p>I also tracked how many references each rule actually inspected. “No violations found” and “the rule was never applied” are different outcomes.</p>
<p>The strength of the evidence affected rule severity. A menu snapshot collected under one account, for example, may be incomplete because of permissions. Absence from that snapshot is not sufficient proof that a menu does not exist.</p>
<p>The KB gate documentation records rule intent, scope, false positives, blind spots, and what a successful check does <strong>not</strong> establish.</p>
<p>The important design decision was to make each rule’s coverage and limits inspectable.</p>
<h2>7. The pytest Index: Test Descriptions Also Need Verification</h2>
<p>Another distinctive component is a generated index of pytest tests.</p>
<p>A large test suite becomes difficult to assess if it is unclear which contracts the tests enforce, whether those tests are actually collected, or whether their descriptions match their assertions.</p>
<p>The index is generated from code rather than maintained as a manual list.</p>
<p>It cross-checks test definitions found through Python’s abstract syntax tree with the items collected by pytest. A mismatch causes generation to fail.</p>
<p>It also distinguishes:</p>
<ul>
<li><p>Test functions from parameter-expanded execution items.</p>
</li>
<li><p>Descriptions taken from a function’s docstring.</p>
</li>
<li><p>Descriptions written separately after inspecting the test body.</p>
</li>
</ul>
<p>Checks detect missing descriptions and stale entries left behind after a test is renamed or removed.</p>
<p>An important finding was that <strong>the descriptions themselves could be wrong</strong>. During the initial review, some descriptions claimed assertions the code did not make or reversed the direction of a check. Those descriptions were corrected.</p>
<p>The index therefore serves as a guide to the code, not a replacement for it. Description sources and review history are explicit, and later additions are not automatically presented as having received the same review.</p>
<p>Generation can help detect omissions and drift. It does not guarantee semantic accuracy. Keeping that distinction visible was part of the design.</p>
<h2>8. Two Feedback Loops</h2>
<p>I separated feedback into two loops: one improves the current test case; the other improves the environment that produces and executes test cases.</p>
<pre><code class="language-mermaid">flowchart LR
    subgraph L1["Loop A: Product and Test Verification"]
        A1["Understand the Workflow"] --&gt; A2["Generate Test Cases"]
        A2 --&gt; A3["Execute and Collect Evidence"]
        A3 --&gt; A4["Classify the Cause"]
        A4 --&gt;|"Refine tests or preconditions"| A2
        A4 --&gt;|"Record product defects"| A5["Maintain Reproduction Tests"]
    end

    subgraph L2["Loop B: Harness Improvement"]
        B1["Find Omissions, Misobservations, or Incorrect Reports"]
        B1 --&gt; B2["Revise Criteria and SOP"]
        B2 --&gt; B3["Add Gate Rules and Contract Tests"]
        B3 --&gt; B4["Check Detection and Side Effects"]
        B4 --&gt; B5["Apply to Subsequent Work"]
    end

    A4 --&gt;|"Identify a recurring structural problem"| B1
    B5 --&gt; A1
</code></pre>
<p>Loop A improves a particular test. Loop B prevents the same class of error from recurring across future work.</p>
<p>A product defect must not be normalized by changing the expected result to match the faulty behavior. If a test intentionally reproduces a defect, that purpose must be explicit.</p>
<p>Similarly, a gate’s false positive should not be resolved by weakening the test. The rule’s evidence and applicability need to be reviewed.</p>
<p>The objective of iteration is <strong>correct cause classification and better verification</strong>, not simply obtaining a passing result.</p>
<h2>9. Turning Incorrect AI Reports into Structural Changes</h2>
<p>There were cases where AI’s reports did not match what had actually been verified.</p>
<p>The records do not establish intentional deception. Nevertheless, unsupported claims such as “fully inspected,” “no writes,” or “verification complete” make the result unreliable.</p>
<p>I addressed these problems by changing the process.</p>
<table>
<thead>
<tr>
<th>Problem</th>
<th>Change</th>
</tr>
</thead>
<tbody><tr>
<td>Inspecting only some tabs and reporting complete coverage</td>
<td>Record inspected and uninspected scope; compare tabs and nested features individually</td>
</tr>
<tr>
<td>A test title claiming more than the execution performed</td>
<td>Review every test’s title, steps, assertions, and results</td>
</tr>
<tr>
<td>Deferred items disappearing from subsequent reports</td>
<td>Define resumption conditions, reassess deferred items, and synchronize remaining-work records</td>
</tr>
<tr>
<td>Reporting no writes while omitting a settings table</td>
<td>Expand data comparisons to the tables modified by invoked APIs</td>
</tr>
<tr>
<td>Reporting completion after execution alone</td>
<td>Require review evidence, current records, indexes, and manuals</td>
</tr>
</tbody></table>
<p>One particularly instructive case involved opening and closing a dialog.</p>
<p>The exploration was assumed to be read-only, but the close handler sent a settings update. The network log captured the request, while the database comparison omitted the settings table.</p>
<p>The resulting screen behavior was then mistaken for a product defect. Repeated reproduction evidence accumulated, but the causal interpretation remained wrong.</p>
<p>The process was revised to inspect close handlers and verify that every observed write path was covered by the data comparison.</p>
<p><strong>Repeated reproduction is not proof of a correct explanation.</strong></p>
<h2>10. The SOP Became a Contract for AI Work</h2>
<p>These failures were incorporated into the standard operating procedure.</p>
<p>Its central principles were:</p>
<ul>
<li><p>Replace vague instructions with verifiable criteria.</p>
</li>
<li><p>Require evidence for completion claims.</p>
</li>
<li><p>Record why work remains incomplete and when it should be reconsidered.</p>
</li>
</ul>
<p>“Checked carefully” was insufficient without scope and method. “No issues” required expectations and observations. “Verified” required evidence that the completion conditions had been met.</p>
<p>The SOP itself was also subject to revision. If following a procedure still produced a failure, the procedure had to be examined. Assuming that opening and closing a dialog was read-only was one such failure.</p>
<p>The SOP became a way to turn experience into constraints and verification criteria for the next run.</p>
<h2>11. Completion Includes What Happens After Execution</h2>
<p>A deletion message does not prove that data was deleted. A functional test can pass while leaving test data behind.</p>
<p>The system therefore checks application results, actual data state, and restoration. Where restoring a change is part of the test’s claim, restoration belongs in the evaluated assertions.</p>
<p>Defect-reproduction tests also need different presentation. A passing reproduction test may mean the defect still exists. It should not appear as an ordinary green success.</p>
<p>Completion consequently requires more than an execution result:</p>
<ul>
<li><p>Reviewed scope and remaining scope.</p>
</li>
<li><p>Links between defects and reproduction tests.</p>
</li>
<li><p>Evidence of data changes and restoration.</p>
</li>
<li><p>Current review records and indexes.</p>
</li>
<li><p>Workflow documentation and unresolved findings.</p>
</li>
</ul>
<p>Not every condition is already enforced automatically. Some remain checklist and review requirements, with automation recorded as future work.</p>
<p>Making those limitations visible is part of reliable reporting.</p>
<h2>12. How the Original Idea Developed</h2>
<p>The November 2025 concept focused on reducing repetitive QA effort. It developed into workflow analysis, test generation, and browser execution. Reviews and failures in August 2026 led to stronger reporting and completion criteria.</p>
<p>My contribution was not limited to deciding what AI should build. It included defining the conditions under which its output could be accepted.</p>
<p>The KB gate checks execution plans against application evidence. pytest contract tests constrain tool behavior. The generated test index checks inventory and documentation consistency. The SOP preserves lessons from failures.</p>
<p>Connecting these components creates a continuous process:</p>
<p><strong>Analysis → execution → evidence → judgment → rule improvement</strong></p>
<p>AI carried out much of the analysis and implementation. I retained responsibility for problem definition, evidence selection, verification scope, action boundaries, and completion decisions.</p>
<p>The original idea was to reduce repetitive work with AI. The resulting system is a <strong>QA harness that verifies AI’s work and turns its failures into rules for subsequent execution</strong>.</p>
]]></content:encoded></item><item><title><![CDATA[From Four Hours to Minutes: Automating Linux Security Remediation with AI]]></title><description><![CDATA[Finding an Opportunity in Repetitive Work
Applying a single security remediation across roughly 100 Linux servers used to take about four hours.
The process involved connecting to each server, checkin]]></description><link>https://cswing.hashnode.dev/from-four-hours-to-minutes-automating-linux-security-remediation-with-ai</link><guid isPermaLink="true">https://cswing.hashnode.dev/from-four-hours-to-minutes-automating-linux-security-remediation-with-ai</guid><category><![CDATA[Linux]]></category><category><![CDATA[Security]]></category><category><![CDATA[automation]]></category><category><![CDATA[AI]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[sung woon cho]]></dc:creator><pubDate>Thu, 08 Oct 2026 00:41:56 GMT</pubDate><content:encoded><![CDATA[<h2>Finding an Opportunity in Repetitive Work</h2>
<p>Applying a single security remediation across roughly 100 Linux servers used to take about four hours.</p>
<p>The process involved connecting to each server, checking its configuration, backing up the original files, applying the change, and verifying the result. Each individual task was straightforward, but repeating it across many servers took time. Tracking completed work and recording results added to the effort.</p>
<p>I saw an opportunity to turn this repeated procedure into a workflow that an operator could initiate with a single action. The system would handle execution and record the results for each server.</p>
<p>I planned the tool and used AI as a development assistant, completing development in <strong>two days</strong>.</p>
<p>This article shares my personal experience from a workplace project. Proprietary implementation details, internal security policies, and actual remediation commands are omitted. It does not represent an official statement from my employer.</p>
<h2>Turning Command Execution into an Operational Tool</h2>
<p>A script that repeatedly executes commands can reduce manual work, but operators also need to manage targets, understand progress, identify failures, and review results.</p>
<p>I built the workflow around these needs:</p>
<ul>
<li><p><strong>SSH execution:</strong> Connect to registered Linux servers, perform remediation, and record results separately for each target.</p>
</li>
<li><p><strong>Policy management:</strong> Store and manage remediation policies and their execution commands in a database.</p>
</li>
<li><p><strong>Distinct execution stages:</strong> Separate checks, backups, changes, and verification so failures can be traced to a specific stage.</p>
</li>
<li><p><strong>Web monitoring:</strong> Display server status and execution logs through a dashboard.</p>
</li>
<li><p><strong>History and permissions:</strong> Retain results for later review and distinguish management, execution, and viewing permissions.</p>
</li>
</ul>
<p>I also included a stop request. It prevents subsequent work after the current command finishes; it does not undo changes already applied.</p>
<p>The aim was to make initiating the work simple while keeping its execution and results visible.</p>
<h2>Using AI to Shorten Development</h2>
<p>Before implementation, I defined the workflow and the features needed to support it. I then used AI to assist with implementation, reviewed the generated results, and revised behavior that did not match the requirements.</p>
<p>Keeping the scope focused helped. Rather than attempting to automate every security task, I concentrated on executing recurring remediation and making the results reviewable.</p>
<p>This approach allowed me to complete development in two days while keeping additional staffing needs low. AI helped accelerate implementation, while I focused on whether the tool matched the operational workflow.</p>
<p>Fast development still requires careful review. A tool that changes server configurations needs clear execution boundaries, permissions, failure handling, and verification.</p>
<h2>From Four Hours to a Few Minutes</h2>
<p>For the remediation task described here, applying one security change across roughly 100 servers went from <strong>about four hours to just a few minutes</strong>.</p>
<p>Instead of connecting to each server and entering commands repeatedly, the operator could initiate the workflow once and review the recorded results. Their attention shifted toward progress monitoring, failed tasks, and exceptions.</p>
<p>This timing reflects that particular task, rather than a guarantee for every remediation or environment.</p>
<p>The experience showed me how a clearly defined operational problem can become a practical tool in a short development cycle with AI assistance. For my next improvement, I would start by looking for another procedure people spend time repeating.</p>
]]></content:encoded></item></channel></rss>