From e171f46f5807d348f5446fe5a706e69911e69731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Lange?= Date: Mon, 13 Apr 2026 16:08:06 +0200 Subject: [PATCH 1/4] =?UTF-8?q?docs:=20reassessment=20=E2=80=94=20update?= =?UTF-8?q?=20README,=20ROADMAP,=20AGENTS=20+=20add=20cockpit=20and=20impl?= =?UTF-8?q?ementation=20plan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit README - Rewrite to reflect v1.6.1 state: 6 Workbench plugins, grid-messenger, internal LAN proxy (Caddy + Pi-hole), node registry at ~/.config/faigrid - Add ecosystem table with faisignal integration note - Add Workbench Plugins and Grid Messenger sections with current feature detail - Add repository layout tree and troubleshooting table ROADMAP - Replace outdated versioning (v1.3.0 bridge) with accurate current baseline - Add Phase 1 (Signal Readiness v1.7-v1.9): /api/v1/health, structured event log, grid-doctor --json, faisignal integration guide - Add Phase 2 (Operator Cockpit v2.0): faigate-inspired dashboard spec - Add Phase 3 (Execution Classes & GitOps) and Phase 4 (fusionAIzeOS) - Align with faisignal ROADMAP integration points (runtime health signals, event stream, cross-layer correlation) AGENTS.md - Update node list with current services (openclaw, codenomad, faigate, grid-messenger, Restic, Pi-hole) - Add faisignal integration note and registry path correction - Add cockpit scope clarification (lightweight, no-build, stays in-scope) docs/IMPLEMENTATION-PLAN.md (new) - Gap analysis from v1.6.1 baseline - v1.7-v1.9 release line: health API, structured events, Signal integration - v2.0 cockpit: full technical spec (file layout, HTTP API, system service) docs/COCKPIT.md (new) - Full design spec for Grid operator cockpit - faigate design language inheritance + Grid-specific differentiation (green) - 7-section IA: Overview / Nodes / Services / Messenger / Workbench / Signals / Setup - Color tokens, layout spec, navigation rail, scope boundary Co-Authored-By: Claude Sonnet 4.6 --- AGENTS.md | 14 +- README.md | 266 +++++++++++++++++-------- docs/COCKPIT.md | 376 ++++++++++++++++++++++++++++++++++++ docs/IMPLEMENTATION-PLAN.md | 259 +++++++++++++++++++++++++ docs/ROADMAP.md | 204 +++++++++++++------ 5 files changed, 979 insertions(+), 140 deletions(-) create mode 100644 docs/COCKPIT.md create mode 100644 docs/IMPLEMENTATION-PLAN.md diff --git a/AGENTS.md b/AGENTS.md index 43ed908..77625ec 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,12 +8,14 @@ This repository is `faigrid`, the official realization of **fusionAIze Grid**. Its job is to define **where** AI-native workloads execute, under **what constraints**, with **what isolation**, through which **queues/runners**, and with which **secrets, observability, and backup patterns**. It physically provisions and structurally connects the 4+1 Node Architecture: -1. **grid-edge**: Edge ingress workloads (Public intake, TLS, reverse proxy, SSO). -2. **grid-core**: Trusted internal services and queued automations (n8n, orchestration helpers). +1. **grid-edge**: Edge ingress workloads (Public intake, TLS, Caddy reverse proxy, Pi-hole DNS, SSO). +2. **grid-core**: Trusted internal services and queued automations (n8n, openclaw, codenomad, faigate, grid-messenger). 3. **grid-worker**: Specialized runners, local model workers (LAN-only inference), and isolated task workers. -4. **grid-backup**: Recovery and observability layer. +4. **grid-backup**: Recovery and observability layer (Restic, Synology). 5. **grid-external**: Cloud model bridges and distributed extensions. +Grid feeds structured runtime health signals (runner failures, service state, queue backlog) into **fusionAIze Signal** (`faisignal`) for cross-layer operational intelligence. Grid's cockpit surface and Signal's ingestion pipeline are designed to be complementary, not overlapping. + In the fusionAIze ecosystem, Grid runs the compute topology. It is explicitly **decoupled** from `fusionAIzeOS`, which serves as the "team operating logic" (defining *how* humans and virtual AI coworkers collaborate, roles, and identity). **Key Tenets:** @@ -26,8 +28,10 @@ In the fusionAIze ecosystem, Grid runs the compute topology. It is explicitly ** The priority is maintaining a universal, highly secure, and easily deployable execution substrate. -Do not optimize the repository around complex web frameworks, operating logic dashboards, or model routing logic (which belong in OS, Studio, or Gate). -Optimize it around rock-solid shell orchestration (`install.sh`), state detection (`.grid-state`), cleanly isolated Workbench plugin registries (`plugins/`), runner layer definition (`docker compose`), and robust Bash-level testing (`tests/`). +Do not optimize the repository around complex web frameworks, operating logic dashboards, or model routing logic (which belong in OS, Gate, and Lens). +Optimize it around rock-solid shell orchestration (`install.sh`), state detection (`~/.config/faigrid/registry/`), cleanly isolated Workbench plugin registries (`plugins/`), runner layer definition (`docker compose`), and robust Bash-level testing (`tests/`). + +The Grid Cockpit (planned v2.0) is an exception to the "no web framework" rule — it is a lightweight, no-build, single-file HTML dashboard served by the existing Python messenger process. It stays inside Grid's scope: node health, service status, pending decisions, workbench state. It does not replicate Gate analytics or Signal correlation. ## Architecture principles diff --git a/README.md b/README.md index 9adf0fe..ee1b9b2 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,49 @@ # fusionAIze Grid (faigrid) -[![repo-safety](https://github.com/fusionAIze/faigrid/actions/workflows/repo-safety.yml/badge.svg)](https://github.com/fusionAIze/faigrid/actions/workflows/repo-safety.yml) [![Lint](https://github.com/fusionAIze/faigrid/actions/workflows/lint.yml/badge.svg)](https://github.com/fusionAIze/faigrid/actions/workflows/lint.yml) [![Test](https://github.com/fusionAIze/faigrid/actions/workflows/test.yml/badge.svg)](https://github.com/fusionAIze/faigrid/actions/workflows/test.yml) [![Release](https://img.shields.io/github/v/release/fusionAIze/faigrid?display_name=tag)](https://github.com/fusionAIze/faigrid/releases) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) -[![OpenClaw-friendly](https://img.shields.io/badge/OpenClaw-friendly-111827.svg)](https://openclaw.ai/) [![n8n-automated](https://img.shields.io/badge/n8n-automated-ea4b71.svg?logo=n8n&logoColor=white)](https://n8n.io/) [![Docker-ready](https://img.shields.io/badge/docker-ready-2496ED?logo=docker&logoColor=white)](https://www.docker.com/) [![Bash-powered](https://img.shields.io/badge/Language-Bash-4EAA25.svg)](https://www.gnu.org/software/bash/) +[![repo-safety](https://github.com/fusionAIze/faigrid/actions/workflows/repo-safety.yml/badge.svg)](https://github.com/fusionAIze/faigrid/actions/workflows/repo-safety.yml) +[![Lint](https://github.com/fusionAIze/faigrid/actions/workflows/lint.yml/badge.svg)](https://github.com/fusionAIze/faigrid/actions/workflows/lint.yml) +[![Test](https://github.com/fusionAIze/faigrid/actions/workflows/test.yml/badge.svg)](https://github.com/fusionAIze/faigrid/actions/workflows/test.yml) +[![Release](https://img.shields.io/github/v/release/fusionAIze/faigrid?display_name=tag)](https://github.com/fusionAIze/faigrid/releases) +[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +[![OpenClaw-friendly](https://img.shields.io/badge/OpenClaw-friendly-111827.svg)](https://openclaw.ai/) +[![n8n-automated](https://img.shields.io/badge/n8n-automated-ea4b71.svg?logo=n8n&logoColor=white)](https://n8n.io/) +[![Docker-ready](https://img.shields.io/badge/docker-ready-2496ED?logo=docker&logoColor=white)](https://www.docker.com/) +[![Bash-powered](https://img.shields.io/badge/Language-Bash-4EAA25.svg)](https://www.gnu.org/software/bash/) > **The sovereign execution substrate for AI-native operations.** -**fusionAIze Grid (faigrid)** is the execution substrate of the fusionAIze ecosystem. Its explicit job is to define **where** AI-native work runs, under **what constraints**, with **what isolation**, through which **queues and runners**, and with which **observability and recovery patterns**. - -It provides a modular, secure, and self-hosted foundation across local, on-prem, private cloud, public cloud, and hybrid deployments. +**fusionAIze Grid** defines *where* AI-native work runs, under *what constraints*, with *what isolation*, through which *queues and runners*, and with which *observability and recovery patterns*. It is the execution layer of the fusionAIze ecosystem — not the context, memory, or routing layer. --- ### Navigation -[The Ecosystem](#the-ecosystem) • -[Architecture](#architecture) • -[Quick Start](#quick-start) • -[Troubleshooting](#troubleshooting) • -[Grid Modules](#grid-modules) • -[Repository Layout](#repository-layout) • + +[Ecosystem](#the-ecosystem) • +[Architecture](#architecture) • +[Quick Start](#quick-start) • +[Grid Modules](#grid-modules) • +[Workbench](#workbench-plugins) • +[Messenger](#grid-messenger) • +[Repository Layout](#repository-layout) • +[Troubleshooting](#troubleshooting) • [License](#license) --- ## The Ecosystem -`faigrid` is part of a 5-layer product architecture that operationalizes human-AI fusion teams: -1. **Gate (`faigate`)**: AI-native gateway for models, providers, tools and clients. *(Connects)* -2. **Lens**: Compression, translation, and context-focusing layer. *(Filters)* -3. **Fabric**: Shared context and memory. *(Remembers & Serves)* -4. **Grid (`faigrid`)**: This repository. The sovereign execution substrate. *(Executes)* -5. **OS (`fusionAIzeOS`)**: The operating logic defining how humans and virtual AI coworkers collaborate. *(Orchestrates Logic)* +`faigrid` is part of the fusionAIze 5-layer product architecture that operationalizes human-AI fusion teams: + +| Layer | Repo | Role | +|---|---|---| +| **Gate** | `faigate` | AI-native gateway for models, providers, tools and clients | +| **Lens** | `failens` | Compression, translation, and context-focusing | +| **Fabric** | `faifabric` | Shared context, memory, and knowledge | +| **Grid** | `faigrid` ← | Sovereign execution substrate | +| **Signal** | `faisignal` | Observability, monitoring, and signal layer | +| **OS** | `fusionAIzeOS` | Operating logic for human-AI fusion teams | -### Core Philosophy -- **Execution First**: We define rigorous *Execution Classes* (Edge, Internal, Queued, Runners, Local Workers) rather than fuzzy environments. -- **Agent Agnostic**: We provide the raw OS execution substrate agnostic of the framework (OpenClaw, AutoGen, CrewAI). -- **Macher-Fokus (Builder Focus)**: Designed originally for the **Solo Operator** and scalable to **Small Teams** and **SMBs** without enterprise compliance theater. -- **Portability**: Full freedom to run proprietary SaaS routes (via Cloud Bridges) or fully local open-source operations (via Local Model Workers). +faigrid feeds **runtime health signals** (runner failures, service state, queue backlog, job completion) directly into fusionAIze Signal for cross-layer operational intelligence. --- @@ -43,94 +51,198 @@ It provides a modular, secure, and self-hosted foundation across local, on-prem, The infrastructure relies on a decoupled, secure **4+1 Node Architecture**: -```text - Public Internet - │ (HTTPS) - ┌─────────────────────▼─────────────────────┐ - │ GRID EDGE │ (1) Ingress / Proxy - │ (Caddy Reverse Proxy, SSO, Auth) │ - └─────────────────────┬─────────────────────┘ - │ (Internal TLS) - ┌─────────────────────▼─────────────────────┐ - │ GRID CORE │ (2) Trusted Internal Services - │ (n8n, OpenClaw, RTK, Postgres, Redis) │ / Queued Automations - └──────┬─────────────────────────────┬──────┘ - │ (Local API) │ (Encrypted Tunnels) - ┌──────────▼──────────┐ ┌──────────▼──────────┐ - │ GRID WORKER │ │ GRID EXTERNAL │ (5) Cloud Model Bridges - │ (Local LLM Nodes) │ │ (Cloud VPS Node) │ / Global Extension - └─────────────────────┘ └─────────────────────┘ - │ - ┌──────────▼──────────┐ - │ GRID BACKUP │ (4) Observability & - │ (Synology / Restic) │ Recovery Base - └─────────────────────┘ ``` + Public Internet + │ (HTTPS) + ┌─────────────────────▼─────────────────────┐ + │ GRID EDGE │ (1) Ingress / Proxy + │ Caddy Reverse Proxy · Pi-hole DNS · SSO │ + └─────────────────────┬─────────────────────┘ + │ (Internal TLS / .grid) + ┌─────────────────────▼─────────────────────┐ + │ GRID CORE │ (2) Trusted Internal Services + │ n8n · openclaw · codenomad · faigate │ + │ grid-messenger · Postgres · Redis │ + └──────┬─────────────────────────────┬──────┘ + │ (Local API) │ (Encrypted Tunnels) + ┌──────────▼──────────┐ ┌──────────▼──────────┐ + │ GRID WORKER │ │ GRID EXTERNAL │ (5) Cloud Model Bridges + │ Local LLM · Ollama │ │ Cloud VPS Node │ + └──────────┬──────────┘ └─────────────────────┘ + │ + ┌──────────▼──────────┐ + │ GRID BACKUP │ (4) Observability & Recovery + │ Synology · Restic │ + └─────────────────────┘ +``` + +**Execution Classes** — Grid's core abstraction: + +| Class | Where | What | +|---|---|---| +| Edge Ingress | grid-edge | TLS termination, reverse proxy, DNS, auth | +| Trusted Internal | grid-core | n8n, APIs, orchestration, messaging | +| Queued Automations | grid-core | Workflow engine, background tasks | +| Local Model Workers | grid-worker | Ollama, LM Studio, LAN-only inference | +| Cloud Model Bridges | grid-external | Egress-controlled cloud reasoning | +| Recovery Base | grid-backup | Automated immutable backup pipelines | --- ## Quick Start -Get your faigrid ecosystem live in 2 steps: - ```bash -# 1. Clone & Provision (Detects macOS/Linux automatically) -git clone https://github.com/fusionAIze/faigrid.git faigrid -cd faigrid && bash install.sh +# Clone and provision (detects macOS/Linux automatically) +git clone https://github.com/fusionAIze/faigrid.git && cd faigrid +bash install.sh -# 2. Deploy your first node (e.g. Core Runtime) +# Deploy a specific role, e.g. Core ./install.sh --mode local --role core --strategy 1 --yes ``` -Done. Your AI execution substrate is now accessible via the **Terminal Dashboard**: +Node registry is stored at `~/.config/faigrid/registry/` and persists across reinstalls and Homebrew upgrades. + ```bash -./scripts/grid-dashboard.sh +# Open the interactive Workbench +./core/workbench/scripts/control.sh + +# Run diagnostics +./scripts/grid-doctor.sh + +# Check live logs +tail -f /var/log/faigrid/grid-system.log ``` --- -## Troubleshooting +## Grid Modules -If something feels off, run the **Grid Doctor**. It performs comprehensive sanity checks on resources, connectivity, and local state: +| Module | Role | Services | +|---|---|---| +| **grid-edge** | Public gatekeeper | Caddy, Pi-hole, CrowdSec, SSO | +| **grid-core** | Private compute substrate | n8n, openclaw, codenomad, faigate, grid-messenger | +| **grid-worker** | Isolated execution | Ollama, LM Studio, shell runners | +| **grid-backup** | Safety net | Restic, Synology, automated snapshots | +| **grid-external** | Cloud bridge | Egress-aware VPS, external model access | -```bash -./scripts/grid-doctor.sh -``` +--- -To view live system telemetry and consolidated logs: -```bash -tail -f /var/log/faigrid/grid-system.log -``` +## Workbench Plugins + +The **Grid Workbench** (`core/workbench/`) is the interactive operator console for managing services on each node. Plugins are self-contained Bash modules with a standard interface (`tool_configure`, `tool_doctor`, `tool_update`). + +**Current plugin registry:** + +| Plugin | Category | Purpose | +|---|---|---| +| `n8n` | automation | Workflow engine — install, configure, manage | +| `openclaw` | agents | OpenClaw agent runtime — deploy, update, doctor | +| `codenomad` | agents | Codenomad coding agent — configure, manage | +| `faigate` | gateway | fusionAIze Gate — install, configure, health | +| `caddy` | proxy | Internal LAN reverse proxy — `.grid` TLD + Pi-hole DNS | +| `grid-messenger` | comms | Telegram decision bridge — configure, health | + +Plugin categories: `agents/` · `automation/` · `proxy/` · `comms/` --- -## Grid Modules +## Grid Messenger + +`grid-messenger` is the **Telegram decision and notification bridge** for the Grid. It runs as a systemd service on grid-core and exposes a local HTTP API (`127.0.0.1:9119`) that any registered app (n8n, openclaw, codenomad, etc.) can call to push decisions or notifications. + +**Three decision types:** + +| Type | UI | Use case | +|---|---|---| +| `approve` | Approve / Reject buttons | Binary gate — deploy, merge, confirm | +| `choice` | N labelled buttons | Multi-option selection — which agent, which branch | +| `input` | Free-text capture | User-supplied values — target dir, config input | -The faigrid framework segments execution classes into specialized operational roles: +**App registry** — each app (openclaw, codenomad, n8n, …) registers with a display name, emoji, and optional Telegram topic thread ID for sub-channel routing. -- **grid-edge**: The gatekeeper. Handles TLS termination (Caddy), CrowdSec bouncers, and identity intake. Public-facing but tightly constrained. -- **grid-core**: The private compute substrate. Hosts internal services (n8n), queue consumers, internal APIs, and stable coordination. Strictly internal. -- **grid-worker**: Dedicated isolated execution workers. Examples include local inference (LM Studio/Ollama), review workers, and shell runners routed securely to the Core. -- **grid-backup**: The safety net. Automated, immutable offline backup pipelines targeting dedicated local network attached storage. -- **grid-external** *(optional)*: Cloud model bridges for access to external hosted workloads under strict egress-aware constraints. +```bash +# HTTP API (from any app on grid-core) +POST http://127.0.0.1:9119/decision/request +POST http://127.0.0.1:9119/notify +POST http://127.0.0.1:9119/app/register +GET http://127.0.0.1:9119/health +``` -> **Security Note:** This repository is intrinsically designed for autonomous deployments. It utilizes dynamic state and `.env.topology` generation. **Never commit secrets**. +See `core/messenger/` for installation and configuration details. --- ## Repository Layout -- `core/` — Docker compose stacks, systemd servers, and core execution scripts. -- `docs/` — Core architecture roadmap, example deployment profiles (Solo to SMB), runbooks. -- `edge/` — Firewall configs, advanced proxy templates, and SSO entry structures. -- `scripts/` — The master orchestration utilities (`install.sh`, `grid-dashboard.sh`, `grid-watchdog.sh`, `grid-doctor.sh`). -- `tests/` — Automated syntactical checks (Bats-core) natively hooked into CI/CD. +``` +faigrid/ +├── install.sh # Root orchestrator (state-aware) +├── core/ +│ ├── workbench/ +│ │ └── scripts/ +│ │ ├── control.sh # Interactive Workbench CLI +│ │ ├── _lib.sh # Shared helpers +│ │ ├── _projects.sh # Project/repo manager +│ │ ├── _skills.sh # AI skill deployer +│ │ └── plugins/ +│ │ ├── agents/ # openclaw, codenomad +│ │ ├── automation/ # n8n +│ │ ├── proxy/ # caddy +│ │ └── comms/ # grid-messenger +│ └── messenger/ +│ ├── src/grid_messenger.py # Telegram bot service +│ ├── install.sh # Messenger installer +│ ├── systemd/ # Service unit +│ └── requirements.txt +├── docs/ +│ ├── ROADMAP.md +│ ├── IMPLEMENTATION-PLAN.md +│ ├── architecture/ +│ ├── runbooks/ +│ └── reference/ +├── scripts/ +│ ├── grid-doctor.sh +│ ├── grid-dashboard.sh +│ ├── grid-deploy.sh +│ ├── grid-watchdog.sh +│ └── faigrid-release +├── tests/ +│ └── smoke/ +└── .github/ + └── workflows/ # lint, test, release-please, codeql, repo-safety +``` + +--- + +## Troubleshooting + +```bash +# Comprehensive health check +./scripts/grid-doctor.sh + +# Live system log +tail -f /var/log/faigrid/grid-system.log + +# Workbench plugin doctor (per-service) +./core/workbench/scripts/control.sh doctor +``` + +Common issues: + +| Symptom | Cause | Fix | +|---|---|---| +| `no registered nodes` after Homebrew install | OLD: registry was repo-relative | Registry migrated to `~/.config/faigrid/registry/` in v1.6.0 | +| `.grid` domains not resolving | Pi-hole DNS not set as resolver | Set workstation DNS to Edge LAN IP | +| `grid-messenger` decisions not arriving | Bot token or chat ID missing | Run Workbench → comms → grid-messenger → configure | --- -### Support +## Security -If you find this engineering blueprint valuable or you're using it to bootstrap your own sovereign AI networks, please consider giving it a ⭐️ to help the community grow! +- All core services bind to `127.0.0.1` — never exposed beyond localhost/LAN without explicit edge config. +- Secrets live in `.env` files outside the repo. Never committed. `.gitignore` covers all credential patterns. +- Services run as dedicated system users (no login shell, no home dir). See `CLAUDE.md` for the full system user pattern. +- Destructive operations (uninstall, wipe, volume removal) always prompt for confirmation. --- @@ -140,4 +252,4 @@ Apache 2.0 — see [LICENSE](LICENSE) for details. --- -> Made with ❤️ in Berlin +> Made with ❤️ in Berlin · Part of the [fusionAIze](https://github.com/fusionAIze) ecosystem diff --git a/docs/COCKPIT.md b/docs/COCKPIT.md new file mode 100644 index 0000000..751452f --- /dev/null +++ b/docs/COCKPIT.md @@ -0,0 +1,376 @@ +# Grid Operator Cockpit — Design Specification + +## Purpose + +The Grid Cockpit is a **lightweight, operator-focused web dashboard** for fusionAIze Grid. It answers the same class of question for Grid that the faigate operator cockpit answers for Gate — but scoped entirely to Grid's execution substrate: node health, service status, pending decisions, and runtime events. + +It is not a control plane. It does not replicate Gate's routing analytics or Signal's cross-layer correlation. Its scope is: **what is happening in my Grid right now, and is everything OK?** + +--- + +## Context + +### What the faigate cockpit teaches us + +faigate's operator cockpit (`dashboard_web.py`, `DASHBOARD-IA.md`) established a design language and IA pattern for the fusionAIze stack: + +- **Dark navy theme** — `--bg:#07101d`, deep blue palette +- **280px sticky left rail** — brand lockup, navigation, version indicator +- **Card-based panels** — grouped by operator job, not by data type +- **Jobs first, metrics second** — every section answers one question +- **No-build, inline HTML** — served directly from Python/aiohttp, zero npm +- **Progressive disclosure** — overview compact, detail on drilldown + +The Grid Cockpit follows this design language family but uses **Grid green** (`#1a7f37`) as the brand color to be visually distinct from Gate blue (`#0052CC`). + +### What faisignal expects from Grid + +From the faisignal roadmap, Signal v1 expects to ingest from Grid: +- runner failure events +- queue backlog anomalies +- job-completion degradation +- local/cloud worker imbalance + +The cockpit is the **human-facing surface** of the same runtime state that Signal ingests programmatically. They read the same data; they serve different audiences. + +--- + +## Design Principles + +1. **Jobs first** — each cockpit section answers exactly one operator job. +2. **Confidence before detail** — Overview gives a pass/fail grid health signal in one glance. +3. **Read-only first** — cockpit observes; it does not mutate state. Actions stay in Workbench CLI. +4. **Signal-compatible** — cockpit sections map to faisignal's runtime health signal family. +5. **Lightweight** — no CDN, no npm, no build. Single Python file + inline HTML. +6. **Distinct but consistent** — uses faigate's design language; Grid green differentiates it. + +--- + +## Visual Design + +### Color tokens + +```css +:root { + /* Base — shared with faigate */ + --bg: #07101d; + --bg-2: #0d1730; + --panel: #0d1830cc; + --panel-strong: #101d38; + --panel-soft: #12224480; + --line: #1e3a2a; + --line-soft: #172e22; + --text: #dbe6f5; + --muted: #8ea7cc; + --muted-soft: #6980a6; + + /* Grid brand — green (Gate = blue #0052CC) */ + --brand: #1a7f37; + --brand-2: #4caf73; + --brand-glow: rgba(26, 127, 55, 0.12); + + /* Shared fusionAIze accent */ + --accent: #54ABEE; + + /* State colors — same as Gate */ + --lime: #C4D900; + --green: #2EA75D; + --orange: #FFAA19; + --danger: #ff7b7b; + + /* Layout */ + --radius-xl: 28px; + --radius-lg: 20px; + --radius-md: 14px; + --radius-sm: 10px; + --shadow: 0 20px 56px rgba(2, 8, 19, .28); + + /* Typography */ + --body: "Open Sans", "Segoe UI", "Helvetica Neue", sans-serif; + --display: "Montserrat", "Avenir Next", "Segoe UI", sans-serif; + --mono: "SFMono-Regular", "IBM Plex Mono", "Menlo", monospace; +} +``` + +### Layout + +``` +┌───────────────────────────────────────────────────────────────────────┐ +│ │ +│ ┌────────────────┐ ┌──────────────────────────────────────────────┐ │ +│ │ LEFT RAIL │ │ MAIN CONTENT │ │ +│ │ 280px sticky │ │ fluid width │ │ +│ │ │ │ │ │ +│ │ [Grid logo] │ │ [Section header] │ │ +│ │ [wordmark] │ │ │ │ +│ │ [version] │ │ [Cards / panels / tables] │ │ +│ │ │ │ │ │ +│ │ ───────── │ │ │ │ +│ │ Overview │ │ │ │ +│ │ Nodes │ │ │ │ +│ │ Services │ │ │ │ +│ │ Messenger │ │ │ │ +│ │ Workbench │ │ │ │ +│ │ Signals │ │ │ │ +│ │ Setup │ │ │ │ +│ │ │ │ │ │ +│ │ ───────── │ │ │ │ +│ │ [Doctor btn] │ │ │ │ +│ └────────────────┘ └──────────────────────────────────────────────┘ │ +│ │ +└───────────────────────────────────────────────────────────────────────┘ +``` + +CSS grid: `grid-template-columns: 280px minmax(0, 1fr)` — same as faigate. + +### Status indicators + +| State | Color | Usage | +|---|---|---| +| healthy / ok | `--green` #2EA75D | Service up, node reachable | +| degraded | `--orange` #FFAA19 | Partial failure, stale data | +| down / error | `--danger` #ff7b7b | Service down, node unreachable | +| unknown | `--muted` #8ea7cc | No data yet | +| pending | `--lime` #C4D900 | Decision awaiting response | + +--- + +## Information Architecture + +### 1. Overview + +**Operator job**: "Is my Grid healthy and ready right now?" + +**Layout**: 2×3 summary card grid + priority-next banner + +**Content:** +- **Node status row** — 5 badges (edge / core / worker / backup / external), each showing reachable / unreachable / unknown +- **Service health** — count of healthy / degraded / unknown services across all nodes +- **Pending decisions** — count of open decisions in grid-messenger + type breakdown (approve / choice / input) +- **Last event** — timestamp + one-line summary of most recent entry in grid-events.jsonl +- **Grid version** — installed version from `VERSION` file +- **Priority next** — top anomaly detected (e.g., "worker node unreachable since 14:32") + +**Why this order:** +Node health first (infrastructure confidence), then service health (application confidence), then decisions (operational backlog), then last event (recent activity). + +--- + +### 2. Nodes + +**Operator job**: "Which nodes are reachable and what are they running?" + +**Layout**: One card per node (5 cards), horizontal or 2-column grid + +**Per-node card:** +- Node name + role badge (`edge` / `core` / `worker` / `backup` / `external`) +- Reachability status + last-seen timestamp +- Services list with inline status icon +- SSH target label (hostname or IP class only — not full credentials) +- Link to detail view + +**Node detail panel (slide-in or expandable):** +- Full service list with port, status, last-checked +- Recent events for this node (filtered from event log) +- Link to Workbench plugin for each service + +--- + +### 3. Services + +**Operator job**: "Which services are up, degraded, or stale?" + +**Layout**: Filterable table + detail panel + +**Table columns:** Service · Node · Port · Status · Last checked · Action + +**Filters:** All / Healthy / Degraded / Down / Unknown + +**Detail panel per service:** +- HTTP health probe response (if applicable) +- Recent log lines (last 10 lines from journalctl / service log) +- Workbench plugin link for reconfiguration +- Uptime since last restart + +--- + +### 4. Messenger + +**Operator job**: "What decisions are pending? What did my apps send recently?" + +**Layout**: Two-column — pending (left) + history (right) + +**Pending decisions:** +- Card per pending decision: type badge · source emoji + name · description · time-in-queue +- Sorted by age (oldest first — most urgent) +- Cancel button (POST to messenger API) + +**Decision history (last 20):** +- Compact list: type · source · choice/approval · resolved-by · timestamp +- Click to expand full payload + +**Registered apps:** +- Compact list with emoji, display name, last-active, thread_id if set + +**Telegram link:** +- Direct link to open bot conversation (t.me/...) + +--- + +### 5. Workbench + +**Operator job**: "Which plugins are installed, configured, and healthy?" + +**Layout**: Plugin cards in 2×N grid + +**Per-plugin card:** +- Plugin name + category badge +- Installation status (installed / not installed) +- Configuration status (configured / unconfigured) +- Health status (last doctor run result) +- Update available indicator +- Quick-actions: Configure · Doctor · Update (link to Workbench CLI command) + +--- + +### 6. Signals + +**Operator job**: "What events has my Grid emitted recently?" + +**Layout**: Event timeline + filter bar + +**Timeline entry:** +- Timestamp · Event type badge · Node · Service · Detail text + +**Event types (with color coding):** +| Type | Color | +|---|---| +| `service_down` | `--danger` | +| `service_recovered` | `--green` | +| `node_unreachable` | `--danger` | +| `node_recovered` | `--green` | +| `decision_requested` | `--lime` | +| `decision_resolved` | `--accent` | +| `plugin_installed` | `--brand-2` | +| `plugin_updated` | `--brand-2` | + +**Filter bar:** All · Service · Node · Decision · Plugin · Time range + +**Live mode toggle:** WebSocket tail of grid-events.jsonl (auto-refreshes on new events) + +**faisignal integration note:** Compact link "View in Signal →" if faisignal is detected at its default port. + +--- + +### 7. Setup + +**Operator job**: "How do I register a new node or configure a missing service?" + +**Layout**: Step-by-step wizard panels + +**Sections:** +- Node registration (topology flags, registry path) +- Workbench plugin quick-start (per-plugin install command) +- Messenger setup (bot token, chat ID, app registration) +- Caddy / Pi-hole DNS setup +- Link to `grid-doctor.sh` and `docs/runbooks/` + +--- + +## Navigation Rail — Detail + +``` +┌─────────────────────────────┐ +│ [fusionAIze wordmark SVG] │ +│ Grid v1.7.0 │ ← version badge, brand-green +│ │ +│ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ +│ │ +│ ⬡ Overview │ ← active state: brand-green left border +│ ◉ Nodes │ +│ ◈ Services │ +│ ✉ Messenger │ ← badge: pending decision count +│ ⚙ Workbench │ ← badge: updates available count +│ ⚡ Signals │ +│ ✦ Setup │ +│ │ +│ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ +│ │ +│ [Run Doctor] │ ← pill button, opens Signals section +│ │ +└─────────────────────────────┘ +``` + +--- + +## Technical Specification + +### File layout + +``` +core/cockpit/ +├── grid_cockpit.py # aiohttp app + API endpoints + WebSocket +├── dashboard_web.py # Inline HTML/CSS/JS (single-file, no build) +├── assets/ +│ └── brand/ +│ ├── grid-wordmark.svg +│ └── favicon.ico +├── install.sh # Creates system user, installs service +└── systemd/ + └── grid-cockpit.service +``` + +### HTTP API (served by grid_cockpit.py) + +``` +GET / → dashboard HTML +GET /dashboard/assets/* → static assets +GET /api/v1/health → node + service health JSON +GET /api/v1/events → last N events from grid-events.jsonl +GET /api/v1/messenger → pending decisions + registered apps +GET /health → cockpit self-health +WS /ws/state → live push: health diffs + new events +``` + +### System service + +- Port: `127.0.0.1:9121` +- User: `grid-cockpit` (no login shell, no home dir) +- Config: `/etc/grid-cockpit/config.env` +- Accessible via Caddy at: `cockpit.grid` (internal LAN, `.grid` TLD) +- Reads: `~/.config/faigrid/registry/*.state`, `/var/log/faigrid/grid-events.jsonl` +- Proxies to: `127.0.0.1:9119` (grid-messenger health/decisions) + +### Workbench plugin + +``` +core/workbench/scripts/plugins/ops/grid-cockpit.sh +``` + +Standard interface: +- `tool_configure()` — set port, messenger URL, event log path +- `tool_doctor()` — check service running, HTTP health, Caddy route active +- `tool_update()` — pull latest from source + +--- + +## Scope Boundary + +| In scope | Out of scope | +|---|---| +| Node reachability (Grid's own nodes) | Faigate provider health | +| Grid service status (n8n, openclaw, etc.) | Signal cross-layer correlation | +| Pending decisions (grid-messenger) | Token usage / cost analytics | +| Grid event timeline | LLM inference quality metrics | +| Workbench plugin status | Route selection explainability | +| Grid setup / onboarding | RBAC / multi-user governance | + +The cockpit is intentionally narrow. Cross-layer intelligence belongs to Signal; routing intelligence belongs to Gate. + +--- + +## Licensing + +Grid Cockpit ships under **Apache 2.0** — same as faigrid. + +The read-only local dashboard (node health, service status, messenger decisions, event log) is a core operator tool and must stay open. diff --git a/docs/IMPLEMENTATION-PLAN.md b/docs/IMPLEMENTATION-PLAN.md new file mode 100644 index 0000000..c663bb7 --- /dev/null +++ b/docs/IMPLEMENTATION-PLAN.md @@ -0,0 +1,259 @@ +# Implementation Plan — fusionAIze Grid + +## Goal + +Turn Grid's existing execution substrate into a **signal-ready, operator-observable platform** — one that feeds clean runtime data into fusionAIze Signal and gives operators a coherent cockpit for their Grid. + +This plan is not a parking lot. It covers the two near-term release lines that move Grid from "working installation tool" to "observable execution substrate with operator dashboard". + +--- + +## Current baseline (v1.6.1) + +What exists and is working: + +| Component | Status | +|---|---| +| `install.sh` orchestrator (state-aware, 4+1 node) | ✅ stable | +| Workbench + plugin registry (6 plugins) | ✅ stable | +| grid-messenger (Telegram, 3 decision types, app registry) | ✅ stable | +| Internal LAN proxy (Caddy + Pi-hole `.grid` TLD) | ✅ stable | +| CI: ShellCheck, ruff, bats, CodeQL, release-please | ✅ green | +| Pre-commit hooks: shellcheck, ruff, version-consistency | ✅ hooked | +| Homebrew tap distribution | ✅ live | +| Node registry at `~/.config/faigrid/registry/` | ✅ stable | + +What is missing before the cockpit and Signal integration can ship: + +| Gap | Needed for | +|---|---| +| No structured `/api/v1/health` endpoint | Cockpit, Signal ingestion | +| No structured event stream | Signal `log_ingestor` plugin | +| `grid-doctor.sh` output is human-only text | Programmatic health checks | +| No cockpit dashboard | Operator observability | +| `grid-messenger` not yet served via HTTP API for Grid state | Cockpit backend | + +--- + +## Release line 1 — Signal Readiness (v1.7 – v1.9) + +*Make Grid's runtime state consumable by faisignal without coupling.* + +**Scope commitment**: No UI, no new user-facing features. Only structured data output. + +### v1.7 — Health API + +**New: `core/api/grid_health.py`** + +Lightweight aiohttp service on `127.0.0.1:9120`. + +``` +GET /api/v1/health +``` + +Response shape: +```json +{ + "version": "1.7.0", + "timestamp": "2026-...", + "nodes": { + "edge": { "reachable": true, "last_seen": "...", "services": ["caddy", "pihole"] }, + "core": { "reachable": true, "last_seen": "...", "services": ["n8n", "openclaw", "faigate", "messenger"] }, + "worker": { "reachable": false, "last_seen": "...", "services": [] }, + "backup": { "reachable": true, "last_seen": "...", "services": ["restic"] }, + "external": { "reachable": false, "last_seen": null, "services": [] } + }, + "services": { + "n8n": { "node": "core", "status": "ok", "port": 5678 }, + "openclaw": { "node": "core", "status": "ok", "port": 18789 }, + "faigate": { "node": "core", "status": "ok", "port": 8090 }, + "messenger": { "node": "core", "status": "ok", "port": 9119 }, + "caddy": { "node": "edge", "status": "ok", "port": 443 } + } +} +``` + +Reads node registry from `~/.config/faigrid/registry/*.state`. +Performs lightweight TCP reachability probes (no SSH, no auth). + +**Implementation notes:** +- Single Python file, Bash 3.2-safe installer +- Runs as `grid-health` system user (same isolation pattern as grid-messenger) +- Started alongside grid-messenger via systemd, or as a separate unit +- No external dependencies beyond Python stdlib + aiohttp + +### v1.8 — Structured event log + +**Update: `scripts/grid-watchdog.sh`** + +Emit structured JSON lines to `/var/log/faigrid/grid-events.jsonl`: + +```json +{ "type": "service_down", "node": "core", "service": "n8n", "at": "2026-...", "detail": "TCP probe failed" } +{ "type": "service_recovered", "node": "core", "service": "n8n", "at": "2026-...", "detail": "TCP probe OK" } +{ "type": "node_unreachable", "node": "worker", "at": "2026-...", "detail": "SSH timeout" } +``` + +Event types: +- `service_down` / `service_recovered` +- `node_unreachable` / `node_recovered` +- `decision_requested` / `decision_resolved` (from grid-messenger) +- `plugin_installed` / `plugin_updated` + +faisignal's `log_ingestor` plugin can tail this file directly. + +**Update: `scripts/grid-doctor.sh`** + +Add `--json` flag for machine-readable output: +```bash +./scripts/grid-doctor.sh --json > /tmp/grid-health.json +``` + +### v1.9 — Signal integration test + +- Document the faisignal collector config for faigrid (how to point `log_ingestor` at `/var/log/faigrid/grid-events.jsonl`) +- Document the `/api/v1/health` polling config for faisignal's `prometheus_scraper` +- Add a `docs/integrations/faisignal.md` integration guide + +--- + +## Release line 2 — Operator Cockpit (v2.0) + +*Ship a lightweight operator dashboard. faigate-inspired design, Grid-scoped content.* + +### Design principles (from faigate DASHBOARD-IA.md, adapted for Grid) + +1. **Jobs first, metrics second** — each section answers one operator question +2. **Confidence before detail** — Overview shows "is my Grid OK?" in one glance +3. **Read-only first** — cockpit is an observation surface; actions go through Workbench CLI +4. **Progressive disclosure** — overview stays compact; node/service detail pages go deep +5. **Signal-compatible** — cockpit sections map to faisignal's runtime health signal family + +### Information architecture + +#### 1. Overview +**Operator job**: "Tell me if my Grid is healthy and request-ready right now." + +- Node status summary (edge / core / worker / backup / external) — colored badges +- Service health summary — count of healthy vs degraded vs unknown +- Pending decisions from grid-messenger (count + top item) +- Last event from grid-events.jsonl +- "Priority next" card — top issue detected, link to relevant section + +#### 2. Nodes +**Operator job**: "Which nodes are reachable and what are they running?" + +- One card per node (edge, core, worker, backup, external) +- Reachability status + last-seen timestamp +- Services list per node with inline status icons +- SSH target hint (derived from registry, never exposed as credential) + +#### 3. Services +**Operator job**: "Which services are up, degraded, or stale?" + +- Table: service name / node / port / status / last-checked +- Drilldown per service: recent log lines, health endpoint response +- Link to Workbench plugin for reconfiguration + +#### 4. Messenger +**Operator job**: "What decisions are pending? What happened recently?" + +- Live pending decision cards (type badge, source, description, time-in-queue) +- Recent resolved decisions (last 20) +- Registered apps list with last-active timestamp +- Direct link to Telegram bot + +#### 5. Workbench +**Operator job**: "Which plugins are installed and what needs attention?" + +- Plugin cards: name / category / installed version / update available +- Plugin status (configured / unconfigured / unhealthy) +- "Run doctor" quick-link per plugin + +#### 6. Signals +**Operator job**: "What events has my Grid emitted recently?" + +- Event timeline from `grid-events.jsonl` +- Filter by type: `service` / `node` / `decision` / `plugin` +- Tail mode (live updates via WebSocket) + +#### 7. Setup +**Operator job**: "How do I add a node or configure a new service?" + +- Node registration wizard (reads install.sh topology flags) +- Quick-start links for each Workbench plugin +- Link to `grid-doctor.sh` output + +### Technical implementation + +**File structure:** +``` +core/cockpit/ +├── grid_cockpit.py # aiohttp server + WebSocket handler +├── dashboard_web.py # Inline HTML (single-file, no build) +├── assets/ +│ └── brand/ # SVG wordmark, favicon +├── install.sh # Cockpit installer (system user, systemd unit) +└── systemd/ + └── grid-cockpit.service +``` + +**Stack:** +- Python 3.10+, aiohttp, same pattern as grid-messenger +- All CSS/JS inline in `dashboard_web.py` — no CDN, no npm +- Fonts: system stack (no custom fonts for v1) +- Live data via WebSocket on `/ws/state` (polls health API every 10s) +- Served on `127.0.0.1:9121` (accessible via Caddy at `cockpit.grid`) + +**Design tokens** (adapted from faigate, Grid-tuned): +```css +--bg: #07101d; /* deep navy — same as Gate */ +--bg-2: #0d1730; +--panel: #0d1830cc; +--brand: #1a7f37; /* Grid green — distinct from Gate blue */ +--brand-2: #4caf73; +--accent: #54ABEE; /* shared fusionAIze blue */ +--lime: #C4D900; +--green: #2EA75D; +--orange: #FFAA19; +--danger: #ff7b7b; +``` + +Gate uses `--brand:#0052CC` (blue). Grid uses `--brand:#1a7f37` (green) to be visually distinct within the same design language family. + +**Navigation rail** (280px sticky left, same layout as faigate): +- fusionAIze Grid wordmark + version badge +- Overview · Nodes · Services · Messenger · Workbench · Signals · Setup +- Bottom: Grid Doctor quick-run button + +--- + +## What this plan defers + +| Feature | Reason | +|---|---| +| Multi-instance / fleet view | Signal's job once Grid emits events | +| Cost / token analytics | Gate + Signal's job | +| Advanced anomaly detection | Signal's machine-learning layer (Phase 3) | +| Role-aware dashboard views | Requires fusionAIzeOS integration (Phase 4) | +| Full control plane (start/stop services from UI) | v2.x — safety boundary | +| Enterprise RBAC | Out of Grid's scope entirely | + +--- + +## Success criteria + +**Signal Readiness (v1.7–1.9) is done when:** +- `GET /api/v1/health` returns structured node + service state +- `/var/log/faigrid/grid-events.jsonl` is populated by watchdog +- faisignal can be configured to ingest Grid events with zero custom code +- `grid-doctor.sh --json` works + +**Cockpit (v2.0) is done when:** +- A new operator can answer in < 2 minutes: + 1. Are all my nodes reachable? + 2. Which services are degraded right now? + 3. What decisions are pending in grid-messenger? + 4. What did my Grid do in the last hour? +- The cockpit runs on `cockpit.grid` in the internal LAN +- No npm, no external CDN, no build step required diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 290e3a2..037ea57 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -1,76 +1,164 @@ -# Roadmap: fusionAIze Grid (faigrid) +# Roadmap — fusionAIze Grid -This roadmap outlines the path from the current baseline towards the fully-fledged, production-ready **fusionAIze Grid v3**. +## Vision + +**fusionAIze Grid is the sovereign execution substrate for AI-native operations.** + +Its job is to define *where* AI-native work runs, under *what constraints*, with *what isolation*, through which *queues and runners*, and with which *observability and recovery patterns*. + +Grid is the execution layer. It does not do context, memory, or routing — those belong to Fabric, Gate, and Lens. What Grid uniquely provides is the hardened, portable, self-hosted infrastructure that makes the rest of the fusionAIze stack actually run. + +--- + +## Guiding Principles + +- **Execution First** — strict Execution Classes over fuzzy environments +- **Solo-to-SMB** — scales from a single operator to a small team without enterprise theater +- **Builder Focus** — predictable Bash, clear state, zero hidden magic +- **Signal-Ready** — emit clean runtime signals that faisignal can consume without coupling +- **Security by Default** — deny-at-edge, internal-only core, secrets never in Git + +--- + +## Stack Position + +| Layer | Repo | Relationship to Grid | +|---|---|---| +| Gate | `faigate` | Routes AI requests through Grid's core services | +| Lens | `failens` | Context layer — future integration via core API | +| Fabric | `faifabric` | Memory layer — future integration via core API | +| **Grid** | `faigrid` ← | Execution substrate | +| Signal | `faisignal` | Consumes Grid's runtime health and event signals | +| OS | `fusionAIzeOS` | Injects role-aware collaboration logic into Grid runners | + +--- + +## Current State — v1.6.1 + +### What exists and works + +**4+1 Node Architecture (install.sh orchestrator)** +- `grid-edge`: Caddy reverse proxy, Pi-hole DNS, internal `.grid` TLD, TLS-internal +- `grid-core`: n8n, openclaw, codenomad, faigate, grid-messenger, Postgres, Redis +- `grid-worker`: Ollama, LM Studio, shell runners +- `grid-backup`: Restic, Synology +- `grid-external`: Cloud model bridges + +**Grid Workbench** — interactive operator console with plugin registry +- Plugins: n8n, openclaw, codenomad, faigate, caddy, grid-messenger +- Standard plugin interface: `tool_configure` · `tool_doctor` · `tool_update` +- Projects manager (`_projects.sh`) — git repo management on nodes +- Skills deployer (`_skills.sh`) — AI skill import and cross-agent deployment + +**Grid Messenger** — Telegram decision and notification bridge +- Three decision types: `approve` / `choice` / `input` +- App registry with emoji, display name, Telegram topic thread routing +- HTTP API on `127.0.0.1:9119` — any core service can push decisions or notifications + +**CI / Quality** +- ShellCheck, ruff, bats smoke tests, CodeQL, repo-safety +- Pre-commit hooks: shellcheck, ruff, conventional commits, version-consistency +- release-please automated versioning + Homebrew tap dispatch + +--- + +## Phase 1 — Signal Readiness (v1.7 – v1.9) + +*Make Grid's runtime state observable by faisignal.* + +faisignal's roadmap explicitly expects Grid to emit: +- runner failures and retry spikes +- queue backlog anomalies +- job-completion degradation +- local/cloud worker imbalance +- service-level health per node + +### Deliverables + +**`/api/v1/health` endpoint** (grid-core, `127.0.0.1:9120`) +- Node reachability (edge, core, worker, backup, external) +- Service status per node (n8n, openclaw, faigate, messenger, caddy) +- Last-seen timestamps + +**`/api/v1/events` stream** (WebSocket or SSE) +- Structured event objects: `ServiceEvent`, `NodeEvent`, `RunnerEvent` +- Fields: `type`, `node`, `service`, `status`, `timestamp`, `detail` +- Consumed by faisignal without any Grid-specific coupling + +**Grid Watchdog hardening** +- Emit structured JSON events on state changes to `grid-system.log` +- Log format aligned with faisignal's `log_ingestor` plugin contract + +**Grid Doctor signals** +- Machine-readable `--json` output flag for programmatic health checks --- -## 🌌 The fusionAIze Vision & Role Architecture +## Phase 2 — Operator Cockpit (v2.0) + +*Ship the Grid operator dashboard — faigate-inspired, Grid-scoped.* -**fusionAIze** builds, operates, and enables *human-AI fusion teams*. The ecosystem connects live execution environments, memory fabrics, and team operating logic to turn AI from an isolated capability into operational collaboration. +The cockpit is a **lightweight, no-build Python-served HTML dashboard** running on `grid-core`. Design language inherits from faigate's cockpit (dark navy, 280px sticky left rail, card-based panels) but all sections answer Grid-specific operator jobs. -### The Component Map (Core Now) -The current, narrowest, and strongest product spine consists of: -1. **fusionAIze Gate:** The AI-native gateway for models, providers, tools, and clients. *(Connects)* -2. **fusionAIze Lens:** The relevance, compression, translation, and explanation layer. *(Filters & Shapes)* -3. **fusionAIze Fabric:** The shared context, memory, and knowledge fabric. *(Remembers & Serves)* -4. **fusionAIze Grid (`faigrid`):** The sovereign execution substrate (this repo). *(Runs)* -5. **fusionAIzeOS:** The operating logic for human-AI fusion teams. *(Defines Coworker Reality)* +### Cockpit Sections -*(Likely Later: **Signal** as an operational intelligence layer, and **Studio** for blueprint authoring).* +| Section | Operator Job | +|---|---| +| **Overview** | "Is my Grid healthy and ready right now?" | +| **Nodes** | "Which nodes are reachable and what are they running?" | +| **Services** | "Which services are up, degraded, or missing?" | +| **Messenger** | "What decisions are pending? What just happened?" | +| **Workbench** | "Which plugins are installed? What needs updating?" | +| **Signals** | "What events has Grid emitted recently?" | +| **Setup** | "How do I add a node or configure a new service?" | + +See `docs/COCKPIT.md` for the full information architecture and design spec. + +### Technical shape +- Python + aiohttp, served alongside grid-messenger or as a separate systemd unit +- Inline HTML — single-file, no npm, no bundler +- Reads from `/api/v1/health` and `grid-messenger`'s `/health` endpoint +- WebSocket live-reload for service status cards + +--- + +## Phase 3 — Execution Classes & GitOps (v2.1 – v2.5) + +*Formalize runner discipline and declarative topology.* + +- **Queue & Runner discipline** — explicit runner boundaries (Browser Runners, Shell Runners, Privileged Runners) with queue depth monitoring +- **GitOps topology** — declarative `topology.yaml` that describes the 4+1 layout and can be applied idempotently +- **Hybrid model bridging** — seamless orchestration between Cloud Bridges (via faigate) and Local Workers (via grid-worker) +- **Deployment Profile templates** — `Solo Operator` → `Small Team` → `SMB` starter configs with documented migration paths --- -## 💠 The True Position of fusionAIze Grid +## Phase 4 — fusionAIzeOS Integration (v3.x) -> **fusionAIze Grid is the sovereign execution substrate for AI-native operations across local, on-prem, private cloud, public cloud, and hybrid deployments.** +*Role-aware collaboration logic injected into Grid runners.* -Its job is to define **where** AI-native work runs, under **what constraints**, with **what isolation**, through which **queues/runners**, and with which **secrets, observability, and backup patterns**. It is the execution layer, not the context, memory, or overarching OS layer. +- Grid runners receive role context from OS (who is allowed to run what, under which policy) +- Escalation and override events surface in Signal's collaboration signals family +- Identity-aware audit log for Grid execution events +- Policy-gated runner classes (e.g., Privileged Runners require explicit OS approval) -### The Product Primitives -Grid moves beyond hardware abstractions and focuses on **Execution Classes** and **Deployment Profiles**: +--- -**Execution Classes:** -- Edge Ingress Workloads (Public intake, Caddy, Auth) -- Trusted Internal Services (n8n, APIs) -- Queued Automations -- Privileged Runners (System-level operations) -- Browser & Shell Runners (Isolated task execution) -- Local Model Workers (LAN-only inference) -- Cloud Model Bridges (Routed external reasoning) +## What Grid Deliberately Does Not Do -**Deployment Profiles:** -1. **Solo Operator**: Local-first, practical, low complexity. -2. **Small Team**: Shared internal services, basic queues, backups. -3. **SMB**: Stricter runners, hybrid local/cloud placement, strong isolation. -4. *(Later)* **Enterprise**: Compliance-heavy, rich policy layers. +- **Model routing** — that is Gate's job +- **Context or memory management** — that is Lens/Fabric's job +- **Operating logic / team coordination** — that is fusionAIzeOS's job +- **Enterprise compliance theater** — Grid stays lean and operator-owned +- **Complex analytics or BI dashboards** — Signal handles cross-layer observability --- -## 📈 Versioning & Execution Horizons - -We build upon standard Semantic Versioning, with **`v1.3.0` forming the bridging milestone.** - -- **Current Status**: Eradicated legacy identity. Consolidating the basic runtime topology. -- **Next Horizon**: Formalizing the distinct **Execution Classes** within the established 4+1 node architecture. - -### Phase 1: Refining the Foundation (Current – v1.3.0) -*Securing the baseline and proving the standalone value.* -- [x] Standardize interactive installer with clear edge/core separation. -- [x] Eradicate legacy terminology and align fully with the fusionAIze brand. -- [x] Stabilize basic plugin ecosystem (mem0, openrouter) as isolated primitives. -- [ ] Formalize **Queue & Runner Discipline** for asynchronous agents. -- [ ] Harden **Observability & Backup Layer** defaults (Logs, Metrics, Snapshotting). - -### Phase 2: Execution Classes & Small-Team Operations (v2.0) -*Moving from "clever setup" to durable operational substrate.* -- Establish clear runner boundaries (Browser Runners, Shell Runners, Privileged Runners). -- Hybrid Model bridging: Seamless orchestration between Cloud Bridges (via faigate) and Local Workers. -- GitOps implementation for declarative execution topology definitions. -- Implement explicit Deployment Profiles (Solo Operator -> Small Team templates). - -### Phase 3: Service Grid & Productization -*Supporting Agency scaling and managed editions.* -- Richer execution classes for multi-project isolation. -- Integration hooks for future `fusionAIze Signal` (Operational Intelligence / Telemetry). -- Seamless adapter endpoints for `fusionAIzeOS` to inject role-aware collaboration logic into the Grid runners. -- Plug-support for external secure runtimes (NemoClaw-inspired execution boundaries / OpenShell adapters). +## Versioning Convention + +Grid follows semantic versioning via `release-please`: +- **Patch** (`x.y.Z`) — bug fixes, doc updates, minor polish +- **Minor** (`x.Y.0`) — new features, new plugins, new API surfaces +- **Major** (`X.0.0`) — explicit breaking changes with documented migration + +Current version tracked in `VERSION` and `install.sh:INSTALL_VERSION`. From 8e7978e5c4a1686b8794709888e89be20f3efb1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Lange?= Date: Mon, 13 Apr 2026 16:53:49 +0200 Subject: [PATCH 2/4] =?UTF-8?q?feat(messenger):=20cross-platform=20install?= =?UTF-8?q?=20=E2=80=94=20macOS=20launchd=20+=20Homebrew,=20Linux=20system?= =?UTF-8?q?d?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit macOS path: - Detects Homebrew-managed faigrid-messenger bin (brew services start faigrid) - Falls back to standalone venv + LaunchAgent plist if brew not available - Config at ~/.config/grid-messenger/config.env (600) - Logs at ~/.local/share/grid-messenger/grid-messenger.log Linux path (unchanged behavior): - apt-get / dnf package manager detection - systemd service + /etc/grid-messenger/ config pattern - system user isolation (grid-messenger:grid-messenger) Co-Authored-By: Claude Sonnet 4.6 --- core/messenger/install.sh | 154 +++++++++++++++++++++++++++++++++----- 1 file changed, 135 insertions(+), 19 deletions(-) diff --git a/core/messenger/install.sh b/core/messenger/install.sh index 8520aaa..d1eec80 100644 --- a/core/messenger/install.sh +++ b/core/messenger/install.sh @@ -1,15 +1,140 @@ #!/usr/bin/env bash # grid-messenger install — runs on the core node +# Supports: macOS (Homebrew / launchd) and Linux (systemd) set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +OS="$(uname -s)" + +# ── macOS (Homebrew / Solo Operator) ────────────────────────────────────────── +if [[ "$OS" == "Darwin" ]]; then + echo "[grid-messenger] macOS detected — using Homebrew + launchd setup" + + CONFIG_DIR="${HOME}/.config/grid-messenger" + DATA_DIR="${HOME}/.local/share/grid-messenger" + VENV_DIR="${DATA_DIR}/venv" + PLIST="${HOME}/Library/LaunchAgents/ai.fusionaize.grid-messenger.plist" + + # Prefer brew-managed faigrid-messenger binary if available + if command -v faigrid-messenger >/dev/null 2>&1; then + MESSENGER_BIN="$(command -v faigrid-messenger)" + VENV_PYTHON="" + echo "[grid-messenger] Using Homebrew-managed faigrid-messenger binary" + else + # Fallback: standalone venv + echo "[grid-messenger] faigrid-messenger not found — setting up standalone venv" + MESSENGER_BIN="" + python3 -m venv "$VENV_DIR" + "$VENV_DIR/bin/pip" install --quiet --upgrade pip + "$VENV_DIR/bin/pip" install --quiet \ + "python-telegram-bot>=20.0" \ + "aiohttp>=3.9" + VENV_PYTHON="${VENV_DIR}/bin/python3" + fi + + mkdir -p "$CONFIG_DIR" "$DATA_DIR" + + # Config template + if [[ ! -f "${CONFIG_DIR}/config.env" ]]; then + cat > "${CONFIG_DIR}/config.env" << 'EOF' +# fusionAIze Grid Messenger — Configuration +# Restart after editing: brew services restart faigrid + +# Required: get from @BotFather on Telegram +TELEGRAM_BOT_TOKEN= + +# Your Telegram user ID (find via @userinfobot) +TELEGRAM_ALLOWED_USER_IDS= + +# Chat IDs for notifications (defaults to ALLOWED_USER_IDS) +NOTIFY_CHAT_IDS= + +# Core service URLs +N8N_BASE_URL=http://127.0.0.1:5678 +FAIGATE_URL=http://127.0.0.1:8090 +OPENCLAW_URL=http://127.0.0.1:18789 + +# Inbound HTTP port +WEBHOOK_PORT=9119 +WEBHOOK_BIND=127.0.0.1 +APPS_FILE= +EOF + # Fill in APPS_FILE path + echo "APPS_FILE=${DATA_DIR}/apps.json" >> "${CONFIG_DIR}/config.env" + chmod 600 "${CONFIG_DIR}/config.env" + echo "[grid-messenger] Config template created at ${CONFIG_DIR}/config.env" + echo " → Edit it and add TELEGRAM_BOT_TOKEN + TELEGRAM_ALLOWED_USER_IDS" + fi + + # LaunchAgent plist (only if not using brew services) + if [[ -z "$MESSENGER_BIN" ]] && [[ ! -f "$PLIST" ]]; then + cat > "$PLIST" << PLIST_EOF + + + + + Label + ai.fusionaize.grid-messenger + ProgramArguments + + ${VENV_PYTHON} + ${SCRIPT_DIR}/src/grid_messenger.py + + EnvironmentVariables + + APPS_FILE + ${DATA_DIR}/apps.json + + EnvironmentFiles + + ${CONFIG_DIR}/config.env + + RunAtLoad + + KeepAlive + + StandardOutPath + ${DATA_DIR}/grid-messenger.log + StandardErrorPath + ${DATA_DIR}/grid-messenger.log + WorkingDirectory + ${SCRIPT_DIR} + + +PLIST_EOF + echo "[grid-messenger] LaunchAgent created at ${PLIST}" + echo " → Start with: launchctl load ${PLIST}" + fi + + echo "" + echo "[grid-messenger] Installed (macOS)." + if command -v faigrid-messenger >/dev/null 2>&1; then + echo " Start: brew services start faigrid" + echo " Restart: brew services restart faigrid" + echo " Logs: tail -f $(brew --prefix)/var/log/faigrid/messenger.log" + else + echo " Edit config: ${CONFIG_DIR}/config.env" + echo " Start: launchctl load ${PLIST}" + echo " Logs: tail -f ${DATA_DIR}/grid-messenger.log" + fi + exit 0 +fi + +# ── Linux (systemd / grid-core node) ───────────────────────────────────────── INSTALL_DIR="/opt/grid-messenger" CONFIG_DIR="/etc/grid-messenger" SERVICE_USER="grid-messenger" -echo "[grid-messenger] Installing prerequisites…" -sudo apt-get update -y -sudo apt-get install -y python3 python3-pip python3-venv +echo "[grid-messenger] Linux detected — using systemd setup" + +if command -v apt-get >/dev/null 2>&1; then + sudo apt-get update -y -q + sudo apt-get install -y -q python3 python3-pip python3-venv +elif command -v dnf >/dev/null 2>&1; then + sudo dnf install -y -q python3 python3-pip +else + echo "[grid-messenger] WARNING: unknown package manager — ensure python3 + venv are available" +fi echo "[grid-messenger] Creating system user '${SERVICE_USER}'…" if ! id -u "$SERVICE_USER" >/dev/null 2>&1; then @@ -39,30 +164,21 @@ echo "[grid-messenger] Creating config template…" if [[ ! -f "${CONFIG_DIR}/config.env" ]]; then sudo tee "${CONFIG_DIR}/config.env" > /dev/null << 'EOF' # fusionAIze Grid Messenger — Configuration -# Edit with: sudo nano /etc/grid-messenger/config.env -# Then restart: sudo systemctl restart grid-messenger +# Edit: sudo nano /etc/grid-messenger/config.env +# Restart: sudo systemctl restart grid-messenger -# Required: get from @BotFather on Telegram TELEGRAM_BOT_TOKEN= - -# Your Telegram user ID (find via @userinfobot) TELEGRAM_ALLOWED_USER_IDS= - -# Chat IDs for proactive notifications (defaults to ALLOWED_USER_IDS) NOTIFY_CHAT_IDS= - -# Core service URLs (default: localhost) N8N_BASE_URL=http://127.0.0.1:5678 FAIGATE_URL=http://127.0.0.1:8090 OPENCLAW_URL=http://127.0.0.1:18789 - -# Inbound HTTP port (for n8n → grid-messenger approval requests) WEBHOOK_PORT=9119 WEBHOOK_BIND=127.0.0.1 +APPS_FILE=/opt/grid-messenger/apps.json EOF sudo chown root:"$SERVICE_USER" "${CONFIG_DIR}/config.env" sudo chmod 640 "${CONFIG_DIR}/config.env" - echo "[grid-messenger] Config template created at ${CONFIG_DIR}/config.env" fi echo "[grid-messenger] Installing systemd service…" @@ -72,7 +188,7 @@ sudo systemctl daemon-reload sudo systemctl enable grid-messenger.service echo "" -echo "[grid-messenger] Installed." -echo " Next: configure via faigrid workbench → grid-messenger → Configure" -echo " Or: sudo nano ${CONFIG_DIR}/config.env" -echo " sudo systemctl start grid-messenger" +echo "[grid-messenger] Installed (Linux)." +echo " Configure: sudo nano ${CONFIG_DIR}/config.env" +echo " Start: sudo systemctl start grid-messenger" +echo " Logs: journalctl -u grid-messenger -f" From 425d14bb93414fb003b10e7c89f2deb48dd4f9ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Lange?= Date: Mon, 13 Apr 2026 21:02:35 +0200 Subject: [PATCH 3/4] ci: remove CodeQL workflow (GitHub Advanced Security costs money for private repos) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Will be re-evaluated when repos move to self-hosted Forgejo. CodeQL scans showed no findings — removal is safe. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/codeql.yml | 41 ------------------------------------ 1 file changed, 41 deletions(-) delete mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index d7ba3e2..0000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: CodeQL Security Analysis - -on: - push: - branches: [main] - pull_request: - branches: [main] - schedule: - - cron: '0 3 * * 1' # Weekly Monday 03:00 UTC - -jobs: - analyze: - name: CodeQL — ${{ matrix.language }} - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - # python covers grid_messenger.py; add more languages as the project grows - language: [python] - - steps: - - name: Checkout - uses: actions/checkout@v6 - - - name: Initialize CodeQL - uses: github/codeql-action/init@v4 - with: - languages: ${{ matrix.language }} - - - name: Autobuild - uses: github/codeql-action/autobuild@v4 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 - with: - category: /language:${{ matrix.language }} From e91f9adbb375fbd7b75e8f1b74e4e4f8476cebeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Lange?= Date: Tue, 14 Apr 2026 03:54:15 +0200 Subject: [PATCH 4/4] ci: consolidate into ci.yml with CI Gate aggregator (mirrors faigate pattern) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add ci.yml with jobs: shellcheck, python-lint, version-check, bats (matrix ubuntu/macos), forbid-artifacts, gate - gate job (name: CI Gate) aggregates all required checks — matches branch protection required_status_checks context - Remove lint.yml and test.yml (jobs consolidated into ci.yml) Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 116 +++++++++++++++++++++++++++++++++++++ .github/workflows/lint.yml | 65 --------------------- .github/workflows/test.yml | 33 ----------- 3 files changed, 116 insertions(+), 98 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/lint.yml delete mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..6263ebd --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,116 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + # ── Shell: ShellCheck ──────────────────────────────────────────────────────── + shellcheck: + name: ShellCheck + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Run ShellCheck + uses: ludeeus/action-shellcheck@master + with: + ignore_paths: tests/* + + # ── Python: grid-messenger ─────────────────────────────────────────────────── + python-lint: + name: Python (ruff) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 + with: + python-version: "3.12" + - run: pip install ruff + - name: Ruff check + run: ruff check core/messenger/src/ + - name: Ruff format check + run: ruff format --check core/messenger/src/ + + # ── Version consistency ────────────────────────────────────────────────────── + version-check: + name: Version consistency + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Compare VERSION vs install.sh + run: | + FILE_VER="$(cat VERSION)" + SCRIPT_VER="$(grep -oE '[0-9]+\.[0-9]+\.[0-9]+' install.sh | head -1)" + echo "VERSION file : ${FILE_VER}" + echo "install.sh : ${SCRIPT_VER}" + if [[ "$FILE_VER" != "$SCRIPT_VER" ]]; then + echo "::error::Version mismatch: VERSION=${FILE_VER} install.sh=${SCRIPT_VER}" + exit 1 + fi + + # ── Bats test suite ────────────────────────────────────────────────────────── + bats: + name: Bats Tests + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v6 + - name: Make scripts executable + run: | + chmod +x install.sh + find tests -type f -name "*.sh" -exec chmod +x {} \; + - name: Run unit tests + run: tests/run_tests.sh --unit + - name: Run functional tests + run: tests/run_tests.sh --functional + - name: Run smoke tests + run: tests/run_tests.sh --smoke + + # ── Forbidden artifacts ────────────────────────────────────────────────────── + forbid-artifacts: + name: Forbid artifacts + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + - name: Fail if forbidden paths are tracked + run: | + set -euo pipefail + if git ls-files | grep -qE '(\.ssh/|\.db($|-)|.*\.sqlite|.*\.log$|\.env$)'; then + echo "ERROR: forbidden files are tracked:" + git ls-files | grep -E '(\.ssh/|\.db($|-)|.*\.sqlite|.*\.log$|\.env$)' || true + exit 1 + fi + - name: Fail if history contains forbidden blobs + run: | + set -euo pipefail + if git rev-list --objects --all | grep -qE '(\.ssh/|.*\.db($|-)|.*\.sqlite|.*\.log$)'; then + echo "ERROR: forbidden artifacts exist in history:" + git rev-list --objects --all \ + | grep -E '(\.ssh/|.*\.db($|-)|.*\.sqlite|.*\.log$)' || true + exit 1 + fi + + # ── CI Gate (aggregator — required by branch protection) ───────────────────── + gate: + name: CI Gate + runs-on: ubuntu-latest + needs: [shellcheck, python-lint, version-check, bats, forbid-artifacts] + if: always() + steps: + - name: All required checks passed + run: | + if [[ "${{ needs.shellcheck.result }}" != "success" ]] || + [[ "${{ needs.python-lint.result }}" != "success" ]] || + [[ "${{ needs.version-check.result }}" != "success" ]] || + [[ "${{ needs.bats.result }}" != "success" ]] || + [[ "${{ needs.forbid-artifacts.result }}" != "success" ]]; then + echo "::error::One or more required checks failed — merge blocked." + exit 1 + fi + echo "All required checks passed." diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 3691c37..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: Lint - -on: - push: - branches: [main] - pull_request: - branches: [main] - -jobs: - # ── Shell: ShellCheck ─────────────────────────────────────────────────────── - shellcheck: - name: ShellCheck - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - name: Run ShellCheck - uses: ludeeus/action-shellcheck@master - with: - ignore_paths: tests/* - - # ── Python: grid-messenger ────────────────────────────────────────────────── - python-lint: - name: Python (ruff) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: '3.12' - - run: pip install ruff - - name: Ruff check - run: ruff check core/messenger/src/ - - name: Ruff format check - run: ruff format --check core/messenger/src/ - - # ── Version consistency ───────────────────────────────────────────────────── - version-check: - name: Version consistency - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - name: Compare VERSION vs install.sh - run: | - FILE_VER="$(cat VERSION)" - SCRIPT_VER="$(grep -oE '[0-9]+\.[0-9]+\.[0-9]+' install.sh | head -1)" - echo "VERSION file : ${FILE_VER}" - echo "install.sh : ${SCRIPT_VER}" - if [[ "$FILE_VER" != "$SCRIPT_VER" ]]; then - echo "::error::Version mismatch: VERSION=${FILE_VER} install.sh=${SCRIPT_VER}" - exit 1 - fi - - # ── CHANGELOG up-to-date ─────────────────────────────────────────────────── - changelog: - name: Changelog (git-cliff) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - uses: orhun/git-cliff-action@v4 - with: - config: .cliff.toml - args: --validate - continue-on-error: true # advisory only until CHANGELOG.md is seeded diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 2dcfc0c..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: fusionAIze Grid Test Suite - -on: - push: - branches: [ "main", "feat/*" ] - pull_request: - branches: [ "main" ] - -jobs: - test: - name: Run Bats Tests - strategy: - matrix: - os: [ubuntu-latest, macos-latest] - runs-on: ${{ matrix.os }} - - steps: - - name: Checkout Code - uses: actions/checkout@v6 - - - name: Make Scripts Executable - run: | - chmod +x install.sh - find tests -type f -name "*.sh" -exec chmod +x {} \; - - - name: Run Unit Tests - run: tests/run_tests.sh --unit - - - name: Run Functional Tests - run: tests/run_tests.sh --functional - - - name: Run Smoke Tests - run: tests/run_tests.sh --smoke