installer: don't clobber an existing config.json on a fresh install - #44
Merged
Conversation
The comment above this write already promised the correct behaviour — "a
re-run must never clobber registry/beacon/consent settings the operator
edited by hand" — but the guard did not deliver it.
UPDATING is derived purely from `[ -x "$BIN_DIR/pilotctl" ]`, i.e. whether the
BINARY exists. It says nothing about the config. So a host with a hand-edited
~/.pilot/config.json but no binary took the "fresh install" branch and had its
config silently overwritten:
- binaries removed for a clean reinstall, config deliberately kept
- config restored from backup before reinstalling
- config pre-seeded before a first install
Same class of bug as the rest of this installer's recent history: the stated
intent was right, the condition tested the wrong thing, and the failure was
silent — no warning, no backup, no diff.
It also made consent settings unreachable before first start. Pre-seeding
{"consent":{...}} or {"skill_inject":{"mode":"disabled"}} was erased by this
write, and the erase happened BEFORE the first `pilotctl skills check` pass
further down — so the documented opt-outs could only be applied after the
first injection had already run. Guarding on the file itself makes them
reachable at install time.
DEFAULTS ARE UNCHANGED. This does not alter skill-injection mode,
auto-updates, telemetry, or any other default: a host with no config still
gets exactly the same config it got before. The only behavioural change is
that an existing file is left alone instead of being destroyed.
Verified in fresh debian:12 containers both ways: a pre-seeded config with a
custom registry, telemetry disabled and skill_inject disabled survives the
install byte-for-byte (exit 0); and a true fresh install with no config still
writes the standard one and yields a working `pilotctl version` (v1.13.7).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Jul 29, 2026
TeoSlayer
added a commit
to pilot-protocol/website
that referenced
this pull request
Jul 29, 2026
The hard drift check added to sync-install-sh.yml fires on this — as designed. pilot-protocol/release#44 landed ("don't clobber an existing config.json on a fresh install"), moving canonical from 906deea1 to c9d11c8c. R2 (the live path) picked it up automatically via repository_dispatch, so the live URL already serves c9d11c8c and users were never affected. This shadowed fallback copy is the one that lagged. public/install.sh is now byte-identical to release@main (c9d11c8c…). Co-authored-by: Teodor Calin <teodor@vulturelabs.io> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
TeoSlayer
added a commit
to pilot-protocol/pilotprotocol
that referenced
this pull request
Jul 29, 2026
The canonical-drift job went red on main again — working exactly as intended. pilot-protocol/release#44 landed ("don't clobber an existing config.json on a fresh install"), moving canonical from 906deea1 to c9d11c8c, while this repo's copy stayed behind. The live URL already serves c9d11c8c — R2 syncs from the release repo automatically — so users were never affected. Only the in-repo copy was stale, which is precisely the gap the drift job exists to catch. install.sh is now byte-identical to release@main (c9d11c8c…). Co-authored-by: Teodor Calin <teodor@vulturelabs.io> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The comment above this write already promised the right behaviour —
— but the guard didn't deliver it.
UPDATINGis derived purely from[ -x "$BIN_DIR/pilotctl" ], i.e. whether the binary exists. It says nothing about the config. So a host with a hand-edited~/.pilot/config.jsonbut no binary took the "fresh install" branch and had its config silently overwritten:Same class as the rest of this installer's recent history: the stated intent was right, the condition tested the wrong thing, and the failure was silent — no warning, no backup, no diff.
Secondary effect
It also made consent settings unreachable before first start. Pre-seeding
{"consent":{...}}or{"skill_inject":{"mode":"disabled"}}was erased by this write — and the erase happened before the firstpilotctl skills checkpass further down. So the opt-outs the installer itself documents could only be applied after the first injection had already run.Guarding on the file makes them reachable at install time.
Defaults are unchanged
This does not alter skill-injection mode, auto-updates, telemetry, or any other default. A host with no config gets exactly the same config it got before. The only behavioural change is that an existing file is left alone instead of destroyed.
Verification
Fresh
debian:12containers, both directions:pilotctl version→v1.13.7🤖 Generated with Claude Code