From 78bf63c209f0306dfd238bd84891ae1ec6967e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Sat, 29 Aug 2026 03:12:45 +0100 Subject: [PATCH] =?UTF-8?q?release=202026.08.29.02=20=E2=80=94=20a=20plugi?= =?UTF-8?q?n=20can=20ship=20a=20commander?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043 --- deploy/2026.08.29.02.md | 119 ++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 deploy/2026.08.29.02.md diff --git a/deploy/2026.08.29.02.md b/deploy/2026.08.29.02.md new file mode 100644 index 00000000..8c9346d6 --- /dev/null +++ b/deploy/2026.08.29.02.md @@ -0,0 +1,119 @@ +# 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//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: + +```bash +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 + +```bash +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 + +```bash +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. + +```bash +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 + +```bash +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. diff --git a/package.json b/package.json index b5ddf56c..f809b015 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "officer", - "version": "2026.08.29.01", + "version": "2026.08.29.02", "private": true, "type": "module", "workspaces": [