Lands task 4 from the ISO first-boot implementation split as a
standalone scripts/set-operator.ts (matches existing scripts/
convention — no clawdie-admin umbrella). Reuses
ensureControlplaneBootstrapOperator() for the Better Auth signUp
path. Prompts password via stdin with echo suppressed; refuses
non-TTY runs; updates OPERATOR_PASSWORD in .env (mode 0600).
First-set only — rotation goes through the dashboard.
Both planning docs updated to drop "notional" references and point
at the real npm run set-operator -- <email> command.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---
Build: pass | Tests: FAIL — Tests 3 failed | 1972 passed (1975)
zAI — the Agent Identity fix in 8138173 is fragile as it stands. On
shared-Linux setups, `user.name` lives in `.git/config` per-clone, so
whichever agent set it most recently wins until the next reset. "Each
agent remembers to re-run `git config user.name`" is exactly the kind
of verbal invariant that silently breaks: one forgotten command and the
next ten commits land under the wrong author, with no warning.
The pre-commit guard I added in 8bafe79 was dormant (opt-in via
`npm run install-hooks`), which preserves the same failure mode for any
agent who skips the manual step. This commit removes that foot-gun:
- package.json gains a `prepare` script that sets
`core.hooksPath=hooks` on every `npm install`. npm runs `prepare`
automatically, so the guard goes live on any fresh clone or dep
refresh — no agent has to opt in.
- The handoff section is re-worded to stop framing the pre-commit hook
as a "nice-to-have" and starts treating it as the actual mechanism.
The `git config user.name` step still matters, but it's now
enforceable: the hook rejects any commit whose author does not start
with `Operator & ` (legacy `Clawdie AI` still allowed).
Net effect: a forgotten `user.name` reset produces an immediate
commit-time error instead of a misattributed commit. Please run
`npm install` at the start of your next session so the guard is live
on your clone too.
---
Build: pass | Tests: pass — Tests 1812 passed (1812)
Adds setup/verify-agent-jails.ts which checks each agent jail's
.env.agent for:
1. Jail exists and is running (bastille list State=Up)
2. .env.agent file is present
3. Domain keys for the specialist are present (warns if missing)
4. No cross-contamination: keys belonging to OTHER specialists
are absent — exits with code 2 if any leaks detected
5. At most one LLM key (shared key) — warns if multiple found
Wire-up:
- setup/index.ts: added 'verify-agent-jails' step
- package.json: added 'verify-agent-jails' npm script
Tests: 23 new tests in setup/verify-agent-jails.test.ts covering
parseEnvKeys, jailIsRunning, and verifyJail for all three specialists
with pass/fail/leak scenarios.
Full suite: 70 files, 1185 tests passing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 1185 passed (1185)
Tools registered via ExtensionAPI.registerTool() (TypeBox schemas):
- jail_status: structured jail list from bastille-list (not raw text)
- system_health: composite — jails + ZFS + PF in one call
- skills_search: fuzzy search library.yaml, returns SKILL.md content inline
- skills_content: get full SKILL.md for a known skill id
- task_create: create controlplane task for specialist delegation
- task_status: check task status or list recent tasks
- hostd: privileged op passthrough (15 ops, safety rules apply)
Also adds @sinclair/typebox@0.34.49 (matches pi's bundled version) and a
tsconfig for the extension directory to resolve the global pi package.
Pre-existing type errors in original index.ts (ctx.ui) left untouched.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 942 passed (942)
---
Build: pass | Tests: FAIL — Tests 40 failed | 766 passed (806)
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)
- Remove 7 redundant .env vars: DB_NAME, DB_USER, DB_HOST, DB_PORT,
MEMORY_DB_NAME, MEMORY_DB_USER, MEMORY_DB_URL — all now derived from
AGENT_NAME by config.ts and common.sh
- Fix DB_HOST in common.sh pointing to .2 (controlplane) instead of .3 (db)
- common.sh: normalise AGENT_NAME → Postgres identifier, same algorithm
as db-identifiers.ts; embed config now reads from .env instead of
overriding with stale OpenRouter values
- embed.sh: drop OPENROUTER_API_KEY requirement; use EMBED_BASE_URL +
EMBED_API_KEY (empty = local llama-server, no auth needed)
- memory-hydrate-pg.sh, memory-lifecycle.ts: replace ai_brain/clawdie_brain
literals with live DB_NAME / MEMORY_DB_NAME values
Bump to 0.9.1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 431 passed (431)
Add npm run release script — creates an annotated git tag from package.json
version and pushes it to Codeberg. Fixes missing tags on Codeberg after
version bumps.
AGENTS.md: document release tagging rule — run only on minor/major bumps,
always confirm with user before tagging.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 414 passed | 10 skipped (424)
README Current Release updated to v0.8.0 Warden, simplified to version
line + changelog link so the pre-commit hook only needs to patch one line.
.githooks/pre-commit: reads version from package.json and patches README
on every commit. Run `npm run install-hooks` once per clone to activate.
Main site: "No subscription" → "No platform subscription" — accurate,
since real workflows require LLM API keys (provider cost, not ours).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- setup/install.ts: single-command orchestrator — 16 steps in order,
ZFS checkpoints at pf/jails/db/git/cms/verify, graceful LLM-absent
handling, --from resume, --dry-run, LLM provider summary at end
- setup/pi-config.ts: exit(1) only on missing pi binary; missing API
key is now a warning so install-all continues without an LLM key
- setup/index.ts: register install step (--step install)
- package.json: add "install-all" script (npm run install-all)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
Build: pass | Tests: pass — Tests 414 passed | 10 skipped (424)
Introduces a Watchdog that sits above GroupQueue and provides dynamic
resource control:
- Run modes: auto / slow / fast / permanent — each with preset
concurrency limits, idle timeouts, poll intervals, and memory
thresholds
- Memory throttle: reads vm.stats.vm.v_free_count via sysctl (fallback
to os.freemem) and drops max concurrency to 1 when free RAM falls
below mode threshold
- IPC socket at /tmp/<agent>-watchdog.sock — operator can query status
or switch mode without restarting the service
- GroupQueue.setMaxConcurrent() / getActiveCount() / getQueuedCount()
for runtime limit control
- Idle timeout and poll interval read dynamically from watchdog; -1 in
permanent mode suppresses idle-kill entirely
- WATCHDOG_MODE env var sets initial mode (default: auto)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- package.json: rename controlplane → clawdie, bump version to 0.4.0,
require node >=24
- docs/REFACTOR-PLAN.md: full host-first orchestrator refactor plan
(orchestrator moves from controlplane jail to host OS; rc.d service;
provider-agnostic pi setup with free-tier bootstrap path)
- html/clawdie/index.html: redesign to reflect new architecture
(4-step quick start, removed stale wizard/ecosystem content,
updated status badge, NanoClaw attribution)
- html/clawdie/guides/, clawdie-eng-v1.md: migrated from live web root
to repo (single source of truth via symlink)
- PI-ZAI-KEY.md: reference doc for pi provider config
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
## Headline Features
- Setup wizard: FreeBSD bsdinstall-style TUI for first-time setup
- Project-relative tmp/: No more /tmp usage
- Infrastructure as code: Ansible reads all IPs from .env
- Password-protected-site: Auto-generated htpasswd during wizard
## Attribution
This release was made possible with assistance from:
AI Systems: Openclaw, NanoClaw, z.ai, Anthropic Claude, OpenAI Codex, OpenRouter, Deepseek, Groq, Ollama, pi-tui
Human: Peter Steinberger
- Replace /tmp with project-relative tmp/ directory
- Add CLAWDIE_TMP_DIR env var with project-relative default
- Add TMP_DIR, TMP_TESTS_DIR, TMP_IPC_DIR, TMP_SKILLS_DIR to config.ts
- Update all test files to use TMP_TESTS_DIR
- Update shell scripts to use project-relative tmp/skills/
- Update agent-runner IPC cleanup to use /workspace/ipc/input.json
- Update Ansible playbooks to use env vars with fallbacks
- Add CMS resource limits
- Add jail-resource-limits.yaml playbook
- Add setup-wizard.ts (FreeBSD bsdinstall-style TUI)
- Add network.ts bootstrap step
- Remove hardcoded public gateway IP
Replace all hardcoded IPs (192.168.100.x) and domains (clawdie.si)
with configurable placeholders. Real values now live exclusively in
.env (gitignored).
Network: code defaults to 10.0.0.x, configurable via WARDEN_SUBNET_BASE,
WARDEN_GATEWAY, WARDEN_CONTROL_PLANE_IP env vars in jail-config.ts.
Domain: code defaults to clawdie.local, configurable via CLAWDIE_DOMAIN
env var. Subdomain scheme: controlplane/db/cms/gui.{domain}.
Also includes PGVector Phase 0 prep:
- Created ai_brain database with pgvector extensions
- Added pg + @types/pg npm packages
- Added CLAWDIE_DB_URL to .env
- Renamed db from 'clawdie' to 'ai_brain' across Ansible and docs
- Resolved embedding model: OpenRouter text-embedding-3-large at 1536d
- Added docs/pgvector-install-log.md
Renamed ai.clawdie.si → controlplane.{domain} (more descriptive).
Renamed vm.clawdie.si → gui.{domain}.
76 files updated across source, tests, skills, docs, Ansible, and scripts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>