From 60fa16462629112222ee964fb448b14d71dd3b50 Mon Sep 17 00:00:00 2001 From: Raphael Maenle Date: Tue, 9 Jun 2026 19:35:43 +0200 Subject: [PATCH] docs: chapters 02 + 03 of the guided tour (Part 1 complete) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 02 — The cast of characters: equipment, EAP, MES, fab planner, AMHS, operator. Who initiates which conversation, why the equipment is the passive side of HSMS by convention, how the AMHS handshake is out-of-band relative to SECS. Cross-references the relevant namespace and test files for each actor. 03 — Vocabulary + a wafer's journey: follows one 300 mm wafer end-to-end through a fab and labels every SECS message and acronym that fires. Introduces SVID / DVID / ECID / CEID / RPTID / ALID / PPID / MDLN / SOFTREV / HCACK / ALCD / OFLACK / CAACK / SMACK / etc. in context rather than as a list. Includes one-screen reference tables for the remaining acknowledge codes, T-timers in all four contexts (HSMS / SECS-I / E84 / E30 communication state), and a stream-by-stream summary. Part 1 (Foundations) of the guided tour is now complete — a reader who reads chapters 01–03 can describe the protocol stack, identify the actors, and recognise every acronym they'll meet in Part 2. Co-Authored-By: Claude Opus 4.7 --- docs/02_the_cast.md | 417 +++++++++++++++ docs/03_vocabulary_and_a_wafers_journey.md | 592 +++++++++++++++++++++ ARCHITECTURE.md => docs/ARCHITECTURE.md | 0 BENCHMARKS.md => docs/BENCHMARKS.md | 0 COMPLIANCE.md => docs/COMPLIANCE.md | 0 FAQ.md => docs/FAQ.md | 0 GLOSSARY.md => docs/GLOSSARY.md | 0 INTEGRATION.md => docs/INTEGRATION.md | 0 MES_INTEROP.md => docs/MES_INTEROP.md | 0 PROOFS.md => docs/PROOFS.md | 0 SECURITY.md => docs/SECURITY.md | 0 VERIFICATION.md => docs/VERIFICATION.md | 0 12 files changed, 1009 insertions(+) create mode 100644 docs/02_the_cast.md create mode 100644 docs/03_vocabulary_and_a_wafers_journey.md rename ARCHITECTURE.md => docs/ARCHITECTURE.md (100%) rename BENCHMARKS.md => docs/BENCHMARKS.md (100%) rename COMPLIANCE.md => docs/COMPLIANCE.md (100%) rename FAQ.md => docs/FAQ.md (100%) rename GLOSSARY.md => docs/GLOSSARY.md (100%) rename INTEGRATION.md => docs/INTEGRATION.md (100%) rename MES_INTEROP.md => docs/MES_INTEROP.md (100%) rename PROOFS.md => docs/PROOFS.md (100%) rename SECURITY.md => docs/SECURITY.md (100%) rename VERIFICATION.md => docs/VERIFICATION.md (100%) diff --git a/docs/02_the_cast.md b/docs/02_the_cast.md new file mode 100644 index 0000000..4c22db5 --- /dev/null +++ b/docs/02_the_cast.md @@ -0,0 +1,417 @@ +# 02 — The cast of characters + +← [01 What is SECS/GEM?](01_what_is_secs_gem.md) | [Back to index](00_index.md) | Next: [03 Vocabulary + a wafer's journey](03_vocabulary_and_a_wafers_journey.md) → + +Chapter [01](01_what_is_secs_gem.md) explained that SECS/GEM is the +protocol a fab uses to make ~100 tools talk to a central MES. That +description hid a lot of structure. In reality, there are at least +**six distinct actors** in a typical fab automation stack — six +roles, each implemented by different software (often by different +vendors), each with its own concerns. + +This chapter introduces them all, draws who-talks-to-whom, and +locates each one in this codebase. After this you'll be able to read +any SECS conversation and know which actor is initiating, which is +responding, and why. + +--- + +## The six actors + +``` + ┌──────────────────┐ + │ Fab planner │ "make 100 wafers + │ (MES upper) │ of recipe R by + └────────┬─────────┘ Friday" + │ + recipes, lot │ yields, KPIs, + assignments, │ alarms, status + process programs │ + ▼ + ┌──────────────────┐ + │ MES (the host) │ per-step orchestration + └────────┬─────────┘ + │ + SECS/GEM │ SECS/GEM + S2F41 RCMD, │ S6F11 events, + S7F3 PP send, │ S5F1 alarms, + S2F33 reports, │ S1F4 status + … │ … + ▼ + ┌──────────────────┐ + │ EAP / equipment automation program │ + │ (vendor application layer) │ + ├──────────────────────────────────────────┤ + │ THIS CODEBASE — the SECS/GEM runtime │ + │ secsgem::gem / secsgem::hsms / … │ + └────────┬─────────────────────────────────┘ + │ + PLC / sensor / recipe-engine APIs (tool-specific) + │ + ▼ + ┌──────────────────┐ + │ Equipment │ the physical tool: + │ (the tool) │ chambers, robots, + └────────┬─────────┘ sensors, recipes + │ + E84 8-line │ (carrier moves, no SECS bytes) + parallel I/O │ + ▼ + ┌──────────────────┐ + │ AMHS │ robot rails / OHT + │ (the carriers) │ that move FOUPs + └──────────────────┘ + + ←───── Operator ──────→ panel buttons, + recipe overrides, + Online/Offline/Local/Remote +``` + +Read the diagram top-down: a fab planner schedules work, the MES +dispatches it tool by tool, each tool's EAP receives commands over +SECS/GEM, the EAP drives the actual hardware, the AMHS robots feed +carriers in and out. An operator can intervene at any layer. + +Each actor has a section below. + +--- + +## 1. Equipment — the tool itself + +**What it is.** A physical processing tool — a chemical-vapor +deposition (CVD) chamber, a plasma etcher, a wafer prober, a +photolithography stepper, an ion implanter, an inspection +microscope. Anywhere from one chamber the size of a microwave to a +full lithography cluster the size of a small bus. + +**What it does in SECS/GEM terms.** + +- **Reports state** — its current control state (Equipment Offline, + Online Remote, …), its processing state (IDLE, EXECUTING, …), its + carrier slots, its current recipe. +- **Emits events** — when something happens worth recording + (processing started, wafer processed, alarm raised, recipe + completed), it fires an `S6F11` to the host. +- **Accepts commands** — START, STOP, ABORT, PAUSE, CHANGE-RECIPE, + CARRIER-PROCEED, etc., delivered as `S2F41` Host Commands. +- **Stores its data dictionary** — every Status Variable (SVID), + Equipment Constant (ECID), Data Variable (DVID), Collection Event + (CEID), Alarm (ALID), and Process Program (PPID) it supports. +- **Manages its own physical safety** — it can refuse a host command + if the requested action would damage hardware, and it can raise + alarms autonomously. + +**In SECS/GEM, the equipment is almost always the "passive" side of +the connection** — it binds a TCP port and waits for the host to +connect, rather than the other way around. This codebase reflects +that: `apps/secs_server.cpp` is the equipment, and it listens. + +**Where it lives in this codebase.** + +- The equipment role's main binary: [`apps/secs_server.cpp`](../apps/secs_server.cpp). +- The data dictionary: [`include/secsgem/gem/data_model.hpp`](../include/secsgem/gem/data_model.hpp) + defines `EquipmentDataModel`, which composes every per-domain + store (SVIDs, ECIDs, CEIDs, alarms, carriers, substrates, recipes, + spool, …). +- A worked example with sensor simulation, recipe runner, and alarm + monitoring: [`examples/pvd_tool/main.cpp`](../examples/pvd_tool/main.cpp). +- Tests covering equipment behaviour: [`tests/test_data_model.cpp`](../tests/test_data_model.cpp), + [`tests/test_control_state.cpp`](../tests/test_control_state.cpp), + [`tests/test_host_handler.cpp`](../tests/test_host_handler.cpp). + +--- + +## 2. EAP — the equipment automation program + +**What it is.** The vendor-written software layer that sits on top +of the SECS/GEM runtime and *makes the tool actually do things*. +The EAP is the glue between: + +- The SECS/GEM library (this codebase), +- The tool's PLCs / sensors / recipe engine / robot controllers, +- The tool vendor's domain logic. + +Every tool vendor ships their own EAP. Two CVD tools from different +vendors both speak GEM, but their EAPs are entirely different +codebases doing entirely different things internally. + +**Why it's a separate role.** The SECS/GEM standards spell out +*what* messages mean — "S2F41 with RCMD=START must initiate +processing on the currently loaded recipe." They don't spell out +*how* a specific CVD tool initiates processing on its specific +hardware. The EAP is the layer that resolves that. + +In particular: + +- When `S2F41 RCMD=START` arrives, the EAP decides whether the tool + is in a state to start (chamber pressure low enough? robot at + home position? recipe loaded?), and if so, calls the tool's + proprietary recipe engine to begin the cycle. +- When a sensor reads a temperature change, the EAP decides whether + to update an SVID, fire a CEID, or raise an alarm — and the + per-tool rules for that aren't in any SEMI standard. +- When a `S7F3` arrives with a new recipe payload, the EAP decides + how to validate the recipe against the tool's actual hardware + capabilities. + +**Where it lives in this codebase.** + +This codebase provides the SECS/GEM runtime; the EAP is what a +customer writes on top of it. We ship two reference EAPs: + +- [`apps/secs_server.cpp`](../apps/secs_server.cpp) — the demo + server. Wires every Router handler the demo flow needs; uses + static YAML data and doesn't simulate any sensors. Useful as a + starting fork. +- [`examples/pvd_tool/main.cpp`](../examples/pvd_tool/main.cpp) — a + fictional PVD tool that adds a sensor simulator, a recipe runner, + an alarm threshold monitor, EPT state cycling, and Prometheus + metrics. This is the closest thing to "what a real EAP looks + like" that we ship. See [`examples/pvd_tool/README.md`](../examples/pvd_tool/README.md) + for the section-by-section walk. + +The integration tutorial — how to *write* an EAP for a real tool — +is [`INTEGRATION.md`](INTEGRATION.md). Chapter +[41](41_integration_hardware_mes_production.md) in this series covers +the same material with cross-references back to the standards. + +--- + +## 3. MES — the host + +**What it is.** The **Manufacturing Execution System**. A +fab-wide server (or cluster) that orchestrates production across +every tool, manages lots and recipes, collects yield and statistical +process control (SPC) data, and provides the operator UI for the +production floor. + +Commercial MES vendors you'll meet: Applied Materials **E3**, Camstar +**InSite**, Wonderware **MES**, Aegis **FactoryWorks**, Inficon +**FabGuard**, Critical Manufacturing **MES**, and many in-house +custom builds especially at the largest fabs. + +**What it does in SECS/GEM terms.** + +- **Connects** to each tool's equipment process. In SECS/GEM + language, the MES is the **active** side of the HSMS connection + (it initiates the TCP connect and sends `Select.req`). +- **Establishes communications** — sends `S1F13` to which the + equipment replies `S1F14(COMMACK=Accept)`. +- **Identifies the tool** — sends `S1F1` (Are You There), reads + back the `MDLN` (model name) and `SOFTREV` (software revision) + in `S1F2`. +- **Reads the data dictionary** — `S1F11` for the SVID namelist, + `S2F29` for the ECID namelist, `S1F23` for the CEID namelist, + `S5F5` for the alarm directory, `S7F19` for the recipe list. +- **Configures event reports** — `S2F33` defines a report, + `S2F35` links it to a Collection Event, `S2F37` enables it. This + is how the MES tells the tool "when CEID 300 fires, send me the + values of SVIDs 1 and 2 along with it." +- **Issues remote commands** — `S2F41 RCMD=START`, `S2F41 + RCMD=PAUSE`, `S2F41 RCMD=ABORT`, etc. +- **Manages recipes** — `S7F3` to send a recipe, `S7F19` to list, + `S7F17` to delete, `S7F5` to read one back. +- **Orchestrates process and control jobs** — `S16F11` to create + a Process Job, `S14F9` to wrap it in a Control Job, `S16F27` + CJSTART to begin execution. +- **Receives alarms and events** — `S5F1` for alarm set/clear, + `S6F11` for collection events. Acknowledges with `S5F2` and + `S6F12` respectively. +- **Sets and reads the equipment's clock** — `S2F17`/`S2F18` to + read, `S2F31`/`S2F32` to set. + +**Where it lives in this codebase.** + +We don't *implement* an MES — that's a separate, much larger product +category. We implement the host *side* of SECS/GEM so the codebase +can drive equipment too, mainly for testing. + +- [`apps/secs_client.cpp`](../apps/secs_client.cpp) — the active + host that drives the demo server through ~24 transactions. +- [`apps/secs_conformance.cpp`](../apps/secs_conformance.cpp) — the + host-driven conformance harness that runs the 47 wire-level checks. +- [`include/secsgem/gem/host_handler.hpp`](../include/secsgem/gem/host_handler.hpp) + + [`src/gem/host_handler.cpp`](../src/gem/host_handler.cpp) — + symmetric handler module so the host side can decode equipment + replies and act on equipment-initiated S5F1 / S6F11. +- [`interop/host_vs_cpp_server.py`](../interop/host_vs_cpp_server.py) + — the secsgem-py active host driving our C++ passive server. + +For integrating against a **commercial** MES, +[`MES_INTEROP.md`](MES_INTEROP.md) is the day-1 punch list. + +--- + +## 4. Fab planner / MES upper layer + +**What it is.** The layer *above* the MES. Goes by many names: +**Advanced Planning and Scheduling (APS)**, **Fab scheduler**, +**Dispatcher**, **MES upper**. Big fabs separate this from the +operational MES; smaller ones bundle it in. + +**What it does.** Decides which lot runs on which tool, in what +order, against what recipe, by what deadline. This is fab-wide +optimisation across hundreds of in-flight lots and dozens of routes. + +**SECS/GEM contact:** none directly. The planner talks to the MES +via REST / SQL / a message queue / a proprietary API. The MES +translates planner decisions into SECS commands. + +**Where it lives in this codebase.** Not implemented; out of scope. +Mentioned here so the reader knows where the recipes and lot +assignments ultimately come from, but no codebase artifact +corresponds to this layer. + +--- + +## 5. AMHS — Automated Material Handling System + +**What it is.** The robot-rail network and overhead hoist transport +(**OHT**) system that physically moves carriers (FOUPs holding ~25 +wafers each) between tools. In a modern 300 mm fab the AMHS is +*always* moving carriers between tools 24/7; humans never touch a +substrate. + +**What it does in SECS/GEM terms.** + +- The AMHS itself **doesn't speak SECS/GEM** — it has its own + control plane talking to a Material Control System (MCS) which is + conceptually peer to the MES. +- But every time a carrier *arrives at* or *departs from* an + equipment's load port, the AMHS-side robot and the equipment-side + load port **handshake over 8 parallel I/O lines** defined by + **E84**. This is a physical-layer handshake (CMOS-level voltages + on real wires) with strict timing — TA1, TA2, TA3 timers — to + make sure a $20 000 FOUP doesn't get dropped because both sides + thought the other one was holding it. +- Once the carrier is physically docked, the equipment fires a + `S6F11(CarrierArrived)` event to the MES and the MES sends back a + `S3F17(CarrierAction=ProceedWithCarrier)` to authorise processing. + +**Where it lives in this codebase.** + +- The E84 handshake state machine: [`include/secsgem/gem/e84.hpp`](../include/secsgem/gem/e84.hpp) + + [`src/gem/e84.cpp`](../src/gem/e84.cpp). +- The TA1/TA2/TA3 timer wiring: [`include/secsgem/gem/e84_timers.hpp`](../include/secsgem/gem/e84_timers.hpp), + [`include/secsgem/gem/e84_asio_timers.hpp`](../include/secsgem/gem/e84_asio_timers.hpp). +- The per-port store: `e84_ports.hpp` (see [`include/secsgem/gem/e84_ports.hpp`](../include/secsgem/gem/e84_ports.hpp)). +- Tests covering the timing rules: [`tests/test_e84.cpp`](../tests/test_e84.cpp), + [`tests/test_e84_timers.cpp`](../tests/test_e84_timers.cpp), + [`tests/test_e84_asio_timers.cpp`](../tests/test_e84_asio_timers.cpp), + [`tests/test_e84_ports.cpp`](../tests/test_e84_ports.cpp). + +Chapter [18](18_e84_parallel_io.md) covers E84 in full. + +--- + +## 6. Operator — the human + +**What it is.** The fab technician at the tool's local panel. Their +job is to handle anything the automation can't: load a non-AMHS +carrier, clear a jammed wafer, run a maintenance recipe, respond to +an alarm the MES can't auto-clear. + +**What they do in SECS/GEM terms.** + +- **Mode switch.** The operator can push the equipment between + control states: `EquipmentOffline`, `OnlineLocal` (commands + accepted only from the local panel), `OnlineRemote` (commands + accepted from the MES). This is E30 §6.2. +- **Override.** An operator can override an MES command (refuse to + start, force-clear an alarm, manually unload a carrier). In + SECS/GEM terms this is reflected by control-state transitions: + `OnlineRemote` → `OnlineLocal` means "operator has taken control." +- **Local alarm acknowledgement.** Some alarms can be cleared at + the panel without the MES being involved; the equipment then + emits an `S5F1` with the cleared bit so the MES catches up. + +**Where it lives in this codebase.** + +- The control state machine: [`include/secsgem/gem/control_state.hpp`](../include/secsgem/gem/control_state.hpp) + + [`src/gem/control_state.cpp`](../src/gem/control_state.cpp). +- The transition table loaded from YAML: [`data/control_state.yaml`](../data/control_state.yaml). +- The operator-initiated transition handlers: + `ControlStateMachine::operator_online`, `::operator_offline`, + `::operator_local`, `::operator_remote` in the same header. +- Tests: [`tests/test_control_state.cpp`](../tests/test_control_state.cpp). + +Chapter [13](13_e30_gem.md) walks through control state in detail. + +--- + +## Who talks to whom + +A short reference table. "Init." marks who initiates the +conversation; "Channel" marks the protocol layer. + +| Pair | Init. | Channel | Examples | +|----------------------------|------------|---------------------------------------------|-----------------------------------------------------------| +| Planner ↔ MES | Planner | REST / SQL / queue (out of scope) | "run lot L on tool T with recipe R" | +| MES ↔ EAP | MES | HSMS-SS (one TCP socket, equipment passive) | `S1F1`, `S2F41`, `S6F11`, `S5F1`, … | +| MES ↔ EAP (multi-MES) | MES | HSMS-GS (one TCP socket, multiple sessions) | Same messages, demuxed by session_id | +| EAP ↔ Equipment | Either | PLC / sensor APIs / recipe engine (tool-specific) | Out of scope of SECS/GEM | +| AMHS ↔ Load port | AMHS | E84 8-line parallel I/O | VALID/CS_0/CS_1/TR_REQ/READY/BUSY/COMPT/CONT/L_REQ/U_REQ/ES | +| MES ↔ EAP (carrier flow) | Equipment | HSMS | `S6F11(CarrierArrived)`, `S3F17(ProceedWithCarrier)` | +| Operator ↔ Equipment | Operator | Local panel | Online/Offline buttons, alarm acks | + +The four interesting things in this table: + +1. **The MES is the active side, the equipment is the passive side.** + Always. Equipment binds the port; MES connects to it. Some MES + want this reversed and will negotiate, but the GEM default is + equipment-passive. +2. **One TCP socket per (MES, equipment) pair.** HSMS-SS doesn't + multiplex; one connection serves one conversation. HSMS-GS adds + session multiplexing on top. +3. **Equipment-initiated traffic exists.** `S6F11` events and + `S5F1` alarms fire from equipment to MES *autonomously*, not + in reply to a host command. An EAP that never emits unsolicited + traffic is broken. +4. **The AMHS handshake is out-of-band relative to SECS/GEM.** + E84's 8 parallel I/O lines are real wires with real voltages; + the SECS messages that follow (`S6F11`, `S3F17`) are just the + *bookkeeping* around a handoff that already happened in + hardware. + +--- + +## A small mental check + +If you've internalised the chapter, you should be able to answer: + +1. When the MES sends `S1F13`, who initiates the TCP connection? +2. When a chamber pressure sensor reads out of range, who decides + whether to fire `S5F1`? +3. What language does the AMHS speak to the equipment to coordinate + a FOUP handoff? +4. Is the operator at the local panel a SECS/GEM actor? +5. Is the fab planner a SECS/GEM actor? + +Answers, in order: + +1. The MES. The equipment is passive; it binds and waits. TCP + connect is the MES's first move. +2. The EAP (the vendor's application code on top of this library). + The SECS/GEM library doesn't know what's a "normal" pressure; + the EAP does. Once the EAP decides "this is alarm-worthy," it + calls into the alarm store and the library emits `S5F1`. +3. E84 8-line parallel I/O — physical wires, not SECS. After the + handoff, the *bookkeeping* SECS messages (`S6F11`, `S3F17`) flow + between equipment and MES. +4. Yes — through E30 §6.2 control-state transitions. Not a SECS + message *sender*, but a state-transition source the equipment + has to report on. +5. No. The planner talks to the MES; the MES talks to the EAP. + The planner is invisible from the SECS wire. + +--- + +## What's next + +You now know who's in the room and who's talking to whom. The next +chapter introduces the **vocabulary** — every SEMI acronym you'll +read in a debug log (SVID, CEID, ALID, PPID, ALCD, HCACK, T-timers, +…) — by tracing **one wafer's journey** end-to-end through a fab and +labelling every SECS message that fires along the way. + +Next: [→ 03 Vocabulary + a wafer's journey](03_vocabulary_and_a_wafers_journey.md) diff --git a/docs/03_vocabulary_and_a_wafers_journey.md b/docs/03_vocabulary_and_a_wafers_journey.md new file mode 100644 index 0000000..3f3a67f --- /dev/null +++ b/docs/03_vocabulary_and_a_wafers_journey.md @@ -0,0 +1,592 @@ +# 03 — Vocabulary + a wafer's journey + +← [02 The cast of characters](02_the_cast.md) | [Back to index](00_index.md) | Next: [10 E5 — SECS-II data items](10_e5_secs_ii_data_items.md) → + +The SEMI standards bury everything in acronyms. Three-letter, four- +letter, sometimes the same letter pattern (`ACKC5`, `ACKC6`, `ACKC7`, +`ACKC10`) but with completely different semantics depending on which +stream you're in. Most readers learn them by absorbing them over +years of integration work. + +This chapter accelerates that. We follow **one 300 mm wafer** from +the moment it enters the fab to the moment it leaves as a finished +die, and at every step we name every acronym that fires, what it +means, and where it lives in this codebase. By the end you'll have +seen `SVID`, `CEID`, `ALID`, `PPID`, `HCACK`, `ALCD`, `RPTID`, +`OFLACK`, `MDLN`, `SOFTREV`, `CAACK`, `SMACK`, and the rest in +*context* — not as a vocabulary list. + +If you're confident with the vocabulary already, skip to Part 2, +Chapter [10](10_e5_secs_ii_data_items.md) (SECS-II encoding). + +--- + +## The setup + +- **The wafer**: an unpatterned 300 mm silicon disc, 775 µm thick, + with a serial number `W-2026-06-09-A47` etched on the bevel. +- **The carrier**: a Front-Opening Universal Pod (**FOUP**) that + holds 25 wafers in vertical slots. Our wafer is in slot 14. The + FOUP's bar code reads `C-31415`. +- **The tools**: + - **PVD-1** (physical vapour deposition — deposits a metal layer) + - **LITHO-3** (photolithography — patterns the metal layer) + - **ETCH-7** (plasma etch — removes uncovered metal) +- **The host**: a fab-wide MES called `meta-fab.example`. +- **The recipe**: `RECIPE-Cu-A` for PVD-1, `RECIPE-193nm-X` for + LITHO-3, `RECIPE-CL2-B` for ETCH-7. + +For brevity we'll only show the wafer's first pass through PVD-1. +The same pattern repeats for LITHO-3 and ETCH-7. + +--- + +## Stage 1 — Establishing communications (already done) + +Before any wafer arrives, **PVD-1 and meta-fab.example have already +HSMS-SELECTed each other**. That's the once-per-power-on dance: + +``` +host (active) equipment (passive) +───────────── ─────────────────── +TCP SYN ─────────────────────────► (bind on :5000) + ◄──── TCP SYN-ACK +HSMS Select.req (sessionID=0) ───► + ◄──── HSMS Select.rsp (SELECT_STATUS=0=accept) + [transport state: SELECTED] +S1F13 Establish Communications ──► + ◄──── S1F14 (COMMACK=0=accepted, [MDLN, SOFTREV]) + [GEM communication state: COMMUNICATING] +``` + +This introduces three acronyms: + +- **`MDLN`** — Model Name. An ASCII string up to 20 chars + identifying the equipment model. PVD-1 returns `"ACME-PVD-3000"`. +- **`SOFTREV`** — Software Revision. ASCII string up to 20 chars + identifying the firmware / EAP version. PVD-1 returns `"1.4.2"`. +- **`COMMACK`** — Communication Acknowledge. One byte; 0 = accepted, + 1 = denied. Defined in E30 §6.5. + +**Where:** see `equipment.yaml` device block; emission flows through +[`gem::Router`](../include/secsgem/gem/router.hpp) → +[`secsgem::secs2::Message`](../include/secsgem/secs2/message.hpp). + +--- + +## Stage 2 — The carrier arrives at PVD-1's load port + +The AMHS overhead hoist swings FOUP `C-31415` onto load port 1. +*Before* anything SECS happens, the **E84 handshake** runs on the +physical I/O lines: + +``` +AMHS robot load port 1 +────────── ─────────── +CS_0 asserted ───────────────────► (carrier select bit 0) +CS_1 asserted ───────────────────► (carrier select bit 1) +VALID asserted ──────────────────► (lines above are stable) + ◄──── L_REQ asserted (LOAD allowed) +TR_REQ asserted ─────────────────► (transfer requested) + ◄──── READY asserted (kinematic interlocks ok) +BUSY asserted ───────────────────► (placement in progress) +… mechanical placement happens (~5 seconds) … +BUSY de-asserted ────────────────► (placement done) + ◄──── COMPT asserted (complete) +CONT asserted ───────────────────► (carrier connected to load port) +``` + +This introduces the E84 line-name acronyms (`VALID`, `CS_0`, `CS_1`, +`TR_REQ`, `READY`, `BUSY`, `COMPT`, `CONT`, `L_REQ`, `U_REQ`, `ES`) +and three timer names: + +- **`TA1`** — armed when `VALID` asserts; the load port must respond + with `L_REQ` within `TA1`. Default ~2 seconds. +- **`TA2`** — armed when `L_REQ` asserts; `TR_REQ` must follow + within `TA2`. Default ~2 seconds. +- **`TA3`** — armed when `BUSY` asserts (transfer in progress); the + whole transfer must finish within `TA3`. Default ~60 seconds. + +Any of these timing out → both sides go to `HandoffFault` and the +operator gets paged. No FOUP gets dropped because the protocol +guarantees both sides agreed on every step. + +**Where:** [`include/secsgem/gem/e84.hpp`](../include/secsgem/gem/e84.hpp) +defines the FSM; [`include/secsgem/gem/e84_timers.hpp`](../include/secsgem/gem/e84_timers.hpp) +defines the timer enforcement; chapter [18](18_e84_parallel_io.md) +walks the whole handshake. + +--- + +## Stage 3 — The carrier is on the load port; PVD-1 tells the MES + +The E84 handshake gave PVD-1 a docked carrier. Now SECS messages +flow: + +``` +PVD-1 (equipment) meta-fab (host) +───────────────── ─────────────── +S6F11 CarrierArrived ────────────► + CEID = 10001 + DATAID = 1 + [ {RPTID=100, V=[CarrierID="C-31415", PortID=1]} ] + ◄──── S6F12 (ACKC6=0=accepted) + +S3F19 Slot Map Verify ───────────► + CARRIERID = "C-31415" + [ slot_state[1..25] ] + ◄──── S3F20 (SMACK=0=match) +``` + +New acronyms in this stage: + +- **`CEID`** — Collection Event ID. An identifier (any unsigned + width; we'll use `U4`) for a noteworthy thing that happened. CEIDs + are *defined in the equipment's YAML* and the MES learns them via + `S1F23/F24`. CEID 10001 = `CarrierArrived` per E87. +- **`RPTID`** — Report ID. A bundle of variables. When CEID 10001 + fires, the MES gets back the values of every variable linked to + every report linked to CEID 10001. Reports are *defined by the + host* via `S2F33` and linked to CEIDs via `S2F35`. +- **`DATAID`** — Data ID, a per-host transaction counter. Lets the + host correlate report data to a specific request. +- **`ACKC6`** — Acknowledge Code 6. S6F12 reply byte. 0 = + accepted, anything else = MES couldn't process the event. +- **`CARRIERID`** — Carrier ID, an ASCII string. Matches what the + AMHS told us via E84. +- **`SMACK`** — Slot Map Acknowledge. S3F20 reply byte. 0 = + matches what the MES expected, 1 = mismatch. Defined in E87. +- **`CAACK`** — Carrier Action Acknowledge (we'll see this one + shortly). S3F18 reply byte for carrier-action commands. + +Note the pattern: every primary message ends in an odd function +(F11, F19), every reply ends in the next even function (F12, F20). +This is invariant across SECS-II. See chapter [10](10_e5_secs_ii_data_items.md) +for the encoding details. + +**Where:** `gem::CarrierStore` in [`include/secsgem/gem/carrier_store.hpp`](../include/secsgem/gem/carrier_store.hpp); +the E87 wire tests in [`tests/test_e87_wire_scenarios.cpp`](../tests/test_e87_wire_scenarios.cpp). + +--- + +## Stage 4 — The host authorises processing + +``` +meta-fab (host) PVD-1 (equipment) +─────────────── ───────────────── +S3F17 CarrierAction ─────────────► + CARRIERACTION = "ProceedWithCarrier" + CARRIERID = "C-31415" + ◄──── S3F18 (CAACK=0=accepted) +``` + +- **`CARRIERACTION`** — an ASCII string from a fixed E87 set: + `ProceedWithCarrier`, `CancelCarrier`, `CarrierOut`, … +- **`CAACK`** — Carrier Action Acknowledge. S3F18 reply byte. 0 = + accepted, 1 = unknown carrier, 2 = invalid action, 3 = invalid + state, 4 = mismatch, 5 = unknown. + +The host could have sent `CancelCarrier` here instead and PVD-1 +would have rejected the FOUP without processing. That decision +lives entirely on the host side. + +--- + +## Stage 5 — The host queues a process job + +``` +meta-fab (host) PVD-1 (equipment) +─────────────── ───────────────── +S16F11 PRJobCreate ──────────────► + PRJobID = "PJ-2026-06-09-001" + MF = "Substrate" + PRMtlOutSpec = [] + PRRecipeMethod = "RecipeOnly" + RCPSpec = "RECIPE-Cu-A" + PRProcessStart = false (we'll start it explicitly later) + PRMtlnameList = ["W-2026-06-09-A47"] + ◄──── S16F12 (PRJobAck=0) + +S14F9 CreateControlJob ─────────► + CJobID = "CJ-2026-06-09-001" + PRJobIDList = ["PJ-2026-06-09-001"] + ◄──── S14F10 (OBJACK=0) +``` + +New acronyms: + +- **`PRJobID`** — Process Job ID, an ASCII string the host invents + for tracking. Sometimes called `PJID`. +- **`MF`** — Material Format. ASCII; `Substrate`, `Carrier`, + `SubstrateLocation`. Tells the equipment what scale the job is + about. +- **`RCPSpec`** — Recipe specification. References a recipe by ID + (`PPID`, below). +- **`PPID`** — Process Program ID. The recipe's identifier. In our + case `"RECIPE-Cu-A"`. +- **`PRJobAck`** — S16F12 reply byte. 0 = accepted, non-zero + values for each failure mode. +- **`CJobID`** — Control Job ID. A control job wraps one or more + process jobs and adds scheduling semantics (start order, abort + policy, dependency on other CJs). +- **`OBJACK`** — Object Acknowledge. S14F10 reply byte. Generic + E39 object-services ack: 0 = accepted, 1 = error. + +E40 governs process jobs; E94 governs control jobs above them. + +**Where:** [`include/secsgem/gem/process_jobs.hpp`](../include/secsgem/gem/process_jobs.hpp), +[`include/secsgem/gem/control_jobs.hpp`](../include/secsgem/gem/control_jobs.hpp). +The state machines are loaded from +[`data/process_job_state.yaml`](../data/process_job_state.yaml) and +[`data/control_job_state.yaml`](../data/control_job_state.yaml). +See chapter [14](14_e40_e94_jobs.md) for the lifecycle in full. + +--- + +## Stage 6 — The host configures event reports + +Before processing starts, the MES wants to subscribe to specific +events. This is a three-message dance: + +``` +meta-fab (host) PVD-1 (equipment) +─────────────── ───────────────── +S2F33 DefineReport ──────────────► + DATAID = 2 + [ { RPTID=200, VID=[1, 2, 5] } ] (link RPTID 200 to SVIDs 1,2,5) + ◄──── S2F34 (DRACK=0=accepted) + +S2F35 LinkEvent ─────────────────► + DATAID = 3 + [ { CEID=300, RPTID=[200] } ] (when CEID 300 fires, send RPTID 200) + ◄──── S2F36 (LRACK=0=accepted) + +S2F37 EnableEvent ───────────────► + CEED = true + CEID = [300] (enable CEID 300) + ◄──── S2F38 (ERACK=0=accepted) +``` + +New acronyms: + +- **`SVID`** — Status Variable ID. An identifier (`U4` typical) for + a *long-lived* value the host can read at any time — current + control state, chamber pressure, wafer counter, recipe in progress, + clock. Roughly: instance variables that survive across events. +- **`DVID`** — Data Variable ID. Same shape, but only meaningful + *at the moment an event fires*. E.g. the temperature at the time + the `ProcessStarted` event was emitted. Not readable independently + via `S1F3`; only delivered as part of a report. +- **`ECID`** — Equipment Constant ID. Same shape, but the host can + *set* it (within declared `min`/`max` bounds) via `S2F15`. + Settings that survive power-cycle: nominal chamber pressure, T3 + timeout, T7 timeout, etc. +- **`VID`** — Variable ID. A generic SVID-or-DVID, used in report + definitions. +- **`CEED`** — Collection Event Enable Disable. Boolean. `true` = + enable the listed CEIDs, `false` = disable them. +- **`DRACK`** — Define Report Acknowledge. S2F34 reply. +- **`LRACK`** — Link Report Acknowledge. S2F36 reply. +- **`ERACK`** — Enable Report Acknowledge. S2F38 reply. + +Acknowledge bytes are *distinct enums per stream/function*. `DRACK += 0` = accepted; `LRACK = 0` = accepted; `ERACK = 0` = accepted — +same value, but each one has its own enumeration of failure codes +(`3 = at least one CEID does not exist`, etc.). Don't reuse one +stream's enum for another's. + +**Where:** [`include/secsgem/gem/report_store.hpp`](../include/secsgem/gem/report_store.hpp), +[`include/secsgem/gem/event_store.hpp`](../include/secsgem/gem/event_store.hpp). +The configuration flow is the heart of E30 §6.6 Dynamic Event Report +Configuration; see chapter [13](13_e30_gem.md). + +--- + +## Stage 7 — Processing begins + +``` +meta-fab (host) PVD-1 (equipment) +─────────────── ───────────────── +S2F41 RemoteCommand ─────────────► + RCMD = "START" + CPNAME[] / CPVAL[] = [] + ◄──── S2F42 (HCACK=0=accepted) + + S6F11 ProcessStarted ──────────► + CEID = 300 + DATAID = 4 + [ {RPTID=200, + V=[ControlState="OnlineRemote", + Clock="20260609173000", + WaferCount=147]} ] +◄──── S6F12 (ACKC6=0) +``` + +New acronyms: + +- **`RCMD`** — Remote Command name. ASCII. `"START"`, `"STOP"`, + `"PAUSE"`, `"ABORT"`, `"VENT"`, etc. Equipment-vendor-defined. +- **`CPNAME` / `CPVAL`** — Command Parameter name / value pairs. + Empty list here; some commands take parameters (e.g. + `RCMD="CHANGE-RECIPE", CPNAME="PPID", CPVAL="RECIPE-Cu-B"`). +- **`HCACK`** — Host Command Acknowledge. S2F42 reply. 0 = + accepted, 1 = invalid command, 2 = cannot perform now, 3 = at + least one parameter is invalid, 4 = accepted-and-will-finish-later, + 5 = rejected, 6 = invalid object. + +The `S6F11(CEID=300)` that fires next is the event report +**defined three messages earlier**. The MES correlated this by: + +1. Earlier sent `S2F33` → equipment now knows that "RPTID 200 = + [SVID 1, SVID 2, SVID 5]." +2. Earlier sent `S2F35` → equipment now knows that "when CEID 300 + fires, the report payload should include RPTID 200." +3. Earlier sent `S2F37` → CEID 300 is enabled, so when the + processing logic fires it, an `S6F11` actually leaves the wire. + (If CEID 300 had been left *disabled*, the processing logic + would still fire it but the wire would stay quiet.) + +**Where:** [`include/secsgem/gem/host_command_registry.hpp`](../include/secsgem/gem/host_command_registry.hpp) +maps `RCMD` strings to handlers; the report-emission machinery lives +in `EquipmentDataModel` ([`include/secsgem/gem/data_model.hpp`](../include/secsgem/gem/data_model.hpp)) +via `compose_reports_for(ceid)`. Wire-level tests: +[`tests/test_wire_ceid_emission.cpp`](../tests/test_wire_ceid_emission.cpp). + +--- + +## Stage 8 — An alarm fires + +Mid-processing, the chamber pressure sensor reads above its +configured `ECID="ChamberPressureMax"` threshold. The EAP's alarm +monitor decides this is alarm-worthy and calls +`alarms.set(ALID=42)`: + +``` +PVD-1 (equipment) meta-fab (host) +───────────────── ─────────────── +S5F1 AlarmReport ────────────────► + ALCD = 0x84 (bit 7 set + category 4 = process) + ALID = 42 + ALTX = "Chamber pressure above max threshold" + ◄──── S5F2 (ACKC5=0) +``` + +- **`ALID`** — Alarm ID. An identifier (`U4` typical) for one + named alarm in the equipment's alarm directory. +- **`ALCD`** — Alarm Code. One byte. Bit 7 = "set" (1) or "clear" + (0). Lower 7 bits = category (1 = personal safety, 2 = equipment + safety, 3 = parameter control warning, 4 = parameter control + error, 5 = irrecoverable error, 6 = equipment status warning, 7 = + attention flag, 8 = data integrity, others reserved). E5 §13. +- **`ALTX`** — Alarm Text. ASCII description, up to 120 chars per + E5 §13. +- **`ACKC5`** — Acknowledge Code 5. S5F2 reply. 0 = accepted. + +If the host had previously *disabled* ALID 42 (via `S5F3 +ALED=0x00`), this `S5F1` wouldn't have left the wire — the equipment +would still note the alarm internally (so `S5F5` would list it), but +the host wouldn't get pinged. + +When the pressure returns to range, a second `S5F1` fires with +`ALCD=0x04` (bit 7 cleared) and the same ALID, signalling "alarm +cleared." + +**Where:** [`include/secsgem/gem/alarm_store.hpp`](../include/secsgem/gem/alarm_store.hpp); +the dispatcher gates emission on the enable list in +[`include/secsgem/gem/alarm_dispatcher.hpp`](../include/secsgem/gem/alarm_dispatcher.hpp). + +--- + +## Stage 9 — Processing completes + +``` +PVD-1 (equipment) meta-fab (host) +───────────────── ─────────────── +S6F11 ProcessCompleted ──────────► + CEID = 301 + DATAID = 5 + [ {RPTID=200, V=[…]} ] + ◄──── S6F12 (ACKC6=0) +``` + +Same pattern as `ProcessStarted` — just a different CEID for a +different lifecycle moment. + +The MES sees `CEID=301` and updates its tracking: process job +`PJ-2026-06-09-001` is now `ProcessComplete` per E40. It clears its +"in progress" counter and updates wafer `W-2026-06-09-A47`'s +location in E90 substrate tracking. + +--- + +## Stage 10 — Carrier transfers out + +``` +meta-fab (host) PVD-1 (equipment) +─────────────── ───────────────── +S3F25 CarrierTransfer ───────────► + CARRIERID = "C-31415" + PortID = 2 (transfer from LP1 to LP2 = outbound) + ◄──── S3F26 (CAACK=0) + +PVD-1 (equipment) meta-fab (host) +───────────────── ─────────────── +S6F11 CarrierTransfered ─────────► + CEID = 10002 + [ … ] + ◄──── S6F12 (ACKC6=0) +``` + +Then E84 runs in reverse: the AMHS robot couples to the load port, +the parallel I/O lines hand control back, the OHT hoist lifts the +FOUP, and `C-31415` heads to LITHO-3 for the next process step. + +--- + +## Wait, what other acronyms exist? + +The journey above covered the most common acronyms but skipped a +handful that show up in other contexts. A reference list for the +rest: + +### Acknowledge codes you haven't met yet + +| Code | Stream | Where | 0 = accepted, then… | +|----------|--------|--------------------------------|----------------------------------------------| +| `OFLACK` | 1 | S1F16 reply to "Request Offline" | 0=accept, 1=already offline | +| `ONLACK` | 1 | S1F18 reply to "Request Online" | 0=accept, 1=not allowed, 2=already online | +| `ACKC7` | 7 | S7F4 / S7F18 (recipe send/delete) | 0=accept, 1=permission denied, 2=length err,3=matrix err,4=PPID not found,5=mode unsupported,6=other | +| `ACKC10` | 10 | S10F2 / F4 / F6 (terminal services)| 0=accept, 1=not displayed, 2=no terminal | +| `CMDA` | 2 | S2F22 reply to legacy `S2F21` | 0=ok, 1=invalid command, 2=cannot do now,3=invalid arg | +| `TIACK` | 2 | S2F32 reply to "Set Clock" | 0=accept, 1=err not done | +| `EAC` | 2 | S2F16 reply to "Set EC values" | 0=accept, 1=≥1 constant out of range, 2=busy, 3=≥1 constant unknown | +| `RSPACK` | 2 | S2F44 reply to "Set Spool Streams" | 0=accept, 1=spool not supported, 2=≥1 stream unknown | +| `RSDA` | 6 | S6F24 reply to "Spool Data Send" | 0=ok, 1=denied | +| `PPGNT` | 7 | S7F2 reply to "PP Load Inquire"| 0=permit, 1=already have, 2=no room, 3=invalid PPID, 4=mode unsupported, 5=PP non-existent, 6=other | + +### Control codes you haven't met + +| Code | Stream | Where | What it means | +|----------|--------|-----------------------------|----------------------------------------------------------------| +| `RSDC` | 6 | S6F23 host command to spool | 0=transmit spooled, 1=purge spool | +| `ALED` | 5 | S5F3 host enable/disable alarm | bit 7 set = enable, bit 7 cleared = disable | +| `TID` | 10 | S10F1/F3/F5 terminal display | Which terminal screen to address (0 = main) | +| `TEXT` | 10 | S10F1/F3/F5 terminal display | The ASCII text payload | + +### Object-services codes (E39) + +| Code | Stream | Where | What it means | +|-----------|--------|-----------------------------|--------------------------------------------------------------| +| `OBJSPEC` | various | S2F49, S14F1 | An "object specifier" — a typed path identifying a target object | +| `OBJACK` | 14 | S14F2 / F10 / F12 reply | 0=ok, 1=command failed | +| `CPACK` | 2 | S2F42 reply (modern) | Per-parameter ack for each `CPNAME/CPVAL` in the command | +| `CEPACK` | 2 | S2F50 reply (enhanced) | Per-parameter ack for enhanced remote commands | + +--- + +## All the T-timers in one place + +You'll meet timer acronyms in three different contexts. They use +the same letters with different meanings — pin them down: + +### HSMS T-timers (E37 §10) + +These bound the *network* behaviour. Only fire when something is +slow or stuck. + +| Name | Default | What it bounds | +|------|-------------|------------------------------------------------------| +| `T3` | 45 s | Reply timeout for a W=1 primary message | +| `T5` | 10 s | How long active side waits between connect attempts | +| `T6` | 5 s | Control-transaction (Select / Linktest) reply timeout | +| `T7` | 10 s | Passive side: max time without Select.req after TCP | +| `T8` | 5 s | Max time between bytes of a single frame | + +Chapter [11](11_e37_hsms.md) covers each one in detail. + +### SECS-I T-timers (E4 §10) + +These bound the *serial-block* behaviour. Distinct from HSMS +T-timers despite the name overlap. + +| Name | Default | What it bounds | +|------|-------------|------------------------------------------------------| +| `T1` | 500 ms | Inter-character timeout within one block | +| `T2` | 10 s | Protocol timer (handshake state) | +| `T3` | 45 s | Reply timeout for a W=1 primary message | +| `T4` | 45 s | Inter-block timeout in a multi-block message | + +`T3` exists in both HSMS and SECS-I with the same semantics — it's +load-bearing in both transports. + +### E84 timers (E84 §6) + +These bound the *physical handoff* timing. Distinct again. + +| Name | Default | What it bounds | +|-------|---------|-------------------------------------------------| +| `TA1` | ~2 s | `VALID` → `L_REQ` | +| `TA2` | ~2 s | `L_REQ` → `TR_REQ` | +| `TA3` | ~60 s | `BUSY` → transfer complete | + +### E30 communication-state timers (E30 §6.5) + +These bound the *application-level* establish-communications loop: + +| Name | Default | What it bounds | +|-----------|---------|-----------------------------------------------------------------| +| `T_CRA` | 45 s | Wait for `S1F14` (Comm Request Acknowledge) reply after `S1F13` | +| `T_DELAY` | 10 s | Retry interval after a failed `S1F13` round-trip | + +Defined in [`include/secsgem/gem/communication_state.hpp`](../include/secsgem/gem/communication_state.hpp); +tested in [`tests/test_communication_state.cpp`](../tests/test_communication_state.cpp). + +--- + +## Stream-by-stream summary + +The streams you'll meet most often, with one sentence each: + +| Stream | What it's for | Most-used messages | +|--------|----------------------------------------------------------|---------------------------------------------------| +| S1 | Identification, status, control | `S1F1/F2`, `S1F3/F4`, `S1F11/F12`, `S1F13/F14`, `S1F15-F18`, `S1F19/F20`, `S1F21-F24` | +| S2 | Equipment constants, clock, events, commands | `S2F13-F18`, `S2F29-F38`, `S2F41/F42`, `S2F43-F50` | +| S3 | Carrier management (E87) | `S3F17/F18`, `S3F19/F20`, `S3F25-F28` | +| S5 | Alarms, exception recovery | `S5F1-F8`, `S5F9-F18` | +| S6 | Data collection, event reports, spool | `S6F11/F12`, `S6F15/F16`, `S6F19-F22`, `S6F23-F26` | +| S7 | Recipe / process program management | `S7F1-F6`, `S7F17-F20`, `S7F23-F26` | +| S9 | Protocol-error reports (auto-emitted by equipment) | `S9F1`, `S9F3`, `S9F5`, `S9F7`, `S9F9`, `S9F11`, `S9F13` | +| S10 | Terminal services | `S10F1-F6` | +| S12 | Wafer maps | (per-stream — chapter [10](10_e5_secs_ii_data_items.md) §6) | +| S14 | Generic object services (E39), control jobs (E94) | `S14F1/F2`, `S14F9-F12` | +| S16 | Process jobs (E40) | `S16F5-F8`, `S16F9`, `S16F11-F14`, `S16F27/F28` | + +Where every named message lives in code: [`build/generated/secsgem/gem/messages.hpp`](../build/generated/secsgem/gem/messages.hpp) +(after a build) — generated from +[`data/messages.yaml`](../data/messages.yaml) by +[`tools/generate_messages.py`](../tools/generate_messages.py). +Chapter [31](31_spec_as_data_and_codegen.md) walks the codegen. + +--- + +## You've made it through Part 1 + +You can now: + +- Explain why SECS/GEM exists, and what each of "SECS", "HSMS", and + "GEM" actually refers to. +- Name every actor in the fab automation stack and describe who + talks to whom. +- Recognise every common acronym (SVID, ECID, DVID, CEID, RPTID, + ALID, PPID, MDLN, SOFTREV, HCACK, ALCD, OFLACK, …) and the + acknowledge bytes that go with each stream. +- List the T-timers in four different contexts (HSMS, SECS-I, E84, + E30 communication state) and not confuse them. + +Part 2 of this guide takes one standard at a time, from the +ground up: byte-level encoding, wire diagrams, every message, every +ack value, the FSMs, and the code that implements each. We start +with the foundation everything else stands on — **E5 SECS-II**, the +data-item encoding. + +Next: [→ 10 E5 — SECS-II data items](10_e5_secs_ii_data_items.md) diff --git a/ARCHITECTURE.md b/docs/ARCHITECTURE.md similarity index 100% rename from ARCHITECTURE.md rename to docs/ARCHITECTURE.md diff --git a/BENCHMARKS.md b/docs/BENCHMARKS.md similarity index 100% rename from BENCHMARKS.md rename to docs/BENCHMARKS.md diff --git a/COMPLIANCE.md b/docs/COMPLIANCE.md similarity index 100% rename from COMPLIANCE.md rename to docs/COMPLIANCE.md diff --git a/FAQ.md b/docs/FAQ.md similarity index 100% rename from FAQ.md rename to docs/FAQ.md diff --git a/GLOSSARY.md b/docs/GLOSSARY.md similarity index 100% rename from GLOSSARY.md rename to docs/GLOSSARY.md diff --git a/INTEGRATION.md b/docs/INTEGRATION.md similarity index 100% rename from INTEGRATION.md rename to docs/INTEGRATION.md diff --git a/MES_INTEROP.md b/docs/MES_INTEROP.md similarity index 100% rename from MES_INTEROP.md rename to docs/MES_INTEROP.md diff --git a/PROOFS.md b/docs/PROOFS.md similarity index 100% rename from PROOFS.md rename to docs/PROOFS.md diff --git a/SECURITY.md b/docs/SECURITY.md similarity index 100% rename from SECURITY.md rename to docs/SECURITY.md diff --git a/VERIFICATION.md b/docs/VERIFICATION.md similarity index 100% rename from VERIFICATION.md rename to docs/VERIFICATION.md