# HIL-OS Deployment & Portability

Making the HIL toolchain deployable and portable to any language.

## Architecture for Portability

### Component Boundaries

Each component has a clean, language-agnostic interface:

| Component | Interface | Protocol |
|-----------|-----------|----------|
| **Monitor** | JSON IPC (stdin/stdout) | JSON lines |
| **CLI** | Command-line arguments | Subcommands + flags |
| **Node.js Wrapper** | JavaScript API | EventEmitter + Promises |
| **CRUMB Bridge** | File system (.cru files) | XML template injection |
| **Firmware** | Serial wire protocol | ASCII frames + CRC |

### JSON IPC Protocol

The monitor's IPC protocol is language-agnostic. Any language can implement a client:

**Monitor → Client messages:**
```json
{"type":"ready","msg":"Connected on <port>"}
{"type":"hardware_event","pin":"D2","value":1}
{"type":"execution_complete"}
```

**Client → Monitor messages:**
```
(LISP FORM)\n
__HIL_END__\n
```

### Serial Wire Protocol

The firmware protocol is language-agnostic ASCII over serial:

```
ACTION TYPE PIN VAL1 VAL2|CRC\r
```

Any language with serial support can implement this protocol.

## Building from Source

### Prerequisites

- **Go 1.26+** — for monitor and CLI
- **Node.js 18+** — for wrapper (optional)
- **TinyGo** — for firmware compilation and flashing (https://tinygo.org)
- **Arduino IDE** (alternative) — bundles avr-gcc + avrdude for firmware flashing

### Build Commands

```powershell
# Build orchestrator (no build tag = default build)
cd firmware
go build -o ../bin/hil-orchestrator.exe .

# Build CLI (with 'cli' build tag)
go build -tags cli -o ../bin/hil-cli.exe .

# Run tests
go test -timeout 120s ./...
go test -tags cli -run TestTranspile -timeout 30s ./...
```

### Cross-Platform Builds

The toolchain is cross-platform by design:

| Platform | Build | Notes |
|----------|-------|-------|
| Windows | `go build -tags cli -o hil-cli.exe .` | Primary development platform |
| Linux | `go build -tags cli -o hil-cli .` | Fully supported |
| macOS | `go build -tags cli -o hil-cli .` | Fully supported |
| ARM (Raspberry Pi) | `GOARCH=arm GOARM=7 go build -tags cli -o hil-cli .` | For on-device monitoring |

### Build Scripts

```powershell
# build-all.ps1 — Build all components
$ErrorActionPreference = "Stop"

Write-Host "Building hil-orchestrator..."
Set-Location firmware
go build -o ../bin/hil-orchestrator.exe .
if (-not $?) { throw "Failed to build orchestrator" }

Write-Host "Building hil-cli..."
go build -tags cli -o ../bin/hil-cli.exe .
if (-not $?) { throw "Failed to build CLI" }

Write-Host "Running tests..."
go test ./... -timeout 120s
if (-not $?) { throw "Tests failed" }

go test -tags cli -run TestTranspile ./... -timeout 30s
if (-not $?) { throw "CLI tests failed" }

Write-Host "Build complete!"
```

## Language Port Specification

### Implementing a HIL Client in Another Language

To implement a HIL client in Python, Rust, C++, etc.:

1. **Spawn the monitor process:**
   ```
   hil-orchestrator.exe -ipc -port none
   ```

2. **Read JSON lines from stdout:**
   ```
   {"type":"ready","msg":"Connected on none"}
   ```

3. **Write LISP scripts to stdin:**
   ```
   (LOG "hello")\n
   __HIL_END__\n
   ```

4. **Handle hardware events:**
   ```json
   {"type":"hardware_event","pin":"D2","value":1}
   ```

5. **Detect completion:**
   ```json
   {"type":"execution_complete"}
   ```

### Python Example

```python
import subprocess
import json

class HILOs:
    def __init__(self, binary="hil-orchestrator.exe"):
        self.proc = subprocess.Popen(
            [binary, "-ipc", "-port", "none"],
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True
        )
    
    def connect(self, port="none", baud=9600):
        # Wait for ready message
        while True:
            line = self.proc.stdout.readline()
            msg = json.loads(line)
            if msg["type"] == "ready":
                return msg
    
    def execute(self, script):
        self.proc.stdin.write(script + "\n__HIL_END__\n")
        self.proc.stdin.flush()
        
        # Read until execution_complete
        while True:
            line = self.proc.stdout.readline()
            msg = json.loads(line)
            if msg["type"] == "execution_complete":
                return
            elif msg["type"] == "hardware_event":
                yield msg
            elif msg["type"] == "log":
                print(msg["msg"])
    
    def shutdown(self):
        self.proc.stdin.close()
        self.proc.wait()
```

### Rust Example

```rust
use std::process::{Command, Stdio};
use std::io::{BufRead, BufReader, Write};

struct HilOs {
    child: std::process::Child,
    stdin: std::process::ChildStdin,
    reader: BufReader<std::process::ChildStdout>,
}

impl HilOs {
    fn new(binary: &str) -> Self {
        let mut child = Command::new(binary)
            .args(&["-ipc", "-port", "none"])
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .spawn()
            .expect("Failed to start monitor");
        
        let stdin = child.stdin.take().unwrap();
        let stdout = child.stdout.take().unwrap();
        let reader = BufReader::new(stdout);
        
        Self { child, stdin, reader }
    }
    
    fn connect(&mut self) {
        loop {
            let mut line = String::new();
            self.reader.read_line(&mut line).unwrap();
            let msg: serde_json::Value = serde_json::from_str(&line).unwrap();
            if msg["type"] == "ready" {
                break;
            }
        }
    }
    
    fn execute(&mut self, script: &str) {
        writeln!(self.stdin, "{}", script).unwrap();
        writeln!(self.stdin, "__HIL_END__").unwrap();
        self.stdin.flush().unwrap();
        
        loop {
            let mut line = String::new();
            self.reader.read_line(&mut line).unwrap();
            let msg: serde_json::Value = serde_json::from_str(&line).unwrap();
            if msg["type"] == "execution_complete" {
                break;
            }
        }
    }
    
    fn shutdown(&mut self) {
        self.stdin.shutdown(std::net::Shutdown::Write).unwrap();
        self.child.wait().unwrap();
    }
}
```

## Package Distribution

### Go Modules

The monitor and CLI are already Go modules. To publish:

```bash
# Tag a release
git tag v1.0.0
git push origin v1.0.0

# Install via go install
go install github.com/user/hil-OS/firmware@latest  # orchestrator (no build tag)
# For CLI: clone and build with -tags cli
```

### Binary Releases

Build binaries for all platforms and upload to GitHub Releases:

```powershell
# Windows
go build -tags cli -o hil-cli-windows-amd64.exe .

# Linux
GOOS=linux GOARCH=amd64 go build -tags cli -o hil-cli-linux-amd64 .

# macOS
GOOS=darwin GOARCH=amd64 go build -tags cli -o hil-cli-darwin-amd64 .

# Raspberry Pi
GOOS=linux GOARCH=arm GOARM=7 go build -tags cli -o hil-cli-linux-arm .
```

### npm Package (for Node.js wrapper)

```json
{
  "name": "hil-node",
  "version": "1.0.0",
  "main": "hil.js",
  "bin": {
    "hil-cli": "./hil-cli.exe"
  },
  "files": [
    "hil.js",
    "hil-cli.exe"
  ]
}
```

## CRUMB Portability

### .cru File Format

The `.cru` format is XML-based. The transpiler injects C code into:
```xml
<toolID>20</toolID>  <!-- Arduino Nano -->
...
<xsd:string>/* injected C code */</xsd:string>
```

### Cross-Platform CRUMB

CRUMB is Windows-only (WPF + Unity). For Linux/macOS:
- Use Wine to run CRUMBWPF.exe
- Or implement alternative simulation backends
- The transpiler generates standard Arduino C — any Arduino IDE can compile it

## Testing Strategy

### Unit Tests

```powershell
# Monitor tests (~97s)
cd firmware
go test ./... -timeout 120s -v

# CLI tests (~0.5s)
go test -tags cli -run TestTranspile ./... -timeout 30s -v
```

### Integration Tests

```powershell
# Full pipeline: LISP → C → .cru
hil-cli crumb test.lisp --strict
# Verify .cru XML well-formedness
# Verify C code correctness

# Headless execution
hil-cli simulate test.lisp
# Verify JSON IPC output
```

### Cross-Platform Testing

Test on:
- Windows (primary)
- Linux (Ubuntu 22.04+)
- macOS (Ventura+)
- Raspberry Pi (ARM)

## Future Language Ports

### Priority Order

1. **Python** — Most popular for education/research
2. **Rust** — Performance-critical applications
3. **C++** — Embedded/desktop applications
4. **JavaScript/TypeScript** — Already have Node.js wrapper
5. **C#** — .NET ecosystem
6. **Java** — Enterprise environments

### Language-Specific Considerations

| Language | Serial Support | JSON Support | Process Spawning |
|----------|---------------|--------------|------------------|
| Python | pyserial | json | subprocess |
| Rust | serialport | serde_json | std::process |
| C++ | Boost.Asio / serialport | nlohmann/json | popen |
| C# | System.IO.Ports | System.Text.Json | Process |
| Java | jSerialComm | Gson/Jackson | ProcessBuilder |

## Deployment Checklist

- [ ] Build scripts for all platforms
- [ ] Binary releases on GitHub
- [ ] npm package for Node.js wrapper
- [ ] PyPI package for Python client
- [ ] Documentation updated
- [ ] Cross-platform testing
- [ ] CI/CD pipeline (GitHub Actions)
- [ ] Language port examples (Python, Rust, C++)
