RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/bbartling/open-fdd/diff

Two files, one repository

bbartling/open-fdd ships 2 formats across 6 indexed files. The question worth asking is whether the second one says anything the first does not.

CompareAGENTS.md ↔ Cursor rules
A · AGENTS.md · 636 wordsB · openfdd_agent_spec/AGENTS.md · 1113 words
What each file covers, counted
DimensionSharedOnly in AOnly in BOverlap
Sections0860%
Commands12033%
Section tags31343%

What each file covers

Sections

0 shared · 8 only in A · 6 only in B
  • − Agent Guide (container stack + external agents)
  • − Start session
  • − or: react (no fieldbus) / csv
  • − Safe scripts
  • − External agent workflow
  • − Product UI / FDD agent notes
  • − Low-RAM hosts (bensbench)
  • − Never
  • + Open-FDD agent workspace — orientation
  • + Product vs libraries
  • + AI agent quick rules (read first)
  • + Authority order
  • + Bootstrap reading order
  • + Skills

Commands

1 shared · 2 only in A · 0 only in B
  • − docker compose down -v
  • − docker volume prune
  •   docker build

Section tags

3 shared · 1 only in A · 3 only in B
  • − ui
  • + security
  • + dependencies
  • + monorepo
  •   code-style
  •   do-not
  •   agent-behaviour

Line diff

+98 added−72 removed22 unchanged18.3% identical
bbartling/open-fdd · AGENTS.md
@@ −1 @@
1# Agent Guide (container stack + external agents)
2 
3Open-FDD ships as a **container stack**: `openfdd-central`, `openfdd-web` (React),
4`openfdd-fieldbus`, `openfdd-mqtt`, plus optional `openfdd-mcp`. It does **not**
5ship an embedded AI chatbot. External orchestrators — Codex CLI, Cursor,
6OpenClaw, Claude Desktop, or any MCP host — connect via **JWT REST** and optional
7**`openfdd-mcp` stdio**.
8 
9| Layer | Responsibility |
10| --- | --- |
11| **central** | MQTTS ingest, Feather/Parquet historian, DataFusion SQL FDD + `/api/analytics/*`, REST + JWT (Rust image — no Python) |
12| **web** | React product UI (`frontend/web`) — sole product UI ([ADR-001](docs/architecture/adr-001-react-rust-modernization.md)) |
13| **fieldbus** | BACnet / Modbus / Haystack OT drivers |
14| **mqtt** | Mosquitto MQTTS broker |
15| **mcp** | Optional read-first stdio tools → central (`OPENFDD_API_BASE`) |
16 
17**Docs:** [Build recipes](docs/operations/build-recipes.md) · [External agents](docs/examples/external-agents.md) · [MCP README](mcp/README.md) · [ECM engineering (PyPI)](docs/ecm/README.md)
18 
19**Software-engineering agent OS:** [`openfdd_agent_spec/`](openfdd_agent_spec/) — architecture locks, skills, Milestone A.
 
20 
21**Active recovery / Vibe 21 twin program:** [`tools/open-fdd-vibe21-production/`](tools/open-fdd-vibe21-production/README.md) · capability ledger [`docs/migration/react-rust/capabilities.yaml`](docs/migration/react-rust/capabilities.yaml).
22 
23**PyPI (`open-fdd`):** ECM engineering + pandas oracle (`open_fdd.rules` / `analytics` / `reporting`) for **third-party tooling** outside the product app. Product FDD is DataFusion on GHCR.
24 
25Dual expression cookbooks (permanent): `docs/rules/cookbook/` (SQL + pandas).
 
 
 
 
 
 
 
 
 
 
26 
27## Start session
28 
29Unmerged UI is **not** on GHCR. Resolve newest published images by OCI
30`created` (`./scripts/ghcr_newest_by_created.py`), and never paste a Caddy
31URL until `./scripts/openfdd_demo_gate.sh` exits 0. See
32[`CONTAINER_AGENT.md`](openfdd_agent_spec/CONTAINER_AGENT.md).
 
 
33 
34```bash
35./scripts/openfdd_stack_up.sh react-ot # React SPA + mqtt + central + fieldbus
36# or: react (no fieldbus) / csv
37TOKEN="$(curl -s -X POST http://127.0.0.1:8080/api/auth/login \
38 -H 'Content-Type: application/json' \
39 -d '{"username":"admin","password":"'"$OPENFDD_ADMIN_PASSWORD"'"}' \
40 | jq -r '.token // .access_token')"
41```
42 
43Discover routes: `curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8080/api/agent/tools | jq '.tools | length'`
44 
45## Safe scripts
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46 
47```bash
48./scripts/openfdd_stack_pull.sh react-ot
49./scripts/openfdd_stack_up.sh react-ot
50./scripts/nightly-ot-bench/run_all.sh # pull sha-* + OT/API gates
51./scripts/openfdd_stack_up.sh csv
52```
53 
54## External agent workflow
55 
561. Stack healthy on LAN/VPN only — never expose on public internet.
572. JWT for admin/operator/viewer (see central auth env).
583. `openfdd-mcp` stdio outside the web UI, or REST `/api/agent/tools`.
594. Read-first; writes need `OPENFDD_MCP_ALLOW_WRITES=1` and `confirm:true`.
605. Never print secrets. BACnet writes need explicit human approval.
61 
62## Product UI / FDD agent notes
63 
64- **Overview plots:** plot Expanders default **open** so charts are not hidden behind carets (`OverviewPopulated`).
65- **Lab → FDD Plots:** `session_config` `confirm_min` (and rule params) apply to the series overlay (`sql_detail_session`). After **Update this rule**, Reports/FDD Plots must refetch on `RULES_UPDATED`.
66- **SCHED-1 occupancy:** treat numeric `0` / `0.0` / `false` **and** string `unoccupied` (and related tokens) as unoccupied — SQL + pandas cookbook stay aligned.
67- **Synthetic-59:** soak via `scripts/synthetic_59_*.py` under `reports/wattlab-parity/fixtures/synthetic_59/`. Do not greenwash `expected_faults.csv`. B100 dump-parity remains **paused**.
68- **Units:** FDD SQL is °F canonical. Metric CSVs convert at query (`unit_system=metric|si`). Lab sliders show °C when metric is selected; Run all rules after switching.
69- **Hourly append:** seed with `POST /api/csv/import/package`, then `POST /api/csv/import/package/append` (JWT, `confirm:true`). Custom appenders stay outside the repo.
70- **Overview layout:** full width beside sidebar (Streamlit-like); named Plotly PNG stems via `downloadFilename`; Lab rule menu A–Z; FDD series = required∪optional roles.
71- **Mech OAT bins:** status/cmd before amps; prefer web/weather OAT. Analytics envelopes: `scripts/synthetic_59_overview_analytics_soak.py`.
72 
73## Low-RAM hosts (bensbench)
 
 
 
 
 
 
 
 
74 
75- **Never** local `docker build` / heavy Rust compile for stack images. Ship via PR → GH Actions → GHCR `nightly` / `sha-*`.
76- Before pulling new images: prune unused/old digests first, then `./scripts/openfdd_stack_pull.sh …` and `./scripts/openfdd_stack_up.sh … --no-pull`.
77- Details: [`openfdd_agent_spec/CONTAINER_AGENT.md`](openfdd_agent_spec/CONTAINER_AGENT.md).
78 
79## Never
80 
81- delete `workspace/`
82- run `docker compose down -v`
83- run `docker volume prune`
84- print secrets or tokens
85- expose API on public internet
86- write BACnet without explicit human approval
87- embed vendor chat relays or model API keys in the stack
88- add Python to the product central/web request path
89- local stack image builds on low-RAM hosts (use GHCR)
90 
91See [docs/agent/index.md](docs/agent/index.md) for external-agent architecture.
92 
93For library/migration/PR missions (Milestone A), start at [openfdd_agent_spec/AGENTS.md](openfdd_agent_spec/AGENTS.md).
94 
bbartling/open-fdd · openfdd_agent_spec/AGENTS.md
@@ +1 @@
1# Open-FDD agent workspace — orientation
2 
3Plain Markdown on disk is the source of truth for **Cursor**, **Codex CLI**, and
4similar agents. Product code lives in `services/`, `sql_rules/`, `frontend/`,
5`mcp/`, `edge/`, `os/`. PyPI libraries live in `open_fdd/`. Orchestration lives in
6**`openfdd_agent_spec/`**.
 
7 
8**Primary agent prompt (paste into new sessions):** [`../AGENTS.md`](../AGENTS.md)
 
 
 
 
 
 
9 
10**Software-engineering mission:** [`MILESTONE_A.md`](MILESTONE_A.md)
11 
12**Ops / edge soak prompts:** [`../docs/agent/`](../docs/agent/) — GHCR bench, nightly
13retest. Do not confuse those with this engineering OS.
14 
15---
16 
17## Product vs libraries
18 
19| Layer | Owns |
20| --- | --- |
21| `services/` + `sql_rules/` + `frontend/web` | **Product:** central DataFusion SQL FDD + analytics, React SPA (`openfdd-web`), fieldbus, mqtt |
22| `open_fdd/` | **PyPI libraries** for third-party tooling: ECM + pandas oracle (`rules` / `analytics` / `reporting`) — not the product runtime |
23| `mcp/` | Optional read-first MCP → central |
24| `edge/`, `os/` | Future concepts — **never delete** |
25| `docs/rules/cookbook/` | Dual expression cookbooks (SQL + pandas) + parity matrix |
26| `tools/open-fdd-vibe21-production/` | Active recovery + Vibe 21 twin program |
27| `docs/migration/react-rust/capabilities.yaml` | Machine-readable capability ledger |
28| `openfdd_agent_spec/` | Agent law, Milestone A, skills, session log |
29| Playground vibe19/20 | External demos; consumers of PyPI |
30 
31**Naming (code truth):**
32 
33| Concept | Module / extra |
34| --- | --- |
35| Pandas oracle (PyPI) | `open_fdd.rules` (+ `open_fdd.analytics`) |
36| Pip extras | `oracle`, `analytics`, `reporting` (`vibe19` deprecated alias through 4.3) |
37| ECM math | `open_fdd.ecm_engineering` |
38| Shared contracts | `open_fdd.contracts` — Phase 2 target (not shipped) |
39 
40---
 
 
 
 
 
 
 
41 
42## AI agent quick rules (read first)
43 
441. Product FDD + Overview analytics = **DataFusion SQL** on GHCR. Never silent pandas fallback in central.
452. Pandas oracle stays forever on **PyPI** + cookbooks + vibe19 — never delete the pandas cookbook because production uses SQL.
463. Never delete the SQL cookbook because pandas remains the oracle.
474. **Product UI:** React SPA (`frontend/web` → `openfdd-web`, `compose.react.yml`) only. Overview = central `/api/analytics/*` (DataFusion) + client Plotly. Browser → central Rust `/api` only — **no Python in the product request path**.
485. **Internet-facing auth/UI hygiene:** Never put bench/dev secrets, credential file paths, default passwords, or JWT dumps on login or other product surfaces. Generic login errors only.
496. Test containers on **`OPENFDD_IMAGE_TAG=nightly`**, but **pin/run `sha-*`** per [`CONTAINER_AGENT.md`](CONTAINER_AGENT.md).
507. Playground images: `ghcr.io/bbartling/vibe19:develop`, `vibe20:develop` (external).
518. `edge/` and `os/` are future concepts — never delete.
529. Bounded PRs only — see [`PR_PROTOCOL.md`](PR_PROTOCOL.md).
5310. Prefer exact wheel install tests over editable-only validation for packaging PRs.
5411. Never trust a moving GHCR tag alone — resolve/pull immutable `sha-*`, recreate containers, then record the digest.
5512. Append [`SESSION_LOG.md`](SESSION_LOG.md) after non-trivial work.
5613. Update [`BUILD_CHECKPOINTS.md`](BUILD_CHECKPOINTS.md) when Milestone A or product capability status changes.
5714. CodeRabbit: fix actionable defects; reject suggestions that violate architecture.
5815. vibe21 = separate plan — not Milestone A.
5916. When blocked (secrets, permissions), finish non-blocked work and record the exact error.
6017. Bound each PR to its declared scope.
6118. **Active program:** [`tools/open-fdd-vibe21-production/`](../tools/open-fdd-vibe21-production/README.md) Master Loop. Keep [`capabilities.yaml`](../docs/migration/react-rust/capabilities.yaml) honest.
6219. For `frontend/web` work: follow [`openfdd-react-spa`](skills/openfdd-react-spa/SKILL.md).
6320. Central product image is **debian + Rust binaries only** — no Python. WattLab AFDD zip export is optional offline tooling (`OPENFDD_WATTLAB_PYTHON_EXPORT=1`).
6421. **Site lock:** Overview + sidebar Active site are the only editors of `?site=`. `SectionTabs` (and sidebar App pages) must `navigate` with `hrefWithSession` so `site` + `eq` survive. FDD / RCx / Results / WattLab show a locked `zip:BUILDING_*` caption — no Building `<Select>`.
6522. **FDD Plots = vibe19 `rule_result_chart`:** auto-load series; last y-axis title is `fault`; `confirmed_fault` is the last trace on the bottom domain (`domain[0] < 0.4`). A successful rule run with an empty overlay is a bug (fail the test), not a soft banner.
6623. **RCx catalog freeze:** every `REQUIRED_RCX_PRESET_IDS` id must stay listed. Family picker order is `RCX_FAMILY_ORDER` (Zones first) plus empty Heat pump / Weather placeholders. Auto-run the selected preset when site+preset are set.
6724. **Actions housekeeping:** default `GET /api/actions?limit=10`; `DELETE /api/actions/:id` and `DELETE /api/actions`; JSONL prune cap 50.
6825. **Section radios:** left, horizontal, **after** hero + Equipment on Overview (never inside `.oracle-hero`, never centered in the logo column). Other pages: same left radio row at the top of the page body.
6926. **Overview plot Expanders** default **open** — do not hide motor / mech / econ / BAS plot sections behind carets (`Expander` unmounts children when closed).
7027. **FDD Plots series overlay** honors Lab/`session_config` `confirm_min` (and typed rule params); source may be `sql_detail_session`. After Update-this-rule, listen for `RULES_UPDATED` and refetch results + series.
7128. **SCHED-1 portable occupancy:** numeric/boolean falsey (`0`, `0.0`, `false`) **and** string `unoccupied` (plus related tokens) — keep SQL (`sched1_unoccupied_runtime.sql`) and pandas `sched1` aligned.
7229. **Low-RAM / bensbench:** never local stack `docker build`; prune old images before pull; wait for GHCR publish then pull `sha-*` / `nightly`. Synthetic-59 soaks use `scripts/synthetic_59_*.py`; B100 dump-parity stays paused; never edit goldens to hide misses.
7330. **Plot PNG downloads:** `PlotlyHost` must pass `toImageButtonOptions.filename` (Overview/Reports). Default Plotly `newplot.png` is a regression.
7431. **Full-width UI:** `.app-content` / `.overview-populated` stretch (`max-width: none`) like Streamlit — do not reintroduce a rem content cap on Overview plots.
7532. **Rule Lab menu:** `RuleTuningPanel` sorts visible rules A–Z by `rule_id` (registry YAML order is engine priority only).
7633. **FDD Plots series roles:** `series_response` SELECT = `required_roles ∪ optional_roles` (SV-*/PID-HUNT keep required empty). Soft-empty when none present on equipment.
7734. **Mech cooling OAT bins:** status/cmd proof **before** amps (never OR amps when status exists); prefer web/`dry_bulb_f`/weather OAT over site-averaged AHU BAS `oa_t`. Version `mechanical-cooling-oat-bins-v2`.
7835. **Synthetic analytics soak:** `scripts/synthetic_59_overview_analytics_soak.py` asserts runtime + mech bin envelopes (separate from FDD pair scores).
7936. **Metric CSVs:** store as-uploaded; convert temperature roles C→F at run-rules/historian query. Do not duplicate 59 SQL files. Sliders display user units.
8037. **Package append:** `POST /api/csv/import/package/append` is the IoT hourly path (JWT + confirm). Vendor pullers are out-of-repo.
81 
82---
 
 
 
 
 
83 
84## Authority order
85 
861. Root [`AGENTS.md`](../AGENTS.md)
872. Machine manifests: [`ownership.yaml`](ownership.yaml), [`capabilities.yaml`](../docs/migration/react-rust/capabilities.yaml)
883. Current phase docs under [`tools/open-fdd-vibe21-production/`](../tools/open-fdd-vibe21-production/)
894. Generated OpenAPI / MCP / rule catalogs
905. Workflow guides and examples
91 
92Nested instructions may specialize but never contradict a higher authority.
93 
94## Bootstrap reading order
 
 
 
 
 
 
 
95 
961. [`../AGENTS.md`](../AGENTS.md)
972. This file
983. [`ARCHITECTURE.md`](ARCHITECTURE.md) + [`ownership.yaml`](ownership.yaml)
994. [`BUILD_CHECKPOINTS.md`](BUILD_CHECKPOINTS.md)
1005. [`tools/open-fdd-vibe21-production/prompts/MASTER_PRODUCTION_LOOP.md`](../tools/open-fdd-vibe21-production/prompts/MASTER_PRODUCTION_LOOP.md)
1016. [`MILESTONE_A.md`](MILESTONE_A.md) if executing Milestone A
1027. [`PR_PROTOCOL.md`](PR_PROTOCOL.md) before opening a PR
1038. Matching skill
1049. Cookbooks under `docs/rules/cookbook/`
105 
106---
 
 
107 
108## Skills
109 
110| Skill | Use when |
111| --- | --- |
112| [`openfdd-architecture`](skills/openfdd-architecture/SKILL.md) | Ownership / engine boundaries |
113| [`openfdd-react-spa`](skills/openfdd-react-spa/SKILL.md) | Product SPA (`frontend/web`) |
114| [`openfdd-sql-fdd`](skills/openfdd-sql-fdd/SKILL.md) | DataFusion SQL rules |
115| [`openfdd-pypi-oracle`](skills/openfdd-pypi-oracle/SKILL.md) | PyPI pandas oracle packaging |
116| [`openfdd-cookbook-parity`](skills/openfdd-cookbook-parity/SKILL.md) | Dual cookbook honesty |
117| [`openfdd-stack-ghcr`](skills/openfdd-stack-ghcr/SKILL.md) | GHCR pull / recreate |
118| [`openfdd-ecm-engineering`](skills/openfdd-ecm-engineering/SKILL.md) | ECM math library |
119| [`openfdd-milestone-a-pr`](skills/openfdd-milestone-a-pr/SKILL.md) | Milestone A PR loop |
 
 
 
120 
@@ −1 +1 @@
1−# Agent Guide (container stack + external agents)
1+# Open-FDD agent workspace — orientation
22  
3−Open-FDD ships as a **container stack**: `openfdd-central`, `openfdd-web` (React),
4−`openfdd-fieldbus`, `openfdd-mqtt`, plus optional `openfdd-mcp`. It does **not**
5−ship an embedded AI chatbot. External orchestrators — Codex CLI, Cursor,
6−OpenClaw, Claude Desktop, or any MCP host — connect via **JWT REST** and optional
7−**`openfdd-mcp` stdio**.
3+Plain Markdown on disk is the source of truth for **Cursor**, **Codex CLI**, and
4+similar agents. Product code lives in `services/`, `sql_rules/`, `frontend/`,
5+`mcp/`, `edge/`, `os/`. PyPI libraries live in `open_fdd/`. Orchestration lives in
6+**`openfdd_agent_spec/`**.
87  
9−| Layer | Responsibility |
10−| --- | --- |
11−| **central** | MQTTS ingest, Feather/Parquet historian, DataFusion SQL FDD + `/api/analytics/*`, REST + JWT (Rust image — no Python) |
12−| **web** | React product UI (`frontend/web`) — sole product UI ([ADR-001](docs/architecture/adr-001-react-rust-modernization.md)) |
13−| **fieldbus** | BACnet / Modbus / Haystack OT drivers |
14−| **mqtt** | Mosquitto MQTTS broker |
15−| **mcp** | Optional read-first stdio tools → central (`OPENFDD_API_BASE`) |
8+**Primary agent prompt (paste into new sessions):** [`../AGENTS.md`](../AGENTS.md)
169  
17−**Docs:** [Build recipes](docs/operations/build-recipes.md) · [External agents](docs/examples/external-agents.md) · [MCP README](mcp/README.md) · [ECM engineering (PyPI)](docs/ecm/README.md)
10+**Software-engineering mission:** [`MILESTONE_A.md`](MILESTONE_A.md)
1811  
19−**Software-engineering agent OS:** [`openfdd_agent_spec/`](openfdd_agent_spec/) — architecture locks, skills, Milestone A.
12+**Ops / edge soak prompts:** [`../docs/agent/`](../docs/agent/) — GHCR bench, nightly
13+retest. Do not confuse those with this engineering OS.
2014  
21−**Active recovery / Vibe 21 twin program:** [`tools/open-fdd-vibe21-production/`](tools/open-fdd-vibe21-production/README.md) · capability ledger [`docs/migration/react-rust/capabilities.yaml`](docs/migration/react-rust/capabilities.yaml).
15+---
2216  
23−**PyPI (`open-fdd`):** ECM engineering + pandas oracle (`open_fdd.rules` / `analytics` / `reporting`) for **third-party tooling** outside the product app. Product FDD is DataFusion on GHCR.
17+## Product vs libraries
2418  
25−Dual expression cookbooks (permanent): `docs/rules/cookbook/` (SQL + pandas).
19+| Layer | Owns |
20+| --- | --- |
21+| `services/` + `sql_rules/` + `frontend/web` | **Product:** central DataFusion SQL FDD + analytics, React SPA (`openfdd-web`), fieldbus, mqtt |
22+| `open_fdd/` | **PyPI libraries** for third-party tooling: ECM + pandas oracle (`rules` / `analytics` / `reporting`) — not the product runtime |
23+| `mcp/` | Optional read-first MCP → central |
24+| `edge/`, `os/` | Future concepts — **never delete** |
25+| `docs/rules/cookbook/` | Dual expression cookbooks (SQL + pandas) + parity matrix |
26+| `tools/open-fdd-vibe21-production/` | Active recovery + Vibe 21 twin program |
27+| `docs/migration/react-rust/capabilities.yaml` | Machine-readable capability ledger |
28+| `openfdd_agent_spec/` | Agent law, Milestone A, skills, session log |
29+| Playground vibe19/20 | External demos; consumers of PyPI |
2630  
27−## Start session
31+**Naming (code truth):**
2832  
29−Unmerged UI is **not** on GHCR. Resolve newest published images by OCI
30−`created` (`./scripts/ghcr_newest_by_created.py`), and never paste a Caddy
31−URL until `./scripts/openfdd_demo_gate.sh` exits 0. See
32−[`CONTAINER_AGENT.md`](openfdd_agent_spec/CONTAINER_AGENT.md).
33+| Concept | Module / extra |
34+| --- | --- |
35+| Pandas oracle (PyPI) | `open_fdd.rules` (+ `open_fdd.analytics`) |
36+| Pip extras | `oracle`, `analytics`, `reporting` (`vibe19` deprecated alias through 4.3) |
37+| ECM math | `open_fdd.ecm_engineering` |
38+| Shared contracts | `open_fdd.contracts` — Phase 2 target (not shipped) |
3339  
34−```bash
35−./scripts/openfdd_stack_up.sh react-ot # React SPA + mqtt + central + fieldbus
36−# or: react (no fieldbus) / csv
37−TOKEN="$(curl -s -X POST http://127.0.0.1:8080/api/auth/login \
38− -H 'Content-Type: application/json' \
39− -d '{"username":"admin","password":"'"$OPENFDD_ADMIN_PASSWORD"'"}' \
40− | jq -r '.token // .access_token')"
41−```
40+---
4241  
43−Discover routes: `curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8080/api/agent/tools | jq '.tools | length'`
42+## AI agent quick rules (read first)
4443  
45−## Safe scripts
44+1. Product FDD + Overview analytics = **DataFusion SQL** on GHCR. Never silent pandas fallback in central.
45+2. Pandas oracle stays forever on **PyPI** + cookbooks + vibe19 — never delete the pandas cookbook because production uses SQL.
46+3. Never delete the SQL cookbook because pandas remains the oracle.
47+4. **Product UI:** React SPA (`frontend/web` → `openfdd-web`, `compose.react.yml`) only. Overview = central `/api/analytics/*` (DataFusion) + client Plotly. Browser → central Rust `/api` only — **no Python in the product request path**.
48+5. **Internet-facing auth/UI hygiene:** Never put bench/dev secrets, credential file paths, default passwords, or JWT dumps on login or other product surfaces. Generic login errors only.
49+6. Test containers on **`OPENFDD_IMAGE_TAG=nightly`**, but **pin/run `sha-*`** per [`CONTAINER_AGENT.md`](CONTAINER_AGENT.md).
50+7. Playground images: `ghcr.io/bbartling/vibe19:develop`, `vibe20:develop` (external).
51+8. `edge/` and `os/` are future concepts — never delete.
52+9. Bounded PRs only — see [`PR_PROTOCOL.md`](PR_PROTOCOL.md).
53+10. Prefer exact wheel install tests over editable-only validation for packaging PRs.
54+11. Never trust a moving GHCR tag alone — resolve/pull immutable `sha-*`, recreate containers, then record the digest.
55+12. Append [`SESSION_LOG.md`](SESSION_LOG.md) after non-trivial work.
56+13. Update [`BUILD_CHECKPOINTS.md`](BUILD_CHECKPOINTS.md) when Milestone A or product capability status changes.
57+14. CodeRabbit: fix actionable defects; reject suggestions that violate architecture.
58+15. vibe21 = separate plan — not Milestone A.
59+16. When blocked (secrets, permissions), finish non-blocked work and record the exact error.
60+17. Bound each PR to its declared scope.
61+18. **Active program:** [`tools/open-fdd-vibe21-production/`](../tools/open-fdd-vibe21-production/README.md) Master Loop. Keep [`capabilities.yaml`](../docs/migration/react-rust/capabilities.yaml) honest.
62+19. For `frontend/web` work: follow [`openfdd-react-spa`](skills/openfdd-react-spa/SKILL.md).
63+20. Central product image is **debian + Rust binaries only** — no Python. WattLab AFDD zip export is optional offline tooling (`OPENFDD_WATTLAB_PYTHON_EXPORT=1`).
64+21. **Site lock:** Overview + sidebar Active site are the only editors of `?site=`. `SectionTabs` (and sidebar App pages) must `navigate` with `hrefWithSession` so `site` + `eq` survive. FDD / RCx / Results / WattLab show a locked `zip:BUILDING_*` caption — no Building `<Select>`.
65+22. **FDD Plots = vibe19 `rule_result_chart`:** auto-load series; last y-axis title is `fault`; `confirmed_fault` is the last trace on the bottom domain (`domain[0] < 0.4`). A successful rule run with an empty overlay is a bug (fail the test), not a soft banner.
66+23. **RCx catalog freeze:** every `REQUIRED_RCX_PRESET_IDS` id must stay listed. Family picker order is `RCX_FAMILY_ORDER` (Zones first) plus empty Heat pump / Weather placeholders. Auto-run the selected preset when site+preset are set.
67+24. **Actions housekeeping:** default `GET /api/actions?limit=10`; `DELETE /api/actions/:id` and `DELETE /api/actions`; JSONL prune cap 50.
68+25. **Section radios:** left, horizontal, **after** hero + Equipment on Overview (never inside `.oracle-hero`, never centered in the logo column). Other pages: same left radio row at the top of the page body.
69+26. **Overview plot Expanders** default **open** — do not hide motor / mech / econ / BAS plot sections behind carets (`Expander` unmounts children when closed).
70+27. **FDD Plots series overlay** honors Lab/`session_config` `confirm_min` (and typed rule params); source may be `sql_detail_session`. After Update-this-rule, listen for `RULES_UPDATED` and refetch results + series.
71+28. **SCHED-1 portable occupancy:** numeric/boolean falsey (`0`, `0.0`, `false`) **and** string `unoccupied` (plus related tokens) — keep SQL (`sched1_unoccupied_runtime.sql`) and pandas `sched1` aligned.
72+29. **Low-RAM / bensbench:** never local stack `docker build`; prune old images before pull; wait for GHCR publish then pull `sha-*` / `nightly`. Synthetic-59 soaks use `scripts/synthetic_59_*.py`; B100 dump-parity stays paused; never edit goldens to hide misses.
73+30. **Plot PNG downloads:** `PlotlyHost` must pass `toImageButtonOptions.filename` (Overview/Reports). Default Plotly `newplot.png` is a regression.
74+31. **Full-width UI:** `.app-content` / `.overview-populated` stretch (`max-width: none`) like Streamlit — do not reintroduce a rem content cap on Overview plots.
75+32. **Rule Lab menu:** `RuleTuningPanel` sorts visible rules A–Z by `rule_id` (registry YAML order is engine priority only).
76+33. **FDD Plots series roles:** `series_response` SELECT = `required_roles ∪ optional_roles` (SV-*/PID-HUNT keep required empty). Soft-empty when none present on equipment.
77+34. **Mech cooling OAT bins:** status/cmd proof **before** amps (never OR amps when status exists); prefer web/`dry_bulb_f`/weather OAT over site-averaged AHU BAS `oa_t`. Version `mechanical-cooling-oat-bins-v2`.
78+35. **Synthetic analytics soak:** `scripts/synthetic_59_overview_analytics_soak.py` asserts runtime + mech bin envelopes (separate from FDD pair scores).
79+36. **Metric CSVs:** store as-uploaded; convert temperature roles C→F at run-rules/historian query. Do not duplicate 59 SQL files. Sliders display user units.
80+37. **Package append:** `POST /api/csv/import/package/append` is the IoT hourly path (JWT + confirm). Vendor pullers are out-of-repo.
4681  
47−```bash
48−./scripts/openfdd_stack_pull.sh react-ot
49−./scripts/openfdd_stack_up.sh react-ot
50−./scripts/nightly-ot-bench/run_all.sh # pull sha-* + OT/API gates
51−./scripts/openfdd_stack_up.sh csv
52−```
82+---
5383  
54−## External agent workflow
84+## Authority order
5585  
56−1. Stack healthy on LAN/VPN only — never expose on public internet.
57−2. JWT for admin/operator/viewer (see central auth env).
58−3. `openfdd-mcp` stdio outside the web UI, or REST `/api/agent/tools`.
59−4. Read-first; writes need `OPENFDD_MCP_ALLOW_WRITES=1` and `confirm:true`.
60−5. Never print secrets. BACnet writes need explicit human approval.
86+1. Root [`AGENTS.md`](../AGENTS.md)
87+2. Machine manifests: [`ownership.yaml`](ownership.yaml), [`capabilities.yaml`](../docs/migration/react-rust/capabilities.yaml)
88+3. Current phase docs under [`tools/open-fdd-vibe21-production/`](../tools/open-fdd-vibe21-production/)
89+4. Generated OpenAPI / MCP / rule catalogs
90+5. Workflow guides and examples
6191  
62−## Product UI / FDD agent notes
92+Nested instructions may specialize but never contradict a higher authority.
6393  
64−- **Overview plots:** plot Expanders default **open** so charts are not hidden behind carets (`OverviewPopulated`).
65−- **Lab → FDD Plots:** `session_config` `confirm_min` (and rule params) apply to the series overlay (`sql_detail_session`). After **Update this rule**, Reports/FDD Plots must refetch on `RULES_UPDATED`.
66−- **SCHED-1 occupancy:** treat numeric `0` / `0.0` / `false` **and** string `unoccupied` (and related tokens) as unoccupied — SQL + pandas cookbook stay aligned.
67−- **Synthetic-59:** soak via `scripts/synthetic_59_*.py` under `reports/wattlab-parity/fixtures/synthetic_59/`. Do not greenwash `expected_faults.csv`. B100 dump-parity remains **paused**.
68−- **Units:** FDD SQL is °F canonical. Metric CSVs convert at query (`unit_system=metric|si`). Lab sliders show °C when metric is selected; Run all rules after switching.
69−- **Hourly append:** seed with `POST /api/csv/import/package`, then `POST /api/csv/import/package/append` (JWT, `confirm:true`). Custom appenders stay outside the repo.
70−- **Overview layout:** full width beside sidebar (Streamlit-like); named Plotly PNG stems via `downloadFilename`; Lab rule menu A–Z; FDD series = required∪optional roles.
71−- **Mech OAT bins:** status/cmd before amps; prefer web/weather OAT. Analytics envelopes: `scripts/synthetic_59_overview_analytics_soak.py`.
94+## Bootstrap reading order
7295  
73−## Low-RAM hosts (bensbench)
96+1. [`../AGENTS.md`](../AGENTS.md)
97+2. This file
98+3. [`ARCHITECTURE.md`](ARCHITECTURE.md) + [`ownership.yaml`](ownership.yaml)
99+4. [`BUILD_CHECKPOINTS.md`](BUILD_CHECKPOINTS.md)
100+5. [`tools/open-fdd-vibe21-production/prompts/MASTER_PRODUCTION_LOOP.md`](../tools/open-fdd-vibe21-production/prompts/MASTER_PRODUCTION_LOOP.md)
101+6. [`MILESTONE_A.md`](MILESTONE_A.md) if executing Milestone A
102+7. [`PR_PROTOCOL.md`](PR_PROTOCOL.md) before opening a PR
103+8. Matching skill
104+9. Cookbooks under `docs/rules/cookbook/`
74105  
75−- **Never** local `docker build` / heavy Rust compile for stack images. Ship via PR → GH Actions → GHCR `nightly` / `sha-*`.
76−- Before pulling new images: prune unused/old digests first, then `./scripts/openfdd_stack_pull.sh …` and `./scripts/openfdd_stack_up.sh … --no-pull`.
77−- Details: [`openfdd_agent_spec/CONTAINER_AGENT.md`](openfdd_agent_spec/CONTAINER_AGENT.md).
106+---
78107  
79−## Never
108+## Skills
80109  
81−- delete `workspace/`
82−- run `docker compose down -v`
83−- run `docker volume prune`
84−- print secrets or tokens
85−- expose API on public internet
86−- write BACnet without explicit human approval
87−- embed vendor chat relays or model API keys in the stack
88−- add Python to the product central/web request path
89−- local stack image builds on low-RAM hosts (use GHCR)
90− 
91−See [docs/agent/index.md](docs/agent/index.md) for external-agent architecture.
92− 
93−For library/migration/PR missions (Milestone A), start at [openfdd_agent_spec/AGENTS.md](openfdd_agent_spec/AGENTS.md).
110+| Skill | Use when |
111+| --- | --- |
112+| [`openfdd-architecture`](skills/openfdd-architecture/SKILL.md) | Ownership / engine boundaries |
113+| [`openfdd-react-spa`](skills/openfdd-react-spa/SKILL.md) | Product SPA (`frontend/web`) |
114+| [`openfdd-sql-fdd`](skills/openfdd-sql-fdd/SKILL.md) | DataFusion SQL rules |
115+| [`openfdd-pypi-oracle`](skills/openfdd-pypi-oracle/SKILL.md) | PyPI pandas oracle packaging |
116+| [`openfdd-cookbook-parity`](skills/openfdd-cookbook-parity/SKILL.md) | Dual cookbook honesty |
117+| [`openfdd-stack-ghcr`](skills/openfdd-stack-ghcr/SKILL.md) | GHCR pull / recreate |
118+| [`openfdd-ecm-engineering`](skills/openfdd-ecm-engineering/SKILL.md) | ECM math library |
119+| [`openfdd-milestone-a-pr`](skills/openfdd-milestone-a-pr/SKILL.md) | Milestone A PR loop |
94120  

Also from Kynth Studios

Built for the same person as RuleStack

ToolDrift

What the AI coding tools changed last night

tooldrift.kynth.studio

StillShipping

Which agent tools have stopped shipping

stillshipping.kynth.studio

BlockDex

Search inside every shadcn registry

blockdex.kynth.studio

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack