diff --git a/.gitignore b/.gitignore index ab097de..3eb9ec4 100644 --- a/.gitignore +++ b/.gitignore @@ -11,9 +11,12 @@ authelia.env pg-ai.env api.env -# Real document content lives on /datadisk/ai-docs on lin001 -docs/* -!docs/.gitkeep +# Real document content lives on /datadisk/ai-docs on lin001, never in Git. +# The folder itself was removed deliberately - an empty docs/ reads as "project +# documentation goes here", which is wrong: that is spec/ and status/. The rule +# stays as a safety net, so a controlled document dropped into a local docs/ +# cannot be committed by accident. +docs/ # Python __pycache__/ diff --git a/CLAUDE.md b/CLAUDE.md index 6404a3c..00f9957 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,8 +1,8 @@ # CLAUDE.md — rules to keep front of mind Plant Operations Assistant for the **Waterloo Road Pump Station (WRPS)**, deployed onto an -existing, live, shared Docker host. Full detail: `BUILD-AI-CONTAINERS.md` (the build spec) and -`YAU_Linux_Host_Onboarding.md` (the host brief). **Where the two conflict, the host brief wins.** +existing, live, shared Docker host. Full detail: `spec/BUILD-AI-CONTAINERS.md` (the build spec) and +`spec/YAU_Linux_Host_Onboarding.md` (the host brief). **Where the two conflict, the host brief wins.** ## The three lines this system does not cross diff --git a/README.md b/README.md index e4eb3df..833baf3 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ returning. A response that fails its contract is regenerated once, then errors. It is never returned. `pytest api/tests` exercises every rule above without an API key or a database, because that is the point of putting them in Python. -Full detail: [`BUILD-AI-CONTAINERS.md`](BUILD-AI-CONTAINERS.md) §2. +Full detail: [`BUILD-AI-CONTAINERS.md`](spec/BUILD-AI-CONTAINERS.md) §2. --- @@ -96,7 +96,7 @@ operator ──► Caddy ──► Authelia (AD + Duo) ──► ai-web ── Everything runs on `yau-sls-poc-lin001` (`10.0.0.17`), a **shared, live** Docker host that already runs 22 containers including `openplc-runtime` — the PLC for -this demo. See [`YAU_Linux_Host_Onboarding.md`](YAU_Linux_Host_Onboarding.md). +this demo. See [`YAU_Linux_Host_Onboarding.md`](spec/YAU_Linux_Host_Onboarding.md). **There is no replication job and no mirror table.** `imh` is already an isolated copy of the raw SCADA historian, so Cube queries it directly with a @@ -233,7 +233,7 @@ Two consequences worth knowing before you read a number off this system: history carries no equipment column, because CI Server's section tree stops at the station and the three pumps and has no wet well to put there. -Full detail in [`BUILD-AI-CONTAINERS.md`](BUILD-AI-CONTAINERS.md) Phase 4, +Full detail in [`BUILD-AI-CONTAINERS.md`](spec/BUILD-AI-CONTAINERS.md) Phase 4, "Resolved 2026-08-31". Eval cases `H26`, `H27` and `H31` cover them, and `H29` covers the retention limit. @@ -263,7 +263,7 @@ should reach the assistant at all. Read this before relying on it. It is an **IP allowlist on a flat network with no OT/IT boundary**: anything that can take `10.0.0.21` inherits unauthenticated access. It is a demo affordance, not a security control, and it is listed as -such in [`BUILD-AI-CONTAINERS.md`](BUILD-AI-CONTAINERS.md) §14. It also makes +such in [`BUILD-AI-CONTAINERS.md`](spec/BUILD-AI-CONTAINERS.md) §14. It also makes Langfuse traces anonymous — there is no longer a record of who asked what — and it puts the assistant out of browser reach over the VPN, so engineers need an SSH tunnel. `api.yokogawa.tech` is unchanged and still fully gated; Phase 9 @@ -316,7 +316,7 @@ password, so anyone who reaches the page can claim it. Rows are marked authenticated ones later. And **the two ingest paths must not be used on the same document** — files published through the UI stay in the inbox and `ai-ingest --all` cannot see them. Full list of divergences in -[`BUILD-AI-CONTAINERS.md`](BUILD-AI-CONTAINERS.md) §14. +[`BUILD-AI-CONTAINERS.md`](spec/BUILD-AI-CONTAINERS.md) §14. The design below is what §16 specifies, and remains the target. @@ -366,7 +366,7 @@ Then the manual steps: the `copy_headers` change on the `api.yokogawa.tech` Caddy block, the `^/docs/.*` Authelia rule **above** the general one, and `AI_DocPublishers` in AD with **direct** membership. -Design and gate: [`BUILD-AI-CONTAINERS.md`](BUILD-AI-CONTAINERS.md) §16 and +Design and gate: [`BUILD-AI-CONTAINERS.md`](spec/BUILD-AI-CONTAINERS.md) §16 and Phase 9. Two gate items matter most. A user who is authenticated but not a publisher must get a **403 from the API**, tested by calling `api.yokogawa.tech` directly — the button being hidden proves nothing. And after withdrawing a @@ -434,10 +434,17 @@ pytest api/tests # contracts, classifier rules, SQL allow-list. No netw ``` CLAUDE.md short rules — what Claude Code keeps front of mind -workflow-map.html the non-technical explainer — how a question becomes + +spec/ what we agreed to build — normative, durable + BUILD-AI-CONTAINERS.md the build spec + YAU_Linux_Host_Onboarding.md the host brief (reference; wins on conflict) + +status/ where it got to — snapshots, go stale, edited often + 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 -YAU_Linux_Host_Onboarding.md the host brief (reference; wins on conflict) + current-state.html what is actually running right now. Open it too + REQUESTS.md what is still needed from other people + compose/ deployed to ~/ai-compose.yml and ~/langfuse-compose.yml caddy/ai-routes.caddy blocks to paste into ~/Caddyfile authelia/access-rules.md the rule additions as text — never the real config @@ -449,7 +456,6 @@ ingest/ Docling → chunk → embed → pg-ai, plus the web/ React + Vite operator UI eval/ 62-case test set and the scorecard runner scripts/ deploy.sh, verify.sh -docs/ GITIGNORED — real content on /datadisk/ai-docs ``` --- @@ -457,7 +463,7 @@ docs/ GITIGNORED — real content on /datadisk/ai-docs ## Known shortcuts Deliberate, documented, and not to be shipped. Full list in -[`BUILD-AI-CONTAINERS.md`](BUILD-AI-CONTAINERS.md) §14. The ones that matter most: +[`BUILD-AI-CONTAINERS.md`](spec/BUILD-AI-CONTAINERS.md) §14. The ones that matter most: - Secrets in `0600` env files, not a vault - No OT/IT firewall boundary — one flat `10.0.0.0/24` PoC network diff --git a/docs/.gitkeep b/docs/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/BUILD-AI-CONTAINERS.md b/spec/BUILD-AI-CONTAINERS.md similarity index 99% rename from BUILD-AI-CONTAINERS.md rename to spec/BUILD-AI-CONTAINERS.md index 89d72fc..9e02da9 100644 --- a/BUILD-AI-CONTAINERS.md +++ b/spec/BUILD-AI-CONTAINERS.md @@ -2,7 +2,7 @@ > **Scope:** add new containers to an **existing, live Docker host**. No machines are being built. > -> **How to use:** keep this alongside `YAU_Linux_Host_Onboarding.md` in the project folder. That file +> **How to use:** keep this alongside `YAU_Linux_Host_Onboarding.md` in `spec/`. That file > describes the host and its rules; this file describes what we are adding. **Where the two conflict, > the host brief wins.** Work through the phases in order and pass each gate before proceeding. diff --git a/YAU_Linux_Host_Onboarding.md b/spec/YAU_Linux_Host_Onboarding.md similarity index 100% rename from YAU_Linux_Host_Onboarding.md rename to spec/YAU_Linux_Host_Onboarding.md diff --git a/REQUESTS.md b/status/REQUESTS.md similarity index 100% rename from REQUESTS.md rename to status/REQUESTS.md diff --git a/current-state.html b/status/current-state.html similarity index 100% rename from current-state.html rename to status/current-state.html diff --git a/workflow-map.html b/status/workflow-map.html similarity index 100% rename from workflow-map.html rename to status/workflow-map.html