diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..8a087cb
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,32 @@
+name: CI
+
+on: [push, pull_request]
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup Node
+ uses: actions/setup-node@v3
+ with:
+ node-version: 20
+ - name: Install Node deps
+ working-directory: LumenIO/clients/web
+ run: npm install
+ - name: Run vitest
+ working-directory: LumenIO/clients/web
+ run: npm test
+ - name: Run playwright
+ working-directory: LumenIO/clients/web
+ run: npx playwright install --with-deps && npx playwright test
+ - name: Setup Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: '3.11'
+ - name: Install Python deps
+ working-directory: LumenIO/hub
+ run: pip install -r requirements.txt
+ - name: Run pytest
+ working-directory: LumenIO/hub
+ run: pytest
diff --git a/.github/workflows/matrix-ci.yml b/.github/workflows/matrix-ci.yml
new file mode 100644
index 0000000..0fc6023
--- /dev/null
+++ b/.github/workflows/matrix-ci.yml
@@ -0,0 +1,79 @@
+name: LumenIO Matrix CI
+
+on:
+ push:
+ branches: [main, develop]
+ pull_request:
+ branches: [main]
+
+jobs:
+ core:
+ name: Core Tests
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v4
+ with:
+ python-version: '3.11'
+ - run: |
+ cd LumenIO/packages/lumenio-core
+ pip install -e .
+ pytest tests/
+
+ variants:
+ name: Variant Tests
+ runs-on: ${{ matrix.os }}
+ needs: core
+ strategy:
+ matrix:
+ variant: [pc, mobile, pcproj, mobileproj, standalone, wearables]
+ os: [ubuntu-latest]
+ include:
+ - variant: pc
+ sensors: webcam,keyboard,mouse
+ e2e: desktop
+ - variant: mobile
+ sensors: camera,gyro,touch,accelerometer
+ e2e: mobile
+ - variant: pcproj
+ sensors: webcam,keyboard,mouse,projector
+ e2e: desktop-projector
+ - variant: mobileproj
+ sensors: camera,gyro,touch,accelerometer,projector
+ e2e: mobile-projector
+ - variant: standalone
+ sensors: camera,lidar,projector,compute
+ e2e: embedded
+ - variant: wearables
+ sensors: imu,camera,haptic,display
+ e2e: wearable
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v4
+ with:
+ python-version: '3.11'
+ - name: Install Core
+ run: |
+ cd LumenIO/packages/lumenio-core
+ pip install -e .
+ - name: Test Variant ${{ matrix.variant }}
+ run: |
+ cd LumenIO/packages/lumenio-${{ matrix.variant }}
+ pip install -e .
+ pytest tests/unit/
+ - name: E2E Tests ${{ matrix.variant }}
+ run: |
+ cd LumenIO/packages/lumenio-${{ matrix.variant }}
+ npm install
+ npx playwright install
+ npx playwright test --project=${{ matrix.e2e }}
+
+ integration:
+ name: Cross-Variant Integration
+ runs-on: ubuntu-latest
+ needs: variants
+ steps:
+ - uses: actions/checkout@v4
+ - run: |
+ python LumenIO/scripts/validate_contracts.py
+ python LumenIO/scripts/version_compatibility_check.py
diff --git a/LumenIO/VERSIONING.md b/LumenIO/VERSIONING.md
new file mode 100644
index 0000000..d2a368d
--- /dev/null
+++ b/LumenIO/VERSIONING.md
@@ -0,0 +1,37 @@
+# LumenIO Versioning & Release Policy
+
+## Core (LumenIO-Core)
+- Semantic Versioning: MAJOR.MINOR.PATCH
+- MAJOR: Breaking contract changes
+- MINOR: Backward-compatible features
+- PATCH: Bug fixes
+
+## Variants
+- Depend on Core with ranges like `^0.1.0`
+- Version independently
+- Must pass Core contract tests
+
+## Release Process
+1. Core release
+2. Update variant core ranges
+3. Matrix CI validates all combinations
+4. Integration tests ensure compatibility
+
+## CHANGELOG Format
+```
+## [Version] - YYYY-MM-DD
+### Core
+- Added: ...
+- Changed: ...
+- Fixed: ...
+### Variant Updates
+- PC: ...
+- Mobile: ...
+### Breaking Changes
+- ...
+```
+
+## Compatibility Matrix
+| Core | PC | Mobile | PCProj | MobileProj | Standalone | Wearables |
+|------|----|--------|--------|------------|------------|-----------|
+|0.1.x|✓|✓|✓|✓|✓|✓|
diff --git a/LumenIO/bootstrap.xml b/LumenIO/bootstrap.xml
new file mode 100644
index 0000000..5abd716
--- /dev/null
+++ b/LumenIO/bootstrap.xml
@@ -0,0 +1,80 @@
+
+
+ LumenIO
+ Gesture-first multi-device programming interface ecosystem
+ https://github.com/testingground/testingground.github.io
+
+
+ LumenIO-Core
+ Shared contracts, schemas, gesture FSM, calibration, agents
+ 0.1.0
+
+ contracts
+ schemas
+ gestures
+ calibration
+ agents
+ common
+
+
+
+
+ LumenIO-PC
+ desktop
+ webcam,keyboard,mouse
+ ^0.1.0
+
+
+ LumenIO-Mobile
+ mobile
+ camera,gyro,touch,accelerometer
+ ^0.1.0
+
+
+ LumenIO-PCProj
+ desktop+projector
+ webcam,projector,keyboard,mouse
+ ^0.1.0
+
+
+ LumenIO-MobileProj
+ mobile+projector
+ camera,projector,gyro,touch,accelerometer
+ ^0.1.0
+
+
+ LumenIO-Standalone
+ embedded
+ camera,lidar,projector,compute
+ ^0.1.0
+
+
+ LumenIO-Wearables
+ wearable
+ imu,camera,haptic,display
+ ^0.1.0
+
+
+
+ Python 3.11+
+ FastAPI + aiortc
+ OpenCV
+ MediaPipe/TFLite
+ Blender Python API
+ WebRTC/WebGPU/WebXR
+ Node 20
+ Vite/Vitest/Playwright
+
+
+ LLM/NN Prompt Engineer
+ Mech/Electrical/Industrial Engineer
+
+
+ CODE_FIRST_MINIMAL
+ semver_core_pinned_variants
+
+
+ LumenIO
+ bootstrap.xml
+
+
diff --git a/LumenIO/clients/web/e2e/app.spec.js b/LumenIO/clients/web/e2e/app.spec.js
new file mode 100644
index 0000000..ab1e6ad
--- /dev/null
+++ b/LumenIO/clients/web/e2e/app.spec.js
@@ -0,0 +1,6 @@
+import { test, expect } from '@playwright/test';
+
+test('renders greeting', async ({ page }) => {
+ await page.setContent('
Hello LumenIO
');
+ await expect(page.locator('#app')).toHaveText('Hello LumenIO');
+});
diff --git a/LumenIO/clients/web/index.html b/LumenIO/clients/web/index.html
new file mode 100644
index 0000000..0e6a123
--- /dev/null
+++ b/LumenIO/clients/web/index.html
@@ -0,0 +1,11 @@
+
+
+
+
+ LumenIO
+
+
+
+
+
+
diff --git a/LumenIO/clients/web/package.json b/LumenIO/clients/web/package.json
new file mode 100644
index 0000000..7a54041
--- /dev/null
+++ b/LumenIO/clients/web/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "lumenio-web-client",
+ "version": "0.1.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "test": "vitest run",
+ "test:e2e": "playwright test"
+ },
+ "devDependencies": {
+ "@playwright/test": "^1.43.0",
+ "vite": "^5.2.0",
+ "vitest": "^1.5.0"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+}
diff --git a/LumenIO/clients/web/src/greet.js b/LumenIO/clients/web/src/greet.js
new file mode 100644
index 0000000..021dae1
--- /dev/null
+++ b/LumenIO/clients/web/src/greet.js
@@ -0,0 +1,3 @@
+export function greet(name) {
+ return `Hello ${name}`;
+}
diff --git a/LumenIO/clients/web/src/main.js b/LumenIO/clients/web/src/main.js
new file mode 100644
index 0000000..b2fa08c
--- /dev/null
+++ b/LumenIO/clients/web/src/main.js
@@ -0,0 +1,3 @@
+import { greet } from './greet.js';
+
+document.getElementById('app').textContent = greet('LumenIO');
diff --git a/LumenIO/clients/web/test/greet.test.js b/LumenIO/clients/web/test/greet.test.js
new file mode 100644
index 0000000..e864955
--- /dev/null
+++ b/LumenIO/clients/web/test/greet.test.js
@@ -0,0 +1,8 @@
+import { describe, it, expect } from 'vitest';
+import { greet } from '../src/greet.js';
+
+describe('greet', () => {
+ it('greets by name', () => {
+ expect(greet('World')).toBe('Hello World');
+ });
+});
diff --git a/LumenIO/clients/web/vitest.config.js b/LumenIO/clients/web/vitest.config.js
new file mode 100644
index 0000000..ec3bfec
--- /dev/null
+++ b/LumenIO/clients/web/vitest.config.js
@@ -0,0 +1,5 @@
+export default {
+ test: {
+ include: ['test/**/*.test.js']
+ }
+};
diff --git a/LumenIO/hub/__init__.py b/LumenIO/hub/__init__.py
new file mode 100644
index 0000000..11bce57
--- /dev/null
+++ b/LumenIO/hub/__init__.py
@@ -0,0 +1 @@
+"""Hub package."""
diff --git a/LumenIO/hub/main.py b/LumenIO/hub/main.py
new file mode 100644
index 0000000..efa6c5d
--- /dev/null
+++ b/LumenIO/hub/main.py
@@ -0,0 +1,7 @@
+from fastapi import FastAPI
+
+app = FastAPI()
+
+@app.get('/ping')
+async def ping():
+ return {'msg': 'pong'}
diff --git a/LumenIO/hub/requirements.txt b/LumenIO/hub/requirements.txt
new file mode 100644
index 0000000..fdcc7c2
--- /dev/null
+++ b/LumenIO/hub/requirements.txt
@@ -0,0 +1,4 @@
+fastapi
+uvicorn
+httpx
+jsonschema
diff --git a/LumenIO/hub/tests/test_ping.py b/LumenIO/hub/tests/test_ping.py
new file mode 100644
index 0000000..39d4aa0
--- /dev/null
+++ b/LumenIO/hub/tests/test_ping.py
@@ -0,0 +1,10 @@
+import pytest
+from httpx import AsyncClient
+from main import app
+
+@pytest.mark.asyncio
+async def test_ping():
+ async with AsyncClient(app=app, base_url='http://test') as ac:
+ res = await ac.get('/ping')
+ assert res.status_code == 200
+ assert res.json() == {'msg': 'pong'}
diff --git a/LumenIO/hub/tests/test_schema.py b/LumenIO/hub/tests/test_schema.py
new file mode 100644
index 0000000..fee6ef5
--- /dev/null
+++ b/LumenIO/hub/tests/test_schema.py
@@ -0,0 +1,9 @@
+import json
+from jsonschema import validate
+from pathlib import Path
+
+def test_gesture_schema():
+ schema_path = Path(__file__).resolve().parent.parent.parent / 'schemas' / 'gesture.json'
+ schema = json.loads(schema_path.read_text())
+ sample = {'type': 'wave', 'confidence': 0.9}
+ validate(instance=sample, schema=schema)
diff --git a/LumenIO/packages/lumenio-core/contracts.json b/LumenIO/packages/lumenio-core/contracts.json
new file mode 100644
index 0000000..100bc59
--- /dev/null
+++ b/LumenIO/packages/lumenio-core/contracts.json
@@ -0,0 +1,80 @@
+{
+ "contracts": {
+ "gesture_fsm": {
+ "interface": "IGestureFSM",
+ "methods": [
+ "register_gesture(pattern: GesturePattern, callback: Callable)",
+ "process_frame(frame: Frame) -> GestureEvent[]",
+ "get_state() -> FSMState",
+ "reset_state() -> None"
+ ],
+ "events": [
+ "gesture_detected",
+ "gesture_started",
+ "gesture_completed",
+ "gesture_cancelled"
+ ]
+ },
+ "calibration_api": {
+ "interface": "ICalibration",
+ "methods": [
+ "calibrate_device(device_config: DeviceConfig) -> CalibrationResult",
+ "save_calibration(device_id: str, data: CalibrationData) -> bool",
+ "load_calibration(device_id: str) -> CalibrationData | None",
+ "validate_calibration(data: CalibrationData) -> ValidationResult"
+ ]
+ },
+ "agent_tools": {
+ "interface": "IAgentTool",
+ "signatures": [
+ "execute(action: ActionSpec, context: ExecutionContext) -> ToolResult",
+ "validate_input(input: Any) -> ValidationResult",
+ "get_capabilities() -> CapabilitySet",
+ "cleanup() -> None"
+ ]
+ },
+ "device_adapter": {
+ "interface": "IDeviceAdapter",
+ "methods": [
+ "initialize(config: DeviceConfig) -> bool",
+ "get_sensor_data() -> SensorData",
+ "send_output(data: OutputData) -> bool",
+ "get_capabilities() -> DeviceCapabilities"
+ ]
+ }
+ },
+ "schemas": {
+ "gesture_pattern": {
+ "type": "object",
+ "properties": {
+ "id": {"type": "string"},
+ "name": {"type": "string"},
+ "sequence": {"type": "array", "items": {"$ref": "#/definitions/gesture_keypoint"}},
+ "tolerance": {"type": "number", "minimum": 0, "maximum": 1},
+ "min_confidence": {"type": "number", "minimum": 0, "maximum": 1}
+ },
+ "required": ["id", "name", "sequence"]
+ },
+ "device_config": {
+ "type": "object",
+ "properties": {
+ "device_id": {"type": "string"},
+ "device_type": {"enum": ["desktop", "mobile", "embedded", "wearable"]},
+ "sensors": {"type": "array", "items": {"type": "string"}},
+ "capabilities": {"$ref": "#/definitions/device_capabilities"},
+ "calibration_data": {"$ref": "#/definitions/calibration_data"}
+ },
+ "required": ["device_id", "device_type", "sensors"]
+ },
+ "agent_action": {
+ "type": "object",
+ "properties": {
+ "tool": {"type": "string"},
+ "operation": {"type": "string"},
+ "parameters": {"type": "object"},
+ "context": {"$ref": "#/definitions/execution_context"}
+ },
+ "required": ["tool", "operation"]
+ }
+ }
+}
diff --git a/LumenIO/packages/lumenio-mobile/.gitkeep b/LumenIO/packages/lumenio-mobile/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/LumenIO/packages/lumenio-mobileproj/.gitkeep b/LumenIO/packages/lumenio-mobileproj/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/LumenIO/packages/lumenio-pc/.gitkeep b/LumenIO/packages/lumenio-pc/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/LumenIO/packages/lumenio-pcproj/.gitkeep b/LumenIO/packages/lumenio-pcproj/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/LumenIO/packages/lumenio-standalone/.gitkeep b/LumenIO/packages/lumenio-standalone/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/LumenIO/packages/lumenio-wearables/.gitkeep b/LumenIO/packages/lumenio-wearables/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/LumenIO/schemas/gesture.json b/LumenIO/schemas/gesture.json
new file mode 100644
index 0000000..177de45
--- /dev/null
+++ b/LumenIO/schemas/gesture.json
@@ -0,0 +1,11 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "Gesture",
+ "type": "object",
+ "properties": {
+ "type": {"type": "string"},
+ "confidence": {"type": "number", "minimum": 0, "maximum": 1}
+ },
+ "required": ["type", "confidence"],
+ "additionalProperties": false
+}
diff --git a/LumenIO/scripts/scaffold_variants.json b/LumenIO/scripts/scaffold_variants.json
new file mode 100644
index 0000000..aae6f47
--- /dev/null
+++ b/LumenIO/scripts/scaffold_variants.json
@@ -0,0 +1,59 @@
+{
+ "variant_template": {
+ "structure": {
+ "package.json": "variant package manifest",
+ "src/": {
+ "adapters/": "device-specific adapter implementations",
+ "config/": "variant-specific configuration",
+ "main.py": "entry point importing Core + adapters"
+ },
+ "tests/": {
+ "unit/": "variant-specific unit tests",
+ "e2e/": "device-specific E2E tests (Playwright)"
+ },
+ "pyproject.toml": "Python dependencies + Core version pin"
+ },
+ "example_package_json": {
+ "name": "@lumenio/pc",
+ "version": "0.1.0",
+ "description": "LumenIO PC Desktop Variant",
+ "main": "src/main.py",
+ "dependencies": {
+ "@lumenio/core": "^0.1.0"
+ },
+ "devDependencies": {
+ "vitest": "^2.0.0",
+ "playwright": "^1.40.0"
+ },
+ "scripts": {
+ "dev": "python src/main.py --dev",
+ "build": "python -m build",
+ "test": "vitest",
+ "test:e2e": "playwright test"
+ },
+ "lumenio": {
+ "variant": "pc",
+ "target": "desktop",
+ "sensors": ["webcam", "keyboard", "mouse"],
+ "features": {
+ "projector": false,
+ "mobile_sensors": false,
+ "embedded_compute": false
+ }
+ }
+ },
+ "adapter_template": {
+ "class_name": "PCDeviceAdapter",
+ "imports": ["from lumenio_core.contracts import IDeviceAdapter"],
+ "methods": ["initialize", "get_sensor_data", "send_output", "get_capabilities"]
+ }
+ },
+ "variant_configs": {
+ "pc": {"sensors": ["webcam", "keyboard", "mouse"], "projector": false},
+ "mobile": {"sensors": ["camera", "gyro", "touch", "accelerometer"], "projector": false},
+ "pcproj": {"sensors": ["webcam", "keyboard", "mouse", "projector"], "projector": true},
+ "mobileproj": {"sensors": ["camera", "gyro", "touch", "accelerometer", "projector"], "projector": true},
+ "standalone": {"sensors": ["camera", "lidar", "projector", "compute"], "embedded": true},
+ "wearables": {"sensors": ["imu", "camera", "haptic", "display"], "wearable": true}
+ }
+}