Skip to content
Merged
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
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ jobs:
with:
binary_name: nullhub
artifact_prefix: nullhub
zig_version: "0.16.0"
node_version: "22"
node_cache_dependency_path: ui/package-lock.json
targets_json: >-
[
{"os":"ubuntu-latest","target":"linux-x86_64","zig_target":"x86_64-linux-musl"},
{"os":"ubuntu-latest","target":"linux-aarch64","zig_target":"aarch64-linux-musl"},
{"os":"macos-latest","target":"macos-aarch64","zig_target":"aarch64-macos"},
{"os":"windows-latest","target":"windows-x86_64","zig_target":"x86_64-windows"}
{"os":"windows-2025-vs2026","target":"windows-x86_64","zig_target":"x86_64-windows"}
]
test_command: bash tests/test_backend.sh
pre_build_command: |
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
with:
binary_name: nullhub
artifact_prefix: nullhub
zig_version: "0.16.0"
node_version: "22"
node_cache_dependency_path: ui/package-lock.json
targets_json: >-
Expand All @@ -27,8 +28,8 @@ jobs:
{"os":"ubuntu-latest","target":"linux-riscv64","zig_target":"riscv64-linux-musl","zig_cpu":"","ext":""},
{"os":"macos-latest","target":"macos-aarch64","zig_target":"aarch64-macos","zig_cpu":"","ext":""},
{"os":"macos-latest","target":"macos-x86_64","zig_target":"x86_64-macos","zig_cpu":"","ext":""},
{"os":"windows-latest","target":"windows-x86_64","zig_target":"x86_64-windows","zig_cpu":"","ext":".exe"},
{"os":"windows-latest","target":"windows-aarch64","zig_target":"aarch64-windows","zig_cpu":"","ext":".exe"}
{"os":"windows-2025-vs2026","target":"windows-x86_64","zig_target":"x86_64-windows","zig_cpu":"","ext":".exe"},
{"os":"windows-2025-vs2026","target":"windows-aarch64","zig_target":"aarch64-windows","zig_cpu":"","ext":".exe"}
]
pre_build_command: |
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ zig-out/
.worktrees/
.generated_ui_assets.zig
src/.generated_ui_assets.zig
/.playwright-mcp/
/nulldesk-web-*.png
3 changes: 1 addition & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Documentation

Project documentation has moved to [README.md](README.md) and `docs/`.
Project documentation lives in [README.md](README.md) and `docs/`.

- Read first: `README.md`
- Design docs: `docs/plans/`
3 changes: 1 addition & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Documentation

Project documentation has moved to [README.md](README.md) and `docs/`.
Project documentation lives in [README.md](README.md) and `docs/`.

- Read first: `README.md`
- Design docs: `docs/plans/`
98 changes: 0 additions & 98 deletions HACKATHON_SUBMISSION.md

This file was deleted.

112 changes: 82 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@ NullTickets, NullWatch).
- **Process supervision** -- start, stop, restart, crash recovery with backoff
- **Health monitoring** -- periodic HTTP health checks, dashboard status cards
- **Cross-component linking** -- auto-connect `NullTickets -> NullBoiler`, generate native tracker config, and inspect queue/orchestrator status from one UI
- **Config management** -- structured editors for `NullClaw`, `NullBoiler`, `NullTickets`, and `NullWatch`, with raw JSON fallback when needed
- **Config management** -- structured editors for `NullClaw`, `NullBoiler`, `NullTickets`, and `NullWatch`, plus direct raw JSON editing when needed
- **Log viewing** -- tail and live SSE streaming per instance
- **One-click updates** -- download, migrate config, rollback on failure
- **Multi-instance** -- run multiple instances of the same component side by side
- **Web UI + CLI** -- browser dashboard for humans, CLI for automation
- **Managed instance admin API** -- instance-scoped status, config, models, cron, channels, and skills routes for managed NullClaw installs
- **Orchestration UI** -- workflow editor, poll-based run monitoring, checkpoint forking, encoded workflow/run/store links, and key-value store browser (proxied to NullTickets through NullHub)
- **Observability cockpit** -- local NullWatch run summaries, span timelines, eval results, token usage, cost, and error context through a NullHub proxy
- **NullBoiler UI** -- workflow editor, poll-based run monitoring, checkpoint forking, and encoded workflow/run links
- **NullTickets Store** -- key-value store browser proxied to NullTickets through NullHub
- **NullWatch Flight Recorder** -- local NullWatch run summaries, span timelines, eval results, token usage, cost, and error context through a NullHub proxy
- **Mission Control** -- local-first agent mission replay with workflow execution, role-based agents, failure, checkpoint recovery, durable replay storage, and live telemetry in one screen

## Quick Start

Expand Down Expand Up @@ -114,17 +116,19 @@ UI modules. NullHub is a generic engine that interprets manifests.
**Storage** -- all state lives under `~/.nullhub/` (config, instances, binaries,
logs, cached manifests).

**Orchestration proxy** -- requests to `/api/orchestration/*` are reverse-proxied
to the local orchestration stack. Most routes go to NullBoiler's REST API via
**NullBoiler proxy** -- requests to `/api/nullboiler/*` are reverse-proxied
to NullBoiler's REST API via
`NULLBOILER_URL` (e.g. `http://localhost:8080`) and optional `NULLBOILER_TOKEN`.
`/api/orchestration/store/*` is proxied to NullTickets via `NULLTICKETS_URL` and

**NullTickets store proxy** -- requests to `/api/nulltickets/store/*` are
proxied to NullTickets via `NULLTICKETS_URL` and
optional `NULLTICKETS_TOKEN`.

**Observability proxy** -- requests to `/api/observability/*` are reverse-proxied
**NullWatch proxy** -- requests to `/api/nullwatch/*` are reverse-proxied
to the managed NullWatch instance installed in NullHub. `NULLWATCH_URL` can
still override the target for an external NullWatch instance, and
`NULLWATCH_TOKEN` overrides the managed instance token when set. The built-in
Observability page uses this proxy to display run summaries, spans, evals,
NullWatch page uses this proxy to display run summaries, spans, evals,
latency, cost, and failure context without sending data to hosted services.

Local NullWatch setup:
Expand All @@ -137,29 +141,65 @@ Local NullWatch setup:

2. In the web UI, open **Install Component**, select **NullWatch**, keep or set
the API port to `7710`, and finish the wizard. The installer starts the
NullWatch instance and the observability proxy discovers it automatically.

3. Optional demo data can be ingested through the NullHub proxy:
NullWatch instance and the NullWatch proxy discovers it automatically.

**Mission Control API** -- requests to `/api/mission-control/*` drive a
deterministic local replay scenario for the `/mission-control` page. It does
not require hosted infrastructure or model secrets, and it hydrates with real
NullBoiler workflow evidence and NullWatch trace detail when matching local
instances are available. Responses include a schema version, scenario id,
deterministic replay mode, controls, graph, timeline, telemetry, NullWatch-style
run/span/eval trace references, and structured conflict errors for invalid
actions. The scenario lives in a versioned embedded replay fixture at
`src/core/mission_control/code_red.v1.json`; `zig build test` validates fixture
schema, references, ordering, required phases, graph links, and telemetry phase
coverage. Mission timeline trace links deep-link to `/nullwatch?run_id=...`.
When a managed NullWatch instance is running, `/mission-control` hydrates the
failure and recovery trace panels from live run detail through the NullWatch
proxy and preserves the selected watch in trace links. When a managed
NullBoiler instance has matching workflow evidence, the Mission Control API
includes that instance name with real workflow run links and checkpoint metadata
resolved through the NullBoiler proxy.
`GET /api/mission-control/replay` exports the current snapshot, source fixture,
the side-by-side failed/recovered replay artifact comparison once the recovered
run completes, and ecosystem mapping metadata as a portable JSON artifact for
debugging and review. `POST /api/mission-control/replay/save` stores that
artifact under `~/.nullhub/mission-control/replays/`; `GET
/api/mission-control/replays` lists saved replay records and `GET
/api/mission-control/replays/{id}` reads the durable artifact back.

### Mission Control Replay

Start NullHub locally and open `/mission-control`:

```bash
curl -X POST http://127.0.0.1:19800/api/observability/v1/spans \
-H 'Content-Type: application/json' \
-d '{"run_id":"demo-run-1","trace_id":"trace-demo-1","span_id":"span-1","source":"nullclaw","operation":"tool.call","status":"error","started_at_ms":1710000000000,"ended_at_ms":1710000001500,"tool_name":"shell","error_message":"tool call failed: command timed out","attributes_json":"{\"exit_code\":124}"}'
```bash
zig build run -- serve --host 127.0.0.1 --port 19802 --no-open
```

curl -X POST http://127.0.0.1:19800/api/observability/v1/evals \
-H 'Content-Type: application/json' \
-d '{"run_id":"demo-run-1","eval_key":"tool_success","scorer":"deterministic","score":0.0,"verdict":"fail","dataset":"demo","notes":"The tool call timed out."}'
```
The page provides `Replay Mission`, `Reset`, `Launch Mission`, and
`Fork From Checkpoint` controls. `Replay Mission` runs the deterministic reset,
launch, failure hold, checkpoint fork, and recovered replay sequence from one
click. Timeline events include trace chips that map the replay back to local
NullWatch-style run ids, span ids, operations, and eval keys. The page also
includes phase milestones and a failed-vs-recovered replay artifact comparison
panel.

### Observability Screenshots
Export the current replay artifact:

Flight Recorder overview:
```bash
curl -fsS http://127.0.0.1:19802/api/mission-control/replay \
-o mission-control-replay.json
```

![NullHub Observability overview](docs/screenshots/nullhub-observability-overview.png)
The same export is available from the `Save Replay` button in Mission Control,
which also writes a durable server-side copy.
See `docs/mission-control.md` for the artifact shape and ecosystem mapping.

Failure detail with tool-call error context:
Run the live API smoke test against a started server:

![NullHub Observability failure detail](docs/screenshots/nullhub-observability-failure.png)
```bash
NULLHUB_URL=http://127.0.0.1:19802 ./tests/test_mission_control_smoke.sh
```

## Development

Expand All @@ -182,6 +222,7 @@ End-to-end:

```bash
./tests/test_e2e.sh
NULLHUB_URL=http://127.0.0.1:19802 ./tests/test_mission_control_smoke.sh
```

`zig build test-integration` runs structured backend HTTP integration tests
Expand All @@ -193,7 +234,7 @@ against a real `nullhub` process started in a temporary home directory.
- Svelte 5 + SvelteKit (static adapter)
- JSON over HTTP/1.1
- SSE for instance log streaming
- Poll-based orchestration run updates over the `/orchestration/runs/{id}/stream` API
- Poll-based NullBoiler run updates over the `/api/nullboiler/runs/{id}/stream` API

## Project Layout

Expand All @@ -204,19 +245,30 @@ src/
server.zig # HTTP server (API + static UI)
auth.zig # Optional bearer token auth
api/ # REST endpoints (components, instances, wizard, ...)
orchestration.zig # Reverse proxy to NullBoiler orchestration API
observability.zig # Reverse proxy to NullWatch tracing/eval API
nullboiler.zig # Reverse proxy to NullBoiler workflow/run API
nulltickets.zig # Reverse proxy to NullTickets store API
nullwatch.zig # Reverse proxy to NullWatch tracing/eval API
mission_control.zig # HTTP adapter for local mission replay commands
core/ # Manifest parser, state, platform, paths
mission_control.zig # Local deterministic agent mission domain model
mission_control_replay.zig # Typed replay fixture parser and validator
mission_control/ # Embedded Mission Control replay fixtures
installer/ # Download, build, UI module fetching
supervisor/ # Process spawn, health checks, manager
ui/src/
routes/ # SvelteKit pages
orchestration/ # Orchestration pages (dashboard, workflows, runs, store)
observability/ # NullWatch flight recorder page
nullboiler/ # NullBoiler pages (dashboard, workflows, runs)
nulltickets/ # NullTickets pages (store)
nullwatch/ # NullWatch Flight Recorder page
mission-control/ # Local agent mission control room
lib/components/ # Reusable Svelte components
orchestration/ # GraphViewer, StateInspector, RunEventLog, InterruptPanel,
nullboiler/ # GraphViewer, StateInspector, RunEventLog, InterruptPanel,
# CheckpointTimeline, WorkflowJsonEditor, NodeCard, SendProgressBar
nulltickets/ # NullTickets store selectors and controls
lib/api/ # Typed API client
lib/missionControl/ # Mission Control feature helpers
tests/
test_e2e.sh # End-to-end test script
docs/
mission-control.md # Mission Control replay and artifact contract
```
Loading