Operator surface for Alpha — the self-improving loop:
observe → evaluate → propose → validate → apply → reflect
Every step is wrapped by Curator default-deny. See ALPHA.md for the contract and src/alpha/ for the runtime.
View app in AI Studio: https://ai.studio/apps/b5aaaeef-c202-4714-bf1a-9659a0516786
Prereqs: Node.js 22+.
npm install
cp .env.example .env.local # then set GEMINI_API_KEY in .env.local
npm run server:dev # terminal 1 — Express on :8080
npm run dev # terminal 2 — Vite client on :3000
The Vite dev server proxies /api/* to http://localhost:8080, so the client never sees GEMINI_API_KEY.
GET /api/health— service status, version, git sha, building info, bridge + Gemini config flags.POST /api/prompt/:name— dispatches an Alpha prompt to Gemini server-side. Names:observer,evaluator,proposer,curator,applier,reflector,repeatCheck,councilSecondOpinion. Body:{ "input": "…" }.
npm test # one-shot
npm run test:watch # watch mode
Covers all Curator denial codes and all 9 Applier hardening rules.
HomeBase polls the AtomArcade Bridge every 15 seconds to check:
- env — required environment variables loaded
- notion — Notion API connectivity (
/users/me) - ollama — local Ollama runtime (
/api/tags) - gemini — Gemini API key valid (if configured)
The /api/bridge/health endpoint returns:
{
"ok": true,
"checks": { "env": { "ok": true, ... }, ... },
"telemetry": {
"historyLength": 5,
"isFlapping": false,
"firstFailureTime": null,
"lastSuccessTime": "2026-05-18T12:00:00Z"
}
}isFlapping: true if 3+ failures in last 10 checks.firstFailureTime: timestamp of first consecutive failure.
A red alert banner appears when:
- Overall status flips from
ok: truetook: false - Flapping is detected (3+ failures in 10 checks)
Health snapshots are stored in-memory (ring buffer of 50) and optionally persisted to JSONL:
HOMEBASE_HEALTH_HISTORY_PATH=C:\AtomArcade\health-history.jsonlWhen bridge health fails, HomeBase can write incidents to Notion.
- Enable the feature:
NOTION_INCIDENT_LOG_ENABLED=true- Configure Notion:
NOTION_API_KEY=secret_...
ATOMARCADE_NOTION_LOG_DB_ID=your-log-db-id- Triggers on:
okflips true→false, OR flapping starts (false→true) - Rate limited: 1 incident per unique failure signature per 30 minutes
- No secrets written: API keys never appear in Notion
If using the Logs DB, ensure it has these properties:
- Kind: Select (e.g., "Incident", "Log")
- Timestamp: Title or Rich Text
- Status: Select (e.g., "Open", "Resolved")
- Detail: Rich Text
- Source: Rich Text (e.g., "HomeBase Telemetry")
When the system recovers (health transitions from ok: false → ok: true), the most recent incident is automatically resolved:
- System detects:
okflips false → true - Looks up open incident by signature (same failed checks)
- Updates Status: "Open" → "Resolved"
- Appends:
Resolved at <timestamp> (Duration: X min HomeBaseSHA=...) - Clears tracking so next failure creates a fresh incident
This ensures you never have stale "Open" incidents after temporary blips.
Every incident now includes version information for deployment correlation:
On Open:
HomeBaseSHA: Git SHA of HomeBase (fromGIT_SHAenv or.git/HEAD)BridgeVersion: Version reported by Bridge (bridge.versionorbridge.gitSha)BridgeURL: The bridge endpoint being monitored
Encoded in Detail: HomeBaseSHA=<...> BridgeVersion=<...> BridgeURL=<...> | <failure detail>
On Resolve:
- Appends:
Resolved at <timestamp> (Duration: X min HomeBaseSHA=<...>)
This enables correlating outages to specific deploys.
Group incidents by version pair to identify regressions. Data is persisted to JSONL and survives restarts.
Endpoint:
GET /api/bridge/incidents/correlation?window=24h|7d|allQuery Params:
| Param | Default | Description |
|---|---|---|
window |
24h |
Time window: 24h, 7d, or all |
Response:
{
"rows": [
{
"homeBaseSha": "abc1234",
"bridgeSha": "def5678",
"count": 5,
"openCount": 1,
"flappingCount": 0,
"lastSeen": "2026-05-18T12:34:56Z",
"avgDuration": "3 min",
"avgDurationMs": 180000
}
],
"window": "24h",
"generatedAt": "2026-05-18T12:34:56Z",
"source": "disk+memory"
}Features:
- Persists to
C:\AtomArcade\incident-log.jsonl(configurable viaINCIDENT_LOG_PATH) - In-memory cache for 30s (invalidated on new incident)
- Numeric
avgDurationMsavailable for programmatic sorting - 7d shows superset of 24h
Export:
GET /api/bridge/incidents/correlation/export?window=24hReturns CSV file for postmortems.
Single routing entrypoint with classification and guardrails.
Request:
{
"request": "show correlation export"
}Response:
{
"traceId": "trace_1234567_abc123",
"route": "telemetry",
"confidence": 1.0,
"decision": "allow",
"reason": "telemetry routes are safe",
"next": { "endpoint": "/api/bridge/incidents/correlation", "method": "GET" },
"timestamp": "2026-05-18T12:00:00.000Z",
"homeBaseSha": "abc1234"
}Routing Decisions:
| Route | Decision | Notes |
|---|---|---|
telemetry |
allow | Health, incidents, correlation, export |
lore |
allow | Memory, profile, curator |
kraken |
deny | Run, execute, deploy - locked by default |
unknown |
needs_human | Unrecognized - requires review |
Test Harness:
node loxa-test.jsRead-only knowledge surface behind Loxa router.
lore/profile.json— Operator profilelore/index.jsonl— Searchable lore entries
Returns the operator profile:
{
"ok": true,
"profile": { "name": "Loxa", ... },
"traceId": "trace_..."
}Search lore entries:
GET /api/lore/search?q=telemetryGet single entry:
GET /api/lore/entry/lore-001Default-deny, require operator confirm, rate limited.
Returns allowlist with schemas.
Headers required:
X-Operator-Confirm: yes(else 403)X-Trace-Id: <uuid>(optional)
Body:
{
"action": "echo",
"params": { "message": "hello" }
}Response:
{
"ok": true,
"traceId": "trace_...",
"action": "echo",
"decision": "executed",
"result": { "echoed": "hello", "at": "..." },
"durationMs": 5
}| Action | Description | Params |
|---|---|---|
echo |
Diagnostic echo | message: string (1-200) |
incident.note |
Append note to log | note: string (1-500), severity: info|warn |
- Default-deny
- Operator confirm required
- Rate limit: 10/min
- Secret scanner blocks tokens
- 5s timeout per action
node kraken-test.js