docs(standards): vendor template into MCP bundle; add component tools + start_app prompt

This commit is contained in:
2026-10-12 21:24:10 +05:30
parent 715bfd8022
commit 2d1278911c
68 changed files with 2044 additions and 102 deletions

View File

@@ -691,7 +691,9 @@
<h1 id="infra-adapters">Infra Adapters</h1>
<h2 id="summary">Summary</h2>
<p>All external systems are reached through adapters in <code>infra/</code>. Prefer an
existing internal library over writing a new adapter.</p>
existing internal library over writing a new adapter; where no library exists,
copy the Tier B scaffold from <code>templates/app</code>. See the Genericity Matrix for the
Tier A / B / C split.</p>
<hr />
<h2 id="database-mongodb">Database (MongoDB)</h2>
<ul>
@@ -720,9 +722,10 @@ existing internal library over writing a new adapter.</p>
<ul>
<li>Transactions use a session context manager provided by the library.</li>
</ul>
<p><strong>Library:</strong> the Mongo operations library (see registry). Do not write raw
Motor calls in the domain.</p>
<p><strong>Tier A — Library (Mongo Ops).</strong> Do not write raw Motor calls in the domain;
consult the registry and the library's MCP before touching the driver.</p>
<h2 id="http-response-cache">HTTP response cache</h2>
<p><strong>Tier B — template.</strong> Copy from <code>templates/app</code>; not a standalone library.</p>
<p>A generic GET cache sits behind a decorator.</p>
<div class="language-python 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></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="nd">@cache_response</span><span class="p">(</span><span class="n">ttl</span><span class="o">=</span><span class="mi">60</span><span class="p">)</span>
@@ -735,14 +738,16 @@ Motor calls in the domain.</p>
invalidation.</li>
</ul>
<h2 id="event-progress-bus">Event / progress bus</h2>
<p><strong>Tier B — template.</strong> Copy from <code>templates/app</code>.</p>
<p>A port with an in-memory default adapter (<code>publish</code>, <code>get_events</code>). Swap for a
durable broker in production (see Worker &amp; Progress).</p>
<h2 id="external-clients-ingestion">External clients (ingestion)</h2>
<p>External fetchers (files, mail, HTTP) are adapters that wrap ingestion
libraries. Construct them in the composition root and inject into
orchestrators.</p>
<p><strong>Libraries:</strong> the ingestion library (formats) and the mail library (email).</p>
<p><strong>Tier A — Libraries:</strong> Omniread (formats) and Mail Intake (email).</p>
<h2 id="llm-clients">LLM clients</h2>
<p><strong>Tier B — template.</strong> Copy the pool scaffold from <code>templates/app</code>.</p>
<p>When a pipeline calls a model provider, route through a pool adaptor that
handles provider selection, retries, and client lifecycle:</p>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-3-1">1</a></span>
@@ -751,11 +756,19 @@ handles provider selection, retries, and client lifecycle:</p>
</span></code></pre></div></td></tr></table></div>
<p>Providers are selected by <code>LLM_PROVIDER</code> and configured by environment.</p>
<h2 id="key-value-store">Key-value store</h2>
<p><strong>Tier B — template.</strong> Copy from <code>templates/app</code>.</p>
<p>For report/snapshot storage, provide a pluggable store port with a Redis
adapter and an in-memory fallback.</p>
<h2 id="rule">Rule</h2>
<p>If a capability already exists as a library (DB, DI, ingestion, mail, auth,
docs), <strong>use it</strong>. Writing a private copy of a library is a defect.</p>
<ul>
<li><strong>Tier A (libraries: DB, DI, ingestion, mail, auth, docs, pipelines)</strong> — use
the library; writing a private copy is a defect. Query <code>find_library</code> first.</li>
<li><strong>Tier B (cache, progress bus, LLM pool, KV store, composition shape, worker,
tests)</strong> — these are template code, not libraries: copy them from
<code>templates/app</code> rather than searching the registry.</li>
<li><strong>Tier C (models, business logic, pipeline families, rules)</strong> — author them
yourself.</li>
</ul>

View File

@@ -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 &amp; 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/&lt;resource&gt;/{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/&lt;family&gt;/</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>

View File

@@ -665,7 +665,7 @@ can read a library's full API by connecting to its MCP and reading
<td><code>hexa</code></td>
<td>Declarative DI / composition-root tooling</td>
<td>manual wiring, hand-written factories</td>
<td><em>(see note)</em></td>
<td><code>:8008</code></td>
</tr>
<tr>
<td>Mongo Ops</td>
@@ -714,7 +714,7 @@ can read a library's full API by connecting to its MCP and reading
<td><em>(service)</em></td>
<td>Central identity service (register/login/me/introspect)</td>
<td>building auth endpoints yourself</td>
<td>—</td>
<td><em>(deferred)</em></td>
</tr>
</tbody>
</table>
@@ -767,9 +767,12 @@ matching library, its import name, its "use instead of" guidance, and its MCP
endpoint. Query it before writing any infrastructure.</p>
<h2 id="notes">Notes</h2>
<ul>
<li><strong>Hexa</strong> ships an MCP bundle but is not yet assigned a dedicated port in the
hub config; it is reachable via the standards registry entry and will be
wired to a port.</li>
<li><strong>Hexa</strong> is a full library with its own MCP server on <code>:8008</code>: read
<code>doc://index</code>, <code>doc://nav</code>, and <code>doc://modules/{module}</code> (e.g.
<code>doc://modules/hexa.container</code>) to discover the DI surface — <code>build(cls, *,
instances, config)</code> and the <code>PortNode</code> model.</li>
<li><strong>Auth Server</strong> is deferred: it has no <code>pyproject.toml</code>/importable package and
no MCP bundle. Do not reach for it yet; <code>py-jwt</code> covers token primitives.</li>
<li>Library MCP servers expose <strong>documentation resources</strong> (not executable tools):
they tell an agent the available API surface so it does not invent code.</li>
</ul>

View File

@@ -516,7 +516,7 @@ patterns, and the internal library catalog that agents consult while coding.</p>
<li><strong>Worker &amp; Progress</strong> — queued work, progress reporting, and visibility.</li>
<li><strong>Human-in-the-Loop</strong> — guardrails and approvals inside automations.</li>
<li><strong>Infra Adapters</strong> — how infrastructure connects without leaking into domain.</li>
<li><strong>Genericity Matrix</strong> — what is generic vs app-specific.</li>
<li><strong>Genericity Matrix</strong> — what is library-backed, template-provided, or authored.</li>
<li><strong>Library Registry</strong> — the catalog of internal libraries behind all of it.</li>
</ul>
<p>Read the <strong>Wiki</strong> for the philosophy and rationale; these pages are the

File diff suppressed because one or more lines are too long