Commit Graph
5 Commits
Author SHA1 Message Date
pastilhasandClaude Opus 5 a0b083db8f officer-setup section 2: one root, and nothing configurable underneath it
$OFFICER_ROOT/
    platform/       the app
    data/           managed homes, attachments, job logs
    dockers/        anything the app store provisions
    capabilities/   skills, tools, tasks, processes

The original asked separately for DATA_PATH and OFFICER_ITEMS_DIR and left the
app store's directory implicit — three answers that had to agree with each other,
given by somebody with no reason to know they had to. One question now, at the
top of the run, and the rest follows from it.

This is also what the code already assumes rather than a new convention:
app-store/paths.ts derives OFFICER_ROOT as dirname(DATA_PATH) and DOCKERS_DIR as
OFFICER_ROOT/dockers, so writing DATA_PATH=<root>/data is the whole of what makes
the layout correct. No code changes.

Anybody who wants data/ on a bigger volume can symlink it. That is a decision
about storage, not about how Officer is laid out, and it does not need a prompt.

The one check worth having: a directory that exists but belongs to somebody else.
That happens when an earlier run created it as root, and everything written into
it afterwards fails in a way that reads as a permissions bug in the platform
rather than as a bad directory. Reported with what writes there and offered as a
chown.

Placed before the repository, because the checkout lands inside it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 22:02:21 +00:00
pastilhasandClaude Opus 5 8a0946ea39 officer-setup section 3: dependencies
bun install, as the account, in the checkout.

Two things stated because a failure here is otherwise opaque.

The lockfile is frozen — bunfig.toml sets [install] frozenLockfile = true — so
bun resolves from bun.lock and nothing else. A package.json that disagrees with
it is a hard failure rather than a quiet resolution, which is deliberate: the
friction exists so an unexplained lockfile change shows up in a diff. If the
install fails complaining about the lockfile, the section says that is the
frozen lockfile working and that it wants a human to read the diff, rather than
reporting a generic failure.

node-pty has no Linux prebuild, so this compiles it from source on every machine.
That is what build-essential and python3 are in machine-setup's core utils for,
and the section says so — the failure would otherwise surface much later as a
terminal that never starts.

Success is checked by the artefact rather than by the exit status: bun can
complete while the native module is not built, because it skips a dependency's
lifecycle scripts unless it trusts the package. So the section looks for
node_modules/node-pty/build/Release/*.node and, when it is missing, names the
consequence and the command that fixes it instead of reporting success.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 21:55:04 +00:00
pastilhasandClaude Opus 5 ee21fa16f0 officer-setup: the repository URL is https
https://gitea.officer.dev/officerdev/platform.git, not the ssh form.

The reachability check is now one test for either scheme: `git ls-remote` with
both prompts disabled. That is the real question — not whether the host answers
but whether this account can read the repository — and neither prompt fails
cleanly on its own. Over https git asks for a username nobody is there to type;
over ssh it asks for a password or stops on host-key verification. With
GIT_TERMINAL_PROMPT=0 and BatchMode both off, an unreadable repository is an
immediate non-zero rather than a hang.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 21:52:53 +00:00
pastilhasandClaude Opus 5 a5a8cd4e9c officer-setup section 2: the repository
Clones from ssh://git@gitea.officer.dev:2222/officerdev/platform.git, or uses the
checkout already at $OFFICER_ROOT/platform.

Cloned as the account, never as root. A repository owned by root is one the owner
cannot pull, cannot commit in, and whose node_modules they cannot write — and
every later section in this script writes into that directory as them.

Three things it refuses to do quietly:

  It does not repoint an existing remote. This checkout points at
  gitea.pastilhas.dev rather than the new gitea.officer.dev; that is reported
  with the command to change it, because where somebody's work pushes to is
  their decision.

  It does not pull over uncommitted changes. A dirty tree means the pull is
  skipped and said so, rather than failing halfway or burying the work.

  It pulls with --ff-only, so a failure means the branch has diverged rather
  than that the network was down, and the message says which.

SSH reachability is checked before the clone, not after. An ssh URL with no
usable key does not fail cleanly: git prompts for a password nobody is there to
type, or stops on host-key verification. BatchMode turns both into an immediate
answer, and the check reads the server's response rather than the exit code —
Gitea greets a successful authentication and then exits 1, so exit status alone
reports success as failure.

When the key is missing it offers the https form of the same URL, which works
without a key if the repository is readable anonymously, and otherwise stops and
says to add the key. Verified against the new host: ssh authentication from this
account already works.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 21:48:35 +00:00
pastilhasandClaude Opus 5 b724e3ffbe start officer-setup: pre-flight, inheriting what machine-setup already asked
The second half of the install, and a much smaller script than the original: of
the old setup.sh's thirteen sections, seven are machine-setup's job now and two
more were already removed. What is left is the repository, dependencies, the
database, .env, the schema, the build and pm2.

Pre-flight asks nothing on a normal run. machine-setup saves the account, the
Officer path and the role beside itself, and this reads the same file — so
machine-setup then officer-setup is two scripts and one set of answers. It
prompts only where that file is absent, which is a supported case rather than an
error: somebody may have provisioned the box their own way.

It then checks the machine is actually ready — git, node, bun and pm2 required,
docker optional — and reports all of them together with what each is for. Finding
out about a missing bun three sections in, after a repository has been cloned and
a database started, is a worse way to learn it. A missing required tool stops the
run and names machine-setup.

Found by running it: a remembered answer can go stale. My own earlier testing had
left SETUP_USERNAME=gitfresh in that file, for a throwaway account I then deleted,
and the run dead-ended on it. A remembered account that no longer exists is a
reason to ask again, not a reason to stop — so it is checked before it is
trusted, reported, and replaced.

Docker being absent is a warning rather than a failure: Postgres can be one you
already run, and the app store simply cannot provision until Docker is there.

Sections 2 to 9 are listed and not built.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 21:45:02 +00:00