Skip to content

docs: the setup block is safe to paste again, and this copy says so - #10

Merged
makseq merged 1 commit into
mainfrom
docs/setup-block-rerunnable
Aug 11, 2026
Merged

docs: the setup block is safe to paste again, and this copy says so#10
makseq merged 1 commit into
mainfrom
docs/setup-block-rerunnable

Conversation

@makseq

@makseq makseq commented Aug 11, 2026

Copy link
Copy Markdown
Member

What this is

The agent setup block in docs/OPERATIONS.mdStarting the agent was still the version written as though it runs once. It is in fact run again after every re-registration, every new agent build and every mistake, and the second paste ended in:

docker: Error response from daemon: Conflict. The container name "/lspo-agent" is already in use

— an error message about a machine that was working perfectly, and the readers of this repository are exactly the people who hit it.

The orchestrator fixed the generator that prints that block (orchestrator 3b622553). This brings our copy in line with it.

What the block does now

It fetches the image, looks for a container left by an earlier paste, stops and removes it, and starts a fresh one. On a machine that has never run it, the two middle lines find nothing and say nothing.

# Safe to re-run: it fetches a newer agent image and replaces the running agent. A failed fetch changes nothing.
docker pull -q ghcr.io/humansignal/lspo-agent:latest &&
c=$(docker ps -aq -f 'name=^/?lspo-agent$') &&
if [ -n "$c" ]; then docker stop -t 20 "$c" && docker rm "$c"; fi &&
docker run -d --name lspo-agent \
  …

The && chaining is a guarantee, not a layout choice: a failed fetch takes nothing away. The shell this is pasted into is interactive and has no set -e, where a failed pull stops nothing on its own — so as separate lines the same block would go on to remove a working agent and then start a stale cached image, or none at all. Measured on a real daemon with an unreachable registry: chained, the existing agent kept running; unchained, a healthy agent was destroyed and the machine was left with none. Hence the RECOMMENDATION not to tidy the lines apart when quoting them into a runbook, and not to drop the single quotes around the filter, where ? is otherwise a shell glob.

Also in this diff

Two pre-existing drifts from what the product actually prints, both in the same block:

  • LSPO_AGENT_NAME came before LSPO_AGENT_POOL / LSPO_AGENT_REGISTRATION_TOKEN, and -e LSPO_AGENT_MAX_CONCURRENT_JOBS=1 was missing.
  • "docker run pulls it for you; docker pull … fetches it on its own if you would rather do that first" is not true of a block that fetches first. Replaced with what the block does, plus the job a standalone pull is actually good for: establishing that a machine can reach the registry at all.

One nearby sentence became imprecise and was corrected: "Four parts of that command are load-bearing" now says four parts of the docker run line, with the chain named as a fifth.

Verification

Byte-identity of the fenced block, checked mechanically rather than by eye. The block is extracted from docs/OPERATIONS.md and compared with the return value of noderegistry.services.docker_run_command at orchestrator 3b622553, called with this section's own placeholders (pool_name='self-hosted', api_base='https://orchestrator.example.com', token=None — which is what makes the token line read PASTE_THE_POOL_TOKEN_HERE). Equal strings, same SHA-256 a5cd8883e9f9a367…, all 19 lines, whitespace included.

Tests. python -m pytest (what CI runs, real Docker daemon 28.4.0): 128 passed, 1 skipped in 134s. The skip is the verbatim-citation check, which needs an orchestrator checkout; run with one (LSPO_ORCHESTRATOR_SRC at 3b622553) that file is 21 passed, 0 skipped.

Sweep for anything the change makes false — rg -n "Conflict|already in use|docker pull|docker run -d|lspo-agent": every remaining hit is docker logs lspo-agent in the troubleshooting sections (still true), the container name default in logs.sh (still true), and docs/_archive/README-2026-08-08.md, which README.md declares a historical record containing statements known to be wrong and is deliberately untouched.

🤖 Generated with Claude Code

The block in `Starting the agent` was still the version written as though it ran
once, and it is in fact run again after every re-registration, every agent build
and every mistake. The second paste ended in `docker: Error response from daemon:
Conflict. The container name "/lspo-agent" is already in use` — an error message
about a machine that was working perfectly, and the reader of this repository is
exactly the person who hit it.

The orchestrator fixed the generator that prints the block (orchestrator #271);
this brings our copy of it in line. The block now fetches the image, looks for a
container left by an earlier paste, stops and removes it, and starts a fresh one.
On a machine that never ran it, the two middle lines find nothing and say nothing.

The three lines are chained with `&&` and that is a guarantee, not a layout
choice: **a failed fetch takes nothing away**. The shell this is pasted into is an
interactive one with no `set -e`, where a failed pull stops nothing on its own —
so as separate lines the same block would go on to remove a working agent and then
start a stale cached image, or none at all. That is measured rather than reasoned
about: on a real daemon, with an unreachable registry, the chained block left the
existing agent running and the unchained one destroyed a healthy agent and left
the machine with none. Hence the RECOMMENDATION not to tidy the lines apart when
quoting them into a runbook, and not to drop the single quotes around the filter,
where `?` is otherwise a shell glob.

Two smaller corrections in the same section, both pre-existing drift from what the
product prints:

* `LSPO_AGENT_NAME` was listed before `LSPO_AGENT_POOL` and
  `LSPO_AGENT_REGISTRATION_TOKEN`, and `-e LSPO_AGENT_MAX_CONCURRENT_JOBS=1` was
  missing entirely.
* "`docker run` pulls it for you; `docker pull …` fetches it on its own if you
  would rather do that first" is no longer true of a block that fetches first. It
  now says what the block does, and keeps the standalone pull for the job it is
  actually good for: establishing that a machine can reach the registry at all.

The fenced block is byte-identical to `noderegistry.services.docker_run_command`'s
output at orchestrator `3b622553` — checked mechanically, not by eye: the block is
extracted from this file and compared with the generator's return value called with
this section's own placeholders (`self-hosted`, `https://orchestrator.example.com`,
no token, which is what makes the token line read `PASTE_THE_POOL_TOKEN_HERE`).
Same SHA-256, all 19 lines, whitespace included.

`python -m pytest`: 128 passed, 1 skipped in 134s — the skip is the verbatim
citation check, which needs an orchestrator checkout. Run with one
(`LSPO_ORCHESTRATOR_SRC` pointed at `3b622553`) it passes too.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@makseq
makseq merged commit bb2ed11 into main Aug 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant