Replace better-sqlite3 with pg Pool for all operational data (chats,
messages, tasks, sessions, router_state, registered_groups). New
OPS_DB_URL config drives a dedicated ops database alongside the
existing memory and skills databases.
All db.ts functions are now async. Callers in src/, setup/, and tests
updated accordingly. Tests use a mock pool (src/test-helpers.ts) so
they run without a live Postgres connection.
---
Build: pass | Tests: not run (Linux)
Mirrors Paperclip's per-adapter ensureCommandResolvable pattern as a single
fail-fast gate at the top of `setup onboard`. Probes {claude, codex, gemini,
pi} via commandExists; throws NoAgentCliError if none resolve. Also surfaces
all four in `setup verify` alongside the existing CODEX check.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: FAIL — Tests 1 failed | 846 passed (847)
Default worker jail had only rsync/cage/chromium. Provisioning scripts
that use heredocs or bash-isms via 'bastille cmd <jail>' failed because
root's login shell was sh. Also missing node/npm/git made the jail
useless as a sandbox for the agent runtime.
- worker-jail.txt: add bash, git, node24, npm-node24
- setup/jails.ts: chsh -s /usr/local/bin/bash root after pkg install
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: FAIL — Tests 1 failed | 846 passed (847)
- Run setup/controlplane.ts against live PostgreSQL — creates schema,
4 agents, operator account, budgets, skills snapshot. Stops the
heartbeat loop's "relation 'agents' does not exist" errors.
- setup/controlplane.ts: write a real logs/setup.log (was a dead label),
scrub OPERATOR_PASSWORD from emitStatus payload, add "do not tee"
warning next to the one stdout password print on first install.
Password still lives only in .env (mode 0600) + one-shot terminal output.
Co-Authored-By: Sam, Clawdie & Claude
---
Build: pass | Tests: pass — Tests 847 passed (847)
- Add permissions.sql with GRANT + ALTER DEFAULT PRIVILEGES
- Add fix-permissions.sh for quick repair on existing databases
- Add POSTGRES-PERMISSIONS.md documentation
- Update setup-db-jail.sh to run permissions.sql after migrations
- Update skills-memory.ts to apply permissions after artifact import
Fixes: permission denied for table memories
New setup/skills-init.ts step creates .nanoclaw/ base snapshot during
npm run install-all. Registered in setup/index.ts and install.ts
(step 10/20, after skills-memory, before cms). Idempotent — skips
if already initialized, --force to reinit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 603 passed (603)
Add a setup helper to enable tailscale inside jails when FEATURE_TAILSCALE
and an auth key are present, prefetch tailscale packages, and document
the installer shortcut.
---
Build: FAIL — not run
Tests: FAIL — not run
Adds setup/cms.ts that bootstraps the CMS jail: installs packages,
scaffolds Astro project from templates, builds static site, deploys
to /srv/www, and configures nginx. Also adds CMS config exports
(CMS_JAIL_IP, CMS_WEBROOT, ASTRO_SITE_PATH) and fixes
loadAllPackageLists to include forgejo-jail.txt and cnc-jail.txt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 605 passed (605)
New setup/forgejo.ts installs Forgejo in the existing git jail, gated
by FEATURE_GITEA=YES or CODE_HOSTING_MODE=gitea. Uses SQLite, runs on
port 3000, generates app.ini with sane defaults (registration disabled,
offline mode, no actions). Wired into install-all and verify.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 605 passed (605)
Onboarding was writing WARDEN_GIT_IP=.4 and WARDEN_OLLAMA_IP=.6 —
reversed from the canonical Ansible/live scheme (.6=git, .5=ollama).
Also fix git.ts feature gate to skip on either FEATURE_GIT=false OR
CODE_HOSTING_MODE=external (was requiring both).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 605 passed (605)
New setup/git.ts provisions a Bastille git jail as local Codeberg
fallback. Mirrors from REMOTE_GIT_URL with graceful fallback to empty
bare repo when remote is unreachable. Fully idempotent.
Fix IP scheme: .4=cms, .5=ollama, .6=git (was .4=git, .5=cms,
.6=ollama in config.ts and local-hosts.ts — now matches Ansible).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 605 passed (605)
Doctor checks runtime health (message loop, watchdog, skills DB) which
are expected to be offline on a fresh bhyve guest before the agent starts.
Mark it softFail so preflight reports 'warning' instead of blocking the
overall status. Install-readiness steps still hard-fail as before.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 605 passed (605)
- Evidence script and checklist looked in logs/preflight-* but preflight
writes to tmp/preflight/ — fixed both to match actual output path
- Checklist referenced npm run preflight (missing) — corrected to
preflight-check
- preflight.ts screenshot capture had hardcoded 'clawdie' session —
now uses AGENT_NAME
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 605 passed (605)
applyHostLocale() was writing whatever charset was detected on the host
(including ISO8859-2) verbatim into ~/.login_conf, silently breaking
Slovenian character rendering on next login.
- Always strip the charset suffix from the detected locale tag and
rewrite it as <base>.UTF-8 — sl_SI.ISO8859-2 → sl_SI.UTF-8
- charset field is always written as UTF-8
- Replace both 'tmux kill-server && tmux' suggestions with instruction
to open a new tmux window or fresh SSH login
- Add UTF-8 compliance section to AGENTS.md documenting the rule,
normalisation table, and the cap_mkdb requirement
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 431 passed (431)
Dropped inferGender() heuristic. The installer now shows the current
.env value (or 'n') as default and requires explicit user selection.
No guessing from name endings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 431 passed (431)
src/agent-identity.ts (new): AgentIdentity resolves name, gender, locale
into pronoun/possessive/title/selfIntro. FORMS map supports sl (full
gendered grammar: asistentka/asistent, ona/on) and en (neutral fallback).
resolveAgentIdentity() exported for onboarding preview before .env write.
src/config.ts: AgentGender type ('m'|'f'|'n'), AGENT_GENDER export.
Accepts 'ž' as alias for 'f' (Slovenian natural input).
src/agent-runner.ts: AGENT_IDENTITY.selfIntro prepended to every pi
system prompt — agent always knows who it is grammatically.
setup/onboarding.ts: gender question after assistant name in both
bsddialog (menu with live preview per gender) and TTY (prompt + preview
line) paths. inferGender() suggests female for names ending in 'a'.
Confirmation screen shows full identity preview. AGENT_GENDER written
to .env.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 431 passed (431)