Compare commits

..
Author SHA1 Message Date
pastilhasandClaude Opus 5 c97da0292a release 2026.08.30.03
One commit — 537cc29c, fixing what the 2026.08.30.01 rollout found on fofos: a plugin declaring
`@tiptap/pm` was reported as a failed install. Nothing was broken on disk. That package has no root
entry point by design — it is tiptap's single pinned copy of ProseMirror and you import
`@tiptap/pm/state`, never the bare name — so the checker asked a question it could not answer.

Worth its own release rather than waiting: `bun run plugins:update` exits 1 on fofos every time until
this lands, so the plugin step of every future deploy fails there and reads as a new problem each time.

No schema change and no dependency change, with the two commands that prove it in the plan. docs:check
green. Only fofos has fofos-admin installed, so everywhere else this is a no-op in behaviour.

── Why .03 ──

2026.08.30.02 was tagged against a commit that was not on master: the rollout's own report had just been
pushed and the release was cut without pulling first. The branch push was rejected and the tag was not,
so a tag pointing off-branch existed for about ten seconds. The watcher claimed the version inside that
window, and a claim is permanent by design — so .02 is spent and carries a claim with no .done, which is
what "attempted and did not succeed" should look like.

No host moved. Every one stayed on 816f8695 throughout.

The lesson is in the ordering, and it is now the practice: pull, then push the branch, then tag only
once the branch has landed. Pushing both in one command means a rejected branch still publishes a tag.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 11:38:06 +01:00
pastilhasandClaude Opus 5 d2c07a9fd2 deploy 2026.08.30.01: 7 of 7 hosts, officer-dev skipped as the host it ran on
fofos-admin failed its resolvability check on fofos — @tiptap/pm has no root
entry point, so the install was perfect and the checker was wrong. Fixed by
537cc29c, which is one commit past this tag and therefore deployed nowhere.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 11:23:23 +01:00
pastilhasandClaude Opus 5 537cc29c3e a package with no root entry point is not a broken install
`unresolvableDependencies` asked `Bun.resolveSync(name, pluginDir)` of every declared package. That is
the right question for almost all of them and unanswerable for a few.

`@tiptap/pm` declares no `main`, no `module`, and an `exports` map with no "." — it exists only as
subpaths. You import `@tiptap/pm/state`, never `@tiptap/pm`. Asked to resolve the bare name Bun
correctly says it cannot, and this read that as a failed install.

It cost a deploy. fofos-admin declares `@tiptap/pm` because tiptap needs it present; the install was
perfect — the directory, its dist and thirteen prosemirror packages all there — and the plugin was
reported as failed on every host that has it.

The strong check stays first, because it is the one that catches a package which installed but cannot
be loaded on this machine — `sharp` resolving to a platform-specific binary is the shape it was written
for. Only a package that fails it is asked the weaker question: is it there. Present-but-unimportable
still fails, since it never reaches the second line.

Verified on the host rather than reasoned about: of the five packages fofos-admin declares, four
resolve and @tiptap/pm alone does not, and it is present.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 11:20:25 +01:00
4 changed files with 234 additions and 2 deletions
+114
View File
@@ -0,0 +1,114 @@
# 2026.08.30.01 — rollout report
**7 of 7 targets succeeded. `officer-dev` skipped by design — it is the host the rollout ran on.**
One plugin failed on one host (`fofos-admin` on `fofos`) and it is a false alarm in the checker, not a
broken install. The owner fixed it mid-rollout in `537cc29c`, which is NOT in this tag. Detail below.
No schema change, no `bun install`, no `bun db:push` — the plan says so and shows the two
`git diff --name-only` commands behind the claim. Nothing was improvised.
## Per host
| Host | HEAD before | HEAD after | plugins:update | `officer` restart_time | /api/health | file-browser `ls` |
| --- | --- | --- | --- | --- | --- | --- |
| `officer-dev` | — | — | — | — | — | **SKIPPED — ran here** |
| `alpha` | `e9b71522` | `816f8695` | 15/15, exit 0 | 6 → 7 | 401 | 200, 77 entries |
| `fofos` | `601849be` | `816f8695` | **4/5, exit 1** | 3 → 4 | 401 | 200, 39 entries |
| `macbookpro` | `e9b71522` | `816f8695` | no plugins installed | 6 → 7 | 401 | 200, 62 entries |
| `macbruno` | `e9b71522` | `816f8695` | 1/1, exit 0 | 9 → 10 | 401 | 200, 41 entries |
| `production-pertento-bridge` | `e9b71522` | `816f8695` | 1/1, exit 0 | 7 → 8 | 401 | 200, 53 entries |
| `edge-pertento-bridge` | `e9b71522` | `816f8695` | 2/2, exit 0 | 8 → 9 | 401 | 200, 29 entries |
| `deadpool-rezio-bridge` | `e9b71522` | `816f8695` | 2/2, exit 0 | 25 → 26 | 401 | 200, 49 entries |
Every host landed on `816f8695`, exactly the tag. `fofos` started ahead of the previous tag and behind
this one, as the plan predicted, so its fast-forward moved 12 files rather than 23.
`401` on `/api/health` is healthy — the plan says so and all seven agreed. Ports were read from each
host's own `.env`, never assumed: 9010 on `macbookpro` and `production-pertento-bridge`, 9000 elsewhere.
## The file browser check
This release touched the listing loader, the clipboard and the row markup, so the plan asked for one
signed `/api/file-browser/ls` per host. **Seven hosts, seven `200`s**, every one with a plausible count
and none of them zero. The counts differ because the homes differ.
Signed as that host's own owner, read from its own `users` table rather than assumed —
`conceiba@gmail.com` on `macbruno`, `brunorezio@gmail.com` on `deadpool-rezio-bridge`,
`pastilhas@officer.dev` on the rest.
## Schema
**No schema verification was performed, because this release changes no schema.** No `db:push` step
exists in the plan and none was run, so there is nothing to verify by query. The clipboard is a key in
`user_state`, a JSONB column that already existed.
The plugin sidecars applied their OWN schemas during `plugins:update`, which belongs to the plugin
updater and not to this release: `music` on `alpha` (4 tables), `proxy-manager` on `fofos` (3) and on
`macbruno` (3), `offscale` on `edge-pertento-bridge` (1), `email` on `deadpool-rezio-bridge` (1).
## The one failure: `fofos-admin` on `fofos`
`bun run plugins:update` exited 1 with:
```
FAILED: packages installed, but @tiptap/pm cannot be resolved from …/plugins/fofos-admin
```
**The install is fine and the plugin is not broken.** Verified on the host rather than assumed:
- `plugins/node_modules/@tiptap/pm` is present, with its `dist` and the prosemirror packages.
- `@tiptap/pm` declares no `main`, no `module`, and an `exports` map with no `"."` — it exists only as
subpaths. Code imports `@tiptap/pm/state`, never the bare name.
- `Bun.resolveSync('@tiptap/pm', pluginDir)` therefore fails, while `@tiptap/react` and
`@tiptap/starter-kit` both resolve. `unresolvableDependencies` reads that as a failed install.
- `fofos-admin`'s own checkout is clean, so this is not the usual uncommitted-change cause.
Also verified there, and it is this release working as intended: `react` resolves out of the PLATFORM's
`node_modules`, not the plugins tree. The eviction added in `9719e367` did its job.
**The owner shipped the fix at 11:20 while the rollout was in flight — `537cc29c`, "a package with no
root entry point is not a broken install".** It is one commit PAST this tag and is therefore deployed
nowhere. `fofos` will keep failing that step on every `plugins:update` until a release carries it.
What this cost on `fofos`: `fofos-admin` did not finish its update — no assets publish, no access grant,
no `recorded at`. Its code was already at the latest commit, and the platform mounted `/fofos-admin`
normally. The other four plugins updated.
## A commit landed on master mid-rollout, and the tag absorbed it
`alpha`, `fofos`, `macbookpro`, `macbruno` and `production-pertento-bridge` fetched `origin/master` at
`816f8695`. `edge-pertento-bridge` and `deadpool-rezio-bridge` fetched it at `537cc29c`.
Because every host merged `--ff-only deploy/2026.08.30.01` and not the branch, **all seven are on the
tag and none carries the extra commit.** This is the exact failure of 2026-08-23, and merging the tag is
what prevented it.
## More restarted than `officer`
`plugins:update` restarts a sidecar whenever it moves a plugin, before the plan's own restart. Naming
only `officer` would understate what moved, so: `officer-music` on `alpha`, `officer-av-club` on
`fofos`, `officer-gitea` on `production-pertento-bridge`, `officer-gitea` and `officer-offscale` on
`edge-pertento-bridge`, `officer-email` on `deadpool-rezio-bridge`. `macbruno` moved `proxy-manager`,
which declares no sidecar, so nothing extra bounced there.
After every restart, `pm2 jlist` showed **every `officer*` process `online` on all seven hosts**. None
was `errored` and none failed to come back.
`ecosystem.config.cjs` was never restarted anywhere. No vault was touched. On
`production-pertento-bridge` the eight Pertento-owned processes — `Dashboard`, `Tracking`, `Uptime` and
the five `Crons *` — were filtered out of every read and never named in a restart.
## What I did not do
- **`officer-dev` — skipped entirely.** Not pulled, not restarted. The rollout ran inside its
`officer-claude-code` sidecar, and restarting it would have ended the session writing this report. Its
working tree already held this code. The owner restarts it deliberately, as the last step.
- **Did not fix the `fofos-admin` checker.** The fix exists in `537cc29c` and belongs to a release, not
to a rollout editing five hosts.
- **Did not re-run `plugins:update` on `fofos`** after diagnosing it. It would fail identically — the
code that decides is in the tag.
- **Did not run `bun run docs:check`.** Not the commander's job.
- **One untracked file noted, not touched:** `scripts/chk.ts` on `fofos`. Untracked is a note, not a
skip, and a fast-forward could never have touched it. Every host was clean on
`--untracked-files=no`.
+99
View File
@@ -0,0 +1,99 @@
# 2026.08.30.03 — a package with no root entry point is not a broken install
**One commit.** `537cc29c`, fixing what the 2026.08.30.01 rollout found on `fofos`.
**Why .03 and not .02.** `2026.08.30.02` was tagged against a commit that was not on `master` — the
rollout's own report had just been pushed and the release was cut without pulling first. The branch push
was rejected, the tag was not, and a tag pointing off-branch was published for about ten seconds before
being withdrawn. The watcher claimed the version inside that window.
A claim is permanent by design and that is correct: `.02` was attempted, so `.02` is spent and cannot be
deployed. It has a claim and no `.done`, which is exactly what "attempted and did not succeed" should
look like in the record. Nothing reached any host — every one stayed on `816f8695` throughout.
**No schema change and no dependency change.** Verified rather than assumed:
```bash
git diff --name-only deploy/2026.08.30.01..deploy/2026.08.30.03 | grep -iE 'schema|/db/|databases' # nothing
git diff --name-only deploy/2026.08.30.01..deploy/2026.08.30.03 -- package.json bun.lock # nothing
```
So **no `bun db:push` and no `bun install` step exists in this plan, and neither should be improvised.**
## What it fixes, and what it does not
`unresolvableDependencies` asked `Bun.resolveSync(name, pluginDir)` of every package a plugin declares.
That is the right question for almost all of them and unanswerable for a few.
`@tiptap/pm` declares no `main`, no `module`, and an `exports` map with no `"."` — it exists only as
subpaths, because it is tiptap's single pinned copy of the ProseMirror packages and you import
`@tiptap/pm/state`, never `@tiptap/pm`. Asked to resolve the bare name, Bun correctly says it cannot,
and the checker read that as a failed install.
**Nothing was ever broken on disk.** The install on `fofos` is complete — the directory, its `dist` and
thirteen prosemirror packages. The editor works. What failed was the verification, which then failed
`plugins:update`, which exits non-zero if any plugin failed.
The consequence worth shipping for: **`bun run plugins:update` exits 1 on `fofos` every time** until
this lands, so the plugin step of every future deploy fails there and looks like a new problem.
The strong check stays first, so a package that installed but cannot be loaded on this machine still
fails — `sharp` resolving to a platform-specific binary is the shape it was written for. Only a package
that fails it is asked the weaker question: is it there.
## Every host — the commands
The standard steps in `prompts/deploy-commander.md` are the whole rollout (dirty check,
`git fetch origin --tags`, `git merge --ff-only deploy/2026.08.30.03`, `bun run plugins:update`), plus:
```bash
pm2 restart officer
```
`officer` only — `plugins:update` has already restarted the plugin sidecars.
**`fofos` is the host this release is for.** Its `plugins:update` failed 4/5 on the last rollout and
should now be 5/5, exit 0. That is the check that matters:
```
→ fofos-admin
packages: installed and resolvable
```
If `fofos` still reports 4/5 with `@tiptap/pm cannot be resolved`, this release did not work and that
is the finding — report it rather than working around it.
Everywhere else this is a no-op in behaviour: no other host has `fofos-admin` installed, so no other
host was failing and none should start.
### Verify 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 healthy.
No file-browser check this time — this release touches one function in the plugin installer and
nothing a browser reaches.
## Per host
Every host went to `816f8695` an hour ago and all seven came back online, so they start from there.
| Host | Note |
| --- | --- |
| `officer-dev` | **SKIP ENTIRELY.** The rollout runs here. It already holds this commit and its `officer` was restarted by hand at 11:23. |
| `alpha` | Ordinary target. No `fofos-admin`, so nothing changes in behaviour. |
| `fofos` | **The reason for this release.** Expect `plugins:update` to go 4/5 → 5/5. |
| `macbookpro` | macOS, port **9010**, a laptop. Unreachable is a SKIP with a note, not a failure. |
| `macbruno` | macOS, login **`brunoalcadapadezmonteirodaconceicao`**. |
| `production-pertento-bridge` | Port **9010**. |
| `edge-pertento-bridge` | Ordinary target. |
| `deadpool-rezio-bridge` | Login **`br`**, checkout `/home/br/officerdev/platform`. |
Note for whoever reads the report: `scripts/chk.ts` is untracked on `fofos` and was noted last time. It
is still a note, not a skip.
## What "done" looks like
Per host: HEAD before and after, `plugins:update` result, `officer` back online with a moved
`restart_time`. And for `fofos` specifically, the `fofos-admin` line reading
`packages: installed and resolvable`.
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "officer",
"version": "2026.08.30.01",
"version": "2026.08.30.03",
"private": true,
"type": "module",
"workspaces": [
+20 -1
View File
@@ -181,12 +181,31 @@ const body = {
export function unresolvableDependencies(plugin: DiscoveredPlugin): string[] {
const names = Object.keys(plugin.manifest.npmDependencies ?? {});
return names.filter((name) => {
// The strong check: it imports. This is what catches a package that installed but cannot be loaded
// on this machine — `sharp` resolving to a platform-specific binary is the shape it was written for.
try {
Bun.resolveSync(name, plugin.dir);
return false;
} catch {
return true;
// fall through
}
/*
Some packages have NO root entry point, and that is not a fault.
`@tiptap/pm` declares no `main`, no `module`, and an `exports` map with no `"."` — it exists only as
subpaths, and you import `@tiptap/pm/state`, never `@tiptap/pm`. Asked to resolve the bare name,
Bun correctly says it cannot, and the check above read that as a broken install.
It cost a deploy: fofos-admin declares `@tiptap/pm` because tiptap needs it present, the install
was perfect — the directory, its dist and thirteen prosemirror packages all there — and the plugin
was reported as failed on every host that had it.
So a package that does not resolve is asked the weaker question instead: is it THERE. Present but
unimportable still fails, because the strong check ran first and only a package with no root entry
reaches this line.
*/
return !existsSync(join(PLUGINS_DIR, 'node_modules', name, 'package.json'));
});
}