colibri/.agent/skills/update/SKILL.md
Sam & Claude fba3f24267 skill: positive framing pass — nginx, setup, update, astro, docs-deployment
nginx:   broken config→valid config, fails→reports error, won't start→status check,
         BIO_new_file() failed→certificate file missing, common causes→things to check
setup:   broken/missing→needs repair, failed to load→need build tools,
         fix each→resolve each, Common causes→What to check
update:  broken state→consistent state, tests fail→tests don't pass,
         unfixable→not immediately resolvable, won't start→needs attention
astro:   fails because→requires
docs-deployment: broken→needs rollback, Check for broken symlinks→Verify symlinks
2026-06-26 14:15:47 +02:00

9.1 KiB

name description
update Update Clawdie from upstream or apply local changes safely with ZFS rollback. Takes a pre-update snapshot, pulls changes, validates build/tests, and supports instant rollback via ZFS. Triggers on "update", "pull upstream", "sync with upstream", "get latest changes".

Clawdie Update

Pull upstream changes and merge them with the current installation, using ZFS snapshots for rollback safety. The update skill always takes a snapshot before applying changes so rollback is instant via zfs rollback.

Principle: Handle everything automatically. Only pause for user confirmation before applying changes, or when merge conflicts need human judgment. Always leave the system in a consistent state — if the update encounters an issue, roll back to the snapshot.

UX Note: Use AskUserQuestion for all user-facing questions.

Answering "are updates available?" questions

When the operator asks for update, package, patch, or security-update status, treat it as a read-only audit unless they explicitly ask to apply changes.

Use the sysadmin/update-report path that calls hostd read-only ops:

  • pkg-version — package update candidates for host or a running jail
  • pkg-audit — vulnerability audit for host or a running jail
  • freebsd-update-status — pending FreeBSD base updates via updatesready
  • freebsd-version — kernel/running/userland version summary
  • bastille-list — discover running jails to audit

Do not run freebsd-update fetch, freebsd-update install, pkg upgrade, or any mutating update command while answering a status question. The report must say explicitly that no updates were applied.

If FreeBSD base status shows installed kernel/userland newer than the running kernel (freebsd-version -k/-u newer than uname -r), record that a reboot is required to complete the update and follow the freebsd-admin reference references/freebsd-update-reboot.md. Never reboot without explicit operator go-ahead.

Attribution: Peter Steinberger created OpenClaw, which established the broader project line. NanoClaw by Gavriel provides the upstream update path and skills-engine patterns Clawdie still uses. Clawdie extends that line with ZFS snapshot-based rollback on FreeBSD.

1. Pre-flight

Check current version

node -e "console.log(require('./package.json').version)"

Check for uncommitted changes

git status --porcelain

If there are uncommitted changes: AskUserQuestion: "You have uncommitted changes. Commit or stash before updating? Options: Continue anyway / Abort (I'll commit first)". If abort, stop.

Check remote

git remote -v

Verify origin points to code.smilepowered.org:clawdie/clawdie-ai.git. Codeberg is mirror/archive only; do not push there unless the operator explicitly asks.

Check Sanoid status

sanoid --version 2>/dev/null && echo "SANOID_OK" || echo "NO_SANOID"

If Sanoid is running, note it — we'll rely on it for automated retention. The manual pre-update snapshot is separate and intentional.

Check watchdog load gate

Before heavy rebuilds (Node + Rust), explicitly acknowledge the load budget.

echo '{"cmd":"status"}' | nc -U "${AGENT_TMP_DIR:-tmp}/ipc/${AGENT_NAME}-watchdog.sock"

If a heavy rebuild is expected, ask the operator whether to switch modes:

AskUserQuestion: "Heavy rebuild ahead (Node + Rust). Switch watchdog mode? Options: Keep auto / Switch to slow (safer) / Switch to fast (accept load) / Cancel"

If they choose slow/fast, apply:

echo '{"cmd":"mode","value":"slow"}' | nc -U "${AGENT_TMP_DIR:-tmp}/ipc/${AGENT_NAME}-watchdog.sock"

or

echo '{"cmd":"mode","value":"fast"}' | nc -U "${AGENT_TMP_DIR:-tmp}/ipc/${AGENT_NAME}-watchdog.sock"

2. ZFS Pre-Update Snapshot

This is mandatory. Always snapshot before applying changes.

Snapshot persistent service datasets

SNAP_NAME="pre-update-$(./scripts/date-format.sh snapshot-stamp)"
for ds in db git cms; do
  zfs list "zroot/clawdie-runtime/jails/clawdie-${ds}" >/dev/null 2>&1 && \
    sudo zfs snapshot "zroot/clawdie-runtime/jails/clawdie-${ds}@${SNAP_NAME}"
done

Snapshot operator home + npm-global (source of truth)

HOME_DATASET=$(zfs list -H -o name,mountpoint -t filesystem | awk -v home="$HOME" '$2==home {print $1}')
[ -n "$HOME_DATASET" ] && sudo zfs snapshot "${HOME_DATASET}@${SNAP_NAME}"

NPM_DATASET="zroot/clawdie-runtime/shared/npm-global"
zfs list "$NPM_DATASET" >/dev/null 2>&1 && sudo zfs snapshot "${NPM_DATASET}@${SNAP_NAME}"

Verify snapshot was created

zfs list -t snapshot -r zroot/clawdie-runtime/jails | tail -9

Record the snapshot name for potential rollback.

3. Fetch Changes

Fetch from origin

git fetch origin main

Check what's new

git log HEAD..origin/main --oneline

If no new commits: Tell the user they're already up to date. AskUserQuestion: "Already up to date. Force pull anyway? Options: Yes / No". If no, stop.

Preview changes

git diff --stat HEAD..origin/main

Present to the user:

  • Number of files changed
  • Key files affected (src/, .agent/skills/, docs/)
  • Any package.json version bump

4. Confirm

AskUserQuestion: "Apply this update? ZFS snapshot {SNAP_NAME} is ready for rollback if anything breaks. Options: Yes, apply / No, cancel"

If cancelled, stop. The snapshot remains (Sanoid will handle retention).

5. Apply

Stop the service (if running)

service clawdie status 2>/dev/null && sudo service clawdie stop

Pull changes

git pull origin main

If merge conflicts:

For each conflicting file:

  1. Read the file — look for conflict markers (<<<<<<<, =======, >>>>>>>)
  2. Check if there's an intent file in .agent/skills/<skill>/modify/<path>.intent.md
  3. Resolve using the intent file and codebase understanding
  4. git add <file> after resolving

If you cannot confidently resolve a conflict, show the user the conflicting sections and ask for guidance.

Install dependencies (if package.json changed)

git diff HEAD~1 --name-only | grep -q "package.json" && npm install

6. Build and Test

Build

npm run build

If build fails:

  • Type errors: read the error, fix the file, retry
  • Missing dependencies: npm install first, retry
  • Native module issues: npm rebuild pg

Run tests

npm test

If tests don't pass: Show which tests need attention. Try to diagnose and resolve. If not immediately resolvable, inform the user and offer rollback.

Type check

npm run typecheck

7. Post-Update Validation

Run doctor

npm run doctor

Restart service

sudo service clawdie start
service clawdie status

Verify Telegram connectivity

Check logs for successful bot startup:

tail -20 logs/clawdie.log

8. Rollback (If Needed)

If the update broke something and you need to roll back:

Stop service

sudo service clawdie stop

Roll back ZFS

for ds in cms git db; do
  zfs list "zroot/clawdie-runtime/jails/clawdie-${ds}@${SNAP_NAME}" >/dev/null 2>&1 && \
    sudo zfs rollback "zroot/clawdie-runtime/jails/clawdie-${ds}@${SNAP_NAME}"
done

Rebuild and restart

npm run build
sudo service clawdie start

Verify rollback

node -e "console.log(require('./package.json').version)"
npm run doctor

The rollback is instant because ZFS snapshots are atomic.

9. Cleanup

After a successful update (service running, tests passing, Telegram working):

Take a post-update milestone snapshot

NEW_VERSION=$(node -e "console.log(require('./package.json').version)")
sudo zfs snapshot zroot/clawdie-runtime/jails/cms@v${NEW_VERSION}-$(./scripts/date-format.sh display-date)

Report status

  • "Updated from {old_version} to {new_version}"
  • Files changed count
  • Build and test status
  • Pre-update snapshot name (for manual rollback reference)
  • Sanoid will handle snapshot retention automatically

Troubleshooting

Merge conflicts in many files: Consider whether extensive local modifications are conflicting with upstream. Use the skills system for customizations instead of direct edits — skills survive updates better.

Build fails after update: Check if dependencies changed. Run npm install to pick up new packages. Check for breaking TypeScript changes.

Service needs attention after update: Check logs/clawdie.error.log. If not immediately resolvable, roll back the affected service jail snapshot under zroot/clawdie-runtime/jails/.

ZFS snapshot missing: If the pre-update snapshot wasn't taken (manual setup without ZFS), fall back to git reset --hard HEAD~1 but this is less safe. Always prefer ZFS rollback.

Sanoid retention: Pre-update snapshots follow the day-first naming convention. Sanoid's automated retention policy will eventually clean old pre-update snapshots according to the policy defined in /sanoid skill.