Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions examples/kineticos-continuation-fleet/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# KineticOS — Architecture (review map)

This document maps the execution plan (Phases 0–9) onto the actual files, so a
reviewer can navigate the scaffold quickly. The build is a **single Next.js 15
app** (the proven shape for these hackathons) rather than the plan's literal
multi-service monorepo — but every plane and gate from the plan is present as a
module, and [`infra/render/render.yaml`](infra/render/render.yaml) shows how the
single app fans out into the plan's separate Render services for production.

## Vision (v2)

> CAD image of an assembly with a broken component → modified CAD file out, so
> production keeps running temporarily.

Input is a CAD image (a render/screenshot of the assembly with a broken or
missing component visible in situ). Output is a `ContinuationCadOutput` — a v1
OpenSCAD-style CAD file, a small BOM, and a textual operator runbook that
together let the line keep moving until the proper OEM replacement arrives.

The system chooses between four continuation strategies:

| Strategy | When |
|---|---|
| `substitute_component` | An off-the-shelf or community-cataloged part fits the surrounding assembly (Track A hit). |
| `printed_insert` | The default for unique geometry: a 3D-printable substitute that respects the assembly's mating interfaces. |
| `bridge_adapter` | A small printed adapter so an available in-stock standard fastener can stand in. |
| `simplified_geometry` | Strip non-load features so in-house tooling can produce the part today. |

## The load-bearing split

> **Render runs things. Superplane decides when and whether things run.**

| Plane | Module | Responsibility |
|---|---|---|
| Perception | `src/agents/perception/**` | CAD image → broken-component class → undamaged intent → mating interfaces |
| Continuation Design | `src/agents/design/**` | strategy choice → sourced substitute OR generated insert/adapter |
| Printability | `src/agents/material-adapter.ts` | re-parameterize against locally-loaded stock; printability margin |
| Orchestration | `src/lib/superplane/client.ts` + `src/lib/gates/` + `src/worker/jobs.ts` | workflow state, gates, fan-in, audit |
| Per-Job Runtime | `src/lib/render/client.ts` | births/kills the dedicated ephemeral `cad-validator-{jobId}` service |
| CAD Output | `src/agents/fabrication.ts` | emits the v1 `ContinuationCadOutput` + runs canary/bulk validator |
| Edge / Machine | `src/lib/edge/client.ts` | simulated on-prem agent: inventory + validator telemetry |

Both sponsor integrations are **clean stubs that run at zero credentials** and
upgrade to real APIs behind a flag (`SUPERPLANE_API_KEY`, `RENDER_API_KEY`).

## How Render is used (4 ways)

1. **Web service `kineticos`** — declared in [`render.yaml`](infra/render/render.yaml).
2. **Per-job ephemeral `cad-validator-{jobId}`** — created at runtime by
[`src/lib/render/client.ts → provisionRuntime`](src/lib/render/client.ts);
deleted on terminal status by `teardownRuntime`. The orphan-reaper cron
(commented in `render.yaml`) reconciles via `listEphemeralServices`.
3. **`/healthz`** — Render's healthcheck probe target
([`src/app/healthz/route.ts`](src/app/healthz/route.ts)).
4. **Managed Postgres `kineticos-pg`** — `DATABASE_URL` injected from the
managed DB into the web service.

## How Superplane is used (4 ways)

1. **`startRun`** — a Superplane run is opened on job ingest; the run id and
canvas URL are stamped on `Job.audit.superplaneRunId`.
2. **`emit`** — every JobStatus transition is emitted as a step event, giving
the run record a live timeline of the pipeline.
3. **`recordGate`** — every gate decision (proceed / human_review / block) is
recorded into the run record alongside the local audit trail.
4. **Workflow gating** — the four gates (`composite_confidence`,
`continuation_strategy`, `printability`, `output_acceptance`) live as pure
policy functions in [`src/lib/gates/`](src/lib/gates/) and the worker
pauses the job (`status: needs_human`, `pendingGate` set) when one routes
to a human.
5. **The agent fleet (Canvas)** — [`infra/superplane/kineticos-fleet.canvas.yaml`](infra/superplane/kineticos-fleet.canvas.yaml)
is the entire pipeline as a 34-node SuperPlane Canvas: the six perception
agents fan out in parallel from the ingest webhook, a `merge` fuses them, the
two design tracks branch on a sourcing hit, and each phase ends in the
`http evaluate-gate → if → approval` gate pattern before the line resumes.
Every action node is an `http` executor hitting one agent endpoint —
granular [`/api/agents/[agent]`](src/app/api/agents) for the perception
sensors + design tracks, coarse [`/api/stages/*`](src/app/api/stages) for
phases 4 and 5–7. The in-process worker and the Canvas are two drivers of the
same agents + gates (`LOCAL_ORCHESTRATOR=1` selects the worker).

## The spine

[`src/lib/types.ts`](src/lib/types.ts) — the canonical `Job` object every stage
keys off (Phase 0.3), plus the Phase 2/3/4/8 output contracts, the gate types,
the new `ContinuationStrategy` enum, the v1 `ContinuationCadOutput` type, and
the **locked stage signatures** the worker imports and each stage module
implements.

## The pipeline (worker drives it, upserting the Job after every step)

`src/worker/jobs.ts` runs stages in order and evaluates a Superplane gate
between phases; a human-scoped gate pauses the job (`needs_human`) and resumes
on `resolveGate()`.

| Phase | Stage | File |
|---|---|---|
| 2A | CAD image conditioning / admissibility | `src/agents/perception/conditioning.ts` |
| 2B | Broken-component localization *(exemplar)* | `src/agents/perception/classification.ts` |
| 2C | Reconstruct the **undamaged intent** | `src/agents/perception/reconstruction.ts` |
| 2D | Interface extraction (terminal scale chain) | `src/agents/perception/dimensioning.ts` |
| 2E | Material & surface inference | `src/agents/perception/material.ts` |
| 2F | Telemetry track + sensor fusion | `src/agents/perception/telemetry.ts` |
| **2.G** | **Composite confidence gate** | `src/lib/gates/index.ts` → `compositeConfidenceGate` |
| 3A | Substitute sourcing (Track A) | `src/agents/design/sourcing.ts` |
| 3B | Generative continuation CAD B1–B8 (Track B) | `src/agents/design/generative-cad.ts` |
| **3.G** | **Continuation strategy gate** | `src/lib/gates/index.ts` → `designAcceptanceGate` |
| 4 | Printability adaptation + toolpath | `src/agents/material-adapter.ts` |
| **4.3** | **Printability feasibility gate** | `src/lib/gates/index.ts` → `structuralGate` |
| 5 | Provision dedicated cad-validator service | `src/lib/render/client.ts` → `provisionRuntime` |
| 6/7 | Emit v1 ContinuationCadOutput + canary/bulk validator | `src/agents/fabrication.ts` |
| 8 | Output validation | `src/agents/fabrication.ts` |
| **8.1** | **Output acceptance gate** → COMPLETE | `src/lib/gates/index.ts` → `acceptanceGate` |
| 8.2 | Teardown dedicated runtime | `src/lib/render/client.ts` → `teardownRuntime` |
| 8.3 | Audit seal | `src/lib/audit.ts` + `Job.audit` |

## Data & API

- `src/lib/store.ts` — dual-layer job store: globalThis `Map` always-on, Postgres
write-through when `DATABASE_URL` is set. `src/lib/db/**` is the pg layer.
- `src/app/api/jobs/route.ts` — `POST` ingest (422 if neither `cadImageUris`
nor `telemetryUri`), `GET` list.
- `src/app/api/jobs/[id]/route.ts` — `GET` one (polling target).
- `src/app/api/jobs/[id]/gate/route.ts` — `POST` resolve a scoped human gate.
- `src/app/healthz/route.ts` — Render health check target.

## UI (live polling, dark theme)

`src/app/page.tsx` tab shell → `src/components/tabs/{IntakeTab,PipelineTab,GatesTab,AuditTab}.tsx`,
all built on `src/components/ui.tsx` primitives and `src/lib/usePolling.ts`.
The PipelineTab carries the new **Continuation CAD output (v1)** panel that
renders the OpenSCAD payload + BOM + runbook with a `data:` download link.

## V1 CAD output — what's intentionally rough

The v1 `ContinuationCadOutput` payload is a plain-text OpenSCAD script. It
captures the resolved mating interfaces (bore, plate footprint, tooth count)
but the non-load features are simplified for fast 3D printing — gear teeth are
square notches, not involute curves; brackets are flat plates with corner
holes; everything else is a bored block. A v2 swap to a real CAD-kernel
B-rep through the `cad-validator-{jobId}` service is a drop-in replacement of
the `buildOpenscadScript` helper in `src/agents/fabrication.ts` — the
`ContinuationCadOutput` contract (`format`, `filename`, `contents`, `bom`,
`runbook`) is the same, and every other plane already keys off that shape.

## Not yet built (Phase 9 hardening — deliberately deferred for review)

- Orphan-reaper cron logic (the primitive `render.listEphemeralServices()`
exists; the reconcile job/endpoint is a TODO in `render.yaml`).
- 2A→3A bounded reconstruction refinement loop (single-pass today).
- Real per-job mTLS / signing-key verification on the edge channel (key is
generated and passed; verification is simulated).
- Real CAD kernel for the v2 continuation output (drop-in behind
`buildOpenscadScript`).
140 changes: 140 additions & 0 deletions examples/kineticos-continuation-fleet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# KineticOS

**CAD image of an assembly with a broken component in → modified CAD file out, so production keeps running.**

<p align="center">
<a href="http://localhost:3001">
<img alt="Open in SuperPlane" src="https://img.shields.io/badge/%E2%96%B6%20Open%20in%20SuperPlane-6E56CF?style=for-the-badge&labelColor=2D2A45" height="40">
</a>
</p>

> ☝️ Opens the **SuperPlane app** — the canvas with the full agent fleet (every
> perception, design, printability, and validation agent + the gates between
> them), hosted locally on **http://localhost:3001** (KineticOS keeps :3000).
> To bring it up from scratch — no Docker Desktop needed:
>
> ```bash
> # 1. a headless container runtime
> brew install colima docker && colima start --vm-type vz --vz-rosetta
> # 2. host the SuperPlane app on :3001
> docker run -d --name superplane -p 3001:3000 \
> -e BASE_URL=http://localhost:3001 -e ALLOWED_WS_ORIGINS=http://localhost:3001 \
> -v spdata:/app/data ghcr.io/superplanehq/superplane-demo:stable
> # 3. point the fleet canvas at KineticOS and load it — host.docker.internal
> # reaches the host from inside the SuperPlane container
> infra/superplane/apply.sh http://host.docker.internal:3000 # or import the YAML in the UI
> ```
>
> See [`infra/superplane/`](infra/superplane/) for the canvas + the full walkthrough.

KineticOS ingests a CAD image of a mechanical assembly that has a broken or
missing component, locates the break, **reconstructs the intended undamaged
geometry** (never the cracked artifact), picks a **continuation strategy** —
an off-the-shelf substitute, a 3D-printable insert, a small bridge adapter, or
a simplified-geometry version — re-parameterizes the design against locally
loaded stock, then spins up a **dedicated, ephemeral cloud validator per job**
and hands back a **v1 CAD file** the operator can save, slice, and use to keep
the line running until the OEM replacement arrives.

> The CAD output itself is **v1** — an OpenSCAD-style script that captures the
> mating interfaces and the chosen strategy. The surrounding system (gates,
> per-job ephemeral runtime, audit trail, multi-plane orchestration) is fit to
> the final vision so v1 can be swapped for a real CAD-kernel output later
> without disturbing anything else.

Two load-bearing constraints, kept strictly separate:

> **Render runs things. Superplane decides when and whether things run.**

## Render — four ways

1. **Web service** — `kineticos` hosts the Next.js app (UI + API + `/healthz`).
See [`infra/render/render.yaml`](infra/render/render.yaml).
2. **Per-job ephemeral service** — `cad-validator-{jobId}` is born and killed
by [`src/lib/render/client.ts`](src/lib/render/client.ts) for every job.
Receives the v1 CAD output, runs the canary→bulk validator passes, streams
progress frames back. No shared multi-tenant endpoint — one job, one service.
3. **Healthcheck probe** — Render polls [`/healthz`](src/app/healthz/route.ts)
to drive its readiness gate.
4. **Managed Postgres** — `kineticos-pg` backs the durable Job + audit store
when `DATABASE_URL` is set ([`src/lib/db/**`](src/lib/db/)).

## Superplane — four ways

1. **Workflow run record** — every Job starts a Superplane run; the canvas
URL is stamped on `Job.audit.superplaneRunId`
([`src/lib/superplane/client.ts`](src/lib/superplane/client.ts) ·
`startRun`).
2. **Step transitions** — every status change is emitted as a step event
(`emit`) so the run record is a live timeline of the pipeline.
3. **Gates** — four distinct gates (`composite_confidence` 2.G,
`continuation_strategy` 3.G, `printability` 4.3, `output_acceptance` 8.1)
live as pure policy functions in [`src/lib/gates/`](src/lib/gates/) and
recorded through `recordGate`. Human-scoped gates park the job in the
**Gates** tab; the rest pass through.
4. **Audit fan-in** — gate decisions are mirrored into the run record, giving
one immutable provenance trail across every plane — the liability record
the AuditTab renders.

### The agent fleet (Canvas)

[`infra/superplane/kineticos-fleet.canvas.yaml`](infra/superplane/kineticos-fleet.canvas.yaml)
is the **whole process as one SuperPlane Canvas** — 34 nodes that fan the six
perception agents out in parallel, fuse them, branch the two design tracks, and
gate between every phase (`http evaluate-gate → if → approval`) before the line
resumes production. Each action node is an `http` executor calling one KineticOS
agent at [`/api/agents/*`](src/app/api/agents) (roster: `GET /api/agents`); it
runs at zero credentials. See [`infra/superplane/README.md`](infra/superplane/README.md)
to load it, and `infra/superplane/smoke.sh` to rehearse a full run offline.

## Runs at zero credentials

Every integration is optional. With **no** environment variables the full
pipeline runs end-to-end on deterministic fallbacks: Claude → rule-based
stages, Superplane → an in-process control-plane model, Render → a simulated
provision/teardown lifecycle, the validator → simulated telemetry, Postgres →
an in-process `Map`. Each key upgrades exactly one plane from simulated to
real.

## Quickstart

```bash
npm install
npm run dev # http://localhost:3000
```

Open the app → **Intake** tab → drop a CAD image of the broken assembly → add
an optional assembly context / failure note → **Ingest CAD image**, then watch
the **Pipeline** tab drive the job through perception → continuation design →
printability → provisioning → CAD output → validation, with Superplane gates
in between. The **Continuation CAD output (v1)** panel shows the emitted
OpenSCAD file with a download link. Low-confidence jobs pause in the
**Gates** tab; the full provenance trail is in **Audit**.

Optional — turn planes real:

```bash
cp .env.example .env.local
# ANTHROPIC_API_KEY → Claude for the LLM-bearing stages
# SUPERPLANE_API_KEY → the real Superplane control plane
# RENDER_API_KEY → real ephemeral per-job cad-validator provisioning
# DATABASE_URL → durable jobs + audit trail (npm run db:migrate && npm run db:seed)
```

## Architecture

The single Next.js app maps the plan's four planes and every gate onto modules;
see **[ARCHITECTURE.md](ARCHITECTURE.md)** for the full Phase-0–9 → file map.
The canonical `Job` object in [`src/lib/types.ts`](src/lib/types.ts) is the
spine everything keys off — including the new `ContinuationStrategy` enum and
the `ContinuationCadOutput` v1 deliverable.
[`infra/render/render.yaml`](infra/render/render.yaml) shows the production
Render split.

## Status

Scaffold + architecture, aligned to the CAD-continuation vision. The pipeline,
gates, dual-layer store, Render/Superplane stub interfaces, live UI, and v1
CAD output emitter run end-to-end. The v1 CAD output is intentionally a
placeholder (OpenSCAD script) — the surrounding system is built to accept a
real CAD-kernel STEP/STL output without changing any other module.
62 changes: 62 additions & 0 deletions examples/kineticos-continuation-fleet/SUBMISSION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# KineticOS — a SuperPlane agent-fleet example

A self-contained snapshot of **KineticOS**, a project built **on top of
SuperPlane**: a CAD image of a broken industrial machine comes in → a fleet of
agents looks at it, identifies the fault, reconstructs the intended part,
generates a new **3D-printable CAD file**, validates it, and **resumes
production** — with SuperPlane gating every phase.

> **Heads-up for maintainers:** this is a *downstream application* example, not a
> change to the SuperPlane platform. It's contributed as an `examples/` folder so
> it adds nothing to your build/CI and touches none of your tree. If you'd prefer
> only the workflow template, the single file worth upstreaming is the Canvas
> below — it can be dropped into `templates/canvases/` with `metadata.isTemplate:
> true` per `docs/contributing/templates.md`. Happy to reshape this PR to just
> that if you'd rather.

## The primary artifact — the Canvas

[`infra/superplane/kineticos-fleet.canvas.yaml`](infra/superplane/kineticos-fleet.canvas.yaml)
is a 34-node Canvas exercising a lot of SuperPlane in one real workflow:

- **Parallel fan-out + `merge`** — six perception agents run concurrently from
the ingest trigger, then a `merge` barrier fuses them.
- **The gate pattern (×4)** — each phase ends in `http` (evaluate-gate) → `if`
(`decision == "proceed"`) → `approval` (the human gate), with rejections
routed to a halt sink.
- **Conditional branching** — an `if` picks an off-the-shelf substitute vs. a
generated continuation part.
- **`http` executors** call the app's agent endpoints; **annotations** document
each section on-canvas.

`infra/superplane/kineticos-fleet.local.canvas.yaml` is the same Canvas with
executor URLs pointed at `host.docker.internal:3000` for a locally-hosted
SuperPlane (container) calling the app (host).

## The rest of the folder (the downstream app)

- `src/app/api/agents/**` + `src/lib/contract.ts` — the Next.js HTTP executors
each Canvas node calls (one agent per endpoint). **Illustrative** — this is
the KineticOS app, not SuperPlane platform code; it isn't built by your CI.
- `infra/superplane/{README.md,apply.sh,smoke.sh}` — node→agent→endpoint map,
a canvas loader (host substitution + `superplane canvas create`), and an
offline end-to-end fleet rehearsal.
- `README.md` / `ARCHITECTURE.md` — the KineticOS project docs for context.

## Run it

```bash
# the app (executors) — runs at zero credentials
npm install && npm run dev # KineticOS on :3000

# SuperPlane locally (no Docker Desktop needed)
brew install colima docker && colima start --vm-type vz --vz-rosetta
docker run -d --name superplane -p 3001:3000 \
-e BASE_URL=http://localhost:3001 -e ALLOWED_WS_ORIGINS=http://localhost:3001 \
-v spdata:/app/data ghcr.io/superplanehq/superplane-demo:stable

# load the fleet (host.docker.internal reaches the host from the container)
infra/superplane/apply.sh http://host.docker.internal:3000 # then import in the UI
```

Full project: https://github.com/sahielbose/KineticOS-Superplane-Hackathon
Loading