Files
docs/standards/lib/01_build_recipe/index.html

999 lines
39 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="The rules and library registry of the standardized application blueprint.">
<link rel="prev" href="..">
<link rel="next" href="../02_layering_rules/">
<link rel="icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.23">
<title>Build Recipe - Aetos Standards — Reference</title>
<link rel="stylesheet" href="../assets/stylesheets/main.84d31ad4.min.css">
<link rel="stylesheet" href="../assets/stylesheets/palette.06af60db.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Inter";--md-code-font:"JetBrains Mono"}</style>
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr" data-md-color-scheme="slate" data-md-color-primary="deep-purple" data-md-color-accent="cyan">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#build-recipe" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="Aetos Standards — Reference" class="md-header__button md-logo" aria-label="Aetos Standards — Reference" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
Aetos Standards — Reference
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Build Recipe
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="deep-purple" data-md-color-accent="cyan" aria-hidden="true" type="radio" name="__palette" id="__palette_0">
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"/></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="Aetos Standards — Reference" class="md-nav__button md-logo" aria-label="Aetos Standards — Reference" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
Aetos Standards — Reference
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Build Recipe
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Build Recipe
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#summary" class="md-nav__link">
<span class="md-ellipsis">
Summary
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#bootstrap" class="md-nav__link">
<span class="md-ellipsis">
🚀 Bootstrap
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#agent-prompt-copyable" class="md-nav__link">
<span class="md-ellipsis">
📋 Agent prompt (copyable)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#where-the-steps-land" class="md-nav__link">
<span class="md-ellipsis">
🧭 Where the steps land
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#definition-of-done" class="md-nav__link">
<span class="md-ellipsis">
⚠️ Definition of done
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#related" class="md-nav__link">
<span class="md-ellipsis">
Related
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../02_layering_rules/" class="md-nav__link">
<span class="md-ellipsis">
Layering Rules
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../03_composition_root/" class="md-nav__link">
<span class="md-ellipsis">
Composition Root
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../04_spec_first_routing/" class="md-nav__link">
<span class="md-ellipsis">
Spec-First Routing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../05_crud_template/" class="md-nav__link">
<span class="md-ellipsis">
CRUD Template
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../06_pipeline_scaffold/" class="md-nav__link">
<span class="md-ellipsis">
Pipeline Scaffold
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../07_worker_and_progress/" class="md-nav__link">
<span class="md-ellipsis">
Worker & Progress
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../08_human_in_loop/" class="md-nav__link">
<span class="md-ellipsis">
Human-in-the-Loop
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../09_infra_adaptors/" class="md-nav__link">
<span class="md-ellipsis">
Infra Adapters
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../12_genericity_matrix/" class="md-nav__link">
<span class="md-ellipsis">
Genericity Matrix
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../13_library_registry/" class="md-nav__link">
<span class="md-ellipsis">
Library Registry
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#summary" class="md-nav__link">
<span class="md-ellipsis">
Summary
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#bootstrap" class="md-nav__link">
<span class="md-ellipsis">
🚀 Bootstrap
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#agent-prompt-copyable" class="md-nav__link">
<span class="md-ellipsis">
📋 Agent prompt (copyable)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#where-the-steps-land" class="md-nav__link">
<span class="md-ellipsis">
🧭 Where the steps land
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#definition-of-done" class="md-nav__link">
<span class="md-ellipsis">
⚠️ Definition of done
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#related" class="md-nav__link">
<span class="md-ellipsis">
Related
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="build-recipe">Build Recipe</h1>
<h2 id="summary">Summary</h2>
<p>The ordered, deterministic checklist for generating a new application of the
standard shape. Every step is fixed; only the resource model (step 2) and the
pipeline family (step 7) need app-specific authoring.</p>
<p>This page is served by the <code>standards</code> MCP as <code>doc://modules/build_recipe</code>. The
<code>start_app</code> prompt on that server collects the two axes and hands off here; pull
exact files with <code>get_app_component</code>.</p>
<hr />
<h2 id="bootstrap">🚀 Bootstrap</h2>
<p>From the standards docs checkout:</p>
<div class="language-bash highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-1">1</a></span>
<span class="normal"><a href="#__codelineno-0-2">2</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1"></a>cp<span class="w"> </span>-r<span class="w"> </span>&lt;docs&gt;/standards/src/templates/app<span class="w"> </span>apps/&lt;your-app&gt;
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="nb">cd</span><span class="w"> </span>apps/&lt;your-app&gt;
</span></code></pre></div></td></tr></table></div>
<p>Install the internal libraries — editable local checkouts (preferred in
development) or the private index (CI / fresh machines). Credentials are
environment-only; never commit them.</p>
<div class="language-bash highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-1-1">1</a></span>
<span class="normal"><a href="#__codelineno-1-2">2</a></span>
<span class="normal"><a href="#__codelineno-1-3">3</a></span>
<span class="normal"><a href="#__codelineno-1-4">4</a></span>
<span class="normal"><a href="#__codelineno-1-5">5</a></span>
<span class="normal"><a href="#__codelineno-1-6">6</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-1-1"><a id="__codelineno-1-1" name="__codelineno-1-1"></a><span class="c1"># local checkouts</span>
</span><span id="__span-1-2"><a id="__codelineno-1-2" name="__codelineno-1-2"></a>pip<span class="w"> </span>install<span class="w"> </span>-e<span class="w"> </span>../aetos/openapi-first<span class="w"> </span>-e<span class="w"> </span>../aetos/mongo-ops<span class="w"> </span>-e<span class="w"> </span>../aetos/hexa<span class="w"> </span><span class="se">\</span>
</span><span id="__span-1-3"><a id="__codelineno-1-3" name="__codelineno-1-3"></a><span class="w"> </span>-e<span class="w"> </span>../aetos/dagpipe<span class="w"> </span>-e<span class="w"> </span>../aetos/doc-forge
</span><span id="__span-1-4"><a id="__codelineno-1-4" name="__codelineno-1-4"></a><span class="c1"># private index</span>
</span><span id="__span-1-5"><a id="__codelineno-1-5" name="__codelineno-1-5"></a>pip<span class="w"> </span>install<span class="w"> </span>--extra-index-url<span class="w"> </span><span class="se">\</span>
</span><span id="__span-1-6"><a id="__codelineno-1-6" name="__codelineno-1-6"></a><span class="w"> </span><span class="s2">&quot;https://</span><span class="nv">$PIP_REGISTRY_USERNAME</span><span class="s2">:</span><span class="nv">$PIP_REGISTRY_PASSWORD</span><span class="s2">@pip.aetoskia.com/simple&quot;</span><span class="w"> </span>.
</span></code></pre></div></td></tr></table></div>
<hr />
<h2 id="agent-prompt-copyable">📋 Agent prompt (copyable)</h2>
<div class="language-markdown highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-2-1"> 1</a></span>
<span class="normal"><a href="#__codelineno-2-2"> 2</a></span>
<span class="normal"><a href="#__codelineno-2-3"> 3</a></span>
<span class="normal"><a href="#__codelineno-2-4"> 4</a></span>
<span class="normal"><a href="#__codelineno-2-5"> 5</a></span>
<span class="normal"><a href="#__codelineno-2-6"> 6</a></span>
<span class="normal"><a href="#__codelineno-2-7"> 7</a></span>
<span class="normal"><a href="#__codelineno-2-8"> 8</a></span>
<span class="normal"><a href="#__codelineno-2-9"> 9</a></span>
<span class="normal"><a href="#__codelineno-2-10">10</a></span>
<span class="normal"><a href="#__codelineno-2-11">11</a></span>
<span class="normal"><a href="#__codelineno-2-12">12</a></span>
<span class="normal"><a href="#__codelineno-2-13">13</a></span>
<span class="normal"><a href="#__codelineno-2-14">14</a></span>
<span class="normal"><a href="#__codelineno-2-15">15</a></span>
<span class="normal"><a href="#__codelineno-2-16">16</a></span>
<span class="normal"><a href="#__codelineno-2-17">17</a></span>
<span class="normal"><a href="#__codelineno-2-18">18</a></span>
<span class="normal"><a href="#__codelineno-2-19">19</a></span>
<span class="normal"><a href="#__codelineno-2-20">20</a></span>
<span class="normal"><a href="#__codelineno-2-21">21</a></span>
<span class="normal"><a href="#__codelineno-2-22">22</a></span>
<span class="normal"><a href="#__codelineno-2-23">23</a></span>
<span class="normal"><a href="#__codelineno-2-24">24</a></span>
<span class="normal"><a href="#__codelineno-2-25">25</a></span>
<span class="normal"><a href="#__codelineno-2-26">26</a></span>
<span class="normal"><a href="#__codelineno-2-27">27</a></span>
<span class="normal"><a href="#__codelineno-2-28">28</a></span>
<span class="normal"><a href="#__codelineno-2-29">29</a></span>
<span class="normal"><a href="#__codelineno-2-30">30</a></span>
<span class="normal"><a href="#__codelineno-2-31">31</a></span>
<span class="normal"><a href="#__codelineno-2-32">32</a></span>
<span class="normal"><a href="#__codelineno-2-33">33</a></span>
<span class="normal"><a href="#__codelineno-2-34">34</a></span>
<span class="normal"><a href="#__codelineno-2-35">35</a></span>
<span class="normal"><a href="#__codelineno-2-36">36</a></span>
<span class="normal"><a href="#__codelineno-2-37">37</a></span>
<span class="normal"><a href="#__codelineno-2-38">38</a></span>
<span class="normal"><a href="#__codelineno-2-39">39</a></span>
<span class="normal"><a href="#__codelineno-2-40">40</a></span>
<span class="normal"><a href="#__codelineno-2-41">41</a></span>
<span class="normal"><a href="#__codelineno-2-42">42</a></span>
<span class="normal"><a href="#__codelineno-2-43">43</a></span>
<span class="normal"><a href="#__codelineno-2-44">44</a></span>
<span class="normal"><a href="#__codelineno-2-45">45</a></span>
<span class="normal"><a href="#__codelineno-2-46">46</a></span>
<span class="normal"><a href="#__codelineno-2-47">47</a></span>
<span class="normal"><a href="#__codelineno-2-48">48</a></span>
<span class="normal"><a href="#__codelineno-2-49">49</a></span>
<span class="normal"><a href="#__codelineno-2-50">50</a></span>
<span class="normal"><a href="#__codelineno-2-51">51</a></span>
<span class="normal"><a href="#__codelineno-2-52">52</a></span>
<span class="normal"><a href="#__codelineno-2-53">53</a></span>
<span class="normal"><a href="#__codelineno-2-54">54</a></span>
<span class="normal"><a href="#__codelineno-2-55">55</a></span>
<span class="normal"><a href="#__codelineno-2-56">56</a></span>
<span class="normal"><a href="#__codelineno-2-57">57</a></span>
<span class="normal"><a href="#__codelineno-2-58">58</a></span>
<span class="normal"><a href="#__codelineno-2-59">59</a></span>
<span class="normal"><a href="#__codelineno-2-60">60</a></span>
<span class="normal"><a href="#__codelineno-2-61">61</a></span>
<span class="normal"><a href="#__codelineno-2-62">62</a></span>
<span class="normal"><a href="#__codelineno-2-63">63</a></span>
<span class="normal"><a href="#__codelineno-2-64">64</a></span>
<span class="normal"><a href="#__codelineno-2-65">65</a></span>
<span class="normal"><a href="#__codelineno-2-66">66</a></span>
<span class="normal"><a href="#__codelineno-2-67">67</a></span>
<span class="normal"><a href="#__codelineno-2-68">68</a></span>
<span class="normal"><a href="#__codelineno-2-69">69</a></span>
<span class="normal"><a href="#__codelineno-2-70">70</a></span>
<span class="normal"><a href="#__codelineno-2-71">71</a></span>
<span class="normal"><a href="#__codelineno-2-72">72</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1"></a><span class="gh"># Build a new application from the Aetos Standards blueprint</span>
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2"></a>
</span><span id="__span-2-3"><a id="__codelineno-2-3" name="__codelineno-2-3"></a>You are coding a complete new backend application conforming to the Aetos
</span><span id="__span-2-4"><a id="__codelineno-2-4" name="__codelineno-2-4"></a>standard app blueprint. Execute every step in order. Only steps 2 and 3 use the
</span><span id="__span-2-5"><a id="__codelineno-2-5" name="__codelineno-2-5"></a>app-specific details provided by the user; everything else is deterministic.
</span><span id="__span-2-6"><a id="__codelineno-2-6" name="__codelineno-2-6"></a>
</span><span id="__span-2-7"><a id="__codelineno-2-7" name="__codelineno-2-7"></a><span class="gu">## Before writing any code</span>
</span><span id="__span-2-8"><a id="__codelineno-2-8" name="__codelineno-2-8"></a>
</span><span id="__span-2-9"><a id="__codelineno-2-9" name="__codelineno-2-9"></a>Connect to the <span class="sb">`standards`</span> MCP server and read:
</span><span id="__span-2-10"><a id="__codelineno-2-10" name="__codelineno-2-10"></a><span class="k">-</span><span class="w"> </span><span class="sb">`doc://nav`</span> (the module list)
</span><span id="__span-2-11"><a id="__codelineno-2-11" name="__codelineno-2-11"></a><span class="k">-</span><span class="w"> </span><span class="sb">`doc://modules/genericity_matrix`</span> (Tier A library / Tier B template / Tier C authored)
</span><span id="__span-2-12"><a id="__codelineno-2-12" name="__codelineno-2-12"></a><span class="k">-</span><span class="w"> </span><span class="sb">`doc://modules/layering_rules`</span> (the dependency rules)
</span><span id="__span-2-13"><a id="__codelineno-2-13" name="__codelineno-2-13"></a>
</span><span id="__span-2-14"><a id="__codelineno-2-14" name="__codelineno-2-14"></a>Then:
</span><span id="__span-2-15"><a id="__codelineno-2-15" name="__codelineno-2-15"></a><span class="k">-</span><span class="w"> </span>call <span class="sb">`find_library`</span> with <span class="sb">`db`</span>, <span class="sb">`di`</span>, <span class="sb">`routing`</span>, <span class="sb">`ingestion`</span>, <span class="sb">`pipeline`</span>, <span class="sb">`docs`</span>
</span><span id="__span-2-16"><a id="__codelineno-2-16" name="__codelineno-2-16"></a> and note the Tier A libraries that already exist — never reimplement one;
</span><span id="__span-2-17"><a id="__codelineno-2-17" name="__codelineno-2-17"></a><span class="k">-</span><span class="w"> </span>call <span class="sb">`list_app_components()`</span> and pull each file you need with
</span><span id="__span-2-18"><a id="__codelineno-2-18" name="__codelineno-2-18"></a> <span class="sb">`get_app_component(kind, resource=..., family=...)`</span> instead of writing it from
</span><span id="__span-2-19"><a id="__codelineno-2-19" name="__codelineno-2-19"></a> scratch.
</span><span id="__span-2-20"><a id="__codelineno-2-20" name="__codelineno-2-20"></a>
</span><span id="__span-2-21"><a id="__codelineno-2-21" name="__codelineno-2-21"></a><span class="gu">## Steps</span>
</span><span id="__span-2-22"><a id="__codelineno-2-22" name="__codelineno-2-22"></a>
</span><span id="__span-2-23"><a id="__codelineno-2-23" name="__codelineno-2-23"></a><span class="k">1.</span> <span class="gs">**Scaffold**</span> — copy <span class="sb">`standards/src/templates/app/`</span> into <span class="sb">`apps/&lt;your-app&gt;/`</span>.
</span><span id="__span-2-24"><a id="__codelineno-2-24" name="__codelineno-2-24"></a> Keep the tree: <span class="sb">`domain/`</span>, <span class="sb">`infra/`</span>, <span class="sb">`interfaces/`</span>, <span class="sb">`pipelines/`</span>, <span class="sb">`tests/`</span>,
</span><span id="__span-2-25"><a id="__codelineno-2-25" name="__codelineno-2-25"></a> <span class="sb">`scripts/`</span>, plus <span class="sb">`pyproject.toml`</span>, <span class="sb">`openapi.yaml`</span>, <span class="sb">`config.py`</span>, <span class="sb">`init.py`</span>,
</span><span id="__span-2-26"><a id="__codelineno-2-26" name="__codelineno-2-26"></a> <span class="sb">`main.py`</span>, <span class="sb">`worker.py`</span>, <span class="sb">`Dockerfile`</span>, <span class="sb">`docker-compose.yaml`</span>, <span class="sb">`.env.example`</span>.
</span><span id="__span-2-27"><a id="__codelineno-2-27" name="__codelineno-2-27"></a>
</span><span id="__span-2-28"><a id="__codelineno-2-28" name="__codelineno-2-28"></a><span class="k">2.</span> <span class="gs">**Author the spec (app-specific)**</span> — write <span class="sb">`openapi.yaml`</span>: resources,
</span><span id="__span-2-29"><a id="__codelineno-2-29" name="__codelineno-2-29"></a> schemas, <span class="sb">`operationId`</span>s, security, and extension metadata. This is the
</span><span id="__span-2-30"><a id="__codelineno-2-30" name="__codelineno-2-30"></a> contract and drives all routing.
</span><span id="__span-2-31"><a id="__codelineno-2-31" name="__codelineno-2-31"></a>
</span><span id="__span-2-32"><a id="__codelineno-2-32" name="__codelineno-2-32"></a><span class="k">3.</span> <span class="gs">**Write each CRUD slice (app-specific)**</span> — per resource create the four-file
</span><span id="__span-2-33"><a id="__codelineno-2-33" name="__codelineno-2-33"></a> slice: <span class="sb">`models.py`</span>, <span class="sb">`ports/db.py`</span>, <span class="sb">`ports/service.py`</span>, and optional
</span><span id="__span-2-34"><a id="__codelineno-2-34" name="__codelineno-2-34"></a> <span class="sb">`converters.py`</span>. Follow the CRUD template.
</span><span id="__span-2-35"><a id="__codelineno-2-35" name="__codelineno-2-35"></a>
</span><span id="__span-2-36"><a id="__codelineno-2-36" name="__codelineno-2-36"></a><span class="k">4.</span> <span class="gs">**Wire the composition root**</span> — in <span class="sb">`init.py`</span>, build leaf repositories, then
</span><span id="__span-2-37"><a id="__codelineno-2-37" name="__codelineno-2-37"></a> dependent repositories, then services; add infra adapters (db, cache, stores,
</span><span id="__span-2-38"><a id="__codelineno-2-38" name="__codelineno-2-38"></a> progress bus, fetchers). Expose <span class="sb">`get_svc`</span> overloads.
</span><span id="__span-2-39"><a id="__codelineno-2-39" name="__codelineno-2-39"></a>
</span><span id="__span-2-40"><a id="__codelineno-2-40" name="__codelineno-2-40"></a><span class="k">5.</span> <span class="gs">**Add routes**</span> — create <span class="sb">`interfaces/&lt;resource&gt;/routes.py`</span> thin handlers bound
</span><span id="__span-2-41"><a id="__codelineno-2-41" name="__codelineno-2-41"></a> to <span class="sb">`operationId`</span>s and re-export them in <span class="sb">`interfaces/openapi.py`</span>. Add the cache
</span><span id="__span-2-42"><a id="__codelineno-2-42" name="__codelineno-2-42"></a> decorator to read endpoints.
</span><span id="__span-2-43"><a id="__codelineno-2-43" name="__codelineno-2-43"></a>
</span><span id="__span-2-44"><a id="__codelineno-2-44" name="__codelineno-2-44"></a><span class="k">6.</span> <span class="gs">**Bootstrap app and worker**</span> — confirm <span class="sb">`main.py`</span> runs the OpenAPI-first app
</span><span id="__span-2-45"><a id="__codelineno-2-45" name="__codelineno-2-45"></a> with its lifespan. If the app has long-running jobs, adapt <span class="sb">`worker.py`</span> to poll
</span><span id="__span-2-46"><a id="__codelineno-2-46" name="__codelineno-2-46"></a> the job collection, run the pipeline, and publish progress.
</span><span id="__span-2-47"><a id="__codelineno-2-47" name="__codelineno-2-47"></a>
</span><span id="__span-2-48"><a id="__codelineno-2-48" name="__codelineno-2-48"></a><span class="k">7.</span> <span class="gs">**Add pipeline families (only if data-driven)**</span> — copy <span class="sb">`pipelines/example/`</span>
</span><span id="__span-2-49"><a id="__codelineno-2-49" name="__codelineno-2-49"></a> to <span class="sb">`pipelines/&lt;family&gt;/`</span> with <span class="sb">`abc.py`</span>, <span class="sb">`impl.py`</span>, <span class="sb">`pipeline.yaml`</span>,
</span><span id="__span-2-50"><a id="__codelineno-2-50" name="__codelineno-2-50"></a> <span class="sb">`resources/`</span>, and reuse <span class="sb">`pipelines/shared/`</span> (loader + registry). Register the
</span><span id="__span-2-51"><a id="__codelineno-2-51" name="__codelineno-2-51"></a> root. Add fixtures and a parity test.
</span><span id="__span-2-52"><a id="__codelineno-2-52" name="__codelineno-2-52"></a>
</span><span id="__span-2-53"><a id="__codelineno-2-53" name="__codelineno-2-53"></a><span class="k">8.</span> <span class="gs">**Add infrastructure only where needed**</span> — Tier A capability: use the
</span><span id="__span-2-54"><a id="__codelineno-2-54" name="__codelineno-2-54"></a> library. Tier B capability: copy the template. Never hand-write a Tier A
</span><span id="__span-2-55"><a id="__codelineno-2-55" name="__codelineno-2-55"></a> library.
</span><span id="__span-2-56"><a id="__codelineno-2-56" name="__codelineno-2-56"></a>
</span><span id="__span-2-57"><a id="__codelineno-2-57" name="__codelineno-2-57"></a><span class="k">9.</span> <span class="gs">**Tests**</span> — integration tests with fakes at the HTTP edge; unit tests for
</span><span id="__span-2-58"><a id="__codelineno-2-58" name="__codelineno-2-58"></a> domain and pipeline logic; a config-consistency test for rule-driven
</span><span id="__span-2-59"><a id="__codelineno-2-59" name="__codelineno-2-59"></a> pipelines.
</span><span id="__span-2-60"><a id="__codelineno-2-60" name="__codelineno-2-60"></a>
</span><span id="__span-2-61"><a id="__codelineno-2-61" name="__codelineno-2-61"></a><span class="k">10.</span> <span class="gs">**Scripts and seeds**</span> — operator scripts under <span class="sb">`scripts/`</span> using
</span><span id="__span-2-62"><a id="__codelineno-2-62" name="__codelineno-2-62"></a> <span class="sb">`init()`</span> / <span class="sb">`get_svc()`</span> / <span class="sb">`shutdown()`</span>; run as <span class="sb">`python -m scripts.&lt;name&gt;`</span>.
</span><span id="__span-2-63"><a id="__codelineno-2-63" name="__codelineno-2-63"></a>
</span><span id="__span-2-64"><a id="__codelineno-2-64" name="__codelineno-2-64"></a><span class="k">11.</span> <span class="gs">**Docs**</span> — author GSDFC docstrings, generate <span class="sb">`.pyi`</span> stubs, mark the package
</span><span id="__span-2-65"><a id="__codelineno-2-65" name="__codelineno-2-65"></a> <span class="sb">`py.typed`</span>, and build the docs.
</span><span id="__span-2-66"><a id="__codelineno-2-66" name="__codelineno-2-66"></a>
</span><span id="__span-2-67"><a id="__codelineno-2-67" name="__codelineno-2-67"></a><span class="gs">**Definition of done:**</span>
</span><span id="__span-2-68"><a id="__codelineno-2-68" name="__codelineno-2-68"></a><span class="k">-</span><span class="w"> </span><span class="sb">`python -c &quot;import main&quot;`</span> succeeds.
</span><span id="__span-2-69"><a id="__codelineno-2-69" name="__codelineno-2-69"></a><span class="k">-</span><span class="w"> </span><span class="sb">`pytest`</span> passes.
</span><span id="__span-2-70"><a id="__codelineno-2-70" name="__codelineno-2-70"></a><span class="k">-</span><span class="w"> </span>The app serves every operation in the spec; the worker drains its queue.
</span><span id="__span-2-71"><a id="__codelineno-2-71" name="__codelineno-2-71"></a><span class="k">-</span><span class="w"> </span>No domain module imports a web framework.
</span><span id="__span-2-72"><a id="__codelineno-2-72" name="__codelineno-2-72"></a><span class="k">-</span><span class="w"> </span>No Tier A library was reimplemented.
</span></code></pre></div></td></tr></table></div>
<hr />
<h2 id="where-the-steps-land">🧭 Where the steps land</h2>
<p>The steps map onto the layers as follows:</p>
<table>
<thead>
<tr>
<th>Step</th>
<th>Package / file</th>
<th>Depends on</th>
</tr>
</thead>
<tbody>
<tr>
<td>1 · Scaffold</td>
<td>whole <code>templates/app/</code></td>
<td>—</td>
</tr>
<tr>
<td>2 · Spec</td>
<td><code>openapi.yaml</code></td>
<td>—</td>
</tr>
<tr>
<td>3 · CRUD slices</td>
<td><code>domain/&lt;resource&gt;/</code></td>
<td>spec, CRUD template</td>
</tr>
<tr>
<td>4 · Wiring</td>
<td><code>init.py</code></td>
<td>every slice</td>
</tr>
<tr>
<td>5 · Routes</td>
<td><code>interfaces/&lt;resource&gt;/</code></td>
<td>services, openapi route registry</td>
</tr>
<tr>
<td>6 · Bootstrap</td>
<td><code>main.py</code>, <code>worker.py</code></td>
<td>composition root</td>
</tr>
<tr>
<td>7 · Pipelines</td>
<td><code>pipelines/&lt;family&gt;/</code>, <code>shared/</code></td>
<td>library pipeline engine</td>
</tr>
<tr>
<td>8 · Infra</td>
<td><code>infra/</code></td>
<td>domain ports</td>
</tr>
<tr>
<td>9 · Tests</td>
<td><code>tests/</code></td>
<td>app + fixtures</td>
</tr>
<tr>
<td>10 · Scripts</td>
<td><code>scripts/</code></td>
<td>composition root</td>
</tr>
<tr>
<td>11 · Docs</td>
<td>docstrings + docs build</td>
<td>code, Doc Forge</td>
</tr>
</tbody>
</table>
<hr />
<h2 id="definition-of-done">⚠️ Definition of done</h2>
<ul>
<li><code>python -c "import main"</code> succeeds.</li>
<li><code>pytest</code> passes.</li>
<li>The app serves the spec's operations; the worker drains its queue.</li>
<li>No domain module imports a web framework.</li>
<li>No Tier A library was reimplemented.</li>
</ul>
<hr />
<h2 id="related">Related</h2>
<ul>
<li><a href="../02_layering_rules/">02 – Layering Rules</a> · <a href="../05_crud_template/">05 – CRUD Template</a> · <a href="../06_pipeline_scaffold/">06 – Pipeline Scaffold</a> · <a href="../12_genericity_matrix/">12 – Genericity Matrix</a></li>
</ul>
</article>
</div>
<script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
Back to top
</button>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "..", "features": ["navigation.sections", "navigation.expand", "navigation.top", "navigation.instant", "navigation.tracking", "navigation.indexes", "content.code.copy", "content.code.annotate", "content.tabs.link", "content.action.edit", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.973d3a69.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
<script src="../assets/javascripts/bundle.f55a23d4.min.js"></script>
</body>
</html>