Skip to content

Demo dataset is now opt-in — fresh installs ship empty#9

Merged
NazmulGit merged 4 commits into
mainfrom
claude/review-project-brief-R6PXw
May 4, 2026
Merged

Demo dataset is now opt-in — fresh installs ship empty#9
NazmulGit merged 4 commits into
mainfrom
claude/review-project-brief-R6PXw

Conversation

@NazmulGit
Copy link
Copy Markdown
Owner

Up through Phase 9 the dev seed ran on every server start in non-production mode and the CLI didn't set NODE_ENV, so every clawcontrol-start ended with the Nova SaaS Co fixtures loaded. That's wrong for users — production deployments shouldn't auto-populate fictional org / agents / tasks / goals.

Fix:
• bin/clawcontrol.js sets NODE_ENV=production when spawning the
bundled server (unless the caller has already set it). Cold
installs land on an empty dashboard. Contributors running via
pnpm start / tsx watch still get the auto-seed.
• packages/server/src/db/seed.ts gains clearDemo() and hasDemo().
SEED_IDS is the canonical list of stable IDs the seed inserts;
clearDemo deletes only those rows, so user-created data is
preserved. Counts the rows present before deletion to give an
honest report (some FKs cascade — direct DELETE.changes
under-counts).
• packages/server/src/routes/system.ts:
GET /api/system/info demo_loaded + per-table counts
POST /api/system/load-demo idempotent (already_loaded:true on
second call)
POST /api/system/clear-demo idempotent inverse
• bin/clawcontrol.js gains the demo subcommand:
clawcontrol demo load
clawcontrol demo --clear remove
clawcontrol demo --status loaded? + counts table
• Settings page gets a Demo dataset card with per-table count
chips, Load demo data button (disabled when already loaded), and
Clear demo with confirmation.
• api-client gets api.system.{info,loadDemo,clearDemo}.

Tests:
packages/server/tests/system.test.ts (6 cases) covers the full
lifecycle: empty DB info → load → counts match the brief
(1 org / 7 agents / 15 goals / 10 tasks / etc.) → second load is a
no-op → clear removes only seed IDs → user-created agent survives a
clear → clear on empty DB is a no-op.

Docs:
USER_GUIDE.md gains a "10. Demo dataset" section, the CLI reference
table picks up demo / --status / --clear, the table of contents is
renumbered. README's quickstart calls out that fresh installs are
empty and how to opt in.

Verified end-to-end on a cold ~/.clawcontrol/:
• clawcontrol start → empty dashboard, /api/agents = []
• clawcontrol demo --status → "not loaded", all counts 0
• clawcontrol demo → "demo dataset loaded"
• /api/agents → 7 agents
• clawcontrol demo (again) → "already loaded"
• clawcontrol demo --clear → "removed 70 demo rows" (correct
sum across 9 tables)
• /api/agents → []

Tests: 34 server (was 28) + 15 UI = 49 passing. Typecheck clean.

claude and others added 4 commits April 28, 2026 10:54
Up through Phase 9 the dev seed ran on every server start in
non-production mode and the CLI didn't set NODE_ENV, so every
clawcontrol-start ended with the Nova SaaS Co fixtures loaded. That's
wrong for users — production deployments shouldn't auto-populate
fictional org / agents / tasks / goals.

Fix:
  • bin/clawcontrol.js sets NODE_ENV=production when spawning the
    bundled server (unless the caller has already set it). Cold
    installs land on an empty dashboard. Contributors running via
    `pnpm start` / tsx watch still get the auto-seed.
  • packages/server/src/db/seed.ts gains clearDemo() and hasDemo().
    SEED_IDS is the canonical list of stable IDs the seed inserts;
    clearDemo deletes only those rows, so user-created data is
    preserved. Counts the rows present *before* deletion to give an
    honest report (some FKs cascade — direct DELETE.changes
    under-counts).
  • packages/server/src/routes/system.ts:
      GET  /api/system/info        demo_loaded + per-table counts
      POST /api/system/load-demo   idempotent (already_loaded:true on
                                   second call)
      POST /api/system/clear-demo  idempotent inverse
  • bin/clawcontrol.js gains the demo subcommand:
      clawcontrol demo            load
      clawcontrol demo --clear    remove
      clawcontrol demo --status   loaded? + counts table
  • Settings page gets a Demo dataset card with per-table count
    chips, Load demo data button (disabled when already loaded), and
    Clear demo with confirmation.
  • api-client gets api.system.{info,loadDemo,clearDemo}.

Tests:
  packages/server/tests/system.test.ts (6 cases) covers the full
  lifecycle: empty DB info → load → counts match the brief
  (1 org / 7 agents / 15 goals / 10 tasks / etc.) → second load is a
  no-op → clear removes only seed IDs → user-created agent survives a
  clear → clear on empty DB is a no-op.

Docs:
  USER_GUIDE.md gains a "10. Demo dataset" section, the CLI reference
  table picks up demo / --status / --clear, the table of contents is
  renumbered. README's quickstart calls out that fresh installs are
  empty and how to opt in.

Verified end-to-end on a cold ~/.clawcontrol/:
  • clawcontrol start                → empty dashboard, /api/agents = []
  • clawcontrol demo --status        → "not loaded", all counts 0
  • clawcontrol demo                 → "demo dataset loaded"
  • /api/agents                      → 7 agents
  • clawcontrol demo (again)         → "already loaded"
  • clawcontrol demo --clear         → "removed 70 demo rows" (correct
                                       sum across 9 tables)
  • /api/agents                      → []

Tests: 34 server (was 28) + 15 UI = 49 passing. Typecheck clean.
Addresses four asks: a setup guide on first install, a properly
configurable OpenClaw gateway, agents that stay in sync with OpenClaw,
and a gateway that can re-establish on demand.

Schema
  Migration v3 adds agents.sync_status ('pending' | 'synced' | 'failed'),
  last_synced_at, sync_error. Existing rows default to 'pending' so
  every agent gets pushed to OpenClaw on the next reconnect.

OpenClaw client
  • reconnectNow(newUrl?) resets the backoff counter and triggers an
    immediate connect — exposed for the UI's "Reconnect now" button and
    the gateway-URL change endpoint.
  • setUrl(url) hot-swaps the gateway URL without a server restart.
  • syncAgent(agent) and deleteAgent(id) push agent definitions over
    the WS — the missing inverse of the existing inbound agent.* events.
  • Closing a CONNECTING socket no longer leaks an unhandled 'error'
    event (previously crashed the server when a PATCH triggered an
    immediate reconnect — caught during the cold-boot smoke).

Agent ↔ OpenClaw sync (openclaw/agent-sync.ts)
  Single chokepoint. The agents route calls pushAgent(id) after every
  create / update / clone and pushAgentDeletion(id) on delete. The
  helper marks the row 'synced' on success, 'pending' (with a reason in
  sync_error) when OpenClaw is offline, 'failed' when the push raised.
  startAutoSync() subscribes to openclaw-client state changes and runs
  syncAllPending() the moment the gateway flips to 'connected'.

System endpoints (routes/system.ts)
  GET    /api/system/openclaw-config       — current + live URL + state
  PATCH  /api/system/openclaw-config       — write config.json + reconnect
  POST   /api/system/openclaw-reconnect    — kick the client now
  POST   /api/system/sync-all              — re-push pending/failed agents
  GET    /api/system/onboarding            — { completed, completed_at }
  POST   /api/system/onboarding/complete   — flip the flag in system_config
  DELETE /api/system/onboarding            — clear the flag (re-run wizard)
  POST   /api/agents/:id/sync              — manual single-agent push

UI surfaces
  • OfflineBanner gains a "Reconnect now" button alongside Run Doctor.
  • Settings → "OpenClaw gateway" card: editable URL, live state chip,
    Save & reconnect, Reconnect now, Re-sync agents. Drift indicator
    when the live URL has diverged from config.
  • New /welcome page (4 steps: hello → connect to OpenClaw with live
    test → choose starting state [demo / first agent / skip] → done).
    Layout checks /api/system/onboarding on mount and redirects to
    /welcome the first time. Fail-open if the probe errors so a flaky
    server never wedges the user out.

Bug fixes
  • Both the openclaw-client and the Doctor's gateway probe used to
    leak a "WebSocket was closed before the connection was established"
    error after closing a CONNECTING socket — Node treated it as
    unhandled because removeAllListeners() ran first. Now we install a
    no-op error handler before close().
  • backup-service path drift fix from the previous commit confirmed
    against the new test setup.

Tests (44 passing, was 34)
  packages/server/tests/sync-onboarding.test.ts (9 cases) covers the
  new endpoints: openclaw-config GET / PATCH (with URL-scheme
  validation), reconnect, sync-all on empty + after agent create
  (verifies sync_status 'pending' when OpenClaw is offline), manual
  /agents/:id/sync, onboarding flag lifecycle (start uncompleted,
  POST flips, DELETE clears).

  Test harness now installs a real openclaw-client per test (pointed at
  a random unused port so reconnect attempts no-op safely) and
  resets the singleton in cleanup.

Docs
  USER_GUIDE.md: §2 split into "CLI wizard" + "In-app onboarding" with
  the 4-step UI walkthrough and the curl recipe for re-running it.
  §3 picks up "Settings → OpenClaw gateway" with the three new buttons
  and the agent sync_status semantics.

Verified end-to-end on a fresh ~/.clawcontrol/:
  • clawcontrol start → server up, dashboard redirects to /welcome.
  • /api/system/onboarding              → { completed: false }
  • /api/system/openclaw-config         → live state + URL
  • PATCH gateway URL                   → saves + reconnects (no crash)
  • POST openclaw-reconnect             → state: connecting
  • POST sync-all on empty DB           → 0/0/0
  • Create agent                        → sync_status: pending,
                                          sync_error: "OpenClaw offline
                                          — queued for reconnect"
  • POST onboarding/complete            → next refresh lands on /
Resolved conflicts by keeping PR's content (main was reverted via PR #7).
Preserves full implementation: README, CLI, tests, docs, LICENSE, CI workflows.
pnpm/action-setup@v4 now rejects having both 'version: 9' and
the package.json 'packageManager' field. Use packageManager only.
@NazmulGit NazmulGit merged commit a12e036 into main May 4, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants