fix: repair cp1252-mangled em-dashes and ellipsis in the reference-app wiki
All checks were successful
continuous-integration/drone/push Build is passing

All four 06_reference_app pages round-tripped U+2014 (em-dash) and U+2026
(ellipsis) through cp1252 during earlier PowerShell edits; restored the
characters and regenerated the wiki HTML + MCP modules.
This commit is contained in:
2026-10-20 23:48:08 +05:30
parent a7f0576f1d
commit 7f951f3fe7
13 changed files with 69 additions and 69 deletions

View File

@@ -74,7 +74,7 @@
<div data-md-component="skip">
<a href="#reference-app-a-overview" class="md-skip">
<a href="#reference-app-overview" class="md-skip">
Skip to content
</a>
@@ -842,9 +842,9 @@
<h1 id="reference-app-a-overview">Reference App — Overview</h1>
<h1 id="reference-app-overview">Reference App — Overview</h1>
<p>The standards ship a <strong>runnable sample</strong> of the whole blueprint: the <strong>vet</strong>
veterinary-clinic application. It exists to be copied — it is the reference
veterinary-clinic application. It exists to be copied — it is the reference
for how a real domain sits on the architecture, and the code an agent pulls
through the MCP tools (<code>get_app_template</code>, <code>get_app_component</code>).</p>
<div class="admonition note">
@@ -866,7 +866,7 @@ at <code>standards/src/templates/client/</code> (Vite + MUI + <code>@aetoskia/re
<tbody>
<tr>
<td><strong>parents</strong></td>
<td>The simplest CRUD slice (no foreign keys) — copy this first</td>
<td>The simplest CRUD slice (no foreign keys) — copy this first</td>
</tr>
<tr>
<td><strong>pets</strong></td>
@@ -886,7 +886,7 @@ at <code>standards/src/templates/client/</code> (Vite + MUI + <code>@aetoskia/re
</tr>
<tr>
<td><strong>jobs</strong></td>
<td>The worker's queue — durable status machine</td>
<td>The worker's queue — durable status machine</td>
</tr>
</tbody>
</table>
@@ -909,7 +909,7 @@ reusable <code>pipelines/shared/</code> scaffold and a <code>worker.py</code> th
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7"></a>python<span class="w"> </span>-m<span class="w"> </span>scripts.seed<span class="w"> </span><span class="c1"># optional: seed demo data (mongo backend)</span>
</span></code></pre></div></td></tr></table></div>
<p>The default <code>REPO_BACKEND=memory</code> means the API boots with <strong>no external
services</strong> — repositories are process-local dictionaries. Switch to
services</strong> — repositories are process-local dictionaries. Switch to
<code>REPO_BACKEND=mongo</code> for persistence (see <code>.env.example</code>).</p>
<p>The client pairs with it:</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>
@@ -930,14 +930,14 @@ services</strong> — repositories are process-local dictionaries. Switch t
(<code>{AUTH_SERVER}</code> introspection). Without a reachable auth-server the API
answers <code>401</code> on resource routes; <code>/health</code> stays public. For a local
no-auth demo, remove the <code>security</code> block from <code>openapi.yaml</code> and the
global security entry — see
global security entry — see
<a href="../../../lib/22_auth_integration/">Auth Integration</a>.</p>
</div>
<h2 id="next">Next</h2>
<ul>
<li><a href="../02_domain_and_api/">Domain &amp; API</a> — walking the resource axis</li>
<li><a href="../03_pipelines_and_worker/">Pipelines &amp; Worker</a> — the pipeline axis</li>
<li><a href="../04_client_admin/">Client Admin</a> — the spec-driven frontend</li>
<li><a href="../02_domain_and_api/">Domain &amp; API</a> — walking the resource axis</li>
<li><a href="../03_pipelines_and_worker/">Pipelines &amp; Worker</a> — the pipeline axis</li>
<li><a href="../04_client_admin/">Client Admin</a> — the spec-driven frontend</li>
</ul>

View File

@@ -74,7 +74,7 @@
<div data-md-component="skip">
<a href="#domain-api-a-the-resource-axis" class="md-skip">
<a href="#domain-api-the-resource-axis" class="md-skip">
Skip to content
</a>
@@ -860,7 +860,7 @@
<h1 id="domain-api-a-the-resource-axis">Domain &amp; API — the resource axis</h1>
<h1 id="domain-api-the-resource-axis">Domain &amp; API — the resource axis</h1>
<p>Every aggregate follows the same four-file slice
(<a href="../../../lib/21_crud_template/">CRUD Template</a>); walk <code>parents</code> first, then
<code>appointments</code> when you need foreign keys.</p>
@@ -877,9 +877,9 @@
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4"></a> db.py # ParentDocument(Parent, BaseDocument) + create_parent_repo()
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5"></a> service.py # ParentCrudsService(CrudsServiceAdaptor[...]) + get_parent_service()
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6"></a>interfaces/parents/
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7"></a> routes.py # list/create/get/update/delete — names == operationIds
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7"></a> routes.py # list/create/get/update/delete — names == operationIds
</span></code></pre></div></td></tr></table></div>
<p>Wiring happens in exactly one place — the composition root
<p>Wiring happens in exactly one place — the composition root
<code>init.py</code>:</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-1-1">1</a></span>
<span class="normal"><a href="#__codelineno-1-2">2</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="n">parent_repo</span> <span class="o">=</span> <span class="n">create_parent_repo</span><span class="p">()</span>
@@ -899,7 +899,7 @@ single source of truth: <code>main.py</code> builds an <code>OpenAPIFirstApp</co
<code>operationId</code> to a function of the same name in <code>interfaces/openapi.py</code> (a flat
re-export of every routes module). There are no decorator routers.</p>
<p>The x- extension fields on schemas and properties are what make the admin
client render itself — see <a href="../../../lib/40_ui_admin/">Auto-Rendered Admin</a> and
client render itself — see <a href="../../../lib/40_ui_admin/">Auto-Rendered Admin</a> and
the worked <code>Job</code> schema (enum selects, hidden fields, filterable columns).</p>
<h2 id="foreign-keys-appointments">Foreign keys (appointments)</h2>
<p><code>Appointment</code> declares <code>pet</code>, <code>vet</code>, <code>treatment</code> as <code>dict | int | None</code>. The
@@ -907,7 +907,7 @@ write path normalizes bare ids through <code>expand_ref</code>; the read path re
fully expanded objects:</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></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1"></a><span class="n">pet</span> <span class="o">=</span> <span class="k">await</span> <span class="n">expand_ref</span><span class="p">(</span><span class="n">svc</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="s2">&quot;pet&quot;</span><span class="p">),</span> <span class="n">body</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;pet&quot;</span><span class="p">),</span> <span class="s2">&quot;pet&quot;</span><span class="p">)</span>
</span></code></pre></div></td></tr></table></div>
<p>The list endpoint additionally filters by date prefix and embedded fk ids —
<p>The list endpoint additionally filters by date prefix and embedded fk ids —
client-side over the repository result, the pattern for small reference data.</p>
<h2 id="ids-on-the-wire">Ids on the wire</h2>
<p>The domain models declare <code>id: int | None = None</code> and documents use the
@@ -917,9 +917,9 @@ keeps the OpenAPI <code>id: integer</code> contract, the in-memory demo store, a
Mongo persistence layer consistent.</p>
<h2 id="tests">Tests</h2>
<ul>
<li><code>tests/integration/test_openapi_app_builds.py</code> — generic gate: every
<li><code>tests/integration/test_openapi_app_builds.py</code> — generic gate: every
<code>operationId</code> resolves and the app builds. Copy it verbatim.</li>
<li><code>tests/unit/test_jobs_routes.py</code> — the pattern for route unit tests with a
<li><code>tests/unit/test_jobs_routes.py</code> — the pattern for route unit tests with a
service double (no HTTP client needed).</li>
</ul>

View File

@@ -74,7 +74,7 @@
<div data-md-component="skip">
<a href="#pipelines-worker-a-the-pipeline-axis" class="md-skip">
<a href="#pipelines-worker-the-pipeline-axis" class="md-skip">
Skip to content
</a>
@@ -851,7 +851,7 @@
<h1 id="pipelines-worker-a-the-pipeline-axis">Pipelines &amp; Worker — the pipeline axis</h1>
<h1 id="pipelines-worker-the-pipeline-axis">Pipelines &amp; Worker — the pipeline axis</h1>
<p>The sample proves the full loop: <strong>API creates a job document → worker polls →
pipeline family runs → job reaches a terminal status.</strong></p>
<h2 id="the-jobs-slice">The jobs slice</h2>
@@ -901,7 +901,7 @@ inspects the queue.</p>
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2"></a><span class="n">reminder</span> <span class="o">=</span> <span class="k">await</span> <span class="n">pipeline</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">appointment_id</span><span class="p">)</span>
</span></code></pre></div></td></tr></table></div>
<p>To add a family: copy <code>appointment_reminder/</code>, replace the stages, call
<code>register(kind, variant, root_cls)</code> — see
<code>register(kind, variant, root_cls)</code> — see
<a href="../../../lib/50_pipeline_scaffold/">Pipeline Scaffold</a>.</p>
<h2 id="the-worker">The worker</h2>
<p><code>worker.py</code> is the process that turns
@@ -909,7 +909,7 @@ documents into execution:</p>
<ol>
<li>poll <code>job_svc.search({"status": "pending"})</code> on <code>WORKER_POLL_SECONDS</code></li>
<li>claim a job: <code>status → processing</code></li>
<li>dispatch through the <code>HANDLERS</code> table — <code>HANDLERS[job.kind](job, resources)</code></li>
<li>dispatch through the <code>HANDLERS</code> table — <code>HANDLERS[job.kind](job, resources)</code></li>
<li>on success <code>status → done</code>; on exception <code>status → failed</code>,
<code>retry_count += 1</code>, <code>error_message</code> captured; jobs at
<code>WORKER_MAX_RETRIES</code> are skipped</li>
@@ -923,19 +923,19 @@ documents into execution:</p>
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4"></a><span class="p">}</span>
</span></code></pre></div></td></tr></table></div>
<p>The worker shares the composition root: <code>from init import init</code> gives it the
same wired services the API uses — one place to add a dependency.</p>
same wired services the API uses — one place to add a dependency.</p>
<div class="admonition note">
<p class="admonition-title">Same process model in production</p>
<p>API and worker are separate processes (see <code>docker-compose.yaml</code>: <code>api</code>,
<code>worker</code>, <code>mongo</code>). Any in-memory progress bus is per-process; to surface
live progress through the API, swap the bus adaptor for a broker-backed
one — see <a href="../../../lib/51_worker_and_progress/">Worker &amp; Progress</a>.</p>
one — see <a href="../../../lib/51_worker_and_progress/">Worker &amp; Progress</a>.</p>
</div>
<h2 id="tests">Tests</h2>
<ul>
<li><code>tests/unit/test_appointment_reminder_pipeline.py</code> — stage units + the wired
<li><code>tests/unit/test_appointment_reminder_pipeline.py</code> — stage units + the wired
root against a fake service.</li>
<li><code>tests/unit/test_worker.py</code> — dispatch, done/failed transitions, retry
<li><code>tests/unit/test_worker.py</code> — dispatch, done/failed transitions, retry
exhaustion, using an in-memory job service double and a cancelled poll task.</li>
</ul>

View File

@@ -74,7 +74,7 @@
<div data-md-component="skip">
<a href="#client-admin-a-the-spec-driven-frontend" class="md-skip">
<a href="#client-admin-the-spec-driven-frontend" class="md-skip">
Skip to content
</a>
@@ -851,18 +851,18 @@
<h1 id="client-admin-a-the-spec-driven-frontend">Client Admin — the spec-driven frontend</h1>
<p>The client sample (<code>standards/src/templates/client/</code>) renders a full admin —
auth pages, resource lists, forms, detail views — <strong>from the server's
<h1 id="client-admin-the-spec-driven-frontend">Client Admin — the spec-driven frontend</h1>
<p>The client sample (<code>standards/src/templates/client/</code>) renders a full admin —
auth pages, resource lists, forms, detail views — <strong>from the server's
<code>openapi.yaml</code></strong>, driven entirely by the x- extension fields. There are no
hand-written screens per resource.</p>
<h2 id="what-ships">What ships</h2>
<p>A Vite + React + MUI app wiring the two Aetos packages:</p>
<ul>
<li><strong><code>@aetoskia/react-openapi</code></strong> — fetches <code>${VITE_API_BASE_URL}/openapi.json</code>,
<li><strong><code>@aetoskia/react-openapi</code></strong> — fetches <code>${VITE_API_BASE_URL}/openapi.json</code>,
builds the router and the resource admin from the spec's schemas and x-
fields (list columns, autocomplete, fk pickers, enum selects, hidden fields…)</li>
<li><strong><code>@aetoskia/react-auth</code></strong> — login/register/logout against the auth-server
fields (list columns, autocomplete, fk pickers, enum selects, hidden fields…)</li>
<li><strong><code>@aetoskia/react-auth</code></strong> — login/register/logout against the auth-server
paths declared in the spec's <code>securitySchemes.bearerAuth</code>, and attaches the
JWT to every API call</li>
<li>a shared MUI theme (<code>src/shared-theme/</code>) and the shell
@@ -892,7 +892,7 @@ hand-written screens per resource.</p>
</span></code></pre></div></td></tr></table></div>
<p>Open the dev-server URL; the admin lists Parents, Pets, Treatments, Vets,
Appointments and Jobs straight from the vet spec. Edit <code>openapi.yaml</code> on the
server and the client follows on reload — the spec is the contract on both
server and the client follows on reload — the spec is the contract on both
sides.</p>
<h2 id="where-the-x-extensions-come-from">Where the x- extensions come from</h2>
<p>The canonical catalog lives in the react-openapi package

File diff suppressed because one or more lines are too long