docs(standards): vendor template into MCP bundle; add component tools + start_app prompt
This commit is contained in:
@@ -482,27 +482,27 @@
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#reusable-as-is-do-not-rewrite" class="md-nav__link">
|
||||
<a href="#tier-a-library-backed-use-never-reimplement" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Reusable as-is (do not rewrite)
|
||||
Tier A — Library-backed (use; never reimplement)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#template-to-adapt-copy-then-change-names" class="md-nav__link">
|
||||
<a href="#tier-b-template-provided-copy-from-templatesapp-then-adapt" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Template to adapt (copy, then change names)
|
||||
Tier B — Template-provided (copy from templates/app, then adapt)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#app-specific-must-be-authored" class="md-nav__link">
|
||||
<a href="#tier-c-app-specific-must-be-authored" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
App-specific (must be authored)
|
||||
Tier C — App-specific (must be authored)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
@@ -583,27 +583,27 @@
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#reusable-as-is-do-not-rewrite" class="md-nav__link">
|
||||
<a href="#tier-a-library-backed-use-never-reimplement" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Reusable as-is (do not rewrite)
|
||||
Tier A — Library-backed (use; never reimplement)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#template-to-adapt-copy-then-change-names" class="md-nav__link">
|
||||
<a href="#tier-b-template-provided-copy-from-templatesapp-then-adapt" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Template to adapt (copy, then change names)
|
||||
Tier B — Template-provided (copy from templates/app, then adapt)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="#app-specific-must-be-authored" class="md-nav__link">
|
||||
<a href="#tier-c-app-specific-must-be-authored" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
App-specific (must be authored)
|
||||
Tier C — App-specific (must be authored)
|
||||
</span>
|
||||
</a>
|
||||
|
||||
@@ -636,101 +636,162 @@
|
||||
|
||||
<h1 id="genericity-matrix">Genericity Matrix</h1>
|
||||
<h2 id="summary">Summary</h2>
|
||||
<p>This page states precisely what is <strong>reusable as-is</strong>, what is a <strong>template to
|
||||
adapt</strong>, and what is <strong>app-specific and must be authored</strong>. Use it to scope a
|
||||
new build.</p>
|
||||
<p>This page states precisely what is <strong>library-backed</strong>, what is
|
||||
<strong>template-provided</strong>, and what is <strong>app-specific and must be authored</strong>. Use it
|
||||
to scope a new build and to know, for any given capability, whether to call a
|
||||
library, copy template code, or write it yourself.</p>
|
||||
<hr />
|
||||
<h2 id="reusable-as-is-do-not-rewrite">Reusable as-is (do not rewrite)</h2>
|
||||
<h2 id="tier-a-library-backed-use-never-reimplement">Tier A — Library-backed (use; never reimplement)</h2>
|
||||
<p>These capabilities already exist as internal libraries. Reach them through the
|
||||
library registry MCP (<code>find_library(capability)</code>) and read the library's own MCP
|
||||
for its API. Writing a private copy of any of these is a defect.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Area</th>
|
||||
<th>Artifact</th>
|
||||
<th>Capability</th>
|
||||
<th>Library</th>
|
||||
<th>MCP</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Persistence: repositories, cache, populate, transactions</td>
|
||||
<td>Mongo Ops (<code>mongo_ops</code>)</td>
|
||||
<td><code>:8007</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Dependency injection / composition</td>
|
||||
<td>Hexa (<code>hexa</code>)</td>
|
||||
<td><code>:8008</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Deterministic multi-step transformation engine</td>
|
||||
<td>DAG Pipe (<code>dagpipe</code>)</td>
|
||||
<td><code>:8006</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Spec-first HTTP edge, client, codegen</td>
|
||||
<td>OpenAPI First (<code>openapi_first</code>)</td>
|
||||
<td><code>:8004</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Format-agnostic fetch + parse (HTML, PDF, CSV, XLSX)</td>
|
||||
<td>Omniread (<code>omniread</code>)</td>
|
||||
<td><code>:8003</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Read-only email ingestion</td>
|
||||
<td>Mail Intake (<code>mail_intake</code>)</td>
|
||||
<td><code>:8002</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JWT auth primitives (register, login, introspect)</td>
|
||||
<td>Py JWT (<code>jwtlib</code>)</td>
|
||||
<td><code>:8005</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Documentation build (MkDocs + MCP)</td>
|
||||
<td>Doc Forge (<code>docforge</code>)</td>
|
||||
<td><code>:8001</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="tier-b-template-provided-copy-from-templatesapp-then-adapt">Tier B — Template-provided (copy from <code>templates/app</code>, then adapt)</h2>
|
||||
<p>These are reusable internal components shipped <strong>inside</strong> the template — they are
|
||||
not independent libraries. Copy them as-is, then rename/populate only what is
|
||||
app-specific. They give every app the same wiring shape as the reference app.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Component</th>
|
||||
<th>Template location</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Layering & dependency rule</td>
|
||||
<td>the package layout and import rules</td>
|
||||
<td>the package layout + import rules</td>
|
||||
<td>keep</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Composition root</td>
|
||||
<td>the <code>init.py</code> shape, idempotency, <code>get_svc</code> overloading</td>
|
||||
<td>Composition root shape</td>
|
||||
<td><code>init.py</code> (<code>get_svc</code>/<code>get_db</code>, idempotency)</td>
|
||||
<td>keep</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Web edge</td>
|
||||
<td><code>OpenAPIFirstApp</code> bootstrap, handler-name = <code>operationId</code>, thin handlers</td>
|
||||
<td>Spec-first web edge</td>
|
||||
<td><code>interfaces/openapi.py</code>, thin handlers bound to <code>operationId</code></td>
|
||||
<td>keep</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CRUD slice</td>
|
||||
<td>the four-file pattern (model / ports-db / ports-service / converters)</td>
|
||||
<td>CRUD slice pattern</td>
|
||||
<td><code>domain/<resource>/{models.py, ports/db.py, ports/service.py, converters.py}</code></td>
|
||||
<td>rename + fill</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Generic CRUD service</td>
|
||||
<td>the base service adaptor</td>
|
||||
<td><code>infra/adapters/service.py</code> (<code>CrudsServiceAdaptor</code>)</td>
|
||||
<td>keep</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Repository factory</td>
|
||||
<td>base / populating / cached selection</td>
|
||||
<td><code>infra/db/repos/mongo.py</code> (<code>_repo_factory</code>)</td>
|
||||
<td>keep</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Worker</td>
|
||||
<td>the poll loop, backoff, retry, status machine</td>
|
||||
<td>Worker poll + status loop</td>
|
||||
<td><code>worker.py</code></td>
|
||||
<td>keep</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Progress bus</td>
|
||||
<td>the bus port + in-memory adapter + streaming endpoint</td>
|
||||
<td>Progress bus + streaming</td>
|
||||
<td>bus port + in-memory adapter + SSE endpoint</td>
|
||||
<td>keep</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Human-in-the-loop</td>
|
||||
<td>the durable pause + question document + resolve endpoint + resume map</td>
|
||||
<td>durable pause + question document + resolve endpoint + resume map</td>
|
||||
<td>keep</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Infra adaptors</td>
|
||||
<td>HTTP cache decorator, KV store port, LLM pool scaffold</td>
|
||||
<td>HTTP response cache</td>
|
||||
<td><code>cache_response</code> decorator + generation invalidation</td>
|
||||
<td>keep</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Testing</td>
|
||||
<td>integration harness with fakes, fixture-parity pattern</td>
|
||||
<td>Key-value store</td>
|
||||
<td>KV store port + Redis adapter + in-memory fallback</td>
|
||||
<td>keep</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Docs</td>
|
||||
<td>GSDFC + generated stubs + MCP bundle pipeline</td>
|
||||
<td>LLM client pool</td>
|
||||
<td>provider-select + retry pool scaffold</td>
|
||||
<td>keep</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pipeline scaffold</td>
|
||||
<td><code>pipelines/shared/{ports,loader,registry}.py</code> + <code>pipelines/<family>/</code></td>
|
||||
<td>rename + fill</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Operator scripts</td>
|
||||
<td><code>scripts/</code> (<code>init()</code> / <code>get_svc()</code> / <code>shutdown()</code>)</td>
|
||||
<td>rename</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Testing harness</td>
|
||||
<td>integration fakes + fixture-parity pattern</td>
|
||||
<td>keep</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Project scaffolding</td>
|
||||
<td><code>pyproject.toml</code>, <code>Dockerfile</code>, <code>docker-compose.yaml</code>, <code>.env.example</code>, <code>openapi.yaml</code></td>
|
||||
<td>rename + fill</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="template-to-adapt-copy-then-change-names">Template to adapt (copy, then change names)</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Artifact</th>
|
||||
<th>Change</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>pyproject.toml</code></td>
|
||||
<td>project name, dependencies</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Dockerfile</code> / <code>docker-compose.yaml</code></td>
|
||||
<td>service name, ports, services</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>.env.example</code></td>
|
||||
<td>connection strings, provider keys</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>openapi.yaml</code></td>
|
||||
<td>every path/schema/operationId</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>scripts/</code></td>
|
||||
<td>seed and operator tasks</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="app-specific-must-be-authored">App-specific (must be authored)</h2>
|
||||
<h2 id="tier-c-app-specific-must-be-authored">Tier C — App-specific (must be authored)</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -752,7 +813,7 @@ new build.</p>
|
||||
<td>domain behaviour</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pipeline families (if any)</td>
|
||||
<td>Pipeline families</td>
|
||||
<td>the transformation graph</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -765,6 +826,7 @@ new build.</p>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h2 id="the-two-axes">The two axes</h2>
|
||||
<p>Everything app-specific reduces to <strong>two axes</strong>:</p>
|
||||
<ol>
|
||||
@@ -772,7 +834,8 @@ new build.</p>
|
||||
the OpenAPI contract.</li>
|
||||
<li><strong>Pipeline family</strong> — only if inputs require multi-step transformation.</li>
|
||||
</ol>
|
||||
<p>If you can specify those two axes, the rest of the app follows mechanically.</p>
|
||||
<p>If you can specify those two axes, the rest of the app follows mechanically:
|
||||
Tier A is imported, Tier B is copied, and Tier C is the only thing you author.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user