213 lines
7.0 KiB
Markdown
213 lines
7.0 KiB
Markdown
# CLAUDE.md
|
||
|
||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
||
## Project Purpose
|
||
|
||
This repository generates runnable Curtin ICS-SimLab scenarios from textual descriptions. It produces:
|
||
- `configuration.json` compatible with Curtin ICS-SimLab
|
||
- `logic/*.py` files implementing PLC control logic and HIL process physics
|
||
|
||
**Hard boundary**: Do NOT modify the Curtin ICS-SimLab repository. Only change files inside this repository.
|
||
|
||
## Common Commands
|
||
|
||
```bash
|
||
# Activate virtual environment
|
||
source .venv/bin/activate
|
||
|
||
# Generate configuration.json from text input (requires OPENAI_API_KEY in .env)
|
||
python3 main.py --input-file prompts/input_testuale.txt
|
||
|
||
# Build complete scenario (config -> IR -> logic)
|
||
python3 build_scenario.py --out outputs/scenario_run --overwrite
|
||
|
||
# Validate PLC callback retry fix is present
|
||
python3 validate_fix.py
|
||
|
||
# Validate logic against configuration
|
||
python3 -m tools.validate_logic \
|
||
--config outputs/configuration.json \
|
||
--logic-dir outputs/scenario_run/logic \
|
||
--check-callbacks \
|
||
--check-hil-init
|
||
|
||
# Run scenario in ICS-SimLab (use ABSOLUTE paths with sudo)
|
||
cd /home/stefano/projects/ICS-SimLab-main/curtin-ics-simlab
|
||
sudo ./start.sh /home/stefano/projects/ics-simlab-config-gen_claude/outputs/scenario_run
|
||
```
|
||
|
||
## Architecture
|
||
|
||
The pipeline follows a deterministic approach:
|
||
|
||
```
|
||
text input -> LLM -> configuration.json -> IR (ir_v1.json) -> logic/*.py
|
||
```
|
||
|
||
### Key Components
|
||
|
||
**Entry Points:**
|
||
- `main.py` - LLM-based generation: text -> configuration.json
|
||
- `build_scenario.py` - Orchestrates full build: config -> IR -> logic (calls tools/*.py)
|
||
|
||
**IR Pipeline (tools/):**
|
||
- `make_ir_from_config.py` - Extracts IR from configuration.json using keyword-based heuristics
|
||
- `compile_ir.py` - Deterministic compiler: IR -> Python logic files (includes `_safe_callback` fix)
|
||
- `validate_logic.py` - Validates generated logic against config
|
||
|
||
**Models (models/):**
|
||
- `ics_simlab_config.py` - Pydantic models for configuration.json (PLC, HIL, registers)
|
||
- `ir_v1.py` - Intermediate Representation: `IRSpec` contains `IRPLC` (rules) and `IRHIL` (blocks)
|
||
|
||
**LLM Pipeline (services/):**
|
||
- `pipeline.py` - Generate -> validate -> repair loop
|
||
- `generation.py` - OpenAI API calls
|
||
- `patches.py` - Auto-fix common config issues
|
||
- `validation/` - Validators for config, PLC callbacks, HIL initialization
|
||
|
||
## ICS-SimLab Contract
|
||
|
||
### PLC Logic
|
||
|
||
File referenced by `plcs[].logic` becomes `src/logic.py` in container.
|
||
|
||
Required signature:
|
||
```python
|
||
def logic(input_registers, output_registers, state_update_callbacks):
|
||
```
|
||
|
||
Rules:
|
||
- Read only registers with `io: "input"` (from `input_registers`)
|
||
- Write only registers with `io: "output"` (to `output_registers`)
|
||
- After EVERY write to an output register, call `state_update_callbacks[id]()`
|
||
- Access by logical `id`/`name`, never by Modbus address
|
||
|
||
### HIL Logic
|
||
|
||
File referenced by `hils[].logic` becomes `src/logic.py` in container.
|
||
|
||
Required signature:
|
||
```python
|
||
def logic(physical_values):
|
||
```
|
||
|
||
Rules:
|
||
- Initialize ALL keys declared in `hils[].physical_values`
|
||
- Update only keys marked as `io: "output"`
|
||
|
||
## Known Runtime Pitfall
|
||
|
||
PLC startup race condition: PLC2 can crash when writing to PLC1 before it's ready (`ConnectionRefusedError`).
|
||
|
||
**Solution implemented in `tools/compile_ir.py`**: The `_safe_callback()` wrapper retries failed callbacks with exponential backoff (30 attempts x 0.2s).
|
||
|
||
Always validate after rebuilding:
|
||
```bash
|
||
python3 validate_fix.py
|
||
```
|
||
|
||
## IR System
|
||
|
||
The IR (Intermediate Representation) enables deterministic code generation.
|
||
|
||
**PLC Rules** (`models/ir_v1.py`):
|
||
- `HysteresisFillRule` - Tank level control with low/high thresholds
|
||
- `ThresholdOutputRule` - Simple threshold-based output
|
||
|
||
**HIL Blocks** (`models/ir_v1.py`):
|
||
- `TankLevelBlock` - Water tank dynamics (level, inlet, outlet)
|
||
- `BottleLineBlock` - Conveyor + bottle fill simulation
|
||
|
||
To add new process physics: create a structured spec (not free-form Python via LLM), then add a deterministic compiler.
|
||
|
||
## Project Notes (appunti.txt)
|
||
|
||
Maintain `appunti.txt` in the repo root with bullet points (in Italian) documenting:
|
||
- Important discoveries about the repo or runtime
|
||
- Code changes, validations, generation behavior modifications
|
||
- Root causes of bugs
|
||
- Verification commands used
|
||
|
||
Include `appunti.txt` in diffs when updated.
|
||
|
||
## Diary Skill (Diario di Lavoro)
|
||
|
||
Il repository usa due file per documentare il lavoro:
|
||
|
||
| File | Uso |
|
||
|------|-----|
|
||
| `appunti.txt` | Note operative rapide (bullet point) |
|
||
| `diario.md` | Registro giornaliero thesis-ready |
|
||
|
||
### Regole per Claude (in italiano)
|
||
|
||
1. **appunti.txt**: aggiornare quando cambiano codice, config, o test. Stile bullet point conciso. Aggiornare subito, durante il lavoro.
|
||
|
||
2. **diario.md**: aggiornare a fine richiesta lunga (prompt utente >30 parole). Usare il template in `diario.md`. Spiegare il *perché* delle decisioni, non solo il *cosa*.
|
||
|
||
3. **Comandi eseguiti**: includere sempre i comandi esatti e il loro esito (✅ PASS, ❌ FAIL). Se un comando non è stato eseguito, scrivere "⚠️ non verificato" esplicitamente.
|
||
|
||
4. **Mai inventare**: non affermare che un comando è stato eseguito se non lo è stato. In caso di dubbio, scrivere "non verificato".
|
||
|
||
5. **Date e path**: usare date assolute (YYYY-MM-DD) e path dal repo root quando rilevante.
|
||
|
||
6. **Tono**: pratico e diretto. Evitare muri di testo. Ogni entry deve essere leggibile in <2 minuti.
|
||
|
||
7. **Artefatti**: elencare sempre i path ai file prodotti (json, py, log, pcap).
|
||
|
||
### Esempio entry minima
|
||
|
||
```markdown
|
||
## 2026-01-29
|
||
|
||
### Obiettivo
|
||
Fix race condition PLC startup.
|
||
|
||
### Azioni
|
||
1. Aggiunto retry in `tools/compile_ir.py`
|
||
|
||
### Decisioni
|
||
- **Retry 30×0.2s**: sufficiente per startup container (~6s max)
|
||
|
||
### Validazione
|
||
```bash
|
||
python3 validate_fix.py
|
||
# ✅ PASS
|
||
```
|
||
|
||
### Artefatti
|
||
- `outputs/scenario_run/logic/plc1.py`
|
||
|
||
### Prossimo step
|
||
Testare end-to-end con ICS-SimLab
|
||
```
|
||
|
||
## Validation Rules
|
||
|
||
Validators catch:
|
||
- PLC callback invoked after each output write
|
||
- HIL initializes all declared physical_values keys
|
||
- HIL updates only `io: "output"` keys
|
||
- No reads from output-only registers, no writes to input-only registers
|
||
- No missing IDs referenced by generated code
|
||
|
||
Prefer adding a validator over adding generation complexity when a runtime crash is possible.
|
||
|
||
## Research-Plan-Implement Framework
|
||
|
||
This repository uses the Research-Plan-Implement framework with the following workflow commands:
|
||
|
||
1. `/1_research_codebase` - Deep codebase exploration with parallel AI agents
|
||
2. `/2_create_plan` - Create detailed, phased implementation plans
|
||
3. `/3_validate_plan` - Verify implementation matches plan
|
||
4. `/4_implement_plan` - Execute plan systematically
|
||
5. `/5_save_progress` - Save work session state
|
||
6. `/6_resume_work` - Resume from saved session
|
||
7. `/7_research_cloud` - Analyze cloud infrastructure (READ-ONLY)
|
||
|
||
Research findings are saved in `thoughts/shared/research/`
|
||
Implementation plans are saved in `thoughts/shared/plans/`
|
||
Session summaries are saved in `thoughts/shared/sessions/`
|
||
Cloud analyses are saved in `thoughts/shared/cloud/`
|