Skip to content

Claude/review project brief r6 p xw#4

Merged
NazmulGit merged 2 commits into
mainfrom
claude/review-project-brief-R6PXw
Apr 27, 2026
Merged

Claude/review project brief r6 p xw#4
NazmulGit merged 2 commits into
mainfrom
claude/review-project-brief-R6PXw

Conversation

@NazmulGit
Copy link
Copy Markdown
Owner

No description provided.

claude added 2 commits April 26, 2026 12:33
bin/clawcontrol.js (530 lines, replaces the Phase 1 stub)
  • Node >= 18 gate; ASCII banner; tiny ANSI colorize that respects
    NO_COLOR and non-TTY pipes.
  • Interactive onboarding wizard via @inquirer/prompts when
    ~/.clawcontrol/config.json is absent:
      gateway URL (auto-detects ws://localhost:3002 if `openclaw` is on
      PATH or ~/.openclaw exists) · admin password (optional; argon2id
      via @node-rs/argon2 stored as authPasswordHash; bearer authToken
      generated independently and printed once) · backup storage
      (Local / S3 with bucket+region+keys captured to a separate 0600
      s3-credentials.json / Disabled) · default LLM provider (anthropic
      / openai / gemini / openrouter / ollama / skip) · API key
      collected once and persisted to ~/.clawcontrol/pending-keys.json
      0600, the server picks it up on first boot · 32-byte master
      secret.key (0600).
  • All subcommands from the brief:
      start    detached spawn of packages/server/dist/index.js, write
               PID file, wait up to 15s on /api/health, open browser
               (suppressed by CLAWCONTROL_NO_OPEN=1)
      stop     SIGTERM with 8s grace then SIGKILL
      status   read PID + check alive + GET /api/health
      backup   POST /api/backups (manual), print path
      doctor   GET /api/doctor, colored PASS/WARN/FAIL table, exits
               non-zero on any FAIL — CI-friendly
      update   GET /check + confirm + POST /install
      reset    delete config.json (keep DB, secrets, backups)
      reset --hard   rm -rf ~/.clawcontrol/
      export <p>     tar -czf, excluding PID + server.log
      import <p>     tar -xzf with overwrite confirm
      logs           tail -F server.log
      --version / --help
  • Resolves the server bundle via repo path → node_modules fallback so
    the same script works in dev, after npm install, and inside Docker.
  • Top-level error handler treats @InQuirer ExitPromptError (Ctrl+C) as
    exit 130 instead of a stack trace.

install.sh
  • Detects macOS / Linux / WSL / Windows-shell / unknown.
  • Verifies node >= 20; auto-installs via nvm if available, Homebrew
    on macOS, or surfaces clear platform-specific guidance otherwise.
  • Honors CLAWCONTROL_PACKAGE override and --no-start flag.
  • Falls through to sudo only when npm prefix isn't writable and
    we're not already root.

Dockerfile (multi-stage)
  • deps  — pnpm install with the build toolchain present so
            better-sqlite3 + @node-rs/argon2 native fallbacks work on
            arm64 Alpine.
  • build — pnpm build (esbuild server + vite UI).
  • runtime — slim image with tini for proper signal handling, only
              the bundles + their runtime node_modules + bin/.
              CLAWCONTROL_NO_OPEN=1 so the entrypoint doesn't try to
              spawn a browser inside the container.

docker-compose.yml
  • Default profile boots only clawcontrol with a persistent volume
    and an /api/health healthcheck.
  • Optional profiles: `--profile ollama` (ollama/ollama at :11434) and
    `--profile openclaw` (overridable via CLAWCONTROL_OPENCLAW_IMAGE)
    each with their own volume.

Publish metadata
  • Root package.json: bin entry retained, files allow-list for
    bin/, packages/{server,ui}/dist + their package.json, install.sh,
    README.md, LICENSE; publishConfig: {"access":"public"};
    prepublishOnly runs pnpm build; license MIT; repository + keywords
    populated.
  • .npmignore strips src/, lockfiles, design/, PROJECT_BRIEF.md,
    *.tsbuildinfo so the tarball is just the bundles + CLI.
  • Note: the npm name `clawcontrol` is already taken on the public
    registry by an unrelated package (v0.2.4 at the time of writing).
    Final publish will use a scoped name (e.g. @clawcontrol/cli) —
    install.sh respects $CLAWCONTROL_PACKAGE for that override.

Bug fix in packages/server/build.mjs
  • The esbuild ESM bundle imploded at runtime because node-cron
    references `__dirname` to locate its daemon.js, and ESM modules
    don't get __dirname/__filename for free. Added them (+ require)
    to the banner so the bundled output runs as a plain `node bundle.js`.

Verified:
  • node bin/clawcontrol.js --help / --version / status / unknown-cmd
    all behave correctly with no server running.
  • CLAWCONTROL_NO_OPEN=1 node bin/clawcontrol.js start now boots the
    bundled server, waits on /api/health, prints "ClawControl is up".
  • status, backup (12.6 KB tar.gz on disk), doctor (4 pass / 3 warn /
    3 fail with colored output), stop (graceful SIGTERM), export
    (tar.gz containing config.json + secret.key + db + backups dir,
    PID/log excluded), reset (confirmation prompt fires) — all
    round-trip cleanly against a freshly-built bundle.
UX polish
  • ToastBus subscribes to /ws and emits the brief's exact taxonomy:
      green: agent started · task done · backup completed ·
             update installed · OpenClaw recovered
      amber: budget at 80% · OpenClaw reconnecting
      red:   budget limit hit · Doctor critical · OpenClaw crashed ·
             backup failed · update failed
    Stable toast IDs mean repeat events dedupe rather than stack.
  • ShortcutsProvider — keyboard surfaces wired at the layout level:
      Cmd/Ctrl + K   fuzzy palette across agents/tasks/goals/nav/actions
                     (label + hint substring scoring, top 30 hits)
      Cmd/Ctrl + D   /doctor
      Cmd/Ctrl + B   POST /api/backups (loading toast, then result)
      Cmd/Ctrl + /   keyboard reference modal
      G then A/M/O   chord with 1.2s window → /agents · /mission-board
                     · /org-chart. Skipped while typing in inputs.
      Esc closes any overlay.
  • MobileTabBar: at <768px the sidebar hides and a 5-tab bottom bar
    (Dash · Agents · Board · Doctor · Settings) takes over with proper
    safe-area-inset-bottom respect. Full nav surface still reachable
    via Cmd+K.
  • Layout.tsx wraps Outlet in the existing per-section ErrorBoundary
    so a render crash in one page never takes down the rest of the app.

Documentation
  • README.md  — quickstart for npm + Docker + source, full CLI
                 reference, "vs Paperclip" comparison table, config
                 example, layout, requirements.
  • CONTRIBUTING.md — adapter-pattern walkthrough (worked example:
                 adding Mistral in one file), Doctor check guide
                 (with the load-bearing "no openclaw-client" rule
                 spelled out), route-add recipe, code style.
  • docs/architecture.md — four-layer ASCII diagram, process
                 boundaries, the typed WS EventMap quoted in full,
                 schema versioning notes, build outputs.
  • docs/doctor-checks.md — table for every check (signals + pass/
                 warn/fail rules + auto-fix) plus the rationale for
                 keeping Doctor out-of-process.
  • CHANGELOG.md — phase-by-phase release history.
  • LICENSE — MIT.

Server tests (vitest + supertest, 28 passing)
  • encryption.test.ts (5)        — AES-256-GCM roundtrip with
                                    multi-byte payloads, IV randomness,
                                    GCM tamper detection, malformed
                                    ciphertext, secret.key 0600 perms.
  • agents.test.ts (6)            — list/get/create+validation/
                                    pause+resume+restart audit chain/
                                    clone/delete (with FK SET NULL
                                    behaviour for audit_log).
  • budget.test.ts (3)            — auto-pause when spent >= budget,
                                    audit row asserted, override+resume
                                    lifts back to idle, summary
                                    projection numerics.
  • doctor.test.ts (7)            — runs all 10 checks offline,
                                    process+gateway FAIL with fix
                                    metadata, summary counters, run
                                    history persists, single-check
                                    route + 404, /fix/:check 400 when
                                    no auto-fix is registered.
  • backup.test.ts (3)            — tar.gz on disk + non-zero size,
                                    delete removes both row and file,
                                    restore round-trip completes with
                                    schema_version validation.
  • anthropic-adapter.test.ts (4) — listModels has the brief's set,
                                    estimateCostCents matches the
                                    static table exactly (opus 4-6:
                                    $90 for 1M+1M; sonnet 100k/50k =
                                    105¢; unknown model = 0), test-
                                    Connection ok=true on success and
                                    ok=false WITHOUT throwing on SDK
                                    failure (mocked SDK).
  Each test file gets a fresh tmp DB via tests/_helpers.ts; no live
  network calls.

UI tests (vitest + RTL + jsdom, 15 passing)
  • ErrorBoundary.test.tsx (3)         — catches a render error and
                                          surfaces Retry; renders
                                          children when nothing throws;
                                          Retry recovers when the
                                          underlying child stops
                                          throwing.
  • primitives.test.tsx (6)             — Card / Button / Chip /
                                          Avatar (initials) /
                                          StatusDot / ProgressBar
                                          (clamped at 100%) /
                                          ProgressRing label /
                                          Skeleton / EmptyState /
                                          ErrorPanel.
  • sections.test.tsx (4)               — Dashboard, Agents, Doctor,
                                          and Heartbeats render with
                                          mocked hook data; mocks the
                                          hooks barrel + websocket
                                          module so no fetch fires.
  • websocket-reconnect.test.tsx (2)    — typed event dispatch +
                                          connection state stream,
                                          plus exponential backoff
                                          (500ms → 1s → 2s timer
                                          ladder verified with fake
                                          timers).

GitHub Actions
  • .github/workflows/ci.yml — typecheck + sequential pnpm test on
    Node 20 and 22 for every push/PR; production build + bundle smoke
    + artifact upload on push to main only.
  • .github/workflows/release.yml — on tag v*: typecheck + test gate,
    pnpm build, npm publish (NPM_TOKEN), Docker buildx multi-arch push
    to Docker Hub when DOCKERHUB_USERNAME/TOKEN are present, GitHub
    Release with auto-generated notes and install.sh attached.

Bug fix surfaced in the encryption suite: the original "ciphertext
doesn't include plaintext" assertion used a single-character sample
that occasionally appeared in random base64 output and flaked the
suite ~5% of runs. Test inputs now have enough entropy to make
collisions vanishingly unlikely.

Verified end-to-end:
  pnpm typecheck   → clean (server + ui)
  pnpm test        → 28 server + 15 ui = 43 passing, sequential
  pnpm build       → server bundle 2.4 MB · ui 90.3 KB gzipped JS
@NazmulGit NazmulGit merged commit 366283c into main Apr 27, 2026
1 of 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