@tpsdev-ai/flair 0.25.4 → 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 +998 -50
- package/dist/doctor-client.js +47 -0
- package/dist/rem/runner.js +60 -3
- package/dist/resources/MemoryDedupStats.js +161 -0
- package/dist/resources/dedup-cluster.js +145 -0
- package/dist/resources/health.js +33 -1
- package/dist/resources/mcp-oauth.js +4 -2
- 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
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Flair supply-chain policy
|
|
2
|
+
|
|
3
|
+
How we keep Flair's published packages safe from upstream supply-chain attacks. This document describes both our policies and the automation that enforces them.
|
|
4
|
+
|
|
5
|
+
> **Why this exists.** Mini Shai-Hulud worm attack (Apr 30 2026, Intercom npm + Composer PHP). Sleeper malicious Ruby gems and Go modules (May 1). NuGet typosquats with crypto-wallet stealers (May 6). The window between "package compromised" and "compromise widely flagged" is the entire risk surface, and it's been hours-to-days, not weeks. As Flair adds integration adapters across more ecosystems, our exposure grows; this is the policy + automation that bounds it.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Policies
|
|
10
|
+
|
|
11
|
+
### 1. Bake-time policy: 7 days minimum for new dep versions
|
|
12
|
+
|
|
13
|
+
We don't pull in any newly-published dep version for **at least 7 days** after its publish date.
|
|
14
|
+
|
|
15
|
+
- The most-attacked window is "compromise published, defenders haven't yet noticed." Most malicious packages get flagged by Socket.dev, npm advisory, GitHub security advisory, or human reports within 1-7 days. Our delay puts us behind that detection front.
|
|
16
|
+
- pnpm 11 shipped this as a default at 1 day (May 4 2026). We chose 7 as a more conservative posture for a security-adjacent project.
|
|
17
|
+
- Workspace-internal `@tpsdev-ai/*` deps are exempt. We publish ourselves; we have direct visibility into our own changes; our 0.8.0 → 0.8.1 patch turnaround was same-day and we want to keep that latitude.
|
|
18
|
+
- Tunable via `FLAIR_DEP_MIN_AGE_DAYS` env var if a specific run needs a different threshold. Don't bypass; document the exception.
|
|
19
|
+
|
|
20
|
+
#### 1a. Keep-current allow-list
|
|
21
|
+
|
|
22
|
+
Some deps are tightly coupled to Flair's runtime correctness — Harper bug fixes and security patches land in `@harperfast/harper`, embedding-pipeline fixes land in `harper-fabric-embeddings`. We accept the bake-time risk and pull these eagerly. Current allow-list:
|
|
23
|
+
|
|
24
|
+
| Package | Why kept current |
|
|
25
|
+
|---------|------------------|
|
|
26
|
+
| `@harperfast/harper` | Foundational. Vector-index and HNSW correctness fixes land here; we want them ASAP. High-volume upstream, fast detection if compromised. |
|
|
27
|
+
| `harper-fabric-embeddings` | Embedding model loader. Coupled to Harper version. Same trust-and-volume reasoning. |
|
|
28
|
+
| `@harperfast/oauth` | Same high-trust `@harperfast/*` owner as `@harperfast/harper`. Used ONLY by the **default-OFF** native-MCP OAuth surface (`FLAIR_MCP_OAUTH`), which dynamically imports it only when the flag is on — it is **not loaded in the shipped default build**, so bake-time exposure is zero until an operator explicitly opts in. Pinned to the exact version whose `withMCPAuth` API the surface was built against; the API surface (not a floating range) is what we depend on. |
|
|
29
|
+
|
|
30
|
+
Adding to this list is a deliberate decision. The bar:
|
|
31
|
+
- The upstream is well-known and high-volume (gets eyeballs fast).
|
|
32
|
+
- We have a direct reason to want patches as soon as published (a known bug we're tracking, a security patch we need, or correctness coupling).
|
|
33
|
+
- We accept that a freshly-malicious version could land in our build before broader detection.
|
|
34
|
+
|
|
35
|
+
Document any addition here, in this section, alongside the package name. The doc is the audit trail.
|
|
36
|
+
|
|
37
|
+
Override per-run via `FLAIR_DEP_KEEP_CURRENT="pkg1,pkg2,@scope/pkg3"` env (additive — adds to the default allow-list, doesn't replace it).
|
|
38
|
+
|
|
39
|
+
### 2. Exact-version pinning for production deps
|
|
40
|
+
|
|
41
|
+
Every `dependencies` entry in any `package.json` must be a single concrete version (`"5.0.9"`), not a range (`"^5.0"`, `"~5.0.9"`, `">=5"`). Range specifiers expose us to silent supply-chain swaps every install — exactly the surface attackers exploit.
|
|
42
|
+
|
|
43
|
+
- `peerDependencies` may use ranges (host-provided; never installed by us). `devDependencies` are also exact-pinned for build reproducibility, though they don't ship in our published tarballs.
|
|
44
|
+
- `bun.lock` is committed and frozen-lockfile installed in CI. Any unintended dep drift fails the workspace-deps consistency gate.
|
|
45
|
+
- Pin updates happen via deliberate, test-gated PRs — never auto-merged. **Renovate is enabled** (`.github/renovate.json`) to *propose* these updates on a schedule, but it respects the bake-time cooldown (`minimumReleaseAge: "7 days"`, matching `FLAIR_DEP_MIN_AGE_DAYS`) and opens PRs only — `automerge` is off, so every bump flows through the full test suite + K&S review. Renovate uses `rangeStrategy: "pin"` so it proposes exact-version bumps (never re-widens to ranges) and shares the keep-current allow-list with `check-dep-ages.mjs`. Vulnerability alerts bypass the cooldown so security fixes aren't delayed.
|
|
46
|
+
|
|
47
|
+
### 3. Internal dep version lockstep
|
|
48
|
+
|
|
49
|
+
Every `@tpsdev-ai/*` dep declared in any workspace package must match the version that workspace package ships. Enforced by `scripts/check-workspace-deps.mjs` in the test-unit CI job.
|
|
50
|
+
|
|
51
|
+
- Why: prevents the v0.8.0 bug shape where `openclaw-flair@0.8.0` declared `@tpsdev-ai/flair-client@0.5.0`, shipping a 3-version-old client to consumers of the published tarball.
|
|
52
|
+
- See `notes/dogfood-log.md` for the full incident.
|
|
53
|
+
|
|
54
|
+
### 4. Workspace `bun.lock` is the source of truth
|
|
55
|
+
|
|
56
|
+
Direct `bun.lock` regenerations (e.g. `rm bun.lock && bun install`) are discouraged. They can rewrite git URLs to use ssh-protocol resolution that breaks Docker builds (the libsignal incident on PR #368) and reset other resolution choices.
|
|
57
|
+
|
|
58
|
+
- Instead: use `bun install` with the existing lockfile, or surgical edits for known bug fixes.
|
|
59
|
+
- All lockfile changes are reviewed; any cross-protocol or cross-version churn beyond the stated scope of the PR is a red flag.
|
|
60
|
+
|
|
61
|
+
### 5. Socket.dev CI job is mandatory
|
|
62
|
+
|
|
63
|
+
Every PR runs the Socket.dev Supply Chain check. Failure blocks merge. The Socket scan complements the bake-time policy — Socket catches *known* compromises; the 7-day delay catches *not-yet-known* ones.
|
|
64
|
+
|
|
65
|
+
### 6. Publish surface
|
|
66
|
+
|
|
67
|
+
Only Nathan publishes to npm (per the existing MFA boundary). Flint preps the release commit + version bump + CHANGELOG; Nathan runs `./scripts/release.sh <ver> --publish` from his laptop.
|
|
68
|
+
|
|
69
|
+
- The build host is not logged into npm by design.
|
|
70
|
+
- A planned post-publish smoke job will add an automated round-trip check after each publish to ensure cross-package resolution works on the actually-published artifacts.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Automation
|
|
75
|
+
|
|
76
|
+
### `.github/renovate.json` — deliberate, cooldown-gated update proposals
|
|
77
|
+
|
|
78
|
+
Renovate opens PRs to propose dependency updates so we don't drift behind upstream indefinitely — but on our terms, not the registry's. It is configured to never auto-merge (`automerge: false`), to pin (`rangeStrategy: "pin"`, consistent with §2), and to respect the bake-time cooldown (`minimumReleaseAge: "7 days"`, matching `FLAIR_DEP_MIN_AGE_DAYS` in `check-dep-ages.mjs`) so it only proposes versions that have already cleared the detection window. Non-major updates are grouped; majors land as isolated PRs. The keep-current allow-list (`@harperfast/harper`, `harper-fabric-embeddings`, `@harperfast/oauth`) mirrors the script's `DEFAULT_KEEP_CURRENT` — keep the two in lockstep when either changes. Vulnerability alerts bypass the cooldown. Every Renovate PR still runs the full CI suite (including the bake-time and workspace-deps gates) and is K&S-reviewed before merge.
|
|
79
|
+
|
|
80
|
+
### `scripts/check-workspace-deps.mjs` (already shipped, PR #368)
|
|
81
|
+
|
|
82
|
+
Fails any PR where a workspace package declares an internal `@tpsdev-ai/*` dep at a version other than what that workspace package ships. Wired into the `test-unit` job.
|
|
83
|
+
|
|
84
|
+
### `scripts/check-dep-ages.mjs` (this PR)
|
|
85
|
+
|
|
86
|
+
Fails any PR with an external pinned production dep version published less than `FLAIR_DEP_MIN_AGE_DAYS` ago (default 7). Queries the npm registry's `time` map. Workspace-internal deps exempt. Wired into the `test-unit` job.
|
|
87
|
+
|
|
88
|
+
Configurable:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Run with a different threshold:
|
|
92
|
+
FLAIR_DEP_MIN_AGE_DAYS=14 node scripts/check-dep-ages.mjs
|
|
93
|
+
|
|
94
|
+
# Run against a private registry:
|
|
95
|
+
FLAIR_NPM_REGISTRY=https://my-registry.example/ node scripts/check-dep-ages.mjs
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Pre-commit secret-guard hook (already shipped, `ops/scripts/git-hooks/`)
|
|
99
|
+
|
|
100
|
+
Blocks at stage time:
|
|
101
|
+
- Secret-shaped filenames (`.pem`, `.key`, `.env*`, `*api-key*`, `*pat*`, `*secret*`, etc.)
|
|
102
|
+
- Embedded git clones added without a `.gitmodules` entry
|
|
103
|
+
- Any single staged file >2MB
|
|
104
|
+
|
|
105
|
+
Available in `ops/scripts/git-hooks/install.sh`. Required for any agent or operator with commit access.
|
|
106
|
+
|
|
107
|
+
### Flair pre-commit hook (`scripts/git-hooks/`)
|
|
108
|
+
|
|
109
|
+
Mirrors the CI test-unit gates locally so issues are caught at `git commit` time, not after the runner round-trip:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
./scripts/git-hooks/install.sh
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Runs three checks before each commit:
|
|
116
|
+
- `check-workspace-deps.mjs` — workspace internal-dep version lockstep
|
|
117
|
+
- `check-dep-ages.mjs` — supply-chain bake-time (≥7 days for external pinned deps)
|
|
118
|
+
- `check-impl-term-leaks.sh` — no Bead refs / impl labels in user-facing docs
|
|
119
|
+
|
|
120
|
+
Each check matches a CI gate exactly so the local and remote outcomes can't drift. Bypass with `git commit --no-verify` when warranted (rare; CI will still catch you). Skip just the dep-ages check (the slowest one, ~2-5s of registry fetches) with `FLAIR_PRECOMMIT_SKIP_DEP_AGES=1 git commit`.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Adopting this policy in a downstream project
|
|
125
|
+
|
|
126
|
+
If you're building on top of `@tpsdev-ai/flair-client` and want the same posture:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Copy the dep-age guard into your repo
|
|
130
|
+
curl -fsSL https://raw.githubusercontent.com/tpsdev-ai/flair/main/scripts/check-dep-ages.mjs \
|
|
131
|
+
-o scripts/check-dep-ages.mjs
|
|
132
|
+
chmod +x scripts/check-dep-ages.mjs
|
|
133
|
+
|
|
134
|
+
# Wire it into your CI as a fast pre-test step
|
|
135
|
+
- run: node scripts/check-dep-ages.mjs
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The script has no external dependencies — node 18+ is enough.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Exceptions and incident response
|
|
143
|
+
|
|
144
|
+
- **Bypass for known-good fresh dep:** set `FLAIR_DEP_MIN_AGE_DAYS=0` for the affected CI run AND open a PR to add a comment-row in this doc explaining the exception. Don't bypass silently.
|
|
145
|
+
- **Confirmed upstream compromise affecting Flair:** rotate any affected credential, revert the offending dep version, ship a patch release, file a public advisory at `github.com/tpsdev-ai/flair/security/advisories`. Notify Nathan immediately; don't act unilaterally.
|
|
146
|
+
- **Suspected (not confirmed) compromise:** open an issue with the evidence; treat it as P0 in our backlog until disproven.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## See also
|
|
151
|
+
|
|
152
|
+
- `notes/dogfood-log.md` — internal incidents that have shaped this policy
|
|
153
|
+
- `scripts/check-workspace-deps.mjs` — the workspace-internal dep consistency gate
|
|
154
|
+
- `scripts/check-dep-ages.mjs` — the bake-time dep guard
|
|
155
|
+
- `ops/scripts/git-hooks/pre-commit-secret-guard.sh` — pre-commit secret blocker (cross-repo)
|
|
156
|
+
- `scripts/git-hooks/pre-commit` + `scripts/git-hooks/install.sh` — flair-specific pre-commit (mirrors test-unit CI gates)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# System Requirements
|
|
2
|
+
|
|
3
|
+
Flair runs Harper v5 (a Node.js HTTP+storage runtime) plus a small CLI/MCP layer. This page documents what to expect at idle, with measured numbers from in-production deployments.
|
|
4
|
+
|
|
5
|
+
## Minimum
|
|
6
|
+
|
|
7
|
+
| Resource | Spec | Notes |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| RAM | 1 GB free | 500–800 MB resident is typical for a single-agent spoke. |
|
|
10
|
+
| Disk | 250 MB | Harper data dir grows ~50–200 MB per active agent over weeks. |
|
|
11
|
+
| Node | 22 LTS or 24 LTS | Native fetch + WebStreams. Verified on 22.22.x and 25.9.x. |
|
|
12
|
+
| Network | Outbound HTTPS | For federation-sync to a hub. Local-only deployments need none. |
|
|
13
|
+
|
|
14
|
+
## Measured at idle (single agent, no load)
|
|
15
|
+
|
|
16
|
+
| Host | RAM (RSS) | Data dir | Node | Uptime | Notes |
|
|
17
|
+
|---|---|---|---|---|---|
|
|
18
|
+
| Mac mini (16 GB) | 740 MB daemon + ~175 MB across 4 flair-mcp clients = ~915 MB total | 163 MB | 25.9.0 | 35 min | Federation hub; 4 local agents. |
|
|
19
|
+
| Linux VM (19 GB pool) | 500 MB | 88 MB | 22.22.0 | 3d 20h | Federation spoke; 1 agent. |
|
|
20
|
+
| Linux VM (19 GB pool) | (not running) | 71 MB | 22.22.1 | — | Linux deps issue (backlog). |
|
|
21
|
+
|
|
22
|
+
## What drives the numbers
|
|
23
|
+
|
|
24
|
+
- **Embedding cache.** First semantic search per cold daemon loads `nomic-embed-text-v1.5` into memory (~270 MB). Subsequent searches reuse it. If you disable embeddings (text-only search), strip ~270 MB.
|
|
25
|
+
- **HNSW index.** In-memory vector index over the agent's memories. Grows linearly with memory count; expect ~1 KB per memory plus the 768-dim vector (~1.5 KB).
|
|
26
|
+
- **Harper transaction log.** Bounded by retention window; grows during writes, compacts on idle.
|
|
27
|
+
- **MCP clients.** Each `flair-mcp` subprocess holds ~40–50 MB. Long-lived MCP host (Claude Code) restarts spawn fresh ones; orphaned ones from the host crashing should be cleaned up by the parent-exit watcher (PR pending).
|
|
28
|
+
|
|
29
|
+
## Scaling expectations
|
|
30
|
+
|
|
31
|
+
The numbers above are 1-agent steady state. Per additional agent on the same daemon:
|
|
32
|
+
|
|
33
|
+
- ~50 MB additional RSS (per-agent HNSW index + small per-agent caches).
|
|
34
|
+
- ~10–30 MB additional data-dir growth per week of active use.
|
|
35
|
+
|
|
36
|
+
A 4-agent Mac mini at full embeddings + federation runs comfortably in 1 GB. An 8-agent host is fine in 2 GB. Multi-org hubs with hundreds of agents would want measured sizing — file an issue or join the Discord.
|
|
37
|
+
|
|
38
|
+
## Known constraints
|
|
39
|
+
|
|
40
|
+
- **Free Fabric tier.** ~512 MB plan ceiling. The full embedding model + HNSW + Harper is tight at that ceiling for a multi-agent spoke; a 1-agent personal spoke fits. Larger deployments (Phase 2 SLM-summarization, multi-agent hubs) require a paid Fabric tier or self-host.
|
|
41
|
+
- **Cold-start.** Embedding model load is ~3–5 s on Mac arm64, ~8–12 s on commodity Linux x86. Subsequent operations are warm.
|
|
42
|
+
- **No GPU required.** Embeddings run on CPU. HNSW is in-memory and CPU-only. GPU only matters if you deploy a Phase 2 SLM-based summarizer (separate process — see [bridges.md](./bridges.md#phase-2-summary-service)).
|
package/docs/the-team.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# The team behind Flair
|
|
2
|
+
|
|
3
|
+
This is how LifestyleLab actually runs the multi-agent team that builds Flair, TPS, and the rest of our open-source stack. We dogfood every part of what we ship — the agents themselves are the reference implementation.
|
|
4
|
+
|
|
5
|
+
If you're trying to run your own multi-agent team using Flair as the memory layer, this is the most concrete example you'll find. Steal whatever's useful.
|
|
6
|
+
|
|
7
|
+
## Roster
|
|
8
|
+
|
|
9
|
+
| Agent | Role | Runtime | Model | Where it runs |
|
|
10
|
+
|---|---|---|---|---|
|
|
11
|
+
| **Flint** | Strategy, product, PR review | Claude Code | Claude Opus | always-on local host |
|
|
12
|
+
| **Anvil** | Implementation, PR opener | OpenClaw | Claude Sonnet (API) | cloud VM |
|
|
13
|
+
| **Kern** | Architecture / perf review | OpenClaw | Open-source via Ollama | local inference box |
|
|
14
|
+
| **Sherlock** | Security review | OpenClaw | Open-source via Ollama (local-only) | local inference box |
|
|
15
|
+
| **Pulse** | EA / intel scanning / coordination | OpenClaw | Claude API | cloud VM |
|
|
16
|
+
| **Nathan** | Founder / product owner / human-in-the-loop | (human) | (human) | wherever |
|
|
17
|
+
|
|
18
|
+
Every agent has its own Ed25519 identity in Flair. They sign every memory write and every read. **Writes are isolated at the Flair API layer** — Sherlock can't accidentally (or maliciously) write into Pulse's memory, because the signature won't verify for anyone but Pulse. Reads are a different story: within one Flair instance, any verified agent can read any other agent's **non-private** memory — that's the shipped model (open-within-org read, no grant needed), not a gap. An agent keeps something genuinely sensitive owner-only by writing it with `visibility: private`. The hard access boundary is the **federation edge** (a separate Flair instance), not reads within one.
|
|
19
|
+
|
|
20
|
+
## How memory flows
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
┌────────────────────────┐
|
|
24
|
+
│ Flair (self-hosted) │
|
|
25
|
+
│ │
|
|
26
|
+
│ Write isolation + │
|
|
27
|
+
│ open-within-org read, │
|
|
28
|
+
│ enforced server-side │
|
|
29
|
+
│ via Ed25519 signing │
|
|
30
|
+
└─────────▲──────────────┘
|
|
31
|
+
│
|
|
32
|
+
┌─────────────────┬───────────────┼──────────────┬─────────────────┐
|
|
33
|
+
│ │ │ │ │
|
|
34
|
+
Flint Anvil Kern Sherlock Pulse
|
|
35
|
+
(local) (cloud VM) (inference box) (inference box) (cloud VM)
|
|
36
|
+
│ │ │ │ │
|
|
37
|
+
writes own writes own writes own writes own writes own
|
|
38
|
+
memories only memories only memories only memories only memories only
|
|
39
|
+
│ │ │ │ │
|
|
40
|
+
└─────────────────┴────────┬──────┴──────────────┴─────────────────┘
|
|
41
|
+
│
|
|
42
|
+
(every agent can read every other
|
|
43
|
+
agent's non-private memories —
|
|
44
|
+
`visibility: private` stays owner-only)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
No agent can write into another agent's memory — that's enforced server-side by signature verification, no exceptions. Reads are intentionally open within the org: when Flint commits a piece of strategy, any agent can find it on `memory_search` unless Flint marked it `private`. **By design** — the goal is relevance and findability across the team, not secrecy between roles. An agent that genuinely needs something to stay owner-only (a draft not ready for the team, a sensitive finding pre-disclosure) marks it `visibility: private`; everything else is fair game for any teammate to search.
|
|
48
|
+
|
|
49
|
+
When agents need to *coordinate* — a direct, targeted handoff rather than ambient searchable memory — they pass **explicit messages** through TPS mail (a separate signed delivery channel; see [tpsdev-ai/cli](https://github.com/tpsdev-ai/cli)). That's a different concern from memory visibility: TPS mail is for "I need you, specifically, to see this now"; Flair memory is the shared, searchable record everyone (except where `private`) can draw on later.
|
|
50
|
+
|
|
51
|
+
## Why these splits
|
|
52
|
+
|
|
53
|
+
### Different runtimes for different work
|
|
54
|
+
|
|
55
|
+
- **Claude Code (Flint)** — strategic + code review needs Opus's depth, and Claude Code's tool ecosystem (Bash, Read/Edit/Write, web fetch, MCP) is the broadest available for "do real work in a real repo."
|
|
56
|
+
- **OpenClaw (Anvil, Kern, Sherlock, Pulse)** — for agents that don't need a full IDE-grade tool surface but DO need stable always-on background capability with model-fallback routing, OpenClaw is the right runtime. It's also the one we built into TPS, so we eat our own dog food.
|
|
57
|
+
|
|
58
|
+
This isn't a value judgment of one runtime over another — it's about matching the runtime to what the agent has to do. **The whole team uses Flair as the memory layer regardless of runtime.** That's the point: Flair is orchestrator-agnostic.
|
|
59
|
+
|
|
60
|
+
### Local vs API for inference
|
|
61
|
+
|
|
62
|
+
- **Anvil + Pulse on the Anthropic API** — high-throughput implementation work and EA-shaped intel scanning need frontier model quality and consistent latency. Worth the API spend.
|
|
63
|
+
- **Kern + Sherlock on local Ollama** — review work can be slower and is bursty (a few PRs/day). Self-hosting on a local Ollama box means no rate limits, no session-locks, no third-party data exposure. Both run a large open-weight model (~120B class, permissively licensed) as primary, with smaller open models in the local fallback chain. **Sherlock is local-only as a deliberate privacy decision** — security findings are pre-disclosure-sensitive, not appropriate to send to any external inference provider.
|
|
64
|
+
- **Flint on Opus** — strategy + spec writing is rate-of-thought, not rate-of-tokens. Opus's reasoning depth matters more than throughput.
|
|
65
|
+
|
|
66
|
+
> **Note on migration safety nets:** when we moved the review agents off a previous cloud model onto local inference, we kept the old model as the *last* fallback for a short trial window to catch quality regressions, then removed it on a fixed date. If you're copying this setup, decide upfront whether you want a cloud safety net during your own migration — and remove it on a known date.
|
|
67
|
+
|
|
68
|
+
### Different hardware for different load
|
|
69
|
+
|
|
70
|
+
- **Always-on local host** — lightweight, runs the founder-facing agent + a watchdog + the local Flair Harper instance.
|
|
71
|
+
- **Local inference box** — heavier local inference on a workstation with strong unified memory / GPU. Hosts Ollama; the review agents target this box.
|
|
72
|
+
- **Cloud VMs** — agents that need internet-side work (intel fetching, opening GitHub PRs from a clean network space). Independent failure domain from the local stack.
|
|
73
|
+
|
|
74
|
+
## The handoff loop
|
|
75
|
+
|
|
76
|
+
Standard PR-shaped work flows like this:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
1. Nathan brings a need to Flint (Discord)
|
|
80
|
+
2. Flint writes a spec, files it in the planning repo, updates Beads
|
|
81
|
+
3. Flint mails Kern + Sherlock for arch + security review of the SPEC
|
|
82
|
+
(catch issues at design time, not after implementation)
|
|
83
|
+
4. K&S respond with concerns or sign-off
|
|
84
|
+
5. Flint refines spec, hands off to Anvil:
|
|
85
|
+
@Anvil <spec-path> branch:<name>. Open PR to main when done.
|
|
86
|
+
6. Anvil works on a feature branch, opens PR
|
|
87
|
+
7. Flint reviews PR, requests K&S review on the implementation
|
|
88
|
+
8. K&S review, comment, approve
|
|
89
|
+
9. CI green + 1 approval (or 2 for security-surface PRs) → merge
|
|
90
|
+
10. Pulse's intel cron picks up the merge in the next 24h cycle and
|
|
91
|
+
adds it to the team's situational awareness
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The rule that keeps this honest: **K&S approvals are individually load-bearing.** A "yes I approve" with a templated body that doesn't engage with the actual code is rejected — they have to write their own one-line rationale based on what they actually found. Otherwise the gate is theatrics. (This was a real lesson; we learned it the hard way after a rubber-stamp made it into the audit log.)
|
|
95
|
+
|
|
96
|
+
## How Flair fits in
|
|
97
|
+
|
|
98
|
+
Flair is the connective tissue:
|
|
99
|
+
|
|
100
|
+
- **Identity:** every agent has an Ed25519 keypair in Flair (`flair agent add <id>`). All signed requests, no shared passwords, no env-var secrets to leak.
|
|
101
|
+
- **Memory:** each agent writes its own lessons, decisions, observations. Flint's strategic memory survives a session crash. Anvil's "this codebase pattern works for X but fails for Y" persists across PR iterations.
|
|
102
|
+
- **Soul:** each agent has a permanent personality block — role, voice, constraints. Loaded on every bootstrap so the agent stays *themselves* across sessions.
|
|
103
|
+
- **Bridges:** when an agent needs context from a foreign system (e.g., Anvil needs to import lessons from another repo), bridges import them into Flair without a custom integration per source.
|
|
104
|
+
|
|
105
|
+
The MCP server (`@tpsdev-ai/flair-mcp`) is what makes this orchestrator-agnostic — Flint's Claude Code, Anvil/Kern/Sherlock/Pulse's OpenClaw all hit the same Flair server with the same write-isolation-plus-open-read guarantees.
|
|
106
|
+
|
|
107
|
+
## What we deliberately don't do
|
|
108
|
+
|
|
109
|
+
- **No shared write identity.** Every memory is written and owned by exactly one agent's Ed25519 key — there's no merged "team" identity that can write on another agent's behalf. Reads are a separate story: within the org, any agent can search any other's non-private memory by default (see [SECURITY.md](../SECURITY.md)) — that's intentional, not a leak. TPS mail is still how agents route a message to a *specific* teammate; it's for targeted delivery, not for gating ambient visibility.
|
|
110
|
+
- **No silent LLM-driven memory extraction.** Each agent decides what it remembers. No background "summarize and persist" on every turn — that's how memory drifts away from intent.
|
|
111
|
+
- **No multiple agents on one identity.** "Anvil" and "Anvil-2" would be two separate agentIds with two separate keys. Same workload, different identities, separately-owned memories.
|
|
112
|
+
- **No replay-safe-but-otherwise-unsigned reads.** Every Flair request is Ed25519-signed and verified, including reads. Even on a private network we don't trust the network.
|
|
113
|
+
- **No password-based access to memory.** A leaked Flair admin password lets you read the database via Harper directly, but doesn't let you impersonate an agent — you can't write under their identity without their key. We treat that as the right asymmetric defense.
|
|
114
|
+
|
|
115
|
+
## What we're still figuring out
|
|
116
|
+
|
|
117
|
+
- **Trust-weighting the open read pool.** Open-within-org read (#578, shipped in 0.21.0) means Flint no longer has to round-trip TPS mail to see Sherlock's recent security findings — `memory_search` already surfaces them directly. What's still unbuilt is any consolidation or trust-discounting of that shared pool: today it's a bigger unfiltered pile, not a ranked or corroborated one. That's the next arc (org-identity, emergent trust from provenance/corroboration/supersession) — it needs a founder-engaged design pass before we build it, not a solo build.
|
|
118
|
+
- **Rhythm agent v1.** Today's v0 is a shell-cron polling for state changes and posting to Discord. v1 moves to a dedicated low-power device, uses a small local model to summarize, and escalates only when truly stuck. Post-1.0 polish.
|
|
119
|
+
|
|
120
|
+
## Try this with your own team
|
|
121
|
+
|
|
122
|
+
Pick a starting point that matches your scale:
|
|
123
|
+
|
|
124
|
+
- **Solo, want continuity across sessions:** install Flair, give Claude Code an MCP-wired identity (see [`docs/mcp-clients.md`](mcp-clients.md)). One agent. Done.
|
|
125
|
+
- **Pair, want explicit handoffs without losing context:** add a second agent identity, each with their own MCP config + Flair agentId. Pass work via TPS mail or your own coordination channel.
|
|
126
|
+
- **Small team, want to see this rig work end-to-end:** clone our setup. Use our Beads issue tracker, our TPS mail, our agent role-splits. Replace Nathan with whoever's playing founder/product-owner.
|
|
127
|
+
- **Bigger team:** federate Flair instances (per [`docs/federation.md`](federation.md)). Each office has its own Flair — that org boundary (the federation edge) is what stays hard across nodes; reads are already open within each office's own instance.
|
|
128
|
+
|
|
129
|
+
Read the rest of the docs from there.
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
Start with `flair doctor` — it diagnoses most common issues automatically.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
flair doctor
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Common Issues
|
|
10
|
+
|
|
11
|
+
### "Harper is not running"
|
|
12
|
+
|
|
13
|
+
**Symptoms:** `flair status` shows not running, bootstrap fails.
|
|
14
|
+
|
|
15
|
+
**Fix:**
|
|
16
|
+
```bash
|
|
17
|
+
flair start
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
If it fails to start:
|
|
21
|
+
```bash
|
|
22
|
+
# Check for port conflict
|
|
23
|
+
lsof -i :19926
|
|
24
|
+
|
|
25
|
+
# Check logs (macOS)
|
|
26
|
+
cat ~/.flair/data/log/hdb.log | tail -50
|
|
27
|
+
|
|
28
|
+
# Check logs (Linux)
|
|
29
|
+
journalctl --user -u flair --since "10 minutes ago"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### "Semantic search DEGRADED — embeddings not loaded"
|
|
33
|
+
|
|
34
|
+
**Symptoms:** `flair doctor` or `flair init` reports `Semantic search DEGRADED — embeddings not loaded; recall-by-meaning will NOT work.` A paraphrase search doesn't recall a memory it should match by meaning; search only finds exact keyword overlaps.
|
|
35
|
+
|
|
36
|
+
**Cause:** The in-process embeddings component (`harper-fabric-embeddings` / the nomic model) failed to initialize, so `SemanticSearch` fell back to a keyword-only scan. The most common cause on a fresh box is a **root-owned global install**: `sudo npm install -g @tpsdev-ai/flair` makes the package directory owned by root, but Harper runs as your user and gets `EACCES` when the embeddings component tries to download/symlink the model file under that package.
|
|
37
|
+
|
|
38
|
+
**Fix — reinstall without sudo (recommended):**
|
|
39
|
+
```bash
|
|
40
|
+
# Use a user-writable npm prefix so the package dir is yours (see README Quick Start)
|
|
41
|
+
mkdir -p ~/.npm-global && npm config set prefix ~/.npm-global
|
|
42
|
+
export PATH="$HOME/.npm-global/bin:$PATH" # add to your shell rc to persist
|
|
43
|
+
|
|
44
|
+
npm uninstall -g @tpsdev-ai/flair # remove the root-owned copy (may need sudo to remove it)
|
|
45
|
+
npm install -g @tpsdev-ai/flair # reinstall, no sudo
|
|
46
|
+
flair restart
|
|
47
|
+
flair doctor # should now report semantic search operational
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Other causes:** a missing native llama.cpp addon for your platform, or a corrupted/partial model download. `flair doctor` prints the underlying init error; `flair reembed` re-downloads the model and regenerates embeddings once the component loads.
|
|
51
|
+
|
|
52
|
+
**HuggingFace outage:** the model normally resolves from HuggingFace (`nomic-ai/nomic-embed-text-v1.5-GGUF`). If HF is down or 403/429-ing, point `FLAIR_MODELS_DIR` at a directory containing your own copy of `nomic-embed-text-v1.5.Q4_K_M.gguf` instead of waiting it out:
|
|
53
|
+
```bash
|
|
54
|
+
mkdir -p ~/models
|
|
55
|
+
curl -fSL -o ~/models/nomic-embed-text-v1.5.Q4_K_M.gguf \
|
|
56
|
+
https://github.com/tpsdev-ai/flair/releases/download/ci-models/nomic-embed-text-v1.5.Q4_K_M.gguf
|
|
57
|
+
sha256sum ~/models/nomic-embed-text-v1.5.Q4_K_M.gguf
|
|
58
|
+
# expect: d4e388894e09cf3816e8b0896d81d265b55e7a9fff9ab03fe8bf4ef5e11295ac
|
|
59
|
+
|
|
60
|
+
export FLAIR_MODELS_DIR=~/models # add to your shell rc to persist
|
|
61
|
+
flair restart
|
|
62
|
+
```
|
|
63
|
+
The `ci-models` release above is a first-party mirror of the same file (public, no auth required) that flair's own CI falls back to for the same reason — same-origin with GitHub, no dependency on HF's availability. Always verify the sha256 against the value printed here (or in `scripts/ci/model-checksums.txt` in the repo) before pointing Harper at a manually-downloaded file.
|
|
64
|
+
|
|
65
|
+
### "Embeddings: hash-fallback (512-dim)"
|
|
66
|
+
|
|
67
|
+
**Symptoms:** `flair status` shows hash-fallback instead of nomic. Search returns poor results.
|
|
68
|
+
|
|
69
|
+
**Cause:** The nomic-embed-text model failed to load. Usually a missing native binary or corrupted model file.
|
|
70
|
+
|
|
71
|
+
**Fix:**
|
|
72
|
+
```bash
|
|
73
|
+
flair doctor # shows the specific error
|
|
74
|
+
flair reembed # re-downloads model and regenerates embeddings
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
If `flair doctor` shows a native addon error:
|
|
78
|
+
```bash
|
|
79
|
+
# Reinstall with native dependencies
|
|
80
|
+
npm install -g @tpsdev-ai/flair --force
|
|
81
|
+
flair restart
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### "invalid_signature" errors
|
|
85
|
+
|
|
86
|
+
**Symptoms:** API calls return `{"error": "invalid_signature"}`.
|
|
87
|
+
|
|
88
|
+
**Causes:**
|
|
89
|
+
1. Agent key doesn't match what's registered in Flair
|
|
90
|
+
2. Clock skew (signature includes timestamp)
|
|
91
|
+
3. Wrong agent ID
|
|
92
|
+
|
|
93
|
+
**Fix:**
|
|
94
|
+
```bash
|
|
95
|
+
# Verify the agent exists
|
|
96
|
+
flair agent list
|
|
97
|
+
|
|
98
|
+
# Re-register the agent's public key
|
|
99
|
+
flair agent rotate-key <agent-id>
|
|
100
|
+
|
|
101
|
+
# Check system clock
|
|
102
|
+
date
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
If using the MCP server, restart Claude Code after rotating keys.
|
|
106
|
+
|
|
107
|
+
### Port conflict
|
|
108
|
+
|
|
109
|
+
**Symptoms:** `flair start` fails, "address already in use".
|
|
110
|
+
|
|
111
|
+
**Fix:**
|
|
112
|
+
```bash
|
|
113
|
+
# Find what's using the port
|
|
114
|
+
lsof -i :19926
|
|
115
|
+
|
|
116
|
+
# If it's a stale Flair process
|
|
117
|
+
flair stop
|
|
118
|
+
flair start
|
|
119
|
+
|
|
120
|
+
# If it's another application, use a different port
|
|
121
|
+
flair init --port 29926
|
|
122
|
+
# Or edit ~/.flair/config.yaml and restart
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### MCP server can't connect
|
|
126
|
+
|
|
127
|
+
**Symptoms:** Claude Code shows "Flair tools unavailable" or bootstrap returns nothing.
|
|
128
|
+
|
|
129
|
+
**Check:**
|
|
130
|
+
```bash
|
|
131
|
+
# Is Flair running?
|
|
132
|
+
flair status
|
|
133
|
+
|
|
134
|
+
# Can you reach it?
|
|
135
|
+
curl http://localhost:19926/Health
|
|
136
|
+
|
|
137
|
+
# Is the agent registered?
|
|
138
|
+
flair agent list
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Common fixes:**
|
|
142
|
+
- Set `FLAIR_URL` in your MCP config if using a non-default port
|
|
143
|
+
- Ensure `FLAIR_AGENT_ID` matches a registered agent
|
|
144
|
+
- Restart Claude Code after config changes
|
|
145
|
+
|
|
146
|
+
### Memories not showing up in search
|
|
147
|
+
|
|
148
|
+
**Symptoms:** You wrote a memory but search doesn't find it.
|
|
149
|
+
|
|
150
|
+
**Possible causes:**
|
|
151
|
+
1. **Hash-fallback embeddings:** Check `flair status` — if embeddings are in hash mode, semantic search won't work properly. Fix with `flair reembed`.
|
|
152
|
+
2. **Content safety flags:** The memory might have been flagged. Search for it directly: `flair memory list --agent <id>`.
|
|
153
|
+
3. **`visibility: private`:** Reads are open within the org by default — any agent can find any other agent's non-private memories. If the memory was written with `visibility: private`, only its author can find it; search as that agent instead.
|
|
154
|
+
4. **Dedup threshold:** If the content is very similar to an existing memory, it may have been deduplicated. Check with `flair memory list`.
|
|
155
|
+
|
|
156
|
+
### High memory usage
|
|
157
|
+
|
|
158
|
+
**Symptoms:** Harper process using excessive RAM.
|
|
159
|
+
|
|
160
|
+
**Context:** Harper with nomic-embed-text loads a ~270MB model into memory. This is normal. Total memory usage should stabilize around 400-600MB.
|
|
161
|
+
|
|
162
|
+
If memory keeps growing:
|
|
163
|
+
```bash
|
|
164
|
+
flair restart # clean restart
|
|
165
|
+
flair doctor # check for issues
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### "content_safety_violation" on write
|
|
169
|
+
|
|
170
|
+
**Symptoms:** Memory write rejected with safety error.
|
|
171
|
+
|
|
172
|
+
**Cause:** Content matched a prompt injection pattern and strict mode is enabled (`FLAIR_CONTENT_SAFETY=strict`).
|
|
173
|
+
|
|
174
|
+
**Fix:** Either rephrase the content to avoid injection patterns, or switch to default mode (remove `FLAIR_CONTENT_SAFETY=strict` from environment). In default mode, flagged content is stored but tagged — not rejected.
|
|
175
|
+
|
|
176
|
+
## Getting Help
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
flair doctor # automated diagnosis
|
|
180
|
+
flair status # server state
|
|
181
|
+
flair --help # all commands
|
|
182
|
+
flair <command> -h # command-specific help
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Logs: `~/.flair/data/log/hdb.log`
|
|
186
|
+
|
|
187
|
+
File issues: [github.com/tpsdev-ai/flair/issues](https://github.com/tpsdev-ai/flair/issues)
|