18 KiB
Waggle OS — Production-Readiness Assessment
Date: 2026-06-01
Commit: 839d4ce (main, tree clean except this report + the vision-E2E design doc)
Method: 5 parallel auditors (build/tsc, CI/deploy, open-work residuals, test-infra/local-run, vision-E2E design) + independent re-verification of every load-bearing claim against the live repo and the GitHub Actions API.
1. Bottom Line
Waggle OS is NOT production-ready for the desktop-binary / containerized-deploy path. A single dependency-ordering gap — build:packages never builds @waggle/hive-mind-core before the packages that hard-depend on it — red-lines the CI e2e job, BOTH Tauri verify jobs (Windows + macOS), and every deploy artifact, while the green CI checkmark on main hides it (the unit-test gate passes only because vitest aliases @waggle/* to src/). The unit-test suite, tsc gates, lint, and the local web build are genuinely green, and the open-work residuals (§10 #1/#2/#3, OQ-4, OQ-5) are code-complete and test-green — but the release/deploy plumbing has 6 hard blockers that must be fixed before any binary or server ship. The gates that remain are: fix the package-build order, make the Dockerfile/render.yaml buildable + add a DB-migration step, then runtime-verify on a real binary.
2. Production Blockers (must-fix-before-launch)
Each blocker re-verified independently. The first is the root cause of four downstream failures.
B1 — build:packages omits @waggle/hive-mind-core → breaks CI e2e + both Tauri verifies + release + deploy (ROOT CAUSE)
- Owner type: code
- Evidence:
package.jsonbuild:packages = shared→core→agent→server.packages/core/package.jsondeclares"@waggle/hive-mind-core": "*".packages/hive-mind-core/package.jsonexports ONLYdist/index.js+dist/index.d.ts(nosrcexport), itsdist/is gitignored (.gitignore:11:dist) and NOT tracked (git ls-files packages/hive-mind-core/dist/→ empty), and it is never built bybuild:packages. On a fresh checkout itsdist/is absent →tsc --buildofcoreemitsTS2307: Cannot find module '@waggle/hive-mind-core'(16 errors). Confirmed live: Tauriverify-macosrun26762292125on the current HEAD839d4cefailed at theBuild packages (shared → core → agent → server)step with exactly these TS2307 errors (src/config.ts(4,69),src/compliance/*,src/index.ts(81,8), etc.). The CIe2ejob fails identically at itsBuild packagesstep. (This is why the BUILD/TSC auditor saw "GREEN locally" — its machine had a stale pre-builtdist/; on fresh checkout it is RED, which the CI logs prove.) - Why CI looks green anyway: the unit
testjob passes only becausevitest.aliases.tsremaps@waggle/*→src/, sidestepping the missing dist. Thee2ejob iscontinue-on-error: true(ci.yml:46), so the workflow reportssuccesseven though e2e never runs. - Fix (verified): prepend
cd packages/hive-mind-core && npx tsc --build &&to thebuild:packagesscript. Re-verified the full corrected chain (hive-mind-core → shared → core → agent → server) exits 0 from a cleandist. This one change un-blocks e2e, both Tauri verifies,release.yml, and any deploy that runsbuild:all.
B2 — Tauri verify-windows + verify-macos both RED (desktop release path broken)
- Owner type: code (resolved by B1)
- Evidence:
gh run list(Tauri Build Verification / main /839d4ce):verify-windows=failure,verify-macos=failure. Both die at theBuild packagesstep with the TS2307 above — NOT at Rust compile / signing / native-deps (the workflow header comment's diagnosis is wrong; it never reaches Rust).release.yml(tag-triggered) shares the samesidecar→core→hive-mind-coredependency and will fail the same way on a realv*tag. - Fix: B1's fix. After it lands, re-run the Tauri verify workflow to confirm it now reaches (and passes) the Rust/Vite/sidecar stages.
B3 — Dockerfile is not buildable (three independent breakages)
- Owner type: code
- Evidence: (1)
Dockerfile:20,57,84COPY packages/ui/package.json packages/ui/— butpackages/ui/package.jsondoes not exist (CLAUDE.md §2:uiis not a workspace; confirmedls→ no such file) → COPY of a literal missing file fails the build. (2) Rootnpm run build=cd apps/web && tsc && vite build, but the Dockerfile only copiesapp/(:22,:29), neverapps/→RUN npm run buildfails (cd apps/webnot found). (3) Nohive-mind-*package source/manifest is copied, yetCMD npx tsx packages/server/src/index.tsresolves@waggle/core → @waggle/hive-mind-coreat runtime. - Fix: remove the
packages/uiCOPY lines; copyapps/(not justapp/); copy thehive-mind-*packages needed for runtime resolution; build packages (with B1's fix) beforenpm run build.
B4 — render.yaml builds the wrong directory and serves an empty/stale shell
- Owner type: code
- Evidence:
render.yaml:16buildCommand: npm install && cd app && npm run buildrunsvite buildinapp/, butapp/has nosrc/(confirmedls app/src→ no such file) andapp/index.htmlreferences/src/main.tsx. The real UI isapps/web.app/distis gitignored and the committed copy is a stale Apr-3 brand shell.WAGGLE_FRONTEND_DIR=./app/dist(render.yaml:28) → server serves nothing usable. The build also never runsbuild:packages, so the runtime entrypoint hits the same hive-mind-core gap. - Fix: point the build at the repo root
npm run build:all(which builds packages +apps/web→ root/dist) and setWAGGLE_FRONTEND_DIR=./dist.
B5 — No DB-migration step in any deploy artifact
- Owner type: code
- Evidence:
packages/server/src/db/migrate.tsruns drizzle migrations from./drizzle(migrations present:0000_wild_glorian.sql,0001_redundant_sauron.sql). Grep ofDockerfile,render.yaml,docker-compose.production.ymlformigrat|seed→ only a code-comment match; nostartCommand/CMD/entrypoint runsmigrate. A fresh Postgres (render-provisioned or compose) starts with no schema → team-server queries fail at runtime. - Fix: add a migrate step to the container entrypoint / render
startCommand(e.g.tsx packages/server/src/db/migrate.ts && <server start>).
B6 — render.yaml provisions Postgres+Redis but runs the local SQLite sidecar entrypoint (infra mismatch + CORS fail-closed gap)
- Owner type: decision (which deployment target?) then code
- Evidence:
render.yaml:17startCommand: npx tsx packages/server/src/local/start.ts --skip-litellm→ the desktop/SQLite single-user sidecar, not the team Postgres server (packages/server/src/index.ts, what the DockerfileCMDruns). render injects/provisions managed Postgres+Redis (render.yaml:32-40) that the chosen entrypoint largely bypasses; team features (Clerk-gated, Postgres-backed) are not actually served. Separately,config.ts:17-35throws'CORS_ORIGIN ... required in production'whenNODE_ENV=production(set inrender.yaml:21) and unset — and render.yaml defines noCORS_ORIGIN(docker-compose.production.yml correctly enforces it at:47), so the team-server path would crash on boot. - Fix: decide the render target. If it is the team server, switch
startCommandto the Postgres entrypoint, addCORS_ORIGIN, and wire migrate (B5). If render is meant to host the local sidecar demo, drop the managed Postgres/Redis to stop paying for bypassed infra.
3. E2E Prerequisite Status
The E2E vision harness depends on npm run build (apps/web → /dist on :3333) succeeding so the Playwright webServer can boot.
- Local status: GREEN.
npm run build(cd apps/web && tsc --noEmit -p tsconfig.app.json && vite build --outDir ../../dist --emptyOutDir) exits 0;dist/index.htmlis freshly written (Jun 1 17:00).apps/webimports only@waggle/shared(grep: 4 hits, zero@waggle/hive-mind-core— the only hive-mind references are comments inLauncherApp.tsx), and@waggle/shared/distexists, so the apps/web build itself is not blocked by B1. - CI status: the e2e job's
npm run buildis currently UNREACHABLE because the step before it —npm run build:packages(ci.yml:66) — fails at B1 (TS2307). So in CI today, the frontend never builds and Playwright never runs (the job iscontinue-on-error, so this is silently masked). - Net: the E2E prerequisite is green on a machine with a pre-built
hive-mind-core/dist, but red on a clean checkout / in CI until B1 is fixed. The handoff's "e2e frontend build blocked" note is real for CI; it just localizes tobuild:packages(B1), not toapps/webtsc. - Exact fix: apply B1 (build
hive-mind-corefirst inbuild:packages). After that, the e2e job reachesnpm run build(already green) and Playwright can boot the :3333 server. No change toapps/webtsconfig is needed.
4. Non-Blocking Residuals
Open-work items (all code-complete + test-green; remaining work is platform/binary-blocked or doc-only):
- OQ-4 hermes compact-on-stop — DONE.
compact-on-stop.ts(opt-inWAGGLE_HERMES_COMPACT_ON_STOP, time-gated, save-first + fail-open); 26/26 tests, package tsc exit 0. - §10 #3 Wave 2/3 hooks — DONE, but CLAUDE.md prose is STALE. codex/cursor/hermes/openclaw (+codex-desktop re-export) are real implementations with full adapter/install/uninstall/verify trees; 203/203 tests. Only
claude-desktopremainsexport {}— a deliberate MCP-only deferral (pinned bytests/placeholder-audit.test.tsEXPECTED_MARKER_COUNT=1). Doc fix (non-code): CLAUDE.md §10 #3 (line 516) still lists all 6 packages as stubs — update to reflect only claude-desktop remains. - §10 #1 Spawn-Agent P36 + P35 model fallback — DONE in code (
Dock.tsx/Desktop.tsxwiring;SpawnAgentDialog.tsx3-tier LiteLLM→runtime→provider-catalog fallback, commit14942be). Residual: runtime verify on a clean Tauri install (platform-blocked). - §10 #2 light-mode finish — DONE structurally (semantic-token migration complete; the 5
hive-950hits are legit token defs/usages, no literal-color rot). Residual: BootScreen + header visual polish needs a binary to eyeball (validation-blocked). - OQ-5 OpenClaw live-install — genuinely platform-blocked. Code path implemented + tested in tmp dirs (15 tests incl. fail-open); needs a real OpenClaw gateway to verify installed-handler dep resolution. Does not block a claude-code-first Waggle launch.
CI / test-infra follow-ups (do not block launch, but should be tracked):
- CI e2e job is
continue-on-error: true— it cannot fail the pipeline. After B1, consider flipping it to blocking so a broken frontend build surfaces. - No Docker-infra CI lane. Zero workflows declare
services: postgresor runtest:infra; Postgres/Redis/MinIO/S3 code paths are unverified by CI.docker-compose.ymlprovides the infra locally but CI never spins it up. - Dead/misleading test config:
apps/web/playwright.config.tsimports the uninstalledlovable-agent-playwright-config(would throw on load; apps/web has no specs) — delete it.playwright-e2e.config.ts(thetest:e2elane) has nowebServer— it silently times out unless a server is pre-started on :3333; document or add a webServer block. - Committed test cruft:
tests/visual/r2-uat-mega.spec.ts:3has a dead hardcoded 64-hex token (rotate if it was ever real);tests/login-flow.spec.tstargets the wrong port (:8083) with a stale Clerk flow — fix or delete. - Build polish (cosmetic): vite warns on
@importorder + a 1.74 MB JS chunk (>500 kB advisory). Non-fatal.
Benchmark arcs (out of launch scope): C-3 full GAIA-2 Phase 4 (needs Docker + ARE + new adapter strategy; budget recalibrate pending). LoCoMo v5 trio-strict re-judge (~$30, ~2h) is the only remaining step on C-1.
5. The Vision-E2E Harness Plan
Design doc: docs/audits/2026-06-01-vision-e2e-harness-design.md
Recommended architecture — Option C (Hybrid). Playwright deterministically drives and captures every surface (×dark/light) plus the 7 flows, emitting a PNG + sidecar JSON per capture enriched with objective signals (console errors via page.on('console'), failed network requests, and a Lighthouse contrast/a11y audit on heavy views). A multi-agent Workflow fans out one vision-judge subagent per capture to grade meaning against a 5-dimension rubric (renders_correctly, no_error_state, flow_completes, theme_legible, plus the objective no_console_errors). A reducer cross-checks vision vs objective signals — a vision-PASS carrying a real console error or a Lighthouse fail is downgraded to FAIL — and writes one report. This buys A's deterministic, replayable navigation plus a deterministic objective floor so a plausible-looking-but-broken screenshot can't fool the gate (defense in depth). Build on the existing tests/visual + tests/e2e helpers and the root playwright.config.ts webServer block (:3333, reuseExistingServer, WAGGLE_TRUST_LOCALHOST=1) — not greenfield. (Rejected: Option A lacks the objective floor; Option B's live agentic drive is non-deterministic → a flaky CI gate.)
Scope. ~19 surfaces (7 core views: chat/memory/events/capabilities/cockpit/mission-control/settings; plus room/agents/files/approvals/vault/connectors/marketplace/timeline/backup/telemetry/governance/dashboard; plus overlays: onboarding, Ctrl+K search, spawn-agent, persona switcher, shortcuts help, upgrade modal) × dark + light themes, plus 7 end-state-graded flows (onboarding, chat round-trip, memory browse, spawn agent, persona switch, marketplace, settings tabs). Total ≈ 52 vision judgments/run. Deterministic entry via /?skipOnboarding=true&tier=power; light theme via data-theme='light' on <html> (the old views.spec.ts dark/light-class toggle is stale and must not be the model). FAIL on any vision dimension at confidence ≥0.7 or any hard signal; WARN at 0.4–0.7 (routes to human, never auto-blocks CI).
Coverage gap this fills: today exactly ONE spec (tests/visual/views.spec.ts) does true pixel-diff (drift-only, brittle), three specs capture screenshots but assert nothing about their content, and zero tests semantically judge "does it actually look and work right." A visually-broken-but-DOM-present screen passes the current suite. The vision harness is net-new.
The one key decision (needs the user's call): Does the Chat round-trip flow grade against a REAL LLM reply or a gracefully-handled degraded state? Verified ground truth (service.ts:217-258): under the harness's own --skip-litellm server with no Anthropic key, /api/chat resolves the provider to health:'degraded' and returns NO assistant message.
- Path 1 (degraded, CI default): "completes" = user message renders + send works + missing-LLM state handled gracefully (clear "configure API key" prompt, not a blank window/stack trace). Deterministic, free, CI-safe — but does not verify a real answer.
- Path 2 (real LLM, opt-in
--live-llm): inject a real key so chat returns an actual reply and vision grades a coherent assistant message. Highest fidelity, but non-deterministic, costs money, and the CI gate must hold a secret. - Recommended: Path 1 as the CI gate, Path 2 as an opt-in pre-release lane. (Secondary, can default: run target = local Chromium against built
apps/webon :3333.)
6. Recommended Sequence
- Fix B1 (the root cause). Prepend
cd packages/hive-mind-core && npx tsc --build &&tobuild:packages. Verified: the full corrected chain exits 0 from a clean dist. This un-blocks CI e2e, both Tauri verifies,release.yml, andbuild:all. (code — ~5 min) - Re-run CI + Tauri verify on the B1 commit. Confirm e2e's
build:packages→npm run buildnow reaches Playwright, and that both Tauri verifies now progress pastBuild packagesinto the Rust/Vite/sidecar stages (and pass, or surface the real next failure). (verification) - Flip the CI e2e job to blocking (drop
continue-on-error) once it's green, so a broken frontend build can never again hide behind a green checkmark. (decision + code) - Fix the deploy artifacts (B3–B6) for whichever target ships first:
- Dockerfile: drop
packages/uiCOPYs, copyapps/+hive-mind-*, build packages beforenpm run build. - render.yaml: build via root
build:all, setWAGGLE_FRONTEND_DIR=./dist, addCORS_ORIGIN, decide local-sidecar vs team-Postgres entrypoint. - Add the drizzle
migrate.tsstep to the chosen entrypoint. (code + one decision)
- Dockerfile: drop
- Decide the vision-harness chat-flow path (Path 1 CI gate + Path 2 opt-in lane — §5). (decision — blocks the harness build)
- Build the Option-C vision harness on the existing :3333 webServer + tests/e2e helpers; extract the copy-pasted nav helpers (
gotoDesktop/skipOnboarding/dismissOverlay/openAppViaDock) intotests/e2e/_helpers.ts; delete the deadapps/web/playwright.config.tsand fix/removelogin-flow.spec.ts+ the dead token inr2-uat-mega.spec.ts. (code — ~3 sessions) - Run the vision harness against the local web build, triage WARN/FAIL, then close the binary-blocked residuals (§10 #1 spawn-agent clean-install, §10 #2 light-mode polish) on a real Tauri build. (verification — platform-blocked steps last)
- Doc cleanup: update CLAUDE.md §10 #3 to reflect only
claude-desktopremains a (deliberate) stub. (doc)
Synthesized 2026-06-01 from 5 parallel auditors; every red claim independently re-verified against the live repo (839d4ce) and the GitHub Actions API.