<?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: Rafael</title>
    <description>The latest articles on DEV Community by Rafael (@rafael_dev).</description>
    <link>https://dev.to/rafael_dev</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%2F4007091%2Fe49ae159-f3b3-49f9-923c-97d0b9898d24.jpg</url>
      <title>DEV Community: Rafael</title>
      <link>https://dev.to/rafael_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rafael_dev"/>
    <language>en</language>
    <item>
      <title>How JavaScript Is Defined: From ECMAScript to Array.prototype.map</title>
      <dc:creator>Rafael</dc:creator>
      <pubDate>Fri, 02 Oct 2026 21:18:51 +0000</pubDate>
      <link>https://dev.to/rafael_dev/how-javascript-is-defined-from-ecmascript-to-arrayprototypemap-5971</link>
      <guid>https://dev.to/rafael_dev/how-javascript-is-defined-from-ecmascript-to-arrayprototypemap-5971</guid>
      <description>&lt;p&gt;We use JavaScript every day through syntax such as:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&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;doubled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We know what &lt;code&gt;map()&lt;/code&gt; does, but there is a more interesting question underneath:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who decided that &lt;code&gt;map()&lt;/code&gt; should behave this way?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why does it skip empty array slots? Why does its callback receive the value, index, and array? Why can &lt;code&gt;Array.prototype.map&lt;/code&gt; even be used with objects that are not arrays?&lt;/p&gt;

&lt;p&gt;The answers are not specific to Chrome, Firefox, or Node.js. They come from the formal definition of the JavaScript language.&lt;/p&gt;

&lt;p&gt;To understand that, we need to go back a little.&lt;/p&gt;

&lt;h2&gt;
  
  
  From JavaScript to ECMAScript
&lt;/h2&gt;

&lt;p&gt;JavaScript was created by Brendan Eich at Netscape in the 1990s and first appeared in Netscape Navigator. Microsoft later introduced its own related implementation, called JScript.&lt;/p&gt;

&lt;p&gt;This created an important problem. If different companies could independently decide how the language worked, code written for one browser could behave differently in another.&lt;/p&gt;

&lt;p&gt;A common definition of the language was needed.&lt;/p&gt;

&lt;p&gt;Standardization work started at &lt;strong&gt;Ecma International&lt;/strong&gt; in November 1996, and the first edition of the ECMAScript standard was adopted in June 1997.&lt;/p&gt;

&lt;p&gt;Ecma International is a standards organization. Inside it, different technical committees are responsible for different technologies. The committee responsible for JavaScript's standardized language is &lt;strong&gt;TC39&lt;/strong&gt;, or &lt;strong&gt;Technical Committee 39&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So we can start building the relationship:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ecma International → TC39 → ECMAScript specification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TC39 discusses and develops changes to the language. New features go through a proposal process before becoming part of the standard.&lt;/p&gt;

&lt;p&gt;But where does &lt;strong&gt;ECMA-262&lt;/strong&gt; fit into this?&lt;/p&gt;

&lt;h2&gt;
  
  
  ECMA-262, ECMAScript, and JavaScript
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ECMA-262&lt;/strong&gt; is the number of the Ecma standard that defines the ECMAScript language.&lt;/p&gt;

&lt;p&gt;Its name is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ECMAScript Language Specification&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So these terms describe different things:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Term&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ecma International&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Standards organization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TC39&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Technical committee responsible for ECMAScript&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ECMA-262&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Standard document that defines ECMAScript&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ECMAScript&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Programming language specification defined by ECMA-262&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;JavaScript&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Programming language based on and implementing the ECMAScript specification&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;ECMA-262 is periodically published in new editions.&lt;/p&gt;

&lt;p&gt;For example, the current published standard is &lt;strong&gt;ECMA-262, 17th Edition&lt;/strong&gt;, which defines &lt;strong&gt;ECMAScript 2026&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Term&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ECMA-262&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The standard identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;17th Edition&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The edition of the ECMA-262 standard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ECMAScript 2026&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The ECMAScript version defined by that edition&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The 17th edition was published in June 2026 and defines ECMAScript 2026.&lt;/p&gt;

&lt;p&gt;The number &lt;code&gt;262&lt;/code&gt; is therefore &lt;strong&gt;not a JavaScript version&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Likewise &lt;code&gt;ECMAScript 2026&lt;/code&gt; does not mean "version 2026" in the traditional software-version sense. ECMAScript has followed an annual release model for several years.&lt;/p&gt;

&lt;p&gt;There is also a &lt;strong&gt;living specification&lt;/strong&gt; maintained by TC39. After the yearly snapshot is published, completed proposals and specification changes continue to be incorporated into the living document. As of October 2026, that document is already titled &lt;strong&gt;ECMAScript 2027&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This gives us the larger picture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5w8bsona885fci5glz2r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5w8bsona885fci5glz2r.png" alt="A horizontal flow diagram showing how JavaScript is standardized and implemented: Ecma International → TC39 → ECMA-262 → ECMAScript Language → JavaScript Engines → Code. Each stage is displayed inside a rounded rectangular box connected by arrows on a dark background." width="800" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can return to &lt;code&gt;map()&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where does &lt;code&gt;map()&lt;/code&gt; actually come from?
&lt;/h2&gt;

&lt;p&gt;Consider:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It may look as if &lt;code&gt;numbers&lt;/code&gt; itself contains a &lt;code&gt;map&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;It does not.&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;map&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Arrays inherit that method through their prototype chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;numbers → Array.prototype → Object.prototype → null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And:&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="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So when we write:&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="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JavaScript finds &lt;code&gt;map&lt;/code&gt; on &lt;code&gt;Array.prototype&lt;/code&gt; and calls it with &lt;code&gt;numbers&lt;/code&gt; as its &lt;code&gt;this&lt;/code&gt; value.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where the ECMAScript definition of &lt;code&gt;Array.prototype.map&lt;/code&gt; becomes relevant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading the specification
&lt;/h2&gt;

&lt;p&gt;The actual specification describes &lt;code&gt;map()&lt;/code&gt; approximately like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Let O be ? ToObject(this value).
2. Let len be ? LengthOfArrayLike(O).
3. If IsCallable(callback) is false, throw a TypeError.
4. Let A be ? ArraySpeciesCreate(O, len).
5. Let k be 0.
6. Repeat while k &amp;lt; len:
   a. Let Pk be ! ToString(𝔽(k)).
   b. Let kPresent be ? HasProperty(O, Pk).
   c. If kPresent is true:
      i.   Let kValue be ? Get(O, Pk).
      ii.  Let mappedValue be ?
           Call(callback, thisArg, « kValue, 𝔽(k), O »).
      iii. Perform ?
           CreateDataPropertyOrThrow(A, Pk, mappedValue).
   d. Set k to k + 1.
7. Return A.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;It's defined in &lt;a href="https://tc39.es/ecma262/pr/3782/multipage/indexed-collections.html#sec-array.prototype.map" rel="noopener noreferrer"&gt;ECMAScript® 2026 Language Specification&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is not JavaScript source code.&lt;/p&gt;

&lt;p&gt;Operations such as &lt;code&gt;ToObject&lt;/code&gt;, &lt;code&gt;HasProperty&lt;/code&gt;, &lt;code&gt;Get&lt;/code&gt;, and &lt;code&gt;Call&lt;/code&gt; are called &lt;strong&gt;abstract operations&lt;/strong&gt;. They are tools the specification uses to formally describe how JavaScript must behave.&lt;/p&gt;

&lt;p&gt;Let's translate this algorithm gradually.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, identify what is being mapped
&lt;/h2&gt;

&lt;p&gt;The algorithm starts with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Let O be ? ToObject(this value).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For:&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="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;this&lt;/code&gt; is &lt;code&gt;numbers&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, for our example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;O = numbers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The specification deliberately calls it &lt;code&gt;O&lt;/code&gt;, meaning an object, rather than something like &lt;code&gt;array&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That is because &lt;code&gt;map()&lt;/code&gt; is more generic than it first appears. It can work with some non-array objects too.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Let len be ? LengthOfArrayLike(O).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;len = 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The algorithm now knows that it needs to consider positions &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt;, and &lt;code&gt;2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It then verifies that the callback is actually callable and creates the array that will contain the result.&lt;/p&gt;

&lt;p&gt;We can approximate the beginning with:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;O&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&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;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;O&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TypeError&lt;/span&gt;&lt;span class="p"&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;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real specification is more precise than this, but this is a useful mental model.&lt;/p&gt;

&lt;h2&gt;
  
  
  From an index to a property
&lt;/h2&gt;

&lt;p&gt;Now the interesting part begins.&lt;/p&gt;

&lt;p&gt;The algorithm initializes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k = 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and repeats until:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k &amp;lt; len
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But it does not simply access:&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="nx"&gt;O&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The specification first creates something called &lt;code&gt;Pk&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Let Pk be ! ToString(𝔽(k)).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k
↓
1

ToString(...)
↓
"1"

Pk = "1"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why convert the index to a string?&lt;/p&gt;

&lt;p&gt;Because an Array is also an Object.&lt;/p&gt;

&lt;p&gt;Consider:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&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="s2"&gt;B&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="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the language level, we can think about its indexed properties like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"0" → "A"
"1" → "B"
"2" → "C"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is why:&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="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Normal JavaScript property keys are strings or symbols. The specification therefore turns the numeric position used by the algorithm into the property key that will be used to inspect the object.&lt;/p&gt;

&lt;p&gt;This does &lt;strong&gt;not&lt;/strong&gt; mean that a JavaScript engine must physically store &lt;code&gt;"1"&lt;/code&gt; as a string somewhere in memory.&lt;/p&gt;

&lt;p&gt;The specification defines behavior. The implementation is free to optimize that behavior internally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does that property actually exist?
&lt;/h2&gt;

&lt;p&gt;After obtaining &lt;code&gt;Pk&lt;/code&gt;, the algorithm asks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Let kPresent be ? HasProperty(O, Pk).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A useful approximation is:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kPresent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Pk&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;O&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This distinction is important because JavaScript arrays can contain &lt;strong&gt;holes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Compare:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&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;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both produce:&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="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But structurally they are different:&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="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;a&lt;/code&gt;, the property exists and its value is &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;b&lt;/code&gt;, the property does not exist.&lt;/p&gt;

&lt;p&gt;This is why &lt;code&gt;map()&lt;/code&gt; cannot simply retrieve the value and check whether it is &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It first asks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Does property "1" exist?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only if the answer is &lt;code&gt;true&lt;/code&gt; does it call the callback.&lt;/p&gt;

&lt;p&gt;That explains this behavior:&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="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10
30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The callback is never executed for the missing property.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;HasProperty&lt;/code&gt; and the prototype chain
&lt;/h2&gt;

&lt;p&gt;There is another subtle detail.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;HasProperty&lt;/code&gt; does not only inspect properties directly owned by the array.&lt;/p&gt;

&lt;p&gt;It also considers the prototype chain.&lt;/p&gt;

&lt;p&gt;That makes it closer to:&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;than:&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The array itself still does not own &lt;code&gt;"1"&lt;/code&gt;:&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But:&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;because JavaScript can find it here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;arr
 │
 │ "1"? no
 ▼
Array.prototype
 │
 │ "1"? yes
 └── 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Therefore:&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="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;// 100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And because &lt;code&gt;map()&lt;/code&gt; uses &lt;code&gt;HasProperty&lt;/code&gt;, this also affects 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="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The callback receives &lt;code&gt;100&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is an intentionally unusual example, and modifying native prototypes like this should generally be avoided. But it exposes how closely &lt;code&gt;map()&lt;/code&gt; interacts with JavaScript's object model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading and mapping the value
&lt;/h2&gt;

&lt;p&gt;Once the property is known to exist, the specification performs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Get(O, Pk)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pk = "1"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Get(numbers, "1")
→ 20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That becomes &lt;code&gt;kValue&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The specification then calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Call(callback, thisArg, « kValue, 𝔽(k), O »)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which can be understood approximately as:&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="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;thisArg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;kValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;O&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also explains where the familiar callback arguments come from:&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="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;array&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="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They directly correspond to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kValue → value
k      → index
O      → array
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If our callback is:&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="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kValue = 20

callback(20, 1, numbers)
↓
40
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The specification calls that result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mappedValue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, it creates the corresponding property in the result array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CreateDataPropertyOrThrow(A, Pk, mappedValue)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which we can roughly imagine as:&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="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Pk&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mappedValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then &lt;code&gt;k&lt;/code&gt; is incremented, and the process repeats.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting the pieces together
&lt;/h2&gt;

&lt;p&gt;A simplified version of everything we have just read would look like this:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;simplifiedMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;thisArg&lt;/span&gt;&lt;span class="p"&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;O&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&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;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;O&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TypeError&lt;/span&gt;&lt;span class="p"&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;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&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;Pk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&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;Pk&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;O&lt;/span&gt;&lt;span class="p"&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;kValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;O&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Pk&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;mappedValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;thisArg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;kValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;O&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Pk&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mappedValue&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is &lt;strong&gt;not the actual implementation used by V8 or another JavaScript engine&lt;/strong&gt;, nor is it a completely faithful reimplementation of every ECMAScript abstract operation.&lt;/p&gt;

&lt;p&gt;But it exposes the logic behind the specification.&lt;/p&gt;

&lt;p&gt;For:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we can now follow the first iteration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k = 0
  ↓
Pk = "0"
  ↓
HasProperty(numbers, "0")
  ↓
 true
  ↓
Get(numbers, "0")
  ↓
 10
  ↓
callback(10, 0, numbers)
  ↓
 20
  ↓
result["0"] = 20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k = 1
  ↓
Pk = "1"
  ↓
HasProperty(numbers, "1")
  ↓
 true
  ↓
Get(numbers, "1")
  ↓
 20
  ↓
callback(20, 1, numbers)
  ↓
 40
  ↓
result["1"] = 40
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally:&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="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What initially looked like a simple loop is actually built on top of several fundamental parts of JavaScript: objects, property keys, prototype lookup, property existence, function calls, and array creation.&lt;/p&gt;

&lt;p&gt;That is the value of reading ECMA-262. It moves us from knowing &lt;strong&gt;how to use JavaScript&lt;/strong&gt; to understanding &lt;strong&gt;why JavaScript behaves the way it does&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>AWS Networking Fundamentals: VPCs, Subnets, Routing, IGWs, NACLs, and Security Groups</title>
      <dc:creator>Rafael</dc:creator>
      <pubDate>Mon, 28 Sep 2026 13:44:58 +0000</pubDate>
      <link>https://dev.to/rafael_dev/aws-networking-fundamentals-vpcs-subnets-routing-igws-nacls-and-security-groups-10f4</link>
      <guid>https://dev.to/rafael_dev/aws-networking-fundamentals-vpcs-subnets-routing-igws-nacls-and-security-groups-10f4</guid>
      <description>&lt;p&gt;In this post, we'll explore some of the fundamental concepts behind &lt;strong&gt;AWS networking&lt;/strong&gt; and understand how they work together.&lt;/p&gt;

&lt;p&gt;The goal is to build a clear mental model of how network communication works inside AWS. By the end of this post, you should be able to explain the role of components such as &lt;strong&gt;Regions, Availability Zones (AZs), VPCs, Subnets, Route Tables, Internet Gateways (IGWs), Network ACLs (NACLs), and Security Groups (SGs)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu8fi61b043ltlrnton86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu8fi61b043ltlrnton86.png" alt="AWS networking diagram showing one VPC spanning two Availability Zones, each with public subnets containing EC2 instances and private subnets containing RDS databases, connected to the internet through an Internet Gateway." width="782" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At its core, networking is about enabling devices and resources to communicate and exchange data. In AWS, the same principle applies, but the network is defined and managed through cloud infrastructure.&lt;/p&gt;

&lt;p&gt;Consider a simple example: an EC2 instance hosting an application that needs to be accessible from the internet. For a user to reach that instance, AWS needs a valid network path and a set of rules controlling how traffic moves through the infrastructure.&lt;/p&gt;

&lt;p&gt;Understanding these components and how they interact provides the foundation for designing and troubleshooting AWS networks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Documentation often uses abbreviations instead of full names. To become more familiar with this terminology, we'll use the abbreviations introduced throughout this post, such as &lt;strong&gt;AZ&lt;/strong&gt;, &lt;strong&gt;VPC&lt;/strong&gt;, &lt;strong&gt;IGW&lt;/strong&gt;, &lt;strong&gt;NACL&lt;/strong&gt;, and &lt;strong&gt;SG&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Region and Availability Zone
&lt;/h3&gt;

&lt;p&gt;An &lt;strong&gt;AWS Region&lt;/strong&gt; is a geographic area where AWS operates its cloud infrastructure.&lt;/p&gt;

&lt;p&gt;Each Region is independent from the others and contains multiple &lt;strong&gt;Availability Zones (AZs)&lt;/strong&gt;. When you create resources in AWS, one of the first decisions you make is which Region they should belong to. For example, &lt;code&gt;us-east-1&lt;/code&gt; represents the &lt;strong&gt;US East (N. Virginia)&lt;/strong&gt; Region, while &lt;code&gt;sa-east-1&lt;/code&gt; represents &lt;strong&gt;South America (São Paulo)&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A useful way to visualize the hierarchy is:&lt;br&gt;
&lt;strong&gt;AWS Global Infrastructure → Region → Availability Zones&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Choosing a Region can affect factors such as &lt;strong&gt;latency, cost, service availability, and data residency requirements&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Something to keep in mind is that the closest Region is not always the best choice. When selecting a Region, you should evaluate trade-offs such as latency, cost, service availability, capacity, and reliability requirements.&lt;/p&gt;

&lt;p&gt;For example, even if your users are located in South America, you might choose a Region in North America if the additional latency is acceptable and that Region provides better pricing, service availability, or other advantages for your workload.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  VPC
&lt;/h3&gt;

&lt;p&gt;Amazon VPC allows you to create a logically isolated virtual network within an AWS Region, where you can launch and manage AWS resources.&lt;/p&gt;

&lt;p&gt;Inside a VPC, you define how your network should behave, including its IP address range, subnets, routing rules, internet connectivity, and network security. Resources such as EC2 instances, databases, and load balancers can then be deployed inside this network according to the level of connectivity and isolation they require.&lt;/p&gt;

&lt;p&gt;Amazon VPC allows you to create a logically isolated virtual network within an AWS Region, where you can launch and manage AWS resources. Also, a VPC can span multiple &lt;strong&gt;Availability Zones&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In practice, the VPC acts as the main network boundary for your AWS resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subnets
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Subnets&lt;/strong&gt; are used to divide a VPC into smaller network segments and organize resources according to their networking requirements.&lt;/p&gt;

&lt;p&gt;Each subnet belongs to a single AZ. This allows you to distribute resources across isolated locations for better availability and fault tolerance.&lt;/p&gt;

&lt;p&gt;A subnet can be designed as &lt;strong&gt;public&lt;/strong&gt; or &lt;strong&gt;private&lt;/strong&gt;, depending on how its routing is configured.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;private subnet&lt;/strong&gt; is commonly used for resources that should not be directly accessible from the internet, such as databases containing customer or transactional data.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;public subnet&lt;/strong&gt; is commonly used for resources that need direct internet connectivity, such as public-facing web servers or load balancers.&lt;/p&gt;

&lt;p&gt;What determines whether a subnet is &lt;strong&gt;public or private&lt;/strong&gt; is mainly its routing configuration.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;public subnet&lt;/strong&gt; has a route to an &lt;strong&gt;Internet Gateway (IGW)&lt;/strong&gt;, which provides a path between the subnet and the internet. However, this does not automatically make every resource inside the subnet publicly accessible. For example, an EC2 instance also needs a public IP address and appropriate security rules to communicate directly with the internet.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;private subnet&lt;/strong&gt; does not have a direct route to an IGW. It can still access the internet for outbound traffic through a &lt;strong&gt;NAT Gateway&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So, in practice, the distinction between public and private subnets comes primarily from how their &lt;strong&gt;route tables&lt;/strong&gt; are configured.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is very common to place compute resources, such as EC2 instances or load balancers, in a &lt;strong&gt;public subnet&lt;/strong&gt; and databases in a &lt;strong&gt;private subnet&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this architecture, users can reach the public-facing compute layer from the internet, while the database remains inaccessible directly from the internet. The database can still be reached by the application through the VPC's private network.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Internet Gateway
&lt;/h3&gt;

&lt;p&gt;An &lt;strong&gt;Internet Gateway (IGW)&lt;/strong&gt; is a VPC component that enables communication between resources inside the VPC and the internet.&lt;/p&gt;

&lt;p&gt;An IGW is attached to a VPC and can be used as a target in a route table. For example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;0.0.0.0/0 → Internet Gateway&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This route provides a path from the subnet to the internet. However, a resource such as an EC2 instance also needs a public IP address and appropriate security rules to communicate directly with the internet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Route Table
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Route Table&lt;/strong&gt; defines where network traffic from a subnet should be sent.&lt;/p&gt;

&lt;p&gt;Each route contains two main pieces of information:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Destination&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The IP range the traffic is trying to reach&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Target&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Where AWS should send that traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Destination&lt;/th&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;10.0.0.0/16&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;local&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0.0.0.0/0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Internet Gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;local&lt;/code&gt; route allows resources inside the VPC to communicate with each other. AWS automatically adds this route to every route table.&lt;/p&gt;

&lt;p&gt;A route such as:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;0.0.0.0/0 → Internet Gateway&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;means that traffic destined for addresses outside the VPC can be sent to the internet.&lt;/p&gt;

&lt;p&gt;Each subnet must be associated with a route table. A route table can be associated with multiple subnets, but each subnet uses only one route table at a time. If no explicit association is defined, the subnet automatically uses the VPC's &lt;strong&gt;main route table&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Route tables are also what primarily distinguish &lt;strong&gt;public and private subnets&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;public subnet&lt;/strong&gt; has a route to an &lt;strong&gt;Internet Gateway (IGW)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;private subnet&lt;/strong&gt; does not have a direct route to an IGW. It may instead route outbound internet traffic through a &lt;strong&gt;NAT Gateway&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When multiple routes could match a destination, AWS uses the &lt;strong&gt;most specific matching route&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In short, a route table answers a simple question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Where should this packet go next?"&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Network ACLs
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Network ACL (NACL)&lt;/strong&gt; is a virtual firewall that controls inbound and outbound traffic at the &lt;strong&gt;subnet level&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can think of it like passport control at an airport. Travelers represent network packets, while the passport control officer represents the NACL. Every time a traveler enters or leaves the country, their credentials are checked. Similarly, a NACL evaluates traffic whenever it enters or leaves a subnet.&lt;/p&gt;

&lt;p&gt;NACLs are &lt;strong&gt;stateless&lt;/strong&gt;, meaning inbound and outbound traffic are evaluated independently. If you allow traffic in one direction, you must also explicitly allow the corresponding traffic in the opposite direction.&lt;/p&gt;

&lt;p&gt;The default behavior of a &lt;strong&gt;Network ACL (NACL)&lt;/strong&gt; depends on whether it is the default NACL or a custom one.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;NACL type&lt;/th&gt;
&lt;th&gt;Default behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Default NACL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Allow all inbound and outbound traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom NACL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Deny all inbound and outbound traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Because NACLs are &lt;strong&gt;stateless&lt;/strong&gt;, inbound and outbound traffic must be allowed independently. &lt;/p&gt;

&lt;p&gt;NACL rules are evaluated in numerical order, starting with the lowest rule number. AWS stops evaluating rules as soon as it finds the first matching rule.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NACLs do not distinguish between requests and responses. They only evaluate whether a packet is entering or leaving the subnet. Because NACLs are &lt;strong&gt;stateless&lt;/strong&gt;, both directions must be explicitly allowed. This applies both to response traffic and to new connections initiated by resources inside the subnet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Security Groups
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Security Group (SG)&lt;/strong&gt; is a virtual firewall attached to specific AWS resources, such as EC2 instances. While a NACL controls traffic at the &lt;strong&gt;subnet level&lt;/strong&gt;, an SG controls traffic at the &lt;strong&gt;resource level&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Security Groups define which traffic is allowed to enter or leave a resource through &lt;strong&gt;inbound&lt;/strong&gt; and &lt;strong&gt;outbound rules&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By default, a newly created SG:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;denies all inbound traffic;&lt;/li&gt;
&lt;li&gt;allows all outbound traffic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SGs only support &lt;strong&gt;allow rules&lt;/strong&gt;. Any traffic that does not match an allowed rule is implicitly denied.&lt;/p&gt;

&lt;p&gt;One of the most important characteristics of Security Groups is that they are &lt;strong&gt;stateful&lt;/strong&gt;. This means AWS keeps track of established connections.&lt;/p&gt;

&lt;p&gt;For example, suppose an EC2 instance allows inbound HTTPS traffic on port &lt;code&gt;443&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client → EC2
1.2.3.4:52000 → 10.0.1.10:443
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this connection is allowed by the SG, the response is automatically allowed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EC2 → Client
10.0.1.10:443 → 1.2.3.4:52000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You do not need to create a separate outbound rule specifically for that response.&lt;/p&gt;

&lt;p&gt;The same principle applies to connections initiated by the EC2 instance: if the outbound connection is allowed, the corresponding response traffic is automatically permitted.&lt;/p&gt;

&lt;p&gt;By default, a new &lt;strong&gt;Security Group (SG)&lt;/strong&gt; denies all inbound traffic and allows all outbound traffic.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Direction&lt;/th&gt;
&lt;th&gt;Default behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Inbound&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Deny all&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Outbound&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Allow all&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If all outbound rules are removed, new outbound connections are denied. Because SGs are &lt;strong&gt;stateful&lt;/strong&gt;, response traffic for an already allowed connection is still permitted automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Differences between SGs and NACLs
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Security Group (SG)&lt;/th&gt;
&lt;th&gt;Network ACL (NACL)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scope&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Resource level&lt;/td&gt;
&lt;td&gt;Subnet level&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Association&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Attached to resources such as EC2 instances&lt;/td&gt;
&lt;td&gt;Associated with subnets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;State&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Stateful&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Stateless&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rules&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Allow rules only&lt;/td&gt;
&lt;td&gt;Allow and deny rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rule evaluation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;All rules are evaluated together&lt;/td&gt;
&lt;td&gt;Rules are evaluated in numerical order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Return traffic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automatically allowed for an established connection&lt;/td&gt;
&lt;td&gt;Must be explicitly allowed in the opposite direction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Inbound traffic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Controlled by inbound rules&lt;/td&gt;
&lt;td&gt;Controlled by inbound rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Outbound traffic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Controlled by outbound rules&lt;/td&gt;
&lt;td&gt;Controlled by outbound rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Default behavior&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;New SGs deny inbound and allow outbound traffic&lt;/td&gt;
&lt;td&gt;Default NACL allows all traffic; custom NACLs deny all traffic until rules are added&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Typical use&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fine-grained protection of individual resources&lt;/td&gt;
&lt;td&gt;Broad traffic control across an entire subnet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best suited for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Defining which resources or clients can communicate with a workload&lt;/td&gt;
&lt;td&gt;Subnet-wide restrictions, explicit deny rules, and additional network filtering&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;In short:&lt;/strong&gt; use &lt;strong&gt;Security Groups as the primary resource-level firewall&lt;/strong&gt;, and use &lt;strong&gt;NACLs when you need subnet-level controls or explicit deny rules&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>network</category>
      <category>cloud</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>AI Subagents orchestration are now reliable</title>
      <dc:creator>Rafael</dc:creator>
      <pubDate>Fri, 25 Sep 2026 14:26:13 +0000</pubDate>
      <link>https://dev.to/rafael_dev/ai-subagents-orchestration-are-now-reliable-2hee</link>
      <guid>https://dev.to/rafael_dev/ai-subagents-orchestration-are-now-reliable-2hee</guid>
      <description>&lt;p&gt;Since the end of 2025, I've been thinking a lot about how to improve my development workflow with AI agents. Like many developers, I started using agents in their simplest form: manually. One agent, one task, a lot of supervision, and a lot of interaction to keep the work moving in the right direction. As I became more comfortable with these tools, understanding how to communicate with them, how much context to provide, and when to intervene, the main question started to change. It was no longer just about how AI could help me write code, but how much of my development workflow I could delegate to AI without losing control or quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  My First Attempts at Agent Orchestration
&lt;/h3&gt;

&lt;p&gt;I previously wrote about my first &lt;a href="https://dev.to/rafael_dev/from-epic-to-merge-an-end-to-end-workflow-for-software-development-with-ai-agents-1ijn"&gt;orchestration design using subagents&lt;/a&gt;. The design itself was reasonably solid, even though there was still a lot to improve, but getting consistent results from it was difficult. The parent agent was not always reliable when coordinating subagents. For example, after spawning a subagent, it would sometimes continue doing unrelated work instead of waiting for the delegated task. In other cases, it would repeatedly poll the subagent for results or start working on something that had already been delegated. That created duplicated work, unnecessary context usage, and unpredictable behavior.&lt;/p&gt;

&lt;p&gt;This wasn't only a prompt-design problem. Part of the issue seemed to come from limitations in the agent harness or model behavior itself, and I even opened an issue in the &lt;a href="https://github.com/openai/codex/issues/40299" rel="noopener noreferrer"&gt;openai/codex&lt;/a&gt; repository documenting one of these cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Changed
&lt;/h3&gt;

&lt;p&gt;Recently, however, this has started to change. For my workflow, Codex subagent orchestration has become reliable enough that I can actually design development processes around it. The parent agent can delegate a well-scoped task and wait when waiting makes sense, while I can continue interacting with the main thread, inspect what the subagents are doing, and redirect the work when necessary.&lt;/p&gt;

&lt;p&gt;That may sound like a relatively small improvement, but I don't think it is. Once delegation itself becomes dependable, the problem changes. You can start thinking about which tasks should be delegated, which can run in parallel, which depend on previous results, what context each agent actually needs, and how the parent agent should integrate everything afterward. At that point, the workflow starts to look much closer to software engineering than simply asking a model to "implement this feature."&lt;/p&gt;

&lt;h3&gt;
  
  
  Planning Before Orchestration
&lt;/h3&gt;

&lt;p&gt;This is also where planning becomes much more important. The fact that an agent can spawn several subagents does not mean that it should. Before delegating anything, I try to understand the feature and break it into tasks with clear boundaries, expected outputs, relevant constraints, and known dependencies. Some tasks should run sequentially, while others can happen in parallel.&lt;/p&gt;

&lt;p&gt;One agent may investigate an unfamiliar part of the codebase, another may work on tests, another may review an implementation, and the parent agent can later combine those results into the next step. The important part is not the number of agents. It is whether the work has been decomposed correctly.&lt;/p&gt;

&lt;p&gt;Repository-level context also becomes much more valuable in this model. Good &lt;code&gt;AGENTS.md&lt;/code&gt; instructions, architecture documentation, project conventions, reusable skills, tests, strict type requirements, and other forms of persistent context give future agents a foundation they can reuse. Without that foundation, every new agent has to rediscover the project. With it, agents can enter the repository with a much better understanding of how the system works and how they are expected to behave. In practice, the quality of the orchestration depends not only on the model or the harness, but also on how well the project itself is prepared for agents.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Is Not Only About Building Faster
&lt;/h3&gt;

&lt;p&gt;Another thing I've been thinking about is how we measure the value of AI in software development. Most discussions focus heavily on speed: how quickly a feature can be built, how much code an agent can generate, or how fast something can be shipped. I don't think that is the most interesting part.&lt;/p&gt;

&lt;p&gt;Before working this way, I worked professionally at a software house where I shipped thousands of production commits. Like many teams working under real client deadlines, we constantly had to make trade-offs. A feature needed to go live, another task was already waiting, and the client needed the change. Because of that, work that we knew would improve the project could easily be postponed: more automated tests, broader integration coverage, additional edge-case validation, deeper refactoring, better documentation, or simply more polish. The problem was not that these things were unimportant. The problem was time.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Changes the Economics of Quality
&lt;/h3&gt;

&lt;p&gt;This is where I think AI changes something important. It reduces the cost of doing some engineering work that was previously expensive in terms of developer time. An agent can investigate edge cases while another works on implementation. A subagent can expand tests without forcing the parent agent to carry every implementation detail in its context. Another agent can review a change against the original requirements or inspect an unfamiliar part of the codebase before any code is changed.&lt;/p&gt;

&lt;p&gt;None of this removes the need for engineering judgment, and it does not guarantee quality, but it makes some work much cheaper to perform.&lt;/p&gt;

&lt;p&gt;That is also why I don't care if I sometimes spend hours or even days working with AI on the same feature. If the result has better architecture, stronger tests, fewer edge cases, better documentation, and a more polished implementation, then the value is not that AI helped me finish the feature in twenty minutes. The value is that AI allowed me to spend engineering effort differently. For me, AI is becoming less about building faster and more about making it practical to build with more quality.&lt;/p&gt;

&lt;p&gt;Anyone who has spent enough time developing with AI agents also knows that generating something that works is becoming relatively easy. Generating something that is consistent with the existing architecture, maintainable, properly tested, understandable by another developer, aligned with the product requirements, and free from generic AI defaults is a different problem.&lt;/p&gt;

&lt;p&gt;This is especially visible in frontend work, where agents can easily converge toward similar layouts and visual patterns without strong direction, but the same problem exists in backend development. Agents can introduce unnecessary abstractions, inconsistent naming, duplicated logic, weak boundaries, or solutions that technically work but do not really fit the architecture of the system. Better models help, but the workflow around them still matters just as much. Planning matters, context matters, task boundaries matter, and review still matters.&lt;/p&gt;

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

&lt;p&gt;I've been applying these ideas while building my public project &lt;a href="https://towelbooks.com" rel="noopener noreferrer"&gt;TowelBooks&lt;/a&gt; and while contributing to different projects through my &lt;a href="https://github.com/rafaself" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. A large amount of that work has been done with relatively low-cost models such as GPT-5.6 Luna, which is another part of this shift that I find interesting.&lt;/p&gt;

&lt;p&gt;Agentic workflows do not necessarily require using the most expensive model for every step. A stronger model can be useful for architecture, planning, difficult reasoning, or ambiguous problems, while smaller implementation, investigation, testing, and review tasks can often be delegated to cheaper models once the work has been decomposed properly. Good task decomposition can therefore improve reliability and cost efficiency at the same time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Femmh9dl92df93kmm5aqz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Femmh9dl92df93kmm5aqz.png" alt="Codex Thread" width="538" height="926"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;What interests me most about this direction is not the idea of an agent generating an entire application from one prompt. It is the possibility of building a development workflow where we can decompose engineering problems, delegate focused pieces of work, execute independent tasks in parallel, preserve context boundaries, review intermediate results, and coordinate everything through a parent agent.&lt;/p&gt;

&lt;p&gt;The developer still owns the architecture, defines the constraints, decides which trade-offs are acceptable, and remains responsible for the final result. But the amount of engineering work that can happen around those decisions is increasing quickly.&lt;/p&gt;

&lt;p&gt;You may have noticed that I've mentioned Codex a lot throughout this article. That's simply because it has become my primary AI development tool. I've been particularly impressed by how quickly the agent experience has evolved. For my workflow, combining stronger models for planning and reasoning with lower-cost models for implementation and delegated tasks has made multi-agent development much more practical.&lt;/p&gt;

&lt;p&gt;The most interesting part, though, is not any single model. It is that the surrounding tooling is finally becoming reliable enough for these workflows to move from experiments into actual software development processes.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>openai</category>
    </item>
    <item>
      <title>From Epic to Merge: An End-to-End Workflow for Software Development with AI Agents</title>
      <dc:creator>Rafael</dc:creator>
      <pubDate>Mon, 21 Sep 2026 21:55:40 +0000</pubDate>
      <link>https://dev.to/rafael_dev/from-epic-to-merge-an-end-to-end-workflow-for-software-development-with-ai-agents-1ijn</link>
      <guid>https://dev.to/rafael_dev/from-epic-to-merge-an-end-to-end-workflow-for-software-development-with-ai-agents-1ijn</guid>
      <description>&lt;p&gt;Coding agents are becoming increasingly capable of implementing individual software tasks. Give an agent a repository, a clear issue, and enough context, and it can often inspect the codebase, modify files, write tests, and produce a working implementation.&lt;/p&gt;

&lt;p&gt;The harder problem starts one level above that.&lt;/p&gt;

&lt;p&gt;What happens when we need to implement an entire feature consisting of ten related tasks? Some can run in parallel, some depend on others, some require architectural decisions, and some touch areas where autonomous changes should not be allowed.&lt;/p&gt;

&lt;p&gt;At that point, the challenge is no longer simply:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can an AI agent write the code?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The more useful question becomes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do we transform a software initiative into units of work that agents can execute, validate, review, and integrate safely?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This article proposes an end-to-end workflow for implementing an Epic using AI agents while minimizing human intervention without removing the controls required by the risk of the changes.&lt;/p&gt;

&lt;p&gt;The core architecture looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
                         ┌─────────────────────┐
                         │        Epic         │
                         │ intent + constraints│
                         └──────────┬──────────┘
                                    │
                                    ▼
                         ┌─────────────────────┐
                         │   Task dependency   │
                         │        graph        │
                         └──────────┬──────────┘
                                    │
                    ┌───────────────┴───────────────┐
                    │                               │
                    ▼                               ▼
            ┌──────────────┐                ┌──────────────┐
            │    Task A    │                │    Task B    │
            └──────┬───────┘                └──────┬───────┘
                   │                               │
                   ▼                               ▼
              ┌─────────┐                     ┌─────────┐
              │ Planner │                     │ Planner │
              └────┬────┘                     └────┬────┘
                   │                               │
                   ▼                               ▼
              ┌─────────┐                     ┌─────────┐
              │ Builder │                     │ Builder │
              └────┬────┘                     └────┬────┘
                   │                               │
                   ▼                               ▼
              ┌─────────┐                     ┌─────────┐
              │Reviewer │                     │Reviewer │
              └────┬────┘                     └────┬────┘
                   │                               │
                   └───────────────┬───────────────┘
                                   ▼
                         ┌─────────────────────┐
                         │ Epic integration PR │
                         │      + CI           │
                         └──────────┬──────────┘
                                    │
                              human approval
                                    │
                                    ▼
                                  main

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The specific tools are interchangeable. The important part is the workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Epic as the source of intent
&lt;/h2&gt;

&lt;p&gt;An Epic is useful because it gives the agents a shared description of what the system is supposed to accomplish.&lt;/p&gt;

&lt;p&gt;It should contain at least:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the objective;&lt;/li&gt;
&lt;li&gt;the problem or product context;&lt;/li&gt;
&lt;li&gt;scope and explicit non-goals;&lt;/li&gt;
&lt;li&gt;requirements;&lt;/li&gt;
&lt;li&gt;tasks or user stories;&lt;/li&gt;
&lt;li&gt;acceptance criteria;&lt;/li&gt;
&lt;li&gt;dependencies and risks;&lt;/li&gt;
&lt;li&gt;success metrics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I would avoid treating the Epic as the absolute "source of truth."&lt;/p&gt;

&lt;p&gt;It is better understood as the &lt;strong&gt;central source of intent, requirements, and constraints&lt;/strong&gt; for the initiative.&lt;/p&gt;

&lt;p&gt;The repository still contains the technical reality of the system. Existing APIs, schemas, architectural decisions, infrastructure, tests, and implementation constraints may reveal information that the Epic does not contain.&lt;/p&gt;

&lt;p&gt;This distinction becomes important once agents start making decisions.&lt;/p&gt;

&lt;p&gt;Imagine that a task only says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Add retry support to payment processing.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An agent might reasonably ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which failures are retryable?&lt;/li&gt;
&lt;li&gt;How many retries are allowed?&lt;/li&gt;
&lt;li&gt;Should retries be synchronous or asynchronous?&lt;/li&gt;
&lt;li&gt;What happens to idempotency?&lt;/li&gt;
&lt;li&gt;Can the payment provider receive the same request twice?&lt;/li&gt;
&lt;li&gt;Is retrying outside the scope of a specific payment method?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The task itself may not answer those questions.&lt;/p&gt;

&lt;p&gt;The Epic can provide the product and architectural boundaries required to answer them without duplicating the entire context in every issue.&lt;/p&gt;

&lt;p&gt;A practical implementation is to represent the Epic as a parent GitHub Issue and its tasks as sub-issues. This keeps the planning artifacts close to the code and allows issues, pull requests, commits, diagrams, files, and technical decisions to reference each other.&lt;/p&gt;




&lt;h2&gt;
  
  
  Task granularity matters more than prompt count
&lt;/h2&gt;

&lt;p&gt;One of the easiest mistakes when building agentic development workflows is to hand a very large objective directly to a coding agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Implement the entire billing Epic.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A sufficiently capable model may still make progress, but the execution becomes difficult to reason about.&lt;/p&gt;

&lt;p&gt;The agent must simultaneously:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;discover the architecture;&lt;/li&gt;
&lt;li&gt;interpret requirements;&lt;/li&gt;
&lt;li&gt;make design decisions;&lt;/li&gt;
&lt;li&gt;modify multiple domains;&lt;/li&gt;
&lt;li&gt;keep dependencies consistent;&lt;/li&gt;
&lt;li&gt;validate behavior;&lt;/li&gt;
&lt;li&gt;understand what is in and out of scope.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem is not simply context-window size.&lt;/p&gt;

&lt;p&gt;The problem is the number of decisions that must remain coherent throughout the execution.&lt;/p&gt;

&lt;p&gt;A better workflow reduces the complexity of each execution.&lt;/p&gt;

&lt;h3&gt;
  
  
  When is a task granular enough?
&lt;/h3&gt;

&lt;p&gt;A useful rule is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A task is sufficiently granular when it represents one coherent delivery, can be implemented and validated independently, and can produce a pull request that can be understood, tested, and reverted without relying on undeclared changes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Task size should therefore not be measured primarily by lines of code or number of files.&lt;/p&gt;

&lt;p&gt;The more important property is &lt;strong&gt;cohesion&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, adding a field to an API may require modifying:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;database schema
    ↓
domain entity
    ↓
service
    ↓
API endpoint
    ↓
tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That can still be one coherent task.&lt;/p&gt;

&lt;p&gt;Several layers are affected, but they all implement the same vertical capability.&lt;/p&gt;

&lt;p&gt;By contrast, a change touching only three files may still be too broad if it combines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;authentication
+ billing rules
+ event processing
+ infrastructure changes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The useful questions are therefore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the task have one observable result?&lt;/li&gt;
&lt;li&gt;Does it represent one coherent capability?&lt;/li&gt;
&lt;li&gt;Can it be validated independently?&lt;/li&gt;
&lt;li&gt;Are major architectural decisions already resolved?&lt;/li&gt;
&lt;li&gt;Can the diff be reviewed as one logical unit?&lt;/li&gt;
&lt;li&gt;Can the change be reverted independently?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last question is particularly useful:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can a reviewer understand and validate this diff as a single logical change?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is no, the task probably needs further decomposition.&lt;/p&gt;




&lt;h2&gt;
  
  
  Separate investigation from implementation
&lt;/h2&gt;

&lt;p&gt;Tasks become especially dangerous when uncertainty and implementation are mixed together.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Choose an asynchronous processing architecture and implement it.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This contains at least two fundamentally different types of work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;deciding what architecture should exist;&lt;/li&gt;
&lt;li&gt;implementing that architecture.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A better decomposition could be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Task 1 — Investigate asynchronous processing alternatives

Task 2 — Record the architectural decision

Task 3 — Implement the event producer

Task 4 — Implement the event consumer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first tasks reduce uncertainty.&lt;/p&gt;

&lt;p&gt;The later tasks execute against a decision that already exists.&lt;/p&gt;

&lt;p&gt;This distinction also makes agent behavior easier to control. We can allow an agent to investigate broadly without implicitly granting it permission to modify the architecture.&lt;/p&gt;




&lt;h2&gt;
  
  
  A readiness check before implementation
&lt;/h2&gt;

&lt;p&gt;Before a task reaches a Builder, the workflow should verify that it is actually ready to be implemented.&lt;/p&gt;

&lt;p&gt;A practical checklist is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] There is one clearly defined outcome.&lt;/li&gt;
&lt;li&gt;[ ] Scope and non-goals are explicit.&lt;/li&gt;
&lt;li&gt;[ ] Acceptance criteria are verifiable.&lt;/li&gt;
&lt;li&gt;[ ] Dependencies are declared.&lt;/li&gt;
&lt;li&gt;[ ] No major architectural decision remains unresolved.&lt;/li&gt;
&lt;li&gt;[ ] The change represents a coherent capability.&lt;/li&gt;
&lt;li&gt;[ ] There is an objective validation strategy.&lt;/li&gt;
&lt;li&gt;[ ] The change can produce an independent pull request.&lt;/li&gt;
&lt;li&gt;[ ] The change can be reverted without removing unrelated work.&lt;/li&gt;
&lt;li&gt;[ ] The expected diff is reasonably bounded or its size is justified.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These do not need to become rigid numerical rules.&lt;/p&gt;

&lt;p&gt;A 2,000-line generated schema migration may be simpler than a 100-line authentication change.&lt;/p&gt;

&lt;p&gt;Cohesion, independence, and verifiability matter more than raw size.&lt;/p&gt;




&lt;h2&gt;
  
  
  One task, one isolated execution environment
&lt;/h2&gt;

&lt;p&gt;Once tasks can run concurrently, filesystem isolation becomes necessary.&lt;/p&gt;

&lt;p&gt;A simple strategy is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Epic
│
├── integration/epic-payments
│
├── task/payment-retry
│   └── worktree A
│
├── task/payment-webhook
│   └── worktree B
│
└── task/payment-events
    └── worktree C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each Builder receives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;its own Git branch;&lt;/li&gt;
&lt;li&gt;its own Git worktree or container;&lt;/li&gt;
&lt;li&gt;the context package for the current task;&lt;/li&gt;
&lt;li&gt;the relevant validation commands.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This prevents two agents from directly modifying the same working directory.&lt;/p&gt;

&lt;p&gt;It does &lt;strong&gt;not&lt;/strong&gt;, however, eliminate integration conflicts.&lt;/p&gt;

&lt;p&gt;Two isolated agents can still independently modify the same API, data model, or subsystem. Their worktrees are isolated operationally, but their changes may conflict semantically when integrated.&lt;/p&gt;

&lt;p&gt;The orchestrator must therefore understand task dependencies and integration order.&lt;/p&gt;




&lt;h2&gt;
  
  
  Model task dependencies explicitly
&lt;/h2&gt;

&lt;p&gt;An Epic should not be treated as a flat task list.&lt;/p&gt;

&lt;p&gt;It is better represented as a dependency graph.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 ┌───────────────┐
                 │ Add DB schema │
                 └───────┬───────┘
                         │
               ┌─────────┴─────────┐
               ▼                   ▼
      ┌────────────────┐   ┌────────────────┐
      │ Write producer │   │ Create API     │
      └───────┬────────┘   └───────┬────────┘
              │                    │
              ▼                    │
      ┌────────────────┐           │
      │ Write consumer │           │
      └───────┬────────┘           │
              └──────────┬─────────┘
                         ▼
                ┌────────────────┐
                │ Integration    │
                │ validation     │
                └────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A task can then have explicit metadata such as:&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;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;payment-consumer&lt;/span&gt;
&lt;span class="na"&gt;blocked_by&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;payment-schema&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;payment-producer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The orchestrator can execute independent nodes concurrently while waiting for their dependencies.&lt;/p&gt;

&lt;p&gt;This is significantly safer than telling several agents to work through the Epic and hoping they discover the correct order themselves.&lt;/p&gt;




&lt;h2&gt;
  
  
  Planner, Builder, and Reviewer
&lt;/h2&gt;

&lt;p&gt;The workflow uses three main roles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Planner
&lt;/h3&gt;

&lt;p&gt;The Planner investigates before implementation.&lt;/p&gt;

&lt;p&gt;Its responsibilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;inspecting the relevant codebase;&lt;/li&gt;
&lt;li&gt;identifying affected components;&lt;/li&gt;
&lt;li&gt;checking dependencies;&lt;/li&gt;
&lt;li&gt;identifying risks;&lt;/li&gt;
&lt;li&gt;proposing an implementation approach;&lt;/li&gt;
&lt;li&gt;defining validation steps;&lt;/li&gt;
&lt;li&gt;detecting whether the task should be split.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Planner should not modify production files during this phase.&lt;/p&gt;

&lt;p&gt;Its output should be an execution plan, not an implementation.&lt;/p&gt;

&lt;p&gt;A typical result might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Affected modules:
- payments/service.ts
- payments/repository.ts
- payments/service.test.ts

Implementation:
1. Add retry classification for transient provider errors.
2. Add bounded exponential retry behavior.
3. Preserve idempotency key across attempts.
4. Add tests for retryable and non-retryable failures.

Validation:
- unit test suite
- payment integration tests
- lint
- typecheck

Risk:
- ensure declined payments are never retried
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That output becomes part of the Builder's context.&lt;/p&gt;

&lt;h3&gt;
  
  
  Builder
&lt;/h3&gt;

&lt;p&gt;The Builder executes the approved task.&lt;/p&gt;

&lt;p&gt;Its responsibilities are intentionally narrower:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;implement the planned change;&lt;/li&gt;
&lt;li&gt;update or create tests;&lt;/li&gt;
&lt;li&gt;run the required validations;&lt;/li&gt;
&lt;li&gt;commit the changes;&lt;/li&gt;
&lt;li&gt;open or update the pull request.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Builder should not silently redefine acceptance criteria or expand scope because it discovered something interesting during implementation.&lt;/p&gt;

&lt;p&gt;If implementation reveals a significant architectural issue, the correct action is usually to escalate the finding back to the orchestrator.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reviewer
&lt;/h3&gt;

&lt;p&gt;The Reviewer evaluates the result independently.&lt;/p&gt;

&lt;p&gt;It should inspect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the actual diff;&lt;/li&gt;
&lt;li&gt;the acceptance criteria;&lt;/li&gt;
&lt;li&gt;tests;&lt;/li&gt;
&lt;li&gt;validation output;&lt;/li&gt;
&lt;li&gt;architectural constraints;&lt;/li&gt;
&lt;li&gt;possible regressions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The review should be based on the expected behavior, not merely on the Builder's explanation of what it implemented.&lt;/p&gt;

&lt;p&gt;That distinction matters because the Builder and Reviewer may otherwise share the same incorrect assumption.&lt;/p&gt;

&lt;p&gt;The Reviewer should return concrete findings such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BLOCKING

Retry logic also retries PaymentDeclinedError.

Acceptance criterion:
Only transient provider failures may be retried.

payments/service.ts:87
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The implementation doesn't look quite right.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Objective findings make automated correction loops possible.&lt;/p&gt;




&lt;h2&gt;
  
  
  Internal and external orchestration
&lt;/h2&gt;

&lt;p&gt;There are two broad ways to coordinate the agents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Internal orchestration
&lt;/h3&gt;

&lt;p&gt;A primary agent delegates work through a native multi-agent runtime.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;main agent
    │
    ├── planner agent
    ├── builder agent
    └── reviewer agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The runtime manages the child executions and returns their results to the parent.&lt;/p&gt;

&lt;p&gt;This is useful when delegation is closely tied to the reasoning process of the primary agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  External orchestration
&lt;/h3&gt;

&lt;p&gt;A separate process controls independent agent executions.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;orchestrator
    │
    ├── agent process -- task A
    ├── agent process -- task B
    └── agent process -- review A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The executions communicate through structured output, files, Git, APIs, or another durable mechanism.&lt;/p&gt;

&lt;p&gt;External orchestration is particularly useful when we need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deterministic workflows;&lt;/li&gt;
&lt;li&gt;separate worktrees or containers;&lt;/li&gt;
&lt;li&gt;explicit concurrency;&lt;/li&gt;
&lt;li&gt;retries;&lt;/li&gt;
&lt;li&gt;timeouts;&lt;/li&gt;
&lt;li&gt;task queues;&lt;/li&gt;
&lt;li&gt;persistent execution state;&lt;/li&gt;
&lt;li&gt;provider-independent agents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The architecture described in this article favors external orchestration for the main workflow while still allowing individual agents to use internal subagents when useful.&lt;/p&gt;




&lt;h2&gt;
  
  
  Give each task only the context it needs
&lt;/h2&gt;

&lt;p&gt;The Epic contains global information.&lt;/p&gt;

&lt;p&gt;That does not mean every agent should receive the entire Epic, every previous conversation, and every implementation log.&lt;/p&gt;

&lt;p&gt;Instead, the orchestrator should build a &lt;strong&gt;task context package&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example:&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;epic&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;objective&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Add asynchronous invoice processing&lt;/span&gt;
  &lt;span class="na"&gt;constraints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;existing synchronous API must remain compatible&lt;/span&gt;

&lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;invoice-event-producer&lt;/span&gt;
  &lt;span class="na"&gt;objective&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish an event after invoice creation&lt;/span&gt;

&lt;span class="na"&gt;acceptance_criteria&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;exactly one event is emitted after a successful transaction&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;failed transactions must not emit events&lt;/span&gt;

&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;completed&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;invoice-event-schema&lt;/span&gt;

&lt;span class="na"&gt;architecture&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ADR-014-event-bus.md&lt;/span&gt;

&lt;span class="na"&gt;relevant_files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/invoices/service.ts&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/events/publisher.ts&lt;/span&gt;

&lt;span class="na"&gt;validation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm test -- invoices&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm run typecheck&lt;/span&gt;

&lt;span class="na"&gt;instructions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;AGENTS.md&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pipeline becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Epic
  ↓
context selection
  ↓
task-specific context
  ↓
isolated execution
  ↓
validated result
  ↓
Epic integration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Long context windows are useful, but they should be treated as available capacity rather than a target to fill.&lt;/p&gt;

&lt;p&gt;More context is not automatically better context.&lt;/p&gt;

&lt;p&gt;Excessive context can introduce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;obsolete information;&lt;/li&gt;
&lt;li&gt;conflicting instructions;&lt;/li&gt;
&lt;li&gt;irrelevant implementation details;&lt;/li&gt;
&lt;li&gt;old architectural assumptions;&lt;/li&gt;
&lt;li&gt;competing objectives.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Context engineering is therefore part of orchestration.&lt;/p&gt;

&lt;p&gt;The question is not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How much information can the model receive?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What is the minimum sufficient context required to make this decision correctly?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Define autonomy as a risk policy
&lt;/h2&gt;

&lt;p&gt;Reducing human intervention does not mean giving agents unrestricted permissions.&lt;/p&gt;

&lt;p&gt;The workflow should define which actions are safe to perform automatically and which require approval.&lt;/p&gt;

&lt;p&gt;A possible policy is:&lt;/p&gt;

&lt;h3&gt;
  
  
  Autonomous
&lt;/h3&gt;

&lt;p&gt;Agents may perform these operations inside their isolated task environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;edit application code;&lt;/li&gt;
&lt;li&gt;add or update tests;&lt;/li&gt;
&lt;li&gt;run tests, linters, and static analysis;&lt;/li&gt;
&lt;li&gt;create commits;&lt;/li&gt;
&lt;li&gt;open pull requests;&lt;/li&gt;
&lt;li&gt;apply Reviewer-requested fixes that remain within the approved scope.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Autonomous with additional validation
&lt;/h3&gt;

&lt;p&gt;Changes in this category may proceed automatically only when specific validation rules succeed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dependency updates;&lt;/li&gt;
&lt;li&gt;non-destructive database migrations;&lt;/li&gt;
&lt;li&gt;API contract changes;&lt;/li&gt;
&lt;li&gt;shared configuration changes;&lt;/li&gt;
&lt;li&gt;changes affecting multiple domains or services.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Human approval required
&lt;/h3&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;production deployments;&lt;/li&gt;
&lt;li&gt;destructive migrations;&lt;/li&gt;
&lt;li&gt;secret access or modification;&lt;/li&gt;
&lt;li&gt;infrastructure mutations;&lt;/li&gt;
&lt;li&gt;authentication or authorization changes;&lt;/li&gt;
&lt;li&gt;billing operations;&lt;/li&gt;
&lt;li&gt;irreversible data transformations;&lt;/li&gt;
&lt;li&gt;final integration into the main branch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These categories should not be universal constants.&lt;/p&gt;

&lt;p&gt;A migration adding a nullable column may be routine in one system and dangerous in another with billions of rows.&lt;/p&gt;

&lt;p&gt;The correct abstraction is therefore not a hardcoded list of actions.&lt;/p&gt;

&lt;p&gt;It is a &lt;strong&gt;risk policy&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The complete implementation cycle
&lt;/h2&gt;

&lt;p&gt;We can now put the pieces together.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create the Epic
&lt;/h3&gt;

&lt;p&gt;The human or product process defines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;objective
problem
scope
non-goals
requirements
acceptance criteria
risks
success metrics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this stage, the emphasis is on &lt;strong&gt;what needs to be achieved&lt;/strong&gt;, not exactly how every part will be implemented.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Decompose the Epic
&lt;/h3&gt;

&lt;p&gt;A planning process converts the Epic into tasks.&lt;/p&gt;

&lt;p&gt;Each task is checked for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cohesion
independence
testability
reversibility
architectural uncertainty
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If major design uncertainty exists, investigation tasks are created before implementation tasks.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Build the dependency graph
&lt;/h3&gt;

&lt;p&gt;Dependencies between tasks are declared explicitly.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A ──► C ──► E
│
└──► D ──► E

B ───────► E
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tasks &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; can begin immediately.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;C&lt;/code&gt; and &lt;code&gt;D&lt;/code&gt; wait for &lt;code&gt;A&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;E&lt;/code&gt; waits for all upstream work.&lt;/p&gt;

&lt;p&gt;The orchestrator now has enough information to determine safe parallelism.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Create the Epic integration branch
&lt;/h3&gt;

&lt;p&gt;A branch is created from the current target branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;main
  │
  └── epic/invoice-processing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Individual task branches are based on an appropriate integration state.&lt;/p&gt;

&lt;p&gt;Long-running Epics should periodically synchronize with the target branch to avoid allowing the integration branch to drift too far from &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Build a context package for the next task
&lt;/h3&gt;

&lt;p&gt;The orchestrator selects only the information required for the task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Epic summary
+ task description
+ acceptance criteria
+ architecture decisions
+ completed dependencies
+ relevant files
+ repository instructions
+ validation commands
+ risk constraints
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This becomes the Planner's initial input.&lt;/p&gt;




&lt;h3&gt;
  
  
  6. Run the Planner
&lt;/h3&gt;

&lt;p&gt;The Planner inspects the repository and produces a plan.&lt;/p&gt;

&lt;p&gt;Possible outcomes are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;READY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NEEDS_SPLIT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BLOCKED_BY_ARCHITECTURE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BLOCKED_BY_DEPENDENCY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only &lt;code&gt;READY&lt;/code&gt; tasks proceed automatically.&lt;/p&gt;

&lt;p&gt;This step acts as an important boundary between project planning and code generation.&lt;/p&gt;




&lt;h3&gt;
  
  
  7. Create an isolated Builder environment
&lt;/h3&gt;

&lt;p&gt;The orchestrator creates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;task branch
+
Git worktree or container
+
task-specific context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;worktrees/
├── payment-retry/
├── payment-webhook/
└── invoice-events/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Independent Builders can now execute concurrently without sharing the same filesystem.&lt;/p&gt;




&lt;h3&gt;
  
  
  8. Execute the Builder
&lt;/h3&gt;

&lt;p&gt;The Builder receives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;task context
+
Planner result
+
repository instructions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It implements the change and runs the required validations.&lt;/p&gt;

&lt;p&gt;The result should include structured information such as:&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;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;completed&lt;/span&gt;

&lt;span class="na"&gt;commit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;a814ed3&lt;/span&gt;

&lt;span class="na"&gt;validation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;unit_tests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;passed&lt;/span&gt;
  &lt;span class="na"&gt;integration_tests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;passed&lt;/span&gt;
  &lt;span class="na"&gt;lint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;passed&lt;/span&gt;
  &lt;span class="na"&gt;typecheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;passed&lt;/span&gt;

&lt;span class="na"&gt;files_changed&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/payments/service.ts&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/payments/service.test.ts&lt;/span&gt;

&lt;span class="na"&gt;notes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;preserved existing idempotency behavior&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact schema is not important.&lt;/p&gt;

&lt;p&gt;Structured output is.&lt;/p&gt;

&lt;p&gt;An orchestrator should not need to parse an essay to determine whether tests passed.&lt;/p&gt;




&lt;h3&gt;
  
  
  9. Open the task pull request
&lt;/h3&gt;

&lt;p&gt;Each task produces a pull request targeting the Epic integration branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;task/payment-retry
        │
        ▼
epic/payment-improvements
        │
        ▼
main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The task PR should remain independently reviewable.&lt;/p&gt;

&lt;p&gt;CI runs again outside the Builder's local environment.&lt;/p&gt;

&lt;p&gt;This gives us two independent validation layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Builder validation
        +
CI validation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  10. Run the Reviewer
&lt;/h3&gt;

&lt;p&gt;The Reviewer receives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;task requirements
+
acceptance criteria
+
diff
+
test results
+
relevant architecture constraints
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returns structured findings.&lt;/p&gt;

&lt;p&gt;For example:&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;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;changes_requested&lt;/span&gt;

&lt;span class="na"&gt;findings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;blocking&lt;/span&gt;
    &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;src/payments/service.ts&lt;/span&gt;
    &lt;span class="na"&gt;line&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;87&lt;/span&gt;
    &lt;span class="na"&gt;reason&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;declined payments are being retried&lt;/span&gt;
    &lt;span class="na"&gt;criterion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;only transient failures may be retried&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or:&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;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;approved&lt;/span&gt;
&lt;span class="na"&gt;findings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  11. Run the correction loop
&lt;/h3&gt;

&lt;p&gt;If the Reviewer finds a blocking problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reviewer
   ↓
Builder
   ↓
validation
   ↓
Reviewer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The loop continues within predefined limits.&lt;/p&gt;

&lt;p&gt;An important operational detail is that retries should not be infinite.&lt;/p&gt;

&lt;p&gt;After a certain number of unsuccessful correction cycles, the task should be escalated.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;attempt 1 → failed review
attempt 2 → failed review
attempt 3 → failed review
               ↓
        human escalation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeated failure is itself useful information. It may indicate that the task is poorly specified, incorrectly decomposed, or hiding an unresolved architectural problem.&lt;/p&gt;




&lt;h3&gt;
  
  
  12. Merge into the Epic integration branch
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Builder validation = passed
CI = passed
Reviewer = approved
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the task can be merged into the Epic branch according to the project's autonomy policy.&lt;/p&gt;

&lt;p&gt;This may unblock downstream tasks in the dependency graph.&lt;/p&gt;

&lt;p&gt;The orchestrator then schedules the newly available work.&lt;/p&gt;




&lt;h3&gt;
  
  
  13. Run Epic-level validation
&lt;/h3&gt;

&lt;p&gt;Passing every task independently does not prove that the Epic works as a whole.&lt;/p&gt;

&lt;p&gt;Once all required tasks are integrated, the workflow runs broader validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;full test suite
integration tests
end-to-end tests
contract tests
migration checks
security checks
performance checks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact set depends on the project.&lt;/p&gt;

&lt;p&gt;This stage catches problems that task-level validation cannot detect.&lt;/p&gt;

&lt;p&gt;For example, two individually correct tasks may still implement incompatible assumptions.&lt;/p&gt;




&lt;h3&gt;
  
  
  14. Validate the Epic acceptance criteria
&lt;/h3&gt;

&lt;p&gt;The final Reviewer evaluates the integrated result against the original Epic rather than individual tasks.&lt;/p&gt;

&lt;p&gt;The question changes from:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Did we implement Task 7 correctly?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does the system now satisfy the outcome defined by the Epic?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This distinction is important.&lt;/p&gt;

&lt;p&gt;A workflow can successfully complete every task and still fail to achieve the intended product behavior if the decomposition itself was incomplete.&lt;/p&gt;




&lt;h3&gt;
  
  
  15. Human approval and final merge
&lt;/h3&gt;

&lt;p&gt;If the final integration satisfies the Epic criteria, the workflow produces an Epic pull request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;epic/payment-improvements
        │
        ▼
       main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an appropriate place for a human approval gate.&lt;/p&gt;

&lt;p&gt;The human is no longer expected to manually implement or review every small code change.&lt;/p&gt;

&lt;p&gt;Instead, human attention is concentrated where it has the highest value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;requirements
architecture
risk
exceptions
final integration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a more realistic interpretation of "human-in-the-loop" development than requiring a person to supervise every tool call made by an agent.&lt;/p&gt;




&lt;h2&gt;
  
  
  Choosing models by role
&lt;/h2&gt;

&lt;p&gt;There is no requirement that every stage use the same model.&lt;/p&gt;

&lt;p&gt;Different roles have different computational requirements.&lt;/p&gt;

&lt;p&gt;The Planner may benefit from stronger reasoning because it needs to understand architecture and dependencies.&lt;/p&gt;

&lt;p&gt;The Reviewer may need similar capability because it must identify subtle inconsistencies.&lt;/p&gt;

&lt;p&gt;A Builder executing a very constrained change may not require the same model.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Orchestrator ── high reasoning capability

Planner      ── high reasoning capability

Reviewer     ── high reasoning capability

Builder      ── selected according to task complexity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also creates room for provider-independent workflows.&lt;/p&gt;

&lt;p&gt;An orchestration layer could use OpenCode, Codex, Claude, or other coding-agent runtimes without fundamentally changing the architecture described here.&lt;/p&gt;

&lt;p&gt;The model becomes an execution component rather than the workflow itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Measure the workflow
&lt;/h2&gt;

&lt;p&gt;Once the process is structured, it can be measured.&lt;/p&gt;

&lt;p&gt;Useful metrics include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tokens consumed per task;&lt;/li&gt;
&lt;li&gt;tokens consumed per agent role;&lt;/li&gt;
&lt;li&gt;execution time per task;&lt;/li&gt;
&lt;li&gt;total Epic execution time;&lt;/li&gt;
&lt;li&gt;number of retries;&lt;/li&gt;
&lt;li&gt;number of failed Builder attempts;&lt;/li&gt;
&lt;li&gt;Reviewer findings;&lt;/li&gt;
&lt;li&gt;CI failures;&lt;/li&gt;
&lt;li&gt;tasks completed without human intervention;&lt;/li&gt;
&lt;li&gt;human escalations;&lt;/li&gt;
&lt;li&gt;cost per pull request;&lt;/li&gt;
&lt;li&gt;cost per Epic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These metrics should not be used only to minimize token usage.&lt;/p&gt;

&lt;p&gt;They can help answer more useful questions.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does adding a Planner reduce failed implementations?&lt;/p&gt;

&lt;p&gt;Does a stronger Reviewer reduce integration defects?&lt;/p&gt;

&lt;p&gt;Are certain task types consistently escalated?&lt;/p&gt;

&lt;p&gt;At what task size does autonomous completion become unreliable?&lt;/p&gt;

&lt;p&gt;Is parallel execution actually reducing lead time?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At that point, decisions about agents and models can be based on workflow performance rather than intuition.&lt;/p&gt;




&lt;h2&gt;
  
  
  The workflow as a state machine
&lt;/h2&gt;

&lt;p&gt;Once everything above is explicit, the orchestration problem becomes surprisingly mechanical.&lt;/p&gt;

&lt;p&gt;A task can move through states such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PENDING
   ↓
READY
   ↓
PLANNING
   ↓
BUILDING
   ↓
VALIDATING
   ↓
REVIEWING
   │
   ├── changes requested ──► BUILDING
   │
   ├── blocked ────────────► ESCALATED
   │
   └── approved
           ↓
        MERGED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Epic has its own lifecycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PLANNING
   ↓
EXECUTING
   ↓
INTEGRATING
   ↓
VALIDATING
   ↓
AWAITING_APPROVAL
   ↓
COMPLETED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the point where AI-assisted software development starts looking less like a chat interface and more like a distributed software-delivery system.&lt;/p&gt;

&lt;p&gt;And that is probably the more useful abstraction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;The most interesting problem in AI-assisted software development is increasingly not code generation itself.&lt;/p&gt;

&lt;p&gt;It is orchestration.&lt;/p&gt;

&lt;p&gt;An autonomous development workflow needs to answer questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What should the agent work on?&lt;/li&gt;
&lt;li&gt;What context should it receive?&lt;/li&gt;
&lt;li&gt;Which work can happen in parallel?&lt;/li&gt;
&lt;li&gt;Which decisions have already been made?&lt;/li&gt;
&lt;li&gt;How should the implementation be validated?&lt;/li&gt;
&lt;li&gt;Who reviews the result?&lt;/li&gt;
&lt;li&gt;What happens when the Reviewer disagrees?&lt;/li&gt;
&lt;li&gt;Which actions can happen automatically?&lt;/li&gt;
&lt;li&gt;Where is human approval required?&lt;/li&gt;
&lt;li&gt;How do independent changes become one coherent feature?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Better models will make individual executions more capable.&lt;/p&gt;

&lt;p&gt;They will not eliminate the need to answer those questions.&lt;/p&gt;

&lt;p&gt;A robust agentic development workflow therefore should not be designed around the assumption that a sufficiently powerful model can receive an entire project and simply "figure it out."&lt;/p&gt;

&lt;p&gt;Instead, the system should reduce ambiguity before execution.&lt;/p&gt;

&lt;p&gt;That means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clear intent
+ coherent tasks
+ explicit dependencies
+ minimal relevant context
+ isolated execution
+ objective validation
+ independent review
+ risk-based autonomy
+ controlled integration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The objective is not to remove humans from software engineering.&lt;/p&gt;

&lt;p&gt;It is to move human attention away from supervising routine implementation and toward the decisions where judgment, product context, architecture, and risk actually matter.&lt;/p&gt;

&lt;p&gt;Once those boundaries are explicit, AI agents stop being isolated coding assistants and become components of a software delivery pipeline.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>automation</category>
      <category>softwaredevelopment</category>
    </item>
  </channel>
</rss>
