@tpsdev-ai/flair 0.26.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/cli.js +434 -50
- package/dist/doctor-client.js +47 -0
- package/docs/assets/flair-cross-orchestrator.cast +33 -0
- package/docs/assets/flair-cross-orchestrator.gif +0 -0
- package/docs/assets/flair-demo.cast +18 -0
- package/docs/assets/flair-demo.gif +0 -0
- package/docs/auth.md +178 -0
- package/docs/bridges.md +291 -0
- package/docs/claude-code.md +202 -0
- package/docs/deployment.md +204 -0
- package/docs/entity-vocabulary.md +109 -0
- package/docs/federation.md +179 -0
- package/docs/integrations.md +197 -0
- package/docs/mcp-clients.md +240 -0
- package/docs/n8n-management.md +142 -0
- package/docs/n8n.md +122 -0
- package/docs/notes/adk-spike-findings-2026-05-05.md +331 -0
- package/docs/notes/mcp-agent-auth-consumer.md +229 -0
- package/docs/notes/mcp-oauth-model2.md +132 -0
- package/docs/notes/rem-ux.md +39 -0
- package/docs/openclaw.md +131 -0
- package/docs/quickstart.md +153 -0
- package/docs/releasing.md +173 -0
- package/docs/rem.md +60 -0
- package/docs/rerank-provisioning.md +67 -0
- package/docs/secrets-and-keys.md +173 -0
- package/docs/spoke-bringup.md +303 -0
- package/docs/supply-chain-policy.md +156 -0
- package/docs/system-requirements.md +42 -0
- package/docs/the-team.md +129 -0
- package/docs/troubleshooting.md +187 -0
- package/docs/upgrade.md +416 -0
- package/package.json +2 -1
package/docs/upgrade.md
ADDED
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
# Upgrade Guide
|
|
2
|
+
|
|
3
|
+
This page covers the mechanics of upgrading Flair — the general path, valid across
|
|
4
|
+
versions. For **what changed in a specific release** (behavior changes, new surfaces,
|
|
5
|
+
breaking changes), see [`CHANGELOG.md`](../CHANGELOG.md) — each version has its own
|
|
6
|
+
`## [X.Y.Z]` section. Check the CHANGELOG entries between your current version and the
|
|
7
|
+
target version before upgrading anything you depend on in production.
|
|
8
|
+
|
|
9
|
+
There are two things you might be upgrading:
|
|
10
|
+
|
|
11
|
+
1. **A local npm install** — the common case: `flair` running on your own machine or a
|
|
12
|
+
VPS, installed via `npm install -g @tpsdev-ai/flair`.
|
|
13
|
+
2. **A Flair component deployed to a Harper Fabric cluster** — a different mechanism
|
|
14
|
+
(`flair deploy` / `flair upgrade --target`), covered separately below.
|
|
15
|
+
|
|
16
|
+
## Standard upgrade (local install)
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# 1. Back up first, always
|
|
20
|
+
flair backup > ~/flair-backup-$(date +%Y%m%d).json
|
|
21
|
+
|
|
22
|
+
# 2. Check what's outdated (doesn't install anything)
|
|
23
|
+
flair upgrade --check
|
|
24
|
+
|
|
25
|
+
# 3. Upgrade — installs, restarts, and verifies the new version is actually
|
|
26
|
+
# serving, all in one step (see "Upgrade is a transaction" below)
|
|
27
|
+
flair upgrade
|
|
28
|
+
|
|
29
|
+
# 4. Verify
|
|
30
|
+
flair status
|
|
31
|
+
flair doctor
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`flair upgrade` checks and upgrades the npm-global packages (`@tpsdev-ai/flair`,
|
|
35
|
+
`@tpsdev-ai/flair-mcp`) and, if present, the `openclaw-flair` plugin (via
|
|
36
|
+
`openclaw plugins install --force --pin`, not `npm install -g` — it needs OpenClaw's
|
|
37
|
+
own plugin loader). Pass `--all` to also see `flair-client` (normally hidden as a
|
|
38
|
+
transitive dependency). **Other integrations upgrade in their own ecosystem, not via
|
|
39
|
+
`flair upgrade`:** `pi-flair` (pi's plugin manager), `langgraph-flair` / `hermes-flair`
|
|
40
|
+
(pip / your Python package manager), `n8n-nodes-flair` (n8n's Community Nodes UI).
|
|
41
|
+
|
|
42
|
+
### Upgrade is a transaction
|
|
43
|
+
|
|
44
|
+
As of flair#635, `flair upgrade` is install → restart → verify →
|
|
45
|
+
rollback-on-failure, in one step — installing new code without restarting used
|
|
46
|
+
to leave the OLD process serving while the version on disk lied about what was
|
|
47
|
+
actually running:
|
|
48
|
+
|
|
49
|
+
- **Restart happens automatically** after install. Pass `--no-restart` to
|
|
50
|
+
stage the new packages without bouncing the process yet (the old
|
|
51
|
+
opt-in `--restart` flag still parses but is now a no-op — restart is the
|
|
52
|
+
default).
|
|
53
|
+
- **Post-restart verification** (skip with `--no-verify`) confirms the
|
|
54
|
+
restarted instance answers `/Health`, that an authenticated request
|
|
55
|
+
round-trips, and that the reported running version matches what was just
|
|
56
|
+
installed.
|
|
57
|
+
- **On verification failure**, `flair upgrade` automatically reinstalls the
|
|
58
|
+
previously-running `@tpsdev-ai/flair` version, restarts again, and
|
|
59
|
+
re-verifies — then exits nonzero with a clear report of what failed. If the
|
|
60
|
+
rollback itself fails verification, it says so loudly and points at the
|
|
61
|
+
concrete pre-upgrade snapshot path (see "Pre-upgrade snapshot" below)
|
|
62
|
+
instead of retrying in a loop — see [Downgrade](#downgrade) for the
|
|
63
|
+
restore procedure.
|
|
64
|
+
|
|
65
|
+
### Pre-upgrade snapshot (opt-in)
|
|
66
|
+
|
|
67
|
+
flair#637 added a **physical**, byte-exact snapshot of `~/.flair/data` — the whole
|
|
68
|
+
directory (RocksDB files, keys, config, `admin-pass`), not just the logical records a
|
|
69
|
+
`flair backup` JSON export covers. As of 2026-07-08 this is **opt-in**: pass
|
|
70
|
+
`--snapshot` to `flair upgrade` to take one before the package swap. It's off by
|
|
71
|
+
default — matching how Harper's own upgrade CLI behaves (it recommends a backup before
|
|
72
|
+
proceeding, but never auto-tars your data directory for you) — because the
|
|
73
|
+
tested-downgrade guarantee below already covers the failure mode a snapshot exists
|
|
74
|
+
for, and the old opt-out default meant every upgrade paid the cost (the data dir can
|
|
75
|
+
be 800MB+; keep-last-3 retention meant up to ~2.5GB of snapshots sitting around)
|
|
76
|
+
whether or not you wanted it.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
flair upgrade --snapshot
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
Snapshotting data before upgrade...
|
|
84
|
+
✅ Snapshot: ~/.flair/upgrade-snapshots/flair-data-2026-07-08T14-32-01-118Z.tar.gz (842.3 MB)
|
|
85
|
+
Restore: flair snapshot restore "~/.flair/upgrade-snapshots/flair-data-2026-07-08T14-32-01-118Z.tar.gz"
|
|
86
|
+
Pruned 1 older snapshot (keeping last 3)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
If you omit `--snapshot` (the default) and a data directory exists, `flair upgrade`
|
|
90
|
+
prints a non-blocking recommendation instead of silently skipping it — it never
|
|
91
|
+
prompts or blocks, so scripted/non-interactive upgrades are unaffected:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
No pre-upgrade snapshot will be taken.
|
|
95
|
+
To capture one first: `flair snapshot create` (physical) or `flair backup` (logical export), or re-run with --snapshot.
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
- **Location:** `~/.flair/upgrade-snapshots/flair-data-<timestamp>.tar.gz` — owner-only
|
|
99
|
+
(`0600`), with every file inside it at its **original** mode (so a `0600` key or
|
|
100
|
+
`admin-pass` file stays `0600` after a restore, not whatever tar's default would be).
|
|
101
|
+
- **Retention:** keeps the newest 3 snapshots, prunes older ones automatically after
|
|
102
|
+
each successful snapshot — whether taken via `--snapshot` or `flair snapshot create`
|
|
103
|
+
(below); both draw from the same `~/.flair/upgrade-snapshots/` pool.
|
|
104
|
+
- **Consistency:** when a snapshot is taken (`--snapshot`, or `flair snapshot create`),
|
|
105
|
+
Flair is briefly stopped, snapshotted, and immediately restarted on the same version
|
|
106
|
+
before anything else happens — a plain file copy of a *running* Harper's data
|
|
107
|
+
directory isn't guaranteed point-in-time consistent (Harper 5.x stores tables in
|
|
108
|
+
RocksDB — an LSM engine whose WAL, MANIFEST, and SST files can be
|
|
109
|
+
mid-write/mid-compaction), so the snapshot always happens against a quiesced
|
|
110
|
+
directory. During an upgrade this means a short stop/start blip even with
|
|
111
|
+
`--no-restart` — the snapshot's correctness doesn't depend on whether you want a
|
|
112
|
+
restart *after* the upgrade, those are separate questions. (A native Harper backup
|
|
113
|
+
operation, `get_backup`, was evaluated and rejected here — see the code comment
|
|
114
|
+
above `createDataSnapshot` in `src/cli.ts` for why: it backs up one table/schema at a
|
|
115
|
+
time over the running HTTP API, not the whole data directory, and would be strictly
|
|
116
|
+
less complete than a plain file copy.)
|
|
117
|
+
- **Failure is a hard stop when requested:** if you passed `--snapshot` and the
|
|
118
|
+
snapshot itself fails (disk full, permissions, etc.), the upgrade aborts before any
|
|
119
|
+
package changes — no packages are swapped, Flair is restarted on the version it was
|
|
120
|
+
already running.
|
|
121
|
+
|
|
122
|
+
#### `flair snapshot` — the standalone command
|
|
123
|
+
|
|
124
|
+
The same mechanism is available on its own, independent of upgrading:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
flair snapshot create # take one now (default: ~/.flair/data)
|
|
128
|
+
flair snapshot create --data-dir <path>
|
|
129
|
+
flair snapshot list # list what's under ~/.flair/upgrade-snapshots/
|
|
130
|
+
flair snapshot list --json
|
|
131
|
+
flair snapshot restore <path> # stop Flair, replace the data dir, restart
|
|
132
|
+
flair snapshot restore <path> --yes # skip the confirmation prompt
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`flair snapshot restore` is destructive — it deletes the current data directory and
|
|
136
|
+
replaces it with the snapshot's contents — so it asks for confirmation unless `--yes`
|
|
137
|
+
is passed, and refuses outright in a non-interactive shell without `--yes` (it will
|
|
138
|
+
never silently destroy data on an unattended run). Symlinks and file modes extract
|
|
139
|
+
exactly as the snapshot recorded them; nothing outside the original data directory is
|
|
140
|
+
ever touched.
|
|
141
|
+
|
|
142
|
+
**`flair snapshot` (physical) vs `flair backup`/`flair restore` (logical) — not the
|
|
143
|
+
same thing:**
|
|
144
|
+
|
|
145
|
+
| | `flair snapshot` | `flair backup` / `flair restore` |
|
|
146
|
+
|---|---|---|
|
|
147
|
+
| What | Byte-exact tar.gz of `~/.flair/data` | JSON export of Agent/Memory/Soul records |
|
|
148
|
+
| Scope | Everything — RocksDB files, keys, config, `admin-pass` | Just the records, over the HTTP API |
|
|
149
|
+
| Portability | Same host, same Flair/Harper version | Portable across hosts and versions |
|
|
150
|
+
| Use for | Undoing an upgrade that wrote data the old version can't read | Migrating data, or a lightweight logical restore |
|
|
151
|
+
|
|
152
|
+
Use whichever (or both) fits — they're complementary, not redundant, which is why they
|
|
153
|
+
live under separate command namespaces instead of overloading `restore`.
|
|
154
|
+
|
|
155
|
+
If you'd rather upgrade by hand instead of `flair upgrade`:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
npm install -g @tpsdev-ai/flair@latest
|
|
159
|
+
npm install -g @tpsdev-ai/flair-mcp@latest # if installed
|
|
160
|
+
flair restart
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`flair doctor` flags issues after an upgrade (stale embeddings, hash-fallback rows,
|
|
164
|
+
connectivity problems) and can auto-remediate some of them with `flair doctor --fix`
|
|
165
|
+
(`--dry-run` to preview first).
|
|
166
|
+
|
|
167
|
+
## Upgrading a Fabric-deployed instance
|
|
168
|
+
|
|
169
|
+
A Flair instance deployed to a Harper Fabric cluster isn't a local npm package — it's a
|
|
170
|
+
component pushed via `flair deploy`. Upgrade it in place with:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
FABRIC_USER=<admin> FABRIC_PASSWORD=<pass> \
|
|
174
|
+
flair upgrade --target https://<fabric-node>/<instance-name>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
(or `--fabric-password-file <path>` instead of the `FABRIC_PASSWORD` env var — reads the
|
|
178
|
+
password from a file, chmod 600). This resolves the target version (latest published
|
|
179
|
+
`@tpsdev-ai/flair`, or pin one with `--version`), stages a clean deployable with the
|
|
180
|
+
required `@harperfast/harper` version pin applied (`--harper-version` to override),
|
|
181
|
+
confirms the staged Harper build before deploying, then reuses `flair deploy` to push it
|
|
182
|
+
and verifies the result. `--check` shows the version diff and plan without deploying
|
|
183
|
+
anything; `--yes` skips the confirmation prompt for scripted use.
|
|
184
|
+
|
|
185
|
+
Inline `--fabric-user`/`--fabric-password` flags also work — **discouraged: both leak to
|
|
186
|
+
shell history and `ps`** for the life of the process, so avoid them on shared/multi-user
|
|
187
|
+
hosts:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
flair upgrade --target https://<fabric-node>/<instance-name> \
|
|
191
|
+
--fabric-user <admin> --fabric-password <pass>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Post-deploy fleet verify
|
|
195
|
+
|
|
196
|
+
As of flair#636, both `flair deploy` and `flair upgrade --target` automatically run a
|
|
197
|
+
fleet convergence sweep after a successful deploy — Harper's own "Successfully
|
|
198
|
+
deployed" (and the served-API verify above) only confirm the *origin* node; nothing
|
|
199
|
+
previously checked that peers actually converged, which is exactly the gap that let
|
|
200
|
+
the 0.21.0 deploy report success while a peer was still throwing replication errors.
|
|
201
|
+
|
|
202
|
+
The sweep hits the origin plus every Flair federation peer on file (`GET
|
|
203
|
+
/FederationPeers`) and checks health, auth, and version. Skip it with
|
|
204
|
+
`--no-fleet-verify`, or run it standalone against any already-deployed instance:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
FABRIC_USER=<admin> FABRIC_PASSWORD=<pass> \
|
|
208
|
+
flair fleet verify --target https://<fabric-node>/<instance-name>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
(inline `--fabric-user`/`--fabric-password` also work but are discouraged — see above.)
|
|
212
|
+
|
|
213
|
+
Exit codes:
|
|
214
|
+
|
|
215
|
+
| Code | Meaning |
|
|
216
|
+
|------|---------|
|
|
217
|
+
| 0 | All nodes verified: healthy, authenticated, and version-matched |
|
|
218
|
+
| 1 | Origin failed (unreachable, unauthenticated, or wrong version) |
|
|
219
|
+
| 2 | Origin OK, but a reachable peer is running a different version (skew) |
|
|
220
|
+
| 3 | Origin OK, no skew among reachable peers, but a peer couldn't be verified at all (unreachable, auth rejected, or no endpoint on file) |
|
|
221
|
+
|
|
222
|
+
**What "peer" means here — read before trusting a green sweep:** this checks
|
|
223
|
+
*Flair's own* federation peer table, not Harper Fabric's own cluster-replication
|
|
224
|
+
nodes. Harper's `cluster_status` operation (the one that would answer "what nodes are
|
|
225
|
+
in this cluster and are they in sync") is harper-pro-only and unavailable in the OSS
|
|
226
|
+
`@harperfast/harper` build this CLI ships — there is no way for this CLI to enumerate
|
|
227
|
+
Fabric's own replication topology, on the origin or anywhere else. A Fabric replica
|
|
228
|
+
that was never separately paired as a Flair federation peer (`flair federation pair`)
|
|
229
|
+
is invisible to this sweep: `0 peers known` means "0 peers on file," never "0 peers
|
|
230
|
+
exist." A peer with no usable endpoint is reported `unverifiable` — never silently
|
|
231
|
+
dropped, never shown green. The sweep also needs Basic-auth credentials
|
|
232
|
+
(`FABRIC_USER`/`FABRIC_PASSWORD` env, or the discouraged inline
|
|
233
|
+
`--fabric-user`/`--fabric-password`) to authenticate each peer probe; a token-only
|
|
234
|
+
(`--fabric-token`) deploy skips it with a note instead of a silent no-op.
|
|
235
|
+
|
|
236
|
+
## Re-embedding after an upgrade
|
|
237
|
+
|
|
238
|
+
Two situations require a re-embed pass, and `flair doctor` will flag both:
|
|
239
|
+
|
|
240
|
+
- **The embedding model changed** between versions — old memories carry vectors from
|
|
241
|
+
the previous model and won't compare correctly against new ones.
|
|
242
|
+
- **Harper's internal vector storage changed across a version bump** (this has
|
|
243
|
+
happened between Harper point releases, e.g. HNSW-index-internal changes) — even
|
|
244
|
+
with the same embedding model, stored vectors may need to be regenerated to match
|
|
245
|
+
what the new Harper build expects.
|
|
246
|
+
|
|
247
|
+
`flair doctor` reports the counts:
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
⚠️ 49 memories have hash-fallback embeddings (512-dim)
|
|
251
|
+
Current model produces 768-dim vectors
|
|
252
|
+
Run: flair reembed
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Fix with:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
flair reembed # all agents, all stale rows
|
|
259
|
+
flair reembed --stale-only # only mismatched-model-tag rows
|
|
260
|
+
flair reembed --agent <id> # scope to one agent
|
|
261
|
+
flair reembed --dry-run # show the count without writing
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
This runs in the background — the server stays available while it re-embeds. This is
|
|
265
|
+
also the step CI's `upgrade-smoke` job exercises directly: it upgrades a running
|
|
266
|
+
instance from the latest published version to the candidate build, then runs
|
|
267
|
+
`flair reembed` before asserting old memories are still searchable and new writes
|
|
268
|
+
round-trip. See the `upgrade-smoke` job in
|
|
269
|
+
[`.github/workflows/test.yml`](../.github/workflows/test.yml) for the exact sequence
|
|
270
|
+
if you want to see it scripted end-to-end.
|
|
271
|
+
|
|
272
|
+
## Version compatibility
|
|
273
|
+
|
|
274
|
+
- **Data format:** Flair stores data in Harper's native format; Harper maintains
|
|
275
|
+
backward compatibility within a major line. Cross-Harper-version data compatibility
|
|
276
|
+
is exactly what `upgrade-smoke` exists to catch regressions in — check the CHANGELOG
|
|
277
|
+
for any called-out breaking change before a major jump.
|
|
278
|
+
- **Keys:** Ed25519 keypairs are version-independent. No key migration is ever needed
|
|
279
|
+
between Flair versions.
|
|
280
|
+
- **Config:** `~/.flair/config.yaml` format is additive — new options fall back to
|
|
281
|
+
defaults when absent, old options aren't removed out from under you.
|
|
282
|
+
|
|
283
|
+
## Rollback
|
|
284
|
+
|
|
285
|
+
If an upgrade causes problems immediately after upgrading (code-level, not data):
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
# Install a specific previous version (substitute your last known-good)
|
|
289
|
+
npm install -g @tpsdev-ai/flair@<previous-version>
|
|
290
|
+
flair restart
|
|
291
|
+
|
|
292
|
+
# If data looks wrong, restore from your pre-upgrade backup
|
|
293
|
+
flair restore < ~/flair-backup-<date>.json
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
`flair upgrade` does this automatically on a failed post-restart verification — see
|
|
297
|
+
"Upgrade is a transaction" above. This section is for doing it by hand, e.g. after
|
|
298
|
+
`--no-verify`, or after problems surface later than the automatic check catches.
|
|
299
|
+
|
|
300
|
+
### Known issue — upgrading *from* an older version can still report a false rollback
|
|
301
|
+
|
|
302
|
+
The 0.25.1 fix (see [`CHANGELOG.md`](../CHANGELOG.md)) makes `flair upgrade` resolve a
|
|
303
|
+
credentials-only post-restart-verification failure to `healthy-unverified` instead of
|
|
304
|
+
rolling back. That fix is **forward-only**: it lives in the *new* CLI code, but an
|
|
305
|
+
upgrade's post-restart verification is run by the CLI that was already installed
|
|
306
|
+
*before* the upgrade — the old code, which doesn't have the fix.
|
|
307
|
+
|
|
308
|
+
So on a machine upgrading **from** a version older than 0.25.1, with no
|
|
309
|
+
`~/.flair/admin-pass` and no agent key on disk, the old verifier still can't
|
|
310
|
+
authenticate to the authenticated `/HealthDetail` check. It reports a false
|
|
311
|
+
`post-restart verification failed … 403: no credentials sent`, triggers an automatic
|
|
312
|
+
rollback, and that rollback's own re-verify hits the identical missing-credential
|
|
313
|
+
wall — leaving you with `ROLLBACK ALSO FAILED VERIFICATION — instance state is
|
|
314
|
+
UNKNOWN`, even though the instance was healthy the entire time (a 403 means the server
|
|
315
|
+
answered).
|
|
316
|
+
|
|
317
|
+
**Workarounds:**
|
|
318
|
+
|
|
319
|
+
- Skip verification for this one upgrade: `flair upgrade --no-verify` — safe as long
|
|
320
|
+
as you've confirmed the instance is reachable first (`flair status`).
|
|
321
|
+
- Or provision credentials before upgrading, so the verifier can authenticate:
|
|
322
|
+
`flair init`, or export `FLAIR_ADMIN_PASS`.
|
|
323
|
+
|
|
324
|
+
This gap only exists while crossing into 0.25.1. Once you're running 0.25.1 or later,
|
|
325
|
+
the verifier itself resolves a credentials-only failure to `healthy-unverified`
|
|
326
|
+
instead of rolling back, so it cannot recur on subsequent upgrades.
|
|
327
|
+
|
|
328
|
+
### Known issue — upgrading *from* 0.26.0 or older can leave the server stopped
|
|
329
|
+
|
|
330
|
+
On Linux (and macOS without a launchd plist), versions up to and including 0.26.0
|
|
331
|
+
had a bug in the upgrade path's port-based stop step: it matched *any* process
|
|
332
|
+
with a socket on the Flair port — including the upgrading CLI's **own** keep-alive
|
|
333
|
+
connections left by the credential pre-flight — and SIGTERM'd itself mid-restart.
|
|
334
|
+
The visible symptom: `Restarting Flair... Stopping...` and then the command dies
|
|
335
|
+
(SIGTERM, exit 143) before `Starting...`, leaving the server down even though the
|
|
336
|
+
package upgraded fine (flair#800).
|
|
337
|
+
|
|
338
|
+
The fix (listening-socket filter + self-PID guard) is **forward-only** for the same
|
|
339
|
+
reason as above: the restart is performed by the *old*, already-installed CLI.
|
|
340
|
+
|
|
341
|
+
**Workarounds when upgrading from ≤ 0.26.0:**
|
|
342
|
+
|
|
343
|
+
- Prefer `flair upgrade --no-verify` — skips the credential pre-flight whose
|
|
344
|
+
keep-alive sockets trigger the self-kill (validated end-to-end).
|
|
345
|
+
- If you already hit it (upgrade "finished" but the server is down): run
|
|
346
|
+
`flair start` — not `restart` — and you're on the new version. Nothing was lost.
|
|
347
|
+
|
|
348
|
+
## Downgrade
|
|
349
|
+
|
|
350
|
+
Rolling back the **package** (above) assumes the data on disk is fine — only the new
|
|
351
|
+
code was the problem. If the new version actually **wrote data in a way the old
|
|
352
|
+
version can't read**, package rollback alone isn't enough. This is what the
|
|
353
|
+
flair#637 pre-upgrade snapshot exists for.
|
|
354
|
+
|
|
355
|
+
### Procedure
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
# 1. Find the snapshot (the exact path/command `flair upgrade --snapshot` printed
|
|
359
|
+
# when it ran, or list them yourself):
|
|
360
|
+
flair snapshot list
|
|
361
|
+
|
|
362
|
+
# 2. Restore it — this stops Flair, replaces ~/.flair/data, and restarts:
|
|
363
|
+
flair snapshot restore ~/.flair/upgrade-snapshots/flair-data-<timestamp>.tar.gz
|
|
364
|
+
|
|
365
|
+
# 3. Install the previous version
|
|
366
|
+
npm install -g @tpsdev-ai/flair@<previous-version>
|
|
367
|
+
flair restart
|
|
368
|
+
|
|
369
|
+
# 4. Verify
|
|
370
|
+
flair status
|
|
371
|
+
flair doctor
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
`flair snapshot restore` does the stop/replace/restart in one step (confirming before
|
|
375
|
+
the destructive replace unless you pass `--yes`); the equivalent by hand is `flair
|
|
376
|
+
stop && rm -rf ~/.flair/data && mkdir -p ~/.flair/data && tar -xzf
|
|
377
|
+
<snapshot> -C ~/.flair/data && flair start`, in case you'd rather not use the command.
|
|
378
|
+
|
|
379
|
+
If you don't have a snapshot (upgraded without `--snapshot`, or on a version from
|
|
380
|
+
before flair#637 shipped it), there is no tested way back short of restoring from a
|
|
381
|
+
`flair backup` JSON export on the older version — do not assume an untested downgrade
|
|
382
|
+
boot will work.
|
|
383
|
+
|
|
384
|
+
### Does the previous version actually boot against newer data? (tested, not assumed)
|
|
385
|
+
|
|
386
|
+
This used to be aspirational — nobody had actually checked. `test/compat/downgrade-boot.test.ts`
|
|
387
|
+
now checks it for real, nightly, alongside the mixed-version federation suite (both run
|
|
388
|
+
from `.github/workflows/federation-compat.yml`'s `bun test test/compat/`): it boots the
|
|
389
|
+
current build, writes a memory and a presence row, stops it *without* wiping the data
|
|
390
|
+
directory, then boots the last **npm-published** `@tpsdev-ai/flair` against that exact
|
|
391
|
+
same directory and confirms it comes up healthy and can read both rows back.
|
|
392
|
+
|
|
393
|
+
**As observed when this suite was added (2026-07-08):** the npm-published baseline
|
|
394
|
+
(0.21.0) boots cleanly against data written by a HEAD build roughly 14 commits ahead of
|
|
395
|
+
it (several security-hardening and CLI-behavior changes, no Flair schema migration, and
|
|
396
|
+
only a patch-level `@harperfast/harper` bump, 5.1.15 → 5.1.17) — both the memory and
|
|
397
|
+
presence rows written by the newer build were readable through the older build's own
|
|
398
|
+
HTTP surface after the downgrade boot. **No downgrade break has been found across that
|
|
399
|
+
gap.**
|
|
400
|
+
|
|
401
|
+
This is *not* a blanket "downgrade is always safe" guarantee for every future release —
|
|
402
|
+
it's a live, continuously-checked claim. If `test/compat/downgrade-boot.test.ts` starts
|
|
403
|
+
failing (a real schema-incompatible change landing without a documented break), this
|
|
404
|
+
section and the test's own assertions get updated together to say so explicitly, the
|
|
405
|
+
same way this paragraph does today. Check the suite's latest nightly run (or the
|
|
406
|
+
CHANGELOG for an explicit "no downgrade past X" note) before relying on this for a jump
|
|
407
|
+
you haven't personally tested.
|
|
408
|
+
|
|
409
|
+
## See also
|
|
410
|
+
|
|
411
|
+
- [`CHANGELOG.md`](../CHANGELOG.md) — what actually changed, version by version.
|
|
412
|
+
- [`docs/releasing.md`](releasing.md) — how a release gets published in the first
|
|
413
|
+
place (staged npm publish with 2FA approval), if you're curious why a new version
|
|
414
|
+
shows up when it does.
|
|
415
|
+
- [`docs/deployment.md`](deployment.md) — initial install / deployment, as opposed to
|
|
416
|
+
upgrading an existing one.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tpsdev-ai/flair",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"packageManager": "bun@1.3.10",
|
|
5
5
|
"description": "Identity, memory, and soul for AI agents. Cryptographic identity (Ed25519), semantic memory with local embeddings, and persistent personality — all in a single process.",
|
|
6
6
|
"type": "module",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"dist/",
|
|
33
33
|
"schemas/",
|
|
34
34
|
"templates/",
|
|
35
|
+
"docs/",
|
|
35
36
|
"config.yaml",
|
|
36
37
|
"LICENSE",
|
|
37
38
|
"README.md",
|