Files
platform/deploy/2026.08.29.02.md
T
pastilhasandClaude Opus 5 78bf63c209 release 2026.08.29.02 — a plugin can ship a commander
THIS ONE CHANGES THE DATABASE, and the plan says so with the command that proves
what the change is rather than the claim alone:

  command_hq_sessions
    + plugin         text   null
    + plugin_config  jsonb  null

both nullable, no default, no constraint — so every existing row is valid the
moment they exist and there is nothing to backfill. no rename, nothing dropped, no
create-then-constrain, and therefore no --force needed or permitted.

THE PLAN DEMANDS A QUERY, NOT AN EXIT CODE. drizzle-kit push can fail and still
exit 0, so step 3 is a verification that must print exactly `plugin plugin_config`
and whose OUTPUT goes in the report per host — not "schema ✓". I ran that exact
command here before asking seven hosts to run it.

NO bun install step: package.json and bun.lock are untouched since .01. that also
sidesteps the step-order bug the last rollout found, where the standard
plugins:update runs before a plan's install and imports a package that is not there
yet.

the backup step reads the env variable name rather than assuming it. several hosts
use OFFICERDEV_POSTGRES_URL and not POSTGRES_URL, which is the kind of detail that
turns a backup step into a file containing an error message.

av-club's commander template reaches each host through the standard plugins:update
step rather than through this plan — worth saying, because av-club moving is
expected here rather than a surprise.

gate before tagging: typecheck clean, docs:check green, locale parity green. the
ModelSelector test still fails and is still not mine — same chat code, untouched by
this range.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
2026-08-29 03:12:45 +01:00

4.9 KiB

2026.08.29.02 — a plugin can ship a commander

This one changes the database. Two columns, both nullable additions, on a table that already exists. There is no rename in it, nothing is dropped, and no existing row changes — but db:push is still not to be trusted on its exit code, so there is a per-host query below and the report must carry its answer for each host.

No dependency change: package.json and bun.lock are untouched since 2026.08.29.01. There is no bun install step in this plan — which also sidesteps the step-order problem the last rollout found, where the standard plugins:update ran before the plan's install.

What is in it

  • Plugins can ship commanders. A plugin with commanders/<name>/COMMANDER.md offers one; it appears in Command HQ under a new From plugins section, arrives not running, and must be configured before it can arm.
  • av-club ships the first one — Convert on arrival: watches a folder, converts what lands in it. It reaches each host through the standard bun run plugins:update step, not through this plan.
  • Marketplace, file browser and Convert Image work from earlier today rides along.

Schema — CHANGED. db:push is required.

command_hq_sessions
  + plugin         text    null    which plugin's template made this commander
  + plugin_config  jsonb   null    the owner's answers to that template's inputs

Verified as the whole of it:

git diff --name-only deploy/2026.08.29.01..deploy/2026.08.29.02 | grep -iE 'schema|/db/|databases'
# → src/databases/officer_db/src/command-hq/queries.ts
#   src/databases/officer_db/src/command-hq/schema.ts

queries.ts is code, not schema. The only structural change is the two columns above.

Both are nullable with no default and no constraint, so every existing row is valid the moment they exist and there is nothing to backfill. This is the shape db:push handles cleanly — there is no create-then-constrain here, and no --force is needed or permitted.

Every host — the commands

After the standard steps in prompts/deploy-commander.md (dirty check, git fetch origin --tags, git merge --ff-only deploy/2026.08.29.02, bun run plugins:update), in the checkout from PM2's pm_cwd:

1. Back the database up first

pg_dump "$(grep -m1 -E '^(OFFICERDEV_)?POSTGRES_URL=' .env | cut -d= -f2-)" > ~/db-backups/officer-$(date +%Y%m%d-%H%M).sql

Read the variable name rather than assuming it: several hosts use OFFICERDEV_POSTGRES_URL, not POSTGRES_URL. mkdir -p ~/db-backups first if it is not there.

2. Push the schema

bun db:push < /dev/null

stdin closed, so it can never sit waiting on a prompt in an unattended run — it fails instead, which is the outcome you want. Expect [✓] Changes applied and then the two post-push scripts.

3. VERIFY BY QUERY. The exit code is not the answer.

bun -e "
const { db } = await import('officerdb/db'); const { sql } = await import('drizzle-orm');
const r = await db.execute(sql\`select column_name from information_schema.columns
  where table_name='command_hq_sessions' and column_name in ('plugin','plugin_config') order by column_name\`);
console.log([...((r as any).rows ?? r)].map((x:any)=>x.column_name).join(' '));
process.exit(0)"

Must print exactly:

plugin plugin_config

Put that line in the report, per host. Not "schema ✓" — the output. A host printing one column, or none, is a failed host: report it, move on, and do not attempt a repair you invented.

4. Restart

pm2 restart officer

officer only. plugins:update has already restarted the plugin sidecars itself.

5. Check it came back

pm2 jlist: officer online and restart_time moved, then /api/health on the host's own port (9010 on macbookpro and production-pertento-bridge, 9000 elsewhere). 200 or 401 are both healthy.

Per host

Host Note
officer-dev SKIP ENTIRELY. The rollout runs here. Its schema is already pushed; nothing else is needed. Name it as skipped.
alpha Nothing special.
fofos The one that matters this time — av-club is installed there and the commander template is the point of the release.
macbookpro macOS, port 9010, a laptop. Unreachable is a SKIP with a note.
macbruno macOS, login brunoalcadapadezmonteirodaconceicao.
production-pertento-bridge Port 9010.
edge-pertento-bridge Nothing special.
deadpool-rezio-bridge Login br, checkout /home/br/officerdev/platform.

What "done" looks like

Per host: HEAD before and after, whether the backup was written, db:push result, the exact output of the verification query, and officer back online with a moved restart_time.

The line that matters in the summary: which hosts print plugin plugin_config. That is the only thing this release actually changes about a machine.