Files
platform/deploy/2026.09.09.01.md
pastilhas be3139f97d release 2026.09.09.01
Twenty-seven commits and ten days. One new table, plugin_ports, which is a plain create — nothing
references it, so db:push has no ordering problem to get wrong. The marketplace's nullable release_tag
is deliberately out of scope: db:push covers officer_db, and the marketplace runs only on officer-dev,
which the rollout skips.

@anthropic-ai/sdk is new, so bun install is a step. The lockfile is committed and matches; a host that
cannot resolve from it is a finding, not something to force past.
2026-09-09 23:17:12 +01:00

6.5 KiB

2026.09.09.01 — ten days of platform work, and one new table

Twenty-seven commits, deploy/2026.08.30.03..fafc1adb. The fleet is ten days behind; this is a catch-up release rather than a fix for anything found in the last one.

The larger threads in it, so a host that misbehaves has somewhere to point:

  • Plugin ports — the platform can allocate a plugin a stable port and remember it (518d329c, d9110c37). This is the schema change; see below.
  • Publishing is a tag — the marketplace reads releases, not working trees (78e89ebc, 19bbbab9).
  • Plugin routing — a plugin owns the routing under its mount and can declare its own routes (89820972, 1fe767ea), with :section given back to the fifteen plugins the splat took it from (eaa92738).
  • The code editor's tree and file browser are exported for plugins to reuse (fb530456, 5fa3f3ec, da07048f).
  • anthropicViaProxy (fafc1adb) — the boundary through which platform-side code, including a plugin's server routes, reaches Claude on the owner's own subscription.

The schema change — one new table, one nullable column

Verified rather than assumed:

git diff --name-only deploy/2026.08.30.03..master | grep -iE 'schema|databases/'

Two files, and they are not equally in scope:

  1. officer_db — plugin_ports, a brand-new table. No foreign key onto it and no existing column pointing at it, so this is not the create-then-constrain shape that db:push cannot do. A plain bun db:push is enough, and it is a create on every host.

  2. marketplace_db — plugins.release_tag, a nullable text column. Out of scope for this rollout. bun db:push covers officer_db only, and the marketplace runs on exactly one machine:

    officer-marketplace → officer-dev only    (verified 2026-09-09, pm2 jlist on all six)
    

    officer-dev is the host the rollout skips. So no target needs it, and nothing should improvise a second push to reach it. It is named here so that when officer-dev is restarted deliberately, the marketplace database is known to be the one outstanding piece.

Dependency change — bun install is required

git diff --name-only deploy/2026.08.30.03..master -- package.json bun.lock   # both changed

@anthropic-ai/sdk@^0.71.0 was added (plus its json-schema-to-ts dependency). The lockfile is committed and matches, so the frozen-lockfile default resolves from it — plain bun install, never --no-frozen-lockfile. A host that cannot resolve from the lockfile is a finding, not something to force past.

Every host — the commands

The standard steps in prompts/deploy-commander.md are the rollout (dirty check — TRACKED only, git fetch origin --tags, git merge --ff-only deploy/2026.09.09.01, bun run plugins:update), plus, in this order:

bun install
bun db:push < /dev/null
pm2 restart officer

bun install before plugins:update, because the plugin installer runs against the platform's own resolved modules. db:push after both, because gen-plugin-schemas runs inside it and reads the plugins as they now are.

< /dev/null on the push is not decoration: stdin closed means a push that wants to ask a question fails instead of hanging forever in an unattended run. This change should ask nothing — a create of a table nothing else references — so a prompt here is a finding.

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

Verify it came back — three checks, per host, by query

Exit 0 from db:push is not evidence; drizzle-kit push can fail and still exit 0.

  1. The table exists, asked of that host's own database:

    psql "$DB_URL" -tAc "select to_regclass('public.plugin_ports')"    # → plugin_ports
    

    Read the URL from that checkout's .env — several hosts use OFFICERDEV_POSTGRES_URL, not POSTGRES_URL.

  2. pm2 jlist — officer is online and its restart_time moved.

  3. HTTP — /api/health on the host's own port. 200 or 401 are both healthy. The port is in .env and is 9010 on macbookpro, 9000 elsewhere.

Per host

Host Login State before Note
alpha pastilhas 19bbbab9, 8 commits past the tag Partially pulled at some point; the fast-forward is shorter than the others'.
fofos pastilhas fafc1adb — already at master Already carries every commit; the merge is a no-op that only moves the tag onto it. Still runs install/push/restart. One untracked file — a note, not a skip.
macbookpro pastilhas c97da029 (2026.08.30.03) Laptop. Asleep is a SKIP with a note. export PATH=$PATH:/opt/homebrew/bin for bun, and run pm2 as a separate command. Port 9010.
deadpool-rezio-bridge br c97da029 (2026.08.30.03) Not pastilhas.

Skipped, deliberately — not failures

  • officer-dev — the host the rollout runs on. Skipping it entirely is the rule; restarting officer there ends the rollout mid-report. It is at fafc1adb and therefore not behind in code; what it does still want is the marketplace column above, whenever the owner restarts it.
  • macbruno — unreachable at cut time (connect to host macbruno port 22: Connection timed out, verified 2026-09-09). A Mac, so most likely asleep.
  • Both Pertento hosts — on the deliberately-skipped list in docs/servers.md since 2026-09-08. Owner's call, no fault on either box.

What "done" looks like

Four hosts attempted: alpha, fofos, macbookpro, deadpool-rezio-bridge. Each at deploy/2026.09.09.01, plugin_ports present by query, officer back online, health answering on the right port.

A host that fails does not stop the rollout. It gets its own line saying which step failed and what never ran.

Known and carried, not introduced here

bunx tsgo reports one pre-existing type error in src/servers/sidecar/claude/claude-manager.ts:667 (SdkUserMessage vs SDKUserMessage, from the agent SDK's own types). It is present on master before this release's commits, it is type-only, and Bun strips types at run time — so it does not affect the rollout. Named here so it is not discovered mid-deploy and mistaken for something this release did.