Add the plain-language workflow map

A single-page explainer for people who will not read the build spec: how a
question becomes an answer, the four lanes and why they are separate, the four
tools the assistant may reach for, where the knowledge comes from, and what is
live against what is only built. Status snapshot as observed on the host,
21 August 2026.

Kept at the repository root beside the other narrative documents rather than in
docs/, which is gitignored and holds controlled plant documents. Listed in the
layout sections of README.md and the build spec so it is findable.

Note: it predates Phase 9 and so does not mention operator document upload,
withdrawal or pool curation. Its step table stops at 8.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Claude 2026-08-21 13:19:45 +10:00
parent 98083cd8d6
commit 189f528d47
3 changed files with 385 additions and 0 deletions

View file

@ -239,6 +239,8 @@ Project lives in Forgejo (`git.yokogawa.tech`). Compose files stay in `~` per ho
. .
├── BUILD-AI-CONTAINERS.md # this file ├── BUILD-AI-CONTAINERS.md # this file
├── CLAUDE.md # symlink or copy of the host onboarding brief ├── CLAUDE.md # symlink or copy of the host onboarding brief
├── workflow-map.html # the plain-language explainer, for people who are
│ # not going to read this file
├── README.md # rebuild-from-zero ├── README.md # rebuild-from-zero
├── compose/ ├── compose/
│ ├── ai-compose.yml # deployed to ~/ai-compose.yml │ ├── ai-compose.yml # deployed to ~/ai-compose.yml

View file

@ -343,6 +343,8 @@ pytest api/tests # contracts, classifier rules, SQL allow-list. No netw
``` ```
CLAUDE.md short rules — what Claude Code keeps front of mind CLAUDE.md short rules — what Claude Code keeps front of mind
workflow-map.html the non-technical explainer — how a question becomes
an answer, and what is built. Open it in a browser
BUILD-AI-CONTAINERS.md the build spec BUILD-AI-CONTAINERS.md the build spec
YAU_Linux_Host_Onboarding.md the host brief (reference; wins on conflict) YAU_Linux_Host_Onboarding.md the host brief (reference; wins on conflict)
compose/ deployed to ~/ai-compose.yml and ~/langfuse-compose.yml compose/ deployed to ~/ai-compose.yml and ~/langfuse-compose.yml

381
workflow-map.html Normal file
View file

@ -0,0 +1,381 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WRPS Plant Assistant — Workflow Map</title>
<style>
:root{
--bg:#f6f7f9; --panel:#ffffff; --ink:#1a1d21; --muted:#5d6672; --line:#dfe3e8;
--live:#1a7f4b; --live-bg:#e6f4ec; --built:#1f5fa8; --built-bg:#e8f0fa;
--blocked:#a86400; --blocked-bg:#fdf1de; --none:#6b7280; --none-bg:#eef0f2;
--accent:#8b4a9c; --stop:#b03030; --stop-bg:#fbebeb;
}
@media (prefers-color-scheme: dark){
:root:not([data-theme="light"]){
--bg:#14161a; --panel:#1c1f25; --ink:#e9ecef; --muted:#9aa4b2; --line:#2c313a;
--live:#5cd39a; --live-bg:#15311f; --built:#7fb2ee; --built-bg:#16283d;
--blocked:#e6b567; --blocked-bg:#332713; --none:#98a1ad; --none-bg:#23262c;
--accent:#cf9ade; --stop:#f08a8a; --stop-bg:#3a1c1c;
}
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);
font:16px/1.55 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;}
.wrap{max-width:1160px;margin:0 auto;padding:32px 20px 80px}
h1{font-size:28px;margin:0 0 6px;line-height:1.25}
h2{font-size:20px;margin:46px 0 4px;padding-top:18px;border-top:1px solid var(--line)}
.sub{color:var(--muted);margin:0 0 18px;max-width:72ch}
.stamp{color:var(--muted);font-size:13px;margin-bottom:24px}
.legend{display:flex;flex-wrap:wrap;gap:10px;margin:18px 0 8px}
.key{display:inline-flex;align-items:center;gap:7px;font-size:13px;color:var(--muted);
background:var(--panel);border:1px solid var(--line);border-radius:20px;padding:5px 12px}
.dot{width:10px;height:10px;border-radius:50%;flex:none;display:inline-block}
.d-live{background:var(--live)} .d-built{background:var(--built)}
.d-blocked{background:var(--blocked)} .d-none{background:var(--none)}
.flow{display:flex;flex-direction:column}
.step{display:grid;grid-template-columns:118px minmax(0,1fr);gap:18px;align-items:start}
.stepnum{color:var(--muted);font-size:12.5px;text-align:right;padding-top:16px;
text-transform:uppercase;letter-spacing:.05em}
.card{background:var(--panel);border:1px solid var(--line);border-left:4px solid var(--none);
border-radius:10px;padding:14px 16px}
.card.live{border-left-color:var(--live)} .card.built{border-left-color:var(--built)}
.card.blocked{border-left-color:var(--blocked)}
.card h3{margin:0 0 5px;font-size:16.5px;display:flex;flex-wrap:wrap;align-items:center;gap:9px}
.card p{margin:0 0 6px;color:var(--muted);font-size:14.5px}
.card p:last-of-type{margin-bottom:0}
.card .ai{display:inline-block;font-size:11px;font-weight:600;letter-spacing:.03em;
padding:1px 7px;border-radius:4px;background:var(--none-bg);color:var(--muted);
text-transform:uppercase}
.tool{font-size:12.5px;color:var(--muted);margin-top:9px;padding-top:8px;
border-top:1px dashed var(--line)}
.tool b{color:var(--ink);font-weight:600;
font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:12.5px}
.badge{font-size:11.5px;font-weight:600;letter-spacing:.02em;padding:2px 9px;border-radius:20px;
white-space:nowrap}
.b-live{color:var(--live);background:var(--live-bg)}
.b-built{color:var(--built);background:var(--built-bg)}
.b-blocked{color:var(--blocked);background:var(--blocked-bg)}
.b-none{color:var(--none);background:var(--none-bg)}
.arrow{grid-column:2;color:var(--line);padding:5px 0 5px 22px;font-size:19px;line-height:1}
.arrow span{color:var(--muted);font-size:12.5px;padding-left:10px}
.lanes{display:grid;grid-template-columns:repeat(auto-fit,minmax(232px,1fr));gap:12px;margin-top:6px}
.lane{background:var(--panel);border:1px solid var(--line);border-top:3px solid var(--accent);
border-radius:10px;padding:13px 14px}
.lane h4{margin:0 0 3px;font-size:14.5px}
.lane .q{font-style:italic;font-size:13.5px;margin:0 0 8px;opacity:.85}
.lane p{margin:0;color:var(--muted);font-size:13.5px}
.lane .uses{margin-top:9px;font-size:12.5px;color:var(--muted);
border-top:1px dashed var(--line);padding-top:8px}
.lane .uses b{color:var(--ink);font-weight:600}
.lane.unclear{border-top-color:var(--muted)}
.cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:14px;margin-top:14px}
table{width:100%;border-collapse:collapse;margin-top:14px;font-size:14.5px}
th,td{text-align:left;padding:10px 12px;border-bottom:1px solid var(--line);vertical-align:top}
th{font-size:12.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);font-weight:600}
td.ph{white-space:nowrap;color:var(--muted);font-variant-numeric:tabular-nums}
.tblwrap{overflow-x:auto}
ul.next{margin:12px 0 0;padding-left:20px;color:var(--muted)}
ul.next li{margin-bottom:8px}
ul.next b{color:var(--ink)}
.note{background:var(--panel);border:1px solid var(--line);border-radius:10px;
padding:14px 16px;margin-top:16px;color:var(--muted);font-size:14.5px}
.note.stop{border-left:4px solid var(--stop);background:var(--stop-bg)}
.note b{color:var(--ink)}
.foot{color:var(--muted);font-size:13px;margin-top:34px;padding-top:14px;
border-top:1px solid var(--line)}
@media (max-width:640px){
.step{grid-template-columns:1fr;gap:4px}
.stepnum{text-align:left;padding-top:10px}
.arrow{grid-column:1;padding-left:6px}
}
</style>
</head>
<body>
<div class="wrap">
<h1>The plant assistant — how a question becomes an answer</h1>
<p class="sub">Waterloo Road Pump Station. An operator types a question in plain English; the
assistant answers it from plant records and controlled documents, and shows its evidence. This page
follows one question through the assistant, names the piece of software doing each job, and marks
what already exists.</p>
<p class="stamp">Status as observed on the live host, 21 August 2026.</p>
<div class="legend">
<span class="key"><i class="dot d-live"></i> Running now</span>
<span class="key"><i class="dot d-built"></i> Built and tested, not yet switched on</span>
<span class="key"><i class="dot d-blocked"></i> Waiting on someone else</span>
<span class="key"><i class="dot d-none"></i> Not started</span>
</div>
<h2>1 &middot; The question&rsquo;s journey</h2>
<p class="sub">Seven stages. The important thing to notice: the assistant decides <em>what kind of
question</em> it is before it looks anything up, and that decision fixes both which sources it may
use and what it is allowed to say.</p>
<div class="flow">
<div class="step">
<div class="stepnum">Ask</div>
<div class="card built">
<h3>The question box <span class="badge b-built">Built, not switched on</span></h3>
<p>A web page with a question box and an answer pane, opened in an ordinary browser on the
control-room PC. Nothing to install.</p>
<div class="tool">Application: <b>ai-web</b> — the operator&rsquo;s screen</div>
</div>
</div>
<div class="arrow">&darr;</div>
<div class="step">
<div class="stepnum">Sort</div>
<div class="card built">
<h3>What kind of question is this? <span class="ai">AI step</span>
<span class="badge b-built">Built, not switched on</span></h3>
<p>A small, fast AI model reads the question and labels it as one of four kinds — or says it is
unsure. It does no answering; it only labels. This is the most safety-relevant step in the
whole assistant, because the label decides everything downstream.</p>
<p>Two rules are built in: if it is not confident, it asks the operator to rephrase rather than
guessing; and if two labels are close, it takes the more cautious one — a question that is
partly advice is treated as advice.</p>
<div class="tool">Application: <b>ai-api</b> &middot; the classifier, using a small AI model</div>
</div>
</div>
<div class="arrow">&darr;</div>
<div class="step">
<div class="stepnum">Translate</div>
<div class="card built">
<h3>What is &ldquo;Pump 02&rdquo;, exactly? <span class="badge b-built">Built, not switched on</span></h3>
<p>Operators say &ldquo;Pump 02&rdquo; or &ldquo;the wet well&rdquo;. The plant records call
those PU-302 and WW-101. This step converts everyday names into the plant&rsquo;s official
ones by looking them up in a list — no AI, no guessing. When it gets a name wrong, the fix is
to add the nickname to the list.</p>
<div class="tool">Application: <b>ai-api</b> &middot; the name resolver, reading the equipment
and tag list in <b>pg-ai</b></div>
</div>
</div>
<div class="arrow">&darr;<span>into one of four lanes — or back to the operator</span></div>
<div class="lanes">
<div class="lane">
<h4>Historical — what happened?</h4>
<p class="q">&ldquo;How many high level alarms last week?&rdquo;</p>
<p>Counts and measurements taken from the plant&rsquo;s recorded history. If there are no
records, the answer says so — it never estimates a figure.</p>
<div class="uses">Looks in: <b>Cube</b> &rarr; the plant historian</div>
</div>
<div class="lane">
<h4>Reference — what does this mean?</h4>
<p class="q">&ldquo;What does the level fault alarm mean?&rdquo;</p>
<p>Explains a signal, alarm or piece of equipment from the manuals and alarm records, quoting
the document it came from.</p>
<div class="uses">Looks in: <b>document search</b> + the equipment and tag list</div>
</div>
<div class="lane">
<h4>Procedural — how do I do it?</h4>
<p class="q">&ldquo;How do I lift the interlock on Pump 02?&rdquo;</p>
<p>Finds the approved procedure and identifies it — document number, revision, date — and
quotes its prerequisites word for word. It never writes the steps itself.</p>
<div class="uses">Looks in: <b>document search</b>, procedures only</div>
</div>
<div class="lane">
<h4>Advisory — what should we do?</h4>
<p class="q">&ldquo;What discharge rate avoids a spill?&rdquo;</p>
<p>Shows what has been run before, what happened when, and the documented limits — then hands
the decision back to a competent person. It never gives a number as the answer.</p>
<div class="uses">Looks in: <b>Cube</b> and <b>document search</b> together</div>
</div>
<div class="lane unclear">
<h4>Unclear — I need more</h4>
<p class="q">&ldquo;Is the pump alright?&rdquo;</p>
<p>When the sorting step is not confident, the assistant stops and asks a clarifying question.
No sources are searched and no answer is drafted.</p>
<div class="uses">Looks in: <b>nothing</b> — it asks instead</div>
</div>
</div>
<div class="arrow" style="grid-column:1/-1">&darr;<span>evidence gathered</span></div>
<div class="step">
<div class="stepnum">Word it</div>
<div class="card built">
<h3>Turn the evidence into a readable answer <span class="ai">AI step</span>
<span class="badge b-built">Built, not switched on</span></h3>
<p>The larger AI model is used here and only here: to put the gathered evidence into plain
English. It cannot go looking for anything else — it only sees what its lane collected. It
supplies wording, not facts.</p>
<div class="tool">Application: <b>ai-api</b> &middot; the answer writer, using the larger AI model</div>
</div>
</div>
<div class="arrow">&darr;</div>
<div class="step">
<div class="stepnum">Check</div>
<div class="card built">
<h3>Is this answer allowed to leave? <span class="badge b-built">Built, not switched on</span></h3>
<p>Every draft is checked against a fixed rulebook before the operator sees it: no invented
steps for safety-critical work, no recommended setpoint, nothing beyond the evidence actually
found, and every claim carrying its citation. A draft that fails is rewritten once and then
refused — it is never shown.</p>
<p>These are ordinary software checks written in code, not instructions given to the AI. That
distinction is the point: an AI can be talked out of an instruction, and cannot be talked out
of a check.</p>
<div class="tool">Application: <b>ai-api</b> &middot; the answer contracts and guardrails</div>
</div>
</div>
<div class="arrow">&darr;</div>
<div class="step">
<div class="stepnum">Show</div>
<div class="card built">
<h3>The answer, and its working <span class="badge b-built">Built, not switched on</span></h3>
<p>Beside the answer the operator sees how it was reached: which kind of question it was judged
to be, what data was counted and over what period, how many records were found, and which
documents were cited with their revision and date. Procedural and advisory answers carry a
visible banner stating plainly what the assistant did <em>not</em> do.</p>
<div class="tool">Application: <b>ai-web</b> &middot; the &ldquo;show working&rdquo; panel</div>
</div>
</div>
<div class="arrow">&darr;</div>
<div class="step">
<div class="stepnum">Record</div>
<div class="card live">
<h3>Everything is written down <span class="badge b-live">Running now</span></h3>
<p>Each question, the kind it was judged to be, the sources used, the rulebook result and how
long it took are all recorded, so any answer can be reviewed afterwards and any mistake traced
to the step that caused it.</p>
<div class="tool">Application: <b>Langfuse</b> — the assistant&rsquo;s logbook</div>
</div>
</div>
</div>
<div class="note stop"><b>Why four lanes instead of one clever assistant:</b> the four kinds of
question need different sources, and — more importantly — different limits on what may be said. One
general-purpose pipeline answering all four is the main way a project like this hurts somebody: it
is how a bypass procedure gets reassembled from fragments nobody approved, or a setpoint gets
suggested and typed into a control system. The assistant cannot wander between lanes, because the
lane is fixed before any searching starts.</div>
<h2>2 &middot; The four tools it can reach for</h2>
<p class="sub">The assistant has no free access to anything. These four, and nothing else.</p>
<div class="cols">
<div class="card blocked">
<h3>Cube — the data translator <span class="badge b-blocked">Waiting on the historian</span></h3>
<p>Turns &ldquo;high level alarms last week&rdquo; into an exact query over the plant&rsquo;s
recorded history. The definitions that make an answer right — what counts as an alarm, what
&ldquo;last week&rdquo; means, what counts as a fill — are written down in files an engineer can
read and check, instead of being invented per question. It also keeps ready-made summaries so
common questions never hammer the live historian.</p>
<p>The assistant never writes database code itself. It fills in a request form; Cube does the
rest.</p>
<div class="tool">Reads: the <b>imh</b> plant historian, read-only. Definitions live in
<b>cube/model/</b> — alarms, process values, operations, equipment.</div>
</div>
<div class="card">
<h3>Document search <span class="badge b-none">No documents loaded yet</span></h3>
<p>Searches the controlled documents by meaning rather than keyword, so &ldquo;lift the
interlock&rdquo; finds the right procedure even when the document says &ldquo;interlock
override&rdquo;. Two rules are permanently on: withdrawn revisions are never returned, and every
result carries its document number, revision, date, page and section — a passage that cannot be
cited cannot be used.</p>
<div class="tool">Reads: document sections stored in <b>pg-ai</b></div>
</div>
<div class="card built">
<h3>The name list <span class="badge b-built">Built, loaded</span></h3>
<p>Every piece of equipment and every measurement point, with the everyday names operators
actually use. Deliberately a plain list rather than something the AI works out, so it behaves the
same way every time and can be corrected by editing one row.</p>
<div class="tool">Reads: the equipment and tag tables in <b>pg-ai</b></div>
</div>
<div class="card live">
<h3>The logbook <span class="badge b-live">Running now</span></h3>
<p>Not a source of answers — the record of them. Every question and every step it took is stored
so the assistant&rsquo;s behaviour can be audited and improved from evidence rather than
impressions.</p>
<div class="tool">Application: <b>Langfuse</b></div>
</div>
</div>
<h2>3 &middot; Where the knowledge comes from</h2>
<p class="sub">Two supply lines feed those tools. Neither is finished.</p>
<div class="cols">
<div class="card">
<h3>Documents in <span class="badge b-none">Not started</span></h3>
<p>Procedures, manuals, alarm rationalisation and design documents are read, split into sections,
and converted into a searchable form. Three habits matter: a numbered step sequence is never cut
in half; the document&rsquo;s type comes from the folder it was filed in, not from a guess; and
a person confirms the document number, revision and date before anything is stored. A wrong
revision on a procedure is a safety problem, not a tidiness one.</p>
<div class="tool">Application: <b>ai-ingest</b>, run by hand when documents change &rarr; stored
in <b>pg-ai</b>. Written and tested; no documents loaded onto the host yet.</div>
</div>
<div class="card blocked">
<h3>Plant history in <span class="badge b-blocked">Waiting on someone else</span></h3>
<p>The station&rsquo;s control system records levels, pump runs and alarms into the plant
historian. The assistant reads that history through Cube — read-only, never writing to it, and
never touching the control system itself.</p>
<div class="tool">Source: the <b>imh</b> historian. That server is still being built, so a
read-only login and the agreed table names are still outstanding.</div>
</div>
</div>
<div class="note"><b>Worth knowing:</b> until the real historian is available, the data lanes run on
stand-in figures. Every answer produced that way carries a warning label all the way to the
operator&rsquo;s screen, so it cannot be mistaken for a real plant number.</div>
<h2>4 &middot; What exists, and the order the rest gets built</h2>
<p class="sub">Each step ends in a check that must pass before the next begins — so that when an
answer comes out wrong, there is one place to look, not four.</p>
<div class="tblwrap">
<table>
<thead><tr><th>Step</th><th>What it delivers</th><th>Status</th><th>What it needs</th></tr></thead>
<tbody>
<tr><td class="ph">1</td><td><b>The store</b> — where documents, equipment names and ready-made summaries live</td><td><span class="badge b-live">Running now</span></td><td>Done. Live, checks passed.</td></tr>
<tr><td class="ph">2</td><td><b>The logbook</b> — recording of every question, put in early on purpose so every later experiment is traceable</td><td><span class="badge b-live">Running now</span></td><td>Done. Live.</td></tr>
<tr><td class="ph">3</td><td><b>The documents</b> — the real procedures and manuals, read in and searchable</td><td><span class="badge b-none">Next up</span></td><td>The documents themselves, and someone to confirm each one&rsquo;s revision and date. Needs nothing from the historian — which is why it goes next.</td></tr>
<tr><td class="ph">4</td><td><b>Access to plant history</b> — a read-only login to the historian</td><td><span class="badge b-blocked">Blocked</span></td><td>The historian server, a read-only login and agreed table names. <b>The only true blocker — start that conversation now, alongside step 3.</b></td></tr>
<tr><td class="ph">5</td><td><b>Cube</b> — the data translator, with every definition written down</td><td><span class="badge b-built">Built, not switched on</span></td><td>Step 4 — though it can be proven on stand-in data first. An engineer must independently confirm its first numbers before anyone trusts them.</td></tr>
<tr><td class="ph">6</td><td><b>The assistant itself</b> — the sorting step, the four lanes, the answer writer and the rulebook</td><td><span class="badge b-built">Built, not switched on</span></td><td>Steps 3 and 5, so that a wrong answer can only be the assistant&rsquo;s own fault.</td></tr>
<tr><td class="ph">7</td><td><b>The operator&rsquo;s screen</b> — the question box, the answer, the working</td><td><span class="badge b-built">Built, not switched on</span></td><td>Step 6, plus one network name record so control-room PCs can reach it — <b>ask for that early</b>, it depends on someone else and will not surface as a problem until the day it is tried.</td></tr>
<tr><td class="ph">8</td><td><b>The exam</b> — 62 engineer-checked questions run end to end and scored</td><td><span class="badge b-built">Written, not run</span></td><td>Everything above. Pass mark: 85% correct overall, 95% on the two dangerous kinds, and <b>zero</b> breaches of the rulebook.</td></tr>
</tbody>
</table>
</div>
<h2>5 &middot; The short version</h2>
<ul class="next">
<li><b>Live today:</b> the store and the logbook — the foundations, not yet anything an operator
would see.</li>
<li><b>Written and tested, waiting to be switched on:</b> the sorting step, all four lanes, the
answer writer, the rulebook, Cube and the operator&rsquo;s screen. The software exists; it has not
been put into service.</li>
<li><b>Not started:</b> loading the real documents. This is the nearest useful milestone — it needs
nothing from the historian, and it is what makes &ldquo;find me the procedure&rdquo; work, a
demonstration that stands on its own.</li>
<li><b>Needs other people, so ask today:</b> the read-only historian login, and the network name
record for the control room. Both take days of someone else&rsquo;s time and neither can be hurried
at the end.</li>
<li><b>Before any operator sees this:</b> what the assistant will and will not say must be reviewed
with an OT/safety representative.</li>
</ul>
<p class="foot">Sign-in, network routing and hosting are handled by platform services already running
on the demo host. They are deliberately left off this map — they protect the assistant, but they are
not part of how it answers a question.</p>
</div>
</body>
</html>