Compare commits

...
3 Commits
Author SHA1 Message Date
pastilhasandClaude Opus 5 89fc3241f6 officer-dev is twenty-six PM2 entries, not thirteen
nothing about the platform changed: all 21 plugins were installed on that
machine so the marketplace UI had something real to render. the paragraph under
this one already says the number tracks plugin installs rather than releases —
this is that working, not an exception to it.

caught by `bun run docs:check`, which is the whole reason the number is checkable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 08:44:58 +00:00
pastilhasandClaude Opus 5 3552a5a7df officer.dev: account creation exists, and roles are a table
This file said there was no way to create a second account. There is, and has
been since 69a31051 — POST /api/users, owner-gated, with a form under Settings.
platform/CLAUDE.md and docs/roles-and-teams.md carried the same stale claim and
were corrected in the platform repo; this one was missed because I said it was
not in a git repository. It is, through the symlink.

Also records roles as a table with foreign keys onto roles.name, USER_ROLES
gone, and UserRole as a plain string guarded at the write path instead of by the
compiler.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
2026-08-23 23:50:00 +00:00
pastilhasandClaude Opus 5 7c41c56577 officer.dev: the pm2 count tracks plugin installs, not releases
Fourteen while Minesweeper was installed, thirteen once it was removed, with no
platform change either way — a plugin that declares a sidecar writes it into the
generated ecosystem file. Says so now, so the next reader does not treat a
change here as a platform change or expect two machines to agree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
2026-08-23 20:31:13 +00:00
+47 -15
View File
@@ -55,18 +55,33 @@ This file captures the **cross-cutting operational reality** that neither of tho
process that runs `claude` was spawned by the main server, so PM2's tree-kill took it down every time.
A restart now costs the agent a socket reconnect, not the session, and output produced while officer is
down survives — the sidecar writes to `chat_session_events` itself. There is no `officer-claude`.
- **Officer is twenty PM2 entries** (verified 2026-08-07 with `pm2 jlist`): `officer`,
`officer-anthropic-proxy`, `officer-agent`, `officer-opencode`, `officer-email`, `officer-pty`,
`officer-vnc`, `officer-music`, `officer-vault`, `officer-slskd`, `officer-headscale`,
`officer-transmission`, `officer-invoiceshelf`, `officer-wallet`, `officer-photos`, `officer-notify`,
`officer-caldav`, `officer-memos`, `officer-jellyfin`, `officer-gitea`.
**`pm2 list` shows twenty-two** — `mybiblepal-api` and `mybiblepal-audio` are a different project sharing
this PM2 daemon, and nothing here should touch them.
Never `pm2 restart ecosystem.config.cjs` — it bounces every
sidecar including the vault. Use `--only <name>`, or restart the single process the change needs.
This list goes stale every time a sidecar lands; `pm2 jlist` is the source of truth.
- **Officer is TWENTY-SIX PM2 entries here today** (verified 2026-08-27 by `bun run docs:check`, which
fails if this drifts): the five core processes — `officer`, `officer-anthropic-proxy`,
`officer-claude-code`, `officer-opencode`, `officer-pty` — plus `officer-notify`, `officer-marketplace`,
`officer-oas`, and one per installed plugin.
## Environment (this machine)
It was thirteen this morning. **Nothing about the platform changed**: all 21 plugins were installed on
this machine so the marketplace UI had something real to render. That is the paragraph below working
exactly as written, not an exception to it.
It was fifteen on 2026-08-25; `officer-minesweeper` and `officer-transcribe` were uninstalled since,
which is the point of the paragraph below rather than an exception to it.
**This number tracks PLUGIN INSTALLS, not platform releases.** It went to fourteen when Minesweeper was
installed and back to thirteen when it was removed, with no platform change either time — installing a
plugin that declares a sidecar writes it into the generated ecosystem file. Do not read a change here as
a platform change, and do not expect two machines to agree.
It said "twenty" and listed a different set until 2026-08-23 — including `officer-vault`, `officer-slskd`,
`officer-headscale`, `officer-transmission`, `officer-invoiceshelf`, `officer-wallet`, `officer-photos`,
`officer-jellyfin`, `officer-gitea`, `officer-music`, `officer-vnc`, none of which run here, while omitting
six that do. That is what a hand-maintained list of processes becomes: accurate on 2026-08-07, and nobody
re-derives a list while editing the sentence around it. `mybiblepal-api` and `mybiblepal-audio` are also
gone; nothing shares this daemon today.
Never `pm2 restart ecosystem.config.cjs` — it bounces every sidecar. Use `--only <name>`, or restart the
single process the change needs. `pm2 jlist` is still the source of truth; the check exists so the copy
cannot silently stop matching it.
- `OFFICER_ITEMS_DIR=/home/pastilhas/dockers/officer.dev/capabilities` ← items live here
- `DATA_PATH=/home/pastilhas/dockers/officer.dev/data`
@@ -167,10 +182,17 @@ keyed on **role**, never on a user, and live in `role_capabilities`; absence den
capabilities (terminal, chat, files, tasks, items, desktop, browser) run as the owner's OS user in the
owner's home and are **never grantable at any level** — that is structural, not a policy default.
What is NOT built: **there is no way to create a second account.** `createUser` has one call site,
`api/auth/bootstrap.ts`, gated on an empty `users` table. No signup route, no invites, no admin
create-user handler — the six accounts in Postgres were inserted by hand. Details and the open defect
list are in `platform/TODO.md` → "Multi-user"; the design write-up is `COMMS/capability-permissions-2026-08-07.md`.
**Account creation now exists** — `POST /api/users`, owner-gated, with a form under Settings → User
Management, plus role change, password reset, Linux provisioning and delete. It landed in `69a31051`; this
file claimed the opposite for days afterwards, and so did `platform/CLAUDE.md` and
`docs/roles-and-teams.md`, which sequenced a phase around building the thing that already existed.
Roles are a table as of 2026-08-23, with `users.role` and `role_permissions.role` as foreign keys onto
`roles.name` with `ON UPDATE CASCADE`. `USER_ROLES` is gone and `UserRole` is `string`, so the guard the
compiler used to provide is now a runtime check at every write path that takes a role from outside.
The design write-up is `COMMS/capability-permissions-2026-08-07.md`; the roles plan and what is still open
is `docs/roles-and-teams.md`.
The single-user claims that used to be all over this repo's docs were corrected on 2026-08-07. If you
find another one, it is stale — `platform/src/servers/capabilities/registry.ts` is the authority.
@@ -231,6 +253,16 @@ actually reset at the providers — it is the only record of which ones.
## Working agreement
- **Delegate the writing.** When a feature is agreed and what remains is typing — a change repeated
across many files, translations, a form, a migration over a list of call sites — hand it to a cheaper
agent, keep working, and review the DIFF when it returns. The owner's architecture, somebody else's
typing, your review in the middle. This is the default here, not a per-task decision, and it does not
need asking for. Read `capabilities/skills/delegating/SKILL.md` before writing the brief: an agent that
has to ask a question has already cost more than it saved. **Pick the cheapest model that will get it
right** — Haiku for mechanical, Sonnet by default, Opus only when the work still holds a decision, which
usually means the brief needs finishing rather than a bigger model. Do NOT delegate anything where a
wrong guess is quiet and expensive — permission checks, credentials, anything that deletes — because reviewing
those properly costs as much as writing them.
- **Fix what you find.** If a defect is diagnosed and you know the fix, apply it — don't stop to ask.
The owner retests immediately and restarts cost nothing. Still ask when it's a genuine product
decision rather than a defect, when it widens scope, or when it's hard to reverse.